Skip to content

Commit 81986db

Browse files
feat: added project references, with more docs
1 parent 27ac09f commit 81986db

15 files changed

+138
-213
lines changed

.prettierignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1+
./cases/
12
.all-contributorsrc
23
.husky/
3-
cases/

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,42 @@
1515

1616
## Usage
1717

18+
You'll need [hyperfine](https://github.com/sharkdp/hyperfine) installed locally, such as with `brew install hyperfine` or `winget install hyperfine`.
19+
See [sharkdp/hyperfine#installation](https://github.com/sharkdp/hyperfine#installation).
20+
1821
```shell
1922
npm install
2023
npm generate
2124
npm measure
2225
```
2326

27+
### Measured Attributes
28+
29+
The `caseEntries` values in `src/data.ts` can be modified to test:
30+
31+
- `files`: roughly how many generated files should be linted
32+
- `layout`: what rough shape of imports those files exhibit:
33+
- `"even"`: a single root-level `index.ts` importing from roughly an even triangle shape of files
34+
- `"references"`: a single root-level `tsconfig.json` with project references to a few projects
35+
- `"wide"`: one root-level `index.ts` importing from all files in the project
36+
- `singleRun`: whether to enable [single-run inference](https://v8--typescript-eslint.netlify.app/packages/parser#disallowautomaticsingleruninference) as a performance boost
37+
- `types`: whether to use `parserOptions.project` or `parserOptions.projectService` for typed linting
38+
39+
## Results
40+
41+
Right now, `parserOptions.project` outperforms `parserOptions.projectService`.
42+
This is a performance issue and we are investigating it as a critical bug for v8.
43+
44+
```plaintext
45+
┌───────┬──────────────────────┬──────────────────────┬──────────────────────┬──────────────────────┐
46+
│ files │ project (even) │ project (references) │ service (even) │ service (references) │
47+
┼───────┼──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────┤
48+
│ 128 │ '1.149 s ± 0.030 s' │ '1.135 s ± 0.008 s' │ '1.178 s ± 0.010 s' │ '1.736 s ± 0.012 s' │
49+
│ 512 │ '1.636 s ± 0.009 s' │ '1.656 s ± 0.004 s' │ '1.895 s ± 0.007 s' │ '2.613 s ± 0.020 s' │
50+
│ 1024 │ '2.353 s ± 0.013 s' │ '2.399 s ± 0.016 s' │ '3.130 s ± 0.017 s' │ '4.034 s ± 0.061 s' │
51+
┴───────┴──────────────────────┴──────────────────────┴──────────────────────┴──────────────────────┘
52+
```
53+
2454
## Contributors
2555

2656
<!-- spellchecker: disable -->

cspell.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"dictionaries": ["typescript"],
33
"ignorePaths": [".github", "cases", "node_modules"],
4-
"words": ["execa", "knip", "packagejson", "tseslint"]
4+
"words": ["execa", "knip", "packagejson", "sharkdp", "tseslint", "winget"]
55
}

src/creators/createEvenCaseFiles.ts

Lines changed: 0 additions & 67 deletions
This file was deleted.

src/creators/createProjectsCaseFiles.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/creators/createWideCaseFiles.ts

Lines changed: 0 additions & 43 deletions
This file was deleted.

src/creators/files.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
export interface ESLintConfigFileOptions {
2+
singleRun: boolean;
3+
types: "tsconfig.eslint.json" | "projectService" | true;
4+
}
5+
6+
export function createESLintConfigFile({
7+
singleRun,
8+
types,
9+
}: ESLintConfigFileOptions) {
10+
const [projectKey, projectValue] =
11+
types === "projectService" ? ["projectService", true] : ["project", types];
12+
13+
return `
14+
import tseslint from "typescript-eslint";
15+
16+
export default tseslint.config(
17+
tseslint.configs.base,
18+
{
19+
files: ["**/*.ts"],
20+
languageOptions: {
21+
parserOptions: {
22+
${singleRun ? "disallowAutomaticSingleRunInference: true," : ""}
23+
${projectKey}: ${typeof projectValue === "string" ? `"${projectValue}"` : projectValue},
24+
tsconfigRootDir: import.meta.dirname,
25+
},
26+
},
27+
rules: {
28+
"@typescript-eslint/no-floating-promises": "error"
29+
}
30+
},
31+
);
32+
`;
33+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { NamedCaseData } from "../../data.js";
2+
3+
export function createPackageFile(data: NamedCaseData) {
4+
return {
5+
devDependencies: {
6+
"@eslint/js": "*",
7+
eslint: "*",
8+
typescript: "*",
9+
"typescript-eslint": "rc-v8",
10+
},
11+
name: data.name,
12+
private: true,
13+
scripts: {
14+
lint: "eslint src",
15+
},
16+
type: "module",
17+
};
18+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export function createStandardTSConfigFile() {
2+
return {
3+
compilerOptions: {
4+
module: "NodeNext",
5+
noEmit: true,
6+
skipLibCheck: true,
7+
strict: true,
8+
target: "ESNext",
9+
},
10+
include: ["src"],
11+
};
12+
}

src/creators/writeCaseFiles.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { CaseData } from "../data.js";
2+
import { writeStructure } from "../writing/writeStructure.js";
3+
import { writeEvenCaseFiles } from "./cases/createEvenCaseFiles.js";
4+
import { createReferencesCaseFiles } from "./cases/createReferencesCaseFiles.js";
5+
import { writeWideCaseFiles } from "./cases/createWideCaseFiles.js";
6+
7+
const caseFileCreators = {
8+
even: writeEvenCaseFiles,
9+
references: createReferencesCaseFiles,
10+
wide: writeWideCaseFiles,
11+
};
12+
13+
export async function writeCaseFiles(data: CaseData, directory: string) {
14+
return await writeStructure(directory, caseFileCreators[data.layout](data));
15+
}

src/data.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ export const casesPath = "cases";
33
export const caseEntries = [
44
{
55
label: "files",
6-
// values: [1, 32, 64, 128, 256, 512, 1024],
7-
values: [512, 1024],
6+
values: [128, 512, 1024],
87
},
98
{
109
label: "layout",
11-
values: ["even" /* , "projects" , "wide" */],
10+
// values: ["even" /* , "references" , "wide" */],
11+
values: ["even", "references" /* , "wide" */],
1212
},
1313
{
1414
label: "singleRun",
15-
values: [false, true],
15+
values: [/* false, */ true],
1616
},
1717
{
1818
label: "types",

src/generate.ts

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,56 +2,27 @@ import { execa } from "execa";
22
import fs from "node:fs/promises";
33
import path from "node:path";
44

5-
import { createESLintConfigFile, writeCaseFiles } from "./creators/files.js";
5+
import { writeCaseFiles } from "./creators/writeCaseFiles.js";
6+
import { createPackageFile } from "./creators/files/createPackageFile.js";
7+
import { createESLintConfigFile } from "./creators/files/createESLintConfigFile.js";
68
import { CaseData, NamedCaseData, caseEntries, casesPath } from "./data.js";
79
import { createProjectName } from "./utils.js";
810
import { writeFile } from "./writing/writeFile.js";
911

10-
async function createCase(data: CaseData): Promise<NamedCaseData> {
11-
const name = createProjectName(data);
12+
async function createCase(data: NamedCaseData): Promise<NamedCaseData> {
13+
const name = createProjectName({
14+
files: data.files,
15+
layout: data.layout,
16+
singleRun: data.singleRun,
17+
types: data.types,
18+
});
1219
const directory = path.join(casesPath, name);
1320

1421
console.log(`Populating ${name}...`);
1522

1623
await fs.mkdir(path.join(directory, "src"), { recursive: true });
1724

18-
await writeFile(directory, "eslint.config.js", createESLintConfigFile(data));
19-
20-
await writeFile(
21-
directory,
22-
"package.json",
23-
{
24-
devDependencies: {
25-
"@eslint/js": "*",
26-
eslint: "*",
27-
typescript: "*",
28-
"typescript-eslint": "rc-v8",
29-
},
30-
name,
31-
private: true,
32-
scripts: {
33-
lint: "eslint src",
34-
},
35-
type: "module",
36-
},
37-
"json",
38-
);
39-
40-
await writeFile(
41-
directory,
42-
"tsconfig.json",
43-
{
44-
compilerOptions: {
45-
module: "NodeNext",
46-
noEmit: true,
47-
skipLibCheck: true,
48-
strict: true,
49-
target: "ESNext",
50-
},
51-
include: ["src"],
52-
},
53-
"json",
54-
);
25+
await writeFile(directory, "package.json", createPackageFile(data), "json");
5526

5627
console.log("Created", await writeCaseFiles(data, directory), "files");
5728

@@ -71,10 +42,10 @@ const cases: NamedCaseData[] = [];
7142

7243
for (const files of caseEntries[0].values) {
7344
for (const layout of caseEntries[1].values) {
74-
for (const singleRun of caseEntries[2].values) {
75-
for (const types of caseEntries[3].values) {
76-
cases.push(await createCase({ files, layout, singleRun, types }));
77-
}
45+
for (const types of caseEntries[3].values) {
46+
const data: CaseData = { files, layout, singleRun: true, types };
47+
const name = createProjectName(data);
48+
cases.push(await createCase({ ...data, name }));
7849
}
7950
}
8051
}

0 commit comments

Comments
 (0)