use of org.python.pydev.ast.codecompletion.revisited.visitors.FindDefinitionModelVisitor in project Pydev by fabioz.
the class SourceModule method findDefinition.
/**
* @param line: starts at 1
* @param col: starts at 1
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private Definition[] findDefinition(ICompletionState state, int line, int col, final IPythonNature nature, Set innerFindPaths) throws Exception {
state.checkMaxTimeForCompletion();
if (onFindDefinition != null) {
onFindDefinition.call(state);
}
final String actTok = state.getActivationToken();
Object key = new Tuple3("findDefinition", this.getName(), actTok);
if (!innerFindPaths.add(key)) {
// So, we can't go on this way as it'd recurse!
return new Definition[0];
}
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);
Object objClassDef = scopeVisitor.scope.getClassDef();
if (objClassDef instanceof ClassDef) {
ClassDef classDef = (ClassDef) objClassDef;
if (actTok.equals("super")) {
if (classDef.bases != null) {
List<Definition> lst = new ArrayList<>(classDef.bases.length);
for (exprType expr : classDef.bases) {
String repr = NodeUtils.getRepresentationString(expr);
if (repr != null) {
state = state.getCopyWithActTok(repr);
Definition[] defs = findDefinition(state, line, col, nature);
if (defs != null && defs.length > 0) {
lst.addAll(Arrays.asList(defs));
}
}
}
if (lst.size() > 0) {
return lst.toArray(new Definition[lst.size()]);
}
}
// Didn't find anything for super
return new Definition[0];
} else if (actTok.startsWith("super()")) {
if (classDef.bases != null) {
List<Definition> lst = new ArrayList<>(classDef.bases.length);
for (exprType expr : classDef.bases) {
String repr = NodeUtils.getRepresentationString(expr);
if (repr != null) {
state = state.getCopyWithActTok(actTok.replace("super()", repr));
Definition[] defs = findDefinition(state, line, col, nature);
if (defs != null && defs.length > 0) {
lst.addAll(Arrays.asList(defs));
}
}
}
if (lst.size() > 0) {
return lst.toArray(new Definition[lst.size()]);
}
}
// Just keep going (may get completions globally).
}
}
// this visitor checks for assigns for the token
FindDefinitionModelVisitor visitor = getFindDefinitionsScopeVisitor(actTok, line, col, nature);
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 toRet.toArray(new Definition[0]);
}
}
// now, check for locals
TokensList localTokens = scopeVisitor.scope.getAllLocalTokens();
int len = localTokens.size();
for (IterTokenEntry entry : localTokens) {
IToken tok = entry.getToken();
final String tokenRep = tok.getRepresentation();
if (tokenRep.equals(actTok)) {
if (tok instanceof SourceToken && ((SourceToken) tok).getAst() instanceof Assign) {
Assign node = (Assign) ((SourceToken) tok).getAst();
String target = tok.getRepresentation();
return new Definition[] { FindDefinitionModelVisitor.getAssignDefinition(node, target, 0, line, col, scopeVisitor.scope, this, -1) };
}
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 + '.')) {
// 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 = 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);
}
}
}
if (ret.size() == 0) {
// Well, it seems it's a parameter, so, let's check if we can get the parameter definition to then resolve
// the token.
ILocalScope scope = scopeVisitor.scope;
List<ITypeInfo> possibleClassesForActivationToken = scope.getPossibleClassesForActivationToken(tokenRep);
// Above we have: actTok.startsWith(tokenRep + ".")
// and we just resolved tokenRep, so, let's check the remainder given type hints.
String remainder = actTok.substring(tokenRepLen + 1);
if (possibleClassesForActivationToken.size() > 0) {
for (ITypeInfo possibleClass : possibleClassesForActivationToken) {
AbstractASTManager astManager = (AbstractASTManager) nature.getAstManager();
if (astManager != null) {
TokensList completionsFromTypeRepresentation = astManager.getCompletionsFromTypeRepresentation(state, Arrays.asList(possibleClass), this);
for (IterTokenEntry entry1 : completionsFromTypeRepresentation) {
IToken iToken = entry1.getToken();
if (remainder.equals(iToken.getRepresentation())) {
String parentPackage = iToken.getParentPackage();
IModule module;
if (this.getName().equals(parentPackage)) {
module = this;
} else {
module = astManager.getModule(parentPackage, nature, true, state);
}
if (module != null) {
ret.add(new Definition(iToken, null, module));
}
}
}
}
}
}
}
return ret.toArray(new Definition[ret.size()]);
}
}
// not found... check as local imports
TokensList localImportedModules = scopeVisitor.scope.getLocalImportedModules(line, col, this.name);
ICodeCompletionASTManager astManager = nature.getAstManager();
for (IterTokenEntry entry : localImportedModules) {
IToken tok = entry.getToken();
String importRep = tok.getRepresentation();
if (importRep.equals(actTok) || actTok.startsWith(importRep + ".")) {
Tuple3<IModule, String, IToken> o = astManager.findOnImportedMods(new TokensList(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 toRet.toArray(new Definition[0]);
}
}
}
// 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);
if (classRep != null) {
TokensList globalTokens = getGlobalTokens(new CompletionState(line - 1, col - 1, classRep, nature, "", // use the old state as the cache
state), astManager);
String withoutSelf = actTok.substring(5);
for (IterTokenEntry entry : globalTokens) {
IToken token = entry.getToken();
if (token.getRepresentation().equals(withoutSelf)) {
String parentPackage = token.getParentPackage();
IModule module = astManager.getModule(parentPackage, nature, true, state);
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(astManager.getNature(), 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);
}
} else if (o.o1 instanceof IAbstractJavaClassModule) {
tok = o.o2;
state.checkFindDefinitionMemory(o.o1, tok);
return (Definition[]) o.o1.findDefinition(state.getCopyWithActTok(tok), -1, -1, nature);
} else {
throw new RuntimeException("Unexpected module found in imports: " + o);
}
}
// mod == this if we are now checking the globals (or maybe not)...heheheh
ICompletionState copy = state.getCopyWithActTok(tok, line - 1, col - 1);
// further on this we will get the first part of the same tok, so token line and column will be the same
try {
state.checkFindDefinitionMemory(mod, tok);
findDefinitionsFromModAndTok(nature, toRet, visitor.moduleImported, mod, copy);
} catch (CompletionRecursionException e) {
// ignore (will return what we've got so far)
// e.printStackTrace();
}
return toRet.toArray(new Definition[0]);
}
use of org.python.pydev.ast.codecompletion.revisited.visitors.FindDefinitionModelVisitor in project Pydev by fabioz.
the class SourceModule method internalCalculateGlobalTokens.
public TokensList internalCalculateGlobalTokens(ICompletionState initialState, ICodeCompletionASTManager manager) {
String activationToken = initialState.getActivationToken();
final int activationTokenLen = activationToken.length();
final List<String> actToks = StringUtils.dotSplit(activationToken);
final int actToksLen = actToks.size();
String goFor = null;
if (actToksLen > 0) {
goFor = actToks.get(0);
}
IToken[] t = getTokens(GlobalModelVisitor.GLOBAL_TOKENS, null, goFor);
LookingFor lookingFor = null;
for (int i = 0; i < t.length; i++) {
SourceToken token = (SourceToken) t[i];
String rep = token.getRepresentation();
SimpleNode ast = token.getAst();
if (activationTokenLen > rep.length() && activationToken.startsWith(rep)) {
// we need this thing to work correctly for nested modules...
// some tests are available at: PythonCompletionTestWithoutBuiltins.testDeepNestedXXX
int iActTok = 0;
if (actToks.get(iActTok).equals(rep)) {
// System.out.println("Now we have to find act..."+activationToken+"(which is a definition of:"+rep+")");
try {
Definition[] definitions;
String value = activationToken;
String initialValue = null;
while (true) {
if (value.equals(initialValue)) {
break;
}
initialValue = value;
if (iActTok > actToksLen) {
// unable to find it
break;
}
// If we have C1.f.x
// At this point we'll find the C1 definition...
definitions = findDefinition(initialState.getCopyWithActTok(value), token.getLineDefinition(), token.getColDefinition() + 1, manager.getNature());
if (definitions.length == 1) {
Definition d = definitions[0];
if (d instanceof TypeInfoDefinition) {
TypeInfoDefinition typeInfoDefinition = (TypeInfoDefinition) d;
List<ITypeInfo> lookForClass = new ArrayList<>();
TypeInfo info = typeInfoDefinition.info;
lookForClass.add(info);
TokensList completionsForClassInLocalScope = manager.getCompletionsForClassInLocalScope(d.module, initialState.getCopyWithActTok(info.getActTok()), true, false, lookForClass);
completionsForClassInLocalScope.setLookingFor(LookingFor.LOOKING_FOR_INSTANCED_VARIABLE);
return completionsForClassInLocalScope;
}
if (d.ast instanceof Assign) {
Assign assign = (Assign) d.ast;
if (assign.targets.length == 1 && assign.targets[0] instanceof Name) {
ClassDef classDef = (ClassDef) d.scope.getClassDef();
if (NodeUtils.isEnum(classDef)) {
return new TokensList(new IToken[] { new ConcreteToken("name", "Enum name", "", "enum", ConcreteToken.TYPE_ATTR, manager.getNature()), new ConcreteToken("value", "Enum value", "", "enum", ConcreteToken.TYPE_ATTR, manager.getNature()) });
}
}
if (assign.value instanceof Call) {
lookingFor = LookingFor.LOOKING_FOR_INSTANCED_VARIABLE;
}
if (assign.type != null) {
value = NodeUtils.getRepresentationString(assign.type);
lookingFor = LookingFor.LOOKING_FOR_INSTANCED_VARIABLE;
} else if (assign.value != null) {
value = NodeUtils.getRepresentationString(assign.value);
}
if (value == null) {
break;
}
definitions = findDefinition(initialState.getCopyWithActTok(value), d.line, d.col, manager.getNature());
} else if (d.ast instanceof ClassDef) {
TokensList toks = ((SourceModule) d.module).getClassToks(initialState, manager, (ClassDef) d.ast);
if (lookingFor != null) {
toks.setLookingFor(lookingFor);
}
if (iActTok == actToksLen - 1) {
return toks;
}
value = d.value;
} else if (d.ast instanceof Name) {
ClassDef classDef = (ClassDef) d.scope.getClassDef();
if (classDef != null) {
if (NodeUtils.isEnum(classDef)) {
return new TokensList(new IToken[] { new ConcreteToken("name", "Enum name", "", "enum", ConcreteToken.TYPE_ATTR, manager.getNature()), new ConcreteToken("value", "Enum value", "", "enum", ConcreteToken.TYPE_ATTR, manager.getNature()) });
}
FindDefinitionModelVisitor visitor = new FindDefinitionModelVisitor(actToks.get(actToksLen - 1), d.line, d.col, d.module, initialState.getNature());
try {
classDef.accept(visitor);
} catch (StopVisitingException e) {
// expected exception
}
if (visitor.definitions.size() == 0) {
return new TokensList(EMPTY_ITOKEN_ARRAY);
}
d = visitor.definitions.get(0);
value = d.value;
if (d instanceof AssignDefinition) {
// Yes, at this point we really are looking for an assign!
// E.g.:
//
// import my.module
//
// class A:
// objects = my.module.Class()
//
// This happens when completing on A.objects.
initialState.setLookingFor(ICompletionState.LookingFor.LOOKING_FOR_ASSIGN, true);
return getValueCompletions(initialState, manager, value, d.module);
}
} else {
if (d.module instanceof SourceModule) {
SourceModule m = (SourceModule) d.module;
String joined = FullRepIterable.joinFirstParts(actToks);
Definition[] definitions2 = m.findDefinition(initialState.getCopyWithActTok(joined), d.line, d.col, manager.getNature());
if (definitions2.length == 0) {
return new TokensList(EMPTY_ITOKEN_ARRAY);
}
d = definitions2[0];
value = d.value + "." + actToks.get(actToksLen - 1);
if (d instanceof AssignDefinition) {
return ((SourceModule) d.module).getValueCompletions(initialState, manager, value, d.module);
}
}
}
} else if ((d.ast == null && d.module != null) || d.ast instanceof ImportFrom) {
return getValueCompletions(initialState, manager, value, d.module);
} else {
break;
}
} else {
return getValueCompletions(initialState, manager, value, this);
}
iActTok++;
}
} catch (CompletionRecursionException e) {
} catch (Exception e) {
Log.log(e);
}
}
} else if (rep.equals(activationToken)) {
TokensList classToks;
if (ast instanceof ClassDef) {
classToks = getClassToks(initialState, manager, (ClassDef) ast);
initialState.setLookingFor(ICompletionState.LookingFor.LOOKING_FOR_UNBOUND_VARIABLE);
classToks.setLookingFor(initialState.getLookingFor());
} else {
classToks = getInnerToks(initialState, manager, ast);
}
if (classToks.empty()) {
if (initialState.getLookingFor() == ICompletionState.LookingFor.LOOKING_FOR_ASSIGN) {
continue;
}
// otherwise, return it empty anyway...
return new TokensList();
}
return classToks;
}
}
return new TokensList(EMPTY_ITOKEN_ARRAY);
}
use of org.python.pydev.ast.codecompletion.revisited.visitors.FindDefinitionModelVisitor in project Pydev by fabioz.
the class SourceModule method getFindDefinitionsScopeVisitor.
/**
* @param nature
* @return a find definition scope visitor that has already found some definition
*/
private FindDefinitionModelVisitor getFindDefinitionsScopeVisitor(String rep, int line, int col, IPythonNature nature) throws Exception {
Tuple3<String, Integer, Integer> key = new Tuple3<String, Integer, Integer>(rep, line, col);
FindDefinitionModelVisitor visitor = this.findDefinitionVisitorCache.getObj(key);
if (visitor == null) {
visitor = new FindDefinitionModelVisitor(rep, line, col, this, nature);
if (ast != null) {
try {
ast.accept(visitor);
} catch (StopVisitingException e) {
// expected exception
}
}
this.findDefinitionVisitorCache.add(key, visitor);
}
return visitor;
}
use of org.python.pydev.ast.codecompletion.revisited.visitors.FindDefinitionModelVisitor in project Pydev by fabioz.
the class SourceModule method findDefinitionsInAssignStatementUncached.
private Definition findDefinitionsInAssignStatementUncached(IPythonNature nature, String rep, SourceModule m, Assign foundInAssign) throws Exception {
// Note: don't use cache because we'll visit just the assign.
FindDefinitionModelVisitor visitor = new FindDefinitionModelVisitor(rep, foundInAssign.beginLine, foundInAssign.beginColumn, m, nature);
try {
foundInAssign.accept(visitor);
} catch (StopVisitingException e) {
// expected exception
}
List<Definition> definitions = visitor.definitions;
if (definitions == null || definitions.size() == 0) {
return null;
}
return definitions.get(0);
}
Aggregations