Skip to content

Commit 5909d2a

Browse files
committed
feat(44888): omit completions in an object expression with an instantiated class type
1 parent 40ec839 commit 5909d2a

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
@@ -3032,16 +3032,9 @@ namespace ts.Completions {
30323032
? checker.getUnionType([contextualType, completionsType!])
30333033
: contextualType;
30343034

3035-
const properties = type.isUnion()
3036-
? checker.getAllPossiblePropertiesOfTypes(type.types.filter(memberType =>
3037-
// 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.
3038-
!(memberType.flags & TypeFlags.Primitive ||
3039-
checker.isArrayLikeType(memberType) ||
3040-
typeHasCallOrConstructSignatures(memberType, checker) ||
3041-
checker.isTypeInvalidDueToUnionDiscriminant(memberType, obj))))
3042-
: type.getApparentProperties();
3043-
3044-
return hasCompletionsType ? properties.filter(hasDeclarationOtherThanSelf) : properties;
3035+
const properties = getApparentProperties(type, obj, checker);
3036+
return type.isClass() && containsNonPublicProperties(properties) ? [] :
3037+
hasCompletionsType ? filter(properties, hasDeclarationOtherThanSelf) : properties;
30453038

30463039
// Filter out members whose only declaration is the object literal itself to avoid
30473040
// self-fulfilling completions like:
@@ -3053,6 +3046,20 @@ namespace ts.Completions {
30533046
}
30543047
}
30553048

3049+
function getApparentProperties(type: Type, node: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker) {
3050+
if (!type.isUnion()) return type.getApparentProperties();
3051+
return checker.getAllPossiblePropertiesOfTypes(filter(type.types, memberType =>
3052+
!(memberType.flags & TypeFlags.Primitive
3053+
|| checker.isArrayLikeType(memberType)
3054+
|| checker.isTypeInvalidDueToUnionDiscriminant(memberType, node)
3055+
|| typeHasCallOrConstructSignatures(memberType, checker)
3056+
|| memberType.isClass() && containsNonPublicProperties(memberType.getApparentProperties()))));
3057+
}
3058+
3059+
function containsNonPublicProperties(props: Symbol[]) {
3060+
return some(props, p => !!(getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.NonPublicAccessibilityModifier));
3061+
}
3062+
30563063
/**
30573064
* Gets all properties on a type, but if that type is a union of several types,
30583065
* 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)