Skip to content

Commit

Permalink
Switched over to entityNameToString
Browse files Browse the repository at this point in the history
Signed-off-by: Titian Cernicova-Dragomir <[email protected]>
  • Loading branch information
dragomirtitian committed Jan 21, 2024
1 parent e1bb300 commit dc1ffe9
Show file tree
Hide file tree
Showing 12 changed files with 548 additions and 81 deletions.
14 changes: 9 additions & 5 deletions src/compiler/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
AssertionLevel,
BigIntLiteralType,
CheckMode,
Comparer,
compareValues,
EmitFlags,
every,
Expand Down Expand Up @@ -386,18 +387,18 @@ export namespace Debug {
* Formats an enum value as a string for debugging and debug assertions.
*/
export function formatEnum(value = 0, enumObject: any, isFlags?: boolean) {
const members = getEnumMembers(enumObject);
const members = getEnumMembers(enumObject, isFlags);
if (value === 0) {
return members.length > 0 && members[0][0] === 0 ? members[0][1] : "0";
}
if (isFlags) {
const result: string[] = [];
let remainingFlags = value;
for (const [enumValue, enumName] of members) {
if (enumValue > value) {
if (enumValue > remainingFlags) {
break;
}
if (enumValue !== 0 && enumValue & value) {
if (enumValue !== 0 && enumValue & remainingFlags) {
result.push(enumName);
remainingFlags &= ~enumValue;
}
Expand All @@ -418,7 +419,7 @@ export namespace Debug {

const enumMemberCache = new Map<any, SortedReadonlyArray<[number, string]>>();

function getEnumMembers(enumObject: any) {
function getEnumMembers(enumObject: any, isFlags?: boolean) {
// Assuming enum objects do not change at runtime, we can cache the enum members list
// to reuse later. This saves us from reconstructing this each and every time we call
// a formatting function (which can be expensive for large enums like SyntaxKind).
Expand All @@ -435,7 +436,10 @@ export namespace Debug {
}
}

const sorted = stableSort<[number, string]>(result, (x, y) => compareValues(x[0], y[0]));
const comparer: Comparer<[number, string]> = isFlags ?
(x, y) => compareValues(x[0] >>> 0, y[0] >>> 0) :
(x, y) => compareValues(x[0], y[0]);
const sorted = stableSort(result, comparer);
enumMemberCache.set(enumObject, sorted);
return sorted;
}
Expand Down
120 changes: 46 additions & 74 deletions src/compiler/transformers/declarations/emitResolver.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
__String,
BigIntLiteral,
bindSourceFile,
CompilerOptions,
ComputedPropertyName,
Expand All @@ -14,6 +15,7 @@ import {
determineIfDeclarationIsVisible,
ElementAccessExpression,
emptyArray,
entityNameToString,
EnumDeclaration,
EnumMember,
ExportSpecifier,
Expand All @@ -35,7 +37,6 @@ import {
Identifier,
InternalSymbolName,
isAccessor,
isBigIntLiteral,
isBinaryExpression,
isComputedPropertyName,
isDeclarationReadonly,
Expand All @@ -54,39 +55,39 @@ import {
isIdentifier,
isInfinityOrNaNString,
isModuleDeclaration,
isNumericLiteral,
isPrefixUnaryExpression,
isPrimitiveLiteralValue,
isPropertyAccessExpression,
isPropertyName,
isSetAccessor,
isSetAccessorDeclaration,
isStringLiteralLike,
isTemplateExpression,
isVarConst,
isVariableDeclaration,
LateBoundDeclaration,
MemberName,
ModifierFlags,
Node,
NodeFlags,
nodeIsPresent,
NoSubstitutionTemplateLiteral,
NumericLiteral,
objectAllocator,
ParameterDeclaration,
parsePseudoBigInt,
PrefixUnaryExpression,
PropertyAccessExpression,
PropertyDeclaration,
PropertyName,
PropertySignature,
skipParentheses,
some,
SourceFile,
StringLiteralLike,
Symbol,
SymbolAccessibility,
SymbolFlags,
SymbolTable,
SyntaxKind,
TemplateExpression,
VariableDeclaration,
} from "../../_namespaces/ts";

Expand Down Expand Up @@ -357,48 +358,44 @@ export function createEmitDeclarationResolver(file: SourceFile, options: Compile
onNumericLiteral() {},
});
function clonePrimitiveLiteralValue(node: Expression): Expression {
if (isNumericLiteral(node)) {
return factory.createNumericLiteral(node.text);
}
if (isBigIntLiteral(node)) {
return factory.createBigIntLiteral({ negative: false, base10Value: parsePseudoBigInt(node.text) });
}
if (isStringLiteralLike(node)) {
return factory.createStringLiteral(node.text);
}

if (node.kind === SyntaxKind.FalseKeyword) {
return factory.createFalse();
}

if (node.kind === SyntaxKind.TrueKeyword) {
return factory.createTrue();
}

if (isPrefixUnaryExpression(node)) {
return factory.createPrefixUnaryExpression(
node.operator,
clonePrimitiveLiteralValue(node.operand),
);
}
if (isTemplateExpression(node)) {
const evaluatedValue = evaluate(node);
if (evaluatedValue !== undefined) {
return factory.createStringLiteral(evaluatedValue);
}
return factory.createTemplateExpression(
factory.createTemplateHead(node.head.text, node.head.rawText, node.head.templateFlags),
node.templateSpans.map(t =>
factory.createTemplateSpan(
clonePrimitiveLiteralValue(t.expression),
t.literal.kind === SyntaxKind.TemplateMiddle ?
factory.createTemplateMiddle(t.literal.text, t.literal.rawText, t.literal.templateFlags) :
factory.createTemplateTail(t.literal.text, t.literal.rawText, t.literal.templateFlags),
)
),
);
switch(node.kind) {
case SyntaxKind.NumericLiteral:
return factory.createNumericLiteral((node as NumericLiteral).text);
case SyntaxKind.BigIntLiteral:
return factory.createBigIntLiteral({ negative: false, base10Value: parsePseudoBigInt((node as BigIntLiteral).text) });
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return factory.createStringLiteral((node as StringLiteralLike).text);
case SyntaxKind.FalseKeyword:
return factory.createFalse();
case SyntaxKind.TrueKeyword:
return factory.createTrue();
case SyntaxKind.PrefixUnaryExpression:
return factory.createPrefixUnaryExpression(
(node as PrefixUnaryExpression).operator,
clonePrimitiveLiteralValue((node as PrefixUnaryExpression).operand),
);
case SyntaxKind.TemplateExpression:
const templateExpression = node as TemplateExpression
const evaluatedValue = evaluate(templateExpression);
if (evaluatedValue !== undefined) {
return factory.createStringLiteral(evaluatedValue);
}
const templateHead = templateExpression.head
return factory.createTemplateExpression(
factory.createTemplateHead(templateHead.text, templateHead.rawText, templateHead.templateFlags),
templateExpression.templateSpans.map(t =>
factory.createTemplateSpan(
clonePrimitiveLiteralValue(t.expression),
t.literal.kind === SyntaxKind.TemplateMiddle ?
factory.createTemplateMiddle(t.literal.text, t.literal.rawText, t.literal.templateFlags) :
factory.createTemplateTail(t.literal.text, t.literal.rawText, t.literal.templateFlags),
)
),
);
default:
Debug.assert(false, `Unable to clone unknown literal type. Kind: ${node.kind}`);
}
Debug.assert(false, `Unable to clone unknown literal type. Kind: ${node.kind}`);
}

function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean {
Expand Down Expand Up @@ -627,37 +624,12 @@ function getSymbolName(name: ElementAccessExpression | PropertyName): __String |
return getDynamicSymbolName(name);
}

function getEntityNameComponent(identifier: MemberName): __String {
const name = getPropertyNameForPropertyNameNode(identifier);
if (name && name.indexOf(".")) {
return name.replace(/\./g, "..") as __String;
}
return name;
}

function getDynamicSymbolName(name: ElementAccessExpression | PropertyName) {
let computedName = isComputedPropertyName(name) ? name.expression :
const computedName = isComputedPropertyName(name) ? name.expression :
isElementAccessExpression(name) ? name.argumentExpression :
undefined;

if (computedName) {
let fullId = "__!";
// We only support dotted identifiers as property keys
while (true) {
if (isIdentifier(computedName)) {
const componentName = getEntityNameComponent(computedName);
fullId += componentName;
return fullId as __String;
}
else if (isPropertyAccessExpression(computedName)) {
const componentName = getEntityNameComponent(computedName.name);
computedName = computedName.expression;
fullId += componentName + ".";
}
else {
return undefined;
}
}
if (computedName && isEntityNameExpression(computedName)) {
return ("__!" + entityNameToString(computedName)) as __String;
}
return undefined;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// [[Reason: Function declarations are not fixed.]] ////
// [[Reason: Expando function declarations are not fixed.]] ////

//// [tests/cases/compiler/isolatedDeclarationErrorsExpandoFunctions.ts] ////

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// [[Reason: Expando function declarations are not fixed.]] ////

//// [tests/cases/compiler/isolatedDeclarationLazySymbols.ts] ////

===================================================================
--- TSC declarations
+++ DTE declarations
@@ -1,11 +1,8 @@


//// [isolatedDeclarationLazySymbols.d.ts]
export declare function foo(): void;
-export declare namespace foo {
- var b: string;
-}
declare const o: {
readonly "prop.inner": "a";
readonly prop: {
readonly inner: "b";
@@ -20,12 +17,13 @@
export {};
//# sourceMappingURL=isolatedDeclarationLazySymbols.d.ts.map
/// [Errors] ////

+isolatedDeclarationLazySymbols.ts(13,1): error TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.
isolatedDeclarationLazySymbols.ts(16,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type.


-==== isolatedDeclarationLazySymbols.ts (1 errors) ====
+==== isolatedDeclarationLazySymbols.ts (2 errors) ====
export function foo(): void {

}

@@ -37,8 +35,10 @@
} as const

foo[o["prop.inner"]] ="A";
foo[o.prop.inner] = "B";
+ ~~~~~~~~~~~~~~~~~
+!!! error TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.

export class Foo {
[o["prop.inner"]] ="A"
~~~~~~~~~~~~~~~~~
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//// [tests/cases/compiler/isolatedDeclarationLazySymbols.ts] ////

//// [isolatedDeclarationLazySymbols.ts]
export function foo(): void {

}

const o = {
["prop.inner"]: "a",
prop: {
inner: "b",
}
} as const

foo[o["prop.inner"]] ="A";
foo[o.prop.inner] = "B";

export class Foo {
[o["prop.inner"]] ="A"
[o.prop.inner] = "B"
}

export let oo: {
a: string;
[o.prop.inner]: string;
} = {
[o['prop.inner']]:"A",
[o.prop.inner]: "B",
}

/// [Declarations] ////



//// [isolatedDeclarationLazySymbols.d.ts]
export declare function foo(): void;
declare const o: {
readonly "prop.inner": "a";
readonly prop: {
readonly inner: "b";
};
};
export declare class Foo {
}
export declare let oo: {
a: string;
[o.prop.inner]: string;
};
export {};
//# sourceMappingURL=isolatedDeclarationLazySymbols.d.ts.map
/// [Errors] ////

isolatedDeclarationLazySymbols.ts(13,1): error TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.
isolatedDeclarationLazySymbols.ts(16,5): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type.


==== isolatedDeclarationLazySymbols.ts (2 errors) ====
export function foo(): void {

}

const o = {
["prop.inner"]: "a",
prop: {
inner: "b",
}
} as const

foo[o["prop.inner"]] ="A";
foo[o.prop.inner] = "B";
~~~~~~~~~~~~~~~~~
!!! error TS9023: Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.

export class Foo {
[o["prop.inner"]] ="A"
~~~~~~~~~~~~~~~~~
!!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type.
[o.prop.inner] = "B"
}

export let oo: {
a: string;
[o.prop.inner]: string;
} = {
[o['prop.inner']]:"A",
[o.prop.inner]: "B",
}
Loading

0 comments on commit dc1ffe9

Please sign in to comment.