mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Lock down computed names in object literals and classes under --isolatedDeclarations (#58596)
This commit is contained in:
@@ -1504,7 +1504,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
var syntacticNodeBuilder = createSyntacticTypeNodeBuilder(compilerOptions, {
|
||||
isEntityNameVisible,
|
||||
isExpandoFunctionDeclaration,
|
||||
isNonNarrowedBindableName,
|
||||
getAllAccessorDeclarations: getAllAccessorDeclarationsForDeclaration,
|
||||
requiresAddingImplicitUndefined,
|
||||
isUndefinedIdentifierExpression(node: Identifier) {
|
||||
@@ -49118,25 +49117,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isNonNarrowedBindableName(node: ComputedPropertyName) {
|
||||
if (!hasBindableName(node.parent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const expression = node.expression;
|
||||
if (!isEntityNameExpression(expression)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const type = getTypeOfExpression(expression);
|
||||
const symbol = getSymbolAtLocation(expression);
|
||||
if (!symbol) {
|
||||
return false;
|
||||
}
|
||||
// Ensure not type narrowing
|
||||
const declaredType = getTypeOfSymbol(symbol);
|
||||
return declaredType === type;
|
||||
}
|
||||
|
||||
function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression {
|
||||
const enumResult = type.flags & TypeFlags.EnumLike ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker)
|
||||
@@ -49262,7 +49242,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return node && getExternalModuleFileFromDeclaration(node);
|
||||
},
|
||||
isLiteralConstDeclaration,
|
||||
isNonNarrowedBindableName,
|
||||
isLateBound: (nodeIn: Declaration): nodeIn is LateBoundDeclaration => {
|
||||
const node = getParseTreeNode(nodeIn, isDeclaration);
|
||||
const symbol = node && getSymbolOfDeclaration(node);
|
||||
|
||||
@@ -7014,6 +7014,10 @@
|
||||
"category": "Error",
|
||||
"code": 9037
|
||||
},
|
||||
"Computed property names on class or object literals cannot be inferred with --isolatedDeclarations.": {
|
||||
"category": "Error",
|
||||
"code": 9038
|
||||
},
|
||||
"JSX attributes must only be assigned a non-empty 'expression'.": {
|
||||
"category": "Error",
|
||||
"code": 17000
|
||||
|
||||
@@ -1123,7 +1123,6 @@ export const notImplementedResolver: EmitResolver = {
|
||||
isArgumentsLocalBinding: notImplemented,
|
||||
getExternalModuleFileFromDeclaration: notImplemented,
|
||||
isLiteralConstDeclaration: notImplemented,
|
||||
isNonNarrowedBindableName: notImplemented,
|
||||
getJsxFactoryEntity: notImplemented,
|
||||
getJsxFragmentFactoryEntity: notImplemented,
|
||||
isBindingCapturedByNode: notImplemented,
|
||||
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
isBlock,
|
||||
isConstTypeReference,
|
||||
isDeclarationReadonly,
|
||||
isEntityNameExpression,
|
||||
isGetAccessor,
|
||||
isIdentifier,
|
||||
isJSDocTypeAssertion,
|
||||
@@ -55,7 +54,6 @@ import {
|
||||
PropertySignature,
|
||||
SetAccessorDeclaration,
|
||||
SignatureDeclaration,
|
||||
SymbolAccessibility,
|
||||
SyntacticTypeNodeBuilderContext,
|
||||
SyntacticTypeNodeBuilderResolver,
|
||||
SyntaxKind,
|
||||
@@ -351,7 +349,7 @@ export function createSyntacticTypeNodeBuilder(options: CompilerOptions, resolve
|
||||
}
|
||||
else if (prop.name.kind === SyntaxKind.ComputedPropertyName) {
|
||||
const expression = prop.name.expression;
|
||||
if (!isPrimitiveLiteralValue(expression, /*includeBigInt*/ false) && !isEntityNameExpression(expression)) {
|
||||
if (!isPrimitiveLiteralValue(expression, /*includeBigInt*/ false)) {
|
||||
context.tracker.reportInferenceFallback(prop.name);
|
||||
result = false;
|
||||
}
|
||||
@@ -367,17 +365,6 @@ export function createSyntacticTypeNodeBuilder(options: CompilerOptions, resolve
|
||||
Debug.assert(!isShorthandPropertyAssignment(prop) && !isSpreadAssignment(prop));
|
||||
|
||||
const name = prop.name;
|
||||
if (prop.name.kind === SyntaxKind.ComputedPropertyName) {
|
||||
if (!resolver.isNonNarrowedBindableName(prop.name)) {
|
||||
context.tracker.reportInferenceFallback(prop.name);
|
||||
}
|
||||
else if (isEntityNameExpression(prop.name.expression)) {
|
||||
const visibilityResult = resolver.isEntityNameVisible(prop.name.expression, context.enclosingDeclaration!, /*shouldComputeAliasToMakeVisible*/ false);
|
||||
if (visibilityResult.accessibility !== SymbolAccessibility.Accessible) {
|
||||
context.tracker.reportInferenceFallback(prop.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (prop.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
canInferObjectLiteral = !!typeFromObjectLiteralMethod(prop, name, context) && canInferObjectLiteral;
|
||||
|
||||
@@ -139,6 +139,7 @@ import {
|
||||
isTupleTypeNode,
|
||||
isTypeAliasDeclaration,
|
||||
isTypeElement,
|
||||
isTypeLiteralNode,
|
||||
isTypeNode,
|
||||
isTypeParameterDeclaration,
|
||||
isTypeQueryNode,
|
||||
@@ -995,16 +996,20 @@ export function transformDeclarations(context: TransformationContext) {
|
||||
if (shouldStripInternal(input)) return;
|
||||
if (isDeclaration(input)) {
|
||||
if (isDeclarationAndNotVisible(input)) return;
|
||||
if (hasDynamicName(input) && !resolver.isLateBound(getParseTreeNode(input) as Declaration)) {
|
||||
if (hasDynamicName(input)) {
|
||||
if (
|
||||
isolatedDeclarations
|
||||
// Classes usually elide properties with computed names that are not of a literal type
|
||||
// Classes and object literals usually elide properties with computed names that are not of a literal type
|
||||
// In isolated declarations TSC needs to error on these as we don't know the type in a DTE.
|
||||
&& isClassDeclaration(input.parent)
|
||||
&& isEntityNameExpression(input.name.expression)
|
||||
// If the symbol is not accessible we get another TS error no need to add to that
|
||||
&& resolver.isEntityNameVisible(input.name.expression, input.parent).accessibility === SymbolAccessibility.Accessible
|
||||
&& !resolver.isNonNarrowedBindableName(input.name)
|
||||
&& (isClassDeclaration(input.parent) || isObjectLiteralExpression(input.parent))
|
||||
) {
|
||||
context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations));
|
||||
}
|
||||
if (
|
||||
isolatedDeclarations
|
||||
// Type declarations just need to double-check that the input computed name is an entity name expression
|
||||
&& (isInterfaceDeclaration(input.parent) || isTypeLiteralNode(input.parent))
|
||||
&& !isEntityNameExpression(input.name.expression)
|
||||
) {
|
||||
context.addDiagnostic(createDiagnosticForNode(input, Diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations));
|
||||
}
|
||||
|
||||
@@ -623,7 +623,7 @@ export function createGetIsolatedDeclarationErrors(resolver: EmitResolver) {
|
||||
[SyntaxKind.VariableDeclaration]: Diagnostics.Variable_must_have_an_explicit_type_annotation_with_isolatedDeclarations,
|
||||
[SyntaxKind.PropertyDeclaration]: Diagnostics.Property_must_have_an_explicit_type_annotation_with_isolatedDeclarations,
|
||||
[SyntaxKind.PropertySignature]: Diagnostics.Property_must_have_an_explicit_type_annotation_with_isolatedDeclarations,
|
||||
[SyntaxKind.ComputedPropertyName]: Diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations,
|
||||
[SyntaxKind.ComputedPropertyName]: Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations,
|
||||
[SyntaxKind.SpreadAssignment]: Diagnostics.Objects_that_contain_spread_assignments_can_t_be_inferred_with_isolatedDeclarations,
|
||||
[SyntaxKind.ShorthandPropertyAssignment]: Diagnostics.Objects_that_contain_shorthand_properties_can_t_be_inferred_with_isolatedDeclarations,
|
||||
[SyntaxKind.ArrayLiteralExpression]: Diagnostics.Only_const_arrays_can_be_inferred_with_isolatedDeclarations,
|
||||
|
||||
@@ -5754,7 +5754,6 @@ export enum TypeReferenceSerializationKind {
|
||||
|
||||
/** @internal */
|
||||
export interface EmitResolver {
|
||||
isNonNarrowedBindableName(node: ComputedPropertyName): boolean;
|
||||
hasGlobalName(name: string): boolean;
|
||||
getReferencedExportContainer(node: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined;
|
||||
getReferencedImportDeclaration(node: Identifier): Declaration | undefined;
|
||||
@@ -10291,7 +10290,6 @@ export interface SyntacticTypeNodeBuilderContext {
|
||||
/** @internal */
|
||||
export interface SyntacticTypeNodeBuilderResolver {
|
||||
isUndefinedIdentifierExpression(name: Identifier): boolean;
|
||||
isNonNarrowedBindableName(name: ComputedPropertyName): boolean;
|
||||
isExpandoFunctionDeclaration(name: FunctionDeclaration | VariableDeclaration): boolean;
|
||||
getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations;
|
||||
isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node, shouldComputeAliasToMakeVisible?: boolean): SymbolVisibilityResult;
|
||||
|
||||
@@ -121,6 +121,7 @@ const errorCodes = [
|
||||
Diagnostics.Property_must_have_an_explicit_type_annotation_with_isolatedDeclarations.code,
|
||||
Diagnostics.Expression_type_can_t_be_inferred_with_isolatedDeclarations.code,
|
||||
Diagnostics.Binding_elements_can_t_be_exported_directly_with_isolatedDeclarations.code,
|
||||
Diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations.code,
|
||||
Diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations.code,
|
||||
Diagnostics.Enum_member_initializers_must_be_computable_without_references_to_external_symbols_with_isolatedDeclarations.code,
|
||||
Diagnostics.Extends_clause_can_t_contain_an_expression_with_isolatedDeclarations.code,
|
||||
|
||||
Reference in New Issue
Block a user