1
- import { Range } from "vscode-languageserver-textdocument" ;
2
1
import * as c from "./constants" ;
3
2
import * as childProcess from "child_process" ;
4
3
import * as p from "vscode-languageserver-protocol" ;
@@ -128,37 +127,6 @@ export let runBsbWatcherUsingValidBsbPath = (
128
127
// }
129
128
} ;
130
129
131
- export let parseDiagnosticLocation = ( location : string ) : Range => {
132
- // example output location:
133
- // 3:9
134
- // 3:5-8
135
- // 3:9-6:1
136
-
137
- // language-server position is 0-based. Ours is 1-based. Don't forget to convert
138
- // also, our end character is inclusive. Language-server's is exclusive
139
- let isRange = location . indexOf ( "-" ) >= 0 ;
140
- if ( isRange ) {
141
- let [ from , to ] = location . split ( "-" ) ;
142
- let [ fromLine , fromChar ] = from . split ( ":" ) ;
143
- let isSingleLine = to . indexOf ( ":" ) >= 0 ;
144
- let [ toLine , toChar ] = isSingleLine ? to . split ( ":" ) : [ fromLine , to ] ;
145
- return {
146
- start : {
147
- line : parseInt ( fromLine ) - 1 ,
148
- character : parseInt ( fromChar ) - 1 ,
149
- } ,
150
- end : { line : parseInt ( toLine ) - 1 , character : parseInt ( toChar ) } ,
151
- } ;
152
- } else {
153
- let [ line , char ] = location . split ( ":" ) ;
154
- let start = { line : parseInt ( line ) - 1 , character : parseInt ( char ) } ;
155
- return {
156
- start : start ,
157
- end : start ,
158
- } ;
159
- }
160
- } ;
161
-
162
130
// Logic for parsing .compiler.log
163
131
/* example .compiler.log content:
164
132
@@ -201,19 +169,60 @@ export let parseDiagnosticLocation = (location: string): Range => {
201
169
*/
202
170
203
171
// parser helper
204
- let splitFileAndLocation = ( fileAndLocation : string ) => {
205
- let isWindows = process . platform === "win32" ;
206
- // Exclude the two first letters in windows paths to avoid the first colon in eg "c:\\.."
207
- let locationSeparator = isWindows
208
- ? fileAndLocation . indexOf ( ":" , 2 )
209
- : fileAndLocation . indexOf ( ":" ) ;
210
-
211
- let file = fileAndLocation . slice ( 0 , locationSeparator ) ;
212
- let location = fileAndLocation . slice ( locationSeparator + 1 ) ;
213
-
172
+ let parseFileAndRange = ( fileAndRange : string ) => {
173
+ // https://github.com/rescript-lang/rescript-compiler/blob/0a3f4bb32ca81e89cefd5a912b8795878836f883/jscomp/super_errors/super_location.ml#L19-L25
174
+ /* The file + location format can be:
175
+ a/b.res:10:20
176
+ a/b.res:10:20-21 <- last number here is the end char of line 10
177
+ a/b.res:10:20-30:11
178
+ */
179
+ let regex = / ( .+ ) \: ( \d + ) \: ( \d + ) ( - ( \d + ) ( \: ( \d + ) ) ? ) ? $ / ;
180
+ /* ^^ file
181
+ ^^^ start line
182
+ ^^^ start character
183
+ ^ optional range
184
+ ^^^ end line or chararacter
185
+ ^^^ end character
186
+ */
187
+ // it's not possible that this regex fails. If it does, something's wrong in the caller
188
+ let [
189
+ _source ,
190
+ file ,
191
+ startLine ,
192
+ startChar ,
193
+ optionalEndGroup ,
194
+ endLineOrChar ,
195
+ _colonPlusEndCharOrNothing ,
196
+ endCharOrNothing ,
197
+ ] = fileAndRange . match ( regex ) ! ;
198
+ // language-server position is 0-based. Ours is 1-based. Convert
199
+ // also, our end character is inclusive. Language-server's is exclusive
200
+ let range ;
201
+ if ( optionalEndGroup == null ) {
202
+ let start = {
203
+ line : parseInt ( startLine ) - 1 ,
204
+ character : parseInt ( startChar ) ,
205
+ } ;
206
+ range = {
207
+ start : start ,
208
+ end : start ,
209
+ } ;
210
+ } else {
211
+ let isSingleLine = endCharOrNothing == null ;
212
+ let [ endLine , endChar ] = isSingleLine
213
+ ? [ startLine , endLineOrChar ]
214
+ : [ endLineOrChar , endCharOrNothing ] ;
215
+ range = {
216
+ start : {
217
+ line : parseInt ( startLine ) - 1 ,
218
+ character : parseInt ( startChar ) - 1 ,
219
+ } ,
220
+ end : { line : parseInt ( endLine ) - 1 , character : parseInt ( endChar ) } ,
221
+ } ;
222
+ }
214
223
return {
215
- file : isWindows ? `file:\\\\\\${ file } ` : file ,
216
- location ,
224
+ file : process . platform === "win32" ? `file:\\\\\\${ file } ` : file ,
225
+ range ,
217
226
} ;
218
227
} ;
219
228
@@ -297,8 +306,8 @@ export let parseCompilerLogOutput = (
297
306
298
307
let result : filesDiagnostics = { } ;
299
308
parsedDiagnostics . forEach ( ( parsedDiagnostic ) => {
300
- let [ fileAndLocationLine , ...diagnosticMessage ] = parsedDiagnostic . content ;
301
- let { file, location } = splitFileAndLocation ( fileAndLocationLine . slice ( 2 ) ) ;
309
+ let [ fileAndRangeLine , ...diagnosticMessage ] = parsedDiagnostic . content ;
310
+ let { file, range } = parseFileAndRange ( fileAndRangeLine . slice ( 2 ) ) ;
302
311
303
312
if ( result [ file ] == null ) {
304
313
result [ file ] = [ ] ;
@@ -316,7 +325,7 @@ export let parseCompilerLogOutput = (
316
325
severity : parsedDiagnostic . severity ,
317
326
tags : parsedDiagnostic . tag === undefined ? [ ] : [ parsedDiagnostic . tag ] ,
318
327
code : parsedDiagnostic . code ,
319
- range : parseDiagnosticLocation ( location ) ,
328
+ range,
320
329
source : "ReScript" ,
321
330
message : cleanedUpDiagnostic ,
322
331
} ) ;
0 commit comments