@@ -480,82 +480,79 @@ pub fn analyze_local_func_stat(
480480 Some ( ( ) )
481481}
482482
483- fn register_expr_key_member ( analyzer : & mut LuaAnalyzer , field : & LuaTableField ) {
484- // Register expression-key members early so table-decl inference (and pairs)
485- // can see them even when the table itself has no explicit generic type.
486- let Some ( field_key) = field. get_field_key ( ) else {
487- return ;
488- } ;
489- let LuaIndexKey :: Expr ( _) = & field_key else {
490- return ;
491- } ;
492- let member_id = LuaMemberId :: new ( field. get_syntax_id ( ) , analyzer. file_id ) ;
493- if analyzer
494- . db
495- . get_member_index ( )
496- . get_member ( & member_id)
497- . is_some ( )
498- {
499- return ;
483+ /// Analyzes an assignment-style table field.
484+ ///
485+ /// Table-declaration analysis already registers static keys and value fields, for
486+ /// example `{ name = value }`, `{ ["name"] = value }`, `{ [1] = value }`, and
487+ /// `{ value1, value2 }`.
488+ ///
489+ /// This pass binds the field value type and eagerly materializes resolved
490+ /// bracket-key members such as `{ [key] = value }`, `{ [true] = value }`, or
491+ /// `{ [SomeEnum.A] = value }` so later consumers like table inference and
492+ /// `pairs` can see them before the unresolved table-field pass runs.
493+ pub fn analyze_table_field ( analyzer : & mut LuaAnalyzer , field : LuaTableField ) -> Option < ( ) > {
494+ if !field. is_assign_field ( ) {
495+ return Some ( ( ) ) ;
500496 }
501- let cache = analyzer
502- . context
503- . infer_manager
504- . get_infer_cache ( analyzer. file_id ) ;
505- let Ok ( member_key) = LuaMemberKey :: from_index_key ( analyzer. db , cache, & field_key) else {
506- return ;
507- } ;
508- if matches ! ( member_key, LuaMemberKey :: ExprType ( ref typ) if typ. is_unknown( ) ) {
509- return ;
497+
498+ if let Some ( field_key) = field. get_field_key ( ) {
499+ if let LuaIndexKey :: Expr ( _) = & field_key {
500+ // Decl analysis leaves `[expr] = value` fields unresolved. If the key
501+ // already resolves here, materialize the member now.
502+ let db = & mut * analyzer. db ;
503+ let member_id = LuaMemberId :: new ( field. get_syntax_id ( ) , analyzer. file_id ) ;
504+ if db. get_member_index ( ) . get_member ( & member_id) . is_none ( ) {
505+ let cache = analyzer
506+ . context
507+ . infer_manager
508+ . get_infer_cache ( analyzer. file_id ) ;
509+ if let Ok ( member_key) = LuaMemberKey :: from_index_key ( db, cache, & field_key) {
510+ if !matches ! ( member_key, LuaMemberKey :: ExprType ( ref typ) if typ. is_unknown( ) ) {
511+ if let Some ( table_expr) = field. get_parent :: < LuaTableExpr > ( ) {
512+ let owner_id = LuaMemberOwner :: Element ( InFiled :: new (
513+ analyzer. file_id ,
514+ table_expr. get_range ( ) ,
515+ ) ) ;
516+ let decl_feature = if analyzer. context . metas . contains ( & analyzer. file_id )
517+ {
518+ LuaMemberFeature :: MetaDefine
519+ } else {
520+ LuaMemberFeature :: FileDefine
521+ } ;
522+ let member = LuaMember :: new ( member_id, member_key, decl_feature, None ) ;
523+ db. get_member_index_mut ( ) . add_member ( owner_id, member) ;
524+ }
525+ }
526+ }
527+ }
528+ }
510529 }
511- let Some ( table_expr) = field. get_parent :: < LuaTableExpr > ( ) else {
512- return ;
513- } ;
514- let owner_id = LuaMemberOwner :: Element ( InFiled :: new ( analyzer. file_id , table_expr. get_range ( ) ) ) ;
515- let decl_feature = if analyzer. context . metas . contains ( & analyzer. file_id ) {
516- LuaMemberFeature :: MetaDefine
517- } else {
518- LuaMemberFeature :: FileDefine
519- } ;
520- let member = LuaMember :: new ( member_id, member_key, decl_feature, None ) ;
521- analyzer
522- . db
523- . get_member_index_mut ( )
524- . add_member ( owner_id, member) ;
525- }
526530
527- pub fn analyze_table_field ( analyzer : & mut LuaAnalyzer , field : LuaTableField ) -> Option < ( ) > {
528- register_expr_key_member ( analyzer, & field) ;
529-
530- if field. is_assign_field ( ) {
531- let value_expr = field. get_value_expr ( ) ?;
532- let member_id = LuaMemberId :: new ( field. get_syntax_id ( ) , analyzer. file_id ) ;
533- let value_type = match analyzer. infer_expr ( & value_expr. clone ( ) ) {
534- Ok ( value_type) => match value_type {
535- LuaType :: Def ( ref_id) => LuaType :: Ref ( ref_id) ,
536- _ => value_type,
537- } ,
538- Err ( InferFailReason :: None ) => LuaType :: Unknown ,
539- Err ( reason) => {
540- let unresolve = UnResolveMember {
541- file_id : analyzer. file_id ,
542- member_id,
543- expr : Some ( value_expr. clone ( ) ) ,
544- prefix : None ,
545- ret_idx : 0 ,
546- } ;
531+ let value_expr = field. get_value_expr ( ) ?;
532+ let member_id = LuaMemberId :: new ( field. get_syntax_id ( ) , analyzer. file_id ) ;
533+ let value_type = match analyzer. infer_expr ( & value_expr. clone ( ) ) {
534+ Ok ( value_type) => match value_type {
535+ LuaType :: Def ( ref_id) => LuaType :: Ref ( ref_id) ,
536+ _ => value_type,
537+ } ,
538+ Err ( InferFailReason :: None ) => LuaType :: Unknown ,
539+ Err ( reason) => {
540+ let unresolve = UnResolveMember {
541+ file_id : analyzer. file_id ,
542+ member_id,
543+ expr : Some ( value_expr. clone ( ) ) ,
544+ prefix : None ,
545+ ret_idx : 0 ,
546+ } ;
547547
548- analyzer. context . add_unresolve ( unresolve. into ( ) , reason) ;
549- return None ;
550- }
551- } ;
548+ analyzer. context . add_unresolve ( unresolve. into ( ) , reason) ;
549+ return None ;
550+ }
551+ } ;
552+
553+ let cache = LuaTypeCache :: InferType ( value_type) ;
554+ bind_type ( analyzer. db , member_id. into ( ) , cache) ;
552555
553- bind_type (
554- analyzer. db ,
555- member_id. into ( ) ,
556- LuaTypeCache :: InferType ( value_type) ,
557- ) ;
558- }
559556 Some ( ( ) )
560557}
561558
0 commit comments