Skip to content

Commit 0f8c134

Browse files
committed
perf(robotlangserver): refactor some unnecessary async/await methods
1 parent 40b7512 commit 0f8c134

File tree

8 files changed

+90
-61
lines changed

8 files changed

+90
-61
lines changed

robotcode/language_server/robotframework/diagnostics/analyzer.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def __init__(self, model: ast.AST, namespace: Namespace) -> None:
6969
self._diagnostics: List[Diagnostic] = []
7070
self._keyword_references: Dict[KeywordDoc, Set[Location]] = defaultdict(set)
7171
self._variable_references: Dict[VariableDefinition, Set[Location]] = defaultdict(set)
72+
self._ignored_lines: Optional[List[int]] = None
7273

7374
async def run(self) -> AnalyzerResult:
7475
self._diagnostics = []
@@ -280,15 +281,28 @@ async def __get_ignored_lines(document: TextDocument) -> List[int]:
280281

281282
return result
282283

284+
@classmethod
285+
async def should_ignore(cls, document: Optional[TextDocument], range: Range) -> bool:
286+
return cls.__should_ignore(await cls.get_ignored_lines(document) if document is not None else [], range)
287+
288+
async def _get_ignored_lines(self) -> List[int]:
289+
if self._ignored_lines is None:
290+
self._ignored_lines = (
291+
await Analyzer.get_ignored_lines(self.namespace.document) if self.namespace.document is not None else []
292+
)
293+
294+
return self._ignored_lines
295+
296+
async def _should_ignore(self, range: Range) -> bool:
297+
return self.__should_ignore(await self._get_ignored_lines(), range)
298+
283299
@staticmethod
284-
async def should_ignore(document: Optional[TextDocument], range: Range) -> bool:
300+
def __should_ignore(lines: List[int], range: Range) -> bool:
285301
import builtins
286302

287-
if document is not None:
288-
lines = await Analyzer.get_ignored_lines(document)
289-
for line_no in builtins.range(range.start.line, range.end.line + 1):
290-
if line_no in lines:
291-
return True
303+
for line_no in builtins.range(range.start.line, range.end.line + 1):
304+
if line_no in lines:
305+
return True
292306

293307
return False
294308

@@ -305,7 +319,7 @@ async def append_diagnostics(
305319
data: Optional[Any] = None,
306320
) -> None:
307321

308-
if await self.should_ignore(self.namespace.document, range):
322+
if await self._should_ignore(range):
309323
return
310324

311325
self._diagnostics.append(
@@ -799,7 +813,7 @@ async def visit_Keyword(self, node: ast.AST) -> None: # noqa: N802
799813

800814
if keyword.name:
801815
name_token = cast(KeywordName, keyword.header).get_token(RobotToken.KEYWORD_NAME)
802-
kw_doc = await self.get_keyword_definition_at_token(self.namespace, name_token)
816+
kw_doc = self.get_keyword_definition_at_token(await self.namespace.get_library_doc(), name_token)
803817

804818
if kw_doc is not None and kw_doc not in self._keyword_references:
805819
self._keyword_references[kw_doc] = set()

robotcode/language_server/robotframework/diagnostics/namespace.py

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
strip_variable_token,
5151
tokenize_variables,
5252
)
53-
from ..utils.async_ast import AsyncVisitor
53+
from ..utils.async_ast import Visitor
5454
from ..utils.match import eq
5555
from ..utils.variables import BUILTIN_VARIABLES
5656
from ..utils.version import get_robot_version
@@ -97,20 +97,20 @@ class NameSpaceError(Exception):
9797
pass
9898

9999

100-
class VariablesVisitor(AsyncVisitor):
101-
async def get(self, source: str, model: ast.AST) -> List[VariableDefinition]:
100+
class VariablesVisitor(Visitor):
101+
def get(self, source: str, model: ast.AST) -> List[VariableDefinition]:
102102
self._results: List[VariableDefinition] = []
103103
self.source = source
104-
await self.visit(model)
104+
self.visit(model)
105105
return self._results
106106

