From d945f5f1e4e7af6743e06a54f68568df3d27d460 Mon Sep 17 00:00:00 2001 From: YellowAfterlife Date: Thu, 29 Apr 2021 16:38:13 +0300 Subject: [PATCH] Immediate-return optimization for Autocomplete.updateCompletions (#4482) --- lib/ace/autocomplete.js | 55 +++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index 07659197954..dde0afd04ab 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -293,22 +293,16 @@ var Autocomplete = function() { // Save current gatherCompletions session, session is close when a match is insert var _id = this.gatherCompletionsId; - this.gatherCompletions(this.editor, function(err, results) { - // Only detach if result gathering is finished - var detachIfFinished = function() { - if (!results.finished) return; - return this.detach(); - }.bind(this); - var prefix = results.prefix; - var matches = results && results.matches; + // Only detach if result gathering is finished + var detachIfFinished = function(results) { + if (!results.finished) return; + return this.detach(); + }.bind(this); - if (!matches || !matches.length) - return detachIfFinished(); - - // Wrong prefix or wrong session -> ignore - if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId) - return; + var processResults = function(results) { + var prefix = results.prefix; + var matches = results.matches; this.completions = new FilteredList(matches); @@ -320,18 +314,47 @@ var Autocomplete = function() { // No results if (!filtered.length) - return detachIfFinished(); + return detachIfFinished(results); // One result equals to the prefix if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet) - return detachIfFinished(); + return detachIfFinished(results); // Autoinsert if one result if (this.autoInsert && filtered.length == 1 && results.finished) return this.insertMatch(filtered[0]); this.openPopup(this.editor, prefix, keepPopupPosition); + }.bind(this); + + var isImmediate = true; + var immediateResults = null; + this.gatherCompletions(this.editor, function(err, results) { + var prefix = results.prefix; + var matches = results && results.matches; + + if (!matches || !matches.length) + return detachIfFinished(results); + + // Wrong prefix or wrong session -> ignore + if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId) + return; + + // If multiple completers return their results immediately, we want to process them together + if (isImmediate) { + immediateResults = results; + return; + } + + processResults(results); }.bind(this)); + + isImmediate = false; + if (immediateResults) { + var results = immediateResults; + immediateResults = null; + processResults(results); + } }; this.cancelContextMenu = function() {