blob: afb5e047223993fbe585ab2616926c2cf9a191a2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2017 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.compiler;
import java.util.List;
import java.util.Stack;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.ASTVisitor;
import org.eclipse.dltk.ast.declarations.Argument;
import org.eclipse.dltk.ast.declarations.MethodDeclaration;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.declarations.TypeDeclaration;
import org.eclipse.dltk.ast.expressions.Expression;
import org.eclipse.dltk.ast.expressions.Literal;
import org.eclipse.dltk.ast.expressions.StringLiteral;
import org.eclipse.dltk.ast.statements.Statement;
import org.eclipse.dltk.compiler.IElementRequestor.TypeInfo;
public class SourceElementRequestVisitor extends ASTVisitor {
protected IElementRequestor fRequestor = null;
protected boolean fInClass = false; // if we are in class
protected boolean fInMethod = false; // if we are in method
protected TypeDeclaration fCurrentClass = null;
protected MethodDeclaration fCurrentMethod = null;
// Used to hold visited nodes in depth
protected Stack<ASTNode> fNodes = new Stack<>();
/**
* @since 2.0
*/
public SourceElementRequestVisitor(IElementRequestor requesor) {
this.fRequestor = requesor;
}
/**
* @return method node that encloses current element, or <code>null</code>
* if there's no one.
*/
public MethodDeclaration getCurrentMethod() {
return this.fCurrentMethod;
}
/**
* @return class node that encloses current element, or <code>null</code> if
* there's no one.
*/
protected TypeDeclaration getCurrentClass() {
return this.fCurrentClass;
}
protected String makeLanguageDependentValue(ASTNode expr) {
return ""; //$NON-NLS-1$
}
/**
* Called then end of methd are visited. Method are added to model before
* this call is done.
*/
protected void onEndVisitMethod(MethodDeclaration method) {
}
protected String[] processSuperClasses(TypeDeclaration type) {
List names = type.getSuperClassNames();
if (names == null) {
return null;
}
if (names.isEmpty()) {
return null;
}
return (String[]) names.toArray(new String[names.size()]);
}
/**
* Called then end of class are visited. Class are added to model before
* this call is done.
*/
protected void onEndVisitClass(TypeDeclaration type) {
}
/**
* Called before method info is propagated to the source element requestor.
* This is a last chance to modify the method info
*
* @since 2.0
*/
protected void modifyMethodInfo(MethodDeclaration methodDeclaration,
ISourceElementRequestor.MethodInfo mi) {
}
/**
* Called before method info is propagated to the source element requestor.
* This is a last chance to modify the class info
*
* @since 2.0
*/
protected void modifyClassInfo(TypeDeclaration typeDeclaration,
TypeInfo ti) {
}
/**
* Creates correct string value from expression. For example for
* StringLiteral returns "value". And so on.
*
* Return "" if it is imposible to make value from expression.
*
* @param expr
* @return
*/
protected String makeValue(ASTNode stmt) {
// if (!(stmt instanceof Expression))
// return null;
String value = ""; //$NON-NLS-1$
if (stmt instanceof StringLiteral) {
value = "\"" + ((StringLiteral) stmt).getValue() + "\""; //$NON-NLS-1$ //$NON-NLS-2$
} else if (stmt instanceof Literal) {
value = ((Literal) stmt).getValue();
} else /* if (stmt instanceof ExtendedVariableReference) */ {
// If it is Dot.
// Lets make recursive value parsing in this case.
value += this.makeLanguageDependentValue(stmt);
}
return value;
}
@Override
public boolean endvisit(MethodDeclaration method) throws Exception {
this.fRequestor.exitMethod(method.sourceEnd());
this.fInMethod = false;
this.fCurrentMethod = null;
this.onEndVisitMethod(method);
this.fNodes.pop();
return true;
}
@Override
public boolean endvisit(TypeDeclaration type) throws Exception {
this.fRequestor.exitType(type.sourceEnd());
this.fInClass = false;
this.fCurrentClass = null;
this.onEndVisitClass(type);
this.fNodes.pop();
return true;
}
@Override
public boolean visit(MethodDeclaration method) throws Exception {
this.fNodes.push(method);
List args = method.getArguments();
String[] parameter = new String[args.size()];
String[] initializers = new String[args.size()];
for (int a = 0; a < args.size(); a++) {
Argument arg = (Argument) args.get(a);
parameter[a] = arg.getName();
if (arg.getInitialization() != null) {
if (arg.getInitialization() instanceof Literal) {
Literal scalar = (Literal) arg.getInitialization();
initializers[a] = scalar.getValue();
}
}
}
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();
mi.parameterInitializers = initializers;
modifyMethodInfo(method, mi);
this.fRequestor.enterMethod(mi);
this.fInMethod = true;
this.fCurrentMethod = method;
return true;
}
@Override
public boolean visit(TypeDeclaration type) throws Exception {
this.fNodes.push(type);
ISourceElementRequestor.TypeInfo info = new ISourceElementRequestor.TypeInfo();
info.modifiers = type.getModifiers();
info.name = type.getName();
info.nameSourceStart = type.getNameStart();
info.nameSourceEnd = type.getNameEnd() - 1;
info.declarationStart = type.sourceStart();
info.superclasses = this.processSuperClasses(type);
modifyClassInfo(type, info);
this.fRequestor.enterType(info);
this.fInClass = true;
this.fCurrentClass = type;
return true;
}
@Override
public boolean endvisit(ModuleDeclaration declaration) throws Exception {
this.fRequestor.exitModule(declaration.sourceEnd());
this.fNodes.pop();
return true;
}
@Override
public boolean visit(ModuleDeclaration declaration) throws Exception {
this.fNodes.push(declaration);
this.fRequestor.enterModule();
return true;
}
@Override
public boolean endvisit(Expression expression) throws Exception {
this.fNodes.pop();
return true;
}
@Override
public boolean endvisit(Statement statement) throws Exception {
this.fNodes.pop();
return true;
}
@Override
public boolean visit(Expression expression) throws Exception {
this.fNodes.push(expression);
return true;
}
@Override
public boolean visit(Statement statement) throws Exception {
this.fNodes.push(statement);
return true;
}
}