107-
async def visit_Section(self, node: ast.AST) -> None: # noqa: N802
107+
def visit_Section(self, node: ast.AST) -> None: # noqa: N802
108108
from robot.parsing.model.blocks import VariableSection
109109

110110
if isinstance(node, VariableSection):
111-
await self.generic_visit(node)
111+
self.generic_visit(node)
112112

113-
async def visit_Variable(self, node: ast.AST) -> None: # noqa: N802
113+
def visit_Variable(self, node: ast.AST) -> None: # noqa: N802
114114
from robot.parsing.lexer.tokens import Token as RobotToken
115115
from robot.parsing.model.statements import Variable
116116
from robot.variables import search_variable
@@ -152,38 +152,38 @@ async def visit_Variable(self, node: ast.AST) -> None: # noqa: N802
152152
)
153153

154154

155-
class BlockVariableVisitor(AsyncVisitor):
155+
class BlockVariableVisitor(Visitor):
156156
def __init__(
157-
self, namespace: Namespace, source: str, position: Optional[Position] = None, in_args: bool = True
157+
self, library_doc: LibraryDoc, source: str, position: Optional[Position] = None, in_args: bool = True
158158
) -> None:
159159
super().__init__()
160-
self.namespace = namespace
160+
self.library_doc = library_doc
161161
self.source = source
162162
self.position = position
163163
self.in_args = in_args
164164

165165
self._results: Dict[str, VariableDefinition] = {}
166166
self.current_kw_doc: Optional[KeywordDoc] = None
167167

168-
async def get(self, model: ast.AST) -> List[VariableDefinition]:
168+
def get(self, model: ast.AST) -> List[VariableDefinition]:
169169

170170
self._results = {}
171171

172-
await self.visit(model)
172+
self.visit(model)
173173

174174
return list(self._results.values())
175175

176-
async def visit(self, node: ast.AST) -> None:
176+
def visit(self, node: ast.AST) -> None:
177177
if self.position is None or self.position >= range_from_node(node).start:
178-
return await super().visit(node)
178+
return super().visit(node)
179179

180-
async def visit_Keyword(self, node: ast.AST) -> None: # noqa: N802
180+
def visit_Keyword(self, node: ast.AST) -> None: # noqa: N802
181181
try:
182-
await self.generic_visit(node)
182+
self.generic_visit(node)
183183
finally:
184184
self.current_kw_doc = None
185185

186-
async def visit_KeywordName(self, node: ast.AST) -> None: # noqa: N802
186+
def visit_KeywordName(self, node: ast.AST) -> None: # noqa: N802
187187
from robot.parsing.lexer.tokens import Token as RobotToken
188188
from robot.parsing.model.statements import KeywordName
189189
from robot.variables.search import search_variable
@@ -194,7 +194,8 @@ async def visit_KeywordName(self, node: ast.AST) -> None: # noqa: N802
194194
name_token = cast(Token, n.get_token(RobotToken.KEYWORD_NAME))
195195

196196
if name_token is not None and name_token.value:
197-
keyword = await ModelHelperMixin.get_keyword_definition_at_token(self.namespace, name_token)
197+
198+
keyword = ModelHelperMixin.get_keyword_definition_at_token(self.library_doc, name_token)
198199
self.current_kw_doc = keyword
199200

200201
for variable_token in filter(
@@ -236,7 +237,7 @@ def get_variable_token(self, token: Token) -> Optional[Token]:
236237
None,
237238
)
238239

239-
async def visit_Arguments(self, node: ast.AST) -> None: # noqa: N802
240+
def visit_Arguments(self, node: ast.AST) -> None: # noqa: N802
240241
from robot.errors import VariableError
241242
from robot.parsing.lexer.tokens import Token as RobotToken
242243
from robot.parsing.model.statements import Arguments
@@ -280,7 +281,7 @@ async def visit_Arguments(self, node: ast.AST) -> None: # noqa: N802
280281
if self.current_kw_doc is not None:
281282
self.current_kw_doc.argument_definitions = argument_definitions
282283

