public QueryAssistProcessor() { super(); try { nodeIcon = ImageDescriptor.createFromURL(new URL(Gra2MoLEditor.getInstallURL(), nodeIconPath)) .createImage(); } catch (Exception e) { e.printStackTrace(); } }
public class QueryAssistProcessor implements IContentAssistProcessor { public static String SINGLE_SLASH = "__single_slash"; public static String DOUBLE_SLASH = "__double_slash"; public static String TRIPLE_SLASH = "__triple_slash"; public static String metamodelPath = Gra2MoLEditor.getAbsoluteInstallPath() + "resources/Grammar.ecore"; public static String modelPath = Gra2MoLEditor.getAbsoluteInstallPath() + "resources/javaGrammar.ecore"; public static String nodeIconPath = "icons/node.gif"; private Model model; private List<ModelElement> rules; private Image nodeIcon = null; public QueryAssistProcessor() { super(); try { nodeIcon = ImageDescriptor.createFromURL(new URL(Gra2MoLEditor.getInstallURL(), nodeIconPath)) .createImage(); } catch (Exception e) { e.printStackTrace(); } } public void setGrammar(String grammarPath) { ModelGrammarExtractor mge = new ModelGrammarExtractor(); if (grammarPath != null) { this.model = mge.discover(grammarPath); this.rules = retrieveSintacticRules(this.model); } } public static void main(String[] args) { System.out.println("Mis pruebas"); // QueryAssistProcessor qa = new QueryAssistProcessor(); // qa.retrieveRuleDerivations("classOrInterfaceDeclaration", qa.rules); } @Override public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { // System.out.println("Computing query completion..."); IDocument document = viewer.getDocument(); CompletionProposal result[] = {}; if (this.model != null && this.rules != null) { try { String query = extractQuery(viewer, offset); // System.out.println("Detected query: " + query); String parentNode = extractParentNode(query); // System.out.println("Parent: " + parentNode); String restNode = extractRestNode(query); // System.out.println("Rest: " + restNode); String type = extractOperatorType(query); List<String> tips = new ArrayList<String>(); // System.out.println("Type: " + type); // Builds the possible tips (it depends on the operator) // (If we have detected the type of the parent) if (type != null && type.equals(QueryAssistProcessor.SINGLE_SLASH)) { tips = retrieveRuleDerivations(parentNode, this.rules); } else if (type != null && (type.equals(QueryAssistProcessor.DOUBLE_SLASH) || type.equals(QueryAssistProcessor.TRIPLE_SLASH))) { tips = retrieveRecursiveRuleDerivations(parentNode, this.rules); } else if (parentNode == null && restNode != null) { tips = retrieveRulesStartsWith(restNode, rules); } else if (parentNode == null && restNode == null) { tips = retrieveRulesNames(this.rules); } // Sort the tip list Object[] arrayTips = tips.toArray(); Arrays.sort(arrayTips); tips = new ArrayList<String>(); for (int i = 0; i < arrayTips.length; i++) { tips.add((String) arrayTips[i]); } // Builds the result if (tips.size() == 0 || restNode == null) { // There is no rest result = new CompletionProposal[tips.size()]; for (int i = 0; i < tips.size(); i++) { result[i] = new CompletionProposal( tips.get(i), offset, 0, ((String) tips.get(i)).length(), nodeIcon, tips.get(i), null, null); } } else { ArrayList<CompletionProposal> partialResult = new ArrayList<CompletionProposal>(); for (int i = 0; i < tips.size(); i++) { String tip = tips.get(i); if (tip.startsWith(restNode)) { String restTip = tip.substring(restNode.length(), tip.length()); partialResult.add( new CompletionProposal( restTip, offset, 0, restTip.length(), nodeIcon, tip, null, null)); } } result = new CompletionProposal[partialResult.size()]; for (int j = 0; j < partialResult.size(); j++) { result[j] = partialResult.get(j); } } } catch (Exception e) { e.printStackTrace(); } } // System.out.println("Devueltos: " + result.length); return result; } /** * Extracts the sintactic rules from the grammar definition * * @param m * @return */ private List<ModelElement> retrieveSintacticRules(Model m) { List<ModelElement> result = new ArrayList<ModelElement>(); // Extracts the first element Collection<ModelElement> content = (Collection<ModelElement>) m.getContents(); ModelElement me = (ModelElement) content.toArray()[0]; // Extracts grammarDefs List<ModelElement> grammarDefsList = (List<ModelElement>) me.get("grammarDefs"); if (grammarDefsList != null && grammarDefsList.size() > 0) { ModelElement grammarDef = (ModelElement) grammarDefsList.toArray()[0]; // Extracts the rules of the grammar definition List<ModelElement> rulesList = (List<ModelElement>) grammarDef.get("rules"); Iterator<ModelElement> rulesIt = rulesList.iterator(); while (rulesIt.hasNext()) { ModelElement rule = rulesIt.next(); String name = (String) rule.getReferenceModelElement().get("name"); if (name.equals("SintacticRule")) { result.add(rule); } } } return result; } /** * Locates the parent rule in the rules and extracts its children (and recursive). * * @param parent * @return */ private List<String> retrieveRecursiveRuleDerivations(String parent, List<ModelElement> rules) { return retrieveRecursiveRuleDerivationsAux(parent, new ArrayList<String>(), rules); } /** * This method is used by retrieveRecursiveRuleDerivations * * @param parent * @param visitedRules * @param rules * @return */ private List<String> retrieveRecursiveRuleDerivationsAux( String parent, List<String> visitedRules, List<ModelElement> rules) { List<String> result = new ArrayList<String>(); List<String> partialRules = retrieveRuleDerivations(parent, rules); Iterator<String> itPartialResult = partialRules.iterator(); while (itPartialResult.hasNext()) { String partialRule = itPartialResult.next(); if (!visitedRules.contains(partialRule)) { result.add(partialRule); visitedRules.add(partialRule); result.addAll(retrieveRecursiveRuleDerivationsAux(partialRule, visitedRules, rules)); } } return result; } /** * Locates the parent rule in the rules and extracts its children (only sintactic derivations) * * @param parent * @return */ private List<String> retrieveRuleDerivations(String parent, List<ModelElement> rules) { List<String> result = new ArrayList<String>(); ModelElement ruleModelElement = retrieveRule(parent, rules); if (ruleModelElement != null) { List<ModelElement> derivationsList = (List<ModelElement>) ruleModelElement.get("derivations"); Iterator<ModelElement> itDerivations = derivationsList.iterator(); while (itDerivations.hasNext()) { ModelElement derivationModelElement = itDerivations.next(); String name = (String) derivationModelElement.getReferenceModelElement().get("name"); if (name.equals("SintacticRule")) { result.add((String) derivationModelElement.get("name")); } } } return result; } /** * Locates the rules that starts with the argument (only sintactic rules) * * @param startsWith * @param rules * @return */ private List<String> retrieveRulesStartsWith(String startsWith, List<ModelElement> rules) { List<String> result = new ArrayList<String>(); Iterator<ModelElement> itRules = rules.iterator(); while (itRules.hasNext()) { ModelElement ruleModelElement = itRules.next(); String type = (String) ruleModelElement.getReferenceModelElement().get("name"); if (type.equals("SintacticRule")) { if (((String) ruleModelElement.get("name")).startsWith(startsWith)) { result.add((String) ruleModelElement.get("name")); } } } return result; } private List<String> retrieveRulesNames(List<ModelElement> rules) { List<String> result = new ArrayList<String>(); Iterator<ModelElement> itRules = rules.iterator(); while (itRules.hasNext()) { ModelElement ruleModelElement = itRules.next(); String type = (String) ruleModelElement.getReferenceModelElement().get("name"); if (type.equals("SintacticRule")) { result.add((String) ruleModelElement.get("name")); } } return result; } /** * Locates the rule in the rules * * @param ruleName * @param rules * @return */ private ModelElement retrieveRule(String ruleName, List<ModelElement> rules) { ModelElement result = null; // Extracts the rules of the grammar definition List<ModelElement> rulesList = rules; Iterator<ModelElement> itRules = rulesList.iterator(); while (itRules.hasNext()) { ModelElement ruleModelElement = itRules.next(); // System.out.println(" Rule:" + ruleModelElement.get("name")); // If the rule is the parent argument, extract its derivations if (ruleModelElement.get("name").equals(ruleName)) { result = ruleModelElement; break; } } return result; } /** * Creates a ModelBuilder (from grammar2Model) and load the model of the grammar * * @return */ private Model retrieveModel() { String metamodel = QueryAssistProcessor.metamodelPath; ModelBuilder mb = new ModelBuilder(metamodel, "Grammar"); String modelPath = QueryAssistProcessor.modelPath; return mb.load(modelPath); } /** * Extract the type of the last operator (/, // or ///) * * @param query * @return */ private String extractOperatorType(String query) { int singleSlash = query.lastIndexOf("/"); int doubleSlash = query.lastIndexOf("//"); int tripleSlash = query.lastIndexOf("///"); String subString = ""; if (singleSlash > 0 && singleSlash > doubleSlash + 1 && singleSlash > tripleSlash + 2) { return QueryAssistProcessor.SINGLE_SLASH; } else if (doubleSlash > 0 && doubleSlash + 1 >= singleSlash && doubleSlash + 1 > tripleSlash + 2) { return QueryAssistProcessor.DOUBLE_SLASH; } else if (tripleSlash > 0 && tripleSlash + 2 >= singleSlash && tripleSlash + 2 >= doubleSlash + 1) { return QueryAssistProcessor.TRIPLE_SLASH; } else return null; // if(singleSlash > 0 && doubleSlash < 0 && tripleSlash < 0) { // return QueryAssistProcessor.SINGLE_SLASH; // } else if(singleSlash > 0 && doubleSlash > 0 && tripleSlash < 0) { // return QueryAssistProcessor.DOUBLE_SLASH; // } else if(singleSlash > 0 && doubleSlash > 0 && tripleSlash > 0) { // return QueryAssistProcessor.TRIPLE_SLASH; // } else return null; } /** * Extracts the rest of string that is located later the last slash * * @param query * @return */ private String extractRestNode(String query) { String result = null; // Delete the last slash int lastSlash = query.lastIndexOf("/"); if (lastSlash != (query.length() - 1)) { result = query.substring(lastSlash + 1, query.length()); } // Delete the sharp character (if it exists) if (result != null) { int sharp = result.indexOf("#"); if (sharp == 0) { result = result.substring(1, result.length()); } } return result; } /** * Extract the last complete node declaration of the query. This node will act as parent of the * content assisted completion. For instance, in the string "/node1/node2/t" the parent node is * node2 and t is the tip for the content assisted completion. * * @param query * @return */ private String extractParentNode(String query) { String result = null; int singleSlash = query.lastIndexOf("/"); int doubleSlash = query.lastIndexOf("//"); int tripleSlash = query.lastIndexOf("///"); String subString = ""; if (singleSlash > 0 && singleSlash > doubleSlash + 1 && singleSlash > tripleSlash + 2) { subString = query.substring(0, singleSlash); } else if (doubleSlash > 0 && doubleSlash + 1 >= singleSlash && doubleSlash + 1 > tripleSlash + 2) { subString = query.substring(0, doubleSlash); } else if (tripleSlash > 0 && tripleSlash + 2 >= singleSlash && tripleSlash + 2 >= doubleSlash + 1) { subString = query.substring(0, tripleSlash); } // Extracts the parent int lastSlash = subString.lastIndexOf('/'); if (lastSlash > -1) { result = subString.substring(lastSlash + 1, subString.length()); } // Delete the sharp character (if it exists) if (result != null) { int sharp = result.indexOf("#"); if (sharp == 0) { result = result.substring(1, result.length()); } } return result; } /** * Extract the query of the line * * @param viewer * @param offset * @return */ private String extractQuery(ITextViewer viewer, int offset) { String result = null; String line = extractEditedLine(viewer, offset); int hasFrom = line.indexOf("from"); if (hasFrom >= 0) { result = "/" + line.substring(5, line.length()); } else { int firstSlash = line.indexOf('/'); result = line.substring(firstSlash); } return result; } /** * Extracts the line that is being edited * * @param viewer * @param offset * @return */ private String extractEditedLine(ITextViewer viewer, int offset) { String result = null; IDocument document = viewer.getDocument(); try { int lastEditedLine = document.getLineOfOffset(offset); int lineLenght = document.getLineLength(lastEditedLine); result = document.get().substring(offset - lineLenght, offset); result = result.trim(); } catch (Exception e) { e.printStackTrace(); } return result; } @Override public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { System.out.println("computeContextInformation"); return null; } @Override public char[] getCompletionProposalAutoActivationCharacters() { // System.out.println("getCompletionProposalAutoActivationCharacters"); return "/".toCharArray(); } @Override public char[] getContextInformationAutoActivationCharacters() { // System.out.println("getContextInformationAutoActivationCharacters"); return null; } @Override public IContextInformationValidator getContextInformationValidator() { System.out.println("getContextInformationValidator"); return null; } @Override public String getErrorMessage() { // System.out.println("getErrorMessage"); return "Han llamado a getErrorMessage"; } }