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

Side by Side Diff: Source/devtools/front_end/languages/LanguageService.js

Issue 1264133002: Devtools: [WIP] Implement enhanced devtools extension language APIs Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Small cleanups - prefer URIs to contentURLs, revert protocol unifications, remove lambdas Created 5 years, 4 months 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 2015 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 /**
6 * @interface
7 */
8 WebInspector.LanguageService = function(){};
9 WebInspector.LanguageService.prototype = {
10 /**
11 * @return {string}
12 */
13 name: function() { throw new Error("Not implemented"); },
14
15 /**
16 * @return {!Array<string>}
17 */
18 capabilities: function() { return []; }
19 }
20
21 /**
22 * The language service capabilities list determines what actions are added
23 * to the LanguageService and LanguageService.Handles objects, in addition
24 * to what methods are searched for on providers to fulfill those capabilities
25 */
26 WebInspector.LanguageService.Capabilities = {
27 Transpile: "transpile",
28 PopulateContextMenu: "populateContextMenu",
29 Completions: "completions",
30 DebuggerCompletions: "debuggerCompletions",
31 };
32
33 /**
34 * @constructor
35 * @extends {WebInspector.Object}
36 */
37 WebInspector.LanguageServiceManager = function() {
38 this._override = {};
39 this._servicesByMime = {};
40
41 for (var key in WebInspector.LanguageService.Capabilities) {
42 var actionName = WebInspector.LanguageService.Capabilities[key];
43 this._servicesByMime[Symbol.for(key)] = {};
44 WebInspector.LanguageService.prototype[actionName] = function() {};
45 }
46
47 var _this = this;
48 function makeHandlesChecker(key) {
49 var actionName = WebInspector.LanguageService.Capabilities[key];
50 return function(mime) {
51 var override = _this._override[actionName];
52 if (typeof override !== "undefined") {
53 return override;
54 }
55 var service = _this._servicesByMime[Symbol.for(key)][mime];
56 return service;
57 };
58 }
59
60 function makeCapabilityAction(key) {
61 var actionName = WebInspector.LanguageService.Capabilities[key];
62 return function(mime) {
63 var override = _this._override[actionName];
64 if (typeof override !== "undefined") {
65 if (typeof override === "boolean") {
66 if (override) {
67 return Promise.resolve();
68 } else {
69 return Promise.reject("No language service present to ha ndle \""+(key)+"\" for mime \""+(mime)+"\".");
70 }
71 }
72 return override[actionName].apply(override, Array.prototype.slic e.call(arguments, 1));
73 }
74 if (!_this.handles[actionName](mime)) {
75 return Promise.reject("No language service present to handle \"" +(key)+"\" for mime \""+(mime)+"\".");
76 }
77 var service = _this._servicesByMime[Symbol.for(key)][mime];
78 return service[actionName].apply(service, Array.prototype.slice.call (arguments, 1));
79 };
80 }
81
82 for (var key in WebInspector.LanguageService.Capabilities) {
83 _this.handles[WebInspector.LanguageService.Capabilities[key]] = makeHand lesChecker(key);
84 _this[WebInspector.LanguageService.Capabilities[key]] = makeCapabilityAc tion(key);
85 }
86 };
87
88 WebInspector.LanguageServiceManager.Events = {
89 ServiceAdded: "onServiceAdded",
90 InferredMimeUpdated: "onInferredMimeUpdated"
91 };
92
93 /**
94 * Stub external API here to satisfy closure compiler - actual implementations
95 * are done in the ctor above. Not sure if there's a better way to type this, wh ile
96 * still making it simple to 'declare' a new optional member to a service
97 */
98 WebInspector.LanguageServiceManager.prototype = {
99
100 handles: {
101 /**
102 * @param {string} mime
103 * @return {?WebInspector.LanguageService}
104 */
105 transpile: function(mime) {return null;},
106
107 /**
108 * @param {string} mime
109 * @return {?WebInspector.LanguageService}
110 */
111 populateContextMenu: function(mime) {return null;},
112
113 /**
114 * @param {string} mime
115 * @return {?WebInspector.LanguageService}
116 */
117 completions: function(mime) {return null;},
118
119 /**
120 * @param {string} mime
121 * @return {?WebInspector.LanguageService}
122 */
123 debuggerCompletions: function(mime) {return null;}
124 },
125
126 /**
127 * @param {!Array<string>} mimes
128 * @param {!WebInspector.LanguageService} service
129 */
130 register: function(mimes, service) {
131 for (var index = 0; index < mimes.length; index++) {
132 var mime = mimes[index];
133 for (var key in WebInspector.LanguageService.Capabilities) {
134 var capability = WebInspector.LanguageService.Capabilities[key];
135 if (service.capabilities().indexOf(capability) !== -1) {
136 this._servicesByMime[Symbol.for(key)][mime] = service;
137 }
138 }
139
140 this._servicesByMime[mime] = service;
141 }
142 this._onServiceAdded(service, mimes);
143 },
144
145 _onServiceAdded(service, mimes) {
146 this.dispatchEventToListeners(WebInspector.LanguageServiceManager.Events .ServiceAdded, {service, mimes});
147 },
148
149 /**
150 * @param {string} capability
151 * @param {!WebInspector.LanguageService=} override
152 */
153 disableContextualHandling: function(capability, override) {
154 this._override[capability] = override || false;
155 },
156
157 /**
158 * @param {string} capability
159 */
160 enableContextualHandling: function(capability) {
161 delete this._override[capability];
162 },
163
164 /**
165 * @param {string=} capability
166 * @return {!Array<!WebInspector.LanguageService>}
167 */
168 registered: function(capability) {
169 return [...new Set(Object.keys(capability ? this._servicesByMime[Symbol. for(capability)]||{} : this._servicesByMime).map((function(k){ return capability ? this._servicesByMime[Symbol.for(capability)][k] : this._servicesByMime[k]; }) .bind(this)))];
170 },
171
172 /**
173 * @param {string} mime
174 * @return {?WebInspector.LanguageService}
175 */
176 for: function(mime) {
177 return this._servicesByMime[mime];
178 },
179
180 /**
181 * @param {string} mime
182 * @param {string} input
183 * @param {?{source: string, line: number, column: number}=} location
184 * @return {!Promise<string>}
185 */
186 transpile: function(mime, input, location) {return Promise.reject();},
187
188 /**
189 * @param {string} mime
190 * @param {{source: string, line: number, column: number}} location
191 * @return {!Promise<!Array<{text: string, callback: !Function}>>}
192 */
193 populateContextMenu: function(mime, location) {return Promise.reject();},
194
195 /**
196 * @param {string} mime
197 * @param {{source: string, line: number, column: number}} location
198 * @param {string} prefix
199 * @return {!Promise<!Array<{text: string, details: !Promise<{detail: string , description: string}>}>>}
200 */
201 completions: function(mime, location, prefix) {return Promise.reject();},
202
203 /**
204 * @param {string} mime
205 * @param {string} content
206 * @param {number} cursorOffset
207 * @param {string} prefix
208 * @param {{source: string, line: number, column: number}=} context
209 * @return {!Promise<!Array<{text: string, details: !Promise<{detail: string , description: string}>}>>}
210 */
211 debuggerCompletions: function(mime, content, cursorOffset, prefix, context) {return Promise.reject();},
212
213 updateInferredMime: function() {
214 this.dispatchEventToListeners(WebInspector.LanguageServiceManager.Events .InferredMimeUpdated);
215 },
216
217 __proto__: WebInspector.Object.prototype
218 };
219
220 /**
221 * @constructor
222 * @implements {WebInspector.LanguageService}
223 */
224 WebInspector.LanguageService.CallbackDelegate = function(name, capabilities) {
225 this._name = name;
226 this._capabilities = [];
227
228 for (var key in WebInspector.LanguageService.Capabilities) {
229 var actionName = WebInspector.LanguageService.Capabilities[key];
230 if (!!capabilities[actionName]) {
231 this.appendActionHandler(actionName, capabilities[actionName]);
232 }
233 }
234 };
235
236 WebInspector.LanguageService.CallbackDelegate.prototype = {
237 /**
238 * @override
239 * @return {string}
240 */
241 name: function() {
242 return this._name;
243 },
244
245 /**
246 * Given an action and a function expecting a callback for
247 * its final argument, modifies it to return a promise and
248 * appends it to the language service
249 *
250 * @param {string} capability
251 * @param {!Function} func
252 */
253 appendActionHandler: function(capability, func) {
254 var _this = this;
255 this._capabilities.push(capability);
256 this[capability] = function() {
257 var args = arguments;
258 return new Promise(function(resolve, reject) {
259 func.call(_this, ...args, resolve);
260 });
261 };
262 },
263
264 /**
265 * @override
266 * @return {!Array<string>}
267 */
268 capabilities: function() {
269 return this._capabilities;
270 }
271 };
272
273 /**
274 * @constructor
275 * @param {!Element} selectElement
276 * @param {!Array<string>} capabilities
277 */
278 WebInspector.LanguageServiceModel = function(selectElement, capabilities) {
279 this._capabilities = capabilities;
280 this._selectElement = selectElement;
281 var newOption = createElement("option");
282 newOption.__type = WebInspector.LanguageServiceModel.OptionType.Inferred;
283 newOption.text = WebInspector.UIString("%s (inferred)", WebInspector.UIStrin g("javascript"));
284 this._selectElement.appendChild(newOption);
285
286 var jsOption = createElement("option");
287 jsOption.__type = WebInspector.LanguageServiceModel.OptionType.Builtin;
288 jsOption.text = WebInspector.UIString("javascript");
289 this._selectElement.appendChild(jsOption);
290
291 WebInspector.languageService.registered().forEach((function(service) {
292 this.addOption(service);
293 }).bind(this));
294
295 WebInspector.languageService.addEventListener(WebInspector.LanguageServiceMa nager.Events.ServiceAdded, this._onServiceAdded, this);
296 WebInspector.languageService.addEventListener(WebInspector.LanguageServiceMa nager.Events.InferredMimeUpdated, this._onViewSelected, this);
297 this._selectElement.addEventListener("change", this._languageServiceChanged. bind(this), false);
298 };
299
300 WebInspector.LanguageServiceModel.prototype = {
301 /**
302 * @param {!WebInspector.LanguageService} service
303 */
304 addOption: function(service) {
305 var newOption = createElement("option");
306 newOption.__service = service;
307 newOption.__type = WebInspector.LanguageServiceModel.OptionType.External ;
308 newOption.text = service.name();
309 this._selectElement.appendChild(newOption);
310 },
311
312 _onServiceAdded: function(evt) {
313 var service = /** @type {!WebInspector.LanguageService} */(evt.data.serv ice);
314 this.addOption(service);
315 },
316
317 _onViewSelected: function(evt) {
318 var mime = WebInspector.ResourceType.fromActivePanel();
319 var service = WebInspector.languageService.for(mime);
320 var name = WebInspector.UIString("javascript");
321 if (service) {
322 name = service.name();
323 }
324 var opts = this._selectElement.options;
325 for (var i = 0; i < opts.length; i++) {
326 var option = opts[i];
327 if (option.__type === WebInspector.LanguageServiceModel.OptionType.I nferred) {
328 option.text = WebInspector.UIString("%s (inferred)", name);
329 }
330 }
331 },
332
333 _languageServiceChanged: function() {
334 var option = this._selectedOption();
335 switch(option.__type) {
336 case WebInspector.LanguageServiceModel.OptionType.Inferred:
337 this._capabilities.forEach(function(c) {
338 WebInspector.languageService.enableContextualHandling(c);
339 });
340 break;
341 case WebInspector.LanguageServiceModel.OptionType.Builtin:
342 this._capabilities.forEach(function(c) {
343 WebInspector.languageService.disableContextualHandling(c);
344 });
345 break;
346 case WebInspector.LanguageServiceModel.OptionType.External:
347 this._capabilities.forEach(function(c) {
348 WebInspector.languageService.disableContextualHandling(c, option .__service);
349 });
350 break;
351 default:
352 break;
353 }
354 },
355
356 /**
357 * @return {?Element}
358 */
359 _selectedOption: function()
360 {
361 if (this._selectElement.selectedIndex >= 0)
362 return this._selectElement[this._selectElement.selectedIndex];
363 return null;
364 }
365 };
366
367 WebInspector.LanguageServiceModel.OptionType = {
368 Inferred: "Inferred",
369 Builtin: "Builtin",
370 External: "External"
371 };
372
373 WebInspector.languageService = new WebInspector.LanguageServiceManager();
OLDNEW
« no previous file with comments | « Source/devtools/front_end/inspector.json ('k') | Source/devtools/front_end/languages/MultiLingualExecutionContext.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698