283-
async def visit_ExceptHeader(self, node: ast.AST) -> None: # noqa: N802
284+
def visit_ExceptHeader(self, node: ast.AST) -> None: # noqa: N802
284285
from robot.errors import VariableError
285286
from robot.parsing.lexer.tokens import Token as RobotToken
286287
from robot.parsing.model.statements import ExceptHeader
@@ -306,7 +307,7 @@ async def visit_ExceptHeader(self, node: ast.AST) -> None: # noqa: N802
306307
except VariableError:
307308
pass
308309

309-
async def visit_KeywordCall(self, node: ast.AST) -> None: # noqa: N802
310+
def visit_KeywordCall(self, node: ast.AST) -> None: # noqa: N802
310311
from robot.errors import VariableError
311312
from robot.parsing.lexer.tokens import Token as RobotToken
312313
from robot.parsing.model.statements import KeywordCall
@@ -341,7 +342,7 @@ async def visit_KeywordCall(self, node: ast.AST) -> None: # noqa: N802
341342
except VariableError:
342343
pass
343344

344-
async def visit_InlineIfHeader(self, node: ast.AST) -> None: # noqa: N802
345+
def visit_InlineIfHeader(self, node: ast.AST) -> None: # noqa: N802
345346
from robot.errors import VariableError
346347
from robot.parsing.lexer.tokens import Token as RobotToken
347348
from robot.parsing.model.statements import InlineIfHeader
@@ -374,7 +375,7 @@ async def visit_InlineIfHeader(self, node: ast.AST) -> None: # noqa: N802
374375
except VariableError:
375376
pass
376377

377-
async def visit_ForHeader(self, node: ast.AST) -> None: # noqa: N802
378+
def visit_ForHeader(self, node: ast.AST) -> None: # noqa: N802
378379
from robot.parsing.lexer.tokens import Token as RobotToken
379380
from robot.parsing.model.statements import ForHeader
380381

@@ -394,20 +395,20 @@ async def visit_ForHeader(self, node: ast.AST) -> None: # noqa: N802
394395
)
395396

396397

397-
class ImportVisitor(AsyncVisitor):
398-
async def get(self, source: str, model: ast.AST) -> List[Import]:
398+
class ImportVisitor(Visitor):
399+
def get(self, source: str, model: ast.AST) -> List[Import]:
399400
self._results: List[Import] = []
400401
self.source = source
401-
await self.visit(model)
402+
self.visit(model)
402403
return self._results
403404

404-
async def visit_Section(self, node: ast.AST) -> None: # noqa: N802
405+
def visit_Section(self, node: ast.AST) -> None: # noqa: N802
405406
from robot.parsing.model.blocks import SettingSection
406407

407408
if isinstance(node, SettingSection):
408-
await self.generic_visit(node)
409+
self.generic_visit(node)
409410

410-
async def visit_LibraryImport(self, node: ast.AST) -> None: # noqa: N802
411+
def visit_LibraryImport(self, node: ast.AST) -> None: # noqa: N802
411412
from robot.parsing.lexer.tokens import Token as RobotToken
412413
from robot.parsing.model.statements import LibraryImport as RobotLibraryImport
413414

@@ -440,7 +441,7 @@ async def visit_LibraryImport(self, node: ast.AST) -> None: # noqa: N802
440441
)
441442
)
442443

443-
async def visit_ResourceImport(self, node: ast.AST) -> None: # noqa: N802
444+
def visit_ResourceImport(self, node: ast.AST) -> None: # noqa: N802
444445
from robot.parsing.lexer.tokens import Token as RobotToken
445446
from robot.parsing.model.statements import ResourceImport as RobotResourceImport
446447

