Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Commit 3ca4f26

Browse files
committed
Expose code inspection providers for the extensions.
First go at inspectFile method. Removed Async.withTimeout from inspectFile() Separated getProvider and inspectFile logic, added usage of DocumentManager.getOpenDocumentForPath to inspectFile Modified run() to use new methods. Moved $problemsPanelTable event handlers from run() to htmlReady() for optimization. Fix the case when getCurrentDocument returns null. Check if current document hasn't changed while inspectFile was running remove async handling of provider.scanFile Refactored according to comments. Made provider response nullable again, removed the warning. Refactored getProvider to getProviderForPath and updated docs. Remove getProvider from exports.
1 parent 22dc671 commit 3ca4f26

1 file changed

Lines changed: 116 additions & 49 deletions

File tree

src/language/CodeInspection.js

Lines changed: 116 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ define(function (require, exports, module) {
4545
CommandManager = require("command/CommandManager"),
4646
DocumentManager = require("document/DocumentManager"),
4747
EditorManager = require("editor/EditorManager"),
48+
FileUtils = require("file/FileUtils"),
4849
LanguageManager = require("language/LanguageManager"),
4950
PreferencesManager = require("preferences/PreferencesManager"),
5051
PerfUtils = require("utils/PerfUtils"),
@@ -72,7 +73,6 @@ define(function (require, exports, module) {
7273
META: "problem_type_meta"
7374
};
7475

75-
7676
/**
7777
* @private
7878
* @type {PreferenceStorage}
@@ -100,6 +100,12 @@ define(function (require, exports, module) {
100100
*/
101101
var $problemsPanel;
102102

103+
/**
104+
* @private
105+
* @type {$.Element}
106+
*/
107+
var $problemsPanelTable;
108+
103109
/**
104110
* @private
105111
* @type {boolean}
@@ -145,7 +151,69 @@ define(function (require, exports, module) {
145151
}
146152
_providers[languageId] = provider;
147153
}
148-
154+
155+
/**
156+
* Returns a provider for given file path, if one is available.
157+
* Decision is made depending on the file extension.
158+
*
159+
* @param {!string} filePath
160+
* @return ?{{name:string, scanFile:function(string, string):?{!errors:Array, aborted:boolean}} provider
161+
*/
162+
function getProviderForPath(filePath) {
163+
return _providers[LanguageManager.getLanguageForPath(filePath).getId()];
164+
}
165+
166+
/**
167+
* Runs a file inspection over passed file, specifying a provider is optional.
168+
* This method doesn't update the Brackets UI, just provides inspection results.
169+
* These results will reflect any unsaved changes present in the file that is currently opened.
170+
*
171+
* @param {!FileEntry} fileEntry File that will be inspected for errors.
172+
* @param ?{{name:string, scanFile:function(string, string):?{!errors:Array, aborted:boolean}} provider
173+
* @return {$.Promise} a jQuery promise that will be resolved with ?{!errors:Array, aborted:boolean}
174+
*/
175+
function inspectFile(fileEntry, provider) {
176+
var response = new $.Deferred();
177+
provider = provider || getProviderForPath(fileEntry.fullPath);
178+
179+
if (!provider) {
180+
response.resolve(null);
181+
return response.promise();
182+
}
183+
184+
var doc = DocumentManager.getOpenDocumentForPath(fileEntry.fullPath),
185+
fileTextPromise;
186+
187+
if (doc) {
188+
fileTextPromise = new $.Deferred().resolve(doc.getText());
189+
} else {
190+
fileTextPromise = FileUtils.readAsText(fileEntry);
191+
}
192+
193+
fileTextPromise
194+
.done(function (fileText) {
195+
var result,
196+
perfTimerInspector = PerfUtils.markStart("CodeInspection '" + provider.name + "':\t" + fileEntry.fullPath);
197+
198+
try {
199+
result = provider.scanFile(fileText, fileEntry.fullPath);
200+
} catch (err) {
201+
console.error("[CodeInspection] Provider " + provider.name + " threw an error: " + err);
202+
response.reject(err);
203+
return;
204+
}
205+
206+
PerfUtils.addMeasurement(perfTimerInspector);
207+
response.resolve(result);
208+
})
209+
.fail(function (err) {
210+
console.error("[CodeInspection] Could not read file for inspection: " + fileEntry.fullPath);
211+
response.reject(err);
212+
});
213+
214+
return response.promise();
215+
}
216+
149217
/**
150218
* Run inspector applicable to current document. Updates status bar indicator and refreshes error list in
151219
* bottom panel.
@@ -159,30 +227,31 @@ define(function (require, exports, module) {
159227
return;
160228
}
161229

162-
var currentDoc = DocumentManager.getCurrentDocument();
163-
164-
var perfTimerDOM,
165-
perfTimerInspector;
166-
167-
var language = currentDoc ? LanguageManager.getLanguageForPath(currentDoc.file.fullPath) : "";
168-
var languageId = language && language.getId();
169-
var provider = language && _providers[languageId];
230+
var currentDoc = DocumentManager.getCurrentDocument(),
231+
provider = currentDoc && getProviderForPath(currentDoc.file.fullPath);
170232

171233
if (provider) {
172-
perfTimerInspector = PerfUtils.markStart("CodeInspection '" + languageId + "':\t" + currentDoc.file.fullPath);
173-
174-
var result = provider.scanFile(currentDoc.getText(), currentDoc.file.fullPath);
175-
_lastResult = result;
176-
177-
PerfUtils.addMeasurement(perfTimerInspector);
178-
perfTimerDOM = PerfUtils.markStart("ProblemsPanel render:\t" + currentDoc.file.fullPath);
179-
180-
if (result && result.errors.length) {
234+
inspectFile(currentDoc.file, provider).then(function (result) {
235+
// check if current document wasn't changed while inspectFile was running
236+
if (currentDoc !== DocumentManager.getCurrentDocument()) {
237+
return;
238+
}
239+
240+
_lastResult = result;
241+
242+
if (!result || !result.errors.length) {
243+
Resizer.hide($problemsPanel);
244+
StatusBar.updateIndicator(INDICATOR_ID, true, "inspection-valid", StringUtils.format(Strings.NO_ERRORS, provider.name));
245+
setGotoEnabled(false);
246+
return;
247+
}
248+
249+
var perfTimerDOM = PerfUtils.markStart("ProblemsPanel render:\t" + currentDoc.file.fullPath);
250+
181251
// Augment error objects with additional fields needed by Mustache template
182252
var numProblems = 0;
183253
result.errors.forEach(function (error) {
184254
error.friendlyLine = error.pos.line + 1;
185-
186255
error.codeSnippet = currentDoc.getLine(error.pos.line);
187256
error.codeSnippet = error.codeSnippet.substr(0, Math.min(175, error.codeSnippet.length)); // limit snippet width
188257

@@ -193,27 +262,11 @@ define(function (require, exports, module) {
193262

194263
// Update results table
195264
var html = Mustache.render(ResultsTemplate, {reportList: result.errors});
196-
var $selectedRow;
197265

198-
$problemsPanel.find(".table-container")
266+
$problemsPanelTable
199267
.empty()
200268
.append(html)
201-
.scrollTop(0) // otherwise scroll pos from previous contents is remembered
202-
.on("click", "tr", function (e) {
203-
if ($selectedRow) {
204-
$selectedRow.removeClass("selected");
205-
}
206-
207-
$selectedRow = $(e.currentTarget);
208-
$selectedRow.addClass("selected");
209-
var lineTd = $selectedRow.find(".line-number");
210-
var line = parseInt(lineTd.text(), 10) - 1; // convert friendlyLine back to pos.line
211-
var character = lineTd.data("character");
212-
213-
var editor = EditorManager.getCurrentFullEditor();
214-
editor.setCursorPos(line, character, true);
215-
EditorManager.focusEditor();
216-
});
269+
.scrollTop(0); // otherwise scroll pos from previous contents is remembered
217270

218271
$problemsPanel.find(".title").text(StringUtils.format(Strings.ERRORS_PANEL_TITLE, provider.name));
219272
if (!_collapsed) {
@@ -231,19 +284,14 @@ define(function (require, exports, module) {
231284
StringUtils.format(Strings.MULTIPLE_ERRORS, provider.name, numProblems));
232285
}
233286
setGotoEnabled(true);
234-
235-
} else {
236-
Resizer.hide($problemsPanel);
237-
StatusBar.updateIndicator(INDICATOR_ID, true, "inspection-valid", StringUtils.format(Strings.NO_ERRORS, provider.name));
238-
setGotoEnabled(false);
239-
}
240-
241-
PerfUtils.addMeasurement(perfTimerDOM);
242287

288+
PerfUtils.addMeasurement(perfTimerDOM);
289+
});
243290
} else {
244291
// No provider for current file
245292
_lastResult = null;
246293
Resizer.hide($problemsPanel);
294+
var language = currentDoc && LanguageManager.getLanguageForPath(currentDoc.file.fullPath);
247295
if (language) {
248296
StatusBar.updateIndicator(INDICATOR_ID, true, "inspection-disabled", StringUtils.format(Strings.NO_LINT_AVAILABLE, language.getName()));
249297
} else {
@@ -339,6 +387,24 @@ define(function (require, exports, module) {
339387
var resultsPanel = PanelManager.createBottomPanel("errors", $(panelHtml), 100);
340388
$problemsPanel = $("#problems-panel");
341389

390+
var $selectedRow;
391+
$problemsPanelTable = $problemsPanel.find(".table-container")
392+
.on("click", "tr", function (e) {
393+
if ($selectedRow) {
394+
$selectedRow.removeClass("selected");
395+
}
396+
397+
$selectedRow = $(e.currentTarget);
398+
$selectedRow.addClass("selected");
399+
var lineTd = $selectedRow.find(".line-number");
400+
var line = parseInt(lineTd.text(), 10) - 1; // convert friendlyLine back to pos.line
401+
var character = lineTd.data("character");
402+
403+
var editor = EditorManager.getCurrentFullEditor();
404+
editor.setCursorPos(line, character, true);
405+
EditorManager.focusEditor();
406+
});
407+
342408
$("#problems-panel .close").click(function () {
343409
toggleCollapsed(true);
344410
});
@@ -363,7 +429,8 @@ define(function (require, exports, module) {
363429

364430

365431
// Public API
366-
exports.register = register;
367-
exports.Type = Type;
368-
exports.toggleEnabled = toggleEnabled;
432+
exports.register = register;
433+
exports.Type = Type;
434+
exports.toggleEnabled = toggleEnabled;
435+
exports.inspectFile = inspectFile;
369436
});

0 commit comments

Comments
 (0)