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

Major Improvements 2 #12

Merged
merged 3 commits into from
Jul 1, 2022
Merged
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
13 changes: 13 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Build",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/build/build.ts",
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
}
]
}
46 changes: 46 additions & 0 deletions build/alias.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const aliasArray: [string, string[]][] = [
[
"TypedNumberArray",
[
"Int8Array",
"Uint8Array",
"Uint8ClampedArray",
"Int16Array",
"Uint16Array",
"Int32Array",
"Uint32Array",
"Float32Array",
"Float64Array",
],
],
["TypedBigIntArray", ["BigInt64Array", "BigUint64Array"]],
];

export const alias = new Map(
aliasArray.flatMap(([originalType, replacementTypes]) => [
[
originalType,
new Map(
replacementTypes.map((replacement) => [
replacement,
new Map([
[originalType, replacement],
[`${originalType}Constructor`, `${replacement}Constructor`],
]),
])
),
],
[
`${originalType}Constructor`,
new Map(
replacementTypes.map((replacement) => [
`${replacement}Constructor`,
new Map([
[originalType, replacement],
[`${originalType}Constructor`, `${replacement}Constructor`],
]),
])
),
],
])
);
133 changes: 88 additions & 45 deletions build/logic/generate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import path from "path";
import ts from "typescript";
import { alias } from "../alias";
import { upsert } from "../util/upsert";
import { projectDir } from "./projectDir";

Expand All @@ -24,14 +25,10 @@ export function generate(

let result = "";

const replacementTargets = scanBetterFile(libFile);
const replacementTargets = scanBetterFile(printer, libFile);

if (replacementTargets.size === 0) {
for (const statement of originalFile.statements) {
result += statement.getFullText(originalFile);
}
result += originalFile.text.slice(originalFile.endOfFileToken.pos);
return result;
return originalFile.text;
}

const consumedReplacements = new Set<string>();
Expand Down Expand Up @@ -132,7 +129,7 @@ export function generate(
},
];
});
result += printInterface(printer, statement, memberList);
result += printInterface(printer, statement, memberList, originalFile);

