@@ -15,11 +15,11 @@ import (
15
15
"go.bug.st/lsp"
16
16
)
17
17
18
- // InoMapper is a mapping between the .ino sketch and the preprocessed .cpp file
19
- type InoMapper struct {
18
+ // SketchMapper is a mapping between the .ino sketch and the preprocessed .cpp file
19
+ type SketchMapper struct {
20
20
CppText * SourceRevision
21
- toCpp map [InoLine ]int // Converts File.ino:line -> line
22
- toIno map [int ]InoLine // Convers line -> File.ino:line
21
+ inoToCpp map [InoLine ]int // Converts File.ino:line -> line
22
+ cppToIno map [int ]InoLine // Convers line -> File.ino:line
23
23
inoPreprocessed map [InoLine ]int // map of the lines taken by the preprocessor: File.ino:line -> preprocessed line
24
24
cppPreprocessed map [int ]InoLine // map of the lines added by the preprocessor: preprocessed line -> File.ino:line
25
25
}
@@ -42,27 +42,27 @@ type InoLine struct {
42
42
}
43
43
44
44
// InoToCppLine converts a source (.ino) line into a target (.cpp) line
45
- func (s * InoMapper ) InoToCppLine (sourceURI lsp.DocumentURI , line int ) int {
46
- return s .toCpp [InoLine {sourceURI .AsPath ().String (), line }]
45
+ func (s * SketchMapper ) InoToCppLine (sourceURI lsp.DocumentURI , line int ) int {
46
+ return s .inoToCpp [InoLine {sourceURI .AsPath ().String (), line }]
47
47
}
48
48
49
49
// InoToCppLineOk converts a source (.ino) line into a target (.cpp) line
50
- func (s * InoMapper ) InoToCppLineOk (sourceURI lsp.DocumentURI , line int ) (int , bool ) {
51
- res , ok := s .toCpp [InoLine {sourceURI .AsPath ().String (), line }]
50
+ func (s * SketchMapper ) InoToCppLineOk (sourceURI lsp.DocumentURI , line int ) (int , bool ) {
51
+ res , ok := s .inoToCpp [InoLine {sourceURI .AsPath ().String (), line }]
52
52
return res , ok
53
53
}
54
54
55
- // InoToCppLSPRange convert a lsp.Ranger reference to a .ino into a lsp.Range to .cpp
56
- func (s * InoMapper ) InoToCppLSPRange (sourceURI lsp.DocumentURI , r lsp.Range ) lsp.Range {
55
+ // InoToCppLSPRange convert a lsp.Range reference to a .ino into a lsp.Range to .cpp
56
+ func (s * SketchMapper ) InoToCppLSPRange (sourceURI lsp.DocumentURI , r lsp.Range ) lsp.Range {
57
57
res := r
58
58
res .Start .Line = s .InoToCppLine (sourceURI , r .Start .Line )
59
59
res .End .Line = s .InoToCppLine (sourceURI , r .End .Line )
60
60
return res
61
61
}
62
62
63
- // InoToCppLSPRangeOk convert a lsp.Ranger reference to a .ino into a lsp.Range to .cpp and returns
63
+ // InoToCppLSPRangeOk convert a lsp.Range reference to a .ino into a lsp.Range to .cpp and returns
64
64
// true if the conversion is successful or false if the conversion is invalid.
65
- func (s * InoMapper ) InoToCppLSPRangeOk (sourceURI lsp.DocumentURI , r lsp.Range ) (lsp.Range , bool ) {
65
+ func (s * SketchMapper ) InoToCppLSPRangeOk (sourceURI lsp.DocumentURI , r lsp.Range ) (lsp.Range , bool ) {
66
66
res := r
67
67
if l , ok := s .InoToCppLineOk (sourceURI , r .Start .Line ); ok {
68
68
res .Start .Line = l
@@ -78,14 +78,14 @@ func (s *InoMapper) InoToCppLSPRangeOk(sourceURI lsp.DocumentURI, r lsp.Range) (
78
78
}
79
79
80
80
// CppToInoLine converts a target (.cpp) line into a source.ino:line
81
- func (s * InoMapper ) CppToInoLine (targetLine int ) (string , int ) {
82
- res := s .toIno [targetLine ]
81
+ func (s * SketchMapper ) CppToInoLine (targetLine int ) (string , int ) {
82
+ res := s .cppToIno [targetLine ]
83
83
return res .File , res .Line
84
84
}
85
85
86
86
// CppToInoRange converts a target (.cpp) lsp.Range into a source.ino:lsp.Range.
87
87
// It will panic if the range spans across multiple ino files.
88
- func (s * InoMapper ) CppToInoRange (cppRange lsp.Range ) (string , lsp.Range ) {
88
+ func (s * SketchMapper ) CppToInoRange (cppRange lsp.Range ) (string , lsp.Range ) {
89
89
inoFile , inoRange , err := s .CppToInoRangeOk (cppRange )
90
90
if err != nil {
91
91
panic (err .Error ())
@@ -105,7 +105,7 @@ func (e AdjustedRangeErr) Error() string {
105
105
// It returns an error if the range spans across multiple ino files.
106
106
// If the range ends on the beginning of a new line in another .ino file, the range
107
107
// is adjusted and AdjustedRangeErr is reported as err: the range may be still valid.
108
- func (s * InoMapper ) CppToInoRangeOk (cppRange lsp.Range ) (string , lsp.Range , error ) {
108
+ func (s * SketchMapper ) CppToInoRangeOk (cppRange lsp.Range ) (string , lsp.Range , error ) {
109
109
inoFile , startLine := s .CppToInoLine (cppRange .Start .Line )
110
110
endInoFile , endLine := s .CppToInoLine (cppRange .End .Line )
111
111
inoRange := cppRange
@@ -131,36 +131,41 @@ func (s *InoMapper) CppToInoRangeOk(cppRange lsp.Range) (string, lsp.Range, erro
131
131
132
132
// CppToInoLineOk converts a target (.cpp) line into a source (.ino) line and
133
133
// returns true if the conversion is successful
134
- func (s * InoMapper ) CppToInoLineOk (targetLine int ) (string , int , bool ) {
135
- res , ok := s .toIno [targetLine ]
134
+ func (s * SketchMapper ) CppToInoLineOk (targetLine int ) (string , int , bool ) {
135
+ res , ok := s .cppToIno [targetLine ]
136
136
return res .File , res .Line , ok
137
137
}
138
138
139
- // IsPreprocessedCppLine returns true if the give .cpp line is part of the
139
+ // IsPreprocessedCppLine returns true if the given .cpp line is part of the
140
140
// section added by the arduino preprocessor.
141
- func (s * InoMapper ) IsPreprocessedCppLine (cppLine int ) bool {
141
+ func (s * SketchMapper ) IsPreprocessedCppLine (cppLine int ) bool {
142
142
_ , preprocessed := s .cppPreprocessed [cppLine ]
143
- _ , mapsToIno := s .toIno [cppLine ]
143
+ _ , mapsToIno := s .cppToIno [cppLine ]
144
144
return preprocessed || ! mapsToIno
145
145
}
146
146
147
147
// CreateInoMapper create a InoMapper from the given target file
148
- func CreateInoMapper (targetFile []byte ) * InoMapper {
149
- mapper := & InoMapper {
150
- toCpp : map [InoLine ]int {},
151
- toIno : map [int ]InoLine {},
152
- inoPreprocessed : map [InoLine ]int {},
153
- cppPreprocessed : map [int ]InoLine {},
148
+ func CreateInoMapper (targetFile []byte ) * SketchMapper {
149
+ mapper := & SketchMapper {
154
150
CppText : & SourceRevision {
155
151
Version : 1 ,
156
152
Text : string (targetFile ),
157
153
},
158
154
}
155
+ mapper .regeneratehMapping ()
156
+ return mapper
157
+ }
158
+
159
+ func (s * SketchMapper ) regeneratehMapping () {
160
+ s .inoToCpp = map [InoLine ]int {}
161
+ s .cppToIno = map [int ]InoLine {}
162
+ s .inoPreprocessed = map [InoLine ]int {}
163
+ s .cppPreprocessed = map [int ]InoLine {}
159
164
160
165
sourceFile := ""
161
166
sourceLine := - 1
162
167
targetLine := 0
163
- scanner := bufio .NewScanner (bytes .NewReader (targetFile ))
168
+ scanner := bufio .NewScanner (bytes .NewReader ([] byte ( s . CppText . Text ) ))
164
169
for scanner .Scan () {
165
170
lineStr := scanner .Text ()
166
171
if strings .HasPrefix (lineStr , "#line" ) {
@@ -170,27 +175,26 @@ func CreateInoMapper(targetFile []byte) *InoMapper {
170
175
sourceLine = l - 1
171
176
}
172
177
sourceFile = paths .New (unquoteCppString (tokens [2 ])).Canonical ().String ()
173
- mapper . toIno [targetLine ] = NotIno
178
+ s . cppToIno [targetLine ] = NotIno
174
179
} else if sourceFile != "" {
175
- mapper .mapLine (sourceFile , sourceLine , targetLine )
180
+ s .mapLine (sourceFile , sourceLine , targetLine )
176
181
sourceLine ++
177
182
} else {
178
- mapper . toIno [targetLine ] = NotIno
183
+ s . cppToIno [targetLine ] = NotIno
179
184
}
180
185
targetLine ++
181
186
}
182
- mapper .mapLine (sourceFile , sourceLine , targetLine )
183
- return mapper
187
+ s .mapLine (sourceFile , sourceLine , targetLine )
184
188
}
185
189
186
- func (s * InoMapper ) mapLine (sourceFile string , sourceLine , targetLine int ) {
187
- inoLine := InoLine {sourceFile , sourceLine }
188
- if line , ok := s .toCpp [inoLine ]; ok {
190
+ func (s * SketchMapper ) mapLine (inoSourceFile string , inoSourceLine , cppLine int ) {
191
+ inoLine := InoLine {inoSourceFile , inoSourceLine }
192
+ if line , ok := s .inoToCpp [inoLine ]; ok {
189
193
s .cppPreprocessed [line ] = inoLine
190
194
s .inoPreprocessed [inoLine ] = line
191
195
}
192
- s .toCpp [inoLine ] = targetLine
193
- s .toIno [ targetLine ] = inoLine
196
+ s .inoToCpp [inoLine ] = cppLine
197
+ s .cppToIno [ cppLine ] = inoLine
194
198
}
195
199
196
200
func unquoteCppString (str string ) string {
@@ -205,9 +209,13 @@ func unquoteCppString(str string) string {
205
209
// ApplyTextChange performs the text change and updates both .ino and .cpp files.
206
210
// It returns true if the change is "dirty", this happens when the change alters preprocessed lines
207
211
// and a new preprocessing may be probably required.
208
- func (s * InoMapper ) ApplyTextChange (inoURI lsp.DocumentURI , inoChange lsp.TextDocumentContentChangeEvent ) (dirty bool ) {
212
+ func (s * SketchMapper ) ApplyTextChange (inoURI lsp.DocumentURI , inoChange lsp.TextDocumentContentChangeEvent ) (dirty bool ) {
209
213
inoRange := inoChange .Range
210
- cppRange := s .InoToCppLSPRange (inoURI , inoRange )
214
+ cppRange , ok := s .InoToCppLSPRangeOk (inoURI , inoRange )
215
+ if ! ok {
216
+ panic ("Invalid sketch range " + inoURI .String () + ":" + inoRange .String ())
217
+ }
218
+ log .Print ("Ino Range: " , inoRange , " -> Cpp Range:" , cppRange )
211
219
deletedLines := inoRange .End .Line - inoRange .Start .Line
212
220
213
221
// Apply text changes
@@ -218,7 +226,7 @@ func (s *InoMapper) ApplyTextChange(inoURI lsp.DocumentURI, inoChange lsp.TextDo
218
226
s .CppText .Text = newText
219
227
s .CppText .Version ++
220
228
221
- if _ , is := s .inoPreprocessed [s .toIno [cppRange .Start .Line ]]; is {
229
+ if _ , is := s .inoPreprocessed [s .cppToIno [cppRange .Start .Line ]]; is {
222
230
dirty = true
223
231
}
224
232
@@ -227,24 +235,24 @@ func (s *InoMapper) ApplyTextChange(inoURI lsp.DocumentURI, inoChange lsp.TextDo
227
235
dirty = dirty || s .deleteCppLine (cppRange .Start .Line )
228
236
deletedLines --
229
237
}
230
- addedLines := strings .Count (inoChange .Text , "\n " ) - 1
238
+ addedLines := strings .Count (inoChange .Text , "\n " )
231
239
for addedLines > 0 {
232
240
dirty = dirty || s .addInoLine (cppRange .Start .Line )
233
241
addedLines --
234
242
}
235
243
return
236
244
}
237
245
238
- func (s * InoMapper ) addInoLine (cppLine int ) (dirty bool ) {
246
+ func (s * SketchMapper ) addInoLine (cppLine int ) (dirty bool ) {
239
247
preprocessToShiftCpp := map [InoLine ]bool {}
240
248
241
- addedInoLine := s .toIno [cppLine ]
242
- carry := s .toIno [cppLine ]
249
+ addedInoLine := s .cppToIno [cppLine ]
250
+ carry := s .cppToIno [cppLine ]
243
251
carry .Line ++
244
252
for {
245
- next , ok := s .toIno [cppLine + 1 ]
246
- s .toIno [cppLine + 1 ] = carry
247
- s .toCpp [carry ] = cppLine + 1
253
+ next , ok := s .cppToIno [cppLine + 1 ]
254
+ s .cppToIno [cppLine + 1 ] = carry
255
+ s .inoToCpp [carry ] = cppLine + 1
248
256
if ! ok {
249
257
break
250
258
}
@@ -282,23 +290,23 @@ func (s *InoMapper) addInoLine(cppLine int) (dirty bool) {
282
290
inoPre .Line ++
283
291
s .inoPreprocessed [inoPre ] = l
284
292
s .cppPreprocessed [l ] = inoPre
285
- s .toIno [l ] = inoPre
293
+ s .cppToIno [l ] = inoPre
286
294
}
287
295
288
296
return
289
297
}
290
298
291
- func (s * InoMapper ) deleteCppLine (line int ) (dirty bool ) {
292
- removed := s .toIno [line ]
299
+ func (s * SketchMapper ) deleteCppLine (line int ) (dirty bool ) {
300
+ removed := s .cppToIno [line ]
293
301
for i := line + 1 ; ; i ++ {
294
- shifted , ok := s .toIno [i ]
302
+ shifted , ok := s .cppToIno [i ]
295
303
if ! ok {
296
- delete (s .toIno , i - 1 )
304
+ delete (s .cppToIno , i - 1 )
297
305
break
298
306
}
299
- s .toIno [i - 1 ] = shifted
307
+ s .cppToIno [i - 1 ] = shifted
300
308
if shifted != NotIno {
301
- s .toCpp [shifted ] = i - 1
309
+ s .inoToCpp [shifted ] = i - 1
302
310
}
303
311
}
304
312
@@ -310,20 +318,20 @@ func (s *InoMapper) deleteCppLine(line int) (dirty bool) {
310
318
next := curr
311
319
next .Line ++
312
320
313
- shifted , ok := s .toCpp [next ]
321
+ shifted , ok := s .inoToCpp [next ]
314
322
if ! ok {
315
- delete (s .toCpp , curr )
323
+ delete (s .inoToCpp , curr )
316
324
break
317
325
}
318
- s .toCpp [curr ] = shifted
319
- s .toIno [shifted ] = curr
326
+ s .inoToCpp [curr ] = shifted
327
+ s .cppToIno [shifted ] = curr
320
328
321
329
if l , ok := s .inoPreprocessed [next ]; ok {
322
330
s .inoPreprocessed [curr ] = l
323
331
s .cppPreprocessed [l ] = curr
324
332
delete (s .inoPreprocessed , next )
325
333
326
- s .toIno [l ] = curr
334
+ s .cppToIno [l ] = curr
327
335
}
328
336
}
329
337
return
@@ -359,11 +367,25 @@ func dumpInoToCppMap(s map[InoLine]int) {
359
367
}
360
368
361
369
// DebugLogAll dumps the internal status of the mapper
362
- func (s * InoMapper ) DebugLogAll () {
370
+ func (s * SketchMapper ) DebugLogAll () {
371
+ stripFile := func (s string ) string {
372
+ return s [strings .LastIndex (s , "/" ):]
373
+ }
363
374
cpp := strings .Split (s .CppText .Text , "\n " )
364
375
log .Printf (" > Current sketchmapper content:" )
365
376
for l , cppLine := range cpp {
366
377
inoFile , inoLine := s .CppToInoLine (l )
367
- log .Printf (" %3d: %-40s : %s:%d" , l , cppLine , inoFile , inoLine )
378
+ cppLine = strings .Replace (cppLine , "\t " , " " , - 1 )
379
+ if len (cppLine ) > 60 {
380
+ cppLine = cppLine [:60 ]
381
+ }
382
+
383
+ cppSource := fmt .Sprintf ("%3d: %-60s" , l , cppLine )
384
+ sketchFile := fmt .Sprintf ("%s:%d" , stripFile (inoFile ), inoLine )
385
+ preprocLine := ""
386
+ if pr , ok := s .cppPreprocessed [l ]; ok {
387
+ preprocLine = fmt .Sprintf ("%s:%d" , stripFile (pr .File ), pr .Line )
388
+ }
389
+ log .Printf ("%s | %-25s %-25s" , cppSource , sketchFile , preprocLine )
368
390
}
369
391
}
0 commit comments