1414
1515import * as vscode from 'vscode' ;
1616import { buildifierLint , getBuildifierFileType } from './execute' ;
17+ import { IBuildifierWarning } from './result' ;
1718import { BuildifierSettings } from './settings' ;
1819
1920/**
@@ -62,6 +63,18 @@ export class BuildifierDiagnosticsManager {
6263 }
6364 }
6465
66+ /**
67+ * Sets a single error diagnostic. This is used when a parsing error occurs
68+ * and we want to report the location.
69+ *
70+ * @param document The text document whose diagnostics should be updated.
71+ */
72+ public async error ( document : vscode . TextDocument , range : vscode . Range , message : string ) {
73+ const diagnostic = new vscode . Diagnostic ( range , message , vscode . DiagnosticSeverity . Error ) ;
74+ diagnostic . source = 'buildifier' ;
75+ this . diagnosticsCollection . set ( document . uri , [ diagnostic ] ) ;
76+ }
77+
6578 /**
6679 * Updates the diagnostics collection with lint warnings for the given text
6780 * document.
@@ -81,32 +94,80 @@ export class BuildifierDiagnosticsManager {
8194 return ;
8295 }
8396
84- const warnings = await buildifierLint (
97+ const result = await buildifierLint (
8598 cfg ,
8699 document . getText ( ) ,
87100 getBuildifierFileType ( document . uri . fsPath ) ,
88101 'warn'
89102 ) ;
90103
91- this . diagnosticsCollection . set (
92- document . uri ,
93- warnings . map ( warning => {
94- // Buildifier returns 1-based line numbers, but VS Code is 0-based.
95- const range = new vscode . Range (
96- warning . start . line - 1 ,
97- warning . start . column - 1 ,
98- warning . end . line - 1 ,
99- warning . end . column - 1
100- ) ;
101- const diagnostic = new vscode . Diagnostic (
102- range ,
103- warning . message ,
104- vscode . DiagnosticSeverity . Warning
105- ) ;
106- diagnostic . source = 'buildifier' ;
107- diagnostic . code = warning . category ;
108- return diagnostic ;
109- } )
110- ) ;
104+ if ( ! result . stderr ) {
105+ this . diagnosticsCollection . set (
106+ document . uri ,
107+ result . file . warnings . map ( warning => {
108+ // Buildifier returns 1-based line numbers, but VS Code is 0-based.
109+ const range = new vscode . Range (
110+ warning . start . line - 1 ,
111+ warning . start . column - 1 ,
112+ warning . end . line - 1 ,
113+ warning . end . column - 1
114+ ) ;
115+ const diagnostic = new vscode . Diagnostic (
116+ range ,
117+ warning . message ,
118+ vscode . DiagnosticSeverity . Warning
119+ ) ;
120+ diagnostic . source = 'buildifier' ;
121+ diagnostic . code = warning . category ;
122+ return diagnostic ;
123+ } )
124+ ) ;
125+ } else {
126+ const warnings : IBuildifierWarning [ ] = [ ] ;
127+ const syntaxError = parseStderr ( result . stderr ) ;
128+ if ( syntaxError ) {
129+ warnings . push ( syntaxError ) ;
130+ }
131+ this . diagnosticsCollection . set (
132+ document . uri ,
133+ warnings . map ( warning => {
134+ // Buildifier returns 1-based line numbers, but VS Code is 0-based.
135+ const range = new vscode . Range (
136+ warning . start . line - 1 ,
137+ warning . start . column - 1 ,
138+ warning . end . line - 1 ,
139+ warning . end . column - 1
140+ ) ;
141+ const diagnostic = new vscode . Diagnostic (
142+ range ,
143+ warning . message ,
144+ vscode . DiagnosticSeverity . Error
145+ ) ;
146+ diagnostic . source = 'buildifier' ;
147+ diagnostic . code = warning . category ;
148+ return diagnostic ;
149+ } )
150+ ) ;
151+
152+ }
111153 }
112154}
155+
156+ function parseStderr ( input : string ) : IBuildifierWarning | undefined {
157+ if ( ! input . startsWith ( '<stdin>' ) ) {
158+ return undefined ;
159+ }
160+ const parts = input . slice ( '<stdin>:' . length ) . split ( ':' ) ;
161+ const line = parseInt ( parts [ 0 ] ) ;
162+ const column = parseInt ( parts [ 1 ] ) ;
163+ const rest = parts . slice ( 2 ) . join ( ':' ) ;
164+ const pos = { line, column } ;
165+
166+ return {
167+ start : pos ,
168+ end : pos ,
169+ category : 'invalid-input' ,
170+ actionable : false ,
171+ message : rest ,
172+ }
173+ }
0 commit comments