@@ -643,6 +643,25 @@ define(function (require, exports, module) {
643
643
644
644
const scrollPositionMap = new Map ( ) ;
645
645
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
+
646
665
/**
647
666
* Run inspector applicable to current document. Updates status bar indicator and refreshes error list in
648
667
* 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) {
687
706
688
707
// run all the providers registered for this file type
689
708
( _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
+ }
690
717
editor . clearAllMarks ( CODE_MARK_TYPE_INSPECTOR ) ;
691
718
editor . clearGutter ( CODE_INSPECTION_GUTTER ) ;
692
719
_updateEditorMarksAndFixResults ( results ) ;
@@ -780,56 +807,73 @@ define(function (require, exports, module) {
780
807
} ) ;
781
808
782
809
} 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 ) ;
798
811
}
799
812
}
800
813
801
814
let gutterRegistrationInProgress = false ;
802
815
803
816
/**
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).
807
822
*
808
823
* 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
810
825
* registered providers.
811
826
*
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.
816
829
*
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.
820
834
*
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
823
842
* replace: "text to replace the offset given below",
824
843
* rangeOffset: {
825
844
* start: number,
826
845
* 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.
833
877
*/
834
878
function register ( languageId , provider ) {
835
879
if ( ! _providers [ languageId ] ) {
0 commit comments