@@ -470,7 +471,7 @@ async def visit_ResourceImport(self, node: ast.AST) -> None: # noqa: N802
470471
)
471472
)
472473

473-
async def visit_VariablesImport(self, node: ast.AST) -> None: # noqa: N802
474+
def visit_VariablesImport(self, node: ast.AST) -> None: # noqa: N802
474475
from robot.parsing.lexer.tokens import Token as RobotToken
475476
from robot.parsing.model.statements import (
476477
VariablesImport as RobotVariablesImport,
@@ -864,15 +865,15 @@ def initialized(self) -> bool:
864865
@_logger.call
865866
async def get_imports(self) -> List[Import]:
866867
if self._imports is None:
867-
self._imports = await ImportVisitor().get(self.source, self.model)
868+
self._imports = ImportVisitor().get(self.source, self.model)
868869

869870
return self._imports
870871

871872
@_logger.call
872873
async def get_own_variables(self) -> List[VariableDefinition]:
873874
async with self._own_variables_lock:
874875
if self._own_variables is None:
875-
self._own_variables = await VariablesVisitor().get(self.source, self.model)
876+
self._own_variables = VariablesVisitor().get(self.source, self.model)
876877

877878
return self._own_variables
878879

@@ -927,8 +928,8 @@ async def yield_variables(
927928
for var in chain(
928929
*[
929930
(
930-
await BlockVariableVisitor(
931-
self,
931+
BlockVariableVisitor(
932+
await self.get_library_doc(),
932933
self.source,
933934
position,
934935
isinstance(test_or_keyword_nodes[-1], Arguments) if nodes else False,

robotcode/language_server/robotframework/parts/codelens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ async def resolve(self, sender: Any, code_lens: CodeLens) -> Optional[CodeLens]:
110110
line = code_lens.data["line"]
111111

112112
if self.parent.diagnostics.workspace_loaded_event.is_set():
113-
kw_doc = await self.get_keyword_definition_at_line(namespace, name, line)
113+
kw_doc = self.get_keyword_definition_at_line(await namespace.get_library_doc(), name, line)
114114

115115
if kw_doc is not None and not kw_doc.is_error_handler:
116116
if not await self.parent.robot_references.has_cached_keyword_references(

robotcode/language_server/robotframework/parts/goto.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ async def definition_KeywordName( # noqa: N802
251251
if not name_token:
252252
return None
253253

254-
result = await self.get_keyword_definition_at_token(namespace, name_token)
254+
result = self.get_keyword_definition_at_token(await namespace.get_library_doc(), name_token)
255255

256256
if result is not None and not result.is_error_handler and result.source:
257257
token_range = range_from_token(name_token)

robotcode/language_server/robotframework/parts/hover.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ async def hover_KeywordName( # noqa: N802
557557
if not name_token:
558558
return None
559559

560-
result = await self.get_keyword_definition_at_token(namespace, name_token)
560+
result = self.get_keyword_definition_at_token(await namespace.get_library_doc(), name_token)
561561

562562
if result is not None and not result.is_error_handler:
563563
return Hover(

robotcode/language_server/robotframework/parts/model_helper.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
from ...common.lsp_types import Position
2121
from ..diagnostics.entities import VariableDefinition, VariableNotFoundDefinition
22-
from ..diagnostics.library_doc import KeywordDoc
22+
from ..diagnostics.library_doc import KeywordDoc, LibraryDoc
2323
from ..diagnostics.namespace import DEFAULT_BDD_PREFIXES, LibraryEntry, Namespace
2424
from ..utils.ast_utils import (
2525
Token,
@@ -580,12 +580,12 @@ def is_bdd_token(cls, namespace: Namespace, token: Token) -> bool:
580580
return False
581581

582582
@classmethod
583-
async def get_keyword_definition_at_token(cls, namespace: Namespace, token: Token) -> Optional[KeywordDoc]:
584-
return await cls.get_keyword_definition_at_line(namespace, token.value, token.lineno)
583+
def get_keyword_definition_at_token(cls, library_doc: LibraryDoc, token: Token) -> Optional[KeywordDoc]:
584+
return cls.get_keyword_definition_at_line(library_doc, token.value, token.lineno)
585585

586586
@classmethod
587-
async def get_keyword_definition_at_line(cls, namespace: Namespace, value: str, line: int) -> Optional[KeywordDoc]:
587+
def get_keyword_definition_at_line(cls, library_doc: LibraryDoc, value: str, line: int) -> Optional[KeywordDoc]:
588588
return next(
589-
(k for k in (await namespace.get_library_doc()).keywords.get_all(value) if k.line_no == line),
589+
(k for k in library_doc.keywords.get_all(value) if k.line_no == line),
590590
None,
591591
)

robotcode/language_server/robotframework/utils/async_ast.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import ast
2-
from typing import Any, AsyncGenerator, Callable, Optional, Type, cast
2+
from typing import Any, AsyncGenerator, Callable, Generator, Optional, Type, cast
33

44
__all__ = ["iter_fields", "iter_child_nodes", "AsyncVisitor", "walk"]
55

66

7-
async def iter_fields(node: ast.AST) -> AsyncGenerator[Any, None]:
7+
def iter_fields(node: ast.AST) -> Generator[Any, None, None]:
88
"""
99
Yield a tuple of ``(fieldname, value)`` for each field in ``node._fields``
1010
that is present on *node*.
@@ -16,12 +16,12 @@ async def iter_fields(node: ast.AST) -> AsyncGenerator[Any, None]:
1616
pass
1717

1818

19-
async def iter_child_nodes(node: ast.AST) -> AsyncGenerator[ast.AST, None]:
19+
def iter_child_nodes(node: ast.AST) -> Generator[ast.AST, None, None]:
2020
"""
2121
Yield all direct child nodes of *node*, that is, all fields that are nodes
2222
and all items of fields that are lists of nodes.
2323
"""
24-
async for _name, field in iter_fields(node):
24+
for _name, field in iter_fields(node):
2525
if isinstance(field, ast.AST):
2626
yield field
2727
elif isinstance(field, list):
@@ -36,12 +36,12 @@ async def walk(node: ast.AST) -> AsyncGenerator[ast.AST, None]:
3636
todo = deque([node])
3737
while todo:
3838
node = todo.popleft()
39-
todo.extend([e async for e in iter_child_nodes(node)])
39+
todo.extend([e for e in iter_child_nodes(node)])
4040
yield node
4141

4242

4343
async def iter_nodes(node: ast.AST) -> AsyncGenerator[ast.AST, None]:
44-
async for _name, value in iter_fields(node):
44+
for _name, value in iter_fields(node):
4545
if isinstance(value, list):
4646
for item in value:
4747
if isinstance(item, ast.AST):
@@ -79,10 +79,26 @@ async def visit(self, node: ast.AST) -> None:
7979

8080
async def generic_visit(self, node: ast.AST) -> None:
8181
"""Called if no explicit visitor function exists for a node."""
82-
async for field, value in iter_fields(node):
82+
for _, value in iter_fields(node):
8383
if isinstance(value, list):
8484
for item in value:
8585
if isinstance(item, ast.AST):
8686
await self.visit(item)
8787
elif isinstance(value, ast.AST):
8888
await self.visit(value)
89+
90+
91+
class Visitor(VisitorFinder):
92+
def visit(self, node: ast.AST) -> None:
93+
visitor = self._find_visitor(type(node)) or self.generic_visit
94+
visitor(node)
95+
96+
def generic_visit(self, node: ast.AST) -> None:
97+
"""Called if no explicit visitor function exists for a node."""
98+
for field, value in iter_fields(node):
99+
if isinstance(value, list):
100+
for item in value:
101+
if isinstance(item, ast.AST):
102+
self.visit(item)
103+
elif isinstance(value, ast.AST):
104+
self.visit(value)

0 commit comments

Comments
 (0)