if (emitOriginalAsComment) {
result += "\n";
Expand Down Expand Up @@ -188,7 +185,10 @@ type ReplacementTarget = (
/**
* Scan better lib file to determine which statements need to be replaced.
*/
function scanBetterFile(libFile: string): Map<string, ReplacementTarget[]> {
function scanBetterFile(
printer: ts.Printer,
libFile: string
): Map<string, ReplacementTarget[]> {
const replacementTargets = new Map<string, ReplacementTarget[]>();
{
const betterLibFile = path.join(betterLibDir, `lib.${libFile}`);
Expand All @@ -198,43 +198,58 @@ function scanBetterFile(libFile: string): Map<string, ReplacementTarget[]> {
// Scan better file to determine which statements need to be replaced.
for (const statement of betterFile.statements) {
const name = getStatementDeclName(statement) ?? "";
if (ts.isInterfaceDeclaration(statement)) {
const members = new Map<
string,
{
member: ts.TypeElement;
text: string;
}[]
>();
for (const member of statement.members) {
const memberName = member.name?.getText(betterFile) ?? "";
upsert(members, memberName, (members = []) => {
members.push({
member,
text: member.getFullText(betterFile),
const aliasesMap =
alias.get(name) ?? new Map([[name, new Map<string, string>()]]);
for (const [targetName, typeMap] of aliasesMap) {
const transformedStatement = replaceAliases(statement, typeMap);
if (ts.isInterfaceDeclaration(transformedStatement)) {
const members = new Map<
string,
{
member: ts.TypeElement;
text: string;
}[]
>();
for (const member of transformedStatement.members) {
const memberName = member.name?.getText(betterFile) ?? "";
upsert(members, memberName, (members = []) => {
const leadingSpacesMatch = /^\s*/.exec(
member.getFullText(betterFile)
);
const leadingSpaces =
leadingSpacesMatch !== null ? leadingSpacesMatch[0] : "";
members.push({
member,
text:
leadingSpaces +
printer.printNode(
ts.EmitHint.Unspecified,
member,
betterFile
),
});
return members;
});
return members;
});
}

upsert(replacementTargets, name, (targets = []) => {
targets.push({
type: "interface",
members,
originalStatement: statement,
sourceFile: betterFile,
}
upsert(replacementTargets, targetName, (targets = []) => {
targets.push({
type: "interface",
members,
originalStatement: transformedStatement,
sourceFile: betterFile,
});
return targets;
});
return targets;
});
} else {
upsert(replacementTargets, name, (statements = []) => {
statements.push({
type: "non-interface",
statement,
sourceFile: betterFile,
} else {
upsert(replacementTargets, targetName, (statements = []) => {
statements.push({
type: "non-interface",
statement: transformedStatement,
sourceFile: betterFile,
});
return statements;
});
return statements;
});
}
}
}
}
Expand Down Expand Up @@ -308,10 +323,12 @@ function isPartialReplacement(
function printInterface(
printer: ts.Printer,
originalNode: ts.InterfaceDeclaration,
members: readonly { text: string }[]
members: readonly { text: string }[],
originalSourceFile: ts.SourceFile
): string {
const originalSourceFile = originalNode.getSourceFile();
graphemecluster marked this conversation as resolved.
Show resolved Hide resolved
let result = "";
let result = originalNode
.getFullText(originalSourceFile)
.slice(0, originalNode.getLeadingTriviaWidth(originalSourceFile));
for (const dec of originalNode.decorators ?? []) {
result += printer.printNode(
ts.EmitHint.Unspecified,
Expand Down Expand Up @@ -372,3 +389,29 @@ function commentOut(code: string): string {
const result = lines.map((line) => `// ${line}`);
return result.join("\n") + "\n";
}

function replaceAliases(
statement: ts.Statement,
typeMap: Map<string, string>
): ts.Statement {
if (typeMap.size === 0) return statement;
return ts.transform(statement, [
(context) => (sourceStatement) => {
const visitor = (node: ts.Node): ts.Node => {
if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName)) {
const replacementType = typeMap.get(node.typeName.text);
if (replacementType === undefined) {
return node;
}
return ts.factory.updateTypeReferenceNode(
node,
ts.factory.createIdentifier(replacementType),
node.typeArguments
);
}
return ts.visitEachChild(node, visitor, context);
};
return ts.visitNode(sourceStatement, visitor);
},
]).transformed[0];
}
1 change: 1 addition & 0 deletions docs/diff.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The following files are improved in better-typescript-lib:
- [es2018.asyncgenerator.d.ts](./diff/es2018.asyncgenerator.d.ts.md)
- [es2018.asynciterable.d.ts](./diff/es2018.asynciterable.d.ts.md)
- [es2019.object.d.ts](./diff/es2019.object.d.ts.md)
- [es2020.bigint.d.ts](./diff/es2020.bigint.d.ts.md)
- [es2021.promise.d.ts](./diff/es2021.promise.d.ts.md)
- [es2021.string.d.ts](./diff/es2021.string.d.ts.md)
- [es2022.object.d.ts](./diff/es2022.object.d.ts.md)
Expand Down
26 changes: 12 additions & 14 deletions docs/diff/es2015.collection.d.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,46 @@ Index: es2015.collection.d.ts
===================================================================
--- es2015.collection.d.ts
+++ es2015.collection.d.ts
@@ -1,28 +1,25 @@
@@ -1,28 +1,27 @@
interface Map<K, V> {
clear(): void;
delete(key: K): boolean;
- forEach(
- callbackfn: (value: V, key: K, map: Map<K, V>) => void,
- thisArg?: any
+ forEach<This = undefined>(
+ callbackfn: (this: This, value: V, key: K, map: Map<K, V>) => void,
+ callbackfn: (this: This, value: V, key: K, map: this) => void,
+ thisArg?: This
): void;
get(key: K): V | undefined;
has(key: K): boolean;
set(key: K, value: V): this;
readonly size: number;
}
-
interface MapConstructor {
- new (): Map<any, any>;
new <K, V>(entries?: readonly (readonly [K, V])[] | null): Map<K, V>;
- readonly prototype: Map<any, any>;
+ readonly prototype: Map<unknown, unknown>;
}
declare var Map: MapConstructor;
-
interface ReadonlyMap<K, V> {
- forEach(
- callbackfn: (value: V, key: K, map: ReadonlyMap<K, V>) => void,
- thisArg?: any
+ forEach<This = undefined>(
+ callbackfn: (this: This, value: V, key: K, map: ReadonlyMap<K, V>) => void,
+ callbackfn: (this: This, value: V, key: K, map: this) => void,
+ thisArg?: This
): void;
get(key: K): V | undefined;
has(key: K): boolean;
readonly size: number;
@@ -33,39 +30,35 @@
get(key: K): V | undefined;
has(key: K): boolean;
@@ -35,37 +34,37 @@
set(key: K, value: V): this;
}
-
interface WeakMapConstructor {
- new <K extends object = object, V = any>(
- entries?: readonly [K, V][] | null
Expand All @@ -57,7 +55,7 @@ Index: es2015.collection.d.ts
+ readonly prototype: WeakMap<object, unknown>;
}
declare var WeakMap: WeakMapConstructor;
-
interface Set<T> {
add(value: T): this;
clear(): void;
Expand All @@ -66,27 +64,27 @@ Index: es2015.collection.d.ts
- callbackfn: (value: T, value2: T, set: Set<T>) => void,
- thisArg?: any
+ forEach<This = undefined>(
+ callbackfn: (this: This, value: T, value2: T, set: Set<T>) => void,
+ callbackfn: (this: This, value: T, value2: T, set: this) => void,
+ thisArg?: This
): void;
has(value: T): boolean;
readonly size: number;
}
-
interface SetConstructor {
- new <T = any>(values?: readonly T[] | null): Set<T>;
- readonly prototype: Set<any>;
+ new <T>(values?: readonly T[] | null): Set<T>;
+ readonly prototype: Set<unknown>;
}
declare var Set: SetConstructor;
-
interface ReadonlySet<T> {
- forEach(
- callbackfn: (value: T, value2: T, set: ReadonlySet<T>) => void,
- thisArg?: any
+ forEach<This = undefined>(
+ callbackfn: (this: This, value: T, value2: T, set: ReadonlySet<T>) => void,
+ callbackfn: (this: This, value: T, value2: T, set: this) => void,
+ thisArg?: This
): void;
has(value: T): boolean;
Expand Down
Loading