| package org.eclipse.dltk.tcl.internal.core.codeassist; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import org.eclipse.dltk.ast.ASTNode; |
| import org.eclipse.dltk.ast.ASTVisitor; |
| 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.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; |
| import org.eclipse.dltk.tcl.ast.TclStatement; |
| import org.eclipse.dltk.tcl.internal.parser.TclParseUtils; |
| |
| public class TclResolver { |
| private IResolveElementParent resolver; |
| private ModuleDeclaration moduleDeclaration; |
| private ISourceModule sourceModule; |
| |
| public TclResolver(ISourceModule sourceModule, |
| ModuleDeclaration moduleDeclaration, IResolveElementParent resolver) { |
| this(sourceModule, moduleDeclaration); |
| this.resolver = resolver; |
| } |
| |
| public TclResolver(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, |
| (IParent) 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 TclStatement) { TclStatement s = |
| * (TclStatement) 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 = ""; |
| String[] split = childName.split("::"); |
| if (split.length > 0) { |
| 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 TclStatement) { |
| String[] var = TclParseUtils.returnVariable((TclStatement) 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 = TclResolver.findTypeFrom(sourceModule |
| .getChildren(), "", pName, '$'); |
| if (element == null) { |
| return; |
| } |
| } catch (ModelException e) { |
| e.printStackTrace(); |
| return; |
| } |
| } |
| methodName = TclResolver.getNodeChildName(nde); |
| } else { |
| if (method.getDeclaringTypeName() != null) { |
| String pName = method.getDeclaringTypeName(); |
| if (!pName.startsWith("::")) { |
| pName = "$" + pName; |
| } |
| pName = pName.replaceAll("::", "\\$"); |
| if (pName.equals("$")) { |
| element = sourceModule; |
| } else { |
| try { |
| element = TclResolver.findTypeFrom(sourceModule |
| .getChildren(), "", pName, '$'); |
| if (element == null) { |
| return; |
| } |
| } catch (ModelException e) { |
| e.printStackTrace(); |
| return; |
| } |
| } |
| methodName = TclResolver.getNodeChildName(nde); |
| } |
| } |
| IModelElement e = TclResolver.findChildrenByName(methodName, |
| (IParent) 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() { |
| 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; |
| } |
| } |