}
public IGoal[] init() {
final VariableReference variableReference = (VariableReference) ((ExpressionTypeGoal) goal)
.getExpression();
IContext context = goal.getContext();
IModelAccessCache cache = null;
if (context instanceof IModelCacheContext) {
cache = ((IModelCacheContext) context).getCache();
}
// Handle $this variable reference
if (variableReference.getName().equals("$this")) { //$NON-NLS-1$
if (context instanceof MethodContext) {
MethodContext methodContext = (MethodContext) context;
final LambdaFunctionDeclaration[] lambdas = new LambdaFunctionDeclaration[1];
ContextFinder contextFinder = new ContextFinder(
methodContext.getSourceModule()) {
@Override
public boolean visit(Expression s) throws Exception {
if (s instanceof LambdaFunctionDeclaration) {
LambdaFunctionDeclaration lambda = (LambdaFunctionDeclaration) s;
if (variableReference.sourceStart() > lambda
.sourceStart()
&& variableReference.sourceEnd() < lambda
.sourceEnd()) {
lambdas[0] = lambda;
}
}
return super.visit(s);
}
};
try {
methodContext.getRootNode().traverse(contextFinder);
} catch (Exception e) {
}
PHPVersion phpVersion = ProjectOptions
.getPhpVersion(methodContext.getSourceModule()
.getScriptProject().getProject());
if (lambdas[0] != null
&& (lambdas[0].isStatic() || phpVersion
.isLessThan(PHPVersion.PHP5_4))) {
this.results.add(new SimpleType(SimpleType.TYPE_NULL));
} else {
IEvaluatedType instanceType = methodContext
.getInstanceType();
if (instanceType != null) {
this.results.add(instanceType);
} else {
this.results.add(new SimpleType(SimpleType.TYPE_NULL));
}
}
return IGoal.NO_GOALS;
}
}
try {
if (context instanceof ISourceModuleContext) {
ISourceModuleContext typedContext = (ISourceModuleContext) context;
ASTNode rootNode = typedContext.getRootNode();
ASTNode localScopeNode = rootNode;
if (context instanceof MethodContext) {
localScopeNode = ((MethodContext) context).getMethodNode();
}
LocalReferenceDeclSearcher varDecSearcher = new LocalReferenceDeclSearcher(
typedContext.getSourceModule(), variableReference,
localScopeNode);
rootNode.traverse(varDecSearcher);
PHPModuleDeclaration phpModule = (PHPModuleDeclaration) rootNode;
List<IGoal> subGoals = new LinkedList<IGoal>();
List<VarComment> varComments = phpModule.getVarComments();
List<VarComment> newList = new ArrayList<VarComment>(phpModule
.getVarComments().size());
newList.addAll(varComments);
Collections.sort(newList, new Comparator<VarComment>() {
public int compare(VarComment o1, VarComment o2) {
return o2.sourceStart() - o1.sourceStart();
}
});
for (VarComment varComment : newList) {
if (varComment.sourceStart() > variableReference
.sourceStart()) {
continue;
}
if (varComment.getVariableReference().getName()
.equals(variableReference.getName())) {
List<IGoal> goals = new LinkedList<IGoal>();
for (TypeReference ref : varComment.getTypeReferences()) {
goals.add(new ExpressionTypeGoal(context, ref));
}
return (IGoal[]) goals.toArray(new IGoal[goals.size()]);
}
}
List<PHPDocBlock> docBlocks = new ArrayList<PHPDocBlock>(
phpModule.getPhpDocBlocks().size());
docBlocks.addAll(phpModule.getPhpDocBlocks());
Collections.sort(docBlocks, new Comparator<PHPDocBlock>() {
@Override
public int compare(PHPDocBlock o1, PHPDocBlock o2) {
return o1.sourceStart() - o1.sourceStart();
}
});
for (PHPDocBlock block : docBlocks) {
if (block.sourceStart() > variableReference.sourceStart()
|| localScopeNode.sourceStart() > block
.sourceStart()) {
continue;
}
for (PHPDocTag tag : block.getTags(PHPDocTagKinds.VAR)) {
String value = tag.getValue().trim();
if (value.length() < 5 || value.charAt(0) != '$') {
continue;
}
String[] split = value.split("\\s+"); //$NON-NLS-1$
if (split.length > 1
&& split[0].equals(variableReference.getName())) {
List<IGoal> goals = new LinkedList<IGoal>();
for (String name : split[1].split("\\|")) { //$NON-NLS-1$
if (name.trim().length() > 0) {
goals.add(new ExpressionTypeGoal(context,
new TypeReference(
tag.sourceStart(), tag
.sourceEnd(), name
.trim())));
}
}
return (IGoal[]) goals.toArray(new IGoal[goals
.size()]);
}
}
}
Declaration[] decls = varDecSearcher.getDeclarations();
boolean mergeWithGlobalScope = false;
for (int i = 0; i < decls.length; ++i) {
Declaration decl = decls[i];
// TODO check ArrayCreation and its element type
if (decl instanceof ArrayDeclaration) {
ArrayDeclaration arrayDeclaration = (ArrayDeclaration) decl;
subGoals.add(new ArrayDeclarationGoal(context,
arrayDeclaration));
} else if (decl.getNode() instanceof GlobalStatement) {
mergeWithGlobalScope = true;
} else {
ASTNode declNode = decl.getNode();
if (declNode instanceof ForEachStatement) {
subGoals.add(new ForeachStatementGoal(context,
((ForEachStatement) declNode)
.getExpression()));
} else {
subGoals.add(new ExpressionTypeGoal(context,
declNode));
}
}
}
if (mergeWithGlobalScope
|| (decls.length == 0 && context.getClass() == FileContext.class)) {
// collect all global variables, and merge results with
// existing declarations
subGoals.add(new GlobalVariableReferencesGoal(context,
variableReference.getName()));
}