diff options
Diffstat (limited to 'org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AsyncCompletionProposalPopup.java')
-rw-r--r-- | org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AsyncCompletionProposalPopup.java | 170 |
1 files changed, 112 insertions, 58 deletions
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AsyncCompletionProposalPopup.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AsyncCompletionProposalPopup.java index b1a02d8a193..26f260d4ac4 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AsyncCompletionProposalPopup.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/AsyncCompletionProposalPopup.java @@ -21,6 +21,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; import org.eclipse.osgi.util.NLS; @@ -148,79 +149,132 @@ class AsyncCompletionProposalPopup extends CompletionProposalPopup { fFilterOffset= fInvocationOffset; fLastCompletionOffset= fFilterOffset; // start invocation of processors as Futures, and make them populate the proposals upon completion - List<ICompletionProposal> computedProposals = Collections.synchronizedList(new ArrayList<>()); fFutures= buildCompletionFuturesOrJobs(fInvocationOffset); - List<CompletableFuture<Void>> populateFutures = new ArrayList<>(fFutures.size()); - for (CompletableFuture<List<ICompletionProposal>> future : fFutures) { - populateFutures.add(future.thenAccept(proposals -> - computedProposals.addAll(proposals) - )); - } + runFutures(fInvocationOffset, null, true, autoActivated, true); + } else { + fLastCompletionOffset= fFilterOffset; + handleRepeatedInvocation(); + } - long requestBeginningTimestamp = System.currentTimeMillis(); - long stillRemainingThreeshold = MAX_WAIT_IN_MS; - for (CompletableFuture<?> future : populateFutures) { - try { - future.get(stillRemainingThreeshold, TimeUnit.MILLISECONDS); - } catch (TimeoutException | ExecutionException | InterruptedException ex) { - // future failed or took more time than we want to wait - } - stillRemainingThreeshold = MAX_WAIT_IN_MS - (System.currentTimeMillis() - requestBeginningTimestamp); - if (stillRemainingThreeshold < 0) { - // we already spent too much time (more than MAX_WAIT_IN_MS), stop waiting. - break; - } + return getErrorMessage(); + } + + @Override + void handleRepeatedInvocation() { + cancelFutures(); + fFutures= buildCompletionFuturesOrJobs(fInvocationOffset); + runFutures(fInvocationOffset, null, false, false, false); + } + + private List<ICompletionProposal> runFutures(int offset, Consumer<List<ICompletionProposal>> callback, boolean createSelector, boolean autoActivated, boolean autoInsert) { + List<ICompletionProposal> computedProposals= Collections.synchronizedList(new ArrayList<>()); + List<CompletableFuture<Void>> populateFutures= new ArrayList<>(fFutures.size()); + for (CompletableFuture<List<ICompletionProposal>> future : fFutures) { + populateFutures.add(future.thenAccept(proposals -> computedProposals.addAll(proposals))); + } + + long requestBeginningTimestamp= System.currentTimeMillis(); + long stillRemainingThreeshold= MAX_WAIT_IN_MS; + for (CompletableFuture<?> future : populateFutures) { + try { + future.get(stillRemainingThreeshold, TimeUnit.MILLISECONDS); + } catch (TimeoutException | ExecutionException | InterruptedException ex) { + // future failed or took more time than we want to wait } - fComputedProposals = computedProposals; - if (stillRemainingThreeshold > 0) { // everything ready in time, go synchronous - int count= computedProposals.size(); - if (count == 0 && hideWhenNoProposals(autoActivated)) - return null; - - if (count == 1 && !autoActivated && canAutoInsert(computedProposals.get(0))) { - insertProposal(computedProposals.get(0), (char) 0, 0, fInvocationOffset); - hide(); - } else { + stillRemainingThreeshold= MAX_WAIT_IN_MS - (System.currentTimeMillis() - requestBeginningTimestamp); + if (stillRemainingThreeshold < 0) { + // we already spent too much time (more than MAX_WAIT_IN_MS), stop waiting. + break; + } + } + fComputedProposals= computedProposals; + if (stillRemainingThreeshold > 0) { // everything ready in time, go synchronous + int count= computedProposals.size(); + if (count == 0 && hideWhenNoProposals(autoActivated)) + return computedProposals; + + if (autoInsert && count == 1 && !autoActivated && canAutoInsert(computedProposals.get(0))) { + insertProposal(computedProposals.get(0), (char) 0, 0, offset); + hide(); + } else { + if (createSelector) { createProposalSelector(); + } + if (callback != null) { + callback.accept(computedProposals); + } else { setProposals(computedProposals, false); displayProposals(); } - } else { // processors took too much time, go asynchronous + } + } else { // processors took too much time, go asynchronous + if (createSelector) { createProposalSelector(); - ComputingProposal computingProposal= new ComputingProposal(fInvocationOffset, fFutures.size()); - computedProposals.add(0, computingProposal); - fComputedProposals = computedProposals; - setProposals(fComputedProposals, false); - Set<CompletableFuture<Void>> remaining = Collections.synchronizedSet(new HashSet<>(populateFutures)); - for (CompletableFuture<Void> populateFuture : populateFutures) { - populateFuture.thenRun(() -> { - remaining.removeIf(CompletableFuture::isDone); - computingProposal.setRemaining(remaining.size()); - if (remaining.isEmpty()) { - computedProposals.remove(computingProposal); - } - List<ICompletionProposal> newProposals = new ArrayList<>(computedProposals); - fComputedProposals = newProposals; - Display.getDefault().asyncExec(() -> { - if (!autoActivated && remaining.isEmpty() && newProposals.size() == 1 && canAutoInsert(newProposals.get(0))) { - if (Helper.okToUse(fProposalShell)) { - insertProposal(newProposals.get(0), (char) 0, 0, fInvocationOffset); - hide(); - } - return; + } + ComputingProposal computingProposal= new ComputingProposal(offset, fFutures.size()); + computedProposals.add(0, computingProposal); + setProposals(fComputedProposals, false); + Set<CompletableFuture<Void>> remaining= Collections.synchronizedSet(new HashSet<>(populateFutures)); + for (CompletableFuture<Void> populateFuture : populateFutures) { + populateFuture.thenRun(() -> { + remaining.removeIf(CompletableFuture::isDone); + computingProposal.setRemaining(remaining.size()); + if (remaining.isEmpty()) { + computedProposals.remove(computingProposal); + } + List<ICompletionProposal> newProposals= new ArrayList<>(computedProposals); + fComputedProposals= newProposals; + Display.getDefault().asyncExec(() -> { + if (autoInsert && !autoActivated && remaining.isEmpty() && newProposals.size() == 1 && canAutoInsert(newProposals.get(0))) { + if (Helper.okToUse(fProposalShell)) { + insertProposal(newProposals.get(0), (char) 0, 0, offset); + hide(); } + return; + } + if (remaining.isEmpty() && callback != null) { + callback.accept(newProposals); + } else { setProposals(newProposals, false); displayProposals(); - }); + } }); - } - displayProposals(); + }); } - } else { - fLastCompletionOffset= fFilterOffset; - handleRepeatedInvocation(); + displayProposals(); + } + return computedProposals; + } + + @Override + public String incrementalComplete() { + cancelFutures(); + if (Helper.okToUse(fProposalShell) && fFilteredProposals != null) { + return super.incrementalComplete(); } + final Control control= fContentAssistSubjectControlAdapter.getControl(); + + if (fKeyListener == null) + fKeyListener= new ProposalSelectionListener(); + + if (!Helper.okToUse(fProposalShell) && !control.isDisposed()) + fContentAssistSubjectControlAdapter.addKeyListener(fKeyListener); + fInvocationOffset= fContentAssistSubjectControlAdapter.getSelectedRange().x; + fFilterOffset= fInvocationOffset; + fLastCompletionOffset= fFilterOffset; + + fFutures= buildCompletionFuturesOrJobs(fInvocationOffset); + fFilteredProposals= runFutures(fInvocationOffset, (List<ICompletionProposal> proposals) -> { + ensureDocumentListenerInstalled(); + if (proposals.size() > 0 && completeCommonPrefix()) { + hide(); + } else { + fFilteredProposals= proposals; + setProposals(proposals, false); + displayProposals(); + } + }, true, false, true); return getErrorMessage(); } |