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

(v2.0) Strict mode by default #19

Merged
merged 31 commits into from
Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
080da27
tests-jest | Converts tests to jest
Oct 4, 2021
fad9854
Merge branch 'master' of https://github.com/allegro/typescript-strict…
Oct 4, 2021
595756d
tests-jest | Type fixes
Oct 4, 2021
01ebd16
tests-jest | Fixes cli test
Oct 4, 2021
d96159a
ts-strict | Adds file ignoring with @ts-strict-ignore comment
Oct 4, 2021
374dbad
ts-strict | Adds insert ignore comment functionality
Oct 4, 2021
fb7a833
ts-strict | Unifies cli and plugin logic
kamkry Oct 20, 2021
ec9fc62
ts-strict | Adds file updating
kamkry Nov 15, 2021
7345fff
ts-strict | Unifies function declarations
kamkry Nov 15, 2021
a582967
ts-strict | 2.0 init
kamkry Nov 29, 2021
525b71a
ts-strict | Readme update 1.0
kamkry Nov 29, 2021
8273719
ts-strict | Readme update migration part
kamkry Dec 10, 2021
3a97b96
ts-strict | Updated user messages
kamkry Dec 10, 2021
2c48159
ts-strict | Fixes test variable names
kamkry Dec 10, 2021
9c5fc80
ts-strict | Fixes type error
kamkry Dec 10, 2021
68f4900
ts-strict | Updates changelog
kamkry Dec 10, 2021
591619f
Merge branch 'master' of https://github.com/allegro/typescript-strict…
kamkry Dec 13, 2021
140f154
ts-strict | Removes updateComments tests for now
kamkry Dec 13, 2021
1d81e03
Refactor
kamkry Jan 1, 2022
f1d3cf2
Bugfixes
kamkry Jan 1, 2022
7d64061
comments refactor
kamkry Jan 6, 2022
e020037
Adds pluralization and cli unit tests
kamkry Jan 6, 2022
a0c589a
Adds process exit expects to tsc-strict root files
kamkry Jan 6, 2022
dbc9d06
Fixes failing tests
kamkry Jan 7, 2022
bcf1588
e2e fixture refactor
kamkry Jan 15, 2022
3760387
typo fixes
kamkry Jan 15, 2022
fcb2e4c
typo fixes
kamkry Jan 15, 2022
f9726e8
cli structure refactor
kamkry Jan 15, 2022
b1f5a73
final test addition
kamkry Jan 16, 2022
6f64cb7
Fixes e2e test name
kamkry Jan 16, 2022
43cf8d8
fixes bin scripts paths
kamkry Jan 16, 2022
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
dist
.idea
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.0.0] - 2021-29-11

### Changed
- Strict by default without `@ts-strict` comment
- Ignores file with `@ts-strict-ignore` comment
- Migration tool `update-strict-comments` which updates comments in files which contain at least 1 strict error

## [1.1.2] - 2021-06-15

### Added
Expand Down
97 changes: 20 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

Typescript plugin that allows turning on strict mode in specific files or directories.

## Do i need this plugin?
This plugin was created for bigger repositories that want to incorporate typescript strict mode, but project is so big that refactoring everything would take ages. This plugin allows user to simply put `//@ts-strict` comment to a top of a file and turn a strict mode to that file. If needed, strict mode can be turned on to directories too.
Plugins in general doesn't work in compile time. They will show errors in your IDE but they won't appear during compilation.
To check strict errors in marked files you can use our script `tsc-strict`.
This command line tool is created to check for files that should be checked with strict rules in compilation time.
It finds all files with `//@ts-strict` comment and files specified in `paths` parameter and checks for strict typescript errors only for that files.
## Do I need this plugin?
`typescript-strict-plugin` was created mainly for existing projects that want to incorporate typescript strict mode, but project is so big that refactoring everything would take ages.


Our plugin allows adding strict mode to a TypeScript project without fixing all the errors at once. By adding `//@ts-strict-ignore` comment at the top of a file, its whole content will be removed from strict type checking. To ease migrating a project to use this plugin, you can use `tsc-strict --updateComment` script, which adds the ignore comment to all files that contain at least one strict error.


TypeScript plugins don't work at compile-time. They will show errors in your IDE, but they won't appear during compilation.
To check strict errors in marked files you can use `tsc-strict` script. This command line tool is created to check for files that should be checked with strict rules in compilation time.
It finds all relevant files and checks for strict typescript errors only for that files.
Therefore, we have strict errors inside our files and during build time.


