@Override public int isInGlobalTokens( String tok, IPythonNature nature, boolean searchSameLevelMods, boolean ifHasGetAttributeConsiderInTokens, ICompletionCache completionCache) throws CompletionRecursionException { // it's worth checking it if it is not dotted... (much faster as it's in a map already) if (tok.indexOf(".") == -1) { if (isInDirectGlobalTokens(tok, completionCache)) { return IModule.FOUND_TOKEN; } } String[] headAndTail = FullRepIterable.headAndTail(tok); String head = headAndTail[1]; String generateTokensFor = headAndTail[0]; Map<String, IToken> cachedTokens = getCachedCompletions(tok, nature, searchSameLevelMods, completionCache, generateTokensFor); if (cachedTokens.containsKey(head)) { return IModule.FOUND_TOKEN; } if (ifHasGetAttributeConsiderInTokens) { IToken token = cachedTokens.get("__getattribute__"); if (token == null || isTokenFromBuiltins(token)) { token = cachedTokens.get("__getattr__"); } if (token != null && !isTokenFromBuiltins(token)) { return IModule.FOUND_BECAUSE_OF_GETATTR; } // Try to determine if the user specified it has a @DynamicAttrs. String[] parentsHeadAndTail = FullRepIterable.headAndTail(generateTokensFor); cachedTokens = getCachedCompletions( tok, nature, searchSameLevelMods, completionCache, parentsHeadAndTail[0]); IToken parentToken = cachedTokens.get(parentsHeadAndTail[1]); if (parentToken != null) { String docString = parentToken.getDocStr(); if (docString != null) { if (docString.indexOf("@DynamicAttrs") != -1) { // class that has things dynamically defined. return IModule.FOUND_BECAUSE_OF_GETATTR; } } } } // if not found until now, it is not defined return IModule.NOT_FOUND; }
/* (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; }