feat(44888): omit completions in an object expression with an instantiated class type (#45044)

This commit is contained in:
Oleksandr T 2021-08-20 23:51:37 +03:00 committed by GitHub
parent 69b5b2b2f3
commit 65ed4124ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 10 deletions

View File

@ -3050,16 +3050,9 @@ namespace ts.Completions {
? checker.getUnionType([contextualType, completionsType!])
: contextualType;
const properties = type.isUnion()
? checker.getAllPossiblePropertiesOfTypes(type.types.filter(memberType =>
// 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.
!(memberType.flags & TypeFlags.Primitive ||
checker.isArrayLikeType(memberType) ||
typeHasCallOrConstructSignatures(memberType, checker) ||
checker.isTypeInvalidDueToUnionDiscriminant(memberType, obj))))
: type.getApparentProperties();
return hasCompletionsType ? properties.filter(hasDeclarationOtherThanSelf) : properties;
const properties = getApparentProperties(type, obj, checker);
return type.isClass() && containsNonPublicProperties(properties) ? [] :
hasCompletionsType ? filter(properties, hasDeclarationOtherThanSelf) : properties;
// Filter out members whose only declaration is the object literal itself to avoid
// self-fulfilling completions like:
@ -3071,6 +3064,20 @@ namespace ts.Completions {
}
}
function getApparentProperties(type: Type, node: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker) {
if (!type.isUnion()) return type.getApparentProperties();
return checker.getAllPossiblePropertiesOfTypes(filter(type.types, memberType =>
!(memberType.flags & TypeFlags.Primitive
|| checker.isArrayLikeType(memberType)
|| checker.isTypeInvalidDueToUnionDiscriminant(memberType, node)
|| typeHasCallOrConstructSignatures(memberType, checker)
|| memberType.isClass() && containsNonPublicProperties(memberType.getApparentProperties()))));
}
function containsNonPublicProperties(props: Symbol[]) {
return some(props, p => !!(getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.NonPublicAccessibilityModifier));
}
/**
* Gets all properties on a type, but if that type is a union of several types,
* excludes array-like types or callable/constructable types.

View File

@ -0,0 +1,38 @@
/// <reference path="fourslash.ts" />
////class C1 {
//// public a: string;
//// protected b: string;
//// private c: string;
////
//// constructor(a: string, b = "", c = "") {
//// this.a = a;
//// this.b = b;
//// this.c = c;
//// }
////}
////class C2 {
//// public a: string;
//// constructor(a: string) {
//// this.a = a;
//// }
////}
////function f1(foo: C1 | C2 | { d: number }) {}
////f1({ /*1*/ });
////function f2(foo: C1 | C2) {}
////f2({ /*2*/ });
////
////function f3(foo: C2) {}
////f3({ /*3*/ });
verify.completions({
marker: "1",
exact: ["a", "d"],
}, {
marker: "2",
exact: ["a"]
}, {
marker: "3",
exact: ["a"]
});