blob: a442498f875ec06b94291b3799de204e61bba7aa [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 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
*
*******************************************************************************/
package org.eclipse.dltk.internal.javascript.parser.visitors;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.Modifiers;
import org.eclipse.dltk.ast.PositionInformation;
import org.eclipse.dltk.ast.declarations.Argument;
import org.eclipse.dltk.ast.declarations.MethodDeclaration;
import org.eclipse.dltk.ast.expressions.Expression;
import org.eclipse.dltk.ast.references.VariableReference;
import org.eclipse.dltk.ast.statements.Statement;
import org.eclipse.dltk.compiler.ISourceElementRequestor;
import org.eclipse.dltk.compiler.SourceElementRequestVisitor;
public class JavaScriptSourceElementRequestor extends
SourceElementRequestVisitor {
private static class TypeField {
private String fName;
private String fInitValue;
private PositionInformation fPos;
private Expression fExpression;
private ASTNode fToNode;
TypeField(String name, String initValue, PositionInformation pos,
Expression expression, ASTNode toNode) {
this.fName = name;
this.fInitValue = initValue;
this.fPos = pos;
this.fExpression = expression;
this.fToNode = toNode;
}
String getName() {
return this.fName;
}
String getInitValue() {
return this.fInitValue;
}
PositionInformation getPos() {
return this.fPos;
}
Expression getExpression() {
return this.fExpression;
}
ASTNode getToNode() {
return this.fToNode;
}
public boolean equals(Object obj) {
if (obj instanceof TypeField) {
TypeField second = (TypeField) obj;
return second.fName.equals(this.fName)
&& second.fToNode.equals(this.fToNode);
}
return super.equals(obj);
}
public String toString() {
return this.fName;
}
}
// Used to prehold fields if adding in methods.
private List/* <TypeField> */fNotAddedFields = new ArrayList/* <TypeField> */();
/**
* Used to depermine duplicate names.
*/
private Map fTypeVariables = new HashMap();
public JavaScriptSourceElementRequestor(ISourceElementRequestor requestor) {
super(requestor);
}
/**
* Used to create Call value in python syntax.
*/
protected String makeLanguageDependentValue(Expression value) {
String outValue = "";
/*
* if (value instanceof ExtendedVariableReference) { // Lets use AST
* Printer to print extended variable in python like // syntax.
* StringWriter stringWriter = new StringWriter(); CorePrinter printer =
* new CorePrinter(stringWriter); value.printNode(printer);
* printer.flush(); return stringWriter.getBuffer().toString(); }
*/
return outValue;
}
/**
* Parsers Expresssion and extract correct variable reference.
*
* @param left
*/
private void addVariableReference(Expression left, Expression right,
boolean inClass, boolean inMethod) {
if (left == null) {
throw new RuntimeException("addVariable expression can't be null");
}
if (left instanceof VariableReference) {
VariableReference var = (VariableReference) left;
if (!inMethod) { // for module static of class static variables.
if (canAddVariables((ASTNode) this.fNodes.peek(), var.getName())) {
ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
info.modifiers = Modifiers.AccStatic;
info.name = var.getName();
info.nameSourceEnd = var.sourceEnd() - 1;
info.nameSourceStart = var.sourceStart();
info.declarationStart = var.sourceStart();
this.fRequestor.enterField(info);
if (right != null) {
this.fRequestor.exitField(right.sourceEnd() - 1);
} else {
this.fRequestor.exitField(var.sourceEnd() - 1);
}
}
}
}/*
* else if (left instanceof ExtendedVariableReference) { // This is for
* in class and in method. if (inClass && inMethod) {
* ExtendedVariableReference extendedVariable =
* ((ExtendedVariableReference) left);
*
* List varParts = extendedVariable.getExpressions(); if
* (extendedVariable.isDot(0)) { Expression first = (Expression)
* varParts.get(0); // support only local variable addition. // TODO:
* Add more complex variable addition. Expression second = (Expression)
* varParts.get(1);
*
* if (first instanceof VariableReference && second instanceof
* VariableReference) { String varName = ((VariableReference)
* first).getName(); MethodDeclaration currentMethod = this
* .getCurrentMethod(); List <Argument> arguments = currentMethod
* .getArguments(); if (arguments != null && arguments.size() > 0) {
* Argument firstArgument = (Argument) arguments .get(0); String
* argumentName = firstArgument.getName(); if
* (argumentName.equals(varName)) { VariableReference var =
* (VariableReference) second; int initialValueStart = 0; int
* initialValueEnd = 0; if (right != null) { initialValueStart =
* right.sourceStart(); initialValueEnd = right.sourceEnd(); }
* PositionInformation pos = new PositionInformation( var.sourceStart(),
* var.sourceEnd(), initialValueStart, initialValueEnd); String
* initialString = this.makeValue(right); ASTNode method = (ASTNode)
* this.fNodes.pop(); ASTNode toClass = (ASTNode) this.fNodes.peek();
* this.fNodes.push(method);
*
* TypeField field = new TypeField(var.getName(), initialString, pos,
* left, toClass); this.fNotAddedFields.add(field); } } } } } else if
* (left instanceof ExpressionList) { // Multiple // TODO: Add list of
* variables reporting.
*
* // assignment. ExpressionList list = (ExpressionList) left;
* List<Expression> exprs = list.getExpressions(); for (Expression expr
* : exprs) { }
*
* } else {// TODO: dynamic variable handling not yet supported.
*
* } }
*/
}
public boolean visit(Expression expression) throws Exception {
return true;
}
public boolean endvisit(Expression expression) throws Exception {
return true;
}
protected void onEndVisitMethod(MethodDeclaration method) {
Iterator i = this.fNotAddedFields.iterator();
while (i.hasNext()) {
TypeField field = (TypeField) i.next();
if (canAddVariables(field.getToNode(), field.getName())) {
PositionInformation pos = field.getPos();
ISourceElementRequestor.FieldInfo info = new ISourceElementRequestor.FieldInfo();
info.modifiers = Modifiers.AccStatic;
info.name = field.getName();
info.nameSourceEnd = pos.nameEnd - 1;
info.nameSourceStart = pos.nameStart;
info.declarationStart = pos.sourceStart;
this.fRequestor.enterField(info);
this.fRequestor.exitField(pos.sourceEnd);
}
}
this.fNotAddedFields.clear();
}
public boolean visit(Statement statement) throws Exception {
return true;
}
private boolean canAddVariables(ASTNode type, String name) {
if (this.fTypeVariables.containsKey(type)) {
List variables = (List) this.fTypeVariables.get(type);
if (variables.contains(name)) {
return false;
}
variables.add(name);
return true;
} else {
List variables = new ArrayList();
variables.add(name);
this.fTypeVariables.put(type, variables);
return true;
}
}
public boolean endvisit(Statement s) throws Exception {
return true;
}
public boolean visit(MethodDeclaration method) throws Exception {
this.fNodes.push(method);
List/* < Argument > */args = method.getArguments();
String[] parameter = new String[args.size()];
for (int a = 0; a < args.size(); a++) {
Argument arg = (Argument) args.get(a);
parameter[a] = arg.getName();
}
ISourceElementRequestor.MethodInfo mi = new ISourceElementRequestor.MethodInfo();
mi.parameterNames = parameter;
mi.name = method.getName();
mi.modifiers = method.getModifiers();
mi.nameSourceStart = method.getNameStart();
mi.nameSourceEnd = method.getNameEnd() - 1;
mi.declarationStart = method.sourceStart();
((ISourceElementRequestor) this.fRequestor).enterMethodRemoveSame(mi);
this.fInMethod = true;
this.fCurrentMethod = method;
return true;
}
}