11use std:: collections:: HashMap ;
22
3- use code_analysis:: { LuaFunctionType , LuaPropertyOwnerId , LuaSignatureId , LuaType , SemanticModel } ;
4- use emmylua_parser:: { LuaAst , LuaAstNode , LuaCallExpr , LuaClosureExpr , LuaExpr , LuaLocalName } ;
5- use lsp_types:: { InlayHint , InlayHintKind , InlayHintLabel } ;
3+ use code_analysis:: {
4+ FileId , InferGuard , LuaFunctionType , LuaMemberId , LuaMemberKey , LuaMemberOwner ,
5+ LuaPropertyOwnerId , LuaSignatureId , LuaType , SemanticModel ,
6+ } ;
7+ use emmylua_parser:: {
8+ LuaAst , LuaAstNode , LuaCallExpr , LuaClosureExpr , LuaExpr , LuaFuncStat , LuaIndexExpr ,
9+ LuaLocalName , LuaSyntaxId , LuaVarExpr ,
10+ } ;
11+ use lsp_types:: { InlayHint , InlayHintKind , InlayHintLabel , InlayHintLabelPart } ;
612use rowan:: NodeOrToken ;
713
814use crate :: util:: humanize_type;
@@ -22,6 +28,9 @@ pub fn build_inlay_hints(semantic_model: &mut SemanticModel) -> Option<Vec<Inlay
2228 LuaAst :: LuaLocalName ( local_name) => {
2329 build_local_name_hint ( semantic_model, & mut result, local_name) ;
2430 }
31+ LuaAst :: LuaFuncStat ( func_stat) => {
32+ build_func_stat_override_hint ( semantic_model, & mut result, func_stat) ;
33+ }
2534 _ => { }
2635 }
2736 }
@@ -360,3 +369,122 @@ fn build_local_name_hint(
360369
361370 Some ( ( ) )
362371}
372+
373+ fn build_func_stat_override_hint (
374+ semantic_model : & mut SemanticModel ,
375+ result : & mut Vec < InlayHint > ,
376+ func_stat : LuaFuncStat ,
377+ ) -> Option < ( ) > {
378+ if !semantic_model. get_emmyrc ( ) . hint . override_hint {
379+ return Some ( ( ) ) ;
380+ }
381+
382+ let func_name = func_stat. get_func_name ( ) ?;
383+ if let LuaVarExpr :: IndexExpr ( index_expr) = func_name {
384+ let prefix_expr = index_expr. get_prefix_expr ( ) ?;
385+ let prefix_type = semantic_model. infer_expr ( prefix_expr. into ( ) ) ?;
386+ if let LuaType :: Def ( id) = prefix_type {
387+ let supers = semantic_model
388+ . get_db ( )
389+ . get_type_index ( )
390+ . get_super_types ( & id) ?;
391+
392+ let name = index_expr. get_index_key ( ) ?;
393+ let member_key: LuaMemberKey = name. into ( ) ;
394+ let infer_guard = & mut InferGuard :: new ( ) ;
395+ for super_type in supers {
396+ if let Some ( member_id) =
397+ get_super_member_id ( semantic_model, super_type, & member_key, infer_guard)
398+ {
399+ let member = semantic_model
400+ . get_db ( )
401+ . get_member_index ( )
402+ . get_member ( & member_id) ?;
403+
404+ let document = semantic_model. get_document ( ) ;
405+ let last_paren_pos = func_stat
406+ . get_closure ( ) ?
407+ . get_params_list ( ) ?
408+ . get_range ( )
409+ . end ( ) ;
410+ let last_paren_lsp_pos = document. to_lsp_position ( last_paren_pos) ?;
411+
412+ let file_id = member. get_file_id ( ) ;
413+ let syntax_id = member. get_syntax_id ( ) ;
414+ let lsp_location =
415+ get_override_lsp_location ( semantic_model, file_id, syntax_id) ?;
416+ let hint = InlayHint {
417+ kind : Some ( InlayHintKind :: TYPE ) ,
418+ label : InlayHintLabel :: LabelParts ( vec ! [ InlayHintLabelPart {
419+ value: "override" . to_string( ) ,
420+ location: Some ( lsp_location) ,
421+ ..Default :: default ( )
422+ } ] ) ,
423+ position : last_paren_lsp_pos,
424+ text_edits : None ,
425+ tooltip : None ,
426+ padding_left : Some ( true ) ,
427+ padding_right : None ,
428+ data : None ,
429+ } ;
430+ result. push ( hint) ;
431+ break ;
432+ }
433+ }
434+ }
435+ }
436+
437+ Some ( ( ) )
438+ }
439+
440+ fn get_super_member_id (
441+ semantic_model : & mut SemanticModel ,
442+ super_type : LuaType ,
443+ member_key : & LuaMemberKey ,
444+ infer_guard : & mut InferGuard ,
445+ ) -> Option < LuaMemberId > {
446+ if let LuaType :: Ref ( super_type_id) = & super_type {
447+ infer_guard. check ( super_type_id) ?;
448+ let member_owner = LuaMemberOwner :: Type ( super_type_id. clone ( ) ) ;
449+ let member_map = semantic_model
450+ . get_db ( )
451+ . get_member_index ( )
452+ . get_member_map ( member_owner) ?;
453+
454+ if let Some ( member_id) = member_map. get ( & member_key) {
455+ return Some ( member_id. clone ( ) ) ;
456+ }
457+
458+ let super_types = semantic_model
459+ . get_db ( )
460+ . get_type_index ( )
461+ . get_super_types ( super_type_id) ?;
462+ for super_type in super_types {
463+ if let Some ( member_id) =
464+ get_super_member_id ( semantic_model, super_type, member_key, infer_guard)
465+ {
466+ return Some ( member_id) ;
467+ }
468+ }
469+ }
470+
471+ None
472+ }
473+
474+ fn get_override_lsp_location (
475+ semantic_model : & mut SemanticModel ,
476+ file_id : FileId ,
477+ syntax_id : LuaSyntaxId ,
478+ ) -> Option < lsp_types:: Location > {
479+ let document = semantic_model. get_document_by_file_id ( file_id) ?;
480+ let root = semantic_model. get_root_by_file_id ( file_id) ?;
481+ let node = syntax_id. to_node_from_root ( root. syntax ( ) ) ?;
482+ let range = if let Some ( index_exor) = LuaIndexExpr :: cast ( node. clone ( ) ) {
483+ index_exor. get_index_name_token ( ) ?. text_range ( )
484+ } else {
485+ node. text_range ( )
486+ } ;
487+
488+ let lsp_range = document. to_lsp_location ( range) ?;
489+ Some ( lsp_range)
490+ }
0 commit comments