Skip to content

Commit 65ed412

Browse files
authored
feat(44888): omit completions in an object expression with an instantiated class type (microsoft#45044)
1 parent 69b5b2b commit 65ed412

File tree

2 files changed

+55
-10
lines changed

2 files changed

+55
-10
lines changed

src/services/completions.ts

+17-10
Original file line numberDiff line numberDiff line change
@@ -3050,16 +3050,9 @@ namespace ts.Completions {
30503050
? checker.getUnionType([contextualType, completionsType!])
30513051
: contextualType;
30523052

3053-
const properties = type.isUnion()
3054-
? checker.getAllPossiblePropertiesOfTypes(type.types.filter(memberType =>
3055-
// If we're providing completions for an object literal, skip primitive, array-like, or callable types since those shouldn't be implemented by object literals.
3056-
!(memberType.flags & TypeFlags.Primitive ||
3057-
checker.isArrayLikeType(memberType) ||
3058-
typeHasCallOrConstructSignatures(memberType, checker) ||
3059-
checker.isTypeInvalidDueToUnionDiscriminant(memberType, obj))))
3060-
: type.getApparentProperties();
3061-
3062-
return hasCompletionsType ? properties.filter(hasDeclarationOtherThanSelf) : properties;
3053+
const properties = getApparentProperties(type, obj, checker);
3054+
return type.isClass() && containsNonPublicProperties(properties) ? [] :
3055+
hasCompletionsType ? filter(properties, hasDeclarationOtherThanSelf) : properties;
30633056

30643057
// Filter out members whose only declaration is the object literal itself to avoid
30653058
// self-fulfilling completions like:
@@ -3071,6 +3064,20 @@ namespace ts.Completions {
30713064
}
30723065
}
30733066

3067+
function getApparentProperties(type: Type, node: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker) {
3068+
if (!type.isUnion()) return type.getApparentProperties();
3069+
return checker.getAllPossiblePropertiesOfTypes(filter(type.types, memberType =>
3070+
!(memberType.flags & TypeFlags.Primitive
3071+
|| checker.isArrayLikeType(memberType)
3072+
|| checker.isTypeInvalidDueToUnionDiscriminant(memberType, node)
3073+
|| typeHasCallOrConstructSignatures(memberType, checker)
3074+
|| memberType.isClass() && containsNonPublicProperties(memberType.getApparentProperties()))));
3075+
}
3076+
3077+
function containsNonPublicProperties(props: Symbol[]) {
3078+
return some(props, p => !!(getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.NonPublicAccessibilityModifier));
3079+
}
3080+
30743081
/**
30753082
* Gets all properties on a type, but if that type is a union of several types,
30763083
* excludes array-like types or callable/constructable types.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
////class C1 {
4+
//// public a: string;
5+
//// protected b: string;
6+
//// private c: string;
7+
////
8+
//// constructor(a: string, b = "", c = "") {
9+
//// this.a = a;
10+
//// this.b = b;
11+
//// this.c = c;
12+
//// }
13+
////}
14+
////class C2 {
15+
//// public a: string;
16+
//// constructor(a: string) {
17+
//// this.a = a;
18+
//// }
19+
////}
20+
////function f1(foo: C1 | C2 | { d: number }) {}
21+
////f1({ /*1*/ });
22+
23+
////function f2(foo: C1 | C2) {}
24+
////f2({ /*2*/ });
25+
////
26+
////function f3(foo: C2) {}
27+
////f3({ /*3*/ });
28+
29+
verify.completions({
30+
marker: "1",
31+
exact: ["a", "d"],
32+
}, {
33+
marker: "2",
34+
exact: ["a"]
35+
}, {
36+
marker: "3",
37+
exact: ["a"]
38+
});

0 commit comments

Comments
 (0)