@@ -2,12 +2,93 @@ package components
22
33import (
44 "context"
5+
6+ protobuf "github.com/emicklei/proto"
57 "github.com/lasorda/protobuf-language-server/proto/view"
68
79 "github.com/lasorda/protobuf-language-server/go-lsp/logs"
810 "github.com/lasorda/protobuf-language-server/go-lsp/lsp/defines"
911)
1012
13+ // calculateEndPosition calculates the end position for a symbol based on its elements
14+ func calculateEndPosition (startLine int , elements []protobuf.Visitee ) uint {
15+ if len (elements ) == 0 {
16+ return uint (startLine )
17+ }
18+
19+ maxLine := startLine
20+ for _ , element := range elements {
21+ switch v := element .(type ) {
22+ case * protobuf.NormalField :
23+ if v .Position .Line > maxLine {
24+ maxLine = v .Position .Line
25+ }
26+ case * protobuf.MapField :
27+ if v .Position .Line > maxLine {
28+ maxLine = v .Position .Line
29+ }
30+ case * protobuf.Oneof :
31+ if v .Position .Line > maxLine {
32+ maxLine = v .Position .Line
33+ }
34+ case * protobuf.EnumField :
35+ if v .Position .Line > maxLine {
36+ maxLine = v .Position .Line
37+ }
38+ case * protobuf.Enum :
39+ if v .Position .Line > maxLine {
40+ maxLine = v .Position .Line
41+ }
42+ // Recursively check nested enum elements
43+ if nestedEnd := int (calculateEndPosition (v .Position .Line , v .Elements )); nestedEnd > maxLine {
44+ maxLine = nestedEnd
45+ }
46+ case * protobuf.Message :
47+ if v .Position .Line > maxLine {
48+ maxLine = v .Position .Line
49+ }
50+ // Recursively check nested message elements
51+ if nestedEnd := int (calculateEndPosition (v .Position .Line , v .Elements )); nestedEnd > maxLine {
52+ maxLine = nestedEnd
53+ }
54+ case * protobuf.RPC :
55+ if v .Position .Line > maxLine {
56+ maxLine = v .Position .Line
57+ }
58+ case * protobuf.Option :
59+ if v .Position .Line > maxLine {
60+ maxLine = v .Position .Line
61+ }
62+ }
63+ }
64+
65+ return uint (maxLine )
66+ }
67+
68+ // calculateMessageEndPosition calculates the end position for a message considering all nested elements
69+ func calculateMessageEndPosition (messageProto * protobuf.Message ) uint {
70+ if messageProto == nil {
71+ return 0
72+ }
73+ return calculateEndPosition (messageProto .Position .Line , messageProto .Elements )
74+ }
75+
76+ // calculateEnumEndPosition calculates the end position for an enum considering all its fields
77+ func calculateEnumEndPosition (enumProto * protobuf.Enum ) uint {
78+ if enumProto == nil {
79+ return 0
80+ }
81+ return calculateEndPosition (enumProto .Position .Line , enumProto .Elements )
82+ }
83+
84+ // calculateServiceEndPosition calculates the end position for a service considering all its RPCs
85+ func calculateServiceEndPosition (serviceProto * protobuf.Service ) uint {
86+ if serviceProto == nil {
87+ return 0
88+ }
89+ return calculateEndPosition (serviceProto .Position .Line , serviceProto .Elements )
90+ }
91+
1192func ProvideDocumentSymbol (ctx context.Context , req * defines.DocumentSymbolParams ) (result * []defines.DocumentSymbol , err error ) {
1293 if ! view .IsProtoFile (req .TextDocument .Uri ) {
1394 return nil , nil
@@ -19,90 +100,110 @@ func ProvideDocumentSymbol(ctx context.Context, req *defines.DocumentSymbolParam
19100 return & res , nil
20101 }
21102 for _ , pack := range file .Proto ().Packages () {
103+ packLine := pack .ProtoPackage .Position .Line - 1
22104 res = append (res , defines.DocumentSymbol {
23105 Name : pack .ProtoPackage .Name ,
24106 Kind : defines .SymbolKindPackage ,
25107 SelectionRange : defines.Range {
26- Start : defines.Position {Line : uint (pack . ProtoPackage . Position . Line - 1 )},
27- End : defines.Position {Line : uint (pack . ProtoPackage . Position . Line - 1 )},
108+ Start : defines.Position {Line : uint (packLine )},
109+ End : defines.Position {Line : uint (packLine )},
28110 },
29111 Range : defines.Range {
30- Start : defines.Position {Line : uint (pack . ProtoPackage . Position . Line - 1 )},
31- End : defines.Position {Line : uint (pack . ProtoPackage . Position . Line - 1 )},
112+ Start : defines.Position {Line : uint (packLine )},
113+ End : defines.Position {Line : uint (packLine )},
32114 },
33115 })
34116 }
35117 for _ , imp := range file .Proto ().Imports () {
118+ impLine := imp .ProtoImport .Position .Line - 1
36119 res = append (res , defines.DocumentSymbol {
37120 Name : imp .ProtoImport .Filename ,
38121 Kind : defines .SymbolKindFile ,
39122 SelectionRange : defines.Range {
40- Start : defines.Position {Line : uint (imp . ProtoImport . Position . Line - 1 )},
41- End : defines.Position {Line : uint (imp . ProtoImport . Position . Line - 1 )},
123+ Start : defines.Position {Line : uint (impLine )},
124+ End : defines.Position {Line : uint (impLine )},
42125 },
43126 Range : defines.Range {
44- Start : defines.Position {Line : uint (imp . ProtoImport . Position . Line - 1 )},
45- End : defines.Position {Line : uint (imp . ProtoImport . Position . Line - 1 )},
127+ Start : defines.Position {Line : uint (impLine )},
128+ End : defines.Position {Line : uint (impLine )},
46129 },
47130 })
48131
49132 }
50133 for _ , enums := range file .Proto ().Enums () {
134+ enumProto := enums .Protobuf ()
135+ startLine := enumProto .Position .Line - 1
136+ endLine := int (calculateEnumEndPosition (enumProto )) - 1
137+ if endLine < startLine {
138+ endLine = startLine
139+ }
51140 res = append (res , defines.DocumentSymbol {
52- Name : enums . Protobuf () .Name ,
141+ Name : enumProto .Name ,
53142 Kind : defines .SymbolKindEnum ,
54143 SelectionRange : defines.Range {
55- Start : defines.Position {Line : uint (enums . Protobuf (). Position . Line - 1 )},
56- End : defines.Position {Line : uint (enums . Protobuf (). Position . Line - 1 )},
144+ Start : defines.Position {Line : uint (startLine )},
145+ End : defines.Position {Line : uint (startLine )},
57146 },
58147 Range : defines.Range {
59- Start : defines.Position {Line : uint (enums . Protobuf (). Position . Line - 1 )},
60- End : defines.Position {Line : uint (enums . Protobuf (). Position . Line - 1 )},
148+ Start : defines.Position {Line : uint (startLine )},
149+ End : defines.Position {Line : uint (endLine )},
61150 },
62151 })
63152 }
64153 for _ , message := range file .Proto ().Messages () {
65154 message_proto := message .Protobuf ()
155+ startLine := message_proto .Position .Line - 1
156+ endLine := int (calculateMessageEndPosition (message_proto )) - 1
157+ if endLine < startLine {
158+ endLine = startLine
159+ }
66160 res = append (res , defines.DocumentSymbol {
67161 Name : message_proto .Name ,
68162 Kind : defines .SymbolKindClass ,
69163 SelectionRange : defines.Range {
70- Start : defines.Position {Line : uint (message_proto . Position . Line - 1 )},
71- End : defines.Position {Line : uint (message_proto . Position . Line - 1 )},
164+ Start : defines.Position {Line : uint (startLine )},
165+ End : defines.Position {Line : uint (startLine )},
72166 },
73167 Range : defines.Range {
74- Start : defines.Position {Line : uint (message_proto . Position . Line - 1 )},
75- End : defines.Position {Line : uint (message_proto . Position . Line - 1 )},
168+ Start : defines.Position {Line : uint (startLine )},
169+ End : defines.Position {Line : uint (endLine )},
76170 },
77171 })
78172 }
79173 for _ , service := range file .Proto ().Services () {
174+ serviceProto := service .Protobuf ()
175+ startLine := serviceProto .Position .Line - 1
176+ endLine := int (calculateServiceEndPosition (serviceProto )) - 1
177+ if endLine < startLine {
178+ endLine = startLine
179+ }
80180 service_sym := defines.DocumentSymbol {
81- Name : service . Protobuf () .Name ,
181+ Name : serviceProto .Name ,
82182 Kind : defines .SymbolKindNamespace ,
83183 SelectionRange : defines.Range {
84- Start : defines.Position {Line : uint (service . Protobuf (). Position . Line - 1 )},
85- End : defines.Position {Line : uint (service . Protobuf (). Position . Line - 1 )},
184+ Start : defines.Position {Line : uint (startLine )},
185+ End : defines.Position {Line : uint (startLine )},
86186 },
87187 Range : defines.Range {
88- Start : defines.Position {Line : uint (service . Protobuf (). Position . Line - 1 )},
89- End : defines.Position {Line : uint (service . Protobuf (). Position . Line - 1 )},
188+ Start : defines.Position {Line : uint (startLine )},
189+ End : defines.Position {Line : uint (endLine )},
90190 },
91191
92192 Children : & []defines.DocumentSymbol {},
93193 }
94194 child := []defines.DocumentSymbol {}
95195 for _ , rpc := range service .RPCs () {
196+ rpcLine := rpc .ProtoRPC .Position .Line - 1
96197 rpc := defines.DocumentSymbol {
97198 Name : rpc .ProtoRPC .Name ,
98199 Kind : defines .SymbolKindMethod ,
99200 SelectionRange : defines.Range {
100- Start : defines.Position {Line : uint (rpc . ProtoRPC . Position . Line - 1 )},
101- End : defines.Position {Line : uint (rpc . ProtoRPC . Position . Line - 1 )},
201+ Start : defines.Position {Line : uint (rpcLine )},
202+ End : defines.Position {Line : uint (rpcLine )},
102203 },
103204 Range : defines.Range {
104- Start : defines.Position {Line : uint (rpc . ProtoRPC . Position . Line - 1 )},
105- End : defines.Position {Line : uint (rpc . ProtoRPC . Position . Line - 1 )},
205+ Start : defines.Position {Line : uint (rpcLine )},
206+ End : defines.Position {Line : uint (rpcLine )},
106207 },
107208 }
108209 child = append (child , rpc )
0 commit comments