1616using System . Collections . Generic ;
1717using System . Linq ;
1818using Microsoft . Python . Analysis ;
19+ using Microsoft . Python . Analysis . Analyzer ;
20+ using Microsoft . Python . Analysis . Types ;
1921using Microsoft . Python . Analysis . Values ;
22+ using Microsoft . Python . Core ;
2023using Microsoft . Python . LanguageServer . Protocol ;
2124using Microsoft . Python . Parsing . Ast ;
2225
2326namespace Microsoft . Python . LanguageServer . Completion {
24- internal static class ExpressionCompletion {
27+ internal static class ExpressionCompletion {
2528 public static IEnumerable < CompletionItem > GetCompletionsFromMembers ( Expression e , IScope scope , CompletionContext context ) {
2629 using ( context . Analysis . ExpressionEvaluator . OpenScope ( scope ) ) {
2730 return GetItemsFromExpression ( e , context ) ;
@@ -35,14 +38,19 @@ public static IEnumerable<CompletionItem> GetCompletionsFromMembers(Expression e
3538 }
3639
3740 private static IEnumerable < CompletionItem > GetItemsFromExpression ( Expression e , CompletionContext context ) {
38- var value = context . Analysis . ExpressionEvaluator . GetValueFromExpression ( e ) ;
41+ var eval = context . Analysis . ExpressionEvaluator ;
42+ var value = eval . GetValueFromExpression ( e ) ;
3943 if ( ! value . IsUnknown ( ) ) {
40- var items = new List < CompletionItem > ( ) ;
44+
4145 var type = value . GetPythonType ( ) ;
42- var names = type . GetMemberNames ( ) . ToArray ( ) ;
43- foreach ( var t in names ) {
46+ if ( type is IPythonClassType cls ) {
47+ return GetClassItems ( cls , e , context ) ;
48+ }
49+
50+ var items = new List < CompletionItem > ( ) ;
51+ foreach ( var t in type . GetMemberNames ( ) . ToArray ( ) ) {
4452 var m = type . GetMember ( t ) ;
45- if ( m is IVariable v && v . Source != VariableSource . Declaration ) {
53+ if ( m is IVariable v && v . Source != VariableSource . Declaration ) {
4654 continue ;
4755 }
4856 items . Add ( context . ItemSource . CreateCompletionItem ( t , m , type ) ) ;
@@ -51,5 +59,36 @@ private static IEnumerable<CompletionItem> GetItemsFromExpression(Expression e,
5159 }
5260 return Enumerable . Empty < CompletionItem > ( ) ;
5361 }
62+
63+ private static IEnumerable < CompletionItem > GetClassItems ( IPythonClassType cls , Expression e , CompletionContext context ) {
64+ var eval = context . Analysis . ExpressionEvaluator ;
65+ // See if we are completing on self. Note that we may be inside inner function
66+ // that does not necessarily have 'self' argument so we are looking beyond local
67+ // scope. We then check that variable type matches the class type, if any.
68+ var selfVariable = eval . LookupNameInScopes ( "self" ) ;
69+ var completingOnSelf = cls . Equals ( selfVariable ? . GetPythonType ( ) ) && e is NameExpression nex && nex . Name == "self" ;
70+
71+ var items = new List < CompletionItem > ( ) ;
72+ var names = cls . GetMemberNames ( ) . ToArray ( ) ;
73+
74+ foreach ( var t in names ) {
75+ var m = cls . GetMember ( t ) ;
76+ if ( m is IVariable v && v . Source != VariableSource . Declaration ) {
77+ continue ;
78+ }
79+ // If this is class member completion, unmangle private member names.
80+ var unmangledName = cls . UnmangleMemberName ( t ) ;
81+ if ( ! string . IsNullOrEmpty ( unmangledName ) ) {
82+ // Hide private variables outside of the class scope.
83+ if ( ! completingOnSelf && cls . IsPrivateMember ( t ) ) {
84+ continue ;
85+ }
86+ items . Add ( context . ItemSource . CreateCompletionItem ( unmangledName , m , cls ) ) ;
87+ } else {
88+ items . Add ( context . ItemSource . CreateCompletionItem ( t , m , cls ) ) ;
89+ }
90+ }
91+ return items ;
92+ }
5493 }
5594}
0 commit comments