Skip to content

Commit

Permalink
Replace TSLint with ESLint (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
BendingBender authored Jun 4, 2021
1 parent 0812f39 commit 28195d6
Show file tree
Hide file tree
Showing 18 changed files with 89 additions and 58 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
source/test/fixtures
9 changes: 9 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": ["xo", "xo-typescript"],
"parserOptions": {
"project": "tsconfig.tsd.json"
},
"rules": {
"@typescript-eslint/comma-dangle": "off"
}
}
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"test": "npm run lint && ava",
"build": "npm run clean && tsc --project tsconfig.tsd.json && chmod +x dist/cli.js",
"clean": "del-cli dist",
"lint": "tslint -p tsconfig.tsd.json --format stylish"
"lint": "eslint 'source/**/*'",
"lint:fix": "eslint --fix 'source/**/*'"
},
"files": [
"dist/**/*.js",
Expand Down Expand Up @@ -49,15 +50,18 @@
"@ava/typescript": "^1.1.1",
"@types/node": "^14.0.0",
"@types/react": "^16.9.2",
"@typescript-eslint/eslint-plugin": "^4.26.0",
"@typescript-eslint/parser": "^4.26.0",
"ava": "^3.8.2",
"cpy-cli": "^3.0.0",
"del-cli": "^3.0.0",
"eslint": "^7.27.0",
"eslint-config-xo": "^0.36.0",
"eslint-config-xo-typescript": "^0.41.1",
"execa": "^5.0.0",
"react": "^16.9.0",
"rxjs": "^6.5.3",
"tslint": "^5.11.0",
"tslint-xo": "^0.9.0",
"typescript": "^4.1.5"
"typescript": "^4.3.2"
},
"ava": {
"timeout": "2m",
Expand Down
9 changes: 6 additions & 3 deletions source/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const cli = meow(`
✖ 10:20 Argument of type string is not assignable to parameter of type number.
`);

(async () => { // tslint:disable-line:no-floating-promises
(async () => {
try {
const options = cli.input.length > 0 ? {cwd: cli.input[0]} : undefined;

Expand All @@ -25,8 +25,11 @@ const cli = meow(`
if (diagnostics.length > 0) {
throw new Error(formatter(diagnostics));
}
} catch (error) {
console.error(error.message);
} catch (error: unknown) {
if (error && typeof (error as Error).message === 'string') {
console.error((error as Error).message);
}

process.exit(1);
}
})();
35 changes: 19 additions & 16 deletions source/lib/assertions/assert.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/* eslint-disable @typescript-eslint/no-unused-vars */

/**
* Check that the type of `value` is identical to type `T`.
*
* @param value - Value that should be identical to type `T`.
*/
// @ts-ignore
export const expectType = <T>(value: T) => { // tslint:disable-line:no-unused
// @ts-expect-error
export const expectType = <T>(value: T) => {
// Do nothing, the TypeScript compiler handles this for us
};

Expand All @@ -13,8 +15,9 @@ export const expectType = <T>(value: T) => { // tslint:disable-line:no-unused
*
* @param value - Value that should be identical to type `T`.
*/
// @ts-ignore
export const expectNotType = <T>(value: any) => { // tslint:disable-line:no-unused
// @ts-expect-error
export const expectNotType = <T>(value: any) => {
// eslint-disable-next-line no-warning-comments
// TODO Use a `not T` type when possible https://github.com/microsoft/TypeScript/pull/29317
// Do nothing, the TypeScript compiler handles this for us
};
Expand All @@ -24,8 +27,8 @@ export const expectNotType = <T>(value: any) => { // tslint:disable-line:no-unu
*
* @param value - Value that should be assignable to type `T`.
*/
// @ts-ignore
export const expectAssignable = <T>(value: T) => { // tslint:disable-line:no-unused
// @ts-expect-error
export const expectAssignable = <T>(value: T) => {
// Do nothing, the TypeScript compiler handles this for us
};

Expand All @@ -34,8 +37,8 @@ export const expectAssignable = <T>(value: T) => { // tslint:disable-line:no-un
*
* @param value - Value that should not be assignable to type `T`.
*/
// @ts-ignore
export const expectNotAssignable = <T>(value: any) => { // tslint:disable-line:no-unused
// @ts-expect-error
export const expectNotAssignable = <T>(value: any) => {
// Do nothing, the TypeScript compiler handles this for us
};

Expand All @@ -44,8 +47,8 @@ export const expectNotAssignable = <T>(value: any) => { // tslint:disable-line:
*
* @param value - Value that should be checked.
*/
// @ts-ignore
export const expectError = <T = any>(value: T) => { // tslint:disable-line:no-unused
// @ts-expect-error
export const expectError = <T = any>(value: T) => {
// Do nothing, the TypeScript compiler handles this for us
};

Expand All @@ -54,8 +57,8 @@ export const expectError = <T = any>(value: T) => { // tslint:disable-line:no-u
*
* @param expression - Expression that should be marked as `@deprecated`.
*/
// @ts-ignore
export const expectDeprecated = (expression: any) => { // tslint:disable-line:no-unused
// @ts-expect-error
export const expectDeprecated = (expression: any) => {
// Do nothing, the TypeScript compiler handles this for us
};

Expand All @@ -64,8 +67,8 @@ export const expectDeprecated = (expression: any) => { // tslint:disable-line:n
*
* @param expression - Expression that should not be marked as `@deprecated`.
*/
// @ts-ignore
export const expectNotDeprecated = (expression: any) => { // tslint:disable-line:no-unused
// @ts-expect-error
export const expectNotDeprecated = (expression: any) => {
// Do nothing, the TypeScript compiler handles this for us
};

Expand All @@ -74,7 +77,7 @@ export const expectNotDeprecated = (expression: any) => { // tslint:disable-lin
*
* @param expression - Expression whose type should be printed as a warning.
*/
// @ts-ignore
export const printType = (expression: any) => { // tslint:disable-line:no-unused
// @ts-expect-error
export const printType = (expression: any) => {
// Do nothing, the TypeScript compiler handles this for us
};
2 changes: 1 addition & 1 deletion source/lib/assertions/handlers/expect-deprecated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const expectDeprecatedHelper = (options: Options): Handler => {

const message = tsutils.expressionToString(checker, argument);

diagnostics.push(makeDiagnostic(node, options.message(message || '?')));
diagnostics.push(makeDiagnostic(node, options.message(message ?? '?')));
}

return diagnostics;
Expand Down
12 changes: 7 additions & 5 deletions source/lib/compiler.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {
flattenDiagnosticMessageText,
createProgram,
Diagnostic as TSDiagnostic,
SourceFile
Diagnostic as TSDiagnostic
} from '@tsd/typescript';
import {ExpectedError, extractAssertions, parseErrorAssertionToLocation} from './parser';
import {Diagnostic, DiagnosticCode, Context, Location} from './interfaces';
Expand Down Expand Up @@ -63,10 +62,12 @@ const ignoreDiagnostic = (
return 'preserve';
}

const diagnosticFileName = (diagnostic.file as SourceFile).fileName;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const diagnosticFileName = diagnostic.file!.fileName;

for (const [location] of expectedErrors) {
const start = diagnostic.start as number;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const start = diagnostic.start!;

if (diagnosticFileName === location.fileName && start > location.start && start < location.end) {
return location;
Expand Down Expand Up @@ -116,7 +117,8 @@ export const getDiagnostics = (context: Context): Diagnostic[] => {
continue;
}

const position = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start as number);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const position = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!);

diagnostics.push({
fileName: diagnostic.file.fileName,
Expand Down
10 changes: 5 additions & 5 deletions source/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ import {
parseJsonSourceFileConfigFileContent,
ModuleKind
} from '@tsd/typescript';
import {Config, RawConfig, RawCompilerOptions} from './interfaces';
import {Config, PackageJsonWithTsdConfig, RawCompilerOptions} from './interfaces';

/**
* Load the configuration settings.
*
* @param pkg - The package.json object.
* @returns The config object.
*/
export default (pkg: {tsd?: RawConfig}, cwd: string): Config => {
const pkgConfig = pkg.tsd || {};
export default (pkg: PackageJsonWithTsdConfig, cwd: string): Config => {
const pkgConfig = pkg.tsd ?? {};

const tsConfigCompilerOptions = getOptionsFromTsConfig(cwd);
const packageJsonCompilerOptions = parseCompilerConfigObject(
pkgConfig.compilerOptions || {},
pkgConfig.compilerOptions ?? {},
cwd
);

Expand Down Expand Up @@ -70,5 +70,5 @@ function parseCompilerConfigObject(compilerOptions: RawCompilerOptions, cwd: str
}

function parseRawLibs(libs: string[], cwd: string): string[] {
return parseCompilerConfigObject({lib: libs}, cwd).lib || [];
return parseCompilerConfigObject({lib: libs}, cwd).lib ?? [];
}
14 changes: 11 additions & 3 deletions source/lib/formatter.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import * as formatter from 'eslint-formatter-pretty';
import {Diagnostic} from './interfaces';

interface FileWithDiagnostics {
filePath: string;
errorCount: number;
warningCount: number;
messages: Diagnostic[];
}

/**
* Format the TypeScript diagnostics to a human readable output.
*
* @param diagnostics - List of TypeScript diagnostics.
* @returns Beautiful diagnostics output
*/
export default (diagnostics: Diagnostic[]) => {
const fileMap = new Map<string, any>();
export default (diagnostics: Diagnostic[]): string => {
const fileMap = new Map<string, FileWithDiagnostics>();

for (const diagnostic of diagnostics) {
let entry = fileMap.get(diagnostic.fileName);
Expand All @@ -28,5 +35,6 @@ export default (diagnostics: Diagnostic[]) => {
entry.messages.push(diagnostic);
}

return formatter(Array.from(fileMap.values()));
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
return String(formatter([...fileMap.values()]));
};
10 changes: 5 additions & 5 deletions source/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import * as globby from 'globby';
import {getDiagnostics as getTSDiagnostics} from './compiler';
import loadConfig from './config';
import getCustomDiagnostics from './rules';
import {Context, Config} from './interfaces';
import {Context, Config, Diagnostic, PackageJsonWithTsdConfig} from './interfaces';

export interface Options {
cwd: string;
typingsFile?: string;
testFiles?: readonly string[];
}

const findTypingsFile = async (pkg: any, options: Options) => {
const findTypingsFile = async (pkg: PackageJsonWithTsdConfig, options: Options): Promise<string> => {
const typings =
options.typingsFile ||
pkg.types ||
Expand Down Expand Up @@ -78,15 +78,15 @@ const findTestFiles = async (typingsFilePath: string, options: Options & {config
*
* @returns A promise which resolves the diagnostics of the type definition.
*/
export default async (options: Options = {cwd: process.cwd()}) => {
export default async (options: Options = {cwd: process.cwd()}): Promise<Diagnostic[]> => {
const pkgResult = await readPkgUp({cwd: options.cwd});

if (!pkgResult) {
throw new Error('No `package.json` file found. Make sure you are running the command in a Node.js project.');
}

const pkg = pkgResult.packageJson;
const config = loadConfig(pkg as any, options.cwd);
const pkg = pkgResult.packageJson as PackageJsonWithTsdConfig;
const config = loadConfig(pkg, options.cwd);

// Look for a typings file, otherwise use `index.d.ts` in the root directory. If the file is not found, throw an error.
const typingsFile = await findTypingsFile(pkg, options);
Expand Down
11 changes: 7 additions & 4 deletions source/lib/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {CompilerOptions} from '@tsd/typescript';
import {NormalizedPackageJson} from 'read-pkg-up';

export interface RawCompilerOptions {
[option: string]: any;
}
export type RawCompilerOptions = Record<string, any>;

export interface Config<Options = CompilerOptions> {
directory: string;
Expand All @@ -11,9 +10,13 @@ export interface Config<Options = CompilerOptions> {

export type RawConfig = Partial<Config<RawCompilerOptions>>;

export type PackageJsonWithTsdConfig = NormalizedPackageJson & {
tsd?: RawConfig;
};

export interface Context {
cwd: string;
pkg: any;
pkg: PackageJsonWithTsdConfig;
typingsFile: string;
testFiles: string[];
config: Config;
Expand Down
2 changes: 1 addition & 1 deletion source/lib/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const extractAssertions = (program: Program): Map<Assertion, Set<CallExpr
if (assertionFnNames.has(identifier)) {
const assertion = identifier as Assertion;

const nodes = assertions.get(assertion) || new Set<CallExpression>();
const nodes = assertions.get(assertion) ?? new Set<CallExpression>();

nodes.add(node);

Expand Down
2 changes: 1 addition & 1 deletion source/lib/rules/files-property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default (context: Context): Diagnostic[] => {
function processGitIgnoreStylePatterns(patterns: readonly string[]): string[] {
const processedPatterns = patterns
.map(pattern => {
const [negatePatternMatch] = pattern.match(/^!+/) || [];
const [negatePatternMatch] = /^!+/.exec(pattern) ?? [];
const negationMarkersCount = negatePatternMatch ? negatePatternMatch.length : 0;

return [
Expand Down
6 changes: 3 additions & 3 deletions source/lib/utils/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {TypeChecker, Expression, isCallLikeExpression, JSDocTagInfo} from '@tsd/
* @return A unique Set of JSDoc tags or `undefined` if they couldn't be resolved.
*/
export const resolveJSDocTags = (checker: TypeChecker, expression: Expression): Map<string, JSDocTagInfo> | undefined => {
const ref = isCallLikeExpression(expression)
? checker.getResolvedSignature(expression)
: checker.getSymbolAtLocation(expression);
const ref = isCallLikeExpression(expression) ?
checker.getResolvedSignature(expression) :
checker.getSymbolAtLocation(expression);

if (!ref) {
return;
Expand Down
5 changes: 3 additions & 2 deletions source/test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ test('includes extended config files along with found ones', async t => {
test('errors in libs from node_modules are not reported', async t => {
const diagnostics = await tsd({cwd: path.join(__dirname, 'fixtures/exclude-node-modules')});

const [nodeModuleDiagnostics, testFileDiagnostics, otherDiagnostics] = diagnostics.reduce(
const [nodeModuleDiagnostics, testFileDiagnostics, otherDiagnostics] = diagnostics.reduce<Diagnostic[][]>(
([nodeModuleDiags, testFileDiags, otherDiags], diagnostic) => {
if (/[/\\]node_modules[/\\]/.test(diagnostic.fileName)) {
nodeModuleDiags.push(diagnostic);
Expand All @@ -379,9 +379,10 @@ test('errors in libs from node_modules are not reported', async t => {
} else {
otherDiags.push(diagnostic);
}

return [nodeModuleDiags, testFileDiags, otherDiags];
},
[[], [], []] as Diagnostic[][]
[[], [], []]
);

t.deepEqual(
Expand Down
1 change: 1 addition & 0 deletions source/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module 'eslint-formatter-pretty';
Loading

0 comments on commit 28195d6

Please sign in to comment.