Chromium Code Reviews

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/components/JavaScriptAutocomplete.js

Issue 2639703002: DevTools: Console: Provide autocompletions for Maps (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 Components.JavaScriptAutocomplete = {}; 5 Components.JavaScriptAutocomplete = {};
6 6
7 /** @typedef {{title:(string|undefined), items:Array<string>}} */ 7 /** @typedef {{title:(string|undefined), items:Array<string>}} */
8 Components.JavaScriptAutocomplete.CompletionGroup; 8 Components.JavaScriptAutocomplete.CompletionGroup;
9 9
10 /** 10 /**
11 * @param {string} text 11 * @param {string} text
12 * @param {string} query 12 * @param {string} query
13 * @param {boolean=} force 13 * @param {boolean=} force
14 * @return {!Promise<!UI.SuggestBox.Suggestions>} 14 * @return {!Promise<!UI.SuggestBox.Suggestions>}
15 */ 15 */
16 Components.JavaScriptAutocomplete.completionsForTextInCurrentContext = function( text, query, force) { 16 Components.JavaScriptAutocomplete.completionsForTextInCurrentContext = function( text, query, force) {
17 var clippedExpression = Components.JavaScriptAutocomplete._clipExpression(text , true);
18 var mapCompletionsPromise = Components.JavaScriptAutocomplete._mapCompletions( text, query);
19 return Components.JavaScriptAutocomplete.completionsForExpression(clippedExpre ssion, query, force)
dgozman 2017/01/18 17:02:39 Should this be Promise.all instead?
einbinder 2017/01/19 01:20:40 The promise has already been triggered. Promise.al
20 .then(completions => mapCompletionsPromise.then(mapCompletions => mapCompl etions.concat(completions)));
21 };
22
23 /**
24 * @param {string} text
25 * @param {boolean=} allowEndingBracket
26 * @return {string}
27 */
28 Components.JavaScriptAutocomplete._clipExpression = function(text, allowEndingBr acket) {
17 var index; 29 var index;
18 var stopChars = new Set(' =:({;,!+-*/&|^<>`'.split('')); 30 var stopChars = new Set(' =:({;,!+-*/&|^<>`'.split(''));
19 for (index = text.length - 1; index >= 0; index--) { 31 for (index = text.length - 1; index >= 0; index--) {
20 // Pass less stop characters to rangeOfWord so the range will be a more comp lete expression.
21 if (stopChars.has(text.charAt(index))) 32 if (stopChars.has(text.charAt(index)))
22 break; 33 break;
23 } 34 }
24 var clippedExpression = text.substring(index + 1); 35 var clippedExpression = text.substring(index + 1);
25 var bracketCount = 0; 36 var bracketCount = 0;
26 37
27 index = clippedExpression.length - 1; 38 index = clippedExpression.length - 1;
28 while (index >= 0) { 39 while (index >= 0) {
29 var character = clippedExpression.charAt(index); 40 var character = clippedExpression.charAt(index);
30 if (character === ']') 41 if (character === ']')
31 bracketCount++; 42 bracketCount++;
32 // Allow an open bracket at the end for property completion. 43 // Allow an open bracket at the end for property completion.
33 if (character === '[' && index < clippedExpression.length - 1) { 44 if (character === '[' && (index < clippedExpression.length - 1 || !allowEndi ngBracket)) {
34 bracketCount--; 45 bracketCount--;
35 if (bracketCount < 0) 46 if (bracketCount < 0)
36 break; 47 break;
37 } 48 }
38 index--; 49 index--;
39 } 50 }
40 clippedExpression = clippedExpression.substring(index + 1); 51 return clippedExpression.substring(index + 1);
41
42 return Components.JavaScriptAutocomplete.completionsForExpression(clippedExpre ssion, query, force);
43 }; 52 };
44 53
45 /** 54 /**
55 * @param {string} text
56 * @param {string} query
57 * @return {!Promise<!UI.SuggestBox.Suggestions>}
58 */
59 Components.JavaScriptAutocomplete._mapCompletions = function(text, query) {
60 var mapMatch = text.match(/\.\s*[gs]et\s*\(\s*$/);
61 var executionContext = UI.context.flavor(SDK.ExecutionContext);
62 if (!executionContext || !mapMatch)
63 return Promise.resolve([]);
64
65 var clippedExpression = Components.JavaScriptAutocomplete._clipExpression(text .substring(0, mapMatch.index), true);
66 var fufill;
67 var promise = new Promise(x => fufill = x);
68 executionContext.evaluate(clippedExpression, 'completion', true, true, false, true, false, evaluated);
69 return promise;
70
71 /**
72 * @param {?SDK.RemoteObject} result
dgozman 2017/01/18 17:02:39 indentation is off
einbinder 2017/01/19 01:20:40 Fixed.
73 * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails
74 */
75 function evaluated(result, exceptionDetails) {
76 if (!result || !!exceptionDetails || !result.preview || result.preview.subty pe !== 'map') {
dgozman 2017/01/18 17:02:39 Don't use preview: - subtype is available in Remot
einbinder 2017/01/19 01:20:40 Done.
77 fufill([]);
78 return;
79 }
80
81 var caseSensitivePrefix = [];
82 var caseInsensitivePrefix = [];
83 var caseSensitiveAnywhere = [];
84 var caseInsensitiveAnywhere = [];
85 var qouteChar = '"';
86 if (query.startsWith('\''))
87 qouteChar = '\'';
88 var endChar = ')';
89 if (mapMatch[0].indexOf('s') !== -1)
90 endChar = ', ';
91 var keys = result.preview.entries.filter(entry => entry.key.type === 'string ')
92 .map(entry => entry.key.description)
93 .sort(String.naturalOrderComparator)
94 .map(key => qouteChar + key + qouteChar + endChar);
95
96 for (var key of keys) {
97 if (key.length < query.length)
98 continue;
99 if (query.length && key.toLowerCase().indexOf(query.toLowerCase()) === -1)
100 continue;
101 // Substitute actual newlines with newline characters. @see crbug.com/4984 21
102 var title = key.split('\n').join('\\n');
103
104 if (key.startsWith(query))
105 caseSensitivePrefix.push({title: title, priority: 4});
106 else if (key.toLowerCase().startsWith(query.toLowerCase()))
107 caseInsensitivePrefix.push({title: title, priority: 3});
108 else if (key.indexOf(query) !== -1)
109 caseSensitiveAnywhere.push({title: title, priority: 2});
110 else
111 caseInsensitiveAnywhere.push({title: title, priority: 1});
112 }
113 var suggestions = caseSensitivePrefix.concat(caseInsensitivePrefix, caseSens itiveAnywhere, caseInsensitiveAnywhere);
114 if (suggestions.length)
115 suggestions[0].subtitle = 'Keys';
116 fufill(suggestions);
117 }
118 };
119
120 /**
46 * @param {string} expressionString 121 * @param {string} expressionString
47 * @param {string} query 122 * @param {string} query
48 * @param {boolean=} force 123 * @param {boolean=} force
49 * @return {!Promise<!UI.SuggestBox.Suggestions>} 124 * @return {!Promise<!UI.SuggestBox.Suggestions>}
50 */ 125 */
51 Components.JavaScriptAutocomplete.completionsForExpression = function(expression String, query, force) { 126 Components.JavaScriptAutocomplete.completionsForExpression = function(expression String, query, force) {
52 var executionContext = UI.context.flavor(SDK.ExecutionContext); 127 var executionContext = UI.context.flavor(SDK.ExecutionContext);
53 if (!executionContext) 128 if (!executionContext)
54 return Promise.resolve([]); 129 return Promise.resolve([]);
55 130
(...skipping 285 matching lines...)
341 function itemComparator(a, b) { 416 function itemComparator(a, b) {
342 var aStartsWithUnderscore = a.startsWith('_'); 417 var aStartsWithUnderscore = a.startsWith('_');
343 var bStartsWithUnderscore = b.startsWith('_'); 418 var bStartsWithUnderscore = b.startsWith('_');
344 if (aStartsWithUnderscore && !bStartsWithUnderscore) 419 if (aStartsWithUnderscore && !bStartsWithUnderscore)
345 return 1; 420 return 1;
346 if (bStartsWithUnderscore && !aStartsWithUnderscore) 421 if (bStartsWithUnderscore && !aStartsWithUnderscore)
347 return -1; 422 return -1;
348 return String.naturalOrderComparator(a, b); 423 return String.naturalOrderComparator(a, b);
349 } 424 }
350 }; 425 };
OLDNEW

Powered by Google App Engine