/******************************************************************************* * Copyright © 2000, 2013 IBM Corporation 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: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.ide.core.internal.search.matching; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.CoreException; import org.eclipse.edt.compiler.core.ast.AbstractASTExpressionVisitor; import org.eclipse.edt.compiler.core.ast.AbstractASTVisitor; import org.eclipse.edt.compiler.core.ast.AnnotationExpression; import org.eclipse.edt.compiler.core.ast.Assignment; import org.eclipse.edt.compiler.core.ast.ClassDataDeclaration; import org.eclipse.edt.compiler.core.ast.DefaultASTVisitor; import org.eclipse.edt.compiler.core.ast.Delegate; import org.eclipse.edt.compiler.core.ast.Class; import org.eclipse.edt.compiler.core.ast.Enumeration; import org.eclipse.edt.compiler.core.ast.Expression; import org.eclipse.edt.compiler.core.ast.ExternalType; import org.eclipse.edt.compiler.core.ast.FunctionParameter; import org.eclipse.edt.compiler.core.ast.Handler; import org.eclipse.edt.compiler.core.ast.ImportDeclaration; import org.eclipse.edt.compiler.core.ast.Interface; import org.eclipse.edt.compiler.core.ast.Library; import org.eclipse.edt.compiler.core.ast.Name; import org.eclipse.edt.compiler.core.ast.NestedFunction; import org.eclipse.edt.compiler.core.ast.Node; import org.eclipse.edt.compiler.core.ast.PackageDeclaration; import org.eclipse.edt.compiler.core.ast.Part; import org.eclipse.edt.compiler.core.ast.Program; import org.eclipse.edt.compiler.core.ast.Record; import org.eclipse.edt.compiler.core.ast.Service; import org.eclipse.edt.compiler.core.ast.SetValuesExpression; import org.eclipse.edt.compiler.core.ast.SettingsBlock; import org.eclipse.edt.compiler.core.ast.StructureItem; import org.eclipse.edt.compiler.core.ast.UseStatement; import org.eclipse.edt.ide.core.internal.model.Util; import org.eclipse.edt.ide.core.internal.model.util.HashtableOfLong; import org.eclipse.edt.ide.core.model.IEGLElement; import org.eclipse.edt.ide.core.model.IPart; import org.eclipse.edt.ide.core.search.ICompiledFileUnit; import org.eclipse.edt.ide.core.search.IEGLSearchResultCollector; import org.eclipse.edt.mof.egl.FunctionPart; /** * A set of matches and potential matches. */ public class MatchingNodeSet { MatchLocator2 locator; int matchContainer; boolean cuHasBeenResolved = false; /** * Set of matching ast nodes that don't need to be resolved. */ Map matchingNodes = new HashMap(5); HashtableOfLong matchingNodesKeys = new HashtableOfLong(5); /** * Set of potential matching ast nodes. They need to be resolved * to determine if they really match the search pattern. */ Map potentialMatchingNodes = new HashMap(5); HashtableOfLong potentialMatchingNodesKeys = new HashtableOfLong(5); public MatchingNodeSet(MatchLocator2 locator) { super(); this.locator = locator; this.matchContainer = locator.matchContainer(); } public void addPossibleMatch(Node node) { // remove existing node at same position from set // (case of recovery that created the same node several time // see http://bugs.eclipse.org/bugs/show_bug.cgi?id=29366) long key = (((long) node.getOffset()) << 32) + (node.getOffset() + node.getLength()); Node existing = (Node) this.potentialMatchingNodesKeys.get(key); if (existing != null && existing.getClass().equals(node.getClass())) { this.potentialMatchingNodes.remove(existing); } // add node to set this.potentialMatchingNodes.put(node, new Integer(SearchPattern.POSSIBLE_MATCH)); this.potentialMatchingNodesKeys.put(key, node); } public void addTrustedMatch(Node node) { // remove existing node at same position from set // (case of recovery that created the same node several time // see http://bugs.eclipse.org/bugs/show_bug.cgi?id=29366) long key = (((long) node.getOffset()) << 32) + (node.getOffset() + node.getLength()); Node existing = (Node) this.matchingNodesKeys.get(key); if (existing != null && existing.getClass().equals(node.getClass())) { this.matchingNodes.remove(existing); } // add node to set this.matchingNodes.put(node, new Integer(SearchPattern.ACCURATE_MATCH)); this.matchingNodesKeys.put(key, node); } public void addInaccurateMatch(Node node) { // remove existing node at same position from set // (case of recovery that created the same node several time // see http://bugs.eclipse.org/bugs/show_bug.cgi?id=29366) long key = (((long) node.getOffset()) << 32) + (node.getOffset() + node.getLength()); Node existing = (Node) this.matchingNodesKeys.get(key); if (existing != null && existing.getClass().equals(node.getClass())) { this.matchingNodes.remove(existing); } // add node to set this.matchingNodes.put(node, new Integer(SearchPattern.INACCURATE_MATCH)); this.matchingNodesKeys.put(key, node); } public int getMatchingLevel(Node node){ return this.locator.matchCheck(node); } public int isMatchingFunctionType(Name node,FunctionPart partBinding) { int level = getMatchingLevel(node); if (level == SearchPattern.POSSIBLE_MATCH || level == SearchPattern.ACCURATE_MATCH){ return locator.matchesFunctionPartType(node,partBinding); } return level; } public int isMatchingNestedFunctionPart(NestedFunction node) { int level = getMatchingLevel(node); if (level == SearchPattern.POSSIBLE_MATCH || level == SearchPattern.ACCURATE_MATCH){ return locator.matchesFunctionPartType(node.getName(),null); } return level; } public int isMatchingType(Name node,org.eclipse.edt.mof.egl.Part partBinding) { int level = getMatchingLevel(node); if (level == SearchPattern.POSSIBLE_MATCH || level == SearchPattern.ACCURATE_MATCH){ return locator.matchesPartType(node,partBinding); } return level; } public int isMatchingPart(Part part) { int level = getMatchingLevel(part); if (level == SearchPattern.POSSIBLE_MATCH || level == SearchPattern.ACCURATE_MATCH){ return locator.matchesPart(part); } return level; } public void checkMatching(Node node) { this.locator.matchCheck(node, this); } public boolean isEmpty() { return this.potentialMatchingNodes.size() == 0 && this.matchingNodes.size() == 0; } /** * Returns the matching nodes that are in the given range. */ private Node[] matchingNodes(int start, int end) { return this.nodesInRange(start, end, this.matchingNodes); } public boolean needsResolve() { return this.potentialMatchingNodes.size() > 0; } /** * Returns the matching nodes that are in the given range in the source order. */ private Node[] nodesInRange(int start, int end, Map set) { // collect nodes in the given range ArrayList nodes = new ArrayList(); for (Iterator keys = set.keySet().iterator(); keys.hasNext();) { Node node = (Node)keys.next(); if (start <= node.getOffset() && (node.getOffset() + node.getLength()) <= end) { nodes.add(node); } } Node[] result = new Node[nodes.size()]; nodes.toArray(result); // sort nodes by source starts Util.Comparer comparer = new Util.Comparer() { public int compare(Object o1, Object o2) { Node node1 = (Node) o1; Node node2 = (Node) o2; return node1.getOffset() - node2.getOffset(); } }; Util.sort(result, comparer); return result; } public Integer removePossibleMatch(Node node) { long key = (((long) node.getOffset()) << 32) + (node.getOffset() + node.getLength()); this.potentialMatchingNodesKeys.put(key, null); return (Integer) this.potentialMatchingNodes.remove(node); } public Integer removeTrustedMatch(Node node) { long key = (((long) node.getOffset()) << 32) + (node.getOffset() + node.getLength()); this.matchingNodesKeys.put(key, null); return (Integer) this.matchingNodes.remove(node); } // /** // * Visit the given method declaration and report the nodes that match exactly the // * search pattern (ie. the ones in the matching nodes set) // * Note that the method declaration has already been checked. // */ // private void reportMatching(AbstractMethodDeclaration method, IJavaElement parent, boolean typeInHierarchy) throws CoreException { // // declaration in this method // // (NB: declarations must be searched first (see bug 20631 Declaration of local binary type not found) // if ((method.bits & AstNode.HasLocalTypeMASK) != 0) { // LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor(); // localDeclarationVisitor.enclosingElement = // (parent instanceof IType) ? this.locator.createMethodHandle(method, (IType) parent) : parent; // try { // method.traverse(localDeclarationVisitor, (ClassScope) null); // } catch (WrappedCoreException e) { // throw e.coreException; // } // } // // // references in this method // if (typeInHierarchy) { // AstNode[] nodes = this.matchingNodes(method.declarationSourceStart, method.declarationSourceEnd); // for (int i = 0; i < nodes.length; i++) { // AstNode node = nodes[i]; // Integer level = (Integer) this.matchingNodes.get(node); // if ((this.matchContainer & SearchPattern.METHOD) != 0) { // this.locator.reportReference( // node, // method, // parent, // level.intValue() == SearchPattern.ACCURATE_MATCH // ? IJavaSearchResultCollector.EXACT_MATCH // : IJavaSearchResultCollector.POTENTIAL_MATCH); // this.matchingNodes.remove(node); // } // } // } // if (this.potentialMatchingNodes(method.declarationSourceStart, method.declarationSourceEnd).length == 0) { // // no need to resolve the statements in the method // method.statements = null; // } // } /** * Visit the given parse tree and report the nodes that match exactly the * search pattern. */ public void reportMatching(ICompiledFileUnit unit) throws CoreException { if (this.cuHasBeenResolved) { // move the potential matching nodes that exactly match the search pattern to the matching nodes set // EGLTODO: Support this? for (Iterator potentialMatches = this.potentialMatchingNodes.keySet().iterator(); potentialMatches.hasNext();) { Node node = (Node) potentialMatches.next(); int level; if (node instanceof ImportDeclaration) { // special case for import refs: they don't know their binding // import ref cannot be in the hirarchy of a type // if (this.locator.hierarchyResolver != null) // continue; // IEGLImportStatement importRef = (IEGLImportStatement) node; // Binding binding; // if (importRef.isOnDemandImportStatement()) { // binding = unit.scope.getTypeOrPackage(CharOperation.subarray(importRef.tokens, 0, importRef.tokens.length)); // } else { // binding = unit.scope.getTypeOrPackage(importRef.tokens); // } // level = this.locator.pattern.matchLevel(binding); // // if (level == SearchPattern.ACCURATE_MATCH || level == SearchPattern.INACCURATE_MATCH) { // // create defining import handle // IEGLElement importHandle = this.locator.createImportHandle(importRef); // this.locator.pattern.matchReportImportRef( // importRef, // binding, // importHandle, // level == SearchPattern.ACCURATE_MATCH // ? IEGLSearchResultCollector.EXACT_MATCH // : IEGLSearchResultCollector.POTENTIAL_MATCH, // this.locator); // } } else { level = this.locator.matchLevel(node, true); if (level == SearchPattern.ACCURATE_MATCH || level == SearchPattern.INACCURATE_MATCH) { this.matchingNodes.put(node, new Integer(level)); } } } this.potentialMatchingNodes = new HashMap(); } // package declaration PackageDeclaration pkg = unit.getFile().getPackageDeclaration(); Integer level; if (pkg != null && (level = (Integer) this.matchingNodes.remove(pkg)) != null) { if ((this.matchContainer & SearchPattern.EGL_FILE) != 0) { this.locator.reportPackageDeclaration(pkg); } } // import declarations if (!this.cuHasBeenResolved) { ImportDeclaration[] imports = (ImportDeclaration[])unit.getFile().getImportDeclarations().toArray(new ImportDeclaration[unit.getFile().getImportDeclarations().size()]); if (imports != null) { for (int i = 0; i < imports.length; i++) { ImportDeclaration importRef = imports[i]; Name importName = importRef.getName(); Node[] importNodes = nodesInRange(importName.getOffset(),importName.getOffset() + importName.getLength(),this.matchingNodes); if (importNodes != null && importNodes.length > 0){ Node node = importNodes[0]; if ((level = (Integer) this.matchingNodes.remove(node)) != null) { if ((this.matchContainer & SearchPattern.EGL_FILE) != 0) { this.locator.reportImport( importRef, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); } } } } } } // else import declarations have already been processed above // parts Part[] parts = (Part[])unit.getFileParts().toArray(new Part[unit.getFileParts().size()]); if (parts != null) { for (int i = 0; i < parts.length; i++) { Part part = parts[i]; if ((level = (Integer) this.matchingNodes.remove(part)) != null) { if ((this.matchContainer & SearchPattern.EGL_FILE) != 0) { this.locator.reportPartDeclaration( part, null, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); } } this.reportMatching(part, null); } } } /** * Visit the given field declaration and report the nodes that match exactly the * search pattern (ie. the ones in the matching nodes set) * Note that the field declaration has already been checked. */ private void reportMatchingField(Node field, IEGLElement parent) // IEGLPart part) , boolean typeInHierarchy) throws CoreException { // EGLTODO: Need typeInHierarchy? //if (typeInHierarchy) { Node[] nodes = this.matchingNodes(((Node)field).getOffset(), ((Node)field).getOffset() + ((Node)field).getLength()); for (int i = 0; i < nodes.length; i++) { Node node = nodes[i]; Integer level = (Integer) this.matchingNodes.get(node); if ((this.matchContainer & SearchPattern.FIELD) != 0) { this.locator.reportFieldReference( node, //part, field, parent, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); this.matchingNodes.remove(node); } } //} } private void reportMatchingUse(Node use, IEGLElement parent, Part part) //, boolean typeInHierarchy) throws CoreException { // EGLTODO: Need typeInHierarchy? //if (typeInHierarchy) { List useNames; if(use instanceof UseStatement){ useNames = ((UseStatement)use).getNames(); for(int i=0; i<useNames.size(); i++) { Node name = (Node)useNames.get(i); Node[] nodes = this.matchingNodes(name.getOffset(), (name.getOffset() + name.getLength())); for (int j = 0; j < nodes.length; j++) { Node node = nodes[j]; Integer level = (Integer) this.matchingNodes.get(node); if ((this.matchContainer & SearchPattern.USE) != 0) { this.locator.reportUseReference( node, part, (Name)name, parent, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); this.matchingNodes.remove(node); } } } } } /** * Visit the given type declaration and report the nodes that match exactly the * search pattern (ie. the ones in the matching nodes set) * Note that the type declaration has already been checked. */ public void reportMatching(Part part, IEGLElement parent) throws CoreException { // filter out element not in hierarchy scope //boolean typeInHierarchy = part == null || this.locator.typeInHierarchy(type.binding); // create type handle IEGLElement enclosingElement; if (parent == null) { enclosingElement = this.locator.createPartHandle(part.getName().getCanonicalName()); } else if (parent instanceof IPart) { enclosingElement = this.locator.createPartHandle((IPart) parent, part.getName().getCanonicalName()); if (enclosingElement == null) return; } else { enclosingElement = parent; } switch (part.getPartType()) { case Part.PROGRAM : reportMatchingProgram((Program) part, enclosingElement); break; case Part.LIBRARY : reportMatchingLibrary((Library) part, enclosingElement); break; case Part.RECORD : reportMatchingRecord((Record)part, enclosingElement); break; case Part.HANDLER : reportMatchingHandler((Handler) part, enclosingElement); break; case Part.SERVICE : reportMatchingService((Service) part, enclosingElement); break; case Part.INTERFACE : reportMatchingInterface((Interface) part, enclosingElement); break; case Part.DELEGATE : reportMatchingDelegate((Delegate) part, enclosingElement); break; case Part.EXTERNALTYPE : reportMatchingExternalType((ExternalType) part, enclosingElement); break; case Part.ENUMERATION : reportMatchingEnumeration((Enumeration) part, enclosingElement); break; case Part.CLASS : reportMatchingClass((Class) part, enclosingElement); break; } Name subtype = part.getSubType(); if (subtype != null) { reportMatchingField(subtype, enclosingElement); } reportMatchingSettings(part,enclosingElement); } private void reportMatchingDelegate(final Delegate delegate, IEGLElement enclosingElement) throws CoreException{ // this.reportMatchingFields(delegate, enclosingElement); Node[] nodes = this.matchingNodes(delegate.getOffset(), delegate.getOffset() + delegate.getLength()); for (int i = 0; i < nodes.length; i++) { Node node = nodes[i]; Integer level = (Integer) this.matchingNodes.get(node); if ((this.matchContainer & SearchPattern.FIELD) != 0) { this.locator.reportReference( node, //part, delegate, enclosingElement, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); this.matchingNodes.remove(node); } } Integer level; if ((level = (Integer) this.matchingNodes.remove(delegate)) != null) { if ((this.matchContainer & SearchPattern.PART) != 0) { this.locator.reportPartDeclaration( delegate, enclosingElement, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); } } } private void reportMatchingExternalType(final ExternalType externalType, IEGLElement enclosingElement) throws CoreException{ reportMatchingFields(externalType, enclosingElement); reportMatchingNestedFunctions(externalType, enclosingElement); for(Iterator iter = externalType.getExtendedTypes().iterator(); iter.hasNext();) { Name name = (Name) iter.next(); Integer level = (Integer) this.matchingNodes.get(name); if (( level != null && (this.matchContainer & SearchPattern.FIELD) != 0)) { this.locator.reportFieldReference( name, //part, externalType, enclosingElement, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); this.matchingNodes.remove(name); } } } private void reportMatchingEnumeration(final Enumeration enumeration, IEGLElement enclosingElement) throws CoreException{ //TODO search } private void reportMatchingProgram(final Program program, final IEGLElement enclosingElement) throws CoreException{ reportMatchingFields(program, enclosingElement); reportMatchingUses(program, enclosingElement); reportMatchingNestedFunctions(program, enclosingElement); } private void reportMatchingLibrary(final Library library, final IEGLElement enclosingElement) throws CoreException{ reportMatchingFields(library, enclosingElement); reportMatchingUses(library, enclosingElement); reportMatchingNestedFunctions(library, enclosingElement); } private void reportMatchingNestedFunctions(Node node,final IEGLElement enclosingElement){ node.accept(new AbstractASTVisitor(){ public boolean visit(NestedFunction nestedFunction) { try { reportMatchingFunction(nestedFunction, enclosingElement); } catch (CoreException e) { e.printStackTrace(); } return false; } }); } private void reportMatchingHandler(final Handler handler, IEGLElement enclosingElement) throws CoreException{ reportMatchingFields(handler, enclosingElement); reportMatchingUses(handler, enclosingElement); reportMatchingNestedFunctions(handler, enclosingElement); } private void reportMatchingClass(final Class eglClass, IEGLElement enclosingElement) throws CoreException{ reportMatchingFields(eglClass, enclosingElement); reportMatchingUses(eglClass, enclosingElement); reportMatchingNestedFunctions(eglClass, enclosingElement); } private void reportMatchingService(final Service service, final IEGLElement enclosingElement) throws CoreException{ reportMatchingFields(service, enclosingElement); reportMatchingUses(service, enclosingElement); reportMatchingNestedFunctions(service, enclosingElement); reportMatchingImplementedInterfaces(service, enclosingElement); } private void reportMatchingImplementedInterfaces(Service service, IEGLElement enclosingElement) throws CoreException{ List definedInterfaceNames = service.getImplementedInterfaces(); for (Iterator iter = definedInterfaceNames.iterator(); iter.hasNext();) { Name interfaceName = (Name) iter.next(); int rangeOffset = ((Node)interfaceName).getOffset(); int rangeLength = ((Node)interfaceName).getLength(); Integer level; // Check for interfaces that are referenced by this service Node[] nodes = this.matchingNodes(rangeOffset, rangeOffset + rangeLength); for (int i = 0; i < nodes.length; i++) { Node node = nodes[i]; level = (Integer) this.matchingNodes.get(node); if ((this.matchContainer & SearchPattern.PART) != 0) { this.locator.reportImplementsReference( node, //part, service, interfaceName, enclosingElement, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); this.matchingNodes.remove(node); } } } } private void reportMatchingInterface(final Interface intrface, IEGLElement enclosingElement) throws CoreException{ reportMatchingNestedFunctions(intrface, enclosingElement); } private void reportMatchingRecord(Record part, IEGLElement enclosingElement)throws CoreException{ reportMatchingFields(part,enclosingElement); } private void reportMatchingFunction(NestedFunction function, IEGLElement enclosingElement) throws CoreException { reportMatchingFields(function, enclosingElement); Integer level; // Check for fields that are being referenced within this function Node[] nodes = this.matchingNodes(function.getOffset(), function.getOffset() + function.getLength()); for (int i = 0; i < nodes.length; i++) { Node node = nodes[i]; level = (Integer) this.matchingNodes.get(node); if ((this.matchContainer & SearchPattern.FIELD) != 0) { this.locator.reportReference( node, //part, function, enclosingElement, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); this.matchingNodes.remove(node); } } // check to see if this function declaration is being searched for if ((level = (Integer) this.matchingNodes.remove(function)) != null) { if ((this.matchContainer & SearchPattern.FUNCTION) != 0) { this.locator.reportFunctionDeclaration( function, enclosingElement, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); } } } private void reportMatchingFields(Node node, final IEGLElement enclosingElement) throws CoreException{ node.accept(new AbstractASTVisitor(){ Integer level; private void reportNamedNode(Node node,IEGLElement parent){ try { if ((level = (Integer) matchingNodes.remove(node)) != null //&& typeInHierarchy // EGLTODO: Type Hierarchy? && (matchContainer & SearchPattern.PART) != 0) { // Only report the field if it has a name (i.e. not filler structure items locator.reportField( node, enclosingElement, level.intValue() == SearchPattern.ACCURATE_MATCH ? IEGLSearchResultCollector.EXACT_MATCH : IEGLSearchResultCollector.POTENTIAL_MATCH); } reportMatchingField(node, parent); } catch (CoreException e) { e.printStackTrace(); } } public boolean visit(ClassDataDeclaration classDataDeclaration) { reportNamedNode(classDataDeclaration,enclosingElement); return false; } public boolean visit(FunctionParameter functionParameter) { reportNamedNode(functionParameter,enclosingElement); return false; } public boolean visit(StructureItem structureItem){ reportNamedNode(structureItem,enclosingElement); return false; } }); } private void reportMatchingUses(final Part part, final IEGLElement enclosingElement) throws CoreException { part.accept(new AbstractASTVisitor(){ public boolean visit(UseStatement useStatement) { try { reportMatchingUse(useStatement,enclosingElement,part); } catch (CoreException e) { e.printStackTrace(); } return false; } }); } private void reportMatchingSettings(final Part part,final IEGLElement enclosingElement) throws CoreException { part.accept(new DefaultASTVisitor(){ public boolean visit(Delegate delegate) { return true; } public boolean visit(ExternalType externalType) { return true; } public boolean visit(Interface interfaceNode) { return true; } public boolean visit(Library library) { return true; } public boolean visit(Program program) { return true; } public boolean visit(Record record) { return true; } public boolean visit(Service service) { return true; } public boolean visit(Handler handler) { return true; } public boolean visit(Enumeration enumeration) { return true; } public boolean visit(SettingsBlock settingsBlock) { reportMatchingSettingsBlock(part,enclosingElement,settingsBlock); return false; } }); } private void reportMatchingSettingsBlock(final Part part,final IEGLElement enclosingElement,SettingsBlock settingsBlock){ List decls = settingsBlock.getSettings(); for (Iterator iter = decls.iterator(); iter.hasNext();) { Node decl = (Node) iter.next(); decl.accept(new DefaultASTVisitor() { private void reportNamedNode(Node node,IEGLElement parent){ try { reportMatchingField(node, parent); } catch (CoreException e) { e.printStackTrace(); } } public boolean visit(SetValuesExpression setValuesExpression) { Expression expr = setValuesExpression.getExpression(); if (expr instanceof AnnotationExpression) { Name name = ((AnnotationExpression)expr).getName(); if (name.resolveType() != null){ reportNamedNode(name,enclosingElement); } else if (name.resolveElement() != null) { reportNamedNode(name,enclosingElement); } } SettingsBlock block = setValuesExpression.getSettingsBlock(); reportMatchingSettingsBlock(part,enclosingElement,block); return false; } public boolean visit(Assignment assignment) { Expression expr = assignment.getRightHandSide(); expr.accept(new AbstractASTExpressionVisitor(){ public boolean visitName(Name name) { if (name.resolveType() != null){ reportNamedNode(name,enclosingElement); } return false; } public boolean visitExpression(Expression expression) { return true; } }); assignment.getLeftHandSide().accept(new AbstractASTExpressionVisitor(){ public boolean visitName(Name name) { if (name.resolveType() != null){ reportNamedNode(name,enclosingElement); } return false; } }); return false; } }); } } public String toString() { StringBuffer result = new StringBuffer(); result.append("Exact matches:"); //$NON-NLS-1$ for (Iterator iter = this.matchingNodes.keySet().iterator(); iter.hasNext();) { result.append("\n"); //$NON-NLS-1$ Node node = (Node) iter.next(); Object value = this.matchingNodes.get(node); if (value instanceof Integer) { result.append('\t'); int accuracy = ((Integer) value).intValue(); switch (accuracy) { case SearchPattern.IMPOSSIBLE_MATCH : result.append("IMPOSSIBLE_MATCH: "); //$NON-NLS-1$ break; case SearchPattern.POSSIBLE_MATCH : result.append("POSSIBLE_MATCH: "); //$NON-NLS-1$ break; case SearchPattern.INACCURATE_MATCH : result.append("INACCURATE_MATCH: "); //$NON-NLS-1$ break; case SearchPattern.ACCURATE_MATCH : result.append("ACCURATE_MATCH: "); //$NON-NLS-1$ break; } } result.append(node.toString()); } result.append("\nPotential matches:"); //$NON-NLS-1$ for (Iterator iter = this.potentialMatchingNodes.keySet().iterator(); iter.hasNext();) { result.append("\n"); //$NON-NLS-1$ Node node = (Node) iter.next(); Object value = this.potentialMatchingNodes.get(node); if (value instanceof Integer) { result.append("\t"); //$NON-NLS-1$ int accuracy = ((Integer) value).intValue(); switch (accuracy) { case SearchPattern.IMPOSSIBLE_MATCH : result.append("IMPOSSIBLE_MATCH: "); //$NON-NLS-1$ break; case SearchPattern.POSSIBLE_MATCH : result.append("POSSIBLE_MATCH: "); //$NON-NLS-1$ break; case SearchPattern.INACCURATE_MATCH : result.append("INACCURATE_MATCH: "); //$NON-NLS-1$ break; case SearchPattern.ACCURATE_MATCH : result.append("ACCURATE_MATCH: "); //$NON-NLS-1$ break; } } result.append(node.toString()); } return result.toString(); } }