/** * We want to apply it on \n or on '.' * * <p>When . is entered, the user will finish (and apply) the current completion and request a new * one with '.' * * <p>If not added, it won't request the new one (and will just stop the current) */ @Override public char[] getTriggerCharacters() { char[] chars = VAR_TRIGGER; if (PyCodeCompletionPreferencesPage.applyCompletionOnLParen()) { chars = StringUtils.addChar(chars, '('); } if (PyCodeCompletionPreferencesPage.applyCompletionOnRParen()) { chars = StringUtils.addChar(chars, ')'); } return chars; }
@Override public boolean validate(IDocument document, int offset, DocumentEvent event) { String[] strs = PySelection.getActivationTokenAndQual(document, offset, false); // System.out.println("validating:"+strs[0]+" - "+strs[1]); // when we end with a '.', we should start a new completion (and not stay in the old one). if (strs[1].length() == 0 && (strs[0].length() == 0 || strs[0].endsWith("."))) { // System.out.println(false); return false; } String qualifier = strs[1]; final boolean useSubstringMatchInCodeCompletion = PyCodeCompletionPreferencesPage.getUseSubstringMatchInCodeCompletion(); String displayString = getDisplayString(); boolean ret = PyCodeCompletionUtils.acceptName( useSubstringMatchInCodeCompletion, displayString, qualifier); return ret; }
@Override public StyledString getStyledDisplayString( IDocument document, int offset, BoldStylerProvider boldStylerProvider) { // Extension enabled with enableColoredLabels(true); on PyContentAssistant. String[] strs = PySelection.getActivationTokenAndQual(document, offset, false); if (strs[1].length() == 0 && (strs[0].length() == 0 || strs[0].endsWith("."))) { StyledString styledString = new StyledString(getDisplayString()); return styledString; } String qualifier = strs[1]; final boolean useSubstringMatchInCodeCompletion = PyCodeCompletionPreferencesPage.getUseSubstringMatchInCodeCompletion(); String original = getDisplayString(); // Qualifier is everything after " - ". int index = original.indexOf(" - "); String strBeforeQualifier; if (index != -1) { strBeforeQualifier = original.substring(0, index); } else { strBeforeQualifier = original; } StyledString styledString = new StyledString(); if (useSubstringMatchInCodeCompletion) { int i = strBeforeQualifier.toLowerCase().indexOf(qualifier.toLowerCase()); if (i < 0) { styledString.append(strBeforeQualifier); } else { styledString.append(strBeforeQualifier.substring(0, i)); styledString.append( strBeforeQualifier.substring(i, i + qualifier.length()), boldStylerProvider.getBoldStyler()); styledString.append( strBeforeQualifier.substring(i + qualifier.length(), strBeforeQualifier.length())); } } else { styledString.append(strBeforeQualifier); } if (styledString.length() < original.length()) { styledString.append(original.substring(styledString.length()), StyledString.QUALIFIER_STYLER); } return styledString; }
/* (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; }
@Override protected boolean getApplyCompletionOnDot() { return PyCodeCompletionPreferencesPage.applyCompletionOnDot(); }