/* * Copyright (c) 2005, 2010 Sven Efftinge and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Sven Efftinge - Initial API and implementation */ package org.eclipse.gmf.internal.xpand.codeassist; import java.util.ArrayList; import java.util.List; import java.util.Stack; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.gmf.internal.xpand.expression.codeassist.ProposalComputer; import org.eclipse.gmf.internal.xpand.expression.codeassist.ProposalFactory; import org.eclipse.gmf.internal.xpand.model.ExecutionContext; import org.eclipse.jface.text.contentassist.ICompletionProposal; public class StatementProposalComputer implements ProposalComputer { private final ProposalFactory proposalFactory; public StatementProposalComputer(ProposalFactory factory) { assert factory != null; proposalFactory = factory; } public List<ICompletionProposal> computeProposals(final String txt, final ExecutionContext ctx) { final List<ICompletionProposal> result = new ArrayList<ICompletionProposal>(); final String ws = findTrailingWhitespace(txt); final Stack<StackElement> s = FastAnalyzer.computeStack(txt); if (s.size() > 0) { final StackElement se = s.peek(); result.add(proposalFactory.createStatementProposal(XpandTokens.LT + "END" + se.block + XpandTokens.RT, "END" + se.block, "")); if (contains(XpandTokens.IF, s)) { result.add(proposalFactory.createStatementProposal(XpandTokens.LT + "ELSE" + XpandTokens.RT, "ELSE", "")); result.add(proposalFactory.createStatementProposal(XpandTokens.LT + "ELSEIF statement" + XpandTokens.RT, "ELSEIF", "")); } if (!contains(XpandTokens.FILE, s)) { result.add(fileBlockProposal(ws)); } if (!contains(XpandTokens.PROTECT, s)) { result.add(protectBlockProposal(ws)); } result.add(foreachBlockProposal(ws)); result.add(ifBlockProposal(ws)); result.add(letBlockProposal(ws)); result.add(expandStatementProposal(ws)); } else { if (txt.indexOf(XpandTokens.LT + XpandTokens.DEFINE) == -1) { if (txt.indexOf(XpandTokens.LT + XpandTokens.EXTENSION) == -1) { result.add(importStatementProposal()); } result.add(extensionStatementProposal()); } result.add(defineBlockProposal(ws)); result.add(aroundBlockProposal(ws)); } return result; } private ICompletionProposal importStatementProposal() { final String insertString = XpandTokens.LT + XpandTokens.IMPORT + " my::imported::namespace" + XpandTokens.RT; return proposalFactory.createStatementProposal(insertString, "IMPORT statement", "", insertString.indexOf("my::imported::namespace"), "my::imported::namespace".length()); } private ICompletionProposal extensionStatementProposal() { final String insertString = XpandTokens.LT + XpandTokens.EXTENSION + " path::to::Extension" + XpandTokens.RT; return proposalFactory.createStatementProposal(insertString, "EXTENSION statement", "", insertString.indexOf("path::to::Extension"), "path::to::Extension".length()); } private final static Pattern WS_PATTERN = Pattern.compile("(\\n?[\\t ]*)\\z"); private String findTrailingWhitespace(final String txt) { final Matcher m = WS_PATTERN.matcher(txt); m.find(); return m.group(1); } private ICompletionProposal expandStatementProposal(final String ws) { final String insertString = XpandTokens.LT + "EXPAND definition FOR self" + XpandTokens.RT; return proposalFactory.createStatementProposal(insertString, "EXPAND statement", "", insertString.indexOf("definition"), "definition".length()); } private ICompletionProposal letBlockProposal(final String ws) { final String insertString = XpandTokens.LT + "LET expression AS e" + XpandTokens.RT + ws + XpandTokens.LT + "ENDLET" + XpandTokens.RT; return proposalFactory.createStatementProposal(insertString, "LET block", "", insertString.indexOf("expression"), "expression".length()); } private ICompletionProposal ifBlockProposal(final String ws) { final String insertString = XpandTokens.LT + "IF condition" + XpandTokens.RT + ws + XpandTokens.LT + "ENDIF" + XpandTokens.RT; return proposalFactory.createStatementProposal(insertString, "IF block", "", insertString.indexOf("condition"), "condition".length()); } private ICompletionProposal foreachBlockProposal(final String ws) { final String insertString = XpandTokens.LT + "FOREACH elements AS e" + XpandTokens.RT + ws + XpandTokens.LT + "ENDFOREACH" + XpandTokens.RT; return proposalFactory.createStatementProposal(insertString, "FOREACH block", "", insertString.indexOf("elements"), "elements".length()); } private ICompletionProposal protectBlockProposal(final String ws) { final String insertString = XpandTokens.LT + "PROTECT CSTART '/*' CEND '*/' ID uniqueId ENABLED" + XpandTokens.RT + ws + XpandTokens.LT + "ENDPROTECT" + XpandTokens.RT; return proposalFactory.createStatementProposal(insertString, "PROTECT region", "", insertString.indexOf("uniqueId"), "uniqueId".length()); } private ICompletionProposal fileBlockProposal(final String ws) { final String insertString = XpandTokens.LT + "FILE fileName" + XpandTokens.RT + ws + XpandTokens.LT + "ENDFILE" + XpandTokens.RT; return proposalFactory.createStatementProposal(insertString, "FILE block", "", insertString.indexOf("fileName"), "fileName".length()); } private ICompletionProposal defineBlockProposal(final String ws) { final String insertString = XpandTokens.LT + "DEFINE definionName FOR Type" + XpandTokens.RT + ws + XpandTokens.LT + "ENDDEFINE" + XpandTokens.RT; return proposalFactory.createStatementProposal(insertString, "new DEFINE", "", insertString.indexOf("definionName"), "definionName".length()); } private ICompletionProposal aroundBlockProposal(final String ws) { final String insertString = XpandTokens.LT + "AROUND fullyQualifiedDefinionName FOR Type" + XpandTokens.RT + ws + XpandTokens.LT + "ENDAROUND" + XpandTokens.RT; return proposalFactory.createStatementProposal(insertString, "new AROUND", "", insertString.indexOf("fullyQualifiedDefinionName"), "fullyQualifiedDefinionName".length()); } private boolean contains(final String blockName, final Stack<StackElement> s) { for (StackElement element : s) { if (element.block.equals(blockName)) { return true; } } return false; } protected String findPrefix(final String txt) { final StringBuffer result = new StringBuffer(); int i = txt.length() - 1; char c = txt.charAt(i); while ((i > 0) && Character.isJavaIdentifierStart(c)) { result.append(c); c = txt.charAt(--i); } return result.reverse().toString(); } }