package com.redhat.ceylon.eclipse.util; import static com.redhat.ceylon.compiler.typechecker.tree.TreeUtil.formatPath; import org.eclipse.jface.text.IRegion; import com.redhat.ceylon.compiler.typechecker.tree.Node; import com.redhat.ceylon.compiler.typechecker.tree.Tree; import com.redhat.ceylon.compiler.typechecker.tree.Tree.DocLink; import com.redhat.ceylon.compiler.typechecker.tree.Visitor; import com.redhat.ceylon.model.typechecker.model.Constructor; import com.redhat.ceylon.model.typechecker.model.Declaration; import com.redhat.ceylon.model.typechecker.model.Function; import com.redhat.ceylon.model.typechecker.model.Setter; import com.redhat.ceylon.model.typechecker.model.TypeDeclaration; import com.redhat.ceylon.model.typechecker.model.Value; public class SearchVisitor extends Visitor { public static final int TYPE = 1; public static final int FUNCTION = 1<<1; public static final int VALUE = 1<<2; public static final int PACKAGES = 1<<3; public static final int ANYTHING = TYPE|FUNCTION|VALUE|PACKAGES; public interface Matcher { boolean matches(String string); boolean includeDeclarations(); boolean includeReferences(); boolean includeTypes(); boolean includeImports(); boolean includeDoc(); int kinds(); } boolean hasPackageKind(int kind) { return (kind&PACKAGES)!=0; } boolean hasKind(Declaration declaration, int kind) { //TODO: anonymous classes if (declaration instanceof Constructor) { Constructor constructor = (Constructor) declaration; return (constructor.getParameterList()==null ? kind&VALUE : kind&FUNCTION) != 0; } else if (declaration instanceof TypeDeclaration) { return (kind&TYPE) != 0; } else if (declaration instanceof Function) { return (kind&FUNCTION) != 0; } else if (declaration instanceof Value || declaration instanceof Setter) { return (kind&VALUE) != 0; } else { return false; } } private final Matcher matcher; public SearchVisitor(Matcher matcher) { this.matcher = matcher; } public void matchingNode(Node node) {} public void matchingRegion(Node node, IRegion region) {} @Override public void visit(Tree.ExtendedTypeExpression that) {} @Override public void visit(Tree.StaticMemberOrTypeExpression that) { if (matcher.includeReferences() && that.getIdentifier()!=null && matcher.matches( that.getIdentifier().getText()) && hasKind(that.getDeclaration(), matcher.kinds())) { matchingNode(that); } super.visit(that); } @Override public void visit(Tree.SimpleType that) { if (matcher.includeTypes() && that.getIdentifier()!=null && matcher.matches( that.getIdentifier().getText()) && hasKind(that.getDeclarationModel(), matcher.kinds())) { matchingNode(that); } super.visit(that); } @Override public void visit(Tree.Declaration that) { if (matcher.includeDeclarations() && that.getIdentifier()!=null && matcher.matches( that.getIdentifier().getText()) && hasKind(that.getDeclarationModel(), matcher.kinds())) { matchingNode(that); } super.visit(that); } @Override public void visit(Tree.ImportMemberOrType that) { if (matcher.includeImports() && that.getIdentifier()!=null && matcher.matches( that.getIdentifier().getText()) && hasKind(that.getDeclarationModel(), matcher.kinds())) { matchingNode(that); } super.visit(that); } @Override public void visit(Tree.TypedArgument that) { if (matcher.includeReferences() && that.getIdentifier()!=null && matcher.matches( that.getIdentifier().getText()) && hasKind(that.getDeclarationModel(), matcher.kinds())) { matchingNode(that); } super.visit(that); } @Override public void visit(Tree.ModuleDescriptor that) { if (matcher.includeDeclarations() && that.getImportPath()!=null && hasPackageKind(matcher.kinds()) && matcher.matches(formatPath( that.getImportPath() .getIdentifiers()))) { matchingNode(that.getImportPath()); } } @Override public void visit(Tree.PackageDescriptor that) { if (matcher.includeDeclarations() && that.getImportPath()!=null && hasPackageKind(matcher.kinds()) && matcher.matches(formatPath( that.getImportPath() .getIdentifiers()))) { matchingNode(that.getImportPath()); } } @Override public void visit(Tree.Import that) { if (matcher.includeImports() && that.getImportPath()!=null && hasPackageKind(matcher.kinds()) && matcher.matches(formatPath( that.getImportPath() .getIdentifiers()))) { matchingNode(that.getImportPath()); } } @Override public void visit(Tree.ImportModule that) { if (matcher.includeImports() && that.getImportPath()!=null && hasPackageKind(matcher.kinds()) && matcher.matches(formatPath( that.getImportPath() .getIdentifiers()))) { matchingNode(that.getImportPath()); } } @Override public void visit(Tree.SpecifiedArgument that) { if (matcher.includeReferences() && that.getIdentifier()!=null && matcher.matches( that.getIdentifier().getText()) && hasKind(that.getParameter().getModel(), matcher.kinds())) { matchingNode(that); } super.visit(that); } @Override public void visit(DocLink that) { if (matcher.includeDoc()) { int i=0; String name; while ((name = DocLinks.name(that, i))!=null) { if (matcher.matches(name)) { if (matcher.kinds()==ANYTHING || hasKind(getLinkedDec(that, i), matcher.kinds())) { matchingRegion(that, DocLinks.nameRegion(that, i)); } } i++; } } } private static Declaration getLinkedDec(DocLink that, int i) { Declaration dec = i==0 ? that.getBase() : that.getQualified().get(i-1); return dec; } }