package org.eclipse.dltk.tcl.core; import java.util.List; import org.eclipse.dltk.ast.ASTNode; import org.eclipse.dltk.ast.ASTVisitor; import org.eclipse.dltk.ast.declarations.FieldDeclaration; import org.eclipse.dltk.ast.declarations.MethodDeclaration; import org.eclipse.dltk.ast.declarations.TypeDeclaration; import org.eclipse.dltk.ast.expressions.CallExpression; import org.eclipse.dltk.ast.expressions.Expression; import org.eclipse.dltk.ast.expressions.MethodCallExpression; import org.eclipse.dltk.ast.expressions.StringLiteral; import org.eclipse.dltk.ast.references.SimpleReference; import org.eclipse.dltk.ast.references.TypeReference; import org.eclipse.dltk.core.DLTKCore; import org.eclipse.dltk.core.search.matching.MatchLocator; import org.eclipse.dltk.core.search.matching.PatternLocator; import org.eclipse.dltk.tcl.ast.TclStatement; import org.eclipse.dltk.tcl.ast.expressions.TclBlockExpression; import org.eclipse.dltk.tcl.ast.expressions.TclExecuteExpression; import org.eclipse.dltk.tcl.core.extensions.IMatchLocatorExtension; import org.eclipse.dltk.tcl.internal.core.TclExtensionManager; import org.eclipse.dltk.tcl.internal.parser.OldTclParserUtils; public class TclMatchLocatorParser extends BasicTclMatchLocatorParser { IMatchLocatorExtension[] extensions; public TclMatchLocatorParser(MatchLocator locator) { super(locator); this.extensions = TclExtensionManager.getDefault() .getMatchLocatorExtensions(); } private ASTVisitor visitor = new ASTVisitor() { public boolean visitGeneral(ASTNode node) throws Exception { // XOTclMatchLocatorParser.this.processStatement(node); PatternLocator locator = TclMatchLocatorParser.this .getPatternLocator(); if (node instanceof TclStatement) { TclStatement statement = (TclStatement) node; // process variables. FieldDeclaration[] fields = OldTclParserUtils .returnVariableDeclarations(statement); for (int k = 0; k < fields.length; ++k) { locator.match(fields[k], TclMatchLocatorParser.this .getNodeSet()); } TclMatchLocatorParser.this.processReferences(statement); } else if (node instanceof FieldDeclaration) { locator.match((FieldDeclaration) node, TclMatchLocatorParser.this.getNodeSet()); } else if (node instanceof CallExpression) { locator.match((CallExpression) node, TclMatchLocatorParser.this .getNodeSet()); } else if (node instanceof TclBlockExpression) { TclBlockExpression block = (TclBlockExpression) node; List ss = block.parseBlockSimple(); if (ss != null) { int slen = ss.size(); for (int u = 0; u < slen; ++u) { ASTNode n = (ASTNode) ss.get(u); TclMatchLocatorParser.this .processReferences((TclStatement) n); } } } for (int i = 0; i < extensions.length; i++) { extensions[i].visitGeneral(node, locator, TclMatchLocatorParser.this.getNodeSet()); } return true; } public boolean visit(MethodDeclaration s) throws Exception { TclMatchLocatorParser.this.getPatternLocator().match( TclMatchLocatorParser.this.processMethod(s), TclMatchLocatorParser.this.getNodeSet()); return true; } public boolean visit(TypeDeclaration s) throws Exception { TclMatchLocatorParser.this.getPatternLocator().match( TclMatchLocatorParser.this.processType(s), TclMatchLocatorParser.this.getNodeSet()); return true; } }; protected void processStatement(ASTNode node) { if (node != null) { try { node.traverse(visitor); } catch (Exception e) { if (DLTKCore.DEBUG) { e.printStackTrace(); } } } } protected void processReferences(TclStatement statement) { Expression commandId = statement.getAt(0); PatternLocator locator; locator = this.getPatternLocator(); if (commandId != null && commandId instanceof SimpleReference) { String name = ((SimpleReference) commandId).getName(); if (name.startsWith("::")) { name = name.substring(2); } if (!kwMap.containsKey(name)) { String[] ns = TclParseUtil.tclSplit(name); for (int i = 0; i < ns.length; ++i) { if (ns[i].length() > 0) { if (i == ns.length - 1) { String namespace = null; int pos = name.lastIndexOf("::"); if (pos != -1) { namespace = name.substring(0, pos); if (namespace.startsWith("::")) { namespace = namespace.substring(2); } } MethodCallExpression node = new MethodCallExpression( commandId.sourceStart(), commandId .sourceEnd(), null, ns[i], null) { public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof ASTNode) { ASTNode s = (ASTNode) obj; if (s.sourceEnd() < 0 || s.sourceStart() < 0) { return false; } return sourceStart() == s.sourceStart() && sourceEnd() == s.sourceEnd(); } return false; } public int hashCode() { return this.sourceEnd() * 1001 + this.sourceEnd(); } }; node.setDeclaringTypeName(namespace); locator.match(node, this.getNodeSet()); } else { locator.match(new TypeReference(commandId .sourceStart(), commandId.sourceEnd(), ns[i]) { public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof ASTNode) { ASTNode s = (ASTNode) obj; if (s.sourceEnd() < 0 || s.sourceStart() < 0) { return false; } return sourceStart() == s.sourceStart() && sourceEnd() == s.sourceEnd(); } return false; } public int hashCode() { return this.sourceEnd() * 1001 + this.sourceEnd(); } }, this.getNodeSet()); } } } } } for (int j = 1; j < statement.getCount(); ++j) { Expression st = statement.getAt(j); if (st instanceof TclExecuteExpression) { TclExecuteExpression expr = (TclExecuteExpression) st; List exprs = expr.parseExpression(); for (int i = 0; i < exprs.size(); ++i) { if (exprs.get(i) instanceof TclStatement) { this.processReferences((TclStatement) exprs.get(i)); } } } else if (st instanceof StringLiteral) { int pos = 0; StringLiteral literal = (StringLiteral) st; String value = literal.getValue(); pos = value.indexOf("$"); while (pos != -1) { SimpleReference ref = OldTclParserUtils .findVariableFromString(literal, pos); if (ref != null) { ref.setName(ref.getName().substring(1)); ref.setEnd(ref.sourceEnd() - 1); locator.match(ref, this.getNodeSet()); pos = pos + ref.getName().length(); } pos = value.indexOf("$", pos + 1); } } else if (st instanceof SimpleReference) { SimpleReference ref = (SimpleReference) st; String name = ref.getName(); if (name.startsWith("$")) { // This is variable usage. ref.setName(name.substring(1)); ref.setEnd(ref.sourceEnd() - 1); locator.match(ref, this.getNodeSet()); } } } } }