1
1
import ast
2
2
import itertools
3
- from typing import TYPE_CHECKING , Any , List , Optional , Union , cast
3
+ from typing import TYPE_CHECKING , Any , List , Optional , Union
4
4
5
+ from robot .errors import VariableError
5
6
from robot .parsing .lexer .tokens import Token
7
+ from robot .parsing .model .blocks import Keyword , Section , TestCase
8
+ from robot .parsing .model .statements import Statement
9
+ from robot .variables import search_variable
6
10
from robotcode .core .lsp .types import DocumentSymbol , SymbolInformation , SymbolKind
7
11
from robotcode .core .utils .logging import LoggingDescriptor
8
12
from robotcode .robot .utils .ast import range_from_node , range_from_token , tokenize_variables
@@ -29,7 +33,7 @@ def __init__(self, parent: "RobotLanguageServerProtocol") -> None:
29
33
def collect (
30
34
self , sender : Any , document : TextDocument
31
35
) -> Optional [Union [List [DocumentSymbol ], List [SymbolInformation ], None ]]:
32
- return _Visitor .find_from (self .parent .documents_cache .get_model (document ), self )
36
+ return _Visitor .find_from (self .parent .documents_cache .get_model (document , False ), self )
33
37
34
38
35
39
class _Visitor (Visitor ):
@@ -56,22 +60,14 @@ def find_from(cls, model: ast.AST, parent: RobotDocumentSymbolsProtocolPart) ->
56
60
57
61
return finder .result if finder .result else None
58
62
59
- def visit_Section (self , node : ast .AST ) -> None : # noqa: N802
60
- from robot .parsing .model .blocks import Section
61
- from robot .parsing .model .statements import SectionHeader
62
-
63
- section = cast (Section , node )
64
- if section .header is None :
65
- return
66
-
67
- header = cast (SectionHeader , section .header )
68
- if not header .name :
63
+ def visit_Section (self , node : Section ) -> None : # noqa: N802
64
+ if not node .header or not node .header .name :
69
65
return
70
66
71
- r = range_from_node (section )
67
+ r = range_from_node (node )
72
68
symbol = DocumentSymbol (
73
- name = header .name . replace ( "*" , "" ). strip () ,
74
- kind = SymbolKind .NAMESPACE ,
69
+ name = node . header .name ,
70
+ kind = SymbolKind .MODULE ,
75
71
range = r ,
76
72
selection_range = r ,
77
73
children = [],
@@ -81,45 +77,33 @@ def visit_Section(self, node: ast.AST) -> None: # noqa: N802
81
77
82
78
self .generic_visit_current_symbol (node , symbol )
83
79
84
- def visit_TestCase (self , node : ast .AST ) -> None : # noqa: N802
85
- from robot .parsing .model .blocks import TestCase
86
-
87
- testcase = cast (TestCase , node )
88
- if testcase .name is None :
80
+ def visit_TestCase (self , node : TestCase ) -> None : # noqa: N802
81
+ if node .name is None :
89
82
return
90
83
91
84
if self .current_symbol is not None and self .current_symbol .children is not None :
92
- r = range_from_node (testcase )
93
- symbol = DocumentSymbol (name = testcase .name , kind = SymbolKind .METHOD , range = r , selection_range = r , children = [])
85
+ r = range_from_node (node )
86
+ symbol = DocumentSymbol (name = node .name , kind = SymbolKind .METHOD , range = r , selection_range = r , children = [])
94
87
self .current_symbol .children .append (symbol )
95
88
96
89
self .generic_visit_current_symbol (node , symbol )
97
90
98
- def visit_Keyword (self , node : ast .AST ) -> None : # noqa: N802
99
- from robot .parsing .model .blocks import Keyword
100
-
101
- keyword = cast (Keyword , node )
102
- if keyword .name is None :
91
+ def visit_Keyword (self , node : Keyword ) -> None : # noqa: N802
92
+ if node .name is None :
103
93
return
104
94
105
95
if self .current_symbol is not None and self .current_symbol .children is not None :
106
- r = range_from_node (keyword )
107
- symbol = DocumentSymbol (
108
- name = keyword .name , kind = SymbolKind .FUNCTION , range = r , selection_range = r , children = []
109
- )
96
+ r = range_from_node (node )
97
+ symbol = DocumentSymbol (name = node .name , kind = SymbolKind .FUNCTION , range = r , selection_range = r , children = [])
110
98
self .current_symbol .children .append (symbol )
111
99
112
100
self .generic_visit_current_symbol (node , symbol )
113
101
114
- def visit_Arguments (self , node : ast .AST ) -> None : # noqa: N802
115
- from robot .parsing .lexer .tokens import Token as RobotToken
116
- from robot .parsing .model .statements import Arguments
117
-
118
- n = cast (Arguments , node )
119
- arguments = n .get_tokens (RobotToken .ARGUMENT )
102
+ def visit_Arguments (self , node : Statement ) -> None : # noqa: N802
103
+ arguments = node .get_tokens (Token .ARGUMENT )
120
104
121
105
if self .current_symbol is not None and self .current_symbol .children is not None :
122
- for argument_token in ( cast ( RobotToken , e ) for e in arguments ) :
106
+ for argument_token in arguments :
123
107
if argument_token .value == "@{}" :
124
108
continue
125
109
@@ -133,29 +117,22 @@ def visit_Arguments(self, node: ast.AST) -> None: # noqa: N802
133
117
self .current_symbol .children .append (symbol )
134
118
135
119
def get_variable_token (self , token : Token ) -> Optional [Token ]:
136
- from robot .parsing .lexer .tokens import Token as RobotToken
137
-
138
120
return next (
139
121
(
140
122
v
141
123
for v in itertools .dropwhile (
142
- lambda t : t .type in RobotToken .NON_DATA_TOKENS ,
124
+ lambda t : t .type in Token .NON_DATA_TOKENS ,
143
125
tokenize_variables (token , ignore_errors = True ),
144
126
)
145
- if v .type == RobotToken .VARIABLE
127
+ if v .type == Token .VARIABLE
146
128
),
147
129
None ,
148
130
)
149
131
150
- def visit_KeywordCall (self , node : ast .AST ) -> None : # noqa: N802
151
- from robot .errors import VariableError
152
- from robot .parsing .lexer .tokens import Token as RobotToken
153
- from robot .parsing .model .statements import KeywordCall
154
-
132
+ def visit_KeywordCall (self , node : Statement ) -> None : # noqa: N802
155
133
# TODO analyse "Set Local/Global/Suite Variable"
156
134
157
- keyword_call = cast (KeywordCall , node )
158
- for assign_token in keyword_call .get_tokens (RobotToken .ASSIGN ):
135
+ for assign_token in node .get_tokens (Token .ASSIGN ):
159
136
if assign_token is None :
160
137
continue
161
138
@@ -175,12 +152,8 @@ def visit_KeywordCall(self, node: ast.AST) -> None: # noqa: N802
175
152
except VariableError :
176
153
pass
177
154
178
- def visit_ForHeader (self , node : ast .AST ) -> None : # noqa: N802
179
- from robot .parsing .lexer .tokens import Token as RobotToken
180
- from robot .parsing .model .statements import ForHeader
181
-
182
- n = cast (ForHeader , node )
183
- variables = n .get_tokens (RobotToken .VARIABLE )
155
+ def visit_ForHeader (self , node : Statement ) -> None : # noqa: N802
156
+ variables = node .get_tokens (Token .VARIABLE )
184
157
185
158
if self .current_symbol is not None and self .current_symbol .children is not None :
186
159
for variable in variables :
@@ -193,12 +166,8 @@ def visit_ForHeader(self, node: ast.AST) -> None: # noqa: N802
193
166
if symbol .name not in map (lambda v : v .name , self .current_symbol .children ):
194
167
self .current_symbol .children .append (symbol )
195
168
196
- def visit_ExceptHeader (self , node : ast .AST ) -> None : # noqa: N802
197
- from robot .parsing .lexer .tokens import Token as RobotToken
198
- from robot .parsing .model .statements import ExceptHeader
199
-
200
- n = cast (ExceptHeader , node )
201
- variables = n .get_tokens (RobotToken .VARIABLE )
169
+ def visit_ExceptHeader (self , node : Statement ) -> None : # noqa: N802
170
+ variables = node .get_tokens (Token .VARIABLE )
202
171
203
172
if self .current_symbol is not None and self .current_symbol .children is not None :
204
173
for variable in variables :
@@ -211,12 +180,8 @@ def visit_ExceptHeader(self, node: ast.AST) -> None: # noqa: N802
211
180
if symbol .name not in map (lambda v : v .name , self .current_symbol .children ):
212
181
self .current_symbol .children .append (symbol )
213
182
214
- def visit_Var (self , node : ast .AST ) -> None : # noqa: N802
215
- from robot .parsing .lexer .tokens import Token as RobotToken
216
- from robot .parsing .model .statements import Var
217
-
218
- n = cast (Var , node )
219
- variables = n .get_tokens (RobotToken .VARIABLE )
183
+ def visit_Var (self , node : Statement ) -> None : # noqa: N802
184
+ variables = node .get_tokens (Token .VARIABLE )
220
185
221
186
if self .current_symbol is not None and self .current_symbol .children is not None :
222
187
for variable in variables :
@@ -229,20 +194,14 @@ def visit_Var(self, node: ast.AST) -> None: # noqa: N802
229
194
if symbol .name not in map (lambda v : v .name , self .current_symbol .children ):
230
195
self .current_symbol .children .append (symbol )
231
196
232
- def visit_KeywordName (self , node : ast .AST ) -> None : # noqa: N802
233
- from robot .parsing .lexer .tokens import Token as RobotToken
234
- from robot .parsing .model .statements import KeywordName
235
-
236
- n = cast (KeywordName , node )
237
- nt = n .get_token (RobotToken .KEYWORD_NAME )
238
- if nt is None :
197
+ def visit_KeywordName (self , node : Statement ) -> None : # noqa: N802
198
+ name_token = node .get_token (Token .KEYWORD_NAME )
199
+ if name_token is None :
239
200
return
240
201
241
- name_token = cast (Token , nt )
242
-
243
202
if self .current_symbol is not None and self .current_symbol .children is not None :
244
203
for variable in filter (
245
- lambda e : e .type == RobotToken .VARIABLE ,
204
+ lambda e : e .type == Token .VARIABLE ,
246
205
tokenize_variables (name_token , identifiers = "$" , ignore_errors = True ),
247
206
):
248
207
variable_token = self .get_variable_token (variable )
@@ -254,14 +213,8 @@ def visit_KeywordName(self, node: ast.AST) -> None: # noqa: N802
254
213
if symbol .name not in map (lambda v : v .name , self .current_symbol .children ):
255
214
self .current_symbol .children .append (symbol )
256
215
257
- def visit_Variable (self , node : ast .AST ) -> None : # noqa: N802
258
- from robot .api .parsing import Token as RobotToken
259
- from robot .parsing .model .statements import Variable
260
- from robot .variables import search_variable
261
-
262
- variable = cast (Variable , node )
263
-
264
- name_token = variable .get_token (RobotToken .VARIABLE )
216
+ def visit_Variable (self , node : Statement ) -> None : # noqa: N802
217
+ name_token = node .get_token (Token .VARIABLE )
265
218
name = name_token .value
266
219
267
220
if name is not None :
@@ -273,6 +226,6 @@ def visit_Variable(self, node: ast.AST) -> None: # noqa: N802
273
226
name = name [:- 1 ].rstrip ()
274
227
275
228
if self .current_symbol is not None and self .current_symbol .children is not None :
276
- r = range_from_node (variable )
229
+ r = range_from_node (node )
277
230
symbol = DocumentSymbol (name = name , kind = SymbolKind .VARIABLE , range = r , selection_range = r )
278
231
self .current_symbol .children .append (symbol )
0 commit comments