@@ -5,129 +5,101 @@ import (
5
5
6
6
"github.com/docker/docker-language-server/internal/pkg/document"
7
7
"github.com/docker/docker-language-server/internal/tliron/glsp/protocol"
8
- "gopkg.in/yaml.v3"
8
+ "github.com/goccy/go-yaml/ast"
9
+ "github.com/goccy/go-yaml/token"
9
10
)
10
11
11
- func DocumentSymbol (ctx context.Context , doc document.ComposeDocument ) (result []any , err error ) {
12
- root := doc .RootNode ()
13
- if len (root .Content ) > 0 {
14
- for i := range root .Content [0 ].Content {
15
- switch root .Content [0 ].Content [i ].Value {
16
- case "services" :
17
- symbols := createSymbol (root .Content [0 ].Content , i + 1 , protocol .SymbolKindClass )
18
- result = append (result , symbols ... )
19
- case "networks" :
20
- symbols := createSymbol (root .Content [0 ].Content , i + 1 , protocol .SymbolKindInterface )
21
- result = append (result , symbols ... )
22
- case "volumes" :
23
- symbols := createSymbol (root .Content [0 ].Content , i + 1 , protocol .SymbolKindFile )
24
- result = append (result , symbols ... )
25
- case "configs" :
26
- symbols := createSymbol (root .Content [0 ].Content , i + 1 , protocol .SymbolKindVariable )
27
- result = append (result , symbols ... )
28
- case "secrets" :
29
- symbols := createSymbol (root .Content [0 ].Content , i + 1 , protocol .SymbolKindKey )
30
- result = append (result , symbols ... )
31
- case "include" :
32
- for _ , included := range root .Content [0 ].Content [i + 1 ].Content {
33
- switch included .Kind {
34
- case yaml .MappingNode :
35
- // long syntax with an object
36
- for j := range included .Content {
37
- if included .Content [j ].Value == "path" {
38
- switch included .Content [j + 1 ].Kind {
39
- case yaml .SequenceNode :
40
- for _ , path := range included .Content [j + 1 ].Content {
41
- character := uint32 (path .Column - 1 )
42
- rng := protocol.Range {
43
- Start : protocol.Position {
44
- Line : uint32 (path .Line - 1 ),
45
- Character : character ,
46
- },
47
- End : protocol.Position {
48
- Line : uint32 (path .Line - 1 ),
49
- Character : character + uint32 (len (path .Value )),
50
- },
51
- }
52
- result = append (result , & protocol.DocumentSymbol {
53
- Name : path .Value ,
54
- Kind : protocol .SymbolKindModule ,
55
- Range : rng ,
56
- SelectionRange : rng ,
57
- })
58
- }
59
- case yaml .ScalarNode :
60
- character := uint32 (included .Content [j + 1 ].Column - 1 )
61
- rng := protocol.Range {
62
- Start : protocol.Position {
63
- Line : uint32 (included .Content [j + 1 ].Line - 1 ),
64
- Character : character ,
65
- },
66
- End : protocol.Position {
67
- Line : uint32 (included .Content [j + 1 ].Line - 1 ),
68
- Character : character + uint32 (len (included .Content [j + 1 ].Value )),
69
- },
70
- }
71
- result = append (result , & protocol.DocumentSymbol {
72
- Name : included .Content [j + 1 ].Value ,
73
- Kind : protocol .SymbolKindModule ,
74
- Range : rng ,
75
- SelectionRange : rng ,
76
- })
77
- }
12
+ var symbolKinds = map [string ]protocol.SymbolKind {
13
+ "services" : protocol .SymbolKindClass ,
14
+ "networks" : protocol .SymbolKindInterface ,
15
+ "volumes" : protocol .SymbolKindFile ,
16
+ "configs" : protocol .SymbolKindVariable ,
17
+ "secrets" : protocol .SymbolKindKey ,
18
+ }
19
+
20
+ func findSymbols (value string , n * ast.MappingValueNode , mapping map [string ]protocol.SymbolKind ) (result []any ) {
21
+ if kind , ok := mapping [value ]; ok {
22
+ if mappingNode , ok := n .Value .(* ast.MappingNode ); ok {
23
+ for _ , service := range mappingNode .Values {
24
+ result = append (result , createSymbol (service .Key .GetToken (), kind ))
25
+ }
26
+ } else if n , ok := n .Value .(* ast.MappingValueNode ); ok {
27
+ result = append (result , createSymbol (n .Key .GetToken (), kind ))
28
+ }
29
+ } else if value == "include" {
30
+ if sequenceNode , ok := n .Value .(* ast.SequenceNode ); ok {
31
+ for _ , include := range sequenceNode .Values {
32
+ if _ , ok := include .(* ast.StringNode ); ok {
33
+ // include:
34
+ // - abc.yml
35
+ // - def.yml
36
+ result = append (result , createSymbol (include .GetToken (), protocol .SymbolKindModule ))
37
+ } else if includeNode , ok := include .(* ast.MappingValueNode ); ok {
38
+ if includeNode .Key .GetToken ().Value == "path" {
39
+ // include:
40
+ // - path:
41
+ // - ../commons/compose.yaml
42
+ // - ./commons-override.yaml
43
+ if included , ok := includeNode .Value .(* ast.SequenceNode ); ok {
44
+ for _ , path := range included .Values {
45
+ result = append (result , createSymbol (path .GetToken (), protocol .SymbolKindModule ))
78
46
}
79
47
}
80
- case yaml .ScalarNode :
81
- // include:
82
- // - abc.yml
83
- // - def.yml
84
- character := uint32 (included .Column - 1 )
85
- rng := protocol.Range {
86
- Start : protocol.Position {
87
- Line : uint32 (included .Line - 1 ),
88
- Character : character ,
89
- },
90
- End : protocol.Position {
91
- Line : uint32 (included .Line - 1 ),
92
- Character : character + uint32 (len (included .Value )),
93
- },
48
+ }
49
+ } else if includeNode , ok := include .(* ast.MappingNode ); ok {
50
+ // include:
51
+ // - path: ../commons/compose.yaml
52
+ // project_directory: ..
53
+ // env_file: ../another/.env
54
+ for _ , attribute := range includeNode .Values {
55
+ if attribute .Key .GetToken ().Value == "path" {
56
+ result = append (result , createSymbol (attribute .Value .GetToken (), protocol .SymbolKindModule ))
94
57
}
95
- result = append (result , & protocol.DocumentSymbol {
96
- Name : included .Value ,
97
- Kind : protocol .SymbolKindModule ,
98
- Range : rng ,
99
- SelectionRange : rng ,
100
- })
101
58
}
102
59
}
103
60
}
104
61
}
105
62
}
106
- return result , nil
63
+ return result
107
64
}
108
65
109
- func createSymbol (nodes []* yaml.Node , idx int , kind protocol.SymbolKind ) (result []any ) {
110
- for i := 0 ; i < len (nodes [idx ].Content ); i += 2 {
111
- service := nodes [idx ].Content [i ]
112
- if service .Value != "" {
113
- character := uint32 (service .Column - 1 )
114
- rng := protocol.Range {
115
- Start : protocol.Position {
116
- Line : uint32 (service .Line - 1 ),
117
- Character : character ,
118
- },
119
- End : protocol.Position {
120
- Line : uint32 (service .Line - 1 ),
121
- Character : character + uint32 (len (service .Value )),
122
- },
66
+ func DocumentSymbol (ctx context.Context , doc document.ComposeDocument ) (result []any , err error ) {
67
+ file := doc .File ()
68
+ if file == nil || len (file .Docs ) == 0 {
69
+ return nil , nil
70
+ }
71
+
72
+ for _ , documentNode := range file .Docs {
73
+ if n , ok := documentNode .Body .(* ast.MappingValueNode ); ok {
74
+ if s , ok := n .Key .(* ast.StringNode ); ok {
75
+ result = append (result , findSymbols (s .Value , n , symbolKinds )... )
76
+ }
77
+ } else if mappingNode , ok := documentNode .Body .(* ast.MappingNode ); ok {
78
+ for _ , n := range mappingNode .Values {
79
+ if s , ok := n .Key .(* ast.StringNode ); ok {
80
+ result = append (result , findSymbols (s .Value , n , symbolKinds )... )
81
+ }
123
82
}
124
- result = append (result , & protocol.DocumentSymbol {
125
- Name : service .Value ,
126
- Kind : kind ,
127
- Range : rng ,
128
- SelectionRange : rng ,
129
- })
130
83
}
131
84
}
132
- return result
85
+ return result , nil
86
+ }
87
+
88
+ func createSymbol (t * token.Token , kind protocol.SymbolKind ) * protocol.DocumentSymbol {
89
+ rng := protocol.Range {
90
+ Start : protocol.Position {
91
+ Line : uint32 (t .Position .Line - 1 ),
92
+ Character : uint32 (t .Position .Column - 1 ),
93
+ },
94
+ End : protocol.Position {
95
+ Line : uint32 (t .Position .Line - 1 ),
96
+ Character : uint32 (t .Position .Column - 1 + len (t .Value )),
97
+ },
98
+ }
99
+ return & protocol.DocumentSymbol {
100
+ Name : t .Value ,
101
+ Kind : kind ,
102
+ Range : rng ,
103
+ SelectionRange : rng ,
104
+ }
133
105
}
0 commit comments