blob: fe85fb1da33e688a3722583edee2bb259aeac568 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.uima.ruta.ide.core.codeassist;
import java.util.ArrayList;
import java.util.List;
import org.apache.uima.ruta.ide.core.extensions.ICompletionExtension;
import org.apache.uima.ruta.ide.core.parser.RutaParseUtils;
import org.apache.uima.ruta.ide.parser.ast.RutaStatement;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.ASTVisitor;
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.references.SimpleReference;
import org.eclipse.dltk.ast.statements.Block;
import org.eclipse.dltk.ast.statements.Statement;
import org.eclipse.dltk.codeassist.complete.CompletionNodeFound;
import org.eclipse.dltk.compiler.env.IModuleSource;
public class RutaCompletionParser extends RutaAssistParser {
private static class RutaEmptyCompleteStatement extends RutaStatement {
public RutaEmptyCompleteStatement(List expressions) {
super(expressions);
}
}
private ICompletionExtension[] extensions;
public RutaCompletionParser(ICompletionExtension[] extensions) {
this.extensions = extensions;
}
/**
* Called then element could not be found.
*/
public void handleNotInElement(ASTNode node, int position) {
if (node != null && node.sourceStart() <= position && position <= node.sourceEnd()) {
// this is empty module case
if (node instanceof ModuleDeclaration) {
ModuleDeclaration unit = (ModuleDeclaration) node;
List exprs = new ArrayList();
exprs.add(new SimpleReference(position, position, ""));
RutaEmptyCompleteStatement statement = new RutaEmptyCompleteStatement(exprs);
unit.addStatement(statement);
this.parseBlockStatements(statement, unit, position);
} else if (node instanceof MethodDeclaration) {
// empty keyword like completion.
MethodDeclaration method = (MethodDeclaration) node;
List exprs = new ArrayList();
exprs.add(new SimpleReference(position, position, ""));
RutaEmptyCompleteStatement statement = new RutaEmptyCompleteStatement(exprs);
method.getStatements().add(statement);
this.parseBlockStatements(statement, method, position);
} else if (node instanceof TypeDeclaration) {
// empty keyword like completion.
TypeDeclaration type = (TypeDeclaration) node;
List exprs = new ArrayList();
exprs.add(new SimpleReference(position, position, ""));
RutaEmptyCompleteStatement statement = new RutaEmptyCompleteStatement(exprs);
type.getStatements().add(statement);
// this.assistNodeParent = node;
this.parseBlockStatements(statement, type, position);
// } else if (node instanceof RutaExecuteExpression) {
// // empty keyword like completion.
// List exprs = new ArrayList();
// exprs.add(new SimpleReference(position, position, ""));
// RutaEmptyCompleteStatement statement = new
// RutaEmptyCompleteStatement(
// exprs);
// this.parseBlockStatements(statement, node, position);
}
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.dltk.codeassist.IAssistParser#parseBlockStatements(org.eclipse.dltk.ast.ASTNode,
* org.eclipse.dltk.ast.ASTNode, int)
*/
public void parseBlockStatements(ASTNode node, ASTNode inNode, int position) {
// if (node instanceof RutaStatement) {
// RutaStatement statement = (RutaStatement) node;
// List expressions = statement.getExpressions();
// int len = expressions.size();
// boolean first = false;
// String completionToken = null;
// ASTNode completionNode = null;
// for (int i = 0; i < len; ++i) {
// ASTNode n = (ASTNode) expressions.get(i);
// if (n.sourceStart() <= position && n.sourceEnd() >= position
// || (node instanceof RutaEmptyCompleteStatement)) {
// if (i == 0) {
// first = true;
// }
// completionNode = n;
// }
// }
// if (completionNode == null) {
// // TODO: Add inner completion here.
// if (len > 0) {
// // ASTNode firstNode = (ASTNode) expressions.get(0);
// // if (position > firstNode.sourceEnd()) {
// // // This could be variable completion.
// // boolean provideDollar =
// // !checkVariableWithoutDollarCompletion(
// // statement, position);
// // this.assistNodeParent = inNode;
// // SimpleReference ref = new SimpleReference(position,
// // position, "");
// // ASTNode nde = new CompletionOnVariable("", ref, node,
// // inNode, true, provideDollar);
// // throw new CompletionNodeFound(nde, null);
// // }
// String[] keywords = checkKeywords(completionToken, MODULE);
// ASTNode nde = new CompletionOnKeywordArgumentOrFunctionArgument("",
// (RutaStatement) node, keywords, position);
// this.assistNodeParent = inNode;
// throw new CompletionNodeFound(nde, null/* ((TypeDeclaration)inNode).scope */);
//
// } else {
// completionToken = "";
// }
// } else if (completionNode instanceof SimpleReference) {
// int maxLen = position - completionNode.sourceStart();
// completionToken = ((SimpleReference) completionNode).getName();
// // We need to cut some sumbols if node is begger then position.
// if (completionToken.length() > maxLen && maxLen > 0) {
// completionToken = completionToken.substring(0, maxLen);
// }
// } /*
// * else if (completionNode instanceof RutaBlockExpression) { RutaBlockExpression
// * block = (RutaBlockExpression) completionNode;
// *
// * List s = block.parseBlock(); if (s != null) { int slen = s.size(); for (int u = 0; u <
// * slen; ++u) { ASTNode n = (ASTNode) s.get(u); n.setStart(n.sourceStart() -
// * block.sourceStart()); n.setEnd(n.sourceEnd() - block.sourceStart());
// * RutaASTUtil.extendStatement(n, block.getBlock()); n.setStart(n.sourceStart() +
// * block.sourceStart()); n.setEnd(n.sourceEnd() + block.sourceStart()); if (n != null &&
// * n.sourceStart() <= position && n.sourceEnd() >= position) { parseBlockStatements(n,
// * inNode, position); } } } handleNotInElement(inNode, position); }
// */
// if (completionNode instanceof StringLiteral) {
// int maxLen = position - completionNode.sourceStart();
// int pos = maxLen;
// SimpleReference tok = RutaParseUtils.extractVariableFromString(
// (StringLiteral) completionNode, pos);
// if (tok != null) {
// this.assistNodeParent = inNode;
// ASTNode nde = new CompletionOnVariable(tok.getName(), tok, node, inNode, false);
// throw new CompletionNodeFound(nde, null);
// } else {
// this.assistNodeParent = inNode;
// SimpleReference ref = new SimpleReference(position, position, "");
// ASTNode nde = new CompletionOnVariable("", ref, node, inNode, true);
// throw new CompletionNodeFound(nde, null);
// }
// }
// // if (completionNode instanceof RutaExecuteExpression) {
// // RutaExecuteExpression expr = (RutaExecuteExpression)
// // completionNode;
// // List exprs = expr.parseExpression();
// // for (int i = 0; i < exprs.size(); ++i) {
// // ASTNode n = (ASTNode) exprs.get(i);
// // if (n.sourceStart() <= position
// // && n.sourceEnd() >= position) {
// // parseBlockStatements(n, expr, position);
// // }
// // }
// // handleNotInElement(expr, position);
// // }
// if (completionToken != null && completionToken.startsWith("$")) {
// // Argument name completion...
// this.assistNodeParent = inNode;
// ASTNode nde = new CompletionOnVariable(completionToken, completionNode, node, inNode, false);
// throw new CompletionNodeFound(nde, null);
// } else {
// // This is keyword or function completion.
// if (inNode instanceof ModuleDeclaration && completionNode != null && first) {
// String[] keywords = checkKeywords(completionToken, MODULE);
// ASTNode nde = new CompletionOnKeywordOrFunction(completionToken, completionNode, node,
// keywords);
// this.assistNodeParent = inNode;
// throw new CompletionNodeFound(nde, ((ModuleDeclaration) inNode).scope);
// } else if (inNode instanceof MethodDeclaration && completionNode != null && first) {
// String[] keywords = checkKeywords(completionToken, FUNCTION);
// ASTNode nde = new CompletionOnKeywordOrFunction(completionToken, completionNode, node,
// keywords);
// this.assistNodeParent = inNode;
// throw new CompletionNodeFound(nde, ((MethodDeclaration) inNode).scope);
// } else if (inNode instanceof TypeDeclaration && completionNode != null && first) {
// String[] keywords = checkKeywords(completionToken, NAMESPACE);
// ASTNode nde = new CompletionOnKeywordOrFunction(completionToken, completionNode, node,
// keywords);
// this.assistNodeParent = inNode;
// throw new CompletionNodeFound(nde, null/* ((TypeDeclaration)inNode).scope */);
// // } else if (inNode instanceof RutaExecuteExpression
// // && completionNode != null && first) {
// // String[] keywords = checkKeywords(completionToken,
// // EXEC_EXPRESSION);
// // ASTNode nde = new CompletionOnKeywordOrFunction(
// // completionToken, completionNode, node, keywords);
// // this.assistNodeParent = inNode;
// // throw new CompletionNodeFound(nde, null/*
// // ((TypeDeclaration)inNode).scope */);
// } else {
// if (completionNode != null) {
// String[] keywords = checkKeywords(completionToken, MODULE);
//
// ASTNode nde = new CompletionOnKeywordArgumentOrFunctionArgument(completionToken,
// completionNode, (RutaStatement) node, keywords);
// this.assistNodeParent = inNode;
// throw new CompletionNodeFound(nde, null/* ((TypeDeclaration)inNode).scope */);
// } else {
// String[] keywords = checkKeywords(completionToken, MODULE);
// if (completionToken == null) {
// completionToken = "";
// }
// ASTNode nde = new CompletionOnKeywordArgumentOrFunctionArgument(completionToken,
// (RutaStatement) node, keywords, position);
// this.assistNodeParent = inNode;
// throw new CompletionNodeFound(nde, null/* ((TypeDeclaration)inNode).scope */);
// }
// }
// }
// // if (checkVariableWithoutDollarCompletion(statement, position)
// // && completionToken != null) {
// // this.assistNodeParent = inNode;
// // SimpleReference ref = new SimpleReference(completionNode
// // .sourceStart(), completionNode.sourceEnd(),
// // completionToken);
// // ASTNode nde = new CompletionOnVariable(completionToken, ref,
// // node, inNode, true);
// // throw new CompletionNodeFound(nde, null);
// // }
//
// } else if (node instanceof MethodDeclaration) {
// MethodDeclaration method = (MethodDeclaration) node;
// List statements = method.getStatements();
// boolean inStatement = false;
// if (statements != null) {
// int length = statements.size();
// for (int i = 0; i < length; i++) {
// ASTNode nde = (ASTNode) statements.get(i);
// if (nde.sourceStart() <= position && nde.sourceEnd() >= position) {
// inStatement = true;
// parseBlockStatements(nde, method, position);
// }
// }
// }
// if (!inStatement) {
// this.handleNotInElement(method, position);
// }
// } else {
// visitElements(node, position);
// }
}
public class CompletionVisitor extends ASTVisitor {
protected int position;
protected ModuleDeclaration module;
public CompletionVisitor(int position, ModuleDeclaration module) {
this.position = position;
this.module = module;
}
@Override
public boolean visit(Statement s) throws Exception {
// if (s.sourceStart() <= position && s.sourceEnd() >= position) {
// for (int i = 0; i < extensions.length; i++) {
// extensions[i].visit(s, RutaCompletionParser.this,
// position);
// }
// if (s instanceof RutaStatement) {
// ASTNode inNode = RutaParseUtil.getScopeParent(module, s);
// RutaCompletionParser.this.parseBlockStatements(s, inNode,
// position);
// }
// if (s instanceof RutaPackageDeclaration) {
// RutaPackageDeclaration decl =
// (RutaPackageDeclaration) s;
// if (decl.getNameStart() <= position
// && position <= decl.getNameEnd()) {
// ASTNode inNode = RutaParseUtil.getScopeParent(module, s);
// assistNodeParent = inNode;
// throw new CompletionNodeFound(decl, null/*
// ((TypeDeclaration)inNode).scope */);
// }
// }
// }
return super.visit(s);
}
@Override
public boolean visit(Expression s) throws Exception {
if (s.sourceStart() <= position && s.sourceEnd() >= position) {
for (int i = 0; i < extensions.length; i++) {
extensions[i].visit(s, RutaCompletionParser.this, position);
}
}
return super.visit(s);
}
@Override
public boolean endvisit(Expression s) throws Exception {
if (s instanceof Block && s.sourceStart() <= position && s.sourceEnd() >= position) {
// We are in block, and no in node completion are done.
String[] keywords = checkKeywords("", MODULE);
ASTNode inNode = RutaParseUtils.getScopeParent(module, s);
ASTNode nde = new CompletionOnKeywordOrFunction("", inNode, s, keywords);
assistNodeParent = inNode;
throw new CompletionNodeFound(nde, null);
}
return super.endvisit(s);
}
};
protected CompletionVisitor createCompletionVisitor(int position) {
return new CompletionVisitor(position, this.getModule());
}
private void visitElements(ASTNode node, int position) {
if (!(node instanceof RutaStatement)) {
CompletionVisitor visitor = createCompletionVisitor(position);
try {
node.traverse(visitor);
} catch (CompletionNodeFound e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
}
}
private boolean checkVariableWithoutDollarCompletion(RutaStatement statement, int position) {
// TODO: Add more compecated check.
Expression e = statement.getAt(0);
if (e instanceof SimpleReference) {
SimpleReference ref = (SimpleReference) e;
String name = ref.getName();
if (name.equals("set")) {
return true;
}
}
return false;
}
public String[] checkKeywords(String completionToken, int type) {
// String[] keywords = RutaKeywordsManager.getKeywords(type);
// // TODO: Possible require cases.
// if (type == MODULE || type == FUNCTION || type == NAMESPACE
// || type == EXEC_EXPRESSION) {
// // Suppose we can handle all keywords.
// String[] kw = new String[keywords.length];
// for (int i = 0; i < keywords.length; ++i) {
// kw[i] = keywords[i];
// }
// return kw;
// }
return null;
}
public void setAssistNodeParent(ASTNode prevParent) {
this.assistNodeParent = prevParent;
}
public ModuleDeclaration parse(IModuleSource sourceModule) {
ModuleDeclaration module = (ModuleDeclaration) this.parser.parse(sourceModule, null);
module.rebuild();
return module;
}
}