/** IPyDevCompletionParticipant */ @SuppressWarnings("unchecked") public Collection getCompletionsForMethodParameter( ICompletionState state, ILocalScope localScope, Collection<IToken> interfaceForLocal) { ArrayList<IToken> ret = new ArrayList<IToken>(); String qual = state.getQualifier(); if (qual.length() >= CodeCompletionPreferencesPage .getCharsForContextInsensitiveGlobalTokensCompletion()) { // at least n characters List<IInfo> tokensStartingWith; try { tokensStartingWith = AdditionalProjectInterpreterInfo.getTokensStartingWith( qual, state.getNature(), AbstractAdditionalInterpreterInfo.INNER); } catch (MisconfigurationException e) { PydevPlugin.log(e); return ret; } for (IInfo info : tokensStartingWith) { ret.add( new SourceToken( null, info.getName(), null, null, info.getDeclaringModuleName(), info.getType())); } } return ret; }
/** * Generates the cached tokens in the needed structure for a 'fast' search given a token * representation (creates a map with the name of the token --> token). */ private Map<String, IToken> internalGenerateCachedTokens( IPythonNature nature, ICompletionCache completionCache, String activationToken, boolean searchSameLevelMods) throws CompletionRecursionException { Map<String, IToken> cachedTokens = new HashMap<String, IToken>(); // if still not found, we have to get all the tokens, including regular and wild imports ICompletionState state = CompletionStateFactory.getEmptyCompletionState(nature, completionCache); ICodeCompletionASTManager astManager = nature.getAstManager(); state.setActivationToken(activationToken); // we don't want to gather builtins in this case. state.setBuiltinsGotten(true); IToken[] globalTokens = astManager.getCompletionsForModule(this, state, searchSameLevelMods); for (IToken token : globalTokens) { String rep = token.getRepresentation(); IToken t = cachedTokens.get(rep); if (t != null) { // only override tokens if it's a getattr that's not defined in the builtin module if (rep.equals("__getattribute__") || rep.equals("__getattr__")) { if (!isTokenFromBuiltins(token)) { cachedTokens.put(rep, token); } } } else { cachedTokens.put(rep, token); } } return cachedTokens; }
/** * @param request this is the request for the completion * @param theList OUT - returned completions are added here. (IToken instances) * @param getOnlySupers whether we should only get things from super classes (in this case, we * won't get things from the current class) * @param checkIfInCorrectScope if true, we'll first check if we're in a scope that actually has a * method with 'self' or 'cls' * @return true if we actually tried to get the completions for self or cls. * @throws MisconfigurationException */ @SuppressWarnings("unchecked") public static boolean getSelfOrClsCompletions( CompletionRequest request, List theList, ICompletionState state, boolean getOnlySupers, boolean checkIfInCorrectScope, String lookForRep) throws MisconfigurationException { SimpleNode s = PyParser.reparseDocument( new PyParser.ParserInfo(request.doc, true, request.nature, state.getLine())) .o1; if (s != null) { FindScopeVisitor visitor = new FindScopeVisitor(state.getLine(), 0); try { s.accept(visitor); if (checkIfInCorrectScope) { boolean scopeCorrect = false; FastStack<SimpleNode> scopeStack = visitor.scope.getScopeStack(); for (Iterator<SimpleNode> it = scopeStack.topDownIterator(); scopeCorrect == false && it.hasNext(); ) { SimpleNode node = it.next(); if (node instanceof FunctionDef) { FunctionDef funcDef = (FunctionDef) node; if (funcDef.args != null && funcDef.args.args != null && funcDef.args.args.length > 0) { // ok, we have some arg, let's check for self or cls String rep = NodeUtils.getRepresentationString(funcDef.args.args[0]); if (rep != null && (rep.equals("self") || rep.equals("cls"))) { scopeCorrect = true; } } } } if (!scopeCorrect) { return false; } } if (lookForRep.equals("self")) { state.setLookingFor(ICompletionState.LOOKING_FOR_INSTANCED_VARIABLE); } else { state.setLookingFor(ICompletionState.LOOKING_FOR_CLASSMETHOD_VARIABLE); } getSelfOrClsCompletions(visitor.scope, request, theList, state, getOnlySupers); } catch (Exception e1) { PydevPlugin.log(e1); } return true; } return false; }
/** @return the names that are already imported in the current document */ private HashSet<String> getImportedNames(ICompletionState state) { List<IToken> tokenImportedModules = state.getTokenImportedModules(); HashSet<String> importedNames = new HashSet<String>(); if (tokenImportedModules != null) { for (IToken token : tokenImportedModules) { importedNames.add(token.getRepresentation()); } } return importedNames; }
@Override public boolean isInGlobalTokens( String tok, IPythonNature nature, ICompletionCache completionCache) { // we have to override because there is no way to check if it is in some import from some other // place if it has dots on the tok... if (tok.indexOf('.') == -1) { return isInDirectGlobalTokens(tok, completionCache); } else { ICompletionState state = CompletionStateFactory.getEmptyCompletionState(nature, completionCache); String[] headAndTail = FullRepIterable.headAndTail(tok); state.setActivationToken(headAndTail[0]); String head = headAndTail[1]; IToken[] globalTokens = getGlobalTokens(state, nature.getAstManager()); for (IToken token : globalTokens) { if (token.getRepresentation().equals(head)) { return true; } } } return false; }
/** * Does a code-completion that will retrieve the globals in the module * * @throws MisconfigurationException */ private void doGlobalsCompletion( CompletionRequest request, ICodeCompletionASTManager astManager, List<Object> tokensList, ICompletionState state) throws CompletionRecursionException, MisconfigurationException { state.setActivationToken(request.activationToken); if (DebugSettings.DEBUG_CODE_COMPLETION) { Log.toLogFile(this, "astManager.getCompletionsForToken"); Log.addLogLevel(); } IToken[] comps = astManager.getCompletionsForToken(request.editorFile, request.doc, state); if (DebugSettings.DEBUG_CODE_COMPLETION) { Log.remLogLevel(); Log.toLogFile(this, "END astManager.getCompletionsForToken"); } tokensList.addAll(Arrays.asList(comps)); tokensList.addAll(getGlobalsFromParticipants(request, state)); }
/** * Does a code-completion that will retrieve the all matches for some token in the module * * @throws MisconfigurationException */ private void doTokenCompletion( CompletionRequest request, ICodeCompletionASTManager astManager, List<Object> tokensList, String trimmed, ICompletionState state) throws CompletionRecursionException, MisconfigurationException { if (request.activationToken.endsWith(".")) { request.activationToken = request.activationToken.substring(0, request.activationToken.length() - 1); } final String initialActivationToken = request.activationToken; int parI = request.activationToken.indexOf('('); if (parI != -1) { request.activationToken = request.activationToken.substring(0, parI); } char[] toks = new char[] {'.', ' '}; List<Object> completions = new ArrayList<Object>(); boolean lookInGlobals = true; if (trimmed.equals("self") || FullRepIterable.getFirstPart(trimmed, toks).equals("self")) { lookInGlobals = !getSelfOrClsCompletions(request, tokensList, state, false, true, "self"); } else if (trimmed.equals("cls") || FullRepIterable.getFirstPart(trimmed, toks).equals("cls")) { lookInGlobals = !getSelfOrClsCompletions(request, tokensList, state, false, true, "cls"); } if (lookInGlobals) { state.setActivationToken(initialActivationToken); // Ok, looking for a token in globals. IToken[] comps = astManager.getCompletionsForToken(request.editorFile, request.doc, state); tokensList.addAll(Arrays.asList(comps)); } tokensList.addAll(completions); }
/* (non-Javadoc) * @see org.python.pydev.editor.codecompletion.IPyCodeCompletion#getCodeCompletionProposals(org.eclipse.jface.text.ITextViewer, org.python.pydev.editor.codecompletion.CompletionRequest) */ @SuppressWarnings("unchecked") public List getCodeCompletionProposals(ITextViewer viewer, CompletionRequest request) throws CoreException, BadLocationException, IOException, MisconfigurationException, PythonNatureWithoutProjectException { if (request.getPySelection().getCursorLineContents().trim().startsWith("#")) { // this may happen if the context is still not correctly computed in python return new PyStringCodeCompletion().getCodeCompletionProposals(viewer, request); } if (DebugSettings.DEBUG_CODE_COMPLETION) { Log.toLogFile(this, "Starting getCodeCompletionProposals"); Log.addLogLevel(); Log.toLogFile(this, "Request:" + request); } ArrayList<ICompletionProposal> ret = new ArrayList<ICompletionProposal>(); // let's see if we should do a code-completion in the current scope... if (!isValidCompletionContext(request)) { request.showTemplates = false; return ret; } try { IPythonNature pythonNature = request.nature; checkPythonNature(pythonNature); ICodeCompletionASTManager astManager = pythonNature.getAstManager(); if (astManager == null) { // we're probably still loading it. return ret; } // list of Object[], IToken or ICompletionProposal List<Object> tokensList = new ArrayList<Object>(); lazyStartShell(request); String trimmed = request.activationToken.replace('.', ' ').trim(); ImportInfo importsTipper = getImportsTipperStr(request); int line = request.doc.getLineOfOffset(request.documentOffset); IRegion region = request.doc.getLineInformation(line); ICompletionState state = new CompletionState( line, request.documentOffset - region.getOffset(), null, request.nature, request.qualifier); state.setIsInCalltip(request.isInCalltip); boolean importsTip = false; if (importsTipper.importsTipperStr.length() != 0) { // code completion in imports request.isInCalltip = false; // if found after (, but in an import, it is not a calltip! importsTip = doImportCompletion(request, astManager, tokensList, importsTipper); } else if (trimmed.length() > 0 && request.activationToken.indexOf('.') != -1) { // code completion for a token doTokenCompletion(request, astManager, tokensList, trimmed, state); } else { // go to globals doGlobalsCompletion(request, astManager, tokensList, state); } Map<String, IToken> alreadyChecked = new HashMap<String, IToken>(); String lowerCaseQual = request.qualifier.toLowerCase(); if (lowerCaseQual.length() >= PyCodeCompletionPreferencesPage.getArgumentsDeepAnalysisNChars()) { // this can take some time on the analysis, so, let's let the user choose on how many chars // does he // want to do the analysis... state.pushFindResolveImportMemoryCtx(); try { for (Iterator<Object> it = tokensList.listIterator(); it.hasNext(); ) { Object o = it.next(); if (o instanceof IToken) { it .remove(); // always remove the tokens from the list (they'll be re-added later // once they are filtered) IToken initialToken = (IToken) o; IToken token = initialToken; String strRep = token.getRepresentation(); IToken prev = alreadyChecked.get(strRep); if (prev != null) { if (prev.getArgs().length() != 0) { continue; // we already have a version with args... just keep going } } if (!strRep.toLowerCase().startsWith(lowerCaseQual)) { // just re-add it if we're going to actually use it (depending on the qualifier) continue; } while (token.isImportFrom()) { // we'll only add it here if it is an import from (so, set the flag to false for the // outer add) if (token.getArgs().length() > 0) { // if we already have the args, there's also no reason to do it (that's what we'll // do here) break; } ICompletionState s = state.getCopyForResolveImportWithActTok(token.getRepresentation()); s.checkFindResolveImportMemory(token); IToken token2 = astManager.resolveImport(s, token); if (token2 != null && initialToken != token2) { String args = token2.getArgs(); if (args.length() > 0) { // put it into the map (may override previous if it didn't have args) initialToken.setArgs(args); initialToken.setDocStr(token2.getDocStr()); if (initialToken instanceof SourceToken && token2 instanceof SourceToken) { SourceToken initialSourceToken = (SourceToken) initialToken; SourceToken token2SourceToken = (SourceToken) token2; initialSourceToken.setAst(token2SourceToken.getAst()); } break; } if (token2 == null || (token2.equals(token) && token2.getArgs().equals(token.getArgs()) && token2.getParentPackage().equals(token.getParentPackage()))) { break; } token = token2; } else { break; } } alreadyChecked.put(strRep, initialToken); } } } finally { state.popFindResolveImportMemoryCtx(); } } tokensList.addAll(alreadyChecked.values()); changeItokenToCompletionPropostal(viewer, request, ret, tokensList, importsTip, state); } catch (CompletionRecursionException e) { if (onCompletionRecursionException != null) { onCompletionRecursionException.call(e); } if (DebugSettings.DEBUG_CODE_COMPLETION) { Log.toLogFile(e); } // PydevPlugin.log(e); // ret.add(new CompletionProposal("",request.documentOffset,0,0,null,e.getMessage(), // null,null)); } if (DebugSettings.DEBUG_CODE_COMPLETION) { Log.remLogLevel(); Log.toLogFile(this, "Finished completion. Returned:" + ret.size() + " completions.\r\n"); } return ret; }
/** * Get self completions when you already have a scope * * @throws MisconfigurationException */ @SuppressWarnings("unchecked") public static void getSelfOrClsCompletions( ILocalScope scope, CompletionRequest request, List theList, ICompletionState state, boolean getOnlySupers) throws BadLocationException, MisconfigurationException { for (Iterator<SimpleNode> it = scope.iterator(); it.hasNext(); ) { SimpleNode node = it.next(); if (node instanceof ClassDef) { ClassDef d = (ClassDef) node; if (getOnlySupers) { List gottenComps = new ArrayList(); for (int i = 0; i < d.bases.length; i++) { if (d.bases[i] instanceof Name) { Name n = (Name) d.bases[i]; state.setActivationToken(n.id); IToken[] completions; try { completions = request .nature .getAstManager() .getCompletionsForToken(request.editorFile, request.doc, state); gottenComps.addAll(Arrays.asList(completions)); } catch (CompletionRecursionException e) { // ok... } } } theList.addAll(gottenComps); } else { // ok, get the completions for the class, only thing we have to take care now is that we // may // not have only 'self' for completion, but something like self.foo. // so, let's analyze our activation token to see what should we do. String trimmed = request.activationToken.replace('.', ' ').trim(); String[] actTokStrs = trimmed.split(" "); if (actTokStrs.length == 0 || (!actTokStrs[0].equals("self") && !actTokStrs[0].equals("cls"))) { throw new AssertionError( "We need to have at least one token (self or cls) for doing completions in the class."); } if (actTokStrs.length == 1) { // ok, it's just really self, let's get on to get the completions state.setActivationToken(NodeUtils.getNameFromNameTok((NameTok) d.name)); try { theList.addAll( Arrays.asList( request .nature .getAstManager() .getCompletionsForToken(request.editorFile, request.doc, state))); } catch (CompletionRecursionException e) { // ok } } else { // it's not only self, so, first we have to get the definition of the token // the first one is self, so, just discard it, and go on, token by token to know what is // the last // one we are completing (e.g.: self.foo.bar) int line = request.doc.getLineOfOffset(request.documentOffset); IRegion region = request.doc.getLineInformationOfOffset(request.documentOffset); int col = request.documentOffset - region.getOffset(); // ok, try our best shot at getting the module name of the current buffer used in the // request. String modName = ""; File requestFile = request.editorFile; if (request.editorFile != null) { String resolveModule = request.nature.resolveModule(requestFile); if (resolveModule != null) { modName = resolveModule; } } IModule module = AbstractModule.createModuleFromDoc( modName, requestFile, request.doc, request.nature, line); AbstractASTManager astMan = ((AbstractASTManager) request.nature.getAstManager()); theList.addAll( new AssignAnalysis() .getAssignCompletions( astMan, module, new CompletionState( line, col, request.activationToken, request.nature, request.qualifier)) .completions); } } } } }
/** * @param findInfo * @see * org.python.pydev.editor.codecompletion.revisited.modules.AbstractModule#findDefinition(java.lang.String, * int, int) */ public Definition[] findDefinition( ICompletionState state, int line, int col, IPythonNature nature) throws Exception { String token = state.getActivationToken(); if (TRACE_COMPILED_MODULES) { System.out.println("CompiledModule.findDefinition:" + token); } Definition[] found = this.definitionsFoundCache.getObj(token); if (found != null) { if (TRACE_COMPILED_MODULES) { System.out.println("CompiledModule.findDefinition: found in cache."); } return found; } AbstractShell shell = AbstractShell.getServerShell(nature, AbstractShell.COMPLETION_SHELL); synchronized (shell) { Tuple<String[], int[]> def = shell.getLineCol( this.name, token, nature .getAstManager() .getModulesManager() .getCompletePythonPath( nature.getProjectInterpreter(), nature.getRelatedInterpreterManager())); // default if (def == null) { if (TRACE_COMPILED_MODULES) { System.out.println("CompiledModule.findDefinition:" + token + " = empty"); } this.definitionsFoundCache.add(token, EMPTY_DEFINITION); return EMPTY_DEFINITION; } String fPath = def.o1[0]; if (fPath.equals("None")) { if (TRACE_COMPILED_MODULES) { System.out.println("CompiledModule.findDefinition:" + token + " = None"); } Definition[] definition = new Definition[] {new Definition(def.o2[0], def.o2[1], token, null, null, this)}; this.definitionsFoundCache.add(token, definition); return definition; } File f = new File(fPath); String foundModName = nature.resolveModule(f); String foundAs = def.o1[1]; IModule mod; if (foundModName == null) { // this can happen in a case where we have a definition that's found from a compiled file // which actually // maps to a file that's outside of the pythonpath known by Pydev. String n = FullRepIterable.getFirstPart(f.getName()); mod = AbstractModule.createModule(n, f, nature, true); } else { mod = nature.getAstManager().getModule(foundModName, nature, true); } if (TRACE_COMPILED_MODULES) { System.out.println("CompiledModule.findDefinition: found at:" + mod.getName()); } int foundLine = def.o2[0]; if (foundLine == 0 && foundAs != null && foundAs.length() > 0 && mod != null && state.canStillCheckFindSourceFromCompiled(mod, foundAs)) { // TODO: The nature (and so the grammar to be used) must be defined by the file we'll parse // (so, we need to know the system modules manager that actually created it to know the // actual nature) IModule sourceMod = AbstractModule.createModuleFromDoc( mod.getName(), f, new Document(REF.getFileContents(f)), nature, true); if (sourceMod instanceof SourceModule) { Definition[] definitions = (Definition[]) sourceMod.findDefinition(state.getCopyWithActTok(foundAs), -1, -1, nature); if (definitions.length > 0) { this.definitionsFoundCache.add(token, definitions); return definitions; } } } if (mod == null) { mod = this; } int foundCol = def.o2[1]; if (foundCol < 0) { foundCol = 0; } if (TRACE_COMPILED_MODULES) { System.out.println("CompiledModule.findDefinition: found compiled at:" + mod.getName()); } Definition[] definitions = new Definition[] {new Definition(foundLine + 1, foundCol + 1, token, null, null, mod)}; this.definitionsFoundCache.add(token, definitions); return definitions; } }
/** * @see * org.python.pydev.editor.codecompletion.revisited.modules.AbstractModule#getGlobalTokens(java.lang.String) */ public IToken[] getGlobalTokens(ICompletionState state, ICodeCompletionASTManager manager) { String activationToken = state.getActivationToken(); if (activationToken.length() == 0) { return getGlobalTokens(); } Map<String, IToken> v = cache.get(activationToken); if (v != null) { Collection<IToken> values = v.values(); return values.toArray(new IToken[values.size()]); } IToken[] toks = new IToken[0]; if (COMPILED_MODULES_ENABLED) { try { final IPythonNature nature = manager.getNature(); final AbstractShell shell; try { shell = AbstractShell.getServerShell(nature, AbstractShell.COMPLETION_SHELL); } catch (Exception e) { throw new RuntimeException("Unable to create shell for CompiledModule: " + this.name, e); } synchronized (shell) { String act = name + '.' + activationToken; String tokenToCompletion = act; if (isPythonBuiltin) { String replacement = BUILTIN_REPLACEMENTS.get(activationToken); if (replacement != null) { tokenToCompletion = name + '.' + replacement; } } List<String[]> completions = shell.getImportCompletions( tokenToCompletion, manager .getModulesManager() .getCompletePythonPath( nature.getProjectInterpreter(), nature.getRelatedInterpreterManager())) .o2; ArrayList<IToken> array = new ArrayList<IToken>(); for (Iterator<String[]> iter = completions.iterator(); iter.hasNext(); ) { String[] element = iter.next(); if (element.length >= 4) { // it might be a server error IToken t = new CompiledToken( element[0], element[1], element[2], act, Integer.parseInt(element[3])); array.add(t); } } toks = (CompiledToken[]) array.toArray(new CompiledToken[0]); HashMap<String, IToken> map = new HashMap<String, IToken>(); for (IToken token : toks) { map.put(token.getRepresentation(), token); } cache.put(activationToken, map); } } catch (Exception e) { Log.log( "Error while getting info for module:" + this.name + ". Project: " + manager.getNature().getProject(), e); } } return toks; }