Index: third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js b/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js |
index b9aad4f0374aa194fbc76020491617051507f0b3..b56b4309b02f925f33e0086bc3676db3d1a611c9 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js |
+++ b/third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js |
@@ -14,13 +14,24 @@ Components.JavaScriptAutocomplete.CompletionGroup; |
* @return {!Promise<!UI.SuggestBox.Suggestions>} |
*/ |
Components.JavaScriptAutocomplete.completionsForTextInCurrentContext = function(text, query, force) { |
+ var clippedExpression = Components.JavaScriptAutocomplete._clipExpression(text, true); |
+ var mapCompletionsPromise = Components.JavaScriptAutocomplete._mapCompletions(text, query); |
+ return Components.JavaScriptAutocomplete.completionsForExpression(clippedExpression, query, force) |
+ .then(completions => mapCompletionsPromise.then(mapCompletions => mapCompletions.concat(completions))); |
+}; |
+ |
+/** |
+ * @param {string} text |
+ * @param {boolean=} allowEndingBracket |
+ * @return {string} |
+ */ |
+Components.JavaScriptAutocomplete._clipExpression = function(text, allowEndingBracket) { |
var index; |
var stopChars = new Set('=:({;,!+-*/&|^<>`'.split('')); |
var whiteSpaceChars = new Set(' \r\n\t'.split('')); |
var continueChars = new Set('[. \r\n\t'.split('')); |
for (index = text.length - 1; index >= 0; index--) { |
- // Pass less stop characters to rangeOfWord so the range will be a more complete expression. |
if (stopChars.has(text.charAt(index))) |
break; |
if (whiteSpaceChars.has(text.charAt(index)) && !continueChars.has(text.charAt(index - 1))) |
@@ -35,16 +46,110 @@ Components.JavaScriptAutocomplete.completionsForTextInCurrentContext = function( |
if (character === ']') |
bracketCount++; |
// Allow an open bracket at the end for property completion. |
- if (character === '[' && index < clippedExpression.length - 1) { |
+ if (character === '[' && (index < clippedExpression.length - 1 || !allowEndingBracket)) { |
bracketCount--; |
if (bracketCount < 0) |
break; |
} |
index--; |
} |
- clippedExpression = clippedExpression.substring(index + 1).trim(); |
+ return clippedExpression.substring(index + 1).trim(); |
+}; |
+ |
+/** |
+ * @param {string} text |
+ * @param {string} query |
+ * @return {!Promise<!UI.SuggestBox.Suggestions>} |
+ */ |
+Components.JavaScriptAutocomplete._mapCompletions = function(text, query) { |
+ var mapMatch = text.match(/\.\s*[gs]et\s*\(\s*$/); |
+ var executionContext = UI.context.flavor(SDK.ExecutionContext); |
+ if (!executionContext || !mapMatch) |
+ return Promise.resolve([]); |
+ |
+ var clippedExpression = Components.JavaScriptAutocomplete._clipExpression(text.substring(0, mapMatch.index), true); |
+ var fufill; |
+ var promise = new Promise(x => fufill = x); |
+ executionContext.evaluate(clippedExpression, 'completion', true, true, false, false, false, evaluated); |
+ return promise; |
+ |
+ /** |
+ * @param {?SDK.RemoteObject} result |
+ * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails |
+ */ |
+ function evaluated(result, exceptionDetails) { |
+ if (!result || !!exceptionDetails || result.subtype !== 'map') { |
+ fufill([]); |
+ return; |
+ } |
+ result.getOwnPropertiesPromise().then(extractEntriesProperty); |
luoe
2017/01/19 18:54:21
Can we make this a method in RemoteObject.js as ge
einbinder
2017/01/19 20:21:38
This only gets the entries from maps with keys as
|
+ } |
+ |
+ /** |
+ * @param {!{properties: ?Array<!SDK.RemoteObjectProperty>, internalProperties: ?Array<!SDK.RemoteObjectProperty>}} properties |
+ */ |
+ function extractEntriesProperty(properties) { |
+ var internalProperties = properties.internalProperties || []; |
+ var entriesProperty = internalProperties.find(property => property.name === '[[Entries]]'); |
+ if (!entriesProperty) { |
+ fufill([]); |
+ return; |
+ } |
+ entriesProperty.value.callFunctionJSONPromise(getEntries).then(keysObj => gotKeys(Object.keys(keysObj))); |
+ } |
- return Components.JavaScriptAutocomplete.completionsForExpression(clippedExpression, query, force); |
+ /** |
+ * @suppressReceiverCheck |
+ * @this {!Array<{key:?, value:?}>} |
luoe
2017/01/19 18:54:20
@return ?
einbinder
2017/01/19 20:21:38
Done.
|
+ */ |
+ function getEntries() { |
+ var result = {__proto__: null}; |
+ for (var i = 0; i < this.length; i++) { |
+ if (typeof this[i].key === 'string') |
+ result[this[i].key] = true; |
+ } |
+ return result; |
+ } |
+ |
+ /** |
+ * @param {!Array<string>} rawKeys |
+ */ |
+ function gotKeys(rawKeys) { |
+ var caseSensitivePrefix = []; |
+ var caseInsensitivePrefix = []; |
+ var caseSensitiveAnywhere = []; |
+ var caseInsensitiveAnywhere = []; |
+ var qouteChar = '"'; |
luoe
2017/01/19 18:54:20
nit: quoteChar
einbinder
2017/01/19 20:21:38
Done.
|
+ if (query.startsWith('\'')) |
+ qouteChar = '\''; |
+ var endChar = ')'; |
+ if (mapMatch[0].indexOf('s') !== -1) |
+ endChar = ', '; |
+ |
+ var keys = rawKeys.sort(String.naturalOrderComparator).map(key => qouteChar + key + qouteChar + endChar); |
+ |
+ for (var key of keys) { |
+ if (key.length < query.length) |
+ continue; |
+ if (query.length && key.toLowerCase().indexOf(query.toLowerCase()) === -1) |
+ continue; |
+ // Substitute actual newlines with newline characters. @see crbug.com/498421 |
+ var title = key.split('\n').join('\\n'); |
+ |
+ if (key.startsWith(query)) |
+ caseSensitivePrefix.push({title: title, priority: 4}); |
+ else if (key.toLowerCase().startsWith(query.toLowerCase())) |
+ caseInsensitivePrefix.push({title: title, priority: 3}); |
+ else if (key.indexOf(query) !== -1) |
+ caseSensitiveAnywhere.push({title: title, priority: 2}); |
+ else |
+ caseInsensitiveAnywhere.push({title: title, priority: 1}); |
+ } |
+ var suggestions = caseSensitivePrefix.concat(caseInsensitivePrefix, caseSensitiveAnywhere, caseInsensitiveAnywhere); |
+ if (suggestions.length) |
+ suggestions[0].subtitle = 'Keys'; |
+ fufill(suggestions); |
+ } |
}; |
/** |