}
if (actTok.length() == 0) {
//No activation token means the module itself.
return new Definition[] { new Definition(1, 1, "", null, null, this) };
}
//the line passed in starts at 1 and the lines for the visitor start at 0
ArrayList<Definition> toRet = new ArrayList<Definition>();
//first thing is finding its scope
FindScopeVisitor scopeVisitor = getScopeVisitor(line, col);
//this visitor checks for assigns for the token
FindDefinitionModelVisitor visitor = getFindDefinitionsScopeVisitor(actTok, line, col);
List<Definition> defs = visitor.definitions;
int size = defs.size();
if (size > 0) {
//ok, it is an assign, so, let's get it
for (int i = 0; i < size; i++) {
Object next = defs.get(i);
if (next instanceof AssignDefinition) {
AssignDefinition element = (AssignDefinition) next;
if (element.target.startsWith("self") == false) {
if (element.scope.isOuterOrSameScope(scopeVisitor.scope) || element.foundAsGlobal) {
toRet.add(element);
}
} else {
toRet.add(element);
}
} else {
toRet.add((Definition) next);
}
}
if (toRet.size() > 0) {
return (Definition[]) toRet.toArray(new Definition[0]);
}
}
//now, check for locals
IToken[] localTokens = scopeVisitor.scope.getAllLocalTokens();
int len = localTokens.length;
for (int i = 0; i < len; i++) {
IToken tok = localTokens[i];
final String tokenRep = tok.getRepresentation();
if (tokenRep.equals(actTok)) {
return new Definition[] { new Definition(tok, scopeVisitor.scope, this, true) };
} else if (actTok.startsWith(tokenRep + ".") && !actTok.startsWith("self.")) {
final int tokenRepLen = tokenRep.length();
//this means we have a declaration in the local scope and we're accessing a part of it
//e.g.:
//class B:
// def met2(self):
// c = C()
// c.met1
state.checkFindLocalDefinedDefinitionMemory(this, tokenRep);
ICompletionState copyWithActTok = state.getCopyWithActTok(tokenRep);
Definition[] definitions = this.findDefinition(copyWithActTok, tok.getLineDefinition(),
tok.getColDefinition(), nature, innerFindPaths);
ArrayList<Definition> ret = new ArrayList<Definition>();
for (Definition definition : definitions) {
if (definition.module != null) {
if (definition.value.length() == 0) {
continue;
}
String checkFor = definition.value + actTok.substring(tokenRepLen);
if (this.equals(definition.module)) {
//no point in finding the starting point
if (actTok.equals(definition.value)) {
continue;
}
if (checkFor.equals(actTok)) {
continue;
}
if (checkFor.startsWith(actTok + '.')) {
//This means that to find some symbol we have a construct such as:
//a = a.strip().rjust()
//So, if we look for a.strip, and we resolve a as a.strip.rjust, we'll try to find:
//a.strip.rjust.strip, in which case we'd recurse.
continue;
}
}
//Note: I couldn't really reproduce this case, so, this fix is just a theoretical
//workaround. Hopefully sometime someone will provide some code to reproduce this.
//see: http://sourceforge.net/tracker/?func=detail&aid=2992629&group_id=85796&atid=577329
int dotsFound = StringUtils.count(checkFor, '.');
if (dotsFound > 15) {
throw new CompletionRecursionException("Trying to go to deep to find definition.\n"
+ "We probably started entering a recursion.\n" + "Module: "
+ definition.module.getName() + "\n" + "Token: " + checkFor);
}
Definition[] realDefinitions;
if (definition.module instanceof SourceModule) {
SourceModule sourceModule = (SourceModule) definition.module;
realDefinitions = (Definition[]) sourceModule.findDefinition(
state.getCopyWithActTok(checkFor), definition.line, definition.col, nature,
innerFindPaths);
} else {
realDefinitions = (Definition[]) definition.module.findDefinition(
state.getCopyWithActTok(checkFor), definition.line, definition.col, nature);
}
for (Definition realDefinition : realDefinitions) {
ret.add(realDefinition);
}
}
}
return ret.toArray(new Definition[ret.size()]);
}
}
//not found... check as local imports
List<IToken> localImportedModules = scopeVisitor.scope.getLocalImportedModules(line, col, this.name);
ICodeCompletionASTManager astManager = nature.getAstManager();
int lenImportedModules = localImportedModules.size();
for (int i = 0; i < lenImportedModules; i++) {
IToken tok = localImportedModules.get(i);
String importRep = tok.getRepresentation();
if (importRep.equals(actTok) || actTok.startsWith(importRep + ".")) {
Tuple3<IModule, String, IToken> o = astManager.findOnImportedMods(new IToken[] { tok },
state.getCopyWithActTok(actTok), this.getName(), this);
if (o != null && o.o1 instanceof SourceModule) {
ICompletionState copy = state.getCopy();
copy.setActivationToken(o.o2);
findDefinitionsFromModAndTok(nature, toRet, null, (SourceModule) o.o1, copy);
}
if (toRet.size() > 0) {
return (Definition[]) toRet.toArray(new Definition[0]);
}
}
}
//ok, not assign nor import, let's check if it is some self (we do not check for only 'self' because that would map to a
//local (which has already been covered).
if (actTok.startsWith("self.")) {
//ok, it is some self, now, that is only valid if we are in some class definition
ClassDef classDef = (ClassDef) scopeVisitor.scope.getClassDef();
if (classDef != null) {
//ok, we are in a class, so, let's get the self completions
String classRep = NodeUtils.getRepresentationString(classDef);
IToken[] globalTokens = getGlobalTokens(new CompletionState(line - 1, col - 1, classRep, nature, "",
state), //use the old state as the cache
astManager);
String withoutSelf = actTok.substring(5);
for (IToken token : globalTokens) {
if (token.getRepresentation().equals(withoutSelf)) {
String parentPackage = token.getParentPackage();
IModule module = astManager.getModule(parentPackage, nature, true);
if (token instanceof SourceToken
&& (module != null || this.name == null || this.name.equals(parentPackage))) {
if (module == null) {
module = this;
}
SimpleNode ast2 = ((SourceToken) token).getAst();
Tuple<Integer, Integer> def = getLineColForDefinition(ast2);
FastStack<SimpleNode> stack = new FastStack<SimpleNode>(5);
if (module instanceof SourceModule) {
stack.push(((SourceModule) module).getAst());
}
stack.push(classDef);
ILocalScope scope = new LocalScope(stack);
return new Definition[] { new Definition(def.o1, def.o2, token.getRepresentation(), ast2,
scope, module) };
} else {
return new Definition[0];
}
}
}
}
}
//ok, it is not an assign, so, let's search the global tokens (and imports)
String tok = actTok;
SourceModule mod = this;
Tuple3<IModule, String, IToken> o = astManager.findOnImportedMods(state.getCopyWithActTok(actTok), this);
if (o != null) {
if (o.o1 instanceof SourceModule) {
mod = (SourceModule) o.o1;
tok = o.o2;
} else if (o.o1 instanceof CompiledModule) {
//ok, we have to check the compiled module
tok = o.o2;
if (tok == null || tok.length() == 0) {
return new Definition[] { new Definition(1, 1, "", null, null, o.o1) };
} else {
state.checkFindDefinitionMemory(o.o1, tok);
return (Definition[]) o.o1.findDefinition(state.getCopyWithActTok(tok), -1, -1, nature);
}