Skip to content

Commit

Permalink
feat(44888): omit completions in an object expression with an instant…
Browse files Browse the repository at this point in the history
…iated class type (microsoft#45044)
  • Loading branch information
a-tarasyuk authored and BobobUnicorn committed Oct 23, 2021
1 parent 0ed3834 commit 9b660b0
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 10 deletions.
27 changes: 17 additions & 10 deletions src/services/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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"]
});

0 comments on commit 9b660b0

Please sign in to comment.