Expand All @@ -21,7 +25,7 @@ or yarn
```bash
yarn add -D typescript-strict-plugin
```
and add plugin to your `tsconfig.json`:
add plugin to your `tsconfig.json`:
```json
{
"compilerOptions": {
Expand All @@ -35,10 +39,14 @@ and add plugin to your `tsconfig.json`:
}
}
```
That's it! You should be able to use `@ts-strict` comment to strictly check your files.
and run the migration script
```
tsc-strict --updateComments
```
That's it! You should be able to see strict typechecking in files without the `@ts-strict-ignore` comment. To make these files strict too, just remove its' ignore comments.

## Configuration
Plugin takes one extra non-mandatory argument `paths` that is an array of relative or absolute paths of directories that should be included.
Plugin takes one extra non-mandatory argument `paths` that is an array of relative or absolute paths of directories that should be included. To add strict mode to files from ignored paths you can insert `//@ts-strict` comment.
```json
{
"compilerOptions": {
Expand Down Expand Up @@ -82,75 +90,10 @@ yarn tsc-strict --strictNullChecks false
would not check for the strict null check in your files. The `tsc-strict` accepts all the arguments that regular `tsc` command
accepts.

## Examples
Let's consider this type and a variable
```typescript
interface TestType {
bar: string;
}

