Coverage for src/robotide/namespace/local_namespace.py: 86%
65 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-06 10:40 +0100
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-06 10:40 +0100
1# Copyright 2008-2015 Nokia Networks
2# Copyright 2016- Robot Framework Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
16from robotide import utils 1df
17from robotide.spec.iteminfo import LocalVariableInfo 1df
20def local_namespace(controller, namespace, row=None): 1df
21 if row is not None: # can be 0! 1dophqlijrsmtuvwxkzAygnbBcea
22 return LocalRowNamespace(controller, namespace, row) 1ophqlijrsmtuvwxkgnbcea
23 return LocalMacroNamespace(controller, namespace) 1dzAyB
26class LocalMacroNamespace(object): 1df
28 def __init__(self, controller, namespace): 1df
29 self._controller = controller 1dophqlijrsmtuvwxkzAygnbBcea
30 self.namespace = namespace 1dophqlijrsmtuvwxkzAygnbBcea
32 def get_suggestions(self, start): 1df
33 # print(f"DEBUG: local_namespace.py LocalMacroNamespace get_suggestions ENTER start={start}")
34 return self.namespace.get_suggestions_for(self._controller, start) 1zbcea
36 def has_name(self, value): 1df
37 for sug in self.namespace.get_suggestions_for(self._controller, value): 1ophqlijrsmtuvwxkAygn
38 if sug.name == value: 38 ↛ 40line 38 didn't jump to line 40 because the condition on line 38 was always true1hjyg
39 return True 1hjyg
40 try:
41 if value in sug.assign:
42 return True
43 except AttributeError:
44 pass
45 return False 1ophqlijrsmtuvwxkAn
47 def update_words_cache(self, words_list: list, reset=False): 1df
48 return self.namespace.update_words_cache(words_list, reset) 1dz
51class LocalRowNamespace(LocalMacroNamespace): 1df
53 def __init__(self, controller, namespace, row): 1df
54 LocalMacroNamespace.__init__(self, controller, namespace) 1ophqlijrsmtuvwxkgnbcea
55 self._row = row 1ophqlijrsmtuvwxkgnbcea
57 def get_suggestions(self, start): 1df
58 suggestions = LocalMacroNamespace.get_suggestions(self, start) 1bcea
59 # print(f"DEBUG: suggesters.py LocalRowNamespace get_suggestions after LocalMacroNamespace start={start}\n"
60 # f"suggestions={suggestions}")
61 if self._could_be_variable(start): 1bcea
62 suggestions = self._harvest_local_variables(start, suggestions) 1bcea
63 else:
64 suggestions = self._harvest_local_variables('${'+start, suggestions) 1a
65 suggestions = self._harvest_local_variables('@{'+start, suggestions) 1a
66 suggestions = self._harvest_local_variables('&{'+start, suggestions) 1a
67 return suggestions 1bcea
69 def _harvest_local_variables(self, start, suggestions): 1df
70 matching_assignments = set() 1bcea
71 for row, step in enumerate(self._controller.steps): 71 ↛ 77line 71 didn't jump to line 77 because the loop on line 71 didn't complete1bcea
72 if self._row == row: 1bcea
73 break 1bcea
74 matching_assignments = matching_assignments.union( 1bcea
75 val.replace('=', '').strip() for val in step.assignments if
76 val.startswith(start))
77 if matching_assignments: 1bcea
78 local_variables = [LocalVariableInfo(name) for name 1bca
79 in matching_assignments]
80 suggestions = sorted(self._remove_duplicates(suggestions, 1bca
81 local_variables))
82 return suggestions 1bcea
84 @staticmethod 1df
85 def _could_be_variable(start): 1df
86 return len(start) == 0 or start[0] in ['$', '@', '&'] 1bcea
88 def has_name(self, value): 1df
89 if self._row is not None: 89 ↛ 95line 89 didn't jump to line 95 because the condition on line 89 was always true1ophqlijrsmtuvwxkgn
90 for row, step in enumerate(self._controller.steps): 90 ↛ 95line 90 didn't jump to line 95 because the loop on line 90 didn't complete1ophqlijrsmtuvwxkgn
91 if self._row == row: 1ophqlijrsmtuvwxkgn
92 break 1ophqlijrsmtuvwxkgn
93 if step.is_assigning(value): 1limkgn
94 return True 1ikg
95 return LocalMacroNamespace.has_name(self, value) 1ophqlijrsmtuvwxkgn
97 @staticmethod 1df
98 def _remove_duplicates(suggestions, local_variables): 1df
99 def is_unique(gvar): 1bca
100 if hasattr(gvar, 'name'): 100 ↛ 103line 100 didn't jump to line 103 because the condition on line 100 was always true1bca
101 return utils.normalize(gvar.name) not in [utils.normalize(lvar.name) for lvar in local_variables] 1bca
102 else:
103 return utils.normalize(gvar) not in [utils.normalize(lvar.name) for lvar in local_variables]
104 unique = [gvar for gvar in suggestions if is_unique(gvar)] 1bca
105 return unique + local_variables 1bca