@@ -174,6 +174,36 @@ pub fn get_reference_from_var_name<'a>(
174174 . ok_or_else ( || HintError :: UnknownIdentifier ( Box :: < str > :: from ( var_name) ) )
175175}
176176
177+ pub fn get_identifier_from_scoped_name < ' a > (
178+ scoped_name : & str ,
179+ identifiers : & ' a HashMap < String , Identifier > ,
180+ accessible_scopes : & [ String ] ,
181+ ) -> Result < & ' a Identifier , HintError > {
182+ for scope in accessible_scopes. iter ( ) . rev ( ) {
183+ let full_path = format ! ( "{}.{}" , scope, scoped_name) ;
184+
185+ if let Some ( identifier) = identifiers. get ( & full_path) {
186+ return Ok ( identifier) ;
187+ }
188+
189+ // The scoped_name can itself contain multiple components (i.e. a.b.c).
190+ // If there is a match for at least the first component, we should
191+ // not continue with the next scope.
192+ if let Some ( first_component) = scoped_name. split ( '.' ) . next ( ) {
193+ if identifiers
194+ . get ( & format ! ( "{}.{}" , scope, first_component) )
195+ . is_some ( )
196+ {
197+ break ;
198+ }
199+ }
200+ }
201+
202+ Err ( HintError :: UnknownIdentifier (
203+ scoped_name. to_string ( ) . into_boxed_str ( ) ,
204+ ) )
205+ }
206+
177207pub fn get_constant_from_var_name < ' a > (
178208 var_name : & str ,
179209 identifiers : & ' a HashMap < String , Identifier > ,
@@ -386,4 +416,62 @@ mod tests {
386416 Err ( HintError :: IdentifierNotInteger ( bx) ) if bx. as_ref( ) == "value"
387417 ) ;
388418 }
419+
420+ #[ test]
421+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
422+ fn get_identifier_from_scoped_name_valid ( ) {
423+ let accessible_scopes = & [ "scope1" . to_string ( ) , "scope1.scope2" . to_string ( ) ] ;
424+
425+ let identifier = const_identifier ( 5 ) ;
426+
427+ let identifiers = HashMap :: from ( [ (
428+ "scope1.scope2.constant1.constant2" . to_string ( ) ,
429+ identifier. clone ( ) ,
430+ ) ] ) ;
431+
432+ assert_matches ! (
433+ get_identifier_from_scoped_name( "constant1.constant2" , & identifiers, accessible_scopes) ,
434+ Ok ( id) if id == & identifier
435+ ) ;
436+ }
437+
438+ #[ test]
439+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
440+ fn get_identifier_from_scoped_name_invalid ( ) {
441+ let accessible_scopes = & [ "scope1" . to_string ( ) , "scope1.scope2" . to_string ( ) ] ;
442+
443+ let identifier = const_identifier ( 5 ) ;
444+
445+ let identifiers = HashMap :: from ( [ (
446+ "scope1.scope2.constant3.constant4" . to_string ( ) ,
447+ identifier. clone ( ) ,
448+ ) ] ) ;
449+
450+ assert_matches ! (
451+ get_identifier_from_scoped_name( "constant1.constant2" , & identifiers, accessible_scopes) ,
452+ Err ( HintError :: UnknownIdentifier ( bx) ) if bx. as_ref( ) == "constant1.constant2"
453+ ) ;
454+ }
455+
456+ #[ test]
457+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
458+ fn get_identifier_from_scoped_name_invalid_partial_match ( ) {
459+ let accessible_scopes = & [ "scope1" . to_string ( ) , "scope1.scope2" . to_string ( ) ] ;
460+
461+ let identifier = const_identifier ( 5 ) ;
462+
463+ let identifiers = HashMap :: from ( [
464+ ( "scope1.scope2.constant1" . to_string ( ) , identifier. clone ( ) ) ,
465+ ( "scope1.constant1.constant2" . to_string ( ) , identifier. clone ( ) ) ,
466+ (
467+ "scope1.scope2.constant1.constant3" . to_string ( ) ,
468+ identifier. clone ( ) ,
469+ ) ,
470+ ] ) ;
471+
472+ assert_matches ! (
473+ get_identifier_from_scoped_name( "constant1.constant2" , & identifiers, accessible_scopes) ,
474+ Err ( HintError :: UnknownIdentifier ( bx) ) if bx. as_ref( ) == "constant1.constant2"
475+ ) ;
476+ }
389477}
0 commit comments