@@ -23,7 +23,7 @@ use erg_compiler::erg_parser::token::TokenKind;
2323use erg_compiler:: hir:: Expr ;
2424use erg_compiler:: module:: SharedCompilerResource ;
2525use erg_compiler:: ty:: { HasType , ParamTy , Type } ;
26- use erg_compiler:: varinfo:: { AbsLocation , VarInfo } ;
26+ use erg_compiler:: varinfo:: { AbsLocation , Mutability , VarInfo , VarKind } ;
2727use TokenKind :: * ;
2828
2929use lsp_types:: {
@@ -35,17 +35,40 @@ use crate::_log;
3535use crate :: server:: { ELSResult , Flags , RedirectableStdout , Server } ;
3636use crate :: util:: { self , loc_to_pos, NormalizedUrl } ;
3737
38- fn comp_item_kind ( vi : & VarInfo ) -> CompletionItemKind {
39- match & vi . t {
38+ fn comp_item_kind ( t : & Type , muty : Mutability ) -> CompletionItemKind {
39+ match t {
4040 Type :: Subr ( subr) if subr. self_t ( ) . is_some ( ) => CompletionItemKind :: METHOD ,
4141 Type :: Quantified ( quant) if quant. self_t ( ) . is_some ( ) => CompletionItemKind :: METHOD ,
4242 Type :: Subr ( _) | Type :: Quantified ( _) => CompletionItemKind :: FUNCTION ,
4343 Type :: ClassType => CompletionItemKind :: CLASS ,
4444 Type :: TraitType => CompletionItemKind :: INTERFACE ,
45+ Type :: Or ( l, r) => {
46+ let l = comp_item_kind ( l, muty) ;
47+ let r = comp_item_kind ( r, muty) ;
48+ if l == r {
49+ l
50+ } else if muty. is_const ( ) {
51+ CompletionItemKind :: CONSTANT
52+ } else {
53+ CompletionItemKind :: VARIABLE
54+ }
55+ }
56+ Type :: And ( l, r) => {
57+ let l = comp_item_kind ( l, muty) ;
58+ let r = comp_item_kind ( r, muty) ;
59+ if l == CompletionItemKind :: VARIABLE {
60+ r
61+ } else {
62+ l
63+ }
64+ }
65+ Type :: Refinement ( r) => comp_item_kind ( & r. t , muty) ,
66+ Type :: Bounded { sub, .. } => comp_item_kind ( sub, muty) ,
4567 t if matches ! ( & t. qual_name( ) [ ..] , "Module" | "PyModule" | "GenericModule" ) => {
4668 CompletionItemKind :: MODULE
4769 }
48- _ if vi. muty . is_const ( ) => CompletionItemKind :: CONSTANT ,
70+ Type :: Type => CompletionItemKind :: CONSTANT ,
71+ _ if muty. is_const ( ) => CompletionItemKind :: CONSTANT ,
4972 _ => CompletionItemKind :: VARIABLE ,
5073 }
5174}
@@ -112,21 +135,24 @@ impl CompletionOrder {
112135}
113136
114137pub struct CompletionOrderSetter < ' b > {
115- vi : & ' b VarInfo ,
138+ t : & ' b Type ,
139+ kind : & ' b VarKind ,
116140 arg_pt : Option < & ' b ParamTy > ,
117141 mod_ctx : & ' b Context , // for subtype judgement, not for variable lookup
118142 label : String ,
119143}
120144
121145impl < ' b > CompletionOrderSetter < ' b > {
122146 pub fn new (
123- vi : & ' b VarInfo ,
147+ t : & ' b Type ,
148+ kind : & ' b VarKind ,
124149 arg_pt : Option < & ' b ParamTy > ,
125150 mod_ctx : & ' b Context ,
126151 label : String ,
127152 ) -> Self {
128153 Self {
129- vi,
154+ t,
155+ kind,
130156 arg_pt,
131157 mod_ctx,
132158 label,
@@ -140,7 +166,7 @@ impl<'b> CompletionOrderSetter<'b> {
140166 } else if self . label . starts_with ( '_' ) {
141167 orders. push ( CompletionOrder :: Escaped ) ;
142168 }
143- if self . vi . kind . is_builtin ( ) {
169+ if self . kind . is_builtin ( ) {
144170 orders. push ( CompletionOrder :: Builtin ) ;
145171 }
146172 if self
@@ -152,11 +178,11 @@ impl<'b> CompletionOrderSetter<'b> {
152178 #[ allow( clippy:: blocks_in_conditions) ]
153179 if self
154180 . arg_pt
155- . map_or ( false , |pt| self . mod_ctx . subtype_of ( & self . vi . t , pt. typ ( ) ) )
181+ . map_or ( false , |pt| self . mod_ctx . subtype_of ( self . t , pt. typ ( ) ) )
156182 {
157183 orders. push ( CompletionOrder :: TypeMatched ) ;
158184 } else if self . arg_pt . map_or ( false , |pt| {
159- let Some ( return_t) = self . vi . t . return_t ( ) else {
185+ let Some ( return_t) = self . t . return_t ( ) else {
160186 return false ;
161187 } ;
162188 if return_t. has_qvar ( ) {
@@ -196,7 +222,7 @@ fn external_item(name: &str, vi: &VarInfo, mod_name: &str) -> CompletionItem {
196222 let mut item =
197223 CompletionItem :: new_simple ( format ! ( "{name} (import from {mod_name})" ) , vi. t . to_string ( ) ) ;
198224 item. sort_text = Some ( format ! ( "{}_{}" , CompletionOrder :: STD_ITEM , item. label) ) ;
199- item. kind = Some ( comp_item_kind ( vi ) ) ;
225+ item. kind = Some ( comp_item_kind ( & vi . t , vi . muty ) ) ;
200226 let import = if PYTHON_MODE {
201227 format ! ( "from {mod_name} import {name}\n " )
202228 } else {
@@ -467,10 +493,16 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
467493 continue ;
468494 }
469495 let mut item = CompletionItem :: new_simple ( label, vi. t . to_string ( ) ) ;
470- CompletionOrderSetter :: new ( vi, arg_pt. as_ref ( ) , mod_ctx, item. label . clone ( ) )
471- . set ( & mut item) ;
496+ CompletionOrderSetter :: new (
497+ & vi. t ,
498+ & vi. kind ,
499+ arg_pt. as_ref ( ) ,
500+ mod_ctx,
501+ item. label . clone ( ) ,
502+ )
503+ . set ( & mut item) ;
472504 // item.sort_text = Some(format!("{}_{}", CompletionOrder::OtherNamespace, item.label));
473- item. kind = Some ( comp_item_kind ( vi ) ) ;
505+ item. kind = Some ( comp_item_kind ( & vi . t , vi . muty ) ) ;
474506 item. data = Some ( Value :: String ( vi. def_loc . to_string ( ) ) ) ;
475507 let import = if PYTHON_MODE {
476508 format ! ( "from {path} import {name}\n " )
@@ -590,6 +622,25 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
590622 _log ! ( self , "module context not found: {uri}" ) ;
591623 return Ok ( Some ( CompletionResponse :: Array ( result) ) ) ;
592624 } ;
625+ if PYTHON_MODE {
626+ if let Some ( receiver_t) = & receiver_t {
627+ for ( field, ty) in mod_ctx. context . fields ( receiver_t) {
628+ let mut item =
629+ CompletionItem :: new_simple ( field. symbol . to_string ( ) , ty. to_string ( ) ) ;
630+ CompletionOrderSetter :: new (
631+ & ty,
632+ & VarKind :: Builtin ,
633+ arg_pt. as_ref ( ) ,
634+ & mod_ctx. context ,
635+ item. label . clone ( ) ,
636+ )
637+ . set ( & mut item) ;
638+ item. kind = Some ( comp_item_kind ( & ty, Mutability :: Immutable ) ) ;
639+ already_appeared. insert ( item. label . clone ( ) ) ;
640+ result. push ( item) ;
641+ }
642+ }
643+ }
593644 for ( name, vi) in contexts. into_iter ( ) . flat_map ( |ctx| ctx. local_dir ( ) ) {
594645 if comp_kind. should_be_method ( ) && vi. vis . is_private ( ) {
595646 continue ;
@@ -621,9 +672,15 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
621672 }
622673 let readable_t = mod_ctx. context . readable_type ( vi. t . clone ( ) ) ;
623674 let mut item = CompletionItem :: new_simple ( label, readable_t. to_string ( ) ) ;
624- CompletionOrderSetter :: new ( vi, arg_pt. as_ref ( ) , & mod_ctx. context , item. label . clone ( ) )
625- . set ( & mut item) ;
626- item. kind = Some ( comp_item_kind ( vi) ) ;
675+ CompletionOrderSetter :: new (
676+ & vi. t ,
677+ & vi. kind ,
678+ arg_pt. as_ref ( ) ,
679+ & mod_ctx. context ,
680+ item. label . clone ( ) ,
681+ )
682+ . set ( & mut item) ;
683+ item. kind = Some ( comp_item_kind ( & vi. t , vi. muty ) ) ;
627684 item. data = Some ( Value :: String ( vi. def_loc . to_string ( ) ) ) ;
628685 already_appeared. insert ( item. label . clone ( ) ) ;
629686 result. push ( item) ;
0 commit comments