/*
* Copyright (c) 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.ui.text.dart;
import com.google.dart.engine.services.assist.AssistContext;
import com.google.dart.tools.core.completion.CompletionContext;
import com.google.dart.tools.core.completion.CompletionProposal;
import com.google.dart.tools.ui.internal.text.completion.DartServerProposalCollector;
import com.google.dart.tools.ui.internal.text.dart.ContentAssistHistory;
import com.google.dart.tools.ui.internal.text.dart.ContentAssistHistory.RHSHistory;
import com.google.dart.tools.ui.internal.text.editor.DartEditor;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.ui.IEditorPart;
/**
* Describes the context of a content assist invocation in a Dart editor.
* <p>
* Clients may use but not subclass this class.
* </p>
* Provisional API: This class/interface is part of an interim API that is still under development
* and expected to change significantly before reaching stability. It is being made available at
* this early stage to solicit feedback from pioneering adopters on the understanding that any code
* that uses this API will almost certainly be broken (repeatedly) as the API evolves.
* Implementation note: There is no need to override hashCode and equals, as we only add cached
* values shared across one assist invocation.
*/
public class DartContentAssistInvocationContext extends ContentAssistInvocationContext {
private final IEditorPart fEditor;
private CompletionProposalLabelProvider fLabelProvider;
private CompletionProposalCollector fCollector;
private RHSHistory fRHSHistory;
private IDartCompletionProposal[] fKeywordProposals = null;
private CompletionContext fCoreContext = null;
private AssistContext assistContext;
private DartServerProposalCollector collector;
/**
* Creates a new context.
*/
public DartContentAssistInvocationContext() {
super();
fEditor = null;
}
/**
* Creates a new context.
*
* @param viewer the viewer used by the editor
* @param offset the invocation offset
* @param editor the editor that content assist is invoked in
* @param assistContext the context or {@code null} if unknown
* @param collector the completion collector or {@code null} if unknown
*/
public DartContentAssistInvocationContext(ITextViewer viewer, int offset, IEditorPart editor,
AssistContext assistContext, DartServerProposalCollector collector) {
super(viewer, offset);
fEditor = editor;
this.assistContext = assistContext;
this.collector = collector;
}
public AssistContext getAssistContext() {
if (assistContext == null) {
assistContext = ((DartEditor) fEditor).getAssistContext();
}
return assistContext;
}
public DartServerProposalCollector getCollector() {
return collector;
}
/**
* Returns the {@link CompletionContext core completion context} if available, <code>null</code>
* otherwise.
* <p>
* <strong>Note:</strong> This method may run
* {@linkplain org.eclipse.wst.jsdt.core.ICodeAssist#codeComplete(int, org.eclipse.wst.jsdt.core.CompletionRequestor)
* codeComplete} on the compilation unit.
* </p>
*
* @return the core completion context if available, <code>null</code> otherwise
*/
public CompletionContext getCoreContext() {
if (fCoreContext == null) {
// use the context from the existing collector if it exists, retrieve one
// ourselves otherwise
if (fCollector != null) {
fCoreContext = fCollector.getContext();
}
if (fCoreContext == null) {
computeKeywordsAndContext();
}
}
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 org.eclipse.wst.jsdt.core.ICodeAssist#codeComplete(int, org.eclipse.wst.jsdt.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);
}
public com.google.dart.engine.ast.CompilationUnit getInputUnit() {
return ((DartEditor) fEditor).getInputUnit();
}
/**
* Returns the keyword proposals that are available in this context, possibly none.
* <p>
* <strong>Note:</strong> This method may run
* {@linkplain org.eclipse.wst.jsdt.core.ICodeAssist#codeComplete(int, org.eclipse.wst.jsdt.core.CompletionRequestor)
* codeComplete} on the compilation unit.
* </p>
*
* @return the available keyword proposals
*/
public IDartCompletionProposal[] 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 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;
}
public int getPartitionOffset() {
return 0;
}
/**
* Sets the collector, which is used to access the compilation unit, the core context and the
* label provider. This is a performance optimization: {@link IDartCompletionProposalComputer}s
* may instantiate a {@link CompletionProposalCollector} and set this invocation context via
* {@link CompletionProposalCollector#setInvocationContext(DartContentAssistInvocationContext)} ,
* 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
*/
protected void setCollector(CompletionProposalCollector collector) {
fCollector = collector;
}
/**
* 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.
*/
private void computeKeywordsAndContext() {
if (fKeywordProposals == null) {
fKeywordProposals = new IDartCompletionProposal[0];
}
}
/**
* 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) {
fRHSHistory = ContentAssistHistory.EMPTY_HISTORY;
}
return fRHSHistory;
}
}