/******************************************************************************* * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.ext.java.jdt.codeassistant; import org.eclipse.che.ide.ext.java.jdt.codeassistant.ContentAssistHistory.RHSHistory; import org.eclipse.che.ide.ext.java.jdt.codeassistant.api.ContentAssistInvocationContext; import org.eclipse.che.ide.ext.java.jdt.codeassistant.api.JavaCompletionProposal; import org.eclipse.che.ide.ext.java.jdt.core.CompletionContext; import org.eclipse.che.ide.ext.java.jdt.core.CompletionProposal; import org.eclipse.che.ide.ext.java.jdt.core.IType; import org.eclipse.che.ide.ext.java.jdt.core.dom.CompilationUnit; import org.eclipse.che.ide.ext.java.jdt.internal.corext.util.SignatureUtil; import org.eclipse.che.ide.ext.java.worker.WorkerMessageHandler; import org.eclipse.che.ide.ext.java.worker.WorkerTypeInfoStorage; import org.eclipse.che.ide.ext.java.jdt.text.Document; /** * Describes the context of a content assist invocation in a Java editor. * <p> * Clients may use but not subclass this class. * </p> * * @noextend This class is not intended to be subclassed by clients. */ public class JavaContentAssistInvocationContext extends ContentAssistInvocationContext { private RHSHistory fRHSHistory; private CompletionProposalLabelProvider fLabelProvider; private CompletionProposalCollector fCollector; private JavaCompletionProposal[] fKeywordProposals = null; private CompletionContext fCoreContext = null; private CompilationUnit compilationUnit; private String docContext; private String projectId; private IType fType; private String vfsId; /** * Creates a new context. * * @param unit * the compilation unit in <code>document</code> */ public JavaContentAssistInvocationContext(Document document, int offset) { super(document, offset); } /** @param compilationUnit */ public JavaContentAssistInvocationContext(CompilationUnit compilationUnit, Document document, int offset, String projectId, String docContext, String vfsId) { this(document, offset); this.compilationUnit = compilationUnit; this.projectId = projectId; this.docContext = docContext; this.vfsId = vfsId; } /** * Returns the keyword proposals that are available in this context, possibly none. * <p> * <strong>Note:</strong> This method may run * {@linkplain ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor) codeComplete} on the compilation unit. * </p> * * @return the available keyword proposals */ public JavaCompletionProposal[] getKeywordProposals() { if (fKeywordProposals == null) { if (fCollector != null && !fCollector.isIgnored(CompletionProposal.KEYWORD) && fCollector.getContext() != null) { // use the existing collector if it exists, collects keywords, and has already been invoked fKeywordProposals = fCollector.getKeywordCompletionProposals(); } // else // { // // otherwise, retrieve keywords ourselves // computeKeywordsAndContext(); // } } return fKeywordProposals; } /** * Returns the {@link CompletionContext core completion context} if available, <code>null</code> otherwise. * <p> * <strong>Note:</strong> This method may run * {@linkplain ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor) codeComplete} on the compilation unit. * </p> * * @return the core completion context if available, <code>null</code> otherwise */ public CompletionContext getCoreContext() { if (fCollector != null) { CompletionContext context = fCollector.getContext(); if (context != null) { if (fCoreContext == null) fCoreContext = context; return context; } } // if (fCoreContext == null) // computeKeywordsAndContext(); // Retrieve the context ourselves return fCoreContext; } /** * Returns an float in [0.0, 1.0] based on whether the type has been recently used as a right hand side for the type * expected in the current context. 0 signals that the <code>qualifiedTypeName</code> does not match the expected type, while * 1.0 signals that <code>qualifiedTypeName</code> has most recently been used in a similar context. * <p> * <strong>Note:</strong> This method may run * {@linkplain ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor) codeComplete} on the compilation unit. * </p> * * @param qualifiedTypeName * the type name of the type of interest * @return a relevance in [0.0, 1.0] based on previous content assist invocations */ public float getHistoryRelevance(String qualifiedTypeName) { return getRHSHistory().getRank(qualifiedTypeName); } /** * Returns the content assist type history for the expected type. * * @return the content assist type history for the expected type */ private RHSHistory getRHSHistory() { if (fRHSHistory == null) { CompletionContext context = getCoreContext(); if (context != null) { char[][] expectedTypes = context.getExpectedTypesSignatures(); if (expectedTypes != null && expectedTypes.length > 0) { String expected = SignatureUtil.stripSignatureToFQN(String.valueOf(expectedTypes[0])); fRHSHistory = WorkerMessageHandler.get().getContentAssistHistory().getHistory(expected); } } if (fRHSHistory == null) fRHSHistory = WorkerMessageHandler.get().getContentAssistHistory().getHistory(null); } return fRHSHistory; } /** * Returns the expected type if any, <code>null</code> otherwise. * <p> * <strong>Note:</strong> This method may run * {@linkplain ICodeAssist#codeComplete(int, org.eclipse.jdt.core.CompletionRequestor) codeComplete} on the compilation unit. * </p> * * @return the expected type if any, <code>null</code> otherwise */ public IType getExpectedType() { if (fType == null && getCompilationUnit() != null) { CompletionContext context = getCoreContext(); if (context != null) { char[][] expectedTypes = context.getExpectedTypesSignatures(); if (expectedTypes != null && expectedTypes.length > 0) { fType = WorkerTypeInfoStorage.get().getTypeByFqn( SignatureUtil.stripSignatureToFQN(String.valueOf(expectedTypes[0]))); } } } return fType; } /** * Returns a label provider that can be used to compute proposal labels. * * @return a label provider that can be used to compute proposal labels */ public CompletionProposalLabelProvider getLabelProvider() { if (fLabelProvider == null) { if (fCollector != null) fLabelProvider = fCollector.getLabelProvider(); else fLabelProvider = new CompletionProposalLabelProvider(); } return fLabelProvider; } /** * Sets the collector, which is used to access the compilation unit, the core context and the label provider. This is a * performance optimization: {@link IJavaCompletionProposalComputer}s may instantiate a {@link CompletionProposalCollector} and * set this invocation context via {@link CompletionProposalCollector#setInvocationContext(JavaContentAssistInvocationContext)} * , which in turn calls this method. This allows the invocation context to retrieve the core context and keyword proposals * from the existing collector, instead of computing theses values itself via {@link #computeKeywordsAndContext()}. * * @param collector * the collector */ void setCollector(CompletionProposalCollector collector) { fCollector = collector; } /** @return the compilationUnit */ public CompilationUnit getCompilationUnit() { return compilationUnit; } /** * @param compilationUnit * the compilationUnit to set */ public void setCompilationUnit(CompilationUnit compilationUnit) { this.compilationUnit = compilationUnit; } /** @return the docContext */ public String getDocContext() { return docContext; } /** @return the projectId */ public String getProjectId() { return projectId; } /** @return the vfsId */ public String getVfsId() { return vfsId; } // /** // * Fallback to retrieve a core context and keyword proposals when no collector is available. Runs code completion on the cu // and // * collects keyword proposals. {@link #fKeywordProposals} is non-<code>null</code> after this call. // * // * @since 3.3 // */ // private void computeKeywordsAndContext() // { // CompilationUnit cu = getCompilationUnit(); // if (cu == null) // { // if (fKeywordProposals == null) // fKeywordProposals = new IJavaCompletionProposal[0]; // return; // } // // CompletionProposalCollector collector = new CompletionProposalCollector(cu, true); // collector.setIgnored(CompletionProposal.KEYWORD, false); // // try // { // cu.codeComplete(getInvocationOffset(), collector); // if (fCoreContext == null) // fCoreContext = collector.getContext(); // if (fKeywordProposals == null) // fKeywordProposals = collector.getKeywordCompletionProposals(); // if (fLabelProvider == null) // fLabelProvider = collector.getLabelProvider(); // } // catch (JavaModelException x) // { // if (!x.isDoesNotExist() || cu.getJavaProject() == null || cu.getJavaProject().isOnClasspath(cu)) // JavaPlugin.log(x); // if (fKeywordProposals == null) // fKeywordProposals = new IJavaCompletionProposal[0]; // } // } /* * Implementation note: There is no need to override hashCode and equals, as we only add cached values shared across one assist * invocation. */ }