@@ -2,6 +2,7 @@ package lspcmd
22
33import (
44 "context"
5+ "encoding/json"
56 "fmt"
67 "io"
78 "os"
@@ -14,6 +15,7 @@ import (
1415 "github.com/a-h/templ/cmd/templ/generatecmd/modcheck"
1516 "github.com/a-h/templ/cmd/templ/lspcmd/lspdiff"
1617 "github.com/a-h/templ/cmd/templ/testproject"
18+ "github.com/google/go-cmp/cmp"
1719 "go.lsp.dev/jsonrpc2"
1820 "go.lsp.dev/uri"
1921 "go.uber.org/zap"
@@ -603,6 +605,139 @@ func TestCodeAction(t *testing.T) {
603605 }
604606}
605607
608+ func TestDocumentSymbol (t * testing.T ) {
609+ if testing .Short () {
610+ return
611+ }
612+
613+ ctx , cancel := context .WithCancel (context .Background ())
614+ log , _ := zap .NewProduction ()
615+
616+ ctx , appDir , _ , server , teardown , err := Setup (ctx , log )
617+ if err != nil {
618+ t .Fatalf ("failed to setup test: %v" , err )
619+ }
620+ defer teardown (t )
621+ defer cancel ()
622+
623+ tests := []struct {
624+ uri string
625+ expect []any
626+ }{
627+ {
628+ uri : "file://" + appDir + "/templates.templ" ,
629+ expect : []any {
630+ protocol.SymbolInformation {
631+ Name : "Page" ,
632+ Kind : protocol .SymbolKindFunction ,
633+ Location : protocol.Location {
634+ Range : protocol.Range {
635+ Start : protocol.Position {Line : 11 , Character : 0 },
636+ End : protocol.Position {Line : 50 , Character : 1 },
637+ },
638+ },
639+ },
640+ protocol.SymbolInformation {
641+ Name : "nihao" ,
642+ Kind : protocol .SymbolKindVariable ,
643+ Location : protocol.Location {
644+ Range : protocol.Range {
645+ Start : protocol.Position {Line : 18 , Character : 4 },
646+ End : protocol.Position {Line : 18 , Character : 16 },
647+ },
648+ },
649+ },
650+ protocol.SymbolInformation {
651+ Name : "Struct" ,
652+ Kind : protocol .SymbolKindStruct ,
653+ Location : protocol.Location {
654+ Range : protocol.Range {
655+ Start : protocol.Position {Line : 20 , Character : 5 },
656+ End : protocol.Position {Line : 22 , Character : 1 },
657+ },
658+ },
659+ },
660+ protocol.SymbolInformation {
661+ Name : "s" ,
662+ Kind : protocol .SymbolKindVariable ,
663+ Location : protocol.Location {
664+ Range : protocol.Range {
665+ Start : protocol.Position {Line : 24 , Character : 4 },
666+ End : protocol.Position {Line : 24 , Character : 16 },
667+ },
668+ },
669+ },
670+ },
671+ },
672+ {
673+ uri : "file://" + appDir + "/remoteparent.templ" ,
674+ expect : []any {
675+ protocol.SymbolInformation {
676+ Name : "RemoteInclusionTest" ,
677+ Kind : protocol .SymbolKindFunction ,
678+ Location : protocol.Location {
679+ Range : protocol.Range {
680+ Start : protocol.Position {Line : 9 , Character : 0 },
681+ End : protocol.Position {Line : 35 , Character : 1 },
682+ },
683+ },
684+ },
685+ protocol.SymbolInformation {
686+ Name : "Remote2" ,
687+ Kind : protocol .SymbolKindFunction ,
688+ Location : protocol.Location {
689+ Range : protocol.Range {
690+ Start : protocol.Position {Line : 37 , Character : 0 },
691+ End : protocol.Position {Line : 63 , Character : 1 },
692+ },
693+ },
694+ },
695+ },
696+ },
697+ }
698+
699+ for i , test := range tests {
700+ t .Run (fmt .Sprintf ("test-%d" , i ), func (t * testing.T ) {
701+ actual , err := server .DocumentSymbol (ctx , & protocol.DocumentSymbolParams {
702+ TextDocument : protocol.TextDocumentIdentifier {
703+ URI : uri .URI (test .uri ),
704+ },
705+ })
706+ if err != nil {
707+ t .Errorf ("failed to get document symbol: %v" , err )
708+ }
709+
710+ // set expected URI
711+ for i := range test .expect {
712+ switch v := test .expect [i ].(type ) {
713+ case protocol.SymbolInformation :
714+ v .Location .URI = uri .URI (test .uri )
715+ test .expect [i ] = v
716+ }
717+ }
718+
719+ expectdSlice , err := sliceToAnySlice (test .expect )
720+ if err != nil {
721+ t .Errorf ("failed to convert expect to any slice: %v" , err )
722+ }
723+ diff := cmp .Diff (expectdSlice , actual )
724+ if diff != "" {
725+ t .Errorf ("unexpected document symbol: %v" , diff )
726+ }
727+ })
728+ }
729+ }
730+
731+ func sliceToAnySlice (in []any ) ([]any , error ) {
732+ b , err := json .Marshal (in )
733+ if err != nil {
734+ return nil , err
735+ }
736+ out := make ([]any , 0 , len (in ))
737+ err = json .Unmarshal (b , & out )
738+ return out , err
739+ }
740+
606741func runeIndexToUTF8ByteIndex (s string , runeIndex int ) (lspChar uint32 , err error ) {
607742 for i , r := range []rune (s ) {
608743 if i == runeIndex {
0 commit comments