@@ -11,7 +11,7 @@ import * as pydocstyle from './../linters/pydocstyle';
1111import * as settings from '../common/configSettings' ;
1212import * as telemetryHelper from '../common/telemetry' ;
1313import * as telemetryContracts from '../common/telemetryContracts' ;
14-
14+ import { LinterErrors } from '../common/constants'
1515const lintSeverityToVSSeverity = new Map < linter . LintMessageSeverity , vscode . DiagnosticSeverity > ( ) ;
1616lintSeverityToVSSeverity . set ( linter . LintMessageSeverity . Error , vscode . DiagnosticSeverity . Error )
1717lintSeverityToVSSeverity . set ( linter . LintMessageSeverity . Hint , vscode . DiagnosticSeverity . Hint )
@@ -37,6 +37,9 @@ function createDiagnostics(message: linter.ILintMessage, txtDocumentLines: strin
3737 return diagnostic ;
3838}
3939
40+ interface DocumentHasJupyterCodeCells {
41+ ( doc : vscode . TextDocument , token : vscode . CancellationToken ) : Promise < Boolean > ;
42+ }
4043export class LintProvider extends vscode . Disposable {
4144 private settings : settings . IPythonSettings ;
4245 private diagnosticCollection : vscode . DiagnosticCollection ;
@@ -45,7 +48,8 @@ export class LintProvider extends vscode.Disposable {
4548 private outputChannel : vscode . OutputChannel ;
4649 private context : vscode . ExtensionContext ;
4750
48- public constructor ( context : vscode . ExtensionContext , outputChannel : vscode . OutputChannel , private workspaceRootPath : string ) {
51+ public constructor ( context : vscode . ExtensionContext , outputChannel : vscode . OutputChannel ,
52+ private workspaceRootPath : string , private documentHasJupyterCodeCells : DocumentHasJupyterCodeCells ) {
4953 super ( ( ) => { } ) ;
5054 this . outputChannel = outputChannel ;
5155 this . context = context ;
@@ -68,13 +72,13 @@ export class LintProvider extends vscode.Disposable {
6872 if ( e . languageId !== 'python' || ! this . settings . linting . enabled || ! this . settings . linting . lintOnSave ) {
6973 return ;
7074 }
71- this . lintDocument ( e . uri , e . getText ( ) . split ( / \r ? \n / g) , 100 ) ;
75+ this . lintDocument ( e , e . uri , e . getText ( ) . split ( / \r ? \n / g) , 100 ) ;
7276 } ) ;
7377 this . context . subscriptions . push ( disposable ) ;
7478 }
7579
7680 private lastTimeout : number ;
77- private lintDocument ( documentUri : vscode . Uri , documentLines : string [ ] , delay : number ) : void {
81+ private lintDocument ( document : vscode . TextDocument , documentUri : vscode . Uri , documentLines : string [ ] , delay : number ) : void {
7882 // Since this is a hack, lets wait for 2 seconds before linting
7983 // Give user to continue typing before we waste CPU time
8084 if ( this . lastTimeout ) {
@@ -83,11 +87,11 @@ export class LintProvider extends vscode.Disposable {
8387 }
8488
8589 this . lastTimeout = setTimeout ( ( ) => {
86- this . onLintDocument ( documentUri , documentLines ) ;
90+ this . onLintDocument ( document , documentUri , documentLines ) ;
8791 } , delay ) ;
8892 }
8993
90- private onLintDocument ( documentUri : vscode . Uri , documentLines : string [ ] ) : void {
94+ private onLintDocument ( document : vscode . TextDocument , documentUri : vscode . Uri , documentLines : string [ ] ) : void {
9195 if ( this . pendingLintings . has ( documentUri . fsPath ) ) {
9296 this . pendingLintings . get ( documentUri . fsPath ) . cancel ( ) ;
9397 this . pendingLintings . delete ( documentUri . fsPath ) ;
@@ -113,29 +117,37 @@ export class LintProvider extends vscode.Disposable {
113117 return results ;
114118 } ) ;
115119 } ) ;
120+ this . documentHasJupyterCodeCells ( document , cancelToken . token ) . then ( hasJupyterCodeCells => {
121+ // linters will resolve asynchronously - keep a track of all
122+ // diagnostics reported as them come in
123+ let diagnostics : vscode . Diagnostic [ ] = [ ] ;
124+
125+ promises . forEach ( p => {
126+ p . then ( msgs => {
127+ if ( cancelToken . token . isCancellationRequested ) {
128+ return ;
129+ }
130+
131+ // Build the message and suffix the message with the name of the linter used
132+ msgs . forEach ( d => {
133+ // ignore magic commands from jupyter
134+ if ( hasJupyterCodeCells && documentLines [ d . line - 1 ] . trim ( ) . startsWith ( '%' ) &&
135+ ( d . code === LinterErrors . pylint . InvalidSyntax ||
136+ d . code === LinterErrors . prospector . InvalidSyntax ||
137+ d . code === LinterErrors . flake8 . InvalidSyntax ) ) {
138+ return ;
139+ }
140+ diagnostics . push ( createDiagnostics ( d , documentLines ) ) ;
141+ } ) ;
142+
143+ // Limit the number of messages to the max value
144+ diagnostics = diagnostics . filter ( ( value , index ) => index <= this . settings . linting . maxNumberOfProblems ) ;
145+
146+ // set all diagnostics found in this pass, as this method always clears existing diagnostics.
147+ this . diagnosticCollection . set ( documentUri , diagnostics )
116148
117- // linters will resolve asynchronously - keep a track of all
118- // diagnostics reported as them come in
119- let diagnostics : vscode . Diagnostic [ ] = [ ] ;
120-
121- promises . forEach ( p => {
122- p . then ( msgs => {
123- if ( cancelToken . token . isCancellationRequested ) {
124- return ;
125- }
126-
127- // Build the message and suffix the message with the name of the linter used
128- msgs . forEach ( d => {
129- diagnostics . push ( createDiagnostics ( d , documentLines ) ) ;
130149 } ) ;
131-
132- // Limit the number of messages to the max value
133- diagnostics = diagnostics . filter ( ( value , index ) => index <= this . settings . linting . maxNumberOfProblems ) ;
134-
135- // set all diagnostics found in this pass, as this method always clears existing diagnostics.
136- this . diagnosticCollection . set ( documentUri , diagnostics )
137-
138- } )
139- } )
150+ } ) ;
151+ } ) ;
140152 }
141153}
0 commit comments