/*******************************************************************************
* Copyright (c) 2009 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
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.core.search;
import java.util.Collection;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.Modifiers;
import org.eclipse.dltk.ast.declarations.Argument;
import org.eclipse.dltk.ast.declarations.FieldDeclaration;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.declarations.TypeDeclaration;
import org.eclipse.dltk.ast.expressions.CallArgumentsList;
import org.eclipse.dltk.ast.expressions.CallExpression;
import org.eclipse.dltk.ast.expressions.Expression;
import org.eclipse.dltk.ast.references.ConstantReference;
import org.eclipse.dltk.ast.references.SimpleReference;
import org.eclipse.dltk.ast.references.TypeReference;
import org.eclipse.dltk.ast.references.VariableReference;
import org.eclipse.dltk.core.search.matching.MatchLocator;
import org.eclipse.dltk.core.search.matching.MatchLocatorParser;
import org.eclipse.dltk.core.search.matching.PatternLocator;
import org.eclipse.php.core.compiler.ast.nodes.*;
import org.eclipse.php.internal.core.compiler.ast.parser.ASTUtils;
public class PHPMatchLocatorParser extends MatchLocatorParser {
public PHPMatchLocatorParser(MatchLocator locator) {
super(locator);
}
protected void visitTypeDeclaration(TypeDeclaration t) {
if (t instanceof NamespaceDeclaration && ((NamespaceDeclaration) t).isGlobal()) {
return;
}
super.visitTypeDeclaration(t);
}
protected void processStatement(ASTNode node, PatternLocator locator) {
if (node instanceof FieldDeclaration) {
locator.match((FieldDeclaration) node, getNodeSet());
} else if (node instanceof ConstantDeclaration) {
ConstantDeclaration constDecl = (ConstantDeclaration) node;
ConstantReference constantName = constDecl.getConstantName();
FieldDeclaration decl = new FieldDeclarationLocation(constantName.getName(), constantName.sourceStart(),
constantName.sourceEnd(), constDecl.sourceStart(), constDecl.sourceEnd());
decl.setModifiers(Modifiers.AccConstant);
locator.match(decl, getNodeSet());
} else if (node instanceof FieldAccess) {
Expression field = ((FieldAccess) node).getField();
if (field instanceof SimpleReference) {
SimpleReference ref = (SimpleReference) field;
SimpleReferenceLocation refLoc = new SimpleReferenceLocation(ref.sourceStart(), ref.sourceEnd(),
'$' + ref.getName());
locator.match(refLoc, getNodeSet());
}
} else if (node instanceof StaticFieldAccess) {
Expression field = ((StaticFieldAccess) node).getField();
if (field instanceof SimpleReference) {
SimpleReference ref = (SimpleReference) field;
SimpleReferenceLocation refLoc = new SimpleReferenceLocation(ref.sourceStart(), ref.sourceEnd(),
'$' + ref.getName());
locator.match(refLoc, getNodeSet());
}
} else if (node instanceof StaticConstantAccess) {
ConstantReference constantRef = ((StaticConstantAccess) node).getConstant();
locator.match(constantRef, getNodeSet());
}
/*
* else if (node instanceof ConstantReference) {
* locator.match((ConstantReference)node, getNodeSet()); }
*/
else if (node instanceof Assignment) {
Expression left = ((Assignment) node).getVariable();
if (left instanceof FieldAccess) { // class variable ($this->a = .)
FieldAccess fieldAccess = (FieldAccess) left;
Expression dispatcher = fieldAccess.getDispatcher();
if (dispatcher instanceof VariableReference) { // &&
// "$this".equals(((VariableReference)
// dispatcher).getName()))
// {
// //$NON-NLS-1$
Expression field = fieldAccess.getField();
if (field instanceof SimpleReference) {
SimpleReference ref = (SimpleReference) field;
FieldDeclaration decl = new FieldDeclarationLocation('$' + ref.getName(), ref.sourceStart(),
ref.sourceEnd(), node.sourceStart(), node.sourceEnd());
locator.match(decl, getNodeSet());
}
}
} else if (left instanceof VariableReference) {
FieldDeclaration decl = new FieldDeclarationLocation(((VariableReference) left).getName(),
left.sourceStart(), left.sourceEnd(), node.sourceStart(), node.sourceEnd());
locator.match(decl, getNodeSet());
}
} else if (node instanceof ListVariable) {
recursiveListMatch(node, locator);
} else if (node instanceof TypeReference) {
locator.match((TypeReference) node, getNodeSet());
} else if (node instanceof VariableReference) {
locator.match((VariableReference) node, getNodeSet());
} else if (node instanceof CallExpression) {
FieldDeclaration constantDecl = ASTUtils.getConstantDeclaration((CallExpression) node);
if (constantDecl != null) {
locator.match(constantDecl, getNodeSet());
} else {
locator.match((CallExpression) node, getNodeSet());
}
} else if (node instanceof Include) {
Include include = (Include) node;
if (include.getExpr() instanceof Scalar) {
Scalar filePath = (Scalar) include.getExpr();
CallExpression callExpression = new CallExpressionLocation(filePath.sourceStart(), filePath.sourceEnd(),
null, "include", new CallArgumentsList()); //$NON-NLS-1$
locator.match(callExpression, getNodeSet());
}
} else if (node instanceof Argument) {
SimpleReference ref = ((Argument) node).getRef();
FieldDeclaration decl = new FieldDeclarationLocation(ref.getName(), ref.sourceStart(), ref.sourceEnd(),
node.sourceStart(), node.sourceEnd());
locator.match(decl, getNodeSet());
} else if (node instanceof ForEachStatement) {
Expression key = ((ForEachStatement) node).getKey();
Expression value = ((ForEachStatement) node).getValue();
if (key instanceof SimpleReference) {
SimpleReference ref = (SimpleReference) key;
FieldDeclaration decl = new FieldDeclarationLocation(ref.getName(), ref.sourceStart(), ref.sourceEnd(),
node.sourceStart(), node.sourceEnd());
locator.match(decl, getNodeSet());
}
if (value instanceof SimpleReference) {
SimpleReference ref = (SimpleReference) value;
FieldDeclaration decl = new FieldDeclarationLocation(ref.getName(), ref.sourceStart(), ref.sourceEnd(),
ref.sourceStart(), ref.sourceEnd());
locator.match(decl, getNodeSet());
}
} else if (node instanceof CatchClause) {
VariableReference ref = ((CatchClause) node).getVariable();
FieldDeclaration decl = new FieldDeclarationLocation(ref.getName(), ref.sourceStart(), ref.sourceEnd(),
node.sourceStart(), node.sourceEnd());
locator.match(decl, getNodeSet());
}
}
private void recursiveListMatch(ASTNode node, PatternLocator locator) {
final Collection<? extends Expression> variables = ((ListVariable) node).getVariables();
for (Expression expression : variables) {
if (expression instanceof ListVariable) {
recursiveListMatch(expression, locator);
} else if (expression instanceof VariableReference) {
FieldDeclaration decl = new FieldDeclarationLocation(((VariableReference) expression).getName(),
expression.sourceStart(), expression.sourceEnd(), expression.sourceStart(),
expression.sourceEnd());
locator.match(decl, getNodeSet());
}
}
}
public void parseBodies(ModuleDeclaration unit) {
unit.rebuild();
super.parseBodies(unit);
}
static boolean locationEquals(ASTNode node, Object obj) {
if (obj == node)
return true;
if (obj instanceof ASTNode) {
return node.locationMatches((ASTNode) obj);
}
return false;
}
class FieldDeclarationLocation extends FieldDeclaration {
public FieldDeclarationLocation(String name, int nameStart, int nameEnd, int declStart, int declEnd) {
super(name, nameStart, nameEnd, declStart, declEnd);
}
public boolean equals(Object obj) {
return locationEquals(this, obj);
}
public int hashCode() {
return this.sourceEnd() * 1001 + this.sourceEnd();
}
}
private static final class SimpleReferenceLocation extends SimpleReference {
private SimpleReferenceLocation(int start, int end, String name) {
super(start, end, name);
}
public boolean equals(Object obj) {
return locationEquals(this, obj);
}
public int hashCode() {
return this.sourceEnd() * 1001 + this.sourceEnd();
}
}
class CallExpressionLocation extends CallExpression {
public CallExpressionLocation(ASTNode receiver, String name, CallArgumentsList args) {
super(receiver, name, args);
}
public CallExpressionLocation(int start, int end, ASTNode receiver, SimpleReference name,
CallArgumentsList args) {
super(start, end, receiver, name, args);
}
public CallExpressionLocation(int start, int end, ASTNode receiver, String name, CallArgumentsList args) {
super(start, end, receiver, name, args);
}
public boolean equals(Object obj) {
return locationEquals(this, obj);
}
public int hashCode() {
return this.sourceEnd() * 1001 + this.sourceEnd();
}
}
}