1+ use std:: collections:: HashSet ;
2+
13use emmylua_parser:: { LuaAstNode , LuaIndexExpr } ;
24use rowan:: NodeOrToken ;
35
@@ -12,43 +14,6 @@ pub fn enum_variable_is_param(
1214 index_expr : & LuaIndexExpr ,
1315 prefix_typ : & LuaType ,
1416) -> Option < ( ) > {
15- fn find_enum_origin (
16- db : & DbIndex ,
17- cache : & mut LuaInferCache ,
18- decl_id : LuaDeclId ,
19- ) -> Option < LuaDeclId > {
20- let syntax_tree = db. get_vfs ( ) . get_syntax_tree ( & decl_id. file_id ) ?;
21- let root = syntax_tree. get_red_root ( ) ;
22-
23- let node = db
24- . get_decl_index ( )
25- . get_decl ( & decl_id) ?
26- . get_value_syntax_id ( ) ?
27- . to_node_from_root ( & root) ?;
28-
29- let semantic_decl = match node. into ( ) {
30- NodeOrToken :: Node ( node) => {
31- infer_node_semantic_decl ( db, cache, node, SemanticDeclLevel :: NoTrace )
32- }
33- NodeOrToken :: Token ( token) => {
34- infer_token_semantic_decl ( db, cache, token, SemanticDeclLevel :: NoTrace )
35- }
36- } ;
37-
38- match semantic_decl {
39- Some ( LuaSemanticDeclId :: Member ( _) ) => None ,
40- Some ( LuaSemanticDeclId :: LuaDecl ( new_decl_id) ) => {
41- let decl = db. get_decl_index ( ) . get_decl ( & new_decl_id) ?;
42- if decl. get_value_syntax_id ( ) . is_some ( ) {
43- Some ( find_enum_origin ( db, cache, new_decl_id) . unwrap_or ( new_decl_id) )
44- } else {
45- Some ( new_decl_id)
46- }
47- }
48- _ => None ,
49- }
50- }
51-
5217 let LuaType :: Ref ( id) = prefix_typ else {
5318 return None ;
5419 } ;
@@ -70,7 +35,8 @@ pub fn enum_variable_is_param(
7035 return None ;
7136 } ;
7237
73- let origin_decl_id = find_enum_origin ( db, cache, decl_id) . unwrap_or ( decl_id) ;
38+ let mut decl_guard = DeclGuard :: new ( ) ;
39+ let origin_decl_id = find_enum_origin ( db, cache, decl_id, & mut decl_guard) . unwrap_or ( decl_id) ;
7440 let decl = db. get_decl_index ( ) . get_decl ( & origin_decl_id) ?;
7541
7642 if decl. is_param ( ) {
@@ -79,3 +45,64 @@ pub fn enum_variable_is_param(
7945 None
8046 }
8147}
48+
49+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
50+ pub struct DeclGuard {
51+ decl_set : HashSet < LuaDeclId > ,
52+ }
53+
54+ impl DeclGuard {
55+ pub fn new ( ) -> Self {
56+ Self {
57+ decl_set : HashSet :: new ( ) ,
58+ }
59+ }
60+
61+ pub fn check ( & mut self , decl_id : LuaDeclId ) -> Option < ( ) > {
62+ if self . decl_set . contains ( & decl_id) {
63+ None
64+ } else {
65+ self . decl_set . insert ( decl_id) ;
66+ Some ( ( ) )
67+ }
68+ }
69+ }
70+
71+ fn find_enum_origin (
72+ db : & DbIndex ,
73+ cache : & mut LuaInferCache ,
74+ decl_id : LuaDeclId ,
75+ decl_guard : & mut DeclGuard ,
76+ ) -> Option < LuaDeclId > {
77+ decl_guard. check ( decl_id) ?;
78+ let syntax_tree = db. get_vfs ( ) . get_syntax_tree ( & decl_id. file_id ) ?;
79+ let root = syntax_tree. get_red_root ( ) ;
80+
81+ let node = db
82+ . get_decl_index ( )
83+ . get_decl ( & decl_id) ?
84+ . get_value_syntax_id ( ) ?
85+ . to_node_from_root ( & root) ?;
86+
87+ let semantic_decl = match node. into ( ) {
88+ NodeOrToken :: Node ( node) => {
89+ infer_node_semantic_decl ( db, cache, node, SemanticDeclLevel :: NoTrace )
90+ }
91+ NodeOrToken :: Token ( token) => {
92+ infer_token_semantic_decl ( db, cache, token, SemanticDeclLevel :: NoTrace )
93+ }
94+ } ;
95+
96+ match semantic_decl {
97+ Some ( LuaSemanticDeclId :: Member ( _) ) => None ,
98+ Some ( LuaSemanticDeclId :: LuaDecl ( new_decl_id) ) => {
99+ let decl = db. get_decl_index ( ) . get_decl ( & new_decl_id) ?;
100+ if decl. get_value_syntax_id ( ) . is_some ( ) {
101+ Some ( find_enum_origin ( db, cache, new_decl_id, decl_guard) . unwrap_or ( new_decl_id) )
102+ } else {
103+ Some ( new_decl_id)
104+ }
105+ }
106+ _ => None ,
107+ }
108+ }
0 commit comments