Skip to content

Commit 5fbc6cc

Browse files
committed
Merge branch 'gen-docs'
2 parents 1f9b5d6 + 27c912e commit 5fbc6cc

File tree

93 files changed

+38996
-25957
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+38996
-25957
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ This package provides an alternative set of type definitions which replaces, and
1414

1515
This package also includes other improved, stricter type definitions.
1616

17+
[You can see the diff from the original TypeScript lib here](./docs/diff.md).
18+
1719
## Installation
1820

1921
You only need to install `better-typescript-lib`. Additional configuration is not needed; your TypeScript project automatically use `better-typescript-lib` definitions.

build/build.ts

Lines changed: 11 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import { mkdir, readdir, readFile, rm, writeFile } from "fs/promises";
1+
import { mkdir, rm, writeFile } from "fs/promises";
22
import path from "path";
3-
import ts from "typescript";
4-
import { replacement } from "./replacement";
3+
import prettier from "prettier";
4+
import { generate } from "./logic/generate";
5+
import { getLibFiles } from "./logic/getLibFiles";
6+
import { projectDir } from "./logic/projectDir";
57

6-
const projectDir = process.env.PROJECT || process.cwd();
7-
const betterLibDir = path.join(projectDir, "lib");
88
const distDir = path.join(projectDir, "generated");
9-
const tsDir = path.join(projectDir, "TypeScript");
109

