mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Fix contextually typed object literal completions where the object being edited affects its own inference (#36556)
* Conditionally elide a parameter from contextual type signature calculation * Slightly different approach to forbid inference to specific expressions * Handle nested literals and mapped types correctly * Delete unused cache * Rename ContextFlags.BaseConstraint and related usage * Add tests from my PR * Update ContextFlags comment Co-Authored-By: Wesley Wigham <wwigham@gmail.com> * Update comments and fourslash triple slash refs Co-authored-by: Wesley Wigham <wwigham@gmail.com>
This commit is contained in:
+11
-11
@@ -1280,8 +1280,8 @@ namespace ts.Completions {
|
||||
// Cursor is inside a JSX self-closing element or opening element
|
||||
const attrsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes);
|
||||
if (!attrsType) return GlobalsSearch.Continue;
|
||||
const baseType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes, ContextFlags.BaseConstraint);
|
||||
symbols = filterJsxAttributes(getPropertiesForObjectExpression(attrsType, baseType, jsxContainer!.attributes, typeChecker), jsxContainer!.attributes.properties);
|
||||
const completionsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes, ContextFlags.Completions);
|
||||
symbols = filterJsxAttributes(getPropertiesForObjectExpression(attrsType, completionsType, jsxContainer!.attributes, typeChecker), jsxContainer!.attributes.properties);
|
||||
setSortTextToOptionalMember();
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
isNewIdentifierLocation = false;
|
||||
@@ -1800,10 +1800,10 @@ namespace ts.Completions {
|
||||
|
||||
if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
const instantiatedType = typeChecker.getContextualType(objectLikeContainer);
|
||||
const baseType = instantiatedType && typeChecker.getContextualType(objectLikeContainer, ContextFlags.BaseConstraint);
|
||||
if (!instantiatedType || !baseType) return GlobalsSearch.Fail;
|
||||
isNewIdentifierLocation = hasIndexSignature(instantiatedType || baseType);
|
||||
typeMembers = getPropertiesForObjectExpression(instantiatedType, baseType, objectLikeContainer, typeChecker);
|
||||
const completionsType = instantiatedType && typeChecker.getContextualType(objectLikeContainer, ContextFlags.Completions);
|
||||
if (!instantiatedType || !completionsType) return GlobalsSearch.Fail;
|
||||
isNewIdentifierLocation = hasIndexSignature(instantiatedType || completionsType);
|
||||
typeMembers = getPropertiesForObjectExpression(instantiatedType, completionsType, objectLikeContainer, typeChecker);
|
||||
existingMembers = objectLikeContainer.properties;
|
||||
}
|
||||
else {
|
||||
@@ -2549,10 +2549,10 @@ namespace ts.Completions {
|
||||
return jsdoc && jsdoc.tags && (rangeContainsPosition(jsdoc, position) ? findLast(jsdoc.tags, tag => tag.pos < position) : undefined);
|
||||
}
|
||||
|
||||
function getPropertiesForObjectExpression(contextualType: Type, baseConstrainedType: Type | undefined, obj: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker): Symbol[] {
|
||||
const hasBaseType = baseConstrainedType && baseConstrainedType !== contextualType;
|
||||
const type = hasBaseType && !(baseConstrainedType!.flags & TypeFlags.AnyOrUnknown)
|
||||
? checker.getUnionType([contextualType, baseConstrainedType!])
|
||||
function getPropertiesForObjectExpression(contextualType: Type, completionsType: Type | undefined, obj: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker): Symbol[] {
|
||||
const hasCompletionsType = completionsType && completionsType !== contextualType;
|
||||
const type = hasCompletionsType && !(completionsType!.flags & TypeFlags.AnyOrUnknown)
|
||||
? checker.getUnionType([contextualType, completionsType!])
|
||||
: contextualType;
|
||||
|
||||
const properties = type.isUnion()
|
||||
@@ -2564,7 +2564,7 @@ namespace ts.Completions {
|
||||
checker.isTypeInvalidDueToUnionDiscriminant(memberType, obj))))
|
||||
: type.getApparentProperties();
|
||||
|
||||
return hasBaseType ? properties.filter(hasDeclarationOtherThanSelf) : properties;
|
||||
return hasCompletionsType ? properties.filter(hasDeclarationOtherThanSelf) : properties;
|
||||
|
||||
// Filter out members whose only declaration is the object literal itself to avoid
|
||||
// self-fulfilling completions like:
|
||||
|
||||
Reference in New Issue
Block a user