blob: 33b88eb4ccc6c866c6e4e1dfeca9b366612b80fb [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.Iterator;
import java.util.List;
import org.apache.uima.ruta.ide.core.parser.RutaParseUtils;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.ASTVisitor;
import org.eclipse.dltk.ast.Modifiers;
import org.eclipse.dltk.ast.declarations.FieldDeclaration;
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.statements.Block;
import org.eclipse.dltk.ast.statements.Statement;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IField;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IParent;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ModelException;
public class RutaResolver {
private IResolveElementParent resolver;
private ModuleDeclaration moduleDeclaration;
private ISourceModule sourceModule;
public RutaResolver(ISourceModule sourceModule, ModuleDeclaration moduleDeclaration,
IResolveElementParent resolver) {
this(sourceModule, moduleDeclaration);
this.resolver = resolver;
}
public RutaResolver(ISourceModule sourceModule, ModuleDeclaration moduleDeclaration) {
this.sourceModule = sourceModule;
this.moduleDeclaration = moduleDeclaration;
}
public IModelElement findModelElementFrom(ASTNode node) {
List statements = moduleDeclaration.getStatements();
List elements = new ArrayList();
searchAddElementsTo(statements, node, sourceModule, elements);
if (elements.size() == 1) {
return (IModelElement) elements.get(0);
}
return null;
}
public interface IResolveElementParent {
IModelElement findElementParent(ASTNode node, String name, IParent parent);
}
public void searchAddElementsTo(List statements, final ASTNode node, IParent element,
List selectionElements) {
if (statements == null || element == null) {
return;
}
Iterator i = statements.iterator();
while (i.hasNext()) {
ASTNode nde = (ASTNode) i.next();
if (nde.equals(node)) {
if (node instanceof MethodDeclaration) {
String oName = ((MethodDeclaration) node).getName();
if (oName.indexOf("::") != -1) {
String pName = oName.substring(0, oName.lastIndexOf("::"));
pName = pName.replaceAll("::", "\\$");
if (pName.startsWith("$")) {
if (pName.equals("$")) {
element = sourceModule;
} else {
try {
element = findTypeFrom(sourceModule.getChildren(), "", pName, '$');
} catch (ModelException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
} else {
pName = "$" + pName;
try {
element = findTypeFrom(element.getChildren(), "", pName, '$');
if (element == null) {
return;
}
} catch (ModelException e) {
e.printStackTrace();
return;
}
}
}
}
String nodeName = getNodeChildName(node);
if (nodeName != null) {
IModelElement e = null;
if (nodeName.startsWith("::")) {
nodeName = nodeName.substring(2);
e = findChildrenByName(nodeName, sourceModule);
} else {
e = findChildrenByName(nodeName, element);
}
if (e == null && resolver != null) {
e = resolver.findElementParent(node, nodeName, element);
}
if (e != null) {
List toRemove = new ArrayList();
for (int k = 0; k < selectionElements.size(); ++k) {
IModelElement ke = (IModelElement) selectionElements.get(k);
String keName = ke.getElementName();
if (keName.equals(nodeName)) {
toRemove.add(ke);
}
}
for (int k = 0; k < toRemove.size(); ++k) {
selectionElements.remove(toRemove.get(k));
}
selectionElements.add(e);
}
}
return;
}
if (nde.sourceStart() <= node.sourceStart() && node.sourceEnd() <= nde.sourceEnd()) {
if (element instanceof IParent) {
if (nde instanceof TypeDeclaration) {
TypeDeclaration type = (TypeDeclaration) nde;
String typeName = getNodeChildName(type);
IModelElement e = findChildrenByName(typeName, element);
if (e == null && type.getName().startsWith("::")) {
try {
e = (IModelElement) findTypeFrom(sourceModule.getChildren(), "", type.getName()
.replaceAll("::", "\\$"), '$');
} catch (ModelException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
if (e instanceof IParent) {
// was: if (e != null || e instanceof IParent)
List stats = ((TypeDeclaration) nde).getStatements();
searchAddElementsTo(stats, node, (IParent) e, selectionElements);
}
} else if (nde instanceof MethodDeclaration) {
searchInMethod(node, element, nde, selectionElements);
} /*
* else if (nde instanceof RutaStatement) { RutaStatement s = (RutaStatement) nde;
* Expression commandId = s.getAt(0); final IParent e = element; if (commandId != null
* && commandId instanceof SimpleReference) { String qname = ((SimpleReference)
* commandId) .getName(); } }
*/
else {
final IParent e = element;
List statements2 = findExtractBlocks(nde);
if (statements2.size() > 0) {
searchAddElementsTo(statements2, node, e, selectionElements);
}
}
}
return;
}
}
}
public static IModelElement findChildrenByName(String childName, IParent element) {
try {
if (element == null) {
return null;
}
String nextName = null;
int pos;
if ((pos = childName.indexOf("::")) != -1) {
nextName = childName.substring(pos + 2);
childName = childName.split("::")[0];
}
IModelElement[] children = element.getChildren();
if (children != null) {
for (int i = 0; i < children.length; ++i) {
String name = children[i].getElementName();
if (children[i] instanceof IField && name.indexOf('(') != -1) {
name = name.substring(0, name.indexOf('('));
}
if (name.equals(childName)) {
if (nextName == null) {
return children[i];
} else if (children[i] instanceof IParent) {
return findChildrenByName(nextName, (IParent) children[i]);
}
}
}
}
} catch (ModelException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
return null;
}
public static IParent findTypeFrom(IModelElement[] childs, String name, String parentName,
char delimiter) {
try {
for (int i = 0; i < childs.length; ++i) {
if (childs[i] instanceof IType) {
if ((((IType) childs[i]).getFlags() & Modifiers.AccNameSpace) == 0) {
continue;
}
IType type = (IType) childs[i];
String qname = name + delimiter + type.getElementName();
if (qname.equals(parentName)) {
return type;
}
IParent val = findTypeFrom(type.getChildren(), qname, parentName, delimiter);
if (val != null) {
return val;
}
}
}
} catch (ModelException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
return null;
}
public static String getNodeChildName(ASTNode node) {
if (node instanceof MethodDeclaration) {
MethodDeclaration method = (MethodDeclaration) node;
String name = method.getName();
if (name.indexOf("::") != -1) {
return name.substring(name.lastIndexOf("::") + 2);
}
return name;
} else if (node instanceof TypeDeclaration) {
TypeDeclaration type = (TypeDeclaration) node;
String name = type.getName();
/*
* if (name.startsWith("::")) { return name.substring(2); }
*/
return name;
} else if (node instanceof Statement) {
String[] var = RutaParseUtils.returnVariable((Statement) node);
if (var != null) {
return var[0];
}
} else if (node instanceof FieldDeclaration) {
return ((FieldDeclaration) node).getName();
}
return null;
}
public void searchInMethod(final ASTNode node, IParent element, ASTNode nde,
List selectionElements) {
MethodDeclaration method = (MethodDeclaration) nde;
String methodName = method.getName();
if (methodName.indexOf("::") != -1) {
String pName = methodName.substring(0, methodName.lastIndexOf("::"));
pName = pName.replaceAll("::", "\\$");
if (pName.equals("$")) {
element = sourceModule;
} else {
try {
element = RutaResolver.findTypeFrom(sourceModule.getChildren(), "", pName, '$');
if (element == null) {
return;
}
} catch (ModelException e) {
e.printStackTrace();
return;
}
}
methodName = RutaResolver.getNodeChildName(nde);
}
IModelElement e = RutaResolver.findChildrenByName(methodName, element);
if (e != null && e instanceof IParent) {
List stats = ((MethodDeclaration) nde).getStatements();
searchAddElementsTo(stats, node, (IParent) e, selectionElements);
}
}
public static List findExtractBlocks(ASTNode node) {
final List statements2 = new ArrayList();
ASTVisitor visitor = new ASTVisitor() {
@Override
public boolean visit(Expression s) throws Exception {
if (s instanceof Block) {
statements2.addAll(((Block) s).getStatements());
}
return super.visit(s);
}
};
try {
node.traverse(visitor);
} catch (Exception e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
return statements2;
}
}