Skip to content

Commit e39afe9

Browse files
committed
perf(analyzer): introduced some caching for parsing variables
1 parent 4e17c8f commit e39afe9

File tree

8 files changed

+75
-35
lines changed

8 files changed

+75
-35
lines changed

packages/language_server/src/robotcode/language_server/robotframework/parts/semantic_tokens.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@
3636
Variable,
3737
VariablesImport,
3838
)
39-
from robot.utils.escaping import split_from_equals, unescape
40-
from robot.variables.search import is_variable
39+
from robot.utils.escaping import unescape
4140

4241
from robotcode.core.concurrent import check_current_task_canceled
4342
from robotcode.core.language import language_id
@@ -70,6 +69,7 @@
7069
iter_over_keyword_names_and_owners,
7170
token_in_range,
7271
)
72+
from robotcode.robot.utils.variables import is_variable, split_from_equals
7373

7474
from .protocol_part import RobotLanguageServerProtocolPart
7575

@@ -1120,13 +1120,13 @@ def get_tokens() -> Iterator[Tuple[Token, ast.AST]]:
11201120
if kw_token is not None:
11211121
kw: Optional[str] = None
11221122

1123-
for _, name in iter_over_keyword_names_and_owners(
1123+
for _, n in iter_over_keyword_names_and_owners(
11241124
ModelHelper.strip_bdd_prefix(namespace, kw_token).value
11251125
):
1126-
if name is not None:
1127-
matcher = KeywordMatcher(name)
1126+
if n is not None:
1127+
matcher = KeywordMatcher(n)
11281128
if matcher in ALL_RUN_KEYWORDS_MATCHERS:
1129-
kw = name
1129+
kw = n
11301130
if kw:
11311131
kw_doc = namespace.find_keyword(kw_token.value)
11321132
if kw_doc is not None and kw_doc.is_any_run_keyword():

packages/robot/src/robotcode/robot/diagnostics/entities.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
)
1313

1414
from robot.parsing.lexer.tokens import Token
15-
from robot.variables.search import search_variable
1615
from robotcode.core.lsp.types import Position, Range
1716
from robotcode.robot.utils.match import normalize
1817

1918
from ..utils.ast import range_from_token
19+
from ..utils.variables import search_variable
2020

2121
if TYPE_CHECKING:
2222
from robotcode.robot.diagnostics.library_doc import KeywordDoc, LibraryDoc

packages/robot/src/robotcode/robot/diagnostics/imports_manager.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
final,
2626
)
2727

