package com.redhat.ceylon.eclipse.util; import static com.redhat.ceylon.compiler.typechecker.parser.CeylonLexer.ASTRING_LITERAL; import static com.redhat.ceylon.compiler.typechecker.parser.CeylonLexer.AVERBATIM_STRING; import static com.redhat.ceylon.compiler.typechecker.parser.CeylonLexer.EOF; import static com.redhat.ceylon.compiler.typechecker.parser.CeylonLexer.LINE_COMMENT; import static com.redhat.ceylon.compiler.typechecker.parser.CeylonLexer.MULTI_COMMENT; import static com.redhat.ceylon.compiler.typechecker.parser.CeylonLexer.STRING_END; import static com.redhat.ceylon.compiler.typechecker.parser.CeylonLexer.STRING_LITERAL; import static com.redhat.ceylon.compiler.typechecker.parser.CeylonLexer.VERBATIM_STRING; import static com.redhat.ceylon.eclipse.util.CeylonHelper.toJavaStringArray; import java.util.Iterator; import java.util.List; import java.util.Set; import org.antlr.runtime.CommonToken; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; import com.redhat.ceylon.compiler.typechecker.tree.Node; import com.redhat.ceylon.compiler.typechecker.tree.Tree; import com.redhat.ceylon.compiler.typechecker.tree.Tree.Statement; import com.redhat.ceylon.ide.common.refactoring.DefaultRegion; import com.redhat.ceylon.ide.common.util.OccurrenceLocation; import com.redhat.ceylon.ide.common.util.nodes_; import com.redhat.ceylon.model.typechecker.model.Declaration; import com.redhat.ceylon.model.typechecker.model.Referenceable; import com.redhat.ceylon.model.typechecker.model.Unit; public class Nodes { private static final nodes_ delegate = nodes_.get_(); public static Tree.Declaration findDeclaration(Tree.CompilationUnit cu, Node node) { return delegate.findDeclaration(cu, node); } public static Tree.Declaration findDeclarationWithBody(Tree.CompilationUnit cu, Node node) { return delegate.findDeclarationWithBody(cu, node); } public static Tree.NamedArgument findArgument(Tree.CompilationUnit cu, Node node) { return delegate.findArgument(cu, node); } public static Tree.OperatorExpression findOperator(Tree.CompilationUnit cu, final Node node) { return delegate.findOperator(cu, node); } public static Statement findStatement(Tree.CompilationUnit cu, Node node) { return delegate.findStatement(cu, node); } public static Statement findToplevelStatement(Tree.CompilationUnit cu, Node node) { return delegate.findTopLevelStatement(cu, node); } public static Declaration getAbstraction(Declaration d) { return delegate.getAbstraction(d); } public static Tree.Declaration getContainer(Tree.CompilationUnit cu, final Declaration dec) { return delegate.getContainer(cu, dec); } public static Tree.ImportMemberOrType findImport(Tree.CompilationUnit cu, Node node) { return delegate.findImport(cu, node); } public static Node findNode(Tree.CompilationUnit cu, int offset) { return findNode(cu, null, offset, offset+1); } public static Node findNode(Tree.CompilationUnit cu, int startOffset, int endOffset) { return findNode(cu, null, startOffset, endOffset); } public static Node findNode(Node node, List<CommonToken> tokens, int startOffset, int endOffset) { return delegate.findNode(node, tokens, startOffset, endOffset); } private static Node findScope(Tree.CompilationUnit cu, int startOffset, int endOffset) { return delegate.findScope(cu, startOffset, endOffset); } public static Node findNode(Tree.CompilationUnit cu, List<CommonToken> tokens, ITextSelection selection) { return findNode(cu, tokens, selection.getOffset(), selection.getOffset() + selection.getLength()); } public static Node findNode(Tree.CompilationUnit cu, List<CommonToken> tokens, IRegion selection) { return findNode(cu, tokens, selection.getOffset(), selection.getOffset() + selection.getLength()); } public static Node findScope(Tree.CompilationUnit cu, ITextSelection s) { return findScope(cu, s.getOffset(), s.getOffset()+s.getLength()); } public static Node getIdentifyingNode(Node node) { return delegate.getIdentifyingNode(node); } public static Iterator<CommonToken> getTokenIterator(List<CommonToken> tokens, IRegion region) { // int regionOffset = region.getOffset(); // int regionLength = region.getLength(); // if (regionLength<=0) { // return Collections.<CommonToken>emptyList().iterator(); // } // int regionEnd = regionOffset + regionLength - 1; // if (tokens==null) { // return null; // } // else { // int firstTokIdx = // getTokenIndexAtCharacter(tokens, regionOffset); // // getTokenIndexAtCharacter() answers the negative of the index of the // // preceding token if the given offset is not actually within a token. // if (firstTokIdx < 0) { // firstTokIdx= -firstTokIdx + 1; // } // int lastTokIdx = // getTokenIndexAtCharacter(tokens, regionEnd); // if (lastTokIdx < 0) { // lastTokIdx= -lastTokIdx; // } // return tokens.subList(firstTokIdx, lastTokIdx+1).iterator(); // } return delegate.getTokenIterator(tokens, new DefaultRegion(region.getOffset(), region.getLength())); } // // This function returns the index of the token element // containing the offset specified. If such a token does // not exist, it returns the negation of the index of the // element immediately preceding the offset. // public static int getTokenIndexAtCharacter(List<CommonToken> tokens, int offset) { //search using bisection // int low = 0, // high = tokens.size(); // while (high > low) // { // int mid = (high + low) / 2; // CommonToken midElement = (CommonToken) tokens.get(mid); // if (offset >= midElement.getStartIndex() && // offset <= midElement.getStopIndex()) // return mid; // else if (offset < midElement.getStartIndex()) // high = mid; // else low = mid + 1; // } // // return -(low - 1); return (int) delegate.getTokenIndexAtCharacter(tokens, offset); } /** * Get the Node referenced by the given Node, searching * in all relevant compilation units. */ public static Node getReferencedNode(Node node) { return getReferencedNode(getReferencedModel(node)); } /** * Get the Node referenced by the given model, searching * in all relevant compilation units. */ public static Node getReferencedNode(Referenceable model) { return delegate.getReferencedNode(model); } /** * Get the Node referenced by the given model, searching * in all relevant compilation units. */ public static Node getReferencedNode(Referenceable model, Tree.CompilationUnit rootNode) { return delegate.getReferencedNode(model, rootNode); } public static Referenceable getReferencedModel(Node node) { return delegate.getReferencedModel(node); } public static Referenceable getReferencedExplicitDeclaration(Node node, Tree.CompilationUnit rn) { return delegate.getReferencedExplicitDeclaration(node, rn); } public static Referenceable getReferencedDeclaration(Node node) { return delegate.getReferencedDeclaration(node); } public static Node findReferencedNode( Tree.CompilationUnit rootNode, Referenceable model) { return delegate.findReferencedNode(rootNode, model); } public static String text(Node term, List<CommonToken> tokens) { // int start = term.getStartIndex(); // int length = term.getDistance(); // Region region = new Region(start, length); // StringBuilder exp = new StringBuilder(); // for (Iterator<CommonToken> ti = // getTokenIterator(tokens, region); // ti.hasNext();) { // CommonToken token = ti.next(); // int type = token.getType(); // String text = token.getText(); // if (type==LIDENTIFIER && // getTokenLength(token)>text.length()) { // exp.append("\\i"); // } // else if (type==UIDENTIFIER && // getTokenLength(token)>text.length()) { // exp.append("\\I"); // } // exp.append(text); // } // return exp.toString(); return delegate.text(tokens, term); } public static int getTokenLength(CommonToken token) { // return token.getStopIndex()-token.getStartIndex()+1; return (int) delegate.getTokenLength(token); } public static String[] nameProposals(Node node) { if (node instanceof Tree.Term || node instanceof Tree.Type) { return nameProposals(node, false); } else { return new String[] {"it"}; } } public static String[] nameProposals(Node node, boolean unplural) { return toJavaStringArray(delegate.nameProposals(node, null, unplural)); } public static void addNameProposals(Set<String> names, boolean plural, String tn) { delegate.addNameProposals(names, plural, tn); } public static Tree.SpecifierOrInitializerExpression getDefaultArgSpecifier( Tree.Parameter p) { // if (p instanceof Tree.ValueParameterDeclaration) { // Tree.AttributeDeclaration pd = (Tree.AttributeDeclaration) // ((Tree.ValueParameterDeclaration) p).getTypedDeclaration(); // return pd.getSpecifierOrInitializerExpression(); // } // else if (p instanceof Tree.FunctionalParameterDeclaration) { // Tree.MethodDeclaration pd = (Tree.MethodDeclaration) // ((Tree.FunctionalParameterDeclaration) p).getTypedDeclaration(); // return pd.getSpecifierExpression(); // } // else if (p instanceof Tree.InitializerParameter) { // return ((Tree.InitializerParameter) p).getSpecifierExpression(); // } // else { // return null; // } return delegate.getDefaultArgSpecifier(p); } public static CommonToken getTokenStrictlyContainingOffset(int offset, List<CommonToken> tokens) { if (tokens!=null) { if (tokens.size()>1) { if (tokens.get(tokens.size()-1).getStartIndex()==offset) { //at very end of file //check to see if last token is an //unterminated string or comment //Note: ANTLR sometimes sends me 2 EOFs, // so do this: CommonToken token = null; for (int i=1; tokens.size()>=i && (token==null || token.getType()==EOF); i++) { token = tokens.get(tokens.size()-i); } int type = token==null ? -1 : token.getType(); if ((type==STRING_LITERAL || type==STRING_END || type==ASTRING_LITERAL) && (!token.getText().endsWith("\"") || token.getText().length()==1) || (type==VERBATIM_STRING || type==AVERBATIM_STRING) && (!token.getText().endsWith("\"\"\"")|| token.getText().length()==3) || (type==MULTI_COMMENT) && (!token.getText().endsWith("*/")|| token.getText().length()==2) || type==LINE_COMMENT) { return token; } } else { int tokenIndex = getTokenIndexAtCharacter(tokens, offset); if (tokenIndex>=0) { CommonToken token = tokens.get(tokenIndex); if (token.getStartIndex()<offset) { return token; } } } } } return null; } public static void appendParameters(StringBuilder result, Tree.FunctionArgument fa, Unit unit, final List<CommonToken> tokens) { delegate.appendParameters(result, fa, unit, tokens); } public static OccurrenceLocation getOccurrenceLocation(Tree.CompilationUnit cu, Node node, int offset) { return delegate.getOccurrenceLocation(cu, node, offset); } public static String getImportedName(Tree.ImportModule im) { ceylon.language.String name = delegate.getImportedModuleName(im); return name==null ? null : name.toString(); } public static String getImportedName(Tree.Import i) { ceylon.language.String name = delegate.getImportedPackageName(i); return name==null ? null : name.toString(); } }