From 3f6a3dfce6ba19d2eb555e9e0a3932e2ba708aa1 Mon Sep 17 00:00:00 2001 From: "Michael A. Lavina" Date: Wed, 10 Jan 2018 17:29:52 -0500 Subject: [PATCH] feat(configuration): set js rules to all valid active rules jsRules can now be a boolean. If it is set to true then parseConfig file, will copy over all active rules that can be applied to js to the jsRules configuration. --- docs/usage/configuration/index.md | 2 +- src/configuration.ts | 33 +++++++++++++++++++--- test/configurationTests.ts | 47 +++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/docs/usage/configuration/index.md b/docs/usage/configuration/index.md index 55f6f407d39..7884399e47c 100644 --- a/docs/usage/configuration/index.md +++ b/docs/usage/configuration/index.md @@ -29,7 +29,7 @@ A path to a directory or an array of paths to directories of [custom rules][2]. - A boolean value may be specified instead of the above object, and is equivalent to setting no options with default severity. - Any rules specified in this block will override those configured in any base configuration being extended. - [Check out the full rules list here][3]. -* `jsRules?: any`: Same format as `rules`. These rules are applied to `.js` and `.jsx` files. +* `jsRules?: any | boolean`: Same format as `rules` or explicit `true` to copy all valid active rules from rules. These rules are applied to `.js` and `.jsx` files. * `defaultSeverity?: "error" | "warning" | "off"`: The severity level that is applied to rules in this config file as well as rules in any inherited config files which have their severity set to "default". If undefined, "error" is used as the defaultSeverity. * `linterOptions?: { exclude?: string[] }`: - `exclude: string[]`: An array of globs. Any file matching these globs will not be linted. All exclude patterns are relative to the configuration file they were specified in. diff --git a/src/configuration.ts b/src/configuration.ts index 6de1dd575a6..9c315d59c64 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -23,6 +23,7 @@ import * as resolve from "resolve"; import { FatalError, showWarningOnce } from "./error"; import { IOptions, RuleSeverity } from "./language/rule/rule"; +import { findRule } from "./ruleLoader"; import { arrayify, hasOwnProperty, stripComments } from "./utils"; export interface IConfigurationFile { @@ -462,7 +463,7 @@ export interface RawConfigFile { rulesDirectory?: string | string[]; defaultSeverity?: string; rules?: RawRulesConfig; - jsRules?: RawRulesConfig; + jsRules?: RawRulesConfig | boolean; } export interface RawRulesConfig { [key: string]: RawRuleConfig; @@ -510,12 +511,18 @@ export function parseConfigFile( } function parse(config: RawConfigFile, dir?: string): IConfigurationFile { + const rulesDirectory: string | string[] = getRulesDirectories(config.rulesDirectory, dir); + const rules = parseRules(config.rules); + const jsRules = typeof config.jsRules === "boolean" ? + filterValidJsRules(rules, config.jsRules, rulesDirectory) : + parseRules(config.jsRules); + return { extends: arrayify(config.extends), - jsRules: parseRules(config.jsRules), + jsRules, linterOptions: parseLinterOptions(config.linterOptions, dir), - rules: parseRules(config.rules), - rulesDirectory: getRulesDirectories(config.rulesDirectory, dir), + rules, + rulesDirectory, }; } @@ -531,6 +538,24 @@ export function parseConfigFile( return map; } + function filterValidJsRules(rules: Map>, + copyRulestoJsRules = false, + rulesDirectory?: string | string[]): Map> { + const validJsRules = new Map>(); + if (copyRulestoJsRules) { + rules.forEach((ruleOptions, ruleName) => { + if (ruleOptions.ruleSeverity !== "off") { + const Rule = findRule(ruleName, rulesDirectory); + if ((Rule !== undefined && (Rule.metadata === undefined || !Rule.metadata.typescriptOnly))) { + validJsRules.set(ruleName, ruleOptions); + } + } + }); + } + + return validJsRules; + } + function parseLinterOptions(raw: RawConfigFile["linterOptions"], dir?: string): IConfigurationFile["linterOptions"] { if (raw === undefined || raw.exclude === undefined) { return {}; diff --git a/test/configurationTests.ts b/test/configurationTests.ts index 3d98ef68609..36e9c90b597 100644 --- a/test/configurationTests.ts +++ b/test/configurationTests.ts @@ -119,6 +119,53 @@ describe("Configuration", () => { }, ); }); + + it("parses jsRules when jsRules is a config", () => { + const rawConfig: RawConfigFile = { + jsRules: { + a: true, + }, + }; + + const expected = getEmptyConfig(); + expected.jsRules.set("a", { ruleArguments: [], ruleSeverity: "error" }); + assertConfigEquals(parseConfigFile(rawConfig), expected); + }); + + it("copies valid rules to jsRules when jsRules is a boolean", () => { + let rawConfig: RawConfigFile = { + jsRules: true, + rules: {}, + }; + + const expected = getEmptyConfig(); + assertConfigEquals(parseConfigFile(rawConfig), expected); + + rawConfig = { + jsRules: true, + rules: { + eofline: true, + }, + }; + + let {rules, jsRules} = parseConfigFile(rawConfig); + assert.deepEqual(demap(rules), demap(jsRules)); + + rawConfig = { + jsRules: true, + rules: { + eofline: true, + typedef: true, + }, + }; + + ({rules, jsRules} = parseConfigFile(rawConfig)); + assert(jsRules.has("eofline")); + assert(!jsRules.has("typedef")); + + rules.delete("typedef"); + assert.deepEqual(demap(rules), demap(jsRules)); + }); }); describe("defaultSeverity", () => {