Skip to content

Commit b5275d8

Browse files
committed
feat: jsx support in eslint
1 parent e24ba3d commit b5275d8

File tree

3 files changed

+90
-41
lines changed

3 files changed

+90
-41
lines changed

src/extensions/default/JSLint/ESLint.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ define(function (require, exports, module) {
142142
} else if(esLintResult.isError) {
143143
esLintServiceFailed = true;
144144
resolve({ errors: _getLintError(esLintResult.errorCode, esLintResult.errorMessage) });
145+
} else if(esLintResult.isPathIgnored) {
146+
resolve({isIgnored: true});
145147
} else {
146148
esLintServiceFailed = false;
147149
if(!esLintResult.result){
@@ -234,15 +236,18 @@ define(function (require, exports, module) {
234236
_reloadOptions();
235237
});
236238

237-
// Register for JS files
238-
CodeInspection.register("javascript", {
239+
const esLintProvider = {
239240
name: Strings.ESLINT_NAME,
240241
scanFileAsync: lintOneFile,
241242
canInspect: function (fullPath) {
242243
return !prefs.get(PREFS_ESLINT_DISABLED) && fullPath && !fullPath.endsWith(".min.js")
243244
&& useESLintFromProject;
244245
}
245-
});
246+
};
247+
248+
// Register for JS files
249+
CodeInspection.register("javascript", esLintProvider);
250+
CodeInspection.register("jsx", esLintProvider);
246251

247252
function isESLintActive() {
248253
return useESLintFromProject && Phoenix.isNativeApp && !esLintServiceFailed;

src/language/CodeInspection.js

Lines changed: 78 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,25 @@ define(function (require, exports, module) {
643643

644644
const scrollPositionMap = new Map();
645645

646+
function _noProviderReturnedResults(currentDoc, fullFilePath) {
647+
// No provider for current file
648+
_hasErrors = false;
649+
_currentPromise = null;
650+
updatePanelTitleAndStatusBar(0, [], false,
651+
fullFilePath ? path.basename(fullFilePath) : Strings.ERRORS_NO_FILE);
652+
if(problemsPanel){
653+
problemsPanel.hide();
654+
}
655+
const language = currentDoc && LanguageManager.getLanguageForPath(currentDoc.file.fullPath);
656+
if (language) {
657+
StatusBar.updateIndicator(INDICATOR_ID, true, "inspection-disabled",
658+
StringUtils.format(Strings.NO_LINT_AVAILABLE, language.getName()));
659+
} else {
660+
StatusBar.updateIndicator(INDICATOR_ID, true, "inspection-disabled", Strings.NOTHING_TO_LINT);
661+
}
662+
setGotoEnabled(false);
663+
}
664+
646665
/**
647666
* Run inspector applicable to current document. Updates status bar indicator and refreshes error list in
648667
* bottom panel. Does not run if inspection is disabled or if a providerName is given and does not
@@ -687,6 +706,14 @@ define(function (require, exports, module) {
687706

688707
// run all the providers registered for this file type
689708
(_currentPromise = inspectFile(currentDoc.file, providerList)).then(function (results) {
709+
// filter out any ignored results
710+
results = results.filter(function (providerResult) {
711+
return !providerResult.result || !providerResult.result.isIgnored;
712+
});
713+
if(!results.length) {
714+
_noProviderReturnedResults(currentDoc, fullFilePath);
715+
return;
716+
}
690717
editor.clearAllMarks(CODE_MARK_TYPE_INSPECTOR);
691718
editor.clearGutter(CODE_INSPECTION_GUTTER);
692719
_updateEditorMarksAndFixResults(results);
@@ -780,56 +807,73 @@ define(function (require, exports, module) {
780807
});
781808

782809
} else {
783-
// No provider for current file
784-
_hasErrors = false;
785-
_currentPromise = null;
786-
updatePanelTitleAndStatusBar(0, [], false,
787-
fullFilePath ? path.basename(fullFilePath) : Strings.ERRORS_NO_FILE);
788-
if(problemsPanel){
789-
problemsPanel.hide();
790-
}
791-
var language = currentDoc && LanguageManager.getLanguageForPath(currentDoc.file.fullPath);
792-
if (language) {
793-
StatusBar.updateIndicator(INDICATOR_ID, true, "inspection-disabled", StringUtils.format(Strings.NO_LINT_AVAILABLE, language.getName()));
794-
} else {
795-
StatusBar.updateIndicator(INDICATOR_ID, true, "inspection-disabled", Strings.NOTHING_TO_LINT);
796-
}
797-
setGotoEnabled(false);
810+
_noProviderReturnedResults(currentDoc, fullFilePath);
798811
}
799812
}
800813

801814
let gutterRegistrationInProgress = false;
802815

803816
/**
804-
* The provider is passed the text of the file and its fullPath. Providers should not assume
805-
* that the file is open (i.e. DocumentManager.getOpenDocumentForPath() may return null) or
806-
* that the file on disk matches the text given (file may have unsaved changes).
817+
* Registers a provider for a specific language to inspect files and provide linting results.
818+
*
819+
* The provider is passed the text of the file and its full path. Providers should not assume that
820+
* the file is open (i.e., `DocumentManager.getOpenDocumentForPath()` may return `null`) or that the
821+
* file on disk matches the text given (the file may have unsaved changes).
807822
*
808823
* Registering any provider for the "javascript" language automatically unregisters the built-in
809-
* Brackets JSLint provider. This is a temporary convenience until UI exists for disabling
824+
* Brackets JSLint provider. This is a temporary convenience until a UI exists for disabling
810825
* registered providers.
811826
*
812-
* Providers implement scanFile() if results are available synchronously, or scanFileAsync() if results
813-
* may require an async wait (if both are implemented, scanFile() is ignored). scanFileAsync() returns
814-
* a {$.Promise} object resolved with the same type of value as scanFile() is expected to return.
815-
* Rejecting the promise is treated as an internal error in the provider.
827+
* Providers must implement `canInspect()`, `scanFile()`, or `scanFileAsync()`. If both `scanFile()`
828+
* and `scanFileAsync()` are implemented, `scanFile()` is ignored.
816829
*
817-
* @param {string} languageId
818-
* @param {{name:string, scanFileAsync:?function(string, string):!{$.Promise},
819-
* scanFile:?function(string, string):?{errors:!Array, aborted:boolean}}} provider
830+
* - `canInspect(fullPath)`: A synchronous call to determine if the file can be scanned by this provider.
831+
* - `scanFile(text, fullPath)`: A synchronous function returning linting results or `null`.
832+
* - `scanFileAsync(text, fullPath)`: An asynchronous function returning a jQuery Promise resolved with
833+
* the same type of value as `scanFile()`. Rejecting the promise is treated as an internal error in the provider.
820834
*
821-
* Each error is: { pos:{line,ch}, endPos:?{line,ch}, message:string, htmlMessage:string, type:?Type ,
822-
* fix: { // an optional fix, if present will show the fix button
835+
* Each error object in the results should have the following structure:
836+
* { pos:{line,ch},
837+
* endPos:?{line,ch},
838+
* message:string,
839+
* htmlMessage:string,
840+
* type:?Type ,
841+
* fix: { // an optional fix, if present will show the fix button
823842
* replace: "text to replace the offset given below",
824843
* rangeOffset: {
825844
* start: number,
826845
* end: number
827-
* }}}
828-
* If type is unspecified, Type.WARNING is assumed.
829-
* If no errors found, return either null or an object with a zero-length `errors` array.
830-
* `message` will be printed as text as is. This is needed when the error text contains HTML that may be
831-
* mis interpreted as html to display. If you want to display html, pass in `htmlMessage`. Both can be used
832-
* at the same time, in which case both will be displayed.
846+
* }}}
847+
* @typedef {Object} Error
848+
* @property {Object} pos - The start position of the error.
849+
* @property {number} pos.line - The line number (0-based).
850+
* @property {number} pos.ch - The character position within the line (0-based).
851+
* @property {?Object} endPos - The end position of the error.
852+
* @property {number} endPos.line - The end line number (0-based).
853+
* @property {number} endPos.ch - The end character position within the line (0-based).
854+
* @property {string} message - The error message to be displayed as text.
855+
* @property {string} htmlMessage - The error message to be displayed as HTML.
856+
* @property {?Type} type - The type of the error. Defaults to `Type.WARNING` if unspecified.
857+
* @property {?Object} fix - An optional fix object.
858+
* @property {string} fix.replace - The text to replace the error with.
859+
* @property {Object} fix.rangeOffset - The range within the text to replace.
860+
* @property {number} fix.rangeOffset.start - The start offset of the range.
861+
* @property {number} fix.rangeOffset.end - The end offset of the range.
862+
*
863+
* If no errors are found, return either `null`(treated as file is problem free) or an object with a
864+
* zero-length `errors` array. Always use `message` to safely display the error as text. If you want to display HTML
865+
* error message, then explicitly use `htmlMessage` to display it. Both `message` and `htmlMessage` can
866+
* be used simultaneously.
867+
*
868+
* After scanning the file, if you need to omit the lint result, return or resolve with `{isIgnored: true}`.
869+
* This prevents the file from being marked with a no errors tick mark in the status bar and excludes the linter
870+
* from the problems panel.
871+
*
872+
* @param {string} languageId - The language ID for which the provider is registered.
873+
* @param {Object} provider - The provider object.
874+
* @param {string} provider.name - The name of the provider.
875+
* @param {?function(string, string): { errors: Array<Error>, aborted: boolean }} provider.scanFile - Synchronous scan function.
876+
* @param {?function(string, string): jQuery.Promise} provider.scanFileAsync - Asynchronous scan function returning a Promise.
833877
*/
834878
function register(languageId, provider) {
835879
if (!_providers[languageId]) {

src/styles/brackets.less

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ html, body {
164164
text-decoration-line: underline;
165165
text-decoration-skip-ink: none;
166166
text-decoration-thickness: 1px;
167-
text-underline-offset: 2px;
167+
text-underline-offset: 1px;
168168
text-decoration-color: @error-underline-text;
169169
}
170170

@@ -173,7 +173,7 @@ html, body {
173173
text-decoration-line: underline;
174174
text-decoration-skip-ink: none;
175175
text-decoration-thickness: 1px;
176-
text-underline-offset: 2px;
176+
text-underline-offset: 1px;
177177
text-decoration-color: @warn-underline-text;
178178
.dark &{
179179
text-decoration-color: @dark-warn-underline-text;
@@ -185,7 +185,7 @@ html, body {
185185
text-decoration-line: underline;
186186
text-decoration-skip-ink: none;
187187
text-decoration-thickness: 1px;
188-
text-underline-offset: 2px;
188+
text-underline-offset: 1px;
189189
text-decoration-color: @spell-underline-text;
190190
}
191191

@@ -194,7 +194,7 @@ html, body {
194194
text-decoration-line: underline;
195195
text-decoration-skip-ink: none;
196196
text-decoration-thickness: 1px;
197-
text-underline-offset: 2px;
197+
text-underline-offset: 1px;
198198
text-decoration-color: @info-underline-text;
199199
}
200200

0 commit comments

Comments
 (0)