blob: 1624862ef29696a20c0bb93d349baaa72eec99d8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 xored software, Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* xored software, Inc. - initial API and Implementation (Alex Panchenko)
*******************************************************************************/
package org.eclipse.dltk.javascript.internal.core.codeassist;
import java.util.Stack;
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.FunctionStatement;
import org.eclipse.dltk.javascript.typeinference.IValueCollection;
import org.eclipse.dltk.javascript.typeinference.IValueReference;
public class CompletionVisitor extends TypeInferencerVisitor {
private final int position;
public CompletionVisitor(ITypeInferenceContext context, int position) {
super(context);
this.position = position;
}
static class Level {
boolean enabled;
}
private Stack<Level> levels = new Stack<Level>();
private IValueCollection savedCollection = null;
private PositionReachedException positionReached = null;
@Override
public IValueReference visit(ASTNode node) {
if (node instanceof FunctionStatement) {
if (levels.isEmpty() && positionReached == null
&& node.sourceStart() >= position) {
return null;
}
return super.visit(node);
}
final IValueReference result = super.visit(node);
if (!levels.isEmpty() && levels.peek().enabled) {
return result;
}
if (savedCollection == null && node.sourceEnd() > position) {
savedCollection = peekContext();
throw new PositionReachedException(node, result);
}
return result;
}
@Override
public IValueReference visitFunctionStatement(FunctionStatement node) {
final Level level = new Level();
level.enabled = node.sourceEnd() < position
|| node.sourceStart() > position;
levels.push(level);
IValueReference result;
try {
result = super.visitFunctionStatement(node);
} finally {
levels.pop();
}
return result;
}
@Override
public void visitFunctionBody(FunctionStatement node) {
try {
super.visitFunctionBody(node);
} catch (PositionReachedException e) {
positionReached = e;
}
}
@Override
public IValueCollection getCollection() {
if (savedCollection != null) {
return savedCollection;
}
return super.getCollection();
}
}