/** * Copyright (c) 2005-2013 by Appcelerator, Inc. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ /* * Created on Mar 9, 2005 * * @author Fabio Zadrozny */ package org.python.pydev.editor.codecompletion; import java.io.File; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.python.pydev.core.ICompletionRequest; import org.python.pydev.core.IModule; import org.python.pydev.core.IPythonNature; import org.python.pydev.core.ITokenCompletionRequest; import org.python.pydev.core.MisconfigurationException; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.docutils.PySelection.ActivationTokenAndQual; import org.python.pydev.editor.codecompletion.revisited.AbstractASTManager; import org.python.pydev.shared_core.string.FastStringBuffer; /** * This class defines the information used for a code completion request. * * @author Fabio Zadrozny */ public final class CompletionRequest implements ICompletionRequest, ITokenCompletionRequest { /** * This is used on the AssistOverride: the activationToken is pre-specified * for some reason */ public CompletionRequest(File editorFile, IPythonNature nature, IDocument doc, String activationToken, int documentOffset, int qlen, IPyCodeCompletion codeCompletion, String qualifier, boolean useSubstringMatchInCodeCompletion) { this.editorFile = editorFile; this.nature = nature; this.doc = doc; this.activationToken = activationToken; this.documentOffset = documentOffset; this.qlen = qlen; this.codeCompletion = codeCompletion; this.qualifier = qualifier; // the full qualifier is not set here this.fullQualifier = null; this.calltipOffset = 0; this.alreadyHasParams = false; this.offsetForKeywordParam = 0; this.useSubstringMatchInCodeCompletion = useSubstringMatchInCodeCompletion; } /** * This is the constructor that should be usually used. It will set the * activation token and the qualifier based on the document and its offset * * @param editorFile * @param nature * @param doc * @param documentOffset * @param codeCompletion */ public CompletionRequest(File editorFile, IPythonNature nature, IDocument doc, int documentOffset, IPyCodeCompletion codeCompletion, boolean useSubstringMatchInCodeCompletion) { //we need those set before requesting a py selection this.doc = doc; this.documentOffset = documentOffset; ActivationTokenAndQual act = getPySelection().getActivationTokenAndQual(false, true); this.activationToken = act.activationToken; this.qualifier = act.qualifier; this.isInCalltip = act.changedForCalltip; this.isInMethodKeywordParam = act.isInMethodKeywordParam; this.offsetForKeywordParam = act.offsetForKeywordParam; this.alreadyHasParams = act.alreadyHasParams; this.calltipOffset = act.calltipOffset; int qlen = qualifier.length(); this.editorFile = editorFile; this.nature = nature; this.qlen = qlen; this.codeCompletion = codeCompletion; this.fullQualifier = getPySelection().getActivationTokenAndQual(true)[1]; this.useSubstringMatchInCodeCompletion = useSubstringMatchInCodeCompletion; } public CompletionRequest createCopyForKeywordParamRequest() { CompletionRequest request = new CompletionRequest(editorFile, nature, doc, this.offsetForKeywordParam, codeCompletion, this.useSubstringMatchInCodeCompletion); request.isInMethodKeywordParam = false; //Just making sure it will not be another request for keyword params return request; } /** * This is the file where the request was created. Note that it might be * null (especially during the tests). It should be available at runtime and * may be used to resolve some path. */ public File editorFile; @Override public File getEditorFile() { return editorFile; } /** * Used when a completion is requested for an editor */ public IPythonNature nature; @Override public IPythonNature getNature() { return nature; } public final IDocument doc; /** * The activation token of this request. * * If it is requested at "m1.m2", the activationToken should be "m1" and the * qualifier should be "m2" * * If requested at "m3", the activationToken should be empty and the * qualifier should be "m3" */ public String activationToken; /** * The qualifier found to the cursor (will be used to filter the found * completions) */ public final String qualifier; /** * The full qualifier found (this is the complete token over where we have * the cursor). May be null. */ public final String fullQualifier; /** * The offset in the document where this request was asked */ public final int documentOffset; /** * The lenght of the qualifier (== qualifier.length()) */ public final int qlen; /** * The engine for doing the code-completion */ public final IPyCodeCompletion codeCompletion; /** * Defines if we're getting the completions for a calltip * This happens when we're after a '(' or ',' in a method call. */ public boolean isInCalltip; /** * Defines if we're in a method call. */ public boolean isInMethodKeywordParam; /** * Only really valid when isInMethodKeywordParam == true. Defines the offset of the method call. */ public final int offsetForKeywordParam; /** * Offset of the parens in a calltip. */ public final int calltipOffset; /** * Useful only if we're in a calltip */ public final boolean alreadyHasParams; /** * A selection object (cache) -- initialized on request */ private PySelection ps; /** * This is a field that is filled in the code-completion engine indicating whether templates should be shown or not. */ public boolean showTemplates = true; @Override public String toString() { FastStringBuffer buffer = new FastStringBuffer(); buffer.append("CompletionRequest["); buffer.append(" editorFile:"); buffer.appendObject(editorFile); buffer.append(" activationToken:"); buffer.append(activationToken); buffer.append(" qualifier:"); buffer.append(qualifier); buffer.append(" isInCalltip:"); buffer.append(isInCalltip); buffer.append(" alreadyHasParams:"); buffer.append(alreadyHasParams); buffer.append("]"); return buffer.toString(); } /** * @return a PySelection that represents the current request. If it doesn't exist, create it and cache * for other requests. */ public PySelection getPySelection() { if (this.ps == null) { this.ps = new PySelection(this.doc, this.documentOffset); } return this.ps; } /** * Cache for the module name */ private String initialModule; /** * Cache for the source module created. */ private IModule module; public final boolean useSubstringMatchInCodeCompletion; /** * @return the module name where the completion request took place (may be null if there is no editor file associated) * @throws MisconfigurationException */ public String resolveModule() throws MisconfigurationException { if (initialModule == null && editorFile != null) { initialModule = nature.resolveModule(editorFile); } return initialModule; } /** * @param state * @param astManager * @return * @throws MisconfigurationException */ @Override public IModule getModule() throws MisconfigurationException { if (module == null) { module = AbstractASTManager.createModule(this.editorFile, this.doc, this.nature); } return module; } @Override public String getActivationToken() { return this.activationToken; } @Override public void setActivationToken(String activationToken) { this.activationToken = activationToken; } @Override public String getQualifier() { return qualifier; } @Override public int getLine() throws BadLocationException { return doc.getLineOfOffset(documentOffset); } @Override public int getCol() throws BadLocationException { IRegion region = doc.getLineInformationOfOffset(documentOffset); int col = documentOffset - region.getOffset(); return col; } }