@@ -19,122 +19,41 @@ export type DiagnosticsResultCodeActionsMap = Map<
19
19
{ range : Range ; codeAction : CodeAction } [ ]
20
20
> ;
21
21
22
- let fileInfoRegex = / F i l e " ( .+ ) " , l i n e ( \d + ) , c h a r a c t e r s ( [ \d - ] + ) / g;
23
-
24
- let extractFileInfo = (
25
- fileInfo : string
26
- ) : {
27
- filePath : string ;
28
- line : string ;
29
- characters : string ;
30
- } | null => {
31
- let m ;
32
-
33
- let filePath : string | null = null ;
34
- let line : string | null = null ;
35
- let characters : string | null = null ;
36
-
37
- while ( ( m = fileInfoRegex . exec ( fileInfo ) ) !== null ) {
38
- if ( m . index === fileInfoRegex . lastIndex ) {
39
- fileInfoRegex . lastIndex ++ ;
22
+ let resultsToDiagnostics = (
23
+ results : [
24
+ {
25
+ name : string ;
26
+ kind : string ;
27
+ file : string ;
28
+ range : [ number , number , number , number ] ;
29
+ message : string ;
30
+ annotate ?: { line : number ; character : number ; text : string } ;
40
31
}
41
-
42
- m . forEach ( ( match : string , groupIndex : number ) => {
43
- switch ( groupIndex ) {
44
- case 1 : {
45
- filePath = match ;
46
- break ;
47
- }
48
- case 2 : {
49
- line = match ;
50
- break ;
51
- }
52
- case 3 : {
53
- characters = match ;
54
- break ;
55
- }
56
- }
57
- } ) ;
58
- }
59
-
60
- if ( filePath != null && line != null && characters != null ) {
61
- return {
62
- filePath,
63
- line,
64
- characters,
65
- } ;
66
- }
67
-
68
- return null ;
69
- } ;
70
-
71
- let dceTextToDiagnostics = (
72
- dceText : string ,
32
+ ] ,
73
33
diagnosticsResultCodeActions : DiagnosticsResultCodeActionsMap
74
34
) : {
75
35
diagnosticsMap : Map < string , Diagnostic [ ] > ;
76
36
} => {
77
37
let diagnosticsMap : Map < string , Diagnostic [ ] > = new Map ( ) ;
78
38
79
- // Each section with a single issue found is seprated by two line breaks in
80
- // the reanalyze output. The section contains information about the issue
81
- // itself, what line/char and in what file it was found, as well as a
82
- // suggestion for what you can replace the line containing the issue with to
83
- // suppress the issue reported.
84
- //
85
- // Here's an example of how a section typically looks:
86
- //
87
- // Warning Dead Value
88
- // File "/Users/zth/git/rescript-intro/src/Machine.res", line 2, characters 0-205
89
- // +use is never used
90
- // <-- line 2
91
- // @dead ("+use") let use = (initialState: 'a, handleEvent: ('a, 'b) => 'a) => {
92
-
93
- dceText . split ( "\n\n" ) . forEach ( ( chunk ) => {
94
- let lines = chunk . split ( "\n" ) . filter ( ( line ) => line != "" ) ;
95
- let [
96
- _title ,
97
- fileInfo ,
98
- text ,
99
-
100
- // These, if they exist, will power code actions for inserting the "fixed"
101
- // line that reanalyze might suggest.
102
- lineNumToReplace ,
103
- lineContentToReplace ,
104
- ] = lines ;
105
-
106
- let processedFileInfo = extractFileInfo ( fileInfo ) ;
107
-
108
- if ( processedFileInfo != null ) {
109
- let [ startCharacter , endCharacter ] =
110
- processedFileInfo . characters . split ( "-" ) ;
111
-
112
- let parsedLine = parseInt ( processedFileInfo . line , 10 ) ;
113
-
114
- let startPos = new Position (
115
- // reanalyze reports lines as index 1 based, while VSCode wants them
116
- // index 0 based. reanalyze reports diagnostics for an entire file on
117
- // line 0 (and chars 0-0). So, we need to ensure that we don't give
118
- // VSCode a negative line index, or it'll be sad.
119
- Math . max ( 0 , parsedLine - 1 ) ,
120
- Math . max ( 0 , parseInt ( startCharacter , 10 ) )
121
- ) ;
122
-
123
- let endPos = new Position (
124
- Math . max ( 0 , parsedLine - 1 ) ,
125
- Math . max ( 0 , parseInt ( endCharacter , 10 ) )
126
- ) ;
39
+ results . forEach ( ( item ) => {
40
+ {
41
+ let startPos : Position , endPos : Position ;
42
+ let [ startLine , startCharacter , endLine , endCharacter ] = item . range ;
127
43
128
44
// Detect if this diagnostic is for the entire file. If so, reanalyze will
129
- // say that the issue is on line 0 and chars 0-0 . This code below ensures
45
+ // say that the issue is on line -1 . This code below ensures
130
46
// that the full file is highlighted, if that's the case.
131
- if ( parsedLine === 0 && processedFileInfo . characters === "0-0" ) {
47
+ if ( startLine < 0 || endLine < 0 ) {
132
48
startPos = new Position ( 0 , 0 ) ;
133
49
endPos = new Position ( 99999 , 0 ) ;
50
+ } else {
51
+ startPos = new Position ( startLine , startCharacter ) ;
52
+ endPos = new Position ( endLine , endCharacter ) ;
134
53
}
135
54
136
55
let issueLocationRange = new Range ( startPos , endPos ) ;
137
- let diagnosticText = text . trim ( ) ;
56
+ let diagnosticText = item . message . trim ( ) ;
138
57
139
58
let diagnostic = new Diagnostic (
140
59
issueLocationRange ,
@@ -146,52 +65,53 @@ let dceTextToDiagnostics = (
146
65
// optional arguments. This will ensure that everything but reduntant
147
66
// optional arguments is highlighted as unecessary/unused code in the
148
67
// editor.
149
- if ( ! diagnosticText . toLowerCase ( ) . startsWith ( "optional argument" ) ) {
68
+ if ( ! item . message . toLowerCase ( ) . startsWith ( "optional argument" ) ) {
150
69
diagnostic . tags = [ DiagnosticTag . Unnecessary ] ;
151
70
}
152
71
153
- if ( diagnosticsMap . has ( processedFileInfo . filePath ) ) {
154
- diagnosticsMap . get ( processedFileInfo . filePath ) . push ( diagnostic ) ;
72
+ if ( diagnosticsMap . has ( item . file ) ) {
73
+ diagnosticsMap . get ( item . file ) . push ( diagnostic ) ;
155
74
} else {
156
- diagnosticsMap . set ( processedFileInfo . filePath , [ diagnostic ] ) ;
75
+ diagnosticsMap . set ( item . file , [ diagnostic ] ) ;
157
76
}
158
77
159
78
// If reanalyze suggests a fix, we'll set that up as a refactor code
160
79
// action in VSCode. This way, it'll be easy to suppress the issue
161
80
// reported if wanted. We also save the range of the issue, so we can
162
81
// leverage that to make looking up the code actions for each cursor
163
82
// position very cheap.
164
- if ( lineNumToReplace != null && lineContentToReplace != null ) {
165
- let [ _ , actualLineToReplaceStr ] = lineNumToReplace . split ( "<-- line " ) ;
166
-
167
- if ( actualLineToReplaceStr != null ) {
83
+ if ( item . annotate != null ) {
84
+ {
168
85
let codeAction = new CodeAction ( `Suppress dead code warning` ) ;
169
86
codeAction . kind = CodeActionKind . RefactorRewrite ;
170
87
171
88
let codeActionEdit = new WorkspaceEdit ( ) ;
172
89
90
+ let { line, character, text } = item . annotate ;
91
+
173
92
// In the future, it would be cool to have an additional code action
174
93
// here for automatically removing whatever the thing that's dead is.
175
94
codeActionEdit . replace (
176
- Uri . parse ( processedFileInfo . filePath ) ,
95
+ Uri . parse ( item . file ) ,
177
96
// Make sure the full line is replaced
97
+
178
98
new Range (
179
- new Position ( issueLocationRange . start . line , 0 ) ,
180
- new Position ( issueLocationRange . start . line , 999999 )
99
+ new Position ( line , character ) ,
100
+ new Position ( line , character )
181
101
) ,
182
102
// reanalyze seems to add two extra spaces at the start of the line
183
103
// content to replace.
184
- lineContentToReplace . slice ( 2 )
104
+ text
185
105
) ;
186
106
187
107
codeAction . edit = codeActionEdit ;
188
108
189
- if ( diagnosticsResultCodeActions . has ( processedFileInfo . filePath ) ) {
109
+ if ( diagnosticsResultCodeActions . has ( item . file ) ) {
190
110
diagnosticsResultCodeActions
191
- . get ( processedFileInfo . filePath )
111
+ . get ( item . file )
192
112
. push ( { range : issueLocationRange , codeAction } ) ;
193
113
} else {
194
- diagnosticsResultCodeActions . set ( processedFileInfo . filePath , [
114
+ diagnosticsResultCodeActions . set ( item . file , [
195
115
{ range : issueLocationRange , codeAction } ,
196
116
] ) ;
197
117
}
@@ -213,7 +133,7 @@ export const runCodeAnalysisWithReanalyze = (
213
133
let currentDocument = window . activeTextEditor . document ;
214
134
let cwd = targetDir ?? path . dirname ( currentDocument . uri . fsPath ) ;
215
135
216
- let p = cp . spawn ( "npx" , [ "reanalyze@2.21.1 " ] , {
136
+ let p = cp . spawn ( "npx" , [ "reanalyze@2.22.0" , "-json "] , {
217
137
cwd,
218
138
} ) ;
219
139
@@ -246,8 +166,15 @@ export const runCodeAnalysisWithReanalyze = (
246
166
247
167
p . on ( "close" , ( ) => {
248
168
diagnosticsResultCodeActions . clear ( ) ;
249
- let { diagnosticsMap } = dceTextToDiagnostics (
250
- data ,
169
+ try {
170
+ var json = JSON . parse ( data ) ;
171
+ } catch ( e ) {
172
+ window . showErrorMessage (
173
+ `Something went wrong parsing the json output of reanalyze: '${ e } '`
174
+ ) ;
175
+ }
176
+ let { diagnosticsMap } = resultsToDiagnostics (
177
+ json ,
251
178
diagnosticsResultCodeActions
252
179
) ;
253
180
0 commit comments