Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ID-Prep] PR1 - Simplify declaration emit for literal types. #57444

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48324,8 +48324,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// Get type of the symbol if this is the valid symbol otherwise get type at location
const symbol = getSymbolOfDeclaration(declaration);
let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
? getWidenedLiteralType(getTypeOfSymbol(symbol))
? getTypeOfSymbol(symbol)
: errorType;
if (!isReadonlySymbol(symbol)) {
type = getWidenedLiteralType(type);
}
if (
type.flags & TypeFlags.UniqueESSymbol &&
type.symbol === symbol
Expand Down
17 changes: 12 additions & 5 deletions src/compiler/transformers/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
EnumDeclaration,
ExportAssignment,
ExportDeclaration,
Expression,
ExpressionWithTypeArguments,
factory,
FileReference,
Expand Down Expand Up @@ -126,6 +127,7 @@ import {
isModifier,
isModuleDeclaration,
isOmittedExpression,
isPrimitiveLiteralValue,
isPrivateIdentifier,
isSemicolonClassElement,
isSetAccessorDeclaration,
Expand Down Expand Up @@ -207,6 +209,7 @@ import {
TypeParameterDeclaration,
TypeReferenceNode,
unescapeLeadingUnderscores,
unwrapParenthesizedExpression,
VariableDeclaration,
VariableDeclarationList,
VariableStatement,
Expand Down Expand Up @@ -666,7 +669,7 @@ export function transformDeclarations(context: TransformationContext) {
elem.dotDotDotToken,
elem.propertyName,
filterBindingPatternInitializers(elem.name),
shouldPrintWithInitializer(elem) ? elem.initializer : undefined,
/*initializer*/ undefined,
);
}
}
Expand All @@ -692,13 +695,17 @@ export function transformDeclarations(context: TransformationContext) {
return newParam;
}

function shouldPrintWithInitializer(node: Node) {
return canHaveLiteralInitializer(node) && resolver.isLiteralConstDeclaration(getParseTreeNode(node) as CanHaveLiteralInitializer); // TODO: Make safe
function shouldPrintWithInitializer(node: Node): node is CanHaveLiteralInitializer & { initializer: Expression; } {
return canHaveLiteralInitializer(node)
&& !node.type
&& !!node.initializer
&& resolver.isLiteralConstDeclaration(getParseTreeNode(node) as CanHaveLiteralInitializer); // TODO: Make safe
}

function ensureNoInitializer(node: CanHaveLiteralInitializer) {
if (shouldPrintWithInitializer(node)) {
return resolver.createLiteralConstValue(getParseTreeNode(node) as CanHaveLiteralInitializer, symbolTracker); // TODO: Make safe
const unwrappedInitializer = unwrapParenthesizedExpression(node.initializer);
return isPrimitiveLiteralValue(unwrappedInitializer) ? unwrappedInitializer : resolver.createLiteralConstValue(getParseTreeNode(node, canHaveLiteralInitializer)!, symbolTracker);
}
return undefined;
}
Expand Down Expand Up @@ -1937,7 +1944,7 @@ function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode
}

type CanHaveLiteralInitializer = VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration;
function canHaveLiteralInitializer(node: Node): boolean {
function canHaveLiteralInitializer(node: Node): node is CanHaveLiteralInitializer {
switch (node.kind) {
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
Expand Down
9 changes: 9 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,15 @@ export type HasIllegalModifiers =
| MissingDeclaration
| NamespaceExportDeclaration;

/** @internal */
export type PrimitiveLiteral =
| BooleanLiteral
| NumericLiteral
| StringLiteral
| NoSubstitutionTemplateLiteral
| BigIntLiteral
| PrefixUnaryExpression;

/**
* Declarations that can contain other declarations. Corresponds with `ContainerFlags.IsContainer` in binder.ts.
*
Expand Down
43 changes: 43 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ import {
Pattern,
PostfixUnaryExpression,
PrefixUnaryExpression,
PrimitiveLiteral,
PrinterOptions,
PrintHandlers,
PrivateIdentifier,
Expand Down Expand Up @@ -2343,6 +2344,14 @@ export function isLet(node: Node): boolean {
return (getCombinedNodeFlags(node) & NodeFlags.BlockScoped) === NodeFlags.Let;
}

/** @internal */
export function isVarConstLike(node: VariableDeclaration | VariableDeclarationList) {
const blockScopeKind = getCombinedNodeFlags(node) & NodeFlags.BlockScoped;
return blockScopeKind === NodeFlags.Const ||
blockScopeKind === NodeFlags.Using ||
blockScopeKind === NodeFlags.AwaitUsing;
}

/** @internal */
export function isSuperCall(n: Node): n is SuperCall {
return n.kind === SyntaxKind.CallExpression && (n as CallExpression).expression.kind === SyntaxKind.SuperKeyword;
Expand Down Expand Up @@ -10639,3 +10648,37 @@ export function replaceFirstStar(s: string, replacement: string): string {
export function getNameFromImportAttribute(node: ImportAttribute) {
return isIdentifier(node.name) ? node.name.escapedText : escapeLeadingUnderscores(node.name.text);
}

/** @internal */
export function isPrimitiveLiteralValue(node: Expression): node is PrimitiveLiteral {
Debug.type<PrimitiveLiteral>(node);
switch (node.kind) {
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.BigIntLiteral:
return true;
case SyntaxKind.PrefixUnaryExpression:
if (node.operator === SyntaxKind.MinusToken) {
return node.operand.kind === SyntaxKind.NumericLiteral ||
node.operand.kind === SyntaxKind.BigIntLiteral;
}
if (node.operator === SyntaxKind.PlusToken) {
return node.operand.kind === SyntaxKind.NumericLiteral;
}
return false;
default:
assertType<never>(node);
return false;
}
}

/** @internal */
export function unwrapParenthesizedExpression(o: Expression) {
while (o.kind === SyntaxKind.ParenthesizedExpression) {
o = (o as ParenthesizedExpression).expression;
}
return o;
}
4 changes: 2 additions & 2 deletions tests/baselines/reference/ambientConstLiterals.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,5 @@ declare const c9: {
declare const c10: number[];
declare const c11: string;
declare const c12: number;
declare const c13: string;
declare const c14: number;
declare const c13: "abc" | "def";
declare const c14: 123 | 456;

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -214,42 +214,48 @@ sourceFile:classStaticBlock25.ts
2 >^^^^^^^^
3 > ^^^^^^
4 > ^
5 > ^^^^
6 > ^
7 > ^->
5 > ^^^
6 > ^
7 > ^
8 > ^->
1 >
2 >
3 > const
4 > a
5 > = 1
6 > ;
5 > =
6 > 1
7 > ;
1 >Emitted(1, 1) Source(1, 1) + SourceIndex(0)
2 >Emitted(1, 9) Source(1, 1) + SourceIndex(0)
3 >Emitted(1, 15) Source(1, 7) + SourceIndex(0)
4 >Emitted(1, 16) Source(1, 8) + SourceIndex(0)
5 >Emitted(1, 20) Source(1, 12) + SourceIndex(0)
6 >Emitted(1, 21) Source(1, 13) + SourceIndex(0)
5 >Emitted(1, 19) Source(1, 11) + SourceIndex(0)
6 >Emitted(1, 20) Source(1, 12) + SourceIndex(0)
7 >Emitted(1, 21) Source(1, 13) + SourceIndex(0)
---
>>>declare const b = 2;
1->
2 >^^^^^^^^
3 > ^^^^^^
4 > ^
5 > ^^^^
6 > ^
5 > ^^^
6 > ^
7 > ^
1->
>
2 >
3 > const
4 > b
5 > = 2
6 > ;
5 > =
6 > 2
7 > ;
1->Emitted(2, 1) Source(2, 1) + SourceIndex(0)
2 >Emitted(2, 9) Source(2, 1) + SourceIndex(0)
3 >Emitted(2, 15) Source(2, 7) + SourceIndex(0)
4 >Emitted(2, 16) Source(2, 8) + SourceIndex(0)
5 >Emitted(2, 20) Source(2, 12) + SourceIndex(0)
6 >Emitted(2, 21) Source(2, 13) + SourceIndex(0)
5 >Emitted(2, 19) Source(2, 11) + SourceIndex(0)
6 >Emitted(2, 20) Source(2, 12) + SourceIndex(0)
7 >Emitted(2, 21) Source(2, 13) + SourceIndex(0)
---
>>>declare class C {
1 >
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -214,42 +214,48 @@ sourceFile:classStaticBlock25.ts
2 >^^^^^^^^
3 > ^^^^^^
4 > ^
5 > ^^^^
6 > ^
7 > ^->
5 > ^^^
6 > ^
7 > ^
8 > ^->
1 >
2 >
3 > const
4 > a
5 > = 1
6 > ;
5 > =
6 > 1
7 > ;
1 >Emitted(1, 1) Source(1, 1) + SourceIndex(0)
2 >Emitted(1, 9) Source(1, 1) + SourceIndex(0)
3 >Emitted(1, 15) Source(1, 7) + SourceIndex(0)
4 >Emitted(1, 16) Source(1, 8) + SourceIndex(0)
5 >Emitted(1, 20) Source(1, 12) + SourceIndex(0)
6 >Emitted(1, 21) Source(1, 13) + SourceIndex(0)
5 >Emitted(1, 19) Source(1, 11) + SourceIndex(0)
6 >Emitted(1, 20) Source(1, 12) + SourceIndex(0)
7 >Emitted(1, 21) Source(1, 13) + SourceIndex(0)
---
>>>declare const b = 2;
1->
2 >^^^^^^^^
3 > ^^^^^^
4 > ^
5 > ^^^^
6 > ^
5 > ^^^
6 > ^
7 > ^
1->
>
2 >
3 > const
4 > b
5 > = 2
6 > ;
5 > =
6 > 2
7 > ;
1->Emitted(2, 1) Source(2, 1) + SourceIndex(0)
2 >Emitted(2, 9) Source(2, 1) + SourceIndex(0)
3 >Emitted(2, 15) Source(2, 7) + SourceIndex(0)
4 >Emitted(2, 16) Source(2, 8) + SourceIndex(0)
5 >Emitted(2, 20) Source(2, 12) + SourceIndex(0)
6 >Emitted(2, 21) Source(2, 13) + SourceIndex(0)
5 >Emitted(2, 19) Source(2, 11) + SourceIndex(0)
6 >Emitted(2, 20) Source(2, 12) + SourceIndex(0)
7 >Emitted(2, 21) Source(2, 13) + SourceIndex(0)
---
>>>declare class C {
1 >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var Foo = /** @class */ (function () {


//// [declarationEmitClassMemberNameConflict2.d.ts]
declare const Bar = "bar";
declare const Bar = 'bar';
declare enum Hello {
World = 0
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ exports.Bar = Bar;


//// [declarationEmitConstantNoWidening.d.ts]
export declare const FOO = "FOO";
export declare const FOO = 'FOO';
export declare class Bar {
readonly type = "FOO";
}
2 changes: 1 addition & 1 deletion tests/baselines/reference/fakeInfinity1.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ export type NegativeInfinity = -1e999;
export type TypeOfInfinity = typeof Infinity;
export type TypeOfNaN = typeof NaN;
export type Oops = 123456789123456789123456789123456789123456789123456789;
export declare const oops = 1.2345678912345678e+53;
export declare const oops = 123456789123456789123456789123456789123456789123456789;
2 changes: 1 addition & 1 deletion tests/baselines/reference/strictFunctionTypes1.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ declare function fs(x: string): void;
declare function fx(f: (x: "def") => void): void;
declare const x1: (x: string) => void;
declare const x2 = "abc";
declare const x3: string;
declare const x3: "def" | "abc";
declare const x4: Func<string>;
declare const never: never;
declare const x10: string;
Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/strictPropertyInitialization.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ declare class C11 {
a: number;
constructor();
}
declare const a = "a";
declare const a = 'a';
declare const b: unique symbol;
declare class C12 {
[a]: number;
Expand Down
8 changes: 4 additions & 4 deletions tests/baselines/reference/stringLiteralTypesOverloads02.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ declare namespace Consts1 {
declare const string = "string";
declare const number = "number";
declare const boolean = "boolean";
declare const stringOrNumber: string;
declare const stringOrBoolean: string;
declare const booleanOrNumber: string;
declare const stringOrBooleanOrNumber: string;
declare const stringOrNumber: "string" | "number";
declare const stringOrBoolean: "string" | "boolean";
declare const booleanOrNumber: "number" | "boolean";
declare const stringOrBooleanOrNumber: "string" | "number" | "boolean";
declare namespace Consts2 {
}
Loading
Loading