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());
}
}
}
}
}