/*******************************************************************************
* 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.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.ASTVisitor;
import org.eclipse.dltk.ast.Modifiers;
import org.eclipse.dltk.ast.declarations.Argument;
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.references.SimpleReference;
import org.eclipse.dltk.ast.statements.Statement;
import org.eclipse.dltk.codeassist.AssistParser;
import org.eclipse.dltk.codeassist.IAssistParser;
import org.eclipse.dltk.codeassist.ICompletionNameProvider;
import org.eclipse.dltk.codeassist.ScriptCompletionEngine;
import org.eclipse.dltk.codeassist.complete.CompletionNodeFound;
import org.eclipse.dltk.compiler.env.IModuleSource;
import org.eclipse.dltk.compiler.env.lookup.Scope;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.CompletionContext;
import org.eclipse.dltk.core.CompletionProposal;
import org.eclipse.dltk.core.CompletionRequestor;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.Flags;
import org.eclipse.dltk.core.IAccessRule;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IField;
import org.eclipse.dltk.core.IMethod;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.RuntimePerformanceMonitor;
import org.eclipse.dltk.core.RuntimePerformanceMonitor.PerformanceNode;
import org.eclipse.dltk.core.mixin.IMixinRequestor;
import org.eclipse.dltk.core.search.IDLTKSearchConstants;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.SearchEngine;
import org.eclipse.dltk.core.search.SearchMatch;
import org.eclipse.dltk.core.search.SearchParticipant;
import org.eclipse.dltk.core.search.SearchPattern;
import org.eclipse.dltk.core.search.SearchRequestor;
import org.eclipse.dltk.launching.IInterpreterInstall;
import org.eclipse.dltk.launching.ScriptRuntime;
import org.eclipse.dltk.tcl.ast.TclStatement;
import org.eclipse.dltk.tcl.core.TclNature;
import org.eclipse.dltk.tcl.core.TclPackagesManager;
import org.eclipse.dltk.tcl.core.TclParseUtil;
import org.eclipse.dltk.tcl.core.ast.TclPackageDeclaration;
import org.eclipse.dltk.tcl.core.extensions.ICompletionExtension;
import org.eclipse.dltk.tcl.core.packages.TclModuleInfo;
import org.eclipse.dltk.tcl.core.packages.TclPackageInfo;
import org.eclipse.dltk.tcl.core.packages.TclSourceEntry;
import org.eclipse.dltk.tcl.internal.core.TclExtensionManager;
import org.eclipse.dltk.tcl.internal.core.codeassist.completion.CompletionOnKeywordArgumentOrFunctionArgument;
import org.eclipse.dltk.tcl.internal.core.codeassist.completion.CompletionOnKeywordOrFunction;
import org.eclipse.dltk.tcl.internal.core.codeassist.completion.CompletionOnVariable;
import org.eclipse.dltk.tcl.internal.core.codeassist.completion.TclCompletionParser;
import org.eclipse.dltk.tcl.internal.core.packages.TclBuildPathPackageCollector;
import org.eclipse.dltk.tcl.internal.core.search.mixin.TclMixinModel;
import org.eclipse.dltk.tcl.internal.core.search.mixin.TclMixinUtils;
import org.eclipse.dltk.tcl.internal.core.search.mixin.model.TclNamespaceImport;
import org.eclipse.dltk.tcl.internal.core.search.mixin.model.TclProc;
import org.eclipse.dltk.tcl.internal.parser.OldTclParserUtils;
import org.eclipse.emf.common.util.EList;
public class TclCompletionEngine extends ScriptCompletionEngine {
protected AssistParser parser;
protected ISourceModule sourceModule;
protected final static boolean TRACE_COMPLETION_TIME = false;
private ICompletionExtension[] extensions;
private TclBuildPathPackageCollector packageCollector;
public TclCompletionEngine() {
this.extensions = TclExtensionManager.getDefault()
.getCompletionExtensions();
this.parser = new AssistParser(new TclCompletionParser(this.extensions));
}
public void complete(IModuleSource sourceModule, int completionPosition,
int pos) {
PerformanceNode p = RuntimePerformanceMonitor.begin();
this.sourceModule = (ISourceModule) sourceModule.getModelElement();
if (VERBOSE) {
System.out.print("COMPLETION IN "); //$NON-NLS-1$
System.out.print(sourceModule.getFileName());
System.out.print(" AT POSITION "); //$NON-NLS-1$
System.out.println(completionPosition);
System.out.println("COMPLETION - Source :"); //$NON-NLS-1$
System.out.println(sourceModule.getSourceContents());
}
this.requestor.beginReporting();
boolean contextAccepted = false;
try {
// this.fileName = sourceModule.getFileName();
this.actualCompletionPosition = completionPosition;
this.offset = pos;
ModuleDeclaration parsedUnit = this.parser.parse(sourceModule);
// Collect all packages information.
packageCollector = new TclBuildPathPackageCollector();
try {
parsedUnit.traverse(packageCollector);
} catch (Exception e1) {
if (DLTKCore.DEBUG) {
e1.printStackTrace();
}
}
if (parsedUnit != null) {
if (VERBOSE) {
System.out.println("COMPLETION - Diet AST :"); //$NON-NLS-1$
System.out.println(parsedUnit.toString());
}
try {
this.source = sourceModule.getContentsAsCharArray();
parser.parseBlockStatements(parsedUnit,
this.actualCompletionPosition);
if (VERBOSE) {
System.out.println("COMPLETION - AST :"); //$NON-NLS-1$
System.out.println(parsedUnit.toString());
}
} catch (CompletionNodeFound e) {
// completionNodeFound = true;
if (e.astNode != null) {
if (VERBOSE) {
System.out.print("COMPLETION - Completion node : "); //$NON-NLS-1$
System.out.println(e.astNode.toString());
if (this.parser.getAssistNodeParent() != null) {
System.out.print("COMPLETION - Parent Node : "); //$NON-NLS-1$
System.out.println(this.parser
.getAssistNodeParent());
}
}
// if null then we found a problem in the completion
// node
contextAccepted = this.complete(e.astNode, this.parser
.getAssistNodeParent(), e.scope,
e.insideTypeAnnotation);
}
}
}
if (this.noProposal && this.problem != null) {
if (!contextAccepted) {
contextAccepted = true;
CompletionContext context = new CompletionContext();
context.setOffset(completionPosition);
context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN);
this.requestor.acceptContext(context);
}
this.requestor.completionFailure(this.problem);
if (DEBUG) {
this.printDebug(this.problem);
}
}
} catch (OperationCanceledException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
} finally {
if (!contextAccepted) {
contextAccepted = true;
CompletionContext context = new CompletionContext();
context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN);
context.setOffset(completionPosition);
this.requestor.acceptContext(context);
}
this.requestor.endReporting();
p.done(TclNature.NATURE_ID, "Completion time", 0);
}
}
protected boolean complete(ASTNode astNode, ASTNode astNodeParent,
Scope scope, boolean insideTypeAnnotation) {
this.setSourceRange(astNode.sourceStart(), astNode.sourceEnd());
for (int i = 0; i < this.extensions.length; i++) {
this.extensions[i].setRequestor(this.getRequestor());
}
if (astNode instanceof CompletionOnKeywordOrFunction) {
CompletionOnKeywordOrFunction key = (CompletionOnKeywordOrFunction) astNode;
this.processCompletionOnKeywords(key, key.getName());
this.processCompletionOnFunctions(astNodeParent, key);
for (int i = 0; i < this.extensions.length; i++) {
this.extensions[i].completeOnKeywordOrFunction(key,
astNodeParent, this);
}
if (key.getToken().length == 0) {
this.findVariables(key.getToken(), key.getInParent(), true,
astNode.sourceStart(), key.canCompleteEmptyToken(),
null);
}
} else if (astNode instanceof CompletionOnVariable) {
this.processCompletionOnVariables(astNode);
for (int i = 0; i < this.extensions.length; i++) {
this.extensions[i].completeOnVariables(
(CompletionOnVariable) astNode, this);
}
} else if (astNode instanceof TclPackageDeclaration) {
TclPackageDeclaration pkg = (TclPackageDeclaration) astNode;
int len = this.actualCompletionPosition - pkg.getNameStart();
String token = "";
if (len <= pkg.getName().length()) {
token = pkg.getName().substring(0, len);
}
this.setSourceRange(pkg.getNameStart(), pkg.getNameEnd());
this.packageNamesCompletion(token.toCharArray(),
new HashSet<String>());
} else if (astNode instanceof CompletionOnKeywordArgumentOrFunctionArgument) {
CompletionOnKeywordArgumentOrFunctionArgument compl = (CompletionOnKeywordArgumentOrFunctionArgument) astNode;
TclStatement st = compl.getStatement();
Set<String> methodNames = new HashSet<String>();
if (st.getCount() >= 1) {
// Completion on two argument keywords
final Expression at = st.getAt(0);
if (at instanceof SimpleReference) {
final String name = ((SimpleReference) at).getName();
if (compl.sourceStart() < at.sourceEnd()
|| requestor.isContextInformationMode()) {
this.processCompletionOnFunctions(astNodeParent, name
.toCharArray(), false);
}
String token = null;
if (compl.argumentIndex() == 1) {
token = compl.getName();
} else if (st.getCount() > 1) {
final Expression at1 = st.getAt(1);
if (at1 instanceof SimpleReference) {
token = ((SimpleReference) at1).getName();
}
}
if (DEBUG) {
System.out.println("compl.argumentIndex="
+ compl.argumentIndex());
System.out.println("name='" + name + "'");
System.out.println("token='" + token);
}
if (token != null) {
this.processPartOfKeywords(st.sourceStart(), compl,
name + " " + token, methodNames);
for (int i = 0; i < this.extensions.length; i++) {
this.extensions[i].completeOnKeywordArgumentsOne(
name, token.toCharArray(), compl,
methodNames, st, this);
}
}
}
}
if (!requestor.isContextInformationMode()
&& (compl.argumentIndex() == 3 || (compl.argumentIndex() == -1 && st
.getCount() > 1))) {
Expression at0 = st.getAt(0);
Expression at1 = st.getAt(1);
if (at1 instanceof SimpleReference
&& at0 instanceof SimpleReference) {
String sat0 = ((SimpleReference) at0).getName();
String sat1 = ((SimpleReference) at1).getName();
if ("package".equals(sat0) && "require".equals(sat1)) {
this.packageNamesCompletion(compl.getToken(),
methodNames);
return true;
}
}
}
// Variables completion here.
// char[] varToken = new char[0];
boolean provideDollar = true;
if (compl.getToken().length > 0 && compl.getToken()[0] == '$') {
// varToken = compl.getToken();
provideDollar = true;
this.findVariables(compl.getToken(), astNodeParent, true,
astNode.sourceStart(), provideDollar, null);
}
}
return true;
}
private void packageNamesCompletion(char[] token, Set<String> methodNames) {
IScriptProject project = this.sourceModule.getScriptProject();
IInterpreterInstall install;
try {
install = ScriptRuntime.getInterpreterInstall(project);
if (install != null) {
List<TclPackageInfo> packageNames = TclPackagesManager
.getPackageInfos(install);
Set<String> added = new HashSet<String>();
List<String> k = new ArrayList<String>();
String prefix = new String(token);
for (Iterator<TclPackageInfo> iterator = packageNames
.iterator(); iterator.hasNext();) {
String kkw = iterator.next().getName();
if (kkw.indexOf('$') == -1) {
if (kkw.startsWith(prefix)) {
if (added.add(kkw)) {
k.add(kkw);
}
}
}
}
List<TclModuleInfo> packages = TclPackagesManager
.getProjectModules(project.getElementName());
if (packages != null) {
for (TclModuleInfo tclModuleInfo : packages) {
EList<TclSourceEntry> provided = tclModuleInfo
.getProvided();
for (TclSourceEntry userPkgs : provided) {
if (added.add(userPkgs.getValue())) {
k.add(userPkgs.getValue());
}
}
}
}
String kw[] = k.toArray(new String[k.size()]);
this.findKeywords(token, kw, true);
if (methodNames != null) {
methodNames.addAll(k);
}
}
} catch (CoreException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
protected void processPartOfKeywords(int sourceStart,
CompletionOnKeywordArgumentOrFunctionArgument compl, String prefix,
Set<String> methodNames) {
if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
List<String> k = processPartOfKeywords(compl.getPossibleKeywords(),
prefix, sourceStart);
if (methodNames != null) {
methodNames.addAll(k);
}
}
}
protected List<String> processPartOfKeywords(String[] keywords,
String prefix, int sourceStart) {
if (prefix != null && prefix.length() != 0 && prefix.charAt(0) == ':') {
String[] doubleColonPrependedKeywords = new String[keywords.length];
for (int i = 0; i < keywords.length; ++i) {
doubleColonPrependedKeywords[i] = "::" + keywords[i];
}
keywords = doubleColonPrependedKeywords;
}
List<String> k = new ArrayList<String>();
if (prefix == null) {
prefix = Util.EMPTY_STRING;
}
prefix = prefix.trim();
selectKeywords(keywords, prefix, k, requestor
.isContextInformationMode());
if (k.isEmpty() && requestor.isContextInformationMode()) {
final int p = prefix.indexOf(' ');
if (p > 0) {
selectKeywords(keywords, prefix.substring(0, p), k, requestor
.isContextInformationMode());
}
}
if (requestor.isContextInformationMode()
|| !(k.size() == 1 && prefix.equals(k.get(0)))) {
// do not report single exact match in completion mode.
reportKeywords(prefix, k, sourceStart);
}
return k;
}
private void reportKeywords(String prefix, List<String> keywords,
int sourceStart) {
final char[] keyword = prefix.toCharArray();
for (final String kw : keywords) {
final String choice = kw;
int relevance = computeBaseRelevance();
relevance += computeRelevanceForInterestingProposal();
relevance += computeRelevanceForCaseMatching(keyword, choice);
relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no
this.noProposal = false;
if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
CompletionProposal proposal = this.createProposal(
CompletionProposal.KEYWORD,
this.actualCompletionPosition);
proposal.setName(choice);
proposal.setCompletion(choice);
proposal.setReplaceRange(sourceStart - this.offset,
this.endPosition - this.offset);
proposal.setRelevance(relevance);
proposal.setExtraInfo(prefix);
this.requestor.accept(proposal);
if (DEBUG) {
this.printDebug(proposal);
}
}
}
}
private void selectKeywords(String[] possibleKeywords, String prefix,
List<String> selection, boolean preferExactMatch) {
if (preferExactMatch) {
for (int i = 0; i < possibleKeywords.length; i++) {
final String kkw = possibleKeywords[i];
if (kkw.equals(prefix)) {
selection.add(kkw);
return;
}
}
}
for (int i = 0; i < possibleKeywords.length; i++) {
final String kkw = possibleKeywords[i];
if (kkw.startsWith(prefix)) {
selection.add(kkw);
}
}
}
protected void processCompletionOnVariables(ASTNode astNode) {
if (!this.requestor.isIgnored(CompletionProposal.LOCAL_VARIABLE_REF)
&& !this.requestor
.isIgnored(CompletionProposal.VARIABLE_DECLARATION)) {
CompletionOnVariable completion = (CompletionOnVariable) astNode;
this.findVariables(completion.getToken(), completion.getInNode(),
completion.canHandleEmpty(), astNode.sourceStart(),
completion.getProvideDollar(), null);
}
}
protected void processCompletionOnFunctions(ASTNode astNodeParent,
CompletionOnKeywordOrFunction key) {
processCompletionOnFunctions(astNodeParent,
removeLastColonFromToken(key.getToken()), key
.canCompleteEmptyToken());
}
protected void processCompletionOnFunctions(ASTNode astNodeParent,
char[] token, boolean canCompleteEmptyToken) {
if (!this.requestor.isIgnored(CompletionProposal.METHOD_REF)) {
List methodNames = new ArrayList();
Set set = new HashSet();
this.findLocalFunctions(token, canCompleteEmptyToken,
astNodeParent, methodNames, set);
set.addAll(methodNames);
this.findNamespaceFunctions(token, set);
if (astNodeParent instanceof TypeDeclaration) {
if ((((TypeDeclaration) astNodeParent).getModifiers() & Modifiers.AccNameSpace) != 0) {
String namespace = TclParseUtil.getElementFQN(
astNodeParent,
IMixinRequestor.MIXIN_NAME_SEPARATOR, this.parser
.getModule());
this.findSpecificNamespaceFunctions(token, set, namespace,
false);
}
}
// Check and process imported namespaces
processImports(token, set, astNodeParent);
}
}
private void processImports(char[] token, Set set, ASTNode astNodeParent) {
String currentNamespace = TclParseUtil.getElementFQN(astNodeParent,
"::", getAssistParser().getModule());
if (token == null) {
return;
}
String t = new String(token);
if (t.startsWith("::")) {
t = t.substring(2);
}
if (t.startsWith(":")) {
t = t.substring(1);
}
Set processed = new HashSet();
if (t.length() > 0) {
processFindNamespace(token, set, currentNamespace, processed);
// Also empty namespace should be processed
if (!currentNamespace.equals("")) {
processFindNamespace(token, set, "", processed);
}
}
}
private void processFindNamespace(char[] token, Set set,
String currentNamespace, Set processed) {
String pattern = "@" + currentNamespace + "|*";
String[] findKeys = TclMixinModel.getInstance().getMixin(
getSourceModule().getScriptProject()).findKeys(pattern);
Set keys = new HashSet();
for (int i = 0; i < findKeys.length; i++) {
if (keys.add(findKeys[i])) {
TclNamespaceImport importSt = TclNamespaceImport
.parseKey(findKeys[i]);
if (importSt != null
&& importSt.getNamespace().equals(currentNamespace)) {
if (processed.add(importSt.getImportNsName())) {
this.findSpecificNamespaceFunctions(token, set,
importSt.getImportNsName(), true);
}
}
}
}
// IMixinElement[] find = TclMixinModel.getInstance().getMixin(
// getSourceModule().getScriptProject()).find(pattern, 0);
// for (int i = 0; i < find.length; i++) {
// Object[] allObjects = find[i].getAllObjects();
// for (int j = 0; j < allObjects.length; j++) {
// if (allObjects[j] instanceof TclNamespaceImport) {
// TclNamespaceImport importSt = (TclNamespaceImport) allObjects[j];
// if (importSt.getNamespace().equals(currentNamespace)) {
// if (processed.add(importSt.getImportNsName())) {
// this.findSpecificNamespaceFunctions(token, set,
// importSt.getImportNsName(), true);
// }
// }
// }
// }
// }
}
protected void processCompletionOnKeywords(
CompletionOnKeywordOrFunction key, String token) {
if (!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
processPartOfKeywords(key.getPossibleKeywords(), token,
this.startPosition);
}
}
/**
* Removes ':' on the end.
*
* @param token
* @return
*/
public char[] removeLastColonFromToken(char[] token) {
if (token.length > 2 && token[token.length - 1] == ':'
&& token[token.length - 2] != ':') {
char co2[] = new char[token.length - 1];
System.arraycopy(token, 0, co2, 0, co2.length);
return co2;
}
return token;
}
protected void findNamespaceFunctions(final char[] token,
final Set methodNames) {
final Set methods = new HashSet();
String to_ = new String(token);
String to = to_;
if (to.startsWith("::")) {
to = to.substring(2);
}
if (to.length() == 0) {
return;
}
methods.addAll(methodNames);
this.findMethodFromMixin(methods, to + "*");
methods.removeAll(methodNames);
// Remove all with same names
this.removeSameFrom(methodNames, methods, to_);
this.filterInternalAPI(methods, this.parser.getModule());
// findTypes(token, true, toList(types));
this.findMethods(token, false, this.toList(methods));
}
protected void findSpecificNamespaceFunctions(final char[] token,
final Set methodNames, String namespace, boolean asImport) {
if (namespace.endsWith(IMixinRequestor.MIXIN_NAME_SEPARATOR)) {
namespace = namespace.substring(0, namespace.length() - 1);
}
Set methods = new HashSet();
String to_ = new String(token);
String to = to_;
if (to.startsWith("::")) {
to = to.substring(2);
}
methods.addAll(methodNames);
this.findMethodFromMixin(methods, namespace
+ IMixinRequestor.MIXIN_NAME_SEPARATOR + to + "*");
methods.removeAll(methodNames);
// Remove all with same names
// removeSameFrom(methodNames, methods, to_);
// filterAllPrivate(methodNames, methods, this.parser.getModule());
// findTypes(token, true, toList(types));
if (asImport) {
filterInternalAPI(methods, getAssistParser().getModule());
methods = filterSubNamespaces(methods, namespace);
}
List list = this.toList(methods);
List mNames = this.removeNamespace(list, namespace, asImport);
this.findMethods(token, true, list, mNames);
}
private Set filterSubNamespaces(Set methods, String namespace) {
Set results = new HashSet();
if (!namespace.startsWith("::")) {
namespace = "::" + namespace;
}
if (!namespace.endsWith("::")) {
namespace = namespace + "::";
}
for (Iterator iterator = methods.iterator(); iterator.hasNext();) {
IModelElement element = (IMethod) iterator.next();
String fqn = TclParseUtil.getFQNFromModelElement(element, "::");
if (fqn.startsWith(namespace)) {
String substring = fqn.substring(namespace.length());
if (substring.indexOf("::") == -1) {
results.add(element);
}
} else {
results.add(element);
}
}
return results;
}
private List removeNamespace(List methods, String namespace,
boolean asImport) {
List names = new ArrayList();
if (!namespace.startsWith("::")) {
namespace = "::" + namespace;
}
if (!namespace.endsWith("::")) {
namespace = namespace + "::";
}
for (Iterator iterator = methods.iterator(); iterator.hasNext();) {
IModelElement element = (IModelElement) iterator.next();
String fqn = TclParseUtil.getFQNFromModelElement(element, "::");
if (fqn.startsWith(namespace)) {
String substring = fqn.substring(namespace.length());
names.add(substring);
} else {
names.add(fqn);
}
}
return names;
}
/**
* Filters all private methods not in current module namespaces.
*
* @param methodNames
* @param methods
*/
private void filterInternalAPI(Set methods, final ModuleDeclaration module) {
if (!this.getRequestor().isIgnored(
ITclCompletionProposalTypes.FILTER_INTERNAL_API)) {
return;
}
final Set namespaceNames = new HashSet();
try {
module.traverse(new ASTVisitor() {
public boolean visit(TypeDeclaration s) throws Exception {
String ns = TclParseUtil.getElementFQN(s, "::", module);
if (!ns.startsWith("::")) {
ns = "::" + ns;
}
namespaceNames.add(ns);
// Also add all subnamespaces
String ns2 = ns;
while (true) {
ns2 = TclCompletionEngine.this.getElementNamespace(ns2);
if (ns2 == null || (ns2 != null && ns2.equals("::"))) {
break;
}
namespaceNames.add(ns2);
}
return super.visit(s);
}
});
} catch (Exception e1) {
if (DLTKCore.DEBUG) {
e1.printStackTrace();
}
}
Set privateSet = new HashSet();
for (Iterator iterator = methods.iterator(); iterator.hasNext();) {
Object method = iterator.next();
if (method instanceof IMethod) {
IMethod m = (IMethod) method;
try {
boolean nsHere = false;
String elemName = TclParseUtil.getFQNFromModelElement(m,
"::");
String elemNSName = this.getElementNamespace(elemName);
if (elemNSName != null) {
nsHere = namespaceNames.contains(elemNSName);
}
if (!nsHere && !Flags.isPublic(m.getFlags())) {
privateSet.add(method);
}
} catch (ModelException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
}
for (Iterator iterator = privateSet.iterator(); iterator.hasNext();) {
Object object = iterator.next();
methods.remove(object);
}
}
private String getElementNamespace(String elemName) {
int pos = elemName.lastIndexOf("::");
if (pos != -1) {
String rs = elemName.substring(0, pos);
if (rs.length() == 0) {
return null;
}
return rs;
}
return null;
}
protected void findMethods(char[] token, boolean canCompleteEmptyToken,
List methods) {
this.findMethods(token, canCompleteEmptyToken, methods,
CompletionProposal.METHOD_REF);
}
public void removeSameFrom(final Set methodNames, final Set elements,
String to_) {
final Set namesToRemove = new HashSet();
for (Iterator iterator = methodNames.iterator(); iterator.hasNext();) {
Object name = iterator.next();
if (name instanceof String) {
namesToRemove.add(name);
}
}
if (!namesToRemove.isEmpty()) {
// We need to remove all elements with namesToRemove from methods.
for (Iterator me = elements.iterator(); me.hasNext();) {
Object m = me.next();
if (m instanceof IMethod) {
String qname = this.processMethodName((IMethod) m, to_);
if (namesToRemove.contains(qname)) {
me.remove();
}
} else if (m instanceof IType) {
String qname = this.processTypeName((IType) m, to_);
if (namesToRemove.contains(qname)) {
me.remove();
}
}
}
}
elements.removeAll(methodNames);
}
public void findMixinTclElement(final Set completions, String tok,
Class mixinClass) {
String pattern = tok.replaceAll("::",
IMixinRequestor.MIXIN_NAME_SEPARATOR);
IModelElement[] elements = TclMixinUtils.findModelElementsFromMixin(
pattern, mixinClass, this.scriptProject, getProgressMonitor());
elements = TclResolver.complexFilter(elements, this.scriptProject,
this.packageCollector, false);
final Set completionNames = calculateCompletionNames(completions);
for (int i = 0; i < elements.length; i++) {
// We should filter external source modules with same
// external path.
final IModelElement element = elements[i];
if (this.moduleFilter(completions, element, completionNames)) {
completions.add(element);
}
}
}
public void findMixinTclElementNoFilter(final Set completions, String tok,
Class mixinClass) {
String pattern = tok.replaceAll("::",
IMixinRequestor.MIXIN_NAME_SEPARATOR);
IModelElement[] elements = TclMixinUtils.findModelElementsFromMixin(
pattern, mixinClass, this.scriptProject, getProgressMonitor());
// long start = System.currentTimeMillis();
for (int i = 0; i < elements.length; i++) {
// We should filter external source modules with same
// external path.
// if (moduleFilter(completions, elements[i])) {
completions.add(elements[i]);
// }
// if (System.currentTimeMillis() - start > 1000) {
// return;
// }
}
}
protected void findMethodFromMixin(final Set methods, String tok) {
this.findMixinTclElement(methods, tok, TclProc.class);
}
protected boolean moduleFilter(Set completions, IModelElement modelElement,
Set completionNames) {
for (int i = 0; i < this.extensions.length; i++) {
if (!this.extensions[i].modelFilter(completions, modelElement)) {
return false;
}
}
return completionNames.add(getFQNFromModelElement(modelElement));
}
private Set calculateCompletionNames(Set completions) {
final Set result = new HashSet();
for (Iterator iterator = completions.iterator(); iterator.hasNext();) {
Object o = iterator.next();
if (!(o instanceof IModelElement)) {
if (o instanceof String) {
result.add(o);
}
continue;
}
final IModelElement element = (IModelElement) o;
result.add(getFQNFromModelElement(element));
}
return result;
}
private static final String getFQNFromModelElement(IModelElement element) {
return TclParseUtil.getFQNFromModelElement(element, "::");
}
public <T> List<T> toList(Set<T> types) {
return new ArrayList<T>(types);
}
protected void search(String patternString, int searchFor, int limitTo,
IDLTKSearchScope scope, SearchRequestor resultCollector)
throws CoreException {
this.search(patternString, searchFor, limitTo, EXACT_RULE, scope,
resultCollector);
}
protected void search(String patternString, int searchFor, int limitTo,
int matchRule, IDLTKSearchScope scope, SearchRequestor requestor)
throws CoreException {
if (patternString.indexOf('*') != -1
|| patternString.indexOf('?') != -1) {
matchRule |= SearchPattern.R_PATTERN_MATCH;
}
SearchPattern pattern = SearchPattern.createPattern(patternString,
searchFor, limitTo, matchRule, scope.getLanguageToolkit());
new SearchEngine().search(pattern,
new SearchParticipant[] { SearchEngine
.getDefaultSearchParticipant() }, scope, requestor,
null);
}
protected void findLocalFunctions(char[] token,
boolean canCompleteEmptyToken, ASTNode astNodeParent,
List methodNames, Set set) {
token = this.removeLastColonFromToken(token);
List methods = new ArrayList();
this.fillFunctionsByLevels(token, astNodeParent, methods, methodNames);
List nodeMethods = new ArrayList();
List nodeMethodNames = new ArrayList();
List otherMethods = new ArrayList();
List otherMethodNames = new ArrayList();
TclResolver resolver = new TclResolver(this.sourceModule, this.parser
.getModule());
if (methods.size() > 0) {
for (int i = 0; i < methods.size(); i++) {
MethodDeclaration method = (MethodDeclaration) methods.get(i);
IModelElement modelElement = resolver
.findModelElementFrom(method);
if (modelElement != null) {
nodeMethods.add(modelElement);
set.add(modelElement);
nodeMethodNames.add(methodNames.get(i));
} else {
otherMethods.add(method);
otherMethodNames.add(methodNames.get(i));
}
// TclParseUtil.fi
}
this.findMethods(token, canCompleteEmptyToken, nodeMethods,
nodeMethodNames);
this.findLocalMethods(token, canCompleteEmptyToken, otherMethods,
otherMethodNames);
}
}
private void fillFunctionsByLevels(char[] token, ASTNode parent,
List methods, List gmethodNames) {
List levels = TclParseUtil
.findLevelsTo(this.parser.getModule(), parent);
int len = levels.size();
List visited = new ArrayList();
List methodNames = new ArrayList();
// visited.addAll(levels);
for (int j = 0; j < len; ++j) {
ASTNode astNodeParent = (ASTNode) levels.get(len - 1 - j);
boolean topLevel = false;
if (token != null && token.length > 0 && token[0] == ':') {
topLevel = true;
}
if (astNodeParent instanceof TypeDeclaration && !topLevel) {
// Add all method here.
TypeDeclaration decl = (TypeDeclaration) astNodeParent;
List statements = decl.getStatements();
if (statements != null) {
this.processMethods(methods, methodNames, statements, "",
visited, parent);
}
} else if (astNodeParent instanceof ModuleDeclaration) {
ModuleDeclaration decl = (ModuleDeclaration) astNodeParent;
List statements = decl.getStatements();
if (statements != null) {
this.processMethods(methods, methodNames, statements,
topLevel ? "::" : "", visited, parent);
}
}
}
gmethodNames.addAll(methodNames);
}
private void processMethods(List methods, List methodNames,
List statements, String namePrefix, List visited, ASTNode realParent) {
for (int i = 0; i < statements.size(); ++i) {
ASTNode nde = (ASTNode) statements.get(i);
if (nde instanceof MethodDeclaration) {
if (!this.isTclMethod((MethodDeclaration) nde)) {
continue;
}
String mName = ((MethodDeclaration) nde).getName();
if (!mName.startsWith("::")) {
mName = namePrefix + mName;
}
if (realParent instanceof MethodDeclaration) {
String name = ((MethodDeclaration) realParent).getName();
String prefix = namePrefix
+ ((MethodDeclaration) nde).getName();
if (name.startsWith("::") && !prefix.startsWith("::")) {
prefix = "::" + prefix;
}
if (!name.equals(prefix)) {
int i1 = name.lastIndexOf("::");
int i2 = prefix.lastIndexOf("::");
if (i1 != -1 && i2 != -1) {
String p1 = name.substring(0, i1);
String p2 = prefix.substring(0, i2);
if (p1.startsWith(p2)) {
// System.out.println("#");
String nn = prefix.substring(i2 + 2);
if (!methodNames.contains(nn)) {
/* && !methods.contains(nde) */
if (this.methodCanBeAdded(nde, realParent,
mName)) {
methods.add(nde);
methodNames.add(nn);
}
}
}
}
}
}
if (!methodNames.contains(mName) /* && !methods.contains(nde) */) {
if (this.methodCanBeAdded(nde, realParent, mName)) {
methods.add(nde);
methodNames.add(mName);
}
}
} else if (nde instanceof TypeDeclaration && !visited.contains(nde)) {
List tStatements = ((TypeDeclaration) nde).getStatements();
visited.add(nde);
if (realParent instanceof MethodDeclaration) {
String name = ((MethodDeclaration) realParent).getName();
String prefix = namePrefix
+ ((TypeDeclaration) nde).getName();
if (name.startsWith("::") && !prefix.startsWith("::")) {
prefix = "::" + prefix;
}
if (name.startsWith(namePrefix)) {
this.processMethods2(methods, methodNames, tStatements,
"", realParent);
}
}
String nn = ((TypeDeclaration) nde).getName();
final String nextPrefix;
if (nn.startsWith("::")) {
nextPrefix = nn;
} else {
nextPrefix = namePrefix + nn;
}
this.processMethods(methods, methodNames, tStatements,
nextPrefix + "::", visited, realParent);
}
visited.add(nde);
}
}
private boolean isTclMethod(MethodDeclaration nde) {
int modifiers = nde.getModifiers();
if (modifiers < (2 << Modifiers.USER_MODIFIER)) {
return true;
}
return false;
}
private boolean isTclType(TypeDeclaration nde) {
int modifiers = nde.getModifiers();
if (modifiers < (2 << Modifiers.USER_MODIFIER)) {
return true;
}
return false;
}
private boolean isTclField(FieldDeclaration nde) {
int modifiers = nde.getModifiers();
if (modifiers < (2 << Modifiers.USER_MODIFIER)) {
return true;
}
return false;
}
protected boolean methodCanBeAdded(ASTNode nde, ASTNode realParent,
String mName) {
// Methods should have same prefix, to be added here.
String realParentFQN = TclParseUtil.getElementFQN(TclParseUtil
.getPrevParent(parser.getModule(), realParent), "::", parser
.getModule());
String ndeFQN = TclParseUtil.getElementFQN(TclParseUtil.getPrevParent(
parser.getModule(), nde), "::", parser.getModule());
if (mName.startsWith("::")) {
mName = mName.substring(2);
}
if (ndeFQN.length() > 0 && mName.startsWith(ndeFQN)) {
return true;
}
if (ndeFQN.equals(realParentFQN)) {
return true;
}
return false;
}
private void processMethods2(List methods, List methodNames,
List statements, String namePrefix, ASTNode realParent) {
for (int i = 0; i < statements.size(); ++i) {
ASTNode nde = (ASTNode) statements.get(i);
if (nde instanceof MethodDeclaration) {
String mName = namePrefix + ((MethodDeclaration) nde).getName();
if (mName.startsWith("::::")) {
mName = mName.substring(2);
}
if (isTclMethod((MethodDeclaration) nde)) {
if (!methodNames.contains(mName) && !methods.contains(nde)) {
if (this.methodCanBeAdded(nde, realParent, mName)) {
methods.add(nde);
methodNames.add(mName);
}
}
}
} else if (nde instanceof TypeDeclaration) {
List tStatements = ((TypeDeclaration) nde).getStatements();
this.processMethods2(methods, methodNames, tStatements,
namePrefix + ((TypeDeclaration) nde).getName() + "::",
realParent);
}
}
}
protected void findVariables(char[] token, ASTNode parent,
boolean canCompleteEmptyToken, int beforePosition,
boolean provideDollar, List cho) {
List gChoices = new ArrayList();
if (cho != null) {
gChoices.addAll(cho);
}
if (token.length > 0 && token[0] != '$') {
provideDollar = false;
}
token = this.removeLastColonFromToken(token);
if (parent instanceof MethodDeclaration) {
MethodDeclaration method = (MethodDeclaration) parent;
List choices = new ArrayList();
List statements = method.getArguments();
if (statements != null) {
for (int i = 0; i < statements.size(); ++i) {
Argument a = (Argument) statements.get(i);
if (a != null) {
String n = a.getName();
this.checkAddVariable(choices, n);
}
}
}
// Process variable setters.
statements = method.getStatements();
this.checkVariableStatements(beforePosition, choices, statements);
String[] cc = new String[choices.size()];
for (int i = 0; i < choices.size(); ++i) {
cc[i] = (String) choices.get(i);
gChoices.add(choices.get(i));
}
this.findLocalVariables(token, cc, canCompleteEmptyToken,
provideDollar);
} else if (parent instanceof ModuleDeclaration) {
ModuleDeclaration module = (ModuleDeclaration) parent;
this.checkVariables(token, canCompleteEmptyToken, beforePosition,
module.getStatements(), provideDollar, gChoices);
} else if (parent instanceof TypeDeclaration) {
TypeDeclaration type = (TypeDeclaration) parent;
this.checkVariables(token, canCompleteEmptyToken, beforePosition,
type.getStatements(), provideDollar, gChoices);
String prefix = "";
if (provideDollar) {
prefix = "$" + prefix;
}
List statements = type.getStatements();
for (int l = 0; l < statements.size(); ++l) {
this.findASTVariables((ASTNode) statements.get(l), prefix,
token, canCompleteEmptyToken, gChoices);
}
}
String prefix = "";
List choices = new ArrayList();
if ((token.length > 0 && (token[0] == ':' || token[0] == '$'))
|| token.length == 0 || (token.length > 2 && token[1] == ':')) {
prefix = "::";
if (provideDollar) {
prefix = "$" + prefix;
}
this.findASTVariables(this.parser.getModule(), prefix, token,
canCompleteEmptyToken, choices);
}
// remove dublicates
for (int i = 0; i < gChoices.size(); ++i) {
String c = (String) gChoices.get(i);
if (choices.contains(c)) {
choices.remove(c);
}
if (c.startsWith("$")) {
String cc = c.substring(1);
if (choices.contains(cc)) {
choices.remove(cc);
}
}
}
String[] cc = new String[choices.size()];
for (int i = 0; i < choices.size(); ++i) {
cc[i] = (String) choices.get(i);
gChoices.add(choices.get(i));
}
this.findLocalVariables(token, cc, canCompleteEmptyToken, true);
this.findGlobalVariables(token, gChoices, provideDollar);
// Find one level up
if (!(this.checkValidParetNode(parent))) {
// Lets find scope parent
List findLevelsTo = TclParseUtil.findLevelsTo(this.parser
.getModule(), parent);
ASTNode realParent = null;
for (Iterator iterator = findLevelsTo.iterator(); iterator
.hasNext();) {
ASTNode nde = (ASTNode) iterator.next();
if (this.checkValidParetNode(nde)) {
realParent = nde;
}
}
if (realParent != null && !realParent.equals(parent)) {
this.findVariables(token, realParent, canCompleteEmptyToken,
beforePosition, provideDollar, gChoices);
}
}
}
private boolean checkValidParetNode(ASTNode parent) {
return parent instanceof MethodDeclaration
|| parent instanceof ModuleDeclaration
|| parent instanceof TypeDeclaration;
}
private void findGlobalVariables(char[] token, final List choices,
final boolean provideDollar) {
final List fields = new ArrayList();
final List types = new ArrayList();
boolean provideDots = false;
SearchRequestor requestor = new SearchRequestor() {
public void acceptSearchMatch(SearchMatch match)
throws CoreException {
Object element = match.getElement();
if (element instanceof IType) {
IType type = (IType) element;
if ((type.getFlags() & Modifiers.AccNameSpace) == 0) {
return;
}
if (!(type.getParent() instanceof ISourceModule)) {
return;
}
String tName = type.getTypeQualifiedName();
if (!choices.contains(tName)) {
types.add(type);
}
// if( token.length > 3 ) {
this.processTypeFields(choices, fields, type);
// }
} else if (element instanceof IField) {
IField field = (IField) element;
if (!(field.getParent() instanceof ISourceModule)) {
return;
}
String mn = field.getTypeQualifiedName("$", false)
.replaceAll("\\$", "::");
if (!mn.startsWith("::")) {
mn = "::" + mn;
}
if (provideDollar) {
mn = "$" + mn;
}
if (!choices.contains(mn)
&& !choices.contains(mn.substring(2))) {
fields.add(field);
choices.add(mn);
}
}
}
private void processTypeFields(final List methodNames,
final List methods, IType type) throws ModelException {
IField[] tmethods = type.getFields();
for (int i = 0; i < tmethods.length; ++i) {
String mn = tmethods[i].getTypeQualifiedName("$", false)
.replaceAll("\\$", "::");
if (!mn.startsWith("::")) {
mn = "::" + mn;
}
if (!methodNames.contains(mn)) {
methods.add(tmethods[i]);
methodNames.add(mn);
}
}
IType[] types = type.getTypes();
for (int i = 0; i < types.length; ++i) {
this.processTypeFields(methodNames, methods, types[i]);
}
}
};
IDLTKLanguageToolkit toolkit = null;
toolkit = DLTKLanguageManager.getLanguageToolkit(this.scriptProject);
IDLTKSearchScope scope = SearchEngine.createWorkspaceScope(toolkit);
if (token.length >= 1 && token[0] == '$') {
char[] token2 = new char[token.length - 1];
for (int i = 0; i < token.length - 1; ++i) {
token2[i] = token[i + 1];
}
token = token2;
}
final String to = new String(token);
if (token != null && token.length >= 3 && token[0] == ':') {
// && token[1] == ':'
provideDots = true;
String[] tokens = TclParseUtil.tclSplit(to);
if (tokens.length < 2) {
return;
}
final String tok = tokens[1];
try {
this.search(tok + "*", IDLTKSearchConstants.TYPE,
IDLTKSearchConstants.DECLARATIONS, scope, requestor);
int nonNoneCount = 0;
String mtok = null;
for (int i = 0; i < tokens.length; ++i) {
if (tokens[i].length() > 0) {
nonNoneCount++;
if (mtok == null) {
mtok = tokens[i];
}
}
}
if (nonNoneCount == 1 && tok.length() >= 2) {
this
.search(mtok + "*", IDLTKSearchConstants.FIELD,
IDLTKSearchConstants.DECLARATIONS, scope,
requestor);
}
} catch (CoreException e) {
e.printStackTrace();
}
if (DLTKCore.VERBOSE_COMPLETION) {
System.out.println("Completion methods cound:" + fields.size());
}
} else if (token != null && token.length >= 1 && token[0] != ':') {
try {
String[] tokens = TclParseUtil.tclSplit(to);
if (tokens.length == 0) {
return;
}
String tok = tokens[0];
this.search(tok + "*", IDLTKSearchConstants.TYPE,
IDLTKSearchConstants.DECLARATIONS, scope, requestor);
int nonNoneCount = 0;
for (int i = 0; i < tokens.length; ++i) {
if (tokens[i].length() > 0) {
nonNoneCount++;
}
}
if (nonNoneCount == 1 && tok.length() >= 2) {
this
.search(tok + "*", IDLTKSearchConstants.FIELD,
IDLTKSearchConstants.DECLARATIONS, scope,
requestor);
}
} catch (CoreException e) {
e.printStackTrace();
}
if (DLTKCore.VERBOSE_COMPLETION) {
System.out.println("Completion methods cound:" + fields.size());
}
}
// this.findTypes(token, true, types);
this.findFields(token, false, fields, new FieldNameProvider(to,
provideDollar ? "$" : ""));
}
protected void findASTVariables(ASTNode node, String prefix, char[] token,
boolean canCompleteEmptyToken, List choices) {
List statements = null;
String add = "";
if (node instanceof ModuleDeclaration) {
statements = ((ModuleDeclaration) node).getStatements();
} else if (node instanceof TypeDeclaration) {
if (!isTclType((TypeDeclaration) node)) {
return;
}
statements = ((TypeDeclaration) node).getStatements();
String nme = ((TypeDeclaration) node).getName();
if (nme.startsWith("::")) {
add = nme.substring(2) + "::";
} else {
add = nme + "::";
}
}
if (statements != null) {
for (int i = 0; i < statements.size(); ++i) {
ASTNode nde = (ASTNode) statements.get(i);
if (nde instanceof TclStatement) {
String[] variable = OldTclParserUtils
.returnVariable((TclStatement) nde);
if (variable != null) {
for (int u = 0; u < variable.length; ++u) {
String prev = this.preProcessVariable(variable[u])
.substring(1);
String var = prefix + add;
if (var.endsWith("::") && prev.startsWith("::")) {
var = var + prev.substring(2);
} else {
var = var + prev;
}
if (!choices.contains(var)) {
choices.add(var);
}
}
continue;
}
} else if (nde instanceof FieldDeclaration) {
FieldDeclaration field = (FieldDeclaration) nde;
if (this.isTclField(field)) {
this.checkAddVariable(choices, prefix + add
+ field.getName());
}
continue;
}
this.findASTVariables(nde, prefix + add, token,
canCompleteEmptyToken, choices);
}
}
}
private void checkVariables(char[] token, boolean canCompleteEmptyToken,
int beforePosition, List statements, boolean provideDollar,
List gChoices) {
List choices = new ArrayList();
// Process variable setters.
this.checkVariableStatements(beforePosition, choices, statements);
String[] cc = new String[choices.size()];
for (int i = 0; i < choices.size(); ++i) {
cc[i] = (String) choices.get(i);
gChoices.add(choices.get(i));
}
this
.findLocalVariables(token, cc, canCompleteEmptyToken,
provideDollar);
}
protected void checkVariableStatements(int beforePosition,
final List choices, List statements) {
if (statements != null) {
for (int i = 0; i < statements.size(); ++i) {
ASTNode node = (ASTNode) statements.get(i);
if (node instanceof FieldDeclaration) {
FieldDeclaration decl = (FieldDeclaration) node;
if (this.isTclField(decl)) {
this.checkAddVariable(choices, decl.getName());
}
} else if (node instanceof TclStatement
&& node.sourceEnd() < beforePosition) {
TclStatement s = (TclStatement) node;
this.checkTclStatementForVariables(choices, s);
} else {
ASTVisitor visitor = new ASTVisitor() {
public boolean visit(Statement s) throws Exception {
if (s instanceof FieldDeclaration) {
String name = TclParseUtil.getElementFQN(s,
"::", TclCompletionEngine.this.parser
.getModule());
ASTNode pp = TclParseUtil.getScopeParent(parser
.getModule(), s);
boolean isTcl = true;
if (pp instanceof TypeDeclaration) {
isTcl = isTclType((TypeDeclaration) pp);
}
if (pp instanceof MethodDeclaration) {
isTcl = isTclMethod((MethodDeclaration) pp);
}
if (isTcl
&& TclCompletionEngine.this
.isTclField((FieldDeclaration) s)) {
TclCompletionEngine.this.checkAddVariable(
choices, name);
// ((FieldDeclaration)s).getName()
}
} else if (s instanceof TclStatement) {
TclCompletionEngine.this
.checkTclStatementForVariables(choices,
(TclStatement) s);
}
return super.visit(s);
}
};
try {
node.traverse(visitor);
} catch (Exception e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
}
}
}
}
private void checkTclStatementForVariables(final List choices,
TclStatement s) {
String[] variable = OldTclParserUtils.returnVariable(s);
if (variable != null) {
for (int u = 0; u < variable.length; ++u) {
this.checkAddVariable(choices, variable[u]);
}
}
}
protected void checkAddVariable(List choices, String n) {
String str = this.preProcessVariable(n);
if (!choices.contains(str)) {
choices.add(str);
}
}
private String preProcessVariable(String n) {
String str;
if (n.startsWith("$")) {
return n;
}
if (n.indexOf(' ') != -1) {
str = "$" + '{' + n + '}';
} else {
str = "$" + n;
}
return str;
}
public IAssistParser getAssistParser() {
return this.parser;
}
// TODO: Remove this. Actually all are done in extending of tcl statements
// in TclCompletionParser.
protected int getEndOfEmptyToken() {
// TODO: Add more complicated code here...
return this.actualCompletionPosition;
}
protected String processMethodName(IMethod method, String tok) {
return OldTclParserUtils.processMethodName(method, tok);
}
public static final ICompletionNameProvider<IField> FIELD_NAME_PROVIDER = new ICompletionNameProvider<IField>() {
public String getCompletion(IField t) {
// TODO Auto-generated method stub
return null;
}
public String getName(IField t) {
return t.getElementName();
}
};
// protected String processFieldName(IField method, String tok) {
// return OldTclParserUtils.processFieldName(method, tok);
// }
protected String processTypeName(IType method, String tok) {
String name = OldTclParserUtils.processTypeName(method, tok);
if (name.startsWith("::")
&& ((tok.length() > 1 && tok.charAt(0) != ':' && tok.charAt(1) != ':') || tok
.length() == 0)) {
name = name.substring(2);
}
return name;
}
public CompletionRequestor getRequestor() {
return this.requestor;
}
public ISourceModule getSourceModule() {
return this.sourceModule;
}
public int getActualCompletionPosition() {
return this.actualCompletionPosition;
}
}