Chromium Code Reviews| OLD | NEW |
|---|---|
| 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) | |
| 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) { | |
|
dgozman
2017/01/20 00:30:32
You always pass |true| as a second parameter.
einbinder
2017/01/23 22:40:53
Fixed.
| |
| 17 var index; | 29 var index; |
| 18 var stopChars = new Set('=:({;,!+-*/&|^<>`'.split('')); | 30 var stopChars = new Set('=:({;,!+-*/&|^<>`'.split('')); |
| 19 var whiteSpaceChars = new Set(' \r\n\t'.split('')); | 31 var whiteSpaceChars = new Set(' \r\n\t'.split('')); |
| 20 var continueChars = new Set('[. \r\n\t'.split('')); | 32 var continueChars = new Set('[. \r\n\t'.split('')); |
| 21 | 33 |
| 22 for (index = text.length - 1; index >= 0; index--) { | 34 for (index = text.length - 1; index >= 0; index--) { |
| 23 // Pass less stop characters to rangeOfWord so the range will be a more comp lete expression. | |
| 24 if (stopChars.has(text.charAt(index))) | 35 if (stopChars.has(text.charAt(index))) |
| 25 break; | 36 break; |
| 26 if (whiteSpaceChars.has(text.charAt(index)) && !continueChars.has(text.charA t(index - 1))) | 37 if (whiteSpaceChars.has(text.charAt(index)) && !continueChars.has(text.charA t(index - 1))) |
| 27 break; | 38 break; |
| 28 } | 39 } |
| 29 var clippedExpression = text.substring(index + 1).trim(); | 40 var clippedExpression = text.substring(index + 1).trim(); |
| 30 var bracketCount = 0; | 41 var bracketCount = 0; |
| 31 | 42 |
| 32 index = clippedExpression.length - 1; | 43 index = clippedExpression.length - 1; |
| 33 while (index >= 0) { | 44 while (index >= 0) { |
| 34 var character = clippedExpression.charAt(index); | 45 var character = clippedExpression.charAt(index); |
| 35 if (character === ']') | 46 if (character === ']') |
| 36 bracketCount++; | 47 bracketCount++; |
| 37 // Allow an open bracket at the end for property completion. | 48 // Allow an open bracket at the end for property completion. |
| 38 if (character === '[' && index < clippedExpression.length - 1) { | 49 if (character === '[' && (index < clippedExpression.length - 1 || !allowEndi ngBracket)) { |
| 39 bracketCount--; | 50 bracketCount--; |
| 40 if (bracketCount < 0) | 51 if (bracketCount < 0) |
| 41 break; | 52 break; |
| 42 } | 53 } |
| 43 index--; | 54 index--; |
| 44 } | 55 } |
| 45 clippedExpression = clippedExpression.substring(index + 1).trim(); | 56 return clippedExpression.substring(index + 1).trim(); |
| 46 | |
| 47 return Components.JavaScriptAutocomplete.completionsForExpression(clippedExpre ssion, query, force); | |
| 48 }; | 57 }; |
| 49 | 58 |
| 50 /** | 59 /** |
| 60 * @param {string} text | |
| 61 * @param {string} query | |
| 62 * @return {!Promise<!UI.SuggestBox.Suggestions>} | |
| 63 */ | |
| 64 Components.JavaScriptAutocomplete._mapCompletions = function(text, query) { | |
| 65 var mapMatch = text.match(/\.\s*[gs]et\s*\(\s*$/); | |
|
dgozman
2017/01/20 00:30:32
Support delete as well.
einbinder
2017/01/23 22:40:53
Done.
| |
| 66 var executionContext = UI.context.flavor(SDK.ExecutionContext); | |
| 67 if (!executionContext || !mapMatch) | |
| 68 return Promise.resolve([]); | |
| 69 | |
| 70 var clippedExpression = Components.JavaScriptAutocomplete._clipExpression(text .substring(0, mapMatch.index), true); | |
| 71 var fufill; | |
|
dgozman
2017/01/20 00:30:32
typo: fufill
einbinder
2017/01/23 22:40:54
Done.
| |
| 72 var promise = new Promise(x => fufill = x); | |
| 73 executionContext.evaluate(clippedExpression, 'completion', true, true, false, false, false, evaluated); | |
| 74 return promise; | |
| 75 | |
| 76 /** | |
| 77 * @param {?SDK.RemoteObject} result | |
| 78 * @param {!Protocol.Runtime.ExceptionDetails=} exceptionDetails | |
| 79 */ | |
| 80 function evaluated(result, exceptionDetails) { | |
| 81 if (!result || !!exceptionDetails || result.subtype !== 'map') { | |
| 82 fufill([]); | |
| 83 return; | |
| 84 } | |
| 85 result.getOwnPropertiesPromise().then(extractEntriesProperty); | |
| 86 } | |
| 87 | |
| 88 /** | |
| 89 * @param {!{properties: ?Array<!SDK.RemoteObjectProperty>, internalProperties : ?Array<!SDK.RemoteObjectProperty>}} properties | |
| 90 */ | |
| 91 function extractEntriesProperty(properties) { | |
| 92 var internalProperties = properties.internalProperties || []; | |
| 93 var entriesProperty = internalProperties.find(property => property.name === '[[Entries]]'); | |
| 94 if (!entriesProperty) { | |
| 95 fufill([]); | |
| 96 return; | |
| 97 } | |
| 98 entriesProperty.value.callFunctionJSONPromise(getEntries).then(keysObj => go tKeys(Object.keys(keysObj))); | |
| 99 } | |
| 100 | |
| 101 /** | |
| 102 * @suppressReceiverCheck | |
| 103 * @this {!Array<{key:?, value:?}>} | |
| 104 * @return {!Object} | |
| 105 */ | |
| 106 function getEntries() { | |
| 107 var result = {__proto__: null}; | |
| 108 for (var i = 0; i < this.length; i++) { | |
| 109 if (typeof this[i].key === 'string') | |
| 110 result[this[i].key] = true; | |
| 111 } | |
| 112 return result; | |
| 113 } | |
| 114 | |
| 115 /** | |
| 116 * @param {!Array<string>} rawKeys | |
| 117 */ | |
| 118 function gotKeys(rawKeys) { | |
| 119 var caseSensitivePrefix = []; | |
| 120 var caseInsensitivePrefix = []; | |
| 121 var caseSensitiveAnywhere = []; | |
| 122 var caseInsensitiveAnywhere = []; | |
| 123 var quoteChar = '"'; | |
| 124 if (query.startsWith('\'')) | |
| 125 quoteChar = '\''; | |
| 126 var endChar = ')'; | |
| 127 if (mapMatch[0].indexOf('s') !== -1) | |
| 128 endChar = ', '; | |
| 129 | |
| 130 var keys = rawKeys.sort(String.naturalOrderComparator).map(key => quoteChar + key + quoteChar + endChar); | |
| 131 | |
| 132 for (var key of keys) { | |
| 133 if (key.length < query.length) | |
| 134 continue; | |
| 135 if (query.length && key.toLowerCase().indexOf(query.toLowerCase()) === -1) | |
| 136 continue; | |
| 137 // Substitute actual newlines with newline characters. @see crbug.com/4984 21 | |
| 138 var title = key.split('\n').join('\\n'); | |
| 139 | |
| 140 if (key.startsWith(query)) | |
| 141 caseSensitivePrefix.push({title: title, priority: 4}); | |
| 142 else if (key.toLowerCase().startsWith(query.toLowerCase())) | |
| 143 caseInsensitivePrefix.push({title: title, priority: 3}); | |
| 144 else if (key.indexOf(query) !== -1) | |
| 145 caseSensitiveAnywhere.push({title: title, priority: 2}); | |
| 146 else | |
| 147 caseInsensitiveAnywhere.push({title: title, priority: 1}); | |
| 148 } | |
| 149 var suggestions = caseSensitivePrefix.concat(caseInsensitivePrefix, caseSens itiveAnywhere, caseInsensitiveAnywhere); | |
| 150 if (suggestions.length) | |
| 151 suggestions[0].subtitle = 'Keys'; | |
|
dgozman
2017/01/20 00:30:32
UIString('Keys')
einbinder
2017/01/23 22:40:54
Done.
| |
| 152 fufill(suggestions); | |
| 153 } | |
| 154 }; | |
| 155 | |
| 156 /** | |
| 51 * @param {string} expressionString | 157 * @param {string} expressionString |
| 52 * @param {string} query | 158 * @param {string} query |
| 53 * @param {boolean=} force | 159 * @param {boolean=} force |
| 54 * @return {!Promise<!UI.SuggestBox.Suggestions>} | 160 * @return {!Promise<!UI.SuggestBox.Suggestions>} |
| 55 */ | 161 */ |
| 56 Components.JavaScriptAutocomplete.completionsForExpression = function(expression String, query, force) { | 162 Components.JavaScriptAutocomplete.completionsForExpression = function(expression String, query, force) { |
| 57 var executionContext = UI.context.flavor(SDK.ExecutionContext); | 163 var executionContext = UI.context.flavor(SDK.ExecutionContext); |
| 58 if (!executionContext) | 164 if (!executionContext) |
| 59 return Promise.resolve([]); | 165 return Promise.resolve([]); |
| 60 | 166 |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 function itemComparator(a, b) { | 449 function itemComparator(a, b) { |
| 344 var aStartsWithUnderscore = a.startsWith('_'); | 450 var aStartsWithUnderscore = a.startsWith('_'); |
| 345 var bStartsWithUnderscore = b.startsWith('_'); | 451 var bStartsWithUnderscore = b.startsWith('_'); |
| 346 if (aStartsWithUnderscore && !bStartsWithUnderscore) | 452 if (aStartsWithUnderscore && !bStartsWithUnderscore) |
| 347 return 1; | 453 return 1; |
| 348 if (bStartsWithUnderscore && !aStartsWithUnderscore) | 454 if (bStartsWithUnderscore && !aStartsWithUnderscore) |
| 349 return -1; | 455 return -1; |
| 350 return String.naturalOrderComparator(a, b); | 456 return String.naturalOrderComparator(a, b); |
| 351 } | 457 } |
| 352 }; | 458 }; |
| OLD | NEW |