⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simpleassistprocessor.java

📁 Python Development Environment (Python IDE plugin for Eclipse). Features editor, code completion, re
💻 JAVA
字号:
/*
 * Created on 24/09/2005
 */
package org.python.pydev.editor.simpleassist;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.jface.text.contentassist.ContentAssistEvent;
import org.eclipse.jface.text.contentassist.ICompletionListener;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.python.pydev.core.ExtensionHelper;
import org.python.pydev.core.docutils.PySelection;
import org.python.pydev.editor.PyEdit;
import org.python.pydev.editor.codecompletion.IPyCodeCompletion;
import org.python.pydev.editor.codecompletion.PyCodeCompletionPreferencesPage;
import org.python.pydev.editor.codecompletion.PyContentAssistant;
import org.python.pydev.editor.codecompletion.PythonCompletionProcessor;
import org.python.pydev.plugin.PydevPlugin;

/**
 * This processor controls the completion cycle (and also works as a 'delegator' to the processor that deals
 * with actual python completions -- which may be a bit slower that simple completions).
 * 
 * @author Fabio
 */
public class SimpleAssistProcessor implements IContentAssistProcessor {
    
    private class ContextInformationDelegator implements IContextInformationValidator, IContextInformationPresenter {
        private final IContextInformationValidator defaultContextInformationValidator;

        private ContextInformationDelegator(IContextInformationValidator defaultContextInformationValidator) {
            Assert.isTrue(defaultContextInformationValidator instanceof IContextInformationPresenter);
            this.defaultContextInformationValidator = defaultContextInformationValidator;
        }

        public void install(IContextInformation info, ITextViewer viewer, int offset) {
            defaultContextInformationValidator.install(info, viewer, offset);
        }

        public boolean isContextInformationValid(int offset) {
            if(showDefault()){
                return defaultContextInformationValidator.isContextInformationValid(offset);
            }
            return true;
        }

        public boolean updatePresentation(int offset, TextPresentation presentation) {
            return ((IContextInformationPresenter)defaultContextInformationValidator).updatePresentation(offset, presentation);
        }
    }

    public static final char[] ALL_ASCII_CHARS = new char[]{
            'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
            'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
            '_'
        };

    
    //-------- cycling through simple completions and default processor
    private static final int SHOW_SIMPLE = 1;
    private static final int SHOW_DEFAULT = 2;
    private int whatToShow = SHOW_SIMPLE;
    
    public void startCycle(){
        whatToShow = SHOW_SIMPLE;
    }
    
    private void doCycle() {
        if(whatToShow == SHOW_SIMPLE){
            whatToShow = SHOW_DEFAULT;
        }
        //cycles only once here
    }
    
    public void updateStatus(){
        if(whatToShow == SHOW_SIMPLE){
            assistant.setIterationStatusMessage("Press %s for default completions.");
        }
    }
    //-------- end cycling through regular completions and templates

    /**
     * The editor that contains this processor
     */
    private PyEdit edit;

    /**
     * The 'default' processor (gets python completions)
     */
    private PythonCompletionProcessor defaultPythonProcessor;

    /**
     * The content assistant that contains this processor
     */
    private PyContentAssistant assistant;

    /**
     * Participants for a simple completion
     */
    private List<ISimpleAssistParticipant> participants;
    
    /**
     * Whether the last completion was auto-activated or not
     */
    private boolean lastCompletionAutoActivated;

    /**
     * Whether we should use the default auto-completion on all ascii chars
     * Cleared when the property cache is updated (based on autoActivationCharsCache)
     */
    private volatile static boolean useAutocompleteOnAllAsciiCharsCache;

    /**
     * Cache with the chars that should be used for auto-activation
     * Cleared when the property cache is updated
     */
    private volatile static char [] autoActivationCharsCache;
    
    @SuppressWarnings("unchecked")
    public SimpleAssistProcessor(PyEdit edit, PythonCompletionProcessor defaultPythonProcessor, final PyContentAssistant assistant){
        this.edit = edit;
        this.defaultPythonProcessor = defaultPythonProcessor;
        this.assistant = assistant;
        this.participants = ExtensionHelper.getParticipants(ExtensionHelper.PYDEV_SIMPLE_ASSIST);

        assistant.addCompletionListener(new ICompletionListener(){
            public void assistSessionEnded(ContentAssistEvent event) {
            }
            
            public void assistSessionStarted(ContentAssistEvent event) {
                startCycle();
                lastCompletionAutoActivated = assistant.getLastCompletionAutoActivated();
                if(!lastCompletionAutoActivated){
                    //user request... cycle to the default completions at once
                    doCycle();
                }
            }

            public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) {
                //ignore
            }
        });
        
        PydevPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener(){
            public void propertyChange(PropertyChangeEvent event) {
                autoActivationCharsCache = null;
            }
        });
    }

    /**
     * Computes the proposals (may forward for simple or 'complete' proposals)
     *  
     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int)
     */
    @SuppressWarnings("unchecked")
    public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
        if(showDefault()){
            return defaultPythonProcessor.computeCompletionProposals(viewer, offset);
            
        }else{
            updateStatus();
            IDocument doc = viewer.getDocument();
            String[] strs = PySelection.getActivationTokenAndQual(doc, offset, false); 
    
            String activationToken = strs[0];
            String qualifier = strs[1];
    
            PySelection ps = new PySelection(edit);
            List<ICompletionProposal> results = new ArrayList<ICompletionProposal>();
    
            for (ISimpleAssistParticipant participant : participants) {
                results.addAll(participant.computeCompletionProposals(activationToken, qualifier, ps, edit, offset));
            }
            
            //don't matter the result... next time we won't ask for simple stuff
            doCycle();
            if(results.size() == 0){
                if(!lastCompletionAutoActivated || defaultAutoActivated(viewer, offset) || useAutocompleteOnAllAsciiCharsCache){
                    return defaultPythonProcessor.computeCompletionProposals(viewer, offset);
                }
                return new ICompletionProposal[0];
            }else{
                Collections.sort(results, IPyCodeCompletion.PROPOSAL_COMPARATOR);
                return (ICompletionProposal[]) results.toArray(new ICompletionProposal[0]);
            }
        }
    }

    /**
     * Determines whether it was auto-activated on the default completion or in the simple one.
     * @param viewer the viewer for which this completion was requested
     * @param offset the offset at which it was requested
     * @return true if it was auto-activated for the default completion (and false if it was for the simple)
     */
    private boolean defaultAutoActivated(ITextViewer viewer, int offset) {
        try {
            char docChar = viewer.getDocument().getChar(offset-1);
            for(char c: this.defaultPythonProcessor.getCompletionProposalAutoActivationCharacters()){
                if(c == docChar){
                    return true;
                }
            }
            
        } catch (BadLocationException e) {
        }
        return false;
    }

    /**
     * @return true if we should show the default completions (and false if we shouldn't)
     */
    private boolean showDefault() {
        return whatToShow == SHOW_DEFAULT || this.participants.size() == 0;
    }

    /**
     * Compute context information
     */
    public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
        if(showDefault()){
            return defaultPythonProcessor.computeContextInformation(viewer, offset);
        }
        return null;
    }
    
    /**
     * only very simple proposals should be here, as it is auto-activated for any character
     *  
     * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
     */
    public char[] getCompletionProposalAutoActivationCharacters() {
        if(autoActivationCharsCache == null){
            char[] defaultAutoActivationCharacters = defaultPythonProcessor.getCompletionProposalAutoActivationCharacters();
            
            useAutocompleteOnAllAsciiCharsCache = 
            	PyCodeCompletionPreferencesPage.useAutocompleteOnAllAsciiChars() &&
            	PyCodeCompletionPreferencesPage.useAutocomplete();
            
            if(this.participants.size() == 0 && !useAutocompleteOnAllAsciiCharsCache){
                return defaultAutoActivationCharacters;
            }
            
            //just use the extension for the simple if we do have it
            char [] c2 = new char[ALL_ASCII_CHARS.length+defaultAutoActivationCharacters.length];
            System.arraycopy(ALL_ASCII_CHARS, 0, c2, 0, ALL_ASCII_CHARS.length);
            System.arraycopy(defaultAutoActivationCharacters, 0, c2, ALL_ASCII_CHARS.length, defaultAutoActivationCharacters.length);

            autoActivationCharsCache = c2;
        }
        return autoActivationCharsCache;
    }

    /**
     * @return chars that are used for context information auto-activation
     */
    public char[] getContextInformationAutoActivationCharacters() {
        return null;
    }

    /**
     * @return some error that might have happened in the completion
     */
    public String getErrorMessage() {
        if(showDefault()){
            return defaultPythonProcessor.getErrorMessage();
        }
        return null;
    }

    /**
     * @return the validator we should use
     */
    public IContextInformationValidator getContextInformationValidator() {
        final IContextInformationValidator defaultContextInformationValidator = defaultPythonProcessor.getContextInformationValidator();
        return new ContextInformationDelegator(defaultContextInformationValidator);
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -