Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

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

Issue 2468493004: DevTools: Consolidate completion code into JavaScriptAutocomplete.js (Closed)
Patch Set: merge Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 WebInspector.JavaScriptAutocomplete = {};
6
7 /**
8 * @param {!Element} proxyElement
9 * @param {!Range} wordRange
10 * @param {boolean} force
11 * @param {function(!Array.<string>, number=)} completionsReadyCallback
12 */
13 WebInspector.JavaScriptAutocomplete.completionsForTextPromptInCurrentContext = f unction(proxyElement, wordRange, force, completionsReadyCallback)
14 {
15 var expressionRange = wordRange.cloneRange();
16 expressionRange.collapse(true);
17 expressionRange.setStartBefore(proxyElement);
18 WebInspector.JavaScriptAutocomplete.completionsForTextInCurrentContext(expre ssionRange.toString(), wordRange.toString(), force).then(completionsReadyCallbac k);
19 };
20
21 /**
22 * @param {string} text
23 * @param {string} completionsPrefix
24 * @param {boolean=} force
25 * @return {!Promise<!Array<string>>}
26 */
27 WebInspector.JavaScriptAutocomplete.completionsForTextInCurrentContext = functio n(text, completionsPrefix, force)
28 {
29 var index;
30 var stopChars = new Set(" =:({;,!+-*/&|^<>`".split(""));
31 for (index = text.length - 1; index >= 0; index--) {
32 // Pass less stop characters to rangeOfWord so the range will be a more complete expression.
33 if (stopChars.has(text.charAt(index)))
34 break;
35 }
36 var clippedExpression = text.substring(index + 1);
37 var bracketCount = 0;
38
39 index = clippedExpression.length - 1;
40 while (index >= 0) {
41 var character = clippedExpression.charAt(index);
42 if (character === "]")
43 bracketCount++;
44 // Allow an open bracket at the end for property completion.
45 if (character === "[" && index < clippedExpression.length - 1) {
46 bracketCount--;
47 if (bracketCount < 0)
48 break;
49 }
50 index--;
51 }
52 clippedExpression = clippedExpression.substring(index + 1);
53
54 return WebInspector.JavaScriptAutocomplete.completionsForExpression(clippedE xpression, completionsPrefix, force);
55 };
56
57
58 /**
59 * @param {string} expressionString
60 * @param {string} prefix
61 * @param {boolean=} force
62 * @return {!Promise<!Array<string>>}
63 */
64 WebInspector.JavaScriptAutocomplete.completionsForExpression = function(expressi onString, prefix, force)
65 {
66 var executionContext = WebInspector.context.flavor(WebInspector.ExecutionCon text);
67 if (!executionContext)
68 return Promise.resolve([]);
69
70 var lastIndex = expressionString.length - 1;
71
72 var dotNotation = (expressionString[lastIndex] === ".");
73 var bracketNotation = (expressionString[lastIndex] === "[");
74
75 if (dotNotation || bracketNotation)
76 expressionString = expressionString.substr(0, lastIndex);
77
78 // User is entering float value, do not suggest anything.
79 if (expressionString && !isNaN(expressionString))
80 return Promise.resolve([]);
81
82 if (!prefix && !expressionString && !force)
83 return Promise.resolve([]);
84
85 var fulfill;
86 var promise = new Promise(x => fulfill = x);
87
88 if (!expressionString && executionContext.debuggerModel.selectedCallFrame())
89 executionContext.debuggerModel.selectedCallFrame().variableNames(receive dPropertyNames);
90 else
91 executionContext.evaluate(expressionString, "completion", true, true, fa lse, false, false, evaluated);
92
93 return promise;
94 /**
95 * @param {?WebInspector.RemoteObject} result
96 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails
97 */
98 function evaluated(result, exceptionDetails)
99 {
100 if (!result || !!exceptionDetails) {
101 fulfill([]);
102 return;
103 }
104
105 /**
106 * @param {?WebInspector.RemoteObject} object
107 * @return {!Promise<?WebInspector.RemoteObject>}
108 */
109 function extractTarget(object)
110 {
111 if (!object)
112 return Promise.resolve(/** @type {?WebInspector.RemoteObject} */ (null));
113 if (object.type !== "object" || object.subtype !== "proxy")
114 return Promise.resolve(/** @type {?WebInspector.RemoteObject} */ (object));
115 return object.getOwnPropertiesPromise().then(extractTargetFromProper ties).then(extractTarget);
116 }
117
118 /**
119 * @param {!{properties: ?Array<!WebInspector.RemoteObjectProperty>, int ernalProperties: ?Array<!WebInspector.RemoteObjectProperty>}} properties
120 * @return {?WebInspector.RemoteObject}
121 */
122 function extractTargetFromProperties(properties)
123 {
124 var internalProperties = properties.internalProperties || [];
125 var target = internalProperties.find(property => property.name === " [[Target]]");
126 return target ? target.value : null;
127 }
128
129 /**
130 * @param {string=} type
131 * @return {!Object}
132 * @suppressReceiverCheck
133 * @this {Object}
134 */
135 function getCompletions(type)
136 {
137 var object;
138 if (type === "string")
139 object = new String("");
140 else if (type === "number")
141 object = new Number(0);
142 else if (type === "boolean")
143 object = new Boolean(false);
144 else
145 object = this;
146
147 var resultSet = { __proto__: null };
148 try {
149 for (var o = object; o; o = Object.getPrototypeOf(o)) {
150 if ((type === "array" || type === "typedarray") && o === obj ect && ArrayBuffer.isView(o) && o.length > 9999)
151 continue;
152 var names = Object.getOwnPropertyNames(o);
153 var isArray = Array.isArray(o);
154 for (var i = 0; i < names.length; ++i) {
155 // Skip array elements indexes.
156 if (isArray && /^[0-9]/.test(names[i]))
157 continue;
158 resultSet[names[i]] = true;
159 }
160 }
161 } catch (e) {
162 }
163 return resultSet;
164 }
165
166 /**
167 * @param {?WebInspector.RemoteObject} object
168 */
169 function completionsForObject(object)
170 {
171 if (!object)
172 receivedPropertyNames(null);
173 else if (object.type === "object" || object.type === "function")
174 object.callFunctionJSON(getCompletions, [WebInspector.RemoteObje ct.toCallArgument(object.subtype)], receivedPropertyNames);
175 else if (object.type === "string" || object.type === "number" || obj ect.type === "boolean")
176 executionContext.evaluate("(" + getCompletions + ")(\"" + result .type + "\")", "completion", false, true, true, false, false, receivedPropertyNa mesFromEval);
177 }
178
179 extractTarget(result).then(completionsForObject);
180 }
181
182 /**
183 * @param {?WebInspector.RemoteObject} result
184 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails
185 */
186 function receivedPropertyNamesFromEval(result, exceptionDetails)
187 {
188 executionContext.target().runtimeAgent().releaseObjectGroup("completion" );
189 if (result && !exceptionDetails)
190 receivedPropertyNames(/** @type {!Object} */(result.value));
191 else
192 fulfill([]);
193 }
194
195 /**
196 * @param {?Object} propertyNames
197 */
198 function receivedPropertyNames(propertyNames)
199 {
200 executionContext.target().runtimeAgent().releaseObjectGroup("completion" );
201 if (!propertyNames) {
202 fulfill([]);
203 return;
204 }
205 var includeCommandLineAPI = (!dotNotation && !bracketNotation);
206 if (includeCommandLineAPI) {
207 const commandLineAPI = ["dir", "dirxml", "keys", "values", "profile" , "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear",
208 "getEventListeners", "debug", "undebug", "monitor", "unmonitor", "table", "$", "$$", "$x"];
209 for (var i = 0; i < commandLineAPI.length; ++i)
210 propertyNames[commandLineAPI[i]] = true;
211 }
212 fulfill(WebInspector.JavaScriptAutocomplete._completionsForPrefix(dotNot ation, bracketNotation, expressionString, prefix, Object.keys(propertyNames)));
213 }
214 };
215
216 /**
217 * @param {boolean} dotNotation
218 * @param {boolean} bracketNotation
219 * @param {string} expressionString
220 * @param {string} prefix
221 * @param {!Array.<string>} properties
222 * @return {!Array<string>}
223 */
224 WebInspector.JavaScriptAutocomplete._completionsForPrefix = function(dotNotation , bracketNotation, expressionString, prefix, properties) {
225 if (bracketNotation) {
226 if (prefix.length && prefix[0] === "'")
227 var quoteUsed = "'";
228 else
229 var quoteUsed = "\"";
230 }
231
232 var results = [];
233
234 if (!expressionString) {
235 const keywords = ["break", "case", "catch", "continue", "default", "dele te", "do", "else", "finally", "for", "function", "if", "in",
236 "instanceof", "new", "return", "switch", "this", "th row", "try", "typeof", "var", "void", "while", "with"];
237 properties = properties.concat(keywords);
238 }
239
240 properties.sort();
241
242 for (var i = 0; i < properties.length; ++i) {
243 var property = properties[i];
244
245 // Assume that all non-ASCII characters are letters and thus can be used as part of identifier.
246 if (dotNotation && !/^[a-zA-Z_$\u008F-\uFFFF][a-zA-Z0-9_$\u008F-\uFFFF]* $/.test(property))
247 continue;
248
249 if (bracketNotation) {
250 if (!/^[0-9]+$/.test(property))
251 property = quoteUsed + property.escapeCharacters(quoteUsed + "\\ ") + quoteUsed;
252 property += "]";
253 }
254
255 if (property.length < prefix.length)
256 continue;
257 if (prefix.length && !property.startsWith(prefix))
258 continue;
259
260 // Substitute actual newlines with newline characters. @see crbug.com/49 8421
261 results.push(property.split("\n").join("\\n"));
262 }
263 return results;
264 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698