1110
async function main() {
1211
await rm(distDir, {
@@ -18,92 +17,23 @@ async function main() {
1817
});
1918

2019
// copy TypeScript lib files
21-
const tsLibDir = path.join(tsDir, "src", "lib");
22-
const libs = await readdir(tsLibDir);
23-
const libFiles: string[] = libs.filter((libFile) =>
24-
/(?:^|\/|\\).+\.d\.ts$/.test(libFile)
25-
);
20+
const { tsLibDir, libFiles } = await getLibFiles();
2621

2722
// modify each lib file
2823
for (const libFile of libFiles) {
29-
const tsLibFile = path.join(tsLibDir, libFile);
30-
const program = ts.createProgram([tsLibFile], {});
31-
const file = program.getSourceFile(tsLibFile);
32-
if (!file) {
24+
let result = generate(tsLibDir, libFile, true);
25+
if (result === undefined) {
3326
continue;
3427
}
35-
let result = "";
36-
const repl = replacement.get(libFile);
37-
if (repl) {
38-
// copy better lib into the top of the file
39-
result += await readFile(
40-
path.join(betterLibDir, `lib.${libFile}`),
41-
"utf8"
42-
);
43-
result += "// --------------------\n";
44-
}
45-
46-
if (!repl) {
47-
for (const statement of file.statements) {
48-
result += statement.getFullText(file);
49-
}
50-
} else {
51-
for (const statement of file.statements) {
52-
const res = checkStatement(statement, repl);
53-
if (res) {
54-
result += res.getFullText(file);
55-
} else {
56-
// Replaced statements are emitted as comments
57-
// to make it easier to detect original lib changes
58-
result += "\n" + commentOut(statement.getFullText(file)) + "\n";
59-
}
60-
}
61-
}
62-
result += file.text.slice(file.endOfFileToken.pos);
28+
result = prettier.format(result, {
29+
parser: "typescript",
30+
});
6331

6432
await writeFile(path.join(distDir, "lib." + libFile), result);
6533
console.log(libFile);
6634
}
6735
}
6836

69-
function checkStatement(
70-
statement: ts.Statement,
71-
replacement: Set<string>
72-
): ts.Statement | undefined {
73-
// check for declrations
74-
if (ts.isVariableStatement(statement)) {
75-
for (const dec of statement.declarationList.declarations) {
76-
if (ts.isIdentifier(dec.name)) {
77-
if (replacement.has(dec.name.text)) {
78-
return undefined;
79-
}
80-
}
81-
}
82-
} else if (
83-
ts.isFunctionDeclaration(statement) ||
84-
ts.isInterfaceDeclaration(statement) ||
85-
ts.isTypeAliasDeclaration(statement) ||
86-
ts.isModuleDeclaration(statement)
87-
) {
88-
const repl = statement.name && replacement.has(statement.name.text);
89-
if (repl) {
90-
return undefined;
91-
}
92-
} else if (ts.isInterfaceDeclaration(statement)) {
93-
const repl = statement.name && replacement.has(statement.name.text);
94-
if (repl) {
95-
return undefined;
96-
}
97-
}
98-
return statement;
99-
}
100-
101-
function commentOut(code: string): string {
102-
const lines = code.split("\n");
103-
const result = lines.map((line) => `// ${line}`);
104-
return result.join("\n");
105-
}
106-
10737
main().catch((err) => {
10838
console.error(err);
10939
process.exit(1);

build/diff.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Generates diff per lib file.
2+
3+
import { createPatch } from "diff";
4+
import { mkdir, readFile, rm, writeFile } from "fs/promises";
5+
import path from "path";
6+
import prettier from "prettier";
7+
import { generate } from "./logic/generate";
8+
import { getLibFiles } from "./logic/getLibFiles";
9+
import { projectDir } from "./logic/projectDir";
10+
11+
const docsDir = path.join(projectDir, "docs");
12+
const docsDiffDir = path.join(docsDir, "diff");
13+
14+
async function main() {
15+
await rm(docsDiffDir, {
16+
force: true,
17+
recursive: true,
18+
});
19+
await mkdir(docsDiffDir, {
20+
recursive: true,
21+
});
22+
23+
const { tsLibDir, libFiles } = await getLibFiles();
24+
const hasDiffFiles: string[] = [];
25+
for (const libFile of libFiles) {
26+
const betterLib = generate(tsLibDir, libFile, false);
27+
if (betterLib === undefined) {
28+
continue;
29+
}
30+
31+
const diffFile = path.join(docsDiffDir, libFile + ".md");
32+
33+
const originalLib = await readFile(path.join(tsLibDir, libFile), "utf8");
34+
const formattedOriginalLib = prettier.format(originalLib, {
35+
parser: "typescript",
36+
});
37+
const formattedBetterLib = prettier.format(betterLib, {
38+
parser: "typescript",
39+
});
40+
if (formattedOriginalLib === formattedBetterLib) {
41+
continue;
42+
}
43+
44+
const diffPatch = createPatch(
45+
libFile,
46+
formattedOriginalLib,
47+
formattedBetterLib
48+
);
49+
50+
const md = `# ${libFile} Diffs
51+
52+
\`\`\`diff
53+
${diffPatch}
54+
\`\`\`
55+
`;
56+
57+
await writeFile(diffFile, md);
58+
console.log(libFile);
59+
hasDiffFiles.push(libFile);
60+
}
61+
const diffDoc = `
62+
# Diffs
63+
64+
The following files are improved in better-typescript-lib:
65+
66+
${hasDiffFiles
67+
.map((libFile) => `- [${libFile}](./diff/${libFile}.md)`)
68+
.join("\n")}
69+
`;
70+
await writeFile(path.join(docsDir, "diff.md"), diffDoc);
71+
}
72+
73+
main().catch((err) => {
74+
console.error(err);
75+
process.exit(1);
76+
});

build/logic/generate.ts

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import path from "path";
2+
import ts from "typescript";
3+
import { replacement } from "../replacement";
4+
import { upsert } from "../util/upsert";
5+
import { projectDir } from "./projectDir";
6+
7+
const betterLibDir = path.join(projectDir, "lib");
8+
9+
/**
10+
* Generate one better lib file.
11+
*/
12+
export function generate(
13+
tsLibDir: string,
14+
libFile: string,
15+
emitOriginalAsComment: boolean
16+
): string | undefined {
17+
const tsLibFile = path.join(tsLibDir, libFile);
18+
const originalProgram = ts.createProgram([tsLibFile], {});
19+
const originalFile = originalProgram.getSourceFile(tsLibFile);
20+
if (!originalFile) {
21+
return undefined;
22+
}
23+
let result = "";
24+
const replacementTargets = new Map<
25+
string,
26+
{
27+
statement: ts.Statement;
28+
sourceFile: ts.SourceFile;
29+
}[]
30+
>();
31+
{
32+
const replSet = replacement.get(libFile);
33+
if (replSet) {
34+
const betterLibFile = path.join(betterLibDir, `lib.${libFile}`);
35+
const betterProgram = ts.createProgram([betterLibFile], {});
36+
const betterFile = betterProgram.getSourceFile(betterLibFile);
37+
if (betterFile) {
38+
for (const statement of betterFile.statements) {
39+
const name = getStatementDeclName(statement) ?? "";
40+
upsert(replacementTargets, name, (statements = []) => [
41+
...statements,
42+
{
43+
statement,
44+
sourceFile: betterFile,
45+
},
46+
]);
47+
}
48+
// copy other statements
49+
result +=
50+
replacementTargets
51+
.get("")
52+
?.map(({ statement, sourceFile }) =>
53+
statement.getFullText(sourceFile)
54+
)
55+
.join("") ?? "";
56+
if (result) {
57+
result += "// --------------------\n";
58+
}
59+
}
60+
}
61+
}
62+
63+
if (replacementTargets.size === 0) {
64+
for (const statement of originalFile.statements) {
65+
result += statement.getFullText(originalFile);
66+
}
67+
} else {
68+
const emittedNames = new Set<string>();
69+
for (const statement of originalFile.statements) {
70+
const name = getStatementDeclName(statement);
71+
if (name === undefined) {
72+
result += statement.getFullText(originalFile);
73+
continue;
74+
}
75+
const replacementTarget = replacementTargets.get(name);
76+
if (replacementTarget === undefined) {
77+
result += statement.getFullText(originalFile);
78+
continue;
79+
}
80+
if (!emittedNames.has(name)) {
81+
// Emit replaced statements
82+
result +=
83+
replacementTarget
84+
.map(({ statement, sourceFile }) =>
85+
statement.getFullText(sourceFile)
86+
)
87+
.join("") ?? "";
88+
emittedNames.add(name);
89+
}
90+
if (emitOriginalAsComment) {
91+
// Replaced statements are emitted as comments
92+
// to make it easier to detect original lib changes
93+
result += "\n" + commentOut(statement.getFullText(originalFile)) + "\n";
94+
}
95+
}
96+
// Emit remaining statements
97+
for (const name of emittedNames) {
98+
replacementTargets.delete(name);
99+
}
100+
const header = Array.from(replacementTargets.values())
101+
.map((statements) =>
102+
statements
103+
.map(({ statement, sourceFile }) => statement.getFullText(sourceFile))
104+
.join("")
105+
)
106+
.join("");
107+
result = (header ? header + "\n" : "") + result;
108+
}
109+
result += originalFile.text.slice(originalFile.endOfFileToken.pos);
110+
return result;
111+
}
112+
113+
function getStatementDeclName(statement: ts.Statement): string | undefined {
114+
if (ts.isVariableStatement(statement)) {
115+
for (const dec of statement.declarationList.declarations) {
116+
if (ts.isIdentifier(dec.name)) {
117+
return dec.name.text;
118+
}
119+
}
120+
} else if (
121+
ts.isFunctionDeclaration(statement) ||
122+
ts.isInterfaceDeclaration(statement) ||
123+
ts.isTypeAliasDeclaration(statement) ||
124+
ts.isModuleDeclaration(statement)
125+
) {
126+
return statement.name?.text;
127+
} else if (ts.isInterfaceDeclaration(statement)) {
128+
return statement.name.text;
129+
}
130+
return undefined;
131+
}
132+
133+
function commentOut(code: string): string {
134+
const lines = code.split("\n");
135+
const result = lines.map((line) => `// ${line}`);
136+
return result.join("\n");
137+
}

build/logic/getLibFiles.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { readdir } from "fs/promises";
2+
import path from "path";
3+
import { projectDir } from "./projectDir";
4+
5+
const tsDir = path.join(projectDir, "TypeScript");
6+
const tsLibDir = path.join(tsDir, "src", "lib");
7+
8+
export async function getLibFiles(): Promise<{
9+
tsLibDir: string;
10+
libFiles: string[];
11+
}> {
12+
// copy TypeScript lib files
13+
const libs = await readdir(tsLibDir);
14+
const libFiles: string[] = libs.filter((libFile) =>
15+
/(?:^|\/|\\).+\.d\.ts$/.test(libFile)
16+
);
17+
return {
18+
tsLibDir,
19+
libFiles,
20+
};
21+
}

build/logic/projectDir.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const projectDir = process.env.PROJECT || process.cwd();

build/util/upsert.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function upsert<K, V>(
2+
map: Map<K, V>,
3+
key: K,
4+
update: (value: V | undefined) => V
5+
) {
6+
const value = map.get(key);
7+
map.set(key, update(value));
8+
}

docs/diff.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
# Diffs
3+
4+
- [es2015.collection.d.ts](es2015.collection.d.ts.md)
5+
- [es2015.core.d.ts](es2015.core.d.ts.md)
6+
- [es2015.generator.d.ts](es2015.generator.d.ts.md)
7+
- [es2015.iterable.d.ts](es2015.iterable.d.ts.md)
8+
- [es2015.promise.d.ts](es2015.promise.d.ts.md)
9+
- [es2015.proxy.d.ts](es2015.proxy.d.ts.md)
10+
- [es2015.reflect.d.ts](es2015.reflect.d.ts.md)
11+
- [es2017.object.d.ts](es2017.object.d.ts.md)
12+
- [es2018.asyncgenerator.d.ts](es2018.asyncgenerator.d.ts.md)
13+
- [es2018.asynciterable.d.ts](es2018.asynciterable.d.ts.md)
14+
- [es2019.object.d.ts](es2019.object.d.ts.md)
15+
- [es2021.promise.d.ts](es2021.promise.d.ts.md)
16+
- [es2021.string.d.ts](es2021.string.d.ts.md)
17+
- [es2022.object.d.ts](es2022.object.d.ts.md)
18+
- [es5.d.ts](es5.d.ts.md)

0 commit comments

Comments
 (0)