1+ import hashlib
12from dataclasses import dataclass , field
23from enum import Enum
34from typing import (
@@ -36,6 +37,7 @@ def range(self) -> Range:
3637 def __hash__ (self ) -> int :
3738 return hash (
3839 (
40+ type (self ),
3941 self .line_no ,
4042 self .col_offset ,
4143 self .end_line_no ,
@@ -45,7 +47,7 @@ def __hash__(self) -> int:
4547 )
4648
4749
48- @dataclass (slots = True )
50+ @dataclass (slots = True , eq = False )
4951class Import (SourceEntity ):
5052 name : Optional [str ]
5153 name_token : Optional [Token ]
@@ -115,7 +117,7 @@ class VariableDefinitionType(Enum):
115117 VARIABLE_NOT_FOUND = "variable not found"
116118
117119
118- @dataclass (slots = True )
120+ @dataclass (slots = True , eq = False )
119121class VariableDefinition (SourceEntity ):
120122 name : str
121123 name_token : Optional [Token ] # TODO: this is not needed anymore, but kept for compatibility
@@ -129,6 +131,47 @@ class VariableDefinition(SourceEntity):
129131 value_is_native : bool = field (default = False , compare = False )
130132 value_type : Optional [str ] = field (default = None , compare = False )
131133
134+ _hash_value : int = field (default = 0 , init = False , compare = False , hash = False , repr = False )
135+ _stable_id : str = field (default = "" , init = False , compare = False , hash = False , repr = False )
136+
137+ def __post_init__ (self ) -> None :
138+ self ._hash_value = hash (
139+ (
140+ type (self ),
141+ self .type .value ,
142+ self .name ,
143+ self .source ,
144+ self .line_no ,
145+ self .col_offset ,
146+ self .end_line_no ,
147+ self .end_col_offset ,
148+ )
149+ )
150+
151+ def _compute_stable_id (self ) -> str :
152+ h = hashlib .sha256 ()
153+ h .update (
154+ "\0 " .join (
155+ (
156+ type (self ).__qualname__ ,
157+ self .type .value ,
158+ self .name ,
159+ self .source or "" ,
160+ str (self .line_no ),
161+ str (self .col_offset ),
162+ str (self .end_line_no ),
163+ str (self .end_col_offset ),
164+ )
165+ ).encode ()
166+ )
167+ return h .hexdigest ()
168+
169+ @property
170+ def stable_id (self ) -> str :
171+ if not self ._stable_id :
172+ self ._stable_id = self ._compute_stable_id ()
173+ return self ._stable_id
174+
132175 @property
133176 def matcher (self ) -> VariableMatcher :
134177 return search_variable (self .name )
@@ -139,8 +182,22 @@ def convertable_name(self) -> str:
139182 value_type = f": { self .value_type } " if self .value_type else ""
140183 return f"{ m .identifier } {{{ m .base .strip ()} { value_type } }}"
141184
185+ def __eq__ (self , other : object ) -> bool :
186+ if not isinstance (other , VariableDefinition ):
187+ return NotImplemented
188+ return (
189+ type (self ) is type (other )
190+ and self .type is other .type
191+ and self .name == other .name
192+ and self .source == other .source
193+ and self .line_no == other .line_no
194+ and self .col_offset == other .col_offset
195+ and self .end_line_no == other .end_line_no
196+ and self .end_col_offset == other .end_col_offset
197+ )
198+
142199 def __hash__ (self ) -> int :
143- return hash (( self .type , self . name , self . source , self . range ))
200+ return self ._hash_value
144201
145202 @property
146203 def name_range (self ) -> Range :
@@ -157,74 +214,50 @@ def range(self) -> Range:
157214 )
158215
159216
160- @dataclass (slots = True )
217+ @dataclass (slots = True , eq = False )
161218class TestVariableDefinition (VariableDefinition ):
162219 type : VariableDefinitionType = VariableDefinitionType .TEST_VARIABLE
163220
164- def __hash__ (self ) -> int :
165- return hash ((self .type , self .name , self .source , self .range ))
166-
167221
168- @dataclass (slots = True )
222+ @dataclass (slots = True , eq = False )
169223class LocalVariableDefinition (VariableDefinition ):
170224 type : VariableDefinitionType = VariableDefinitionType .LOCAL_VARIABLE
171225
172- def __hash__ (self ) -> int :
173- return hash ((self .type , self .name , self .source , self .range ))
174-
175226
176- @dataclass (slots = True )
227+ @dataclass (slots = True , eq = False )
177228class GlobalVariableDefinition (VariableDefinition ):
178229 type : VariableDefinitionType = VariableDefinitionType .GLOBAL_VARIABLE
179230
180- def __hash__ (self ) -> int :
181- return hash ((self .type , self .name , self .source , self .range ))
182-
183231
184- @dataclass (slots = True )
232+ @dataclass (slots = True , eq = False )
185233class BuiltInVariableDefinition (GlobalVariableDefinition ):
186234 type : VariableDefinitionType = VariableDefinitionType .BUILTIN_VARIABLE
187235 resolvable : bool = True
188236
189- def __hash__ (self ) -> int :
190- return hash ((self .type , self .name , self .source , self .range ))
191237
192-
193- @dataclass (slots = True )
238+ @dataclass (slots = True , eq = False )
194239class CommandLineVariableDefinition (GlobalVariableDefinition ):
195240 type : VariableDefinitionType = VariableDefinitionType .COMMAND_LINE_VARIABLE
196241 resolvable : bool = True
197242
198- def __hash__ (self ) -> int :
199- return hash ((self .type , self .name , self .source , self .range ))
200-
201243
202- @dataclass (slots = True )
244+ @dataclass (slots = True , eq = False )
203245class ArgumentDefinition (LocalVariableDefinition ):
204246 type : VariableDefinitionType = VariableDefinitionType .ARGUMENT
205247 keyword_doc : Optional ["KeywordDoc" ] = field (default = None , compare = False , metadata = {"nosave" : True })
206248
207- def __hash__ (self ) -> int :
208- return hash ((self .type , self .name , self .source , self .range ))
209-
210249
211- @dataclass (slots = True )
250+ @dataclass (slots = True , eq = False )
212251class EmbeddedArgumentDefinition (ArgumentDefinition ):
213252 pattern : Optional [str ] = field (default = None , compare = False )
214253
215- def __hash__ (self ) -> int :
216- return hash ((self .type , self .name , self .source , self .range ))
217-
218254
219- @dataclass (slots = True )
255+ @dataclass (slots = True , eq = False )
220256class LibraryArgumentDefinition (ArgumentDefinition ):
221257 type : VariableDefinitionType = VariableDefinitionType .LIBRARY_ARGUMENT
222258
223- def __hash__ (self ) -> int :
224- return hash ((self .type , self .name , self .source , self .range ))
225-
226259
227- @dataclass (slots = True , frozen = True , eq = False , repr = False )
260+ @dataclass (slots = True , eq = False , repr = False )
228261class NativeValue :
229262 value : Any
230263
@@ -235,34 +268,25 @@ def __str__(self) -> str:
235268 return str (self .value )
236269
237270
238- @dataclass (slots = True )
271+ @dataclass (slots = True , eq = False )
239272class ImportedVariableDefinition (VariableDefinition ):
240273 type : VariableDefinitionType = VariableDefinitionType .IMPORTED_VARIABLE
241274 value : Optional [NativeValue ] = field (default = None , compare = False )
242275
243- def __hash__ (self ) -> int :
244- return hash ((self .type , self .name , self .source , self .range ))
245-
246276
247- @dataclass (slots = True )
277+ @dataclass (slots = True , eq = False )
248278class EnvironmentVariableDefinition (VariableDefinition ):
249279 type : VariableDefinitionType = VariableDefinitionType .ENVIRONMENT_VARIABLE
250280 resolvable : bool = True
251281
252282 default_value : Any = field (default = None , compare = False )
253283
254- def __hash__ (self ) -> int :
255- return hash ((self .type , self .name , self .source , self .range ))
256-
257284
258- @dataclass (slots = True )
285+ @dataclass (slots = True , eq = False )
259286class VariableNotFoundDefinition (VariableDefinition ):
260287 type : VariableDefinitionType = VariableDefinitionType .VARIABLE_NOT_FOUND
261288 resolvable : bool = False
262289
263- def __hash__ (self ) -> int :
264- return hash ((self .type , self .name , self .source , self .range ))
265-
266290
267291@dataclass (slots = True )
268292class LibraryEntry :
@@ -339,6 +363,7 @@ class TestCaseDefinition(SourceEntity):
339363 def __hash__ (self ) -> int :
340364 return hash (
341365 (
366+ type (self ),
342367 self .line_no ,
343368 self .col_offset ,
344369 self .end_line_no ,
@@ -356,6 +381,7 @@ class TagDefinition(SourceEntity):
356381 def __hash__ (self ) -> int :
357382 return hash (
358383 (
384+ type (self ),
359385 self .line_no ,
360386 self .col_offset ,
361387 self .end_line_no ,
0 commit comments