28+
from robot.libraries import STDLIBS
2829
from robot.utils.text import split_args_from_name_or_path
2930
from robotcode.core.concurrent import RLock, run_as_task
3031
from robotcode.core.documents_manager import DocumentsManager
@@ -43,6 +44,7 @@
4344
from ..__version__ import __version__
4445
from ..utils import get_robot_version, get_robot_version_str
4546
from ..utils.robot_path import find_file_ex
47+
from ..utils.variables import contains_variable
4648
from .entities import (
4749
CommandLineVariableDefinition,
4850
VariableDefinition,
@@ -1023,8 +1025,6 @@ def _find_library(
10231025
base_dir: str,
10241026
variables: Optional[Dict[str, Any]] = None,
10251027
) -> str:
1026-
from robot.libraries import STDLIBS
1027-
from robot.variables.search import contains_variable
10281028

10291029
if contains_variable(name, "$@&%"):
10301030
return find_library(
@@ -1062,8 +1062,6 @@ def __find_resource(
10621062
file_type: str = "Resource",
10631063
variables: Optional[Dict[str, Any]] = None,
10641064
) -> str:
1065-
from robot.variables.search import contains_variable
1066-
10671065
if contains_variable(name, "$@&%"):
10681066
return find_file(
10691067
name,
@@ -1102,8 +1100,6 @@ def __find_variables(
11021100
resolve_variables: bool = True,
11031101
resolve_command_line_vars: bool = True,
11041102
) -> str:
1105-
from robot.variables.search import contains_variable
1106-
11071103
if resolve_variables and contains_variable(name, "$@&%"):
11081104
return find_variables(
11091105
name,

packages/robot/src/robotcode/robot/diagnostics/library_doc.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@
6262
from robot.variables.filesetter import PythonImporter, YamlImporter
6363
from robot.variables.finders import VariableFinder
6464
from robot.variables.replacer import VariableReplacer
65-
from robot.variables.search import contains_variable
6665
from robotcode.core.lsp.types import Position, Range
6766
from robotcode.core.utils.path import normalized_path
6867
from robotcode.robot.diagnostics.entities import (
@@ -84,6 +83,8 @@
8483
from robotcode.robot.utils.match import normalize, normalize_namespace
8584
from robotcode.robot.utils.stubs import HasError, HasErrors
8685

86+
from ..utils.variables import contains_variable
87+
8788
if get_robot_version() < (7, 0):
8889
from robot.running.handlers import _PythonHandler, _PythonInitHandler # pyright: ignore[reportMissingImports]
8990
from robot.running.model import ResourceFile # pyright: ignore[reportMissingImports]
@@ -1669,9 +1670,8 @@ def _find_library_internal(
16691670

16701671
robot_variables = None
16711672

1672-
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
1673-
16741673
if contains_variable(name, "$@&%"):
1674+
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
16751675
try:
16761676
name = robot_variables.replace_string(name, ignore_errors=False)
16771677
except DataError as error:
@@ -1840,7 +1840,11 @@ def get_test_library(
18401840
library_name,
18411841
args,
18421842
create_handlers=False,
1843-
variables=robot_variables,
1843+
variables=(
1844+
robot_variables
1845+
if robot_variables is not None
1846+
else resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
1847+
),
18441848
)
18451849
if get_robot_version() < (7, 0):
18461850
_ = lib.get_instance()
@@ -2099,9 +2103,8 @@ def _find_variables_internal(
20992103

21002104
_update_env(working_dir)
21012105

2102-
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
2103-
21042106
if contains_variable(name, "$@&%"):
2107+
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
21052108
try:
21062109
name = robot_variables.replace_string(name, ignore_errors=False)
21072110
except DataError as error:
@@ -2122,12 +2125,18 @@ def resolve_args(
21222125
command_line_variables: Optional[Dict[str, Optional[Any]]] = None,
21232126
variables: Optional[Dict[str, Optional[Any]]] = None,
21242127
) -> Tuple[Any, ...]:
2125-
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
2128+
# robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
2129+
robot_variables: Any = None
21262130

21272131
result = []
21282132
for arg in args:
21292133
if isinstance(arg, str):
2130-
result.append(robot_variables.replace_string(arg, ignore_errors=True))
2134+
if contains_variable(arg, "$@&%"):
2135+
if robot_variables is None:
2136+
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
2137+
result.append(robot_variables.replace_string(arg, ignore_errors=True))
2138+
else:
2139+
result.append(arg)
21312140
else:
21322141
result.append(arg)
21332142

@@ -2402,8 +2411,8 @@ def find_file(
24022411
) -> str:
24032412
_update_env(working_dir)
24042413

2405-
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
24062414
if contains_variable(name, "$@&%"):
2415+
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
24072416
try:
24082417
name = robot_variables.replace_string(name, ignore_errors=False)
24092418
except DataError as error:
@@ -2505,7 +2514,7 @@ def complete_library_import(
25052514
if e not in DEFAULT_LIBRARIES
25062515
]
25072516

2508-
if name is not None:
2517+
if name is not None and contains_variable(name, "$@&%"):
25092518
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
25102519

25112520
name = robot_variables.replace_string(name, ignore_errors=True)
@@ -2581,7 +2590,7 @@ def complete_resource_import(
25812590

25822591
result: List[CompleteResult] = []
25832592

2584-
if name is not None:
2593+
if name is not None and contains_variable(name, "$@&%"):
25852594
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
25862595

25872596
name = robot_variables.replace_string(name, ignore_errors=True)
@@ -2621,7 +2630,7 @@ def complete_variables_import(
26212630

26222631
result: List[CompleteResult] = []
26232632

2624-
if name is not None:
2633+
if name is not None and contains_variable(name, "$@&%"):
26252634
robot_variables = resolve_robot_variables(working_dir, base_dir, command_line_variables, variables)
26262635

26272636
name = robot_variables.replace_string(name, ignore_errors=True)

packages/robot/src/robotcode/robot/diagnostics/model_helper.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@
2121

2222
from robot.errors import VariableError
2323
from robot.parsing.lexer.tokens import Token
24-
from robot.utils.escaping import split_from_equals, unescape
24+
from robot.utils.escaping import unescape
2525
from robot.variables.finders import NOT_FOUND, NumberFinder
26-
from robot.variables.search import contains_variable, search_variable
2726
from robotcode.core.lsp.types import Position
2827

2928
from ..utils import get_robot_version
@@ -35,6 +34,7 @@
3534
whitespace_at_begin_of_token,
3635
whitespace_from_begin_of_token,
3736
)
37+
from ..utils.variables import contains_variable, search_variable, split_from_equals
3838
from .entities import (
3939
LibraryEntry,
4040
VariableDefinition,

packages/robot/src/robotcode/robot/diagnostics/namespace.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@
2828
from robot.parsing.model.statements import (
2929
VariablesImport as RobotVariablesImport,
3030
)
31-
from robot.variables.search import (
32-
is_scalar_assign,
33-
is_variable,
34-
search_variable,
35-
)
3631
from robotcode.core.concurrent import RLock
3732
from robotcode.core.event import event
3833
from robotcode.core.lsp.types import (
@@ -57,7 +52,12 @@
5752
tokenize_variables,
5853
)
5954
from ..utils.stubs import Languages
60-
from ..utils.variables import BUILTIN_VARIABLES
55+
from ..utils.variables import (
56+
BUILTIN_VARIABLES,
57+
is_scalar_assign,
58+
is_variable,
59+
search_variable,
60+
)
6161
from ..utils.visitor import Visitor
6262
from .entities import (
6363
ArgumentDefinition,

packages/robot/src/robotcode/robot/diagnostics/namespace_analyzer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@
2828
Variable,
2929
VariablesImport,
3030
)
31-
from robot.utils.escaping import split_from_equals, unescape
31+
from robot.utils.escaping import unescape
3232
from robot.variables.finders import NOT_FOUND, NumberFinder
33-
from robot.variables.search import contains_variable, is_scalar_assign, is_variable, search_variable
3433
from robotcode.core.concurrent import check_current_task_canceled
3534
from robotcode.core.lsp.types import (
3635
CodeDescription,
@@ -54,6 +53,7 @@
5453
strip_variable_token,
5554
tokenize_variables,
5655
)
56+
from ..utils.variables import contains_variable, is_scalar_assign, is_variable, search_variable, split_from_equals
5757
from ..utils.visitor import Visitor
5858
from .entities import (
5959
ArgumentDefinition,

packages/robot/src/robotcode/robot/utils/variables.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
import functools
2+
from typing import Optional, Tuple, cast
3+
4+
from robot.utils.escaping import split_from_equals as robot_split_from_equals
5+
from robot.variables.search import VariableMatch as RobotVariableMatch
6+
from robot.variables.search import contains_variable as robot_contains_variable
7+
from robot.variables.search import is_scalar_assign as robot_is_scalar_assign
8+
from robot.variables.search import is_variable as robot_is_variable
9+
from robot.variables.search import search_variable as robot_search_variable
10+
111
BUILTIN_VARIABLES = [
212
"${CURDIR}",
313
"${EMPTY}",
@@ -35,3 +45,28 @@
3545
"${DEBUG_FILE}",
3646
"${OUTPUT_DIR}",
3747
]
48+
49+
50+
@functools.lru_cache(maxsize=512)
51+
def contains_variable(string: str, identifiers: str = "$@&") -> bool:
52+
return cast(bool, robot_contains_variable(string, identifiers))
53+
54+
55+
@functools.lru_cache(maxsize=512)
56+
def is_scalar_assign(string: str, allow_assign_mark: bool = False) -> bool:
57+
return cast(bool, robot_is_scalar_assign(string, allow_assign_mark))
58+
59+
60+
@functools.lru_cache(maxsize=512)
61+
def is_variable(string: str, identifiers: str = "$@&") -> bool:
62+
return cast(bool, robot_is_variable(string, identifiers))
63+
64+
65+
@functools.lru_cache(maxsize=512)
66+
def search_variable(string: str, identifiers: str = "$@&%*", ignore_errors: bool = False) -> RobotVariableMatch:
67+
return robot_search_variable(string, identifiers, ignore_errors)
68+
69+
70+
@functools.lru_cache(maxsize=512)
71+
def split_from_equals(string: str) -> Tuple[str, Optional[str]]:
72+
return cast(Tuple[str, Optional[str]], robot_split_from_equals(string))

0 commit comments

Comments
 (0)