/******************************************************************************* * Copyright (c) 2005, 2007 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.tcl.internal.core.codeassist; import java.util.List; import org.eclipse.dltk.ast.ASTNode; import org.eclipse.dltk.ast.ASTVisitor; import org.eclipse.dltk.ast.declarations.Declaration; 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.StringLiteral; import org.eclipse.dltk.ast.references.SimpleReference; import org.eclipse.dltk.ast.statements.Statement; import org.eclipse.dltk.internal.codeassist.select.SelectionNodeFound; import org.eclipse.dltk.tcl.ast.ITclStatementLookLike; import org.eclipse.dltk.tcl.ast.TclStatement; import org.eclipse.dltk.tcl.ast.expressions.TclBlockExpression; import org.eclipse.dltk.tcl.ast.expressions.TclExecuteExpression; import org.eclipse.dltk.tcl.core.TclParseUtil; import org.eclipse.dltk.tcl.internal.core.codeassist.selection.SelectionOnAST; import org.eclipse.dltk.tcl.internal.core.codeassist.selection.SelectionOnKeywordOrFunction; import org.eclipse.dltk.tcl.internal.core.codeassist.selection.SelectionOnNode; import org.eclipse.dltk.tcl.internal.core.codeassist.selection.SelectionOnVariable; import org.eclipse.dltk.tcl.internal.parser.OldTclParserUtils; public class TclSelectionParser extends TclAssistParser { public void handleNotInElement(ASTNode node, int position) { // System.out.println(node); if (node instanceof TypeDeclaration) { TypeDeclaration memberType = (TypeDeclaration) node; if (memberType.getNameStart() <= position && memberType.getNameEnd() >= position) { ASTNode nde = new SelectionOnAST(memberType); throw new SelectionNodeFound(nde); } } } public void parseBlockStatements(ASTNode node, ASTNode inNode, int position) { if (node instanceof TclStatement) { TclStatement statement = (TclStatement) node; List expressions = statement.getExpressions(); int len = expressions.size(); boolean first = false; ASTNode completionNode = null; String completionToken = null; for (int i = 0; i < len; ++i) { ASTNode n = (ASTNode) expressions.get(i); if (n.sourceStart() <= position && n.sourceEnd() >= position) { if (i == 0) { first = true; } completionNode = n; } } if (completionNode instanceof SimpleReference) { completionToken = ((SimpleReference) completionNode).getName(); if (completionToken.indexOf("[") != -1) { processInnerExecuteExpression(inNode, position, completionNode, completionToken); } } // Map Variable if (completionToken != null && completionToken.indexOf('(') != -1) { if (position < completionNode.sourceStart() + completionToken.indexOf('(')) { completionToken = completionToken.substring(0, completionToken.indexOf('(')); } else { completionToken = completionToken.substring(completionToken .indexOf('(') + 1, completionToken.length() - 1); } } if (completionNode instanceof TclBlockExpression) { TclBlockExpression block = (TclBlockExpression) completionNode; List s = block.parseBlockSimple(); if (s != null) { int slen = s.size(); for (int u = 0; u < slen; ++u) { ASTNode n = (ASTNode) s.get(u); if (n != null && n.sourceStart() <= position && n.sourceEnd() >= position) { parseBlockStatements(n, inNode, position); } } } handleNotInElement(inNode, position); } if (completionNode instanceof StringLiteral) { processStringLiteral(node, inNode, position, completionNode); } if (completionNode instanceof TclExecuteExpression) { TclExecuteExpression expr = (TclExecuteExpression) 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); } String var = OldTclParserUtils.returnVariableCheck(statement, position); if ((completionToken != null && completionToken.startsWith("$")) || var != null) { this.assistNodeParent = inNode; if (var != null) { // ASTNode nde = new SelectionOnVariable("$" + var, // statement, node, inNode); // throw new SelectionNodeFound(nde); ASTNode nde = new SelectionOnAST(statement); throw new SelectionNodeFound(nde); } else { // inNode = this.findInNode(module, completionNode); ASTNode nde = new SelectionOnVariable(completionToken, completionNode, node, inNode); throw new SelectionNodeFound(nde); } } else { if (completionToken != null && completionNode != null && first) { ASTNode nde = new SelectionOnKeywordOrFunction( completionToken, completionNode, node); this.assistNodeParent = inNode; throw new SelectionNodeFound(nde); } } if (completionNode != null) { this.visitElements(completionNode, position); } } else if (node instanceof MethodDeclaration) { MethodDeclaration method = (MethodDeclaration) node; List statements = method.getStatements(); boolean inStatement = false; if (method.getNameStart() <= position && method.getNameEnd() >= position) { ASTNode nde = new SelectionOnAST(method); this.assistNodeParent = inNode; throw new SelectionNodeFound(nde); } 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); } } // Handle other cases here // New Parser cases if (node.sourceStart() <= position && node.sourceEnd() >= position) { visitElements(node, position); if (node instanceof ITclStatementLookLike) { TclStatement statement = ((ITclStatementLookLike) node) .getStatement(); this.parseBlockStatements(statement, inNode, position); } SelectionOnNode nde = new SelectionOnNode(node); nde.setPosition(position); throw new SelectionNodeFound(nde); } } private void visitElements(ASTNode node, int position) { if (!(node instanceof TclStatement)) { SelectionVisitor visitor = createSelectionVisitor(position); try { node.traverse(visitor); } catch (SelectionNodeFound e) { throw e; } catch (Exception e) { e.printStackTrace(); } } } private SelectionVisitor createSelectionVisitor(int position) { return new SelectionVisitor(position, this.getModule()); } private void processStringLiteral(ASTNode node, ASTNode inNode, int position, ASTNode completionNode) { int pos = position - completionNode.sourceStart(); String content = ((StringLiteral) completionNode).getValue(); if (content.indexOf("[") != -1) { processInnerExecuteExpression(inNode, position, completionNode, content); } SimpleReference tok = OldTclParserUtils.findVariableFromString( (StringLiteral) completionNode, pos); if (tok != null) { this.assistNodeParent = inNode; ASTNode nde = new SelectionOnVariable(tok.getName(), tok, node, inNode); if (nde != null) { throw new SelectionNodeFound(nde); } } } private class SelectionVisitor extends ASTVisitor { private int position; ModuleDeclaration module; SelectionVisitor(int position, ModuleDeclaration module) { this.position = position; this.module = module; } public boolean visit(Statement s) throws Exception { if (s.sourceStart() <= position && s.sourceEnd() >= position) { if (s instanceof TclStatement) { ASTNode inNode = findInNode(this.module, s); TclSelectionParser.this.parseBlockStatements(s, inNode, position); } else if (s instanceof Declaration) { Declaration decl = (Declaration) s; if (decl.getNameStart() <= position && position <= decl.getNameEnd()) { SelectionOnAST nde = new SelectionOnAST(s); throw new SelectionNodeFound(nde); } } } return super.visit(s); } public boolean endvisit(Statement s) throws Exception { if (s.sourceStart() <= position && s.sourceEnd() >= position) { if (s instanceof ITclStatementLookLike) { TclStatement statement = ((ITclStatementLookLike) s) .getStatement(); ASTNode inNode = findInNode(this.module, s); TclSelectionParser.this.parseBlockStatements(statement, inNode, position); } } return super.endvisit(s); } public boolean visit(Expression s) throws Exception { if (s.sourceStart() <= position && s.sourceEnd() >= position) { if (s instanceof StringLiteral) { ASTNode inNode = findInNode(this.module, s); TclSelectionParser.this.processStringLiteral(s, inNode, position, s); } else if (s instanceof TclBlockExpression) { ASTNode inNode = findInNode(this.module, s); TclBlockExpression block = (TclBlockExpression) s; List ss = block.parseBlockSimple(); if (ss != null) { int slen = ss.size(); for (int u = 0; u < slen; ++u) { ASTNode n = (ASTNode) ss.get(u); if (n != null && n.sourceStart() <= position && n.sourceEnd() >= position) { parseBlockStatements(n, inNode, position); } } } handleNotInElement(inNode, position); } else if (s instanceof SimpleReference) { SimpleReference ref = (SimpleReference) s; if (ref.getName().startsWith("$")) { ASTNode inNode = findInNode(this.module, s); assistNodeParent = inNode; ASTNode nde = new SelectionOnVariable(ref.getName(), ref, ref, inNode); throw new SelectionNodeFound(nde); } else { SimpleReference var = OldTclParserUtils .extractVariableFromString(ref.sourceStart(), ref.sourceEnd(), position - ref.sourceStart(), ref .getName()); if (var != null) { ASTNode inNode = findInNode(this.module, s); assistNodeParent = inNode; ASTNode nde = new SelectionOnVariable( var.getName(), ref, ref, inNode); throw new SelectionNodeFound(nde); } } } } return super.visit(s); } }; private ASTNode findInNode(ModuleDeclaration module, ASTNode node) { return TclParseUtil.getScopeParent(module, node); } private void processInnerExecuteExpression(ASTNode inNode, int position, ASTNode completionNode, String completionToken) { String toks = null; int pos = position - completionNode.sourceStart(); int end = 0; for (end = pos; end < completionToken.length(); ++end) { char c = completionToken.charAt(end); if (c == '[') { break; } if (c == ']') { end = end + 1; break; } } int begin = 0; for (begin = pos - 1; begin > 0; --begin) { char c = completionToken.charAt(begin); if (c == ']') { break; } if (c == '[') { break; } } if (begin > 0 && begin < end && end <= completionToken.length()) { toks = completionToken.substring(begin, end); } else { return; } if (toks != null) { TclExecuteExpression ex = new TclExecuteExpression(completionNode .sourceStart() + begin, completionNode.sourceStart() + end, toks); List exprs = ex.parseExpression(); for (int i = 0; i < exprs.size(); ++i) { this.parseBlockStatements((ASTNode) exprs.get(i), inNode, position); } return; } } }