mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 18:04:18 -05:00
Fix spurious circularity caused by removeOptionalityFromDeclaredType, cache result (#52696)
This commit is contained in:
@@ -1233,6 +1233,7 @@ const enum TypeSystemPropertyName {
|
||||
ResolvedTypeArguments,
|
||||
ResolvedBaseTypes,
|
||||
WriteType,
|
||||
ParameterInitializerContainsUndefined,
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -9983,6 +9984,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return !!(target as InterfaceType).baseTypesResolved;
|
||||
case TypeSystemPropertyName.WriteType:
|
||||
return !!getSymbolLinks(target as Symbol).writeType;
|
||||
case TypeSystemPropertyName.ParameterInitializerContainsUndefined:
|
||||
return getNodeLinks(target as ParameterDeclaration).parameterInitializerContainsUndefined !== undefined;
|
||||
}
|
||||
return Debug.assertNever(propertyName);
|
||||
}
|
||||
@@ -27295,22 +27298,37 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return symbol.flags & SymbolFlags.Variable && (getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0;
|
||||
}
|
||||
|
||||
function parameterInitializerContainsUndefined(declaration: ParameterDeclaration): boolean {
|
||||
const links = getNodeLinks(declaration);
|
||||
|
||||
if (links.parameterInitializerContainsUndefined === undefined) {
|
||||
if (!pushTypeResolution(declaration, TypeSystemPropertyName.ParameterInitializerContainsUndefined)) {
|
||||
reportCircularityError(declaration.symbol);
|
||||
return true;
|
||||
}
|
||||
|
||||
const containsUndefined = !!(getTypeFacts(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFacts.IsUndefined);
|
||||
|
||||
if (!popTypeResolution()) {
|
||||
reportCircularityError(declaration.symbol);
|
||||
return true;
|
||||
}
|
||||
|
||||
links.parameterInitializerContainsUndefined = containsUndefined;
|
||||
}
|
||||
|
||||
return links.parameterInitializerContainsUndefined;
|
||||
}
|
||||
|
||||
/** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */
|
||||
function removeOptionalityFromDeclaredType(declaredType: Type, declaration: VariableLikeDeclaration): Type {
|
||||
if (pushTypeResolution(declaration.symbol, TypeSystemPropertyName.DeclaredType)) {
|
||||
const annotationIncludesUndefined = strictNullChecks &&
|
||||
declaration.kind === SyntaxKind.Parameter &&
|
||||
declaration.initializer &&
|
||||
getTypeFacts(declaredType) & TypeFacts.IsUndefined &&
|
||||
!(getTypeFacts(checkExpression(declaration.initializer)) & TypeFacts.IsUndefined);
|
||||
popTypeResolution();
|
||||
const removeUndefined = strictNullChecks &&
|
||||
declaration.kind === SyntaxKind.Parameter &&
|
||||
declaration.initializer &&
|
||||
getTypeFacts(declaredType) & TypeFacts.IsUndefined &&
|
||||
!parameterInitializerContainsUndefined(declaration);
|
||||
|
||||
return annotationIncludesUndefined ? getTypeWithFacts(declaredType, TypeFacts.NEUndefined) : declaredType;
|
||||
}
|
||||
else {
|
||||
reportCircularityError(declaration.symbol);
|
||||
return declaredType;
|
||||
}
|
||||
return removeUndefined ? getTypeWithFacts(declaredType, TypeFacts.NEUndefined) : declaredType;
|
||||
}
|
||||
|
||||
function isConstraintPosition(type: Type, node: Node) {
|
||||
|
||||
@@ -5997,6 +5997,7 @@ export interface NodeLinks {
|
||||
declarationRequiresScopeChange?: boolean; // Set by `useOuterVariableScopeInParameter` in checker when downlevel emit would change the name resolution scope inside of a parameter.
|
||||
serializedTypes?: Map<string, SerializedTypeEntry>; // Collection of types serialized at this location
|
||||
decoratorSignature?: Signature; // Signature for decorator as if invoked by the runtime.
|
||||
parameterInitializerContainsUndefined?: boolean; // True if this is a parameter declaration whose type annotation contains "undefined".
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
@@ -38,4 +38,36 @@ describe("unittests:: tsserver:: inconsistentErrorInEditor", () => {
|
||||
verifyGetErrRequest({ session, host, files: ["^/untitled/ts-nul-authority/Untitled-1"] });
|
||||
baselineTsserverLogs("inconsistentErrorInEditor", "should not error", session);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: inconsistentErrorInEditor2", () => {
|
||||
it("should not error", () => {
|
||||
const host = createServerHost([]);
|
||||
const session = createSession(host, { canUseEvents: true, noGetErrOnBackgroundUpdate: true, logger: createLoggerWithInMemoryLogs(host) });
|
||||
session.executeCommandSeq<ts.server.protocol.UpdateOpenRequest>({
|
||||
command: ts.server.protocol.CommandTypes.UpdateOpen,
|
||||
arguments: {
|
||||
changedFiles: [],
|
||||
closedFiles: [],
|
||||
openFiles: [
|
||||
{
|
||||
file: "^/untitled/ts-nul-authority/Untitled-1",
|
||||
fileContent: "function fn(Foo: number) {\r\n type Foo = typeof Foo;\r\n return 0 as any as {x: Foo};\r\n}",
|
||||
scriptKindName: "TS"
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
session.executeCommandSeq<ts.server.protocol.EncodedSemanticClassificationsRequest>({
|
||||
command: ts.server.protocol.CommandTypes.EncodedSemanticClassificationsFull,
|
||||
arguments: {
|
||||
file: "^/untitled/ts-nul-authority/Untitled-1",
|
||||
start: 0,
|
||||
length: 128,
|
||||
format: "2020"
|
||||
}
|
||||
});
|
||||
verifyGetErrRequest({ session, host, files: ["^/untitled/ts-nul-authority/Untitled-1"] });
|
||||
baselineTsserverLogs("inconsistentErrorInEditor2", "should not error", session);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user