@@ -3,17 +3,20 @@ package proxy
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "os"
7
+ "path/filepath"
6
8
"regexp"
7
9
"strings"
8
10
9
11
"github.com/a-h/parse"
10
12
lsp "github.com/a-h/protocol"
13
+ "go.lsp.dev/uri"
14
+ "go.uber.org/zap"
15
+
11
16
"github.com/a-h/templ"
12
17
"github.com/a-h/templ/cmd/templ/imports"
13
18
"github.com/a-h/templ/generator"
14
19
"github.com/a-h/templ/parser/v2"
15
- "go.lsp.dev/uri"
16
- "go.uber.org/zap"
17
20
)
18
21
19
22
// Server is responsible for rewriting messages that are
@@ -37,6 +40,7 @@ type Server struct {
37
40
DiagnosticCache * DiagnosticCache
38
41
TemplSource * DocumentContents
39
42
GoSource map [string ]string
43
+ preLoadURIs []* lsp.DidOpenTextDocumentParams
40
44
}
41
45
42
46
func NewServer (log * zap.Logger , target lsp.Server , cache * SourceMapCache , diagnosticCache * DiagnosticCache ) (s * Server ) {
@@ -81,6 +85,7 @@ func (p *Server) convertTemplRangeToGoRange(templURI lsp.DocumentURI, input lsp.
81
85
var sourceMap * parser.SourceMap
82
86
sourceMap , ok = p .SourceMapCache .Get (string (templURI ))
83
87
if ! ok {
88
+ p .Log .Warn ("templ->go: sourcemap not found in cache" )
84
89
return
85
90
}
86
91
// Map from the source position to target Go position.
@@ -101,6 +106,7 @@ func (p *Server) convertGoRangeToTemplRange(templURI lsp.DocumentURI, input lsp.
101
106
output = input
102
107
sourceMap , ok := p .SourceMapCache .Get (string (templURI ))
103
108
if ! ok {
109
+ p .Log .Warn ("go->templ: sourcemap not found in cache" )
104
110
return
105
111
}
106
112
// Map from the source position to target Go position.
@@ -228,6 +234,62 @@ func (p *Server) Initialize(ctx context.Context, params *lsp.InitializeParams) (
228
234
Save : & lsp.SaveOptions {IncludeText : true },
229
235
}
230
236
237
+ for _ , c := range params .WorkspaceFolders {
238
+ path := strings .TrimPrefix (c .URI , "file://" )
239
+ werr := filepath .Walk (path , func (path string , info os.FileInfo , err error ) error {
240
+ if err != nil {
241
+ return err
242
+ }
243
+ p .Log .Info ("found file" , zap .String ("path" , path ))
244
+ uri := uri .URI ("file://" + path )
245
+ isTemplFile , goURI := convertTemplToGoURI (uri )
246
+
247
+ if ! isTemplFile {
248
+ p .Log .Info ("not a templ file" , zap .String ("uri" , string (uri )))
249
+ return nil
250
+ }
251
+
252
+ b , err := os .ReadFile (path )
253
+ if err != nil {
254
+ return err
255
+ }
256
+ p .TemplSource .Set (string (uri ), NewDocument (p .Log , string (b )))
257
+ // Parse the template.
258
+ template , ok , err := p .parseTemplate (ctx , uri , string (b ))
259
+ if err != nil {
260
+ p .Log .Error ("parseTemplate failure" , zap .Error (err ))
261
+ }
262
+ if ! ok {
263
+ p .Log .Info ("parsing template did not succeed" , zap .String ("uri" , string (uri )))
264
+ return nil
265
+ }
266
+ w := new (strings.Builder )
267
+ sm , _ , err := generator .Generate (template , w )
268
+ if err != nil {
269
+ return fmt .Errorf ("generate failure: %w" , err )
270
+ }
271
+ p .Log .Info ("setting source map cache contents" , zap .String ("uri" , string (uri )))
272
+ p .SourceMapCache .Set (string (uri ), sm )
273
+ // Set the Go contents.
274
+ p .GoSource [string (uri )] = w .String ()
275
+
276
+ didOpenParams := & lsp.DidOpenTextDocumentParams {
277
+ TextDocument : lsp.TextDocumentItem {
278
+ URI : goURI ,
279
+ Text : w .String (),
280
+ Version : 1 ,
281
+ LanguageID : "go" ,
282
+ },
283
+ }
284
+
285
+ p .preLoadURIs = append (p .preLoadURIs , didOpenParams )
286
+ return nil
287
+ })
288
+ if werr != nil {
289
+ p .Log .Error ("walk error" , zap .Error (werr ))
290
+ }
291
+ }
292
+
231
293
result .ServerInfo .Name = "templ-lsp"
232
294
result .ServerInfo .Version = templ .Version ()
233
295
@@ -237,7 +299,17 @@ func (p *Server) Initialize(ctx context.Context, params *lsp.InitializeParams) (
237
299
func (p * Server ) Initialized (ctx context.Context , params * lsp.InitializedParams ) (err error ) {
238
300
p .Log .Info ("client -> server: Initialized" )
239
301
defer p .Log .Info ("client -> server: Initialized end" )
240
- return p .Target .Initialized (ctx , params )
302
+ goInitErr := p .Target .Initialized (ctx , params )
303
+
304
+ for i , doParams := range p .preLoadURIs {
305
+ doErr := p .Target .DidOpen (ctx , doParams )
306
+ if doErr != nil {
307
+ return doErr
308
+ }
309
+ p .preLoadURIs [i ] = nil
310
+ }
311
+
312
+ return goInitErr
241
313
}
242
314
243
315
func (p * Server ) Shutdown (ctx context.Context ) (err error ) {
@@ -464,8 +536,8 @@ func getPackageFromItemDetail(pkg string) string {
464
536
}
465
537
466
538
type importInsert struct {
467
- LineIndex int
468
539
Text string
540
+ LineIndex int
469
541
}
470
542
471
543
var nonImportKeywordRegexp = regexp .MustCompile (`^(?:templ|func|css|script|var|const|type)\s` )
2 commit comments
a-h commentedon Sep 25, 2024
There are incorrectly cased files in this commit. They will need to be fixed to
remotechild.templ
andremoteparent.templ
.joerdav commentedon Sep 25, 2024
Good point, I missed that one