blob: 87db87413a44293ab2233fa140b5aec650b86fda [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 xored software, Inc.
*
* 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:
* xored software, Inc. - initial API and Implementation (Alex Panchenko)
*******************************************************************************/
package org.eclipse.dltk.javascript.internal.core.codeassist;
import java.util.List;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.internal.javascript.ti.ITypeInferenceContext;
import org.eclipse.dltk.internal.javascript.ti.PositionReachedException;
import org.eclipse.dltk.internal.javascript.ti.TypeInferencerVisitor;
import org.eclipse.dltk.javascript.ast.Argument;
import org.eclipse.dltk.javascript.ast.CallExpression;
import org.eclipse.dltk.javascript.ast.Expression;
import org.eclipse.dltk.javascript.ast.FunctionStatement;
import org.eclipse.dltk.javascript.ast.Identifier;
import org.eclipse.dltk.javascript.ast.VariableDeclaration;
import org.eclipse.dltk.javascript.typeinference.IValueCollection;
import org.eclipse.dltk.javascript.typeinference.IValueReference;
import org.eclipse.dltk.javascript.typeinference.ReferenceKind;
public class SelectionVisitor extends TypeInferencerVisitor {
private final ASTNode target;
private IValueReference value;
private IValueReference[] arguments;
public SelectionVisitor(ITypeInferenceContext context, ASTNode target) {
super(context);
this.target = target;
}
public IValueReference getValue() {
return value;
}
public IValueReference[] getArguments() {
return arguments;
}
@Override
public IValueReference visit(ASTNode node) {
final IValueReference result = super.visit(node);
if (node == target) {
value = result;
earlyExit();
}
return result;
}
@Override
public IValueReference visitCallExpression(CallExpression node) {
final IValueReference reference;
boolean nullValue = value == null;
try {
reference = visit(node.getExpression());
} finally {
boolean valueHit = value != null && nullValue;
final List<ASTNode> callArgs = node.getArguments();
final IValueReference[] arguments = new IValueReference[callArgs
.size()];
for (int i = 0, size = callArgs.size(); i < size; ++i) {
arguments[i] = visit(callArgs.get(i));
}
if (valueHit) {
this.arguments = arguments;
}
}
if (reference != null) {
return reference.getChild(IValueReference.FUNCTION_OP);
} else {
return null;
}
}
@Override
protected IValueReference extractNamedChild(IValueReference parent,
Expression name) {
final IValueReference result = super.extractNamedChild(parent, name);
if (name == target) {
value = result;
earlyExit();
}
return result;
}
private IValueReference check(Identifier node, IValueReference reference) {
if (node == target) {
value = reference;
earlyExit();
}
return reference;
}
@Override
public void visitFunctionBody(FunctionStatement node) {
for (Argument argument : node.getArguments()) {
check(argument.getIdentifier(),
peekContext().getChild(argument.getArgumentName()));
}
super.visitFunctionBody(node);
}
@Override
protected IValueReference createVariable(
IValueCollection context, VariableDeclaration declaration) {
return check(declaration.getIdentifier(),
super.createVariable(context, declaration));
}
@Override
public IValueReference visitFunctionStatement(FunctionStatement node) {
IValueReference fs = super.visitFunctionStatement(node);
if (node.getName() != null)
visit(node.getName());
return fs;
}
private void earlyExit() {
if (value == null || value.getKind() != ReferenceKind.UNKNOWN) {
throw new PositionReachedException(target, value);
}
}
}