@@ -15,11 +15,11 @@ import (
1515 "go.bug.st/lsp"
1616)
1717
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 {
2020 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
2323 inoPreprocessed map [InoLine ]int // map of the lines taken by the preprocessor: File.ino:line -> preprocessed line
2424 cppPreprocessed map [int ]InoLine // map of the lines added by the preprocessor: preprocessed line -> File.ino:line
2525}
@@ -42,27 +42,27 @@ type InoLine struct {
4242}
4343
4444// 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 }]
4747}
4848
4949// 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 }]
5252 return res , ok
5353}
5454
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 {
5757 res := r
5858 res .Start .Line = s .InoToCppLine (sourceURI , r .Start .Line )
5959 res .End .Line = s .InoToCppLine (sourceURI , r .End .Line )
6060 return res
6161}
6262
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
6464// 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 ) {
6666 res := r
6767 if l , ok := s .InoToCppLineOk (sourceURI , r .Start .Line ); ok {
6868 res .Start .Line = l
@@ -78,14 +78,14 @@ func (s *InoMapper) InoToCppLSPRangeOk(sourceURI lsp.DocumentURI, r lsp.Range) (
7878}
7979
8080// 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 ]
8383 return res .File , res .Line
8484}
8585
8686// CppToInoRange converts a target (.cpp) lsp.Range into a source.ino:lsp.Range.
8787// 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 ) {
8989 inoFile , inoRange , err := s .CppToInoRangeOk (cppRange )
9090 if err != nil {
9191 panic (err .Error ())
@@ -105,7 +105,7 @@ func (e AdjustedRangeErr) Error() string {
105105// It returns an error if the range spans across multiple ino files.
106106// If the range ends on the beginning of a new line in another .ino file, the range
107107// 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 ) {
109109 inoFile , startLine := s .CppToInoLine (cppRange .Start .Line )
110110 endInoFile , endLine := s .CppToInoLine (cppRange .End .Line )
111111 inoRange := cppRange
@@ -131,36 +131,41 @@ func (s *InoMapper) CppToInoRangeOk(cppRange lsp.Range) (string, lsp.Range, erro
131131
132132// CppToInoLineOk converts a target (.cpp) line into a source (.ino) line and
133133// 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 ]
136136 return res .File , res .Line , ok
137137}
138138
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
140140// section added by the arduino preprocessor.
141- func (s * InoMapper ) IsPreprocessedCppLine (cppLine int ) bool {
141+ func (s * SketchMapper ) IsPreprocessedCppLine (cppLine int ) bool {
142142 _ , preprocessed := s .cppPreprocessed [cppLine ]
143- _ , mapsToIno := s .toIno [cppLine ]
143+ _ , mapsToIno := s .cppToIno [cppLine ]
144144 return preprocessed || ! mapsToIno
145145}
146146
147147// 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 {
154150 CppText : & SourceRevision {
155151 Version : 1 ,
156152 Text : string (targetFile ),
157153 },
158154 }
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 {}
159164
160165 sourceFile := ""
161166 sourceLine := - 1
162167 targetLine := 0
163- scanner := bufio .NewScanner (bytes .NewReader (targetFile ))
168+ scanner := bufio .NewScanner (bytes .NewReader ([] byte ( s . CppText . Text ) ))
164169 for scanner .Scan () {
165170 lineStr := scanner .Text ()
166171 if strings .HasPrefix (lineStr , "#line" ) {
@@ -170,27 +175,26 @@ func CreateInoMapper(targetFile []byte) *InoMapper {
170175 sourceLine = l - 1
171176 }
172177 sourceFile = paths .New (unquoteCppString (tokens [2 ])).Canonical ().String ()
173- mapper . toIno [targetLine ] = NotIno
178+ s . cppToIno [targetLine ] = NotIno
174179 } else if sourceFile != "" {
175- mapper .mapLine (sourceFile , sourceLine , targetLine )
180+ s .mapLine (sourceFile , sourceLine , targetLine )
176181 sourceLine ++
177182 } else {
178- mapper . toIno [targetLine ] = NotIno
183+ s . cppToIno [targetLine ] = NotIno
179184 }
180185 targetLine ++
181186 }
182- mapper .mapLine (sourceFile , sourceLine , targetLine )
183- return mapper
187+ s .mapLine (sourceFile , sourceLine , targetLine )
184188}
185189
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 {
189193 s .cppPreprocessed [line ] = inoLine
190194 s .inoPreprocessed [inoLine ] = line
191195 }
192- s .toCpp [inoLine ] = targetLine
193- s .toIno [ targetLine ] = inoLine
196+ s .inoToCpp [inoLine ] = cppLine
197+ s .cppToIno [ cppLine ] = inoLine
194198}
195199
196200func unquoteCppString (str string ) string {
@@ -205,9 +209,13 @@ func unquoteCppString(str string) string {
205209// ApplyTextChange performs the text change and updates both .ino and .cpp files.
206210// It returns true if the change is "dirty", this happens when the change alters preprocessed lines
207211// 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 ) {
209213 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 )
211219 deletedLines := inoRange .End .Line - inoRange .Start .Line
212220
213221 // Apply text changes
@@ -218,7 +226,7 @@ func (s *InoMapper) ApplyTextChange(inoURI lsp.DocumentURI, inoChange lsp.TextDo
218226 s .CppText .Text = newText
219227 s .CppText .Version ++
220228
221- if _ , is := s .inoPreprocessed [s .toIno [cppRange .Start .Line ]]; is {
229+ if _ , is := s .inoPreprocessed [s .cppToIno [cppRange .Start .Line ]]; is {
222230 dirty = true
223231 }
224232
@@ -227,24 +235,24 @@ func (s *InoMapper) ApplyTextChange(inoURI lsp.DocumentURI, inoChange lsp.TextDo
227235 dirty = dirty || s .deleteCppLine (cppRange .Start .Line )
228236 deletedLines --
229237 }
230- addedLines := strings .Count (inoChange .Text , "\n " ) - 1
238+ addedLines := strings .Count (inoChange .Text , "\n " )
231239 for addedLines > 0 {
232240 dirty = dirty || s .addInoLine (cppRange .Start .Line )
233241 addedLines --
234242 }
235243 return
236244}
237245
238- func (s * InoMapper ) addInoLine (cppLine int ) (dirty bool ) {
246+ func (s * SketchMapper ) addInoLine (cppLine int ) (dirty bool ) {
239247 preprocessToShiftCpp := map [InoLine ]bool {}
240248
241- addedInoLine := s .toIno [cppLine ]
242- carry := s .toIno [cppLine ]
249+ addedInoLine := s .cppToIno [cppLine ]
250+ carry := s .cppToIno [cppLine ]
243251 carry .Line ++
244252 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
248256 if ! ok {
249257 break
250258 }
@@ -282,23 +290,23 @@ func (s *InoMapper) addInoLine(cppLine int) (dirty bool) {
282290 inoPre .Line ++
283291 s .inoPreprocessed [inoPre ] = l
284292 s .cppPreprocessed [l ] = inoPre
285- s .toIno [l ] = inoPre
293+ s .cppToIno [l ] = inoPre
286294 }
287295
288296 return
289297}
290298
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 ]
293301 for i := line + 1 ; ; i ++ {
294- shifted , ok := s .toIno [i ]
302+ shifted , ok := s .cppToIno [i ]
295303 if ! ok {
296- delete (s .toIno , i - 1 )
304+ delete (s .cppToIno , i - 1 )
297305 break
298306 }
299- s .toIno [i - 1 ] = shifted
307+ s .cppToIno [i - 1 ] = shifted
300308 if shifted != NotIno {
301- s .toCpp [shifted ] = i - 1
309+ s .inoToCpp [shifted ] = i - 1
302310 }
303311 }
304312
@@ -310,20 +318,20 @@ func (s *InoMapper) deleteCppLine(line int) (dirty bool) {
310318 next := curr
311319 next .Line ++
312320
313- shifted , ok := s .toCpp [next ]
321+ shifted , ok := s .inoToCpp [next ]
314322 if ! ok {
315- delete (s .toCpp , curr )
323+ delete (s .inoToCpp , curr )
316324 break
317325 }
318- s .toCpp [curr ] = shifted
319- s .toIno [shifted ] = curr
326+ s .inoToCpp [curr ] = shifted
327+ s .cppToIno [shifted ] = curr
320328
321329 if l , ok := s .inoPreprocessed [next ]; ok {
322330 s .inoPreprocessed [curr ] = l
323331 s .cppPreprocessed [l ] = curr
324332 delete (s .inoPreprocessed , next )
325333
326- s .toIno [l ] = curr
334+ s .cppToIno [l ] = curr
327335 }
328336 }
329337 return
@@ -359,11 +367,25 @@ func dumpInoToCppMap(s map[InoLine]int) {
359367}
360368
361369// 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+ }
363374 cpp := strings .Split (s .CppText .Text , "\n " )
364375 log .Printf (" > Current sketchmapper content:" )
365376 for l , cppLine := range cpp {
366377 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 )
368390 }
369391}
0 commit comments