Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat(eslint-plugin): add config all.json (#313)
  • Loading branch information
ldrick authored and bradzacher committed May 15, 2019
1 parent 8c8497c commit 67537b8
Show file tree
Hide file tree
Showing 19 changed files with 389 additions and 109 deletions.
1 change: 0 additions & 1 deletion .prettierignore
Expand Up @@ -3,7 +3,6 @@
**/coverage
**/shared-fixtures
**/tests/integration/fixtures/**/*
**/lib/configs/recommended.json
**/.vscode
**/.nyc_output
packages/eslint-plugin-tslint/tests/test-tslint-rules-directory/alwaysFailRule.js
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/README.md
Expand Up @@ -161,7 +161,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e
| [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string. (`restrict-plus-operands` from TSLint) | | | :thought_balloon: |
| [`@typescript-eslint/semi`](./docs/rules/semi.md) | Require or disallow semicolons instead of ASI | | :wrench: | |
| [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations (`typedef-whitespace` from TSLint) | :heavy_check_mark: | :wrench: | |
| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope. (`no-unbound-method` from TSLint) | :heavy_check_mark: | | :thought_balloon: |
| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope. (`no-unbound-method` from TSLint) | | | :thought_balloon: |
| [`@typescript-eslint/prefer-regexp-exec`](./docs/rules/prefer-regexp-exec.md) | Enforce to use `RegExp#exec` over `String#match` | | | :thought_balloon: |
| [`@typescript-eslint/unified-signatures`](./docs/rules/unified-signatures.md) | Warns for any two overloads that could be unified into one. (`unified-signatures` from TSLint) | | | |

Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin/package.json
Expand Up @@ -29,10 +29,11 @@
"clean": "rimraf dist/",
"docs": "eslint-docs",
"docs:check": "eslint-docs check",
"test": "jest --coverage",
"generate:configs": "ts-node --files tools/generate-configs.ts",
"format": "prettier --write \"./**/*.{ts,js,json,md}\" --ignore-path ../../.prettierignore",
"prebuild": "npm run clean",
"recommended:update": "ts-node tools/update-recommended.ts",
"test": "jest --coverage",
"typecheck": "tsc --noEmit"
},
"dependencies": {
Expand All @@ -41,7 +42,6 @@
"eslint-utils": "^1.3.1",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^2.0.1",
"requireindex": "^1.2.0",
"tsutils": "^3.7.0"
},
"devDependencies": {
Expand Down
64 changes: 64 additions & 0 deletions packages/eslint-plugin/src/configs/all.json
@@ -0,0 +1,64 @@
{
"extends": "./configs/base.json",
"rules": {
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-ignore": "error",
"@typescript-eslint/ban-types": "error",
"camelcase": "off",
"@typescript-eslint/camelcase": "error",
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/explicit-function-return-type": "error",
"@typescript-eslint/explicit-member-accessibility": "error",
"@typescript-eslint/func-call-spacing": "error",
"@typescript-eslint/generic-type-naming": "error",
"indent": "off",
"@typescript-eslint/indent": "error",
"@typescript-eslint/interface-name-prefix": "error",
"@typescript-eslint/member-delimiter-style": "error",
"@typescript-eslint/member-naming": "error",
"@typescript-eslint/member-ordering": "error",
"@typescript-eslint/no-angle-bracket-type-assertion": "error",
"no-array-constructor": "off",
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-extra-parens": "error",
"@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-magic-numbers": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "error",
"@typescript-eslint/no-object-literal-type-assertion": "error",
"@typescript-eslint/no-parameter-properties": "error",
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/no-this-alias": "error",
"@typescript-eslint/no-triple-slash-reference": "error",
"@typescript-eslint/no-type-alias": "error",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-use-before-define": "error",
"no-useless-constructor": "off",
"@typescript-eslint/no-useless-constructor": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "error",
"@typescript-eslint/prefer-function-type": "error",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-interface": "error",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/prefer-regexp-exec": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"@typescript-eslint/semi": "error",
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unbound-method": "error",
"@typescript-eslint/unified-signatures": "error"
}
}
7 changes: 7 additions & 0 deletions packages/eslint-plugin/src/configs/base.json
@@ -0,0 +1,7 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module"
},
"plugins": ["@typescript-eslint"]
}
6 changes: 1 addition & 5 deletions packages/eslint-plugin/src/configs/recommended.json
@@ -1,9 +1,5 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"extends": "./configs/base.json",
"rules": {
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": "error",
Expand Down
20 changes: 6 additions & 14 deletions packages/eslint-plugin/src/index.ts
@@ -1,23 +1,15 @@
import requireIndex from 'requireindex';
import path from 'path';
import rules from './rules';

import all from './configs/all.json';
import base from './configs/base.json';
import recommended from './configs/recommended.json';
import eslintRecommended from './configs/eslint-recommended';

const rules = requireIndex(path.join(__dirname, 'rules'));
// eslint expects the rule to be on rules[name], not rules[name].default
const rulesWithoutDefault = Object.keys(rules).reduce<Record<string, any>>(
(acc, ruleName) => {
acc[ruleName] = rules[ruleName].default;
return acc;
},
{},
);

// import all rules in lib/rules
export = {
rules: rulesWithoutDefault,
rules,
configs: {
all,
base,
recommended,
'eslint-recommended': eslintRecommended,
},
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/rules/ban-ts-ignore.ts
Expand Up @@ -8,7 +8,7 @@ export default util.createRule({
description: 'Bans “// @ts-ignore” comments from being used.',
tslintRuleName: 'ban-ts-ignore',
category: 'Best Practices',
recommended: 'error',
recommended: false,
},
schema: [],
messages: {
Expand Down
111 changes: 111 additions & 0 deletions packages/eslint-plugin/src/rules/index.ts
@@ -0,0 +1,111 @@
import adjacentOverloadSignatures from './adjacent-overload-signatures';
import arrayType from './array-type';
import awaitThenable from './await-thenable';
import banTsIgnore from './ban-ts-ignore';
import banTypes from './ban-types';
import camelcase from './camelcase';
import classNameCasing from './class-name-casing';
import explicitFunctionReturnType from './explicit-function-return-type';
import explicitMemberAccessibility from './explicit-member-accessibility';
import funcCallSpacing from './func-call-spacing';
import genericTypeNaming from './generic-type-naming';
import indent from './indent';
import interfaceNamePrefix from './interface-name-prefix';
import memberDelimiterStyle from './member-delimiter-style';
import memberNaming from './member-naming';
import memberOrdering from './member-ordering';
import noAngleBracketTypeAssertion from './no-angle-bracket-type-assertion';
import noArrayConstructor from './no-array-constructor';
import noEmptyInterface from './no-empty-interface';
import noExplicitAny from './no-explicit-any';
import noExtraParens from './no-extra-parens';
import noExtraneousClass from './no-extraneous-class';
import noForInArray from './no-for-in-array';
import noInferrableTypes from './no-inferrable-types';
import noMagicNumbers from './no-magic-numbers';
import noMisusedNew from './no-misused-new';
import noNamespace from './no-namespace';
import noNonNullAssertion from './no-non-null-assertion';
import noObjectLiteralTypeAssertion from './no-object-literal-type-assertion';
import noParameterProperties from './no-parameter-properties';
import noRequireImports from './no-require-imports';
import noThisAlias from './no-this-alias';
import noTripleSlashReference from './no-triple-slash-reference';
import noTypeAlias from './no-type-alias';
import noUnnecessaryQualifier from './no-unnecessary-qualifier';
import noUnnecessaryTypeAssertion from './no-unnecessary-type-assertion';
import noUnusedVars from './no-unused-vars';
import noUseBeforeDefine from './no-use-before-define';
import noUselessConstructor from './no-useless-constructor';
import noVarRequires from './no-var-requires';
import preferForOf from './prefer-for-of';
import preferFunctionType from './prefer-function-type';
import preferIncludes from './prefer-includes';
import preferInterface from './prefer-interface';
import preferNamespaceKeyword from './prefer-namespace-keyword';
import preferRegexpExec from './prefer-regexp-exec';
import preferStringStartsEndsWith from './prefer-string-starts-ends-with';
import promiseFunctionAsync from './promise-function-async';
import requireArraySortCompare from './require-array-sort-compare';
import restrictPlusOperands from './restrict-plus-operands';
import semi from './semi';
import typeAnnotationSpacing from './type-annotation-spacing';
import unboundMethod from './unbound-method';
import unifiedSignatures from './unified-signatures';

export default {
'adjacent-overload-signatures': adjacentOverloadSignatures,
'array-type': arrayType,
'await-thenable': awaitThenable,
'ban-ts-ignore': banTsIgnore,
'ban-types': banTypes,
camelcase: camelcase,
'class-name-casing': classNameCasing,
'explicit-function-return-type': explicitFunctionReturnType,
'explicit-member-accessibility': explicitMemberAccessibility,
'func-call-spacing': funcCallSpacing,
'generic-type-naming': genericTypeNaming,
indent: indent,
'interface-name-prefix': interfaceNamePrefix,
'member-delimiter-style': memberDelimiterStyle,
'member-naming': memberNaming,
'member-ordering': memberOrdering,
'no-angle-bracket-type-assertion': noAngleBracketTypeAssertion,
'no-array-constructor': noArrayConstructor,
'no-empty-interface': noEmptyInterface,
'no-explicit-any': noExplicitAny,
'no-extra-parens': noExtraParens,
'no-extraneous-class': noExtraneousClass,
'no-for-in-array': noForInArray,
'no-inferrable-types': noInferrableTypes,
'no-magic-numbers': noMagicNumbers,
'no-misused-new': noMisusedNew,
'no-namespace': noNamespace,
'no-non-null-assertion': noNonNullAssertion,
'no-object-literal-type-assertion': noObjectLiteralTypeAssertion,
'no-parameter-properties': noParameterProperties,
'no-require-imports': noRequireImports,
'no-this-alias': noThisAlias,
'no-triple-slash-reference': noTripleSlashReference,
'no-type-alias': noTypeAlias,
'no-unnecessary-qualifier': noUnnecessaryQualifier,
'no-unnecessary-type-assertion': noUnnecessaryTypeAssertion,
'no-unused-vars': noUnusedVars,
'no-use-before-define': noUseBeforeDefine,
'no-useless-constructor': noUselessConstructor,
'no-var-requires': noVarRequires,
'prefer-for-of': preferForOf,
'prefer-function-type': preferFunctionType,
'prefer-includes': preferIncludes,
'prefer-interface': preferInterface,
'prefer-namespace-keyword': preferNamespaceKeyword,
'prefer-regexp-exec': preferRegexpExec,
'prefer-string-starts-ends-with': preferStringStartsEndsWith,
'promise-function-async': promiseFunctionAsync,
'require-array-sort-compare': requireArraySortCompare,
'restrict-plus-operands': restrictPlusOperands,
semi: semi,
'type-annotation-spacing': typeAnnotationSpacing,
'unbound-method': unboundMethod,
'unified-signatures': unifiedSignatures,
};
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/rules/no-require-imports.ts
Expand Up @@ -9,7 +9,7 @@ export default util.createRule({
description: 'Disallows invocation of `require()`.',
tslintName: 'no-require-imports',
category: 'Best Practices',
recommended: 'error',
recommended: false,
},
schema: [],
messages: {
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/rules/promise-function-async.ts
Expand Up @@ -21,7 +21,7 @@ export default util.createRule<Options, MessageIds>({
'Requires any function or method that returns a Promise to be marked async.',
tslintName: 'promise-function-async',
category: 'Best Practices',
recommended: 'error',
recommended: false,
},
messages: {
missingAsync: 'Functions that return promises must be async.',
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/rules/unbound-method.ts
Expand Up @@ -26,7 +26,7 @@ export default util.createRule<Options, MessageIds>({
description:
'Enforces unbound methods are called with their expected scope.',
tslintName: 'no-unbound-method',
recommended: 'error',
recommended: false,
},
messages: {
unbound:
Expand Down
46 changes: 46 additions & 0 deletions packages/eslint-plugin/tests/configs/all.test.ts
@@ -0,0 +1,46 @@
import rules from '../../src/rules';
import allConfig from '../../src/configs/all.json';
import { TSESLint } from '@typescript-eslint/experimental-utils';

interface IndexRules {
[name: string]: TSESLint.RuleModule<string, any, any>;
}
interface JsonRules {
[name: string]: string;
}

describe('all.json config', () => {
const RULE_NAME_PREFIX = '@typescript-eslint/';

const typedRules: IndexRules = rules;
const notDeprecatedRuleNames = Object.keys(typedRules).reduce<string[]>(
(collection, name) => {
if (!typedRules[name].meta.deprecated) {
collection.push(`${RULE_NAME_PREFIX}${name}`);
}
return collection;
},
[],
);

// with end of Node.js 6 support, we can use Object.entries(allConfig.rules) here
const configRules: JsonRules = allConfig.rules;
const typescriptEslintConfigRules = Object.keys(configRules).filter(name =>
name.startsWith(RULE_NAME_PREFIX),
);
const typescriptEslintConfigRuleValues = typescriptEslintConfigRules.map(
name => configRules[name],
);

it('contains all @typescript-eslint/eslint-plugin rule modules, except the deprecated ones', () => {
expect(notDeprecatedRuleNames).toEqual(
expect.arrayContaining(typescriptEslintConfigRules),
);
});

it('has all containing @typescript-eslint/eslint-plugin rules enabled with "error"', () => {
expect(['error']).toEqual(
expect.arrayContaining(typescriptEslintConfigRuleValues),
);
});
});
24 changes: 24 additions & 0 deletions packages/eslint-plugin/tests/index.test.ts
@@ -0,0 +1,24 @@
import fs from 'fs';
import path from 'path';

import eslintPlugin from '../src';
import rules from '../src/rules';

describe('eslint-plugin ("./src/index.ts")', () => {
const ruleKeys = Object.keys(rules);
const eslintPluginRuleKeys = Object.keys(eslintPlugin.rules);

const configs = fs
.readdirSync('./src/configs')
.filter(file => ['.json', '.ts'].includes(path.extname(file).toLowerCase()))
.map(file => path.basename(file, path.extname(file)));
const eslintPluginConfigKeys = Object.keys(eslintPlugin.configs);

it('exports all available rules', () => {
expect(ruleKeys).toEqual(expect.arrayContaining(eslintPluginRuleKeys));
});

it('exports all available configs', () => {
expect(configs).toEqual(expect.arrayContaining(eslintPluginConfigKeys));
});
});
14 changes: 14 additions & 0 deletions packages/eslint-plugin/tests/rules/index.test.ts
@@ -0,0 +1,14 @@
import fs from 'fs';

import rules from '../../src/rules';

describe('./src/rules/index.ts', () => {
const ruleNames = Object.keys(rules).map(name => `${name}.ts`);
const files = fs
.readdirSync('./src/rules')
.filter(file => file !== 'index.ts' && file.endsWith('.ts'));

it('imports all available rule modules', () => {
expect(ruleNames).toEqual(expect.arrayContaining(files));
});
});

0 comments on commit 67537b8

Please sign in to comment.