Skip to content

Commit

Permalink
fix: writing TypeScript config file (#2114)
Browse files Browse the repository at this point in the history
## PR Checklist

- [x] Addresses an existing open issue: fixes #2113
- [x] That issue was marked as [`status: accepting
prs`](https://github.com/JoshuaKGoldberg/TypeStat/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22)
- [x] Steps in
[CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/TypeStat/blob/main/.github/CONTRIBUTING.md)
were taken

## Overview

- Fixes issue where `null` was inserted to typestat.json `includes` list
- Fixes issue where option was `inferableTypes` when it should be
`noInferableTypes`
- Added basic testing for config generation

For future:
- Config generation is still little bit broken. If I want to select just
"Remove type annotations that don't change the meaning of code" option,
the generated config file does not have it but instead has just
`"incompleteTypes": true`. -> Needs new issue created.

🐙
  • Loading branch information
rubiesonthesky authored Jan 17, 2025
1 parent 3c740f7 commit 90ef5e5
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { describe, expect, it } from "vitest";

import { InitializationImprovement } from "./improvements.js";
import { generateMultiTypeScriptConfig } from "./writeMultiTypeScriptConfig.js";

describe("writeMultiTypeScriptConfig", () => {
it("creates multi TypeScript config", () => {
const config = generateMultiTypeScriptConfig({
fileName: "typestat.json",
improvements: new Set([
InitializationImprovement.MissingProperties,
InitializationImprovement.NoImplicitAny,
InitializationImprovement.NoImplicitThis,
InitializationImprovement.NoInferableTypes,
InitializationImprovement.StrictNullChecks,
]),
project: { filePath: "./tsconfig.json" },
testFiles: "test/**/*.{ts,tsx}",
});

expect(config).toStrictEqual([
{
fixes: {
incompleteTypes: true,
noImplicitAny: true,
noImplicitThis: true,
noInferableTypes: true,
strictNonNullAssertions: true,
},
include: ["test/**/*.{ts,tsx}"],
projectPath: "./tsconfig.json",
types: {
strictNullChecks: true,
},
},
{
fixes: {
incompleteTypes: true,
noImplicitAny: true,
noImplicitThis: true,
noInferableTypes: true,
},
include: undefined,
projectPath: "./tsconfig.json",
},
{
fixes: {
incompleteTypes: true,
noImplicitAny: true,
noImplicitThis: true,
noInferableTypes: true,
},
include: ["test/**/*.{ts,tsx}"],
projectPath: "./tsconfig.json",
},
]);
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as fs from "node:fs/promises";

import { Fixes, RawTypeStatOptions } from "../../options/types.js";
import { isNotUndefined } from "../../shared/arrays.js";
import { ProjectDescription } from "../initializeProject/shared.js";
import { InitializationImprovement } from "./improvements.js";

Expand All @@ -11,61 +13,62 @@ export interface MultiTypeScriptConfigSettings {
testFiles?: string;
}

export const writeMultiTypeScriptConfig = async ({
fileName,
export const writeMultiTypeScriptConfig = async (
settings: MultiTypeScriptConfigSettings,
) => {
const config = generateMultiTypeScriptConfig(settings);
await fs.writeFile(settings.fileName, JSON.stringify(config, undefined, 4));
};

export const generateMultiTypeScriptConfig = ({
improvements,
project,
sourceFiles,
testFiles,
}: MultiTypeScriptConfigSettings) => {
await fs.writeFile(
fileName,
JSON.stringify(
[
{
fixes: {
...printImprovements(improvements),
strictNonNullAssertions: true,
},
...(testFiles && { include: [testFiles] }),
projectPath: project.filePath,
types: {
strictNullChecks: true,
},
},
{
...(testFiles && { exclude: [testFiles] }),
fixes: printImprovements(improvements),
...(sourceFiles && { include: [sourceFiles] }),
projectPath: project.filePath,
},
{
fixes: printImprovements(improvements),
...(testFiles
? { include: [testFiles, sourceFiles] }
: { include: [sourceFiles] }),
projectPath: project.filePath,
},
],
undefined,
4,
),
);
const fixes = printImprovements(improvements);

const stage1: Partial<RawTypeStatOptions> = {
fixes: {
...fixes,
strictNonNullAssertions: true,
},
include: testFiles ? [testFiles] : undefined,
projectPath: project.filePath,
types: {
strictNullChecks: true,
},
};

const stage2: Partial<RawTypeStatOptions> = {
fixes,
include: sourceFiles ? [sourceFiles] : undefined,
projectPath: project.filePath,
};

const stage3Include = [testFiles, sourceFiles].filter(isNotUndefined);

const stage3: Partial<RawTypeStatOptions> = {
fixes,
include: stage3Include.length ? stage3Include : undefined,
projectPath: project.filePath,
};

return [stage1, stage2, stage3];
};

const printImprovements = (
improvements: ReadonlySet<InitializationImprovement>,
) => {
return {
incompleteTypes: true,
...(improvements.has(InitializationImprovement.NoImplicitAny) && {
noImplicitAny: true,
}),
...(improvements.has(InitializationImprovement.NoInferableTypes) && {
inferableTypes: true,
}),
...(improvements.has(InitializationImprovement.NoImplicitThis) && {
noImplicitThis: true,
}),
};
): Partial<Fixes> => {
const fixes: Partial<Fixes> = { incompleteTypes: true };
if (improvements.has(InitializationImprovement.NoImplicitAny)) {
fixes.noImplicitAny = true;
}
if (improvements.has(InitializationImprovement.NoInferableTypes)) {
fixes.noInferableTypes = true;
}
if (improvements.has(InitializationImprovement.NoImplicitThis)) {
fixes.noImplicitThis = true;
}
return fixes;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { describe, expect, it } from "vitest";

import { InitializationImprovement } from "./improvements.js";
import { generateSingleTypeScriptConfig } from "./writeSingleTypeScriptConfig.js";

describe("writeMultiTypeScriptConfig", () => {
it("creates multi TypeScript config", () => {
const config = generateSingleTypeScriptConfig({
fileName: "typestat.json",
improvements: new Set([InitializationImprovement.NoImplicitAny]),
project: { filePath: "./tsconfig.json" },
});

expect(config).toStrictEqual({
fixes: {
incompleteTypes: true,
noImplicitAny: true,
},
include: undefined,
projectPath: "./tsconfig.json",
});

expect(JSON.stringify(config)).toBe(
'{"fixes":{"incompleteTypes":true,"noImplicitAny":true},"projectPath":"./tsconfig.json"}',
);
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as fs from "node:fs/promises";

import { Fixes, RawTypeStatOptions } from "../../options/types.js";
import { ProjectDescription } from "../initializeProject/shared.js";
import { InitializationImprovement } from "./improvements.js";

Expand All @@ -10,36 +11,35 @@ export interface SingleTypeScriptConfigSettings {
sourceFiles?: string;
}

export const writeSingleTypeScriptConfig = async ({
fileName,
export const writeSingleTypeScriptConfig = async (
settings: SingleTypeScriptConfigSettings,
) => {
const config = generateSingleTypeScriptConfig(settings);
await fs.writeFile(settings.fileName, JSON.stringify(config, undefined, 4));
};

export const generateSingleTypeScriptConfig = ({
improvements,
project,
sourceFiles,
}: SingleTypeScriptConfigSettings) => {
await fs.writeFile(
fileName,
JSON.stringify(
{
fixes: printImprovements(improvements),
...(sourceFiles && { include: [sourceFiles] }),
projectPath: project.filePath,
},
undefined,
4,
),
);
const config: Partial<RawTypeStatOptions> = {
fixes: printImprovements(improvements),
include: sourceFiles ? [sourceFiles] : undefined,
projectPath: project.filePath,
};
return config;
};

const printImprovements = (
improvements: ReadonlySet<InitializationImprovement>,
) => {
return {
incompleteTypes: true,
...(improvements.has(InitializationImprovement.NoImplicitAny) && {
noImplicitAny: true,
}),
...(improvements.has(InitializationImprovement.NoImplicitThis) && {
noImplicitThis: true,
}),
};
): Partial<Fixes> => {
const fixes: Partial<Fixes> = { incompleteTypes: true };
if (improvements.has(InitializationImprovement.NoImplicitAny)) {
fixes.noImplicitAny = true;
}
if (improvements.has(InitializationImprovement.NoImplicitThis)) {
fixes.noImplicitThis = true;
}
return fixes;
};

0 comments on commit 90ef5e5

Please sign in to comment.