/*
* Copyright (c) 2014, 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.internal.text.completion;
import com.google.dart.tools.core.DartCore;
import com.google.dart.tools.core.completion.DartSuggestionReceiver;
import com.google.dart.tools.ui.internal.text.dart.DartServerInformationalProposal;
import com.google.dart.tools.ui.internal.text.dart.DartServerProposal;
import com.google.dart.tools.ui.text.dart.CompletionProposalComparator;
import org.dartlang.analysis.server.protocol.CompletionSuggestion;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* The {@link DartServerProposalCollector} consumes information received from the server by the
* {@link DartSuggestionReceiver} and produces a collection of completion proposals.
*/
public class DartServerProposalCollector {
private final boolean auto;
private final int replacementOffset;
private final int replacementLength;
private final List<CompletionSuggestion> suggestions;
private final boolean isComplete;
private ArrayList<ICompletionProposal> proposals;
public DartServerProposalCollector(boolean auto, DartSuggestionReceiver receiver) {
this(
auto,
receiver.getReplacementOffset(),
receiver.getReplacementLength(),
receiver.getSuggestions(),
receiver.isComplete());
}
public DartServerProposalCollector(boolean auto, int replacementOffset, int replacementLength,
List<CompletionSuggestion> suggestions, boolean isComplete) {
this.auto = auto;
this.replacementOffset = replacementOffset;
this.replacementLength = replacementLength;
this.suggestions = suggestions;
this.isComplete = isComplete;
}
/**
* Build the list of proposals from the supplied suggestions. This can be called on a background
* thread so that code completion initialization does not block the UI.
*
* @return {@code true} if proposals should be displayed, else {@code false}
*/
public boolean computeAndSortProposals() {
proposals = new ArrayList<ICompletionProposal>();
if (!DartCore.getAnalysisServer().isSocketOpen()) {
proposals.add(DartServerInformationalProposal.SERVER_DEAD);
return !auto; // Do not display message if auto '.' triggered the completion request
}
if (suggestions == null) {
proposals.add(DartServerInformationalProposal.NO_RESPONSE);
return !auto;
}
if (suggestions.size() == 0) {
proposals.add(isComplete ? DartServerInformationalProposal.NO_RESULTS_COMPLETE
: DartServerInformationalProposal.NO_RESULTS_TIMED_OUT);
return !auto;
}
for (CompletionSuggestion suggestion : suggestions) {
proposals.add(new DartServerProposal(this, suggestion));
}
Collections.sort(proposals, new CompletionProposalComparator());
if (!isComplete) {
proposals.add(Math.min(proposals.size(), 9), DartServerInformationalProposal.PARTIAL_RESULTS);
}
return true;
}
/**
* Called on the UI thread to filter the proposals based upon the current document text.
*/
public void filterProposals(IDocument document, int offset) {
ArrayList<ICompletionProposal> filtered = new ArrayList<ICompletionProposal>();
ArrayList<ICompletionProposal> informational = new ArrayList<ICompletionProposal>();
for (ICompletionProposal p : proposals) {
if (p instanceof DartServerProposal
&& ((DartServerProposal) p).validate(document, offset, null)) {
filtered.add(p);
} else if (p instanceof DartServerInformationalProposal) {
informational.add(p);
}
}
filtered.addAll(Math.min(filtered.size(), 9), informational);
if (filtered.isEmpty()) {
filtered.add(DartServerInformationalProposal.NO_RESULTS_COMPLETE);
}
proposals = filtered;
}
/**
* Return the suggestion exactly matching the specified text or {@code null} if none found.
*
* @param text the text to be matched (not {@code null})
* @return the suggestion or {@code null}
*/
public DartServerProposal getExactMatch(String text) {
for (ICompletionProposal p : proposals) {
if (p instanceof DartServerProposal) {
if (text.equals(((DartServerProposal) p).getCompletionSelector())) {
return (DartServerProposal) p;
}
}
}
return null;
}
/**
* Return the proposals or {@code null} if {@link #computeAndSortProposals()} has not been called
* or was called but returned {@code false}.
*/
public List<ICompletionProposal> getProposals() {
return proposals;
}
public int getReplacementLength() {
return replacementLength;
}
public int getReplacementOffset() {
return replacementOffset;
}
}