1- import { Range } from "vscode-languageserver-textdocument" ;
21import * as c from "./constants" ;
32import * as childProcess from "child_process" ;
43import * as p from "vscode-languageserver-protocol" ;
@@ -128,37 +127,6 @@ export let runBsbWatcherUsingValidBsbPath = (
128127 // }
129128} ;
130129
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-
162130// Logic for parsing .compiler.log
163131/* example .compiler.log content:
164132
@@ -201,19 +169,60 @@ export let parseDiagnosticLocation = (location: string): Range => {
201169*/
202170
203171// 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+ }
214223 return {
215- file : isWindows ? `file:\\\\\\${ file } ` : file ,
216- location ,
224+ file : process . platform === "win32" ? `file:\\\\\\${ file } ` : file ,
225+ range ,
217226 } ;
218227} ;
219228
@@ -297,8 +306,8 @@ export let parseCompilerLogOutput = (
297306
298307 let result : filesDiagnostics = { } ;
299308 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 ) ) ;
302311
303312 if ( result [ file ] == null ) {
304313 result [ file ] = [ ] ;
@@ -316,7 +325,7 @@ export let parseCompilerLogOutput = (
316325 severity : parsedDiagnostic . severity ,
317326 tags : parsedDiagnostic . tag === undefined ? [ ] : [ parsedDiagnostic . tag ] ,
318327 code : parsedDiagnostic . code ,
319- range : parseDiagnosticLocation ( location ) ,
328+ range,
320329 source : "ReScript" ,
321330 message : cleanedUpDiagnostic ,
322331 } ) ;
0 commit comments