const foo: TestType | undefined = undefined;
```
1. No `paths` argument
With `tsconfig.json` like this:
```json
{
"compilerOptions": {
...
"strict": false,
"plugins": [
{
"name": "typescript-strict-plugin"
}
]
}
}
```
Typescript will produce errors:
```typescript
//@ts-strict
...
const boo = foo.bar; // TS2532: Object is possibly 'undefined'.
```
Or not, depending on whether we used `ts-strict` or not:
```typescript
//no strict comment here
...
const boo = foo.bar; // no error here
```

2. With `paths` argument
With `tsconfig.json` like this:
```json
{
"compilerOptions": {
...
"strict": false,
"plugins": [
{
"name": "typescript-strict-plugin",
"path": "./src"
}
]
}
}
```
If file is in the directory typescript will produce errors even if `ts-strict` comment is not in the file :
```typescript
// ./src/index.ts
const boo = foo.bar; // TS2532: Object is possibly 'undefined'.
```
If file is not in the diretory there will be no error
```typescript
// ./lib/index.ts
const boo = foo.bar; // no error here
## Migrating to v2
Because of difficulties with migrating large projects to strict mode with original `//@ts-strict` comment, we've taken an another approach. Now in version 2.0+ typescript files are strict by default, and to ignore a file, you can use special `//@ts-strict-ignore` comment. It allows to have strict mode in newly created files without remembering about adding strict comment at the top of it. With version 2.0 script `tsc-strict` comes with a new flag, which detects all files with at least one strict error and adds the ignore comment to ease the migration. To update from v1 to v2, you just need to run:
```
If file is not in the diretory but there is `ts-strict` file will be check with strict mode:
```typescript
// ./lib/index.ts
//@ts-strict
...
const boo = foo.bar; // TS2532: Object is possibly 'undefined'.
tsc-strict --updateComments
```

## Testing the plugin
Expand Down
4 changes: 4 additions & 0 deletions e2e/fixtures/default-config/ignored.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @ts-strict-ignore
const text: string = null;

export {};
3 changes: 3 additions & 0 deletions e2e/fixtures/default-config/strict.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
17 changes: 17 additions & 0 deletions e2e/fixtures/default-config/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"lib": ["es2018"],
"baseUrl": "./",
"outDir": "./dist",
"strict": false,
"esModuleInterop": true,
"noImplicitAny": true,
"plugins": [
{
"name": "../../dist/plugin"
}
]
}
}
3 changes: 3 additions & 0 deletions e2e/fixtures/path-config/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
3 changes: 3 additions & 0 deletions e2e/fixtures/path-config/excluded/excluded.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
3 changes: 3 additions & 0 deletions e2e/fixtures/path-config/excluded/excluded2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @ts-strict
const text: string = null;

export {};
3 changes: 3 additions & 0 deletions e2e/fixtures/path-config/included/included.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
3 changes: 3 additions & 0 deletions e2e/fixtures/path-config/included/included2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const text: string = null;

export {};
20 changes: 20 additions & 0 deletions e2e/fixtures/paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import path from 'path';

export const fixtureWithDefaultConfig = {
projectPath: path.resolve(__dirname, 'default-config'),
filePaths: {
strict: 'strict.ts',
ignored: 'ignored.ts',
},
};

export const fixtureWithPathConfig = {
projectPath: path.resolve(__dirname, 'path-config'),
filePaths: {
included: 'included/included.ts',
included2: 'included/included2.ts',
excluded: 'excluded/excluded.ts',
excluded2: 'excluded/excluded2.ts',
excludedWithStrictComment: 'excluded/excludedWithStrictComment.ts',
},
};
15 changes: 15 additions & 0 deletions e2e/plugin/multipleFile.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { getMultipleDiagnostics } from './utils/getMultipleDiagnostics';
import { fixtureWithDefaultConfig } from '../fixtures/paths';

it('should show errors only on file with strict comment', async () => {
// given
const { projectPath, filePaths } = fixtureWithDefaultConfig;
const fileList = [filePaths.strict, filePaths.ignored];

// when
const diagnostics = await getMultipleDiagnostics(projectPath, fileList);

// then
expect(diagnostics[0]).toHaveLength(1);
expect(diagnostics[1]).toHaveLength(0);
});
48 changes: 48 additions & 0 deletions e2e/plugin/singleFile.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { getDiagnostics } from './utils/getDiagnostics';
import { fixtureWithDefaultConfig, fixtureWithPathConfig } from '../fixtures/paths';

describe('single file diagnostics', () => {
it('should enable strict mode by default in project without config', async () => {
// given
const { projectPath, filePaths } = fixtureWithDefaultConfig;

// when
const diagnostics = await getDiagnostics(projectPath, filePaths.strict);

// then
expect(diagnostics).toHaveLength(1);
});

it('should not enable strict mode in ignored file', async () => {
// given
const { projectPath, filePaths } = fixtureWithDefaultConfig;

// when
const diagnostics = await getDiagnostics(projectPath, filePaths.ignored);

// then
expect(diagnostics).toHaveLength(0);
});

it('should not enable strict mode when file is not on path', async () => {
// given
const { projectPath, filePaths } = fixtureWithPathConfig;

// when
const diagnostics = await getDiagnostics(projectPath, filePaths.excluded);

// then
expect(diagnostics).toHaveLength(0);
});

it('should enable strict mode when file is not on path and contains strict comment', async () => {
// given
const { projectPath, filePaths } = fixtureWithPathConfig;

// when
const diagnostics = await getDiagnostics(projectPath, filePaths.excludedWithStrictComment);

// then
expect(diagnostics).toHaveLength(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,9 @@ export class TSServer {
this._responseCommandEmitter = new EventEmitter();
const tsserverPath = require.resolve('typescript/lib/tsserver');

// to create ts log from tests
// process.env['TSS_LOG'] = '-logToFile true -file /path/typescript-strict-plugin/log1.txt -level verbose';
const server = fork(tsserverPath, {
cwd: join(__dirname, '../project-fixture/src'),
stdio: ['pipe', 'pipe', 'pipe', 'ipc'],
// env: { TSS_LOG: '-logToFile true -file ./ts.log -level verbose' }, // creates tsserver log from tests
});
this._exitPromise = new Promise((resolve, reject) => {
server.on('exit', (code: string) => resolve(code));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { ServerResponse, TSServer } from './fixtures/lang-server';
import path from 'path';
import { ServerResponse, TSServer } from './TSServer';
import path, { resolve } from 'path';
import { readFileSync } from 'fs';

function findResponse(responses: ServerResponse[], eventName: string) {
return responses.find((response) => response.event === eventName);
}

export async function getDiagnostics(fileContent: string, fileName = 'src/notOnPath.ts') {
export async function getDiagnostics(projectPath: string, filePath: string) {
const server = new TSServer();

const file = path.resolve(__dirname, 'project-fixture', fileName);
const file = resolve(projectPath, filePath);

const fileContent = readFileSync(file, 'utf-8');

server.send({ command: 'open', arguments: { file, fileContent, scriptKindName: 'TS' } });

Expand All @@ -21,5 +24,6 @@ export async function getDiagnostics(fileContent: string, fileName = 'src/notOnP
await server.close();

const semanticDiagEvent = findResponse(server.responses, 'semanticDiag');

return semanticDiagEvent?.body.diagnostics;
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import { ServerResponse, TSServer } from './fixtures/lang-server';
import { ServerResponse, TSServer } from './TSServer';
import path from 'path';

interface FileInfo {
fileContent: string;
fileName: string;
}
import * as fs from 'fs';

function findResponses(responses: ServerResponse[], eventName: string) {
return responses.filter((response) => response.event === eventName);
}

export async function getMultipleDiagnostics(fileInfoList: FileInfo[], rootPath: string) {
export async function getMultipleDiagnostics(projectPath: string, filePaths: string[]) {
const server = new TSServer();

const openFiles = fileInfoList.map((fileInfo) => ({
file: path.resolve(rootPath, fileInfo.fileName),
fileContent: fileInfo.fileContent,
projectRootPath: rootPath,
scriptKindName: 'TS',
}));
const openFiles = filePaths.map((filePath) => {
const file = path.resolve(projectPath, filePath);
return {
file,
fileContent: fs.readFileSync(file, 'utf-8'),
projectRootPath: projectPath,
scriptKindName: 'TS',
};
});

const openFilePaths = openFiles.map((file) => file.file);

Expand Down
Loading