diff --git a/.project b/.project
deleted file mode 100644
index b4816234ede..00000000000
--- a/.project
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
- tslint
-
-
-
-
-
- com.palantir.typescript.typeScriptBuilder
-
-
-
-
-
- com.palantir.typescript.typeScriptNature
-
-
-
- 1414432614134
-
- 22
-
- org.eclipse.ui.ide.multiFilter
- 1.0-name-matches-false-false-tslint.d.ts
-
-
-
- 1414431975439
- test
- 10
-
- org.eclipse.ui.ide.multiFilter
- 1.0-name-matches-true-false-files
-
-
-
-
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4303c136ff3..c9f49572aa7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,42 @@
Change Log
===
+
+
v4.5.1-dev.0
---
diff --git a/circle.yml b/circle.yml
index 4a2f85346de..6f0627e6a30 100644
--- a/circle.yml
+++ b/circle.yml
@@ -10,7 +10,7 @@ dependencies:
- yarn
test:
override:
- - case $CIRCLE_NODE_INDEX in [0-2]) yarn verify ;; 3) npm run clean && yarn compile && yarn add typescript@2.0.10 && yarn test ;; esac:
+ - case $CIRCLE_NODE_INDEX in [0-1]) yarn verify ;; 2) npm run clean && yarn compile && yarn add typescript@2.0.10 && yarn test ;; 3) npm run clean && yarn compile && yarn add typescript@next && yarn test ;; esac:
parallel: true
deployment:
npm-latest:
diff --git a/docs/_data/formatters.json b/docs/_data/formatters.json
index 1617406a14b..dec1dacbcce 100644
--- a/docs/_data/formatters.json
+++ b/docs/_data/formatters.json
@@ -36,13 +36,13 @@
"formatterName": "pmd",
"description": "Formats errors as through they were PMD output.",
"descriptionDetails": "Imitates the XML output from PMD. All errors have a priority of 1.",
- "sample": "\n\n \n \n \n",
+ "sample": "\n\n \n \n \n",
"consumer": "machine"
},
{
"formatterName": "prose",
"description": "The default formatter which outputs simple human-readable messages.",
- "sample": "myFile.ts[1, 14]: Missing semicolon",
+ "sample": "ERROR: myFile.ts[1, 14]: Missing semicolon",
"consumer": "human"
},
{
@@ -56,7 +56,7 @@
"formatterName": "verbose",
"description": "The human-readable formatter which includes the rule name in messages.",
"descriptionDetails": "The output is the same as the prose formatter with the rule name included",
- "sample": "(semicolon) myFile.ts[1, 14]: Missing semicolon",
+ "sample": "ERROR: (semicolon) myFile.ts[1, 14]: Missing semicolon",
"consumer": "human"
},
{
diff --git a/docs/_includes/rule_list.html b/docs/_includes/rule_list.html
index dd990de3029..dd4ee71c380 100644
--- a/docs/_includes/rule_list.html
+++ b/docs/_includes/rule_list.html
@@ -1,6 +1,21 @@
-
+
\ No newline at end of file
diff --git a/docs/_layouts/rule.html b/docs/_layouts/rule.html
index de7b8ca3c8c..9299ab37db1 100644
--- a/docs/_layouts/rule.html
+++ b/docs/_layouts/rule.html
@@ -9,11 +9,21 @@
Rationale
{{page.rationale | markdownify}}
{% endif %}
-{% if page.requiresTypeInfo %}
- Note:
- This rule requires type info to run
-{% endif %}
+{% if page.typescriptOnly or page.hasFix or page.requiresTypeInfo %}
+ Notes:
+
+ {% if page.typescriptOnly %}
+
TS Only
+ {% endif %}
+ {% if page.hasFix %}
+
Has Fixer
+ {% endif %}
+ {% if page.requiresTypeInfo %}
+
Requires Type Info
+ {% endif %}
+
+{% endif %}
Config
{{page.optionsDescription | markdownify}}
diff --git a/docs/_sass/_base.scss b/docs/_sass/_base.scss
index 52b4aea6e1d..52e6af050e6 100644
--- a/docs/_sass/_base.scss
+++ b/docs/_sass/_base.scss
@@ -70,3 +70,106 @@ figcaption {
}
}
}
+
+
+/**
+ * Rules & Feature Badges
+ */
+ .rules-list {
+ list-style: none;
+ margin: 0 !important; //need to override the `main-content ul` selector
+
+ > li {
+ &:nth-child(odd) {
+ a {
+ background-color: rgba(0, 0, 0, .03);
+ }
+ }
+
+ a {
+ display: block;
+ border-left: 3px solid transparent;
+ text-decoration: none;
+ padding: .75rem;
+
+ &:hover {
+ background-color: rgba(0, 0, 0,.075);
+ border-left-color: #159957;
+ }
+ }
+ }
+ }
+
+ .rule-features {
+ //This is the container for a list of feature badges
+ display: -webkit-box;
+ display: -moz-box;
+ display: -ms-flexbox;
+ display: -webkit-flex;
+ display: flex;
+ }
+
+ .feature {
+ //This is the setup for the a feature badge
+ display: inline-block;
+ margin-right: 2px;
+ padding: 2px 4px;
+ font-weight: 700;
+ line-height: 1;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border: 1px solid transparent;
+ border-radius: .25rem;
+ cursor: help;
+
+ &:before {
+ //This is the setup for the icon that appears inside the badge
+ display: inline-block;
+ margin-right: 2px;
+ }
+
+ &.feature-sm {
+ //This class is added to make the feature badge smaller. This is used on the rules list
+ padding: 1px 3px;
+ font-size: 75%;
+ }
+
+ &.feature-ts-only {
+ //This feature badge is added to rules that are "TypeScript Only"
+ background-color: #FCF8E3;
+ border-color: #FAF2CC;
+ color: #8A6D3B;
+
+ &:before {
+ content: "\1F4C4"; //"page facing up" icon - http://www.fileformat.info/info/unicode/char/1F4C4/index.htm
+ }
+ }
+
+ &.feature-fixer {
+ //This feature badge is added to rules that have an auto-fixer
+ background-color: #DFF0D8;
+ border-color: #D0E9C6;
+ color: #3C763D;
+
+ &:before {
+ content: "\1f527"; //"wrench" icon - http://www.fileformat.info/info/unicode/char/1f527/index.htm
+ }
+ }
+
+ &.feature-requires-type-info {
+ //This feature badge is added to rules that require type information
+ background-color: #F2DEDE;
+ border-color: #EBCCCC;
+ color: #A94442;
+
+ &:before {
+ content: "\2139"; //"information source" icon - http://www.fileformat.info/info/unicode/char/2139/index.htm
+ //Surround it with a blue circle
+ border-radius: 50%;
+ background: #0078D7;
+ color: #FFF;
+ width: 1em;
+ }
+ }
+ }
diff --git a/docs/formatters/pmd/index.html b/docs/formatters/pmd/index.html
index 6ebb32c7f4c..1b7a53b8d21 100644
--- a/docs/formatters/pmd/index.html
+++ b/docs/formatters/pmd/index.html
@@ -6,7 +6,7 @@
-
+
consumer: machine
diff --git a/docs/formatters/prose/index.html b/docs/formatters/prose/index.html
index 054e16dd3dd..f01f4afd6f7 100644
--- a/docs/formatters/prose/index.html
+++ b/docs/formatters/prose/index.html
@@ -1,7 +1,7 @@
---
formatterName: prose
description: The default formatter which outputs simple human-readable messages.
-sample: 'myFile.ts[1, 14]: Missing semicolon'
+sample: 'ERROR: myFile.ts[1, 14]: Missing semicolon'
consumer: human
layout: formatter
title: 'Formatter: prose'
diff --git a/docs/formatters/verbose/index.html b/docs/formatters/verbose/index.html
index ad2fd1d4c29..5a7de802b60 100644
--- a/docs/formatters/verbose/index.html
+++ b/docs/formatters/verbose/index.html
@@ -2,7 +2,7 @@
formatterName: verbose
description: The human-readable formatter which includes the rule name in messages.
descriptionDetails: The output is the same as the prose formatter with the rule name included
-sample: '(semicolon) myFile.ts[1, 14]: Missing semicolon'
+sample: 'ERROR: (semicolon) myFile.ts[1, 14]: Missing semicolon'
consumer: human
layout: formatter
title: 'Formatter: verbose'
diff --git a/package.json b/package.json
index d530d3afb2d..500a92aa0f5 100644
--- a/package.json
+++ b/package.json
@@ -43,11 +43,10 @@
"glob": "^7.1.1",
"optimist": "~0.6.0",
"resolve": "^1.1.7",
- "tsutils": "^1.1.0",
- "update-notifier": "^2.0.0"
+ "tsutils": "^1.1.0"
},
"peerDependencies": {
- "typescript": ">=2.0.0-dev || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev"
+ "typescript": ">=2.0.0 || >=2.0.0-dev || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev"
},
"devDependencies": {
"@types/babel-code-frame": "^6.20.0",
@@ -62,7 +61,6 @@
"@types/node": "^6.0.56",
"@types/optimist": "0.0.29",
"@types/resolve": "0.0.4",
- "@types/update-notifier": "^1.0.0",
"chai": "^3.5.0",
"github": "^8.1.1",
"js-yaml": "^3.7.0",
diff --git a/scripts/assertMinCircleNodes.js b/scripts/assertMinCircleNodes.js
index 449864e72e7..bf73b44cc9c 100644
--- a/scripts/assertMinCircleNodes.js
+++ b/scripts/assertMinCircleNodes.js
@@ -1,7 +1,7 @@
var requiredNodes = 4;
var nodes = parseInt(process.argv[2], 10);
if (requiredNodes != null && requiredNodes > nodes) {
- console.error("ERROR: You must run CircleCI with 4 parallel nodes");
+ console.error("ERROR: You must run CircleCI with " + requiredNodes + " parallel nodes");
console.error(" This ensures that different environments are tested for TSLint compatibility");
console.error(" https://circleci.com/gh//tslint/edit#parallel-builds");
process.exit(1);
diff --git a/src/configs/latest.ts b/src/configs/latest.ts
index 928abec07e0..7cc43241c04 100644
--- a/src/configs/latest.ts
+++ b/src/configs/latest.ts
@@ -23,11 +23,13 @@ export const rules = {
"no-angle-bracket-type-assertion": true,
// added in v4.1
- "only-arrow-functions": [true,
- "allow-declarations",
- // the following option was added in 4.1
- "allow-named-functions",
- ],
+ "only-arrow-functions": {
+ options: [
+ "allow-declarations",
+ // the following option was added in 4.1
+ "allow-named-functions",
+ ],
+ },
"prefer-const": true,
// added in v4.2
@@ -38,13 +40,15 @@ export const rules = {
// added in v4.3
"import-spacing": true,
- "space-before-function-paren": [true, {
- "anonymous": "never",
- "asyncArrow": "always",
- "constructor": "never",
- "method": "never",
- "named": "never",
- }],
+ "space-before-function-paren": {
+ options: {
+ "anonymous": "never",
+ "asyncArrow": "always",
+ "constructor": "never",
+ "method": "never",
+ "named": "never",
+ },
+ },
"typeof-compare": true,
"unified-signatures": true,
@@ -54,15 +58,16 @@ export const rules = {
"no-misused-new": true,
// added in v4.5
- "ban-types": [
- true,
- ["Object", "Avoid using the `Object` type. Did you mean `object`?"],
- ["Function", "Avoid using the `Function` type. Prefer a specific function type, like `() => void`."],
- ["Boolean", "Avoid using the `Boolean` type. Did you mean `boolean`?"],
- ["Number", "Avoid using the `Number` type. Did you mean `number`?"],
- ["String", "Avoid using the `String` type. Did you mean `string`?"],
- ["Symbol", "Avoid using the `Symbol` type. Did you mean `symbol`?"],
- ],
+ "ban-types": {
+ options: [
+ ["Object", "Avoid using the `Object` type. Did you mean `object`?"],
+ ["Function", "Avoid using the `Function` type. Prefer a specific function type, like `() => void`."],
+ ["Boolean", "Avoid using the `Boolean` type. Did you mean `boolean`?"],
+ ["Number", "Avoid using the `Number` type. Did you mean `number`?"],
+ ["String", "Avoid using the `String` type. Did you mean `string`?"],
+ ["Symbol", "Avoid using the `Symbol` type. Did you mean `symbol`?"],
+ ],
+ },
"no-duplicate-super": true,
};
// tslint:enable object-literal-sort-keys
diff --git a/src/configs/recommended.ts b/src/configs/recommended.ts
index 23e3a64f81b..9247df857dc 100644
--- a/src/configs/recommended.ts
+++ b/src/configs/recommended.ts
@@ -15,47 +15,62 @@
* limitations under the License.
*/
-/* tslint:disable:object-literal-key-quotes */
export const rules = {
"adjacent-overload-signatures": true,
- "align": [true,
- "parameters",
- "statements",
- ],
- "array-type": [true, "array-simple"],
+ "align": {
+ options: [
+ "parameters",
+ "statements",
+ ],
+ },
+ "array-type": {
+ options: ["array-simple"],
+ },
"arrow-parens": true,
"class-name": true,
- "comment-format": [true,
- "check-space",
- ],
+ "comment-format": {
+ options: ["check-space"],
+ },
"curly": true,
"cyclomatic-complexity": false,
"eofline": true,
"forin": true,
- "indent": [true, "spaces"],
- "interface-name": [true, "always-prefix"],
+ "indent": {
+ options: ["spaces"],
+ },
+ "interface-name": {
+ options: ["always-prefix"],
+ },
"jsdoc-format": true,
"label-position": true,
- "max-classes-per-file": [true, 1],
- "max-line-length": [true, 120],
+ "max-classes-per-file": {
+ options: [1],
+ },
+ "max-line-length": {
+ options: [120],
+ },
"member-access": true,
- "member-ordering": [true, {
- "order": "statics-first",
- }],
+ "member-ordering": {
+ options: {
+ order: "statics-first",
+ },
+ },
"new-parens": true,
"no-any": false,
"no-arg": true,
"no-bitwise": true,
"no-conditional-assignment": true,
"no-consecutive-blank-lines": true,
- "no-console": [true,
- "debug",
- "info",
- "log",
- "time",
- "timeEnd",
- "trace",
- ],
+ "no-console": {
+ options: [
+ "debug",
+ "info",
+ "log",
+ "time",
+ "timeEnd",
+ "trace",
+ ],
+ },
"no-construct": true,
"no-debugger": true,
"no-empty": true,
@@ -75,89 +90,122 @@ export const rules = {
"no-use-before-declare": false,
"no-var-keyword": true,
"no-var-requires": true,
- "object-literal-key-quotes": [true, "consistent-as-needed"],
+ "object-literal-key-quotes": {
+ options: ["consistent-as-needed"],
+ },
"object-literal-shorthand": true,
"object-literal-sort-keys": true,
- "one-line": [true,
- "check-catch",
- "check-else",
- "check-finally",
- "check-open-brace",
- "check-whitespace",
- ],
- "one-variable-per-declaration": [true,
- "ignore-for-loop",
- ],
- "only-arrow-functions": [true, "allow-declarations"],
- "ordered-imports": [true, {
- "import-sources-order": "case-insensitive",
- "named-imports-order": "case-insensitive",
- }],
+ "one-line": {
+ options: [
+ "check-catch",
+ "check-else",
+ "check-finally",
+ "check-open-brace",
+ "check-whitespace",
+ ],
+ },
+ "one-variable-per-declaration": {
+ options: ["ignore-for-loop"],
+ },
+ "only-arrow-functions": {
+ options: ["allow-declarations"],
+ },
+ "ordered-imports": {
+ options: {
+ "import-sources-order": "case-insensitive",
+ "named-imports-order": "case-insensitive",
+ },
+ },
"prefer-for-of": true,
- "quotemark": [true, "double", "avoid-escape"],
+ "quotemark": {
+ options: [
+ "double",
+ "avoid-escape",
+ ],
+ },
"radix": true,
- "semicolon": [true, "always"],
+ "semicolon": {
+ options: ["always"],
+ },
"switch-default": true,
- "trailing-comma": [true, {
- "multiline": "always",
- "singleline": "never",
- }],
- "triple-equals": [true, "allow-null-check"],
+ "trailing-comma": {
+ options: {
+ multiline: "always",
+ singleline: "never",
+ },
+ },
+ "triple-equals": {
+ options: ["allow-null-check"],
+ },
"typedef": false,
- "typedef-whitespace": [true, {
- "call-signature": "nospace",
- "index-signature": "nospace",
- "parameter": "nospace",
- "property-declaration": "nospace",
- "variable-declaration": "nospace",
- }, {
- "call-signature": "onespace",
- "index-signature": "onespace",
- "parameter": "onespace",
- "property-declaration": "onespace",
- "variable-declaration": "onespace",
- }],
+ "typedef-whitespace": {
+ options: [{
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace",
+ }, {
+ "call-signature": "onespace",
+ "index-signature": "onespace",
+ "parameter": "onespace",
+ "property-declaration": "onespace",
+ "variable-declaration": "onespace",
+ }],
+ },
"use-isnan": true,
- "variable-name": [true,
- "ban-keywords",
- "check-format",
- "allow-pascal-case",
- ],
- "whitespace": [true,
- "check-branch",
- "check-decl",
- "check-operator",
- "check-separator",
- "check-type",
- "check-typecast",
- ],
+ "variable-name": {
+ options: [
+ "ban-keywords",
+ "check-format",
+ "allow-pascal-case",
+ ],
+ },
+ "whitespace": {
+ options: [
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type",
+ "check-typecast",
+ ],
+ },
};
export const jsRules = {
- "align": [true,
- "parameters",
- "statements",
- ],
+ "align": {
+ options: [
+ "parameters",
+ "statements",
+ ],
+ },
"class-name": true,
"curly": true,
"eofline": true,
"forin": true,
- "indent": [true, "spaces"],
+ "indent": {
+ options: ["spaces"],
+ },
"jsdoc-format": true,
"label-position": true,
- "max-line-length": [true, 120],
+ "max-line-length": {
+ options: [120],
+ },
"new-parens": true,
"no-arg": true,
"no-bitwise": true,
"no-conditional-assignment": true,
"no-consecutive-blank-lines": true,
- "no-console": [true,
- "debug",
- "info",
- "log",
- "time",
- "timeEnd",
- "trace",
- ],
+ "no-console": {
+ options: [
+ "debug",
+ "info",
+ "log",
+ "time",
+ "timeEnd",
+ "trace",
+ ],
+ },
"no-construct": true,
"no-debugger": true,
"no-duplicate-variable": true,
@@ -173,38 +221,54 @@ export const jsRules = {
// disable this rule as it is very heavy performance-wise and not that useful
"no-use-before-declare": false,
"object-literal-sort-keys": true,
- "one-line": [true,
- "check-catch",
- "check-else",
- "check-finally",
- "check-open-brace",
- "check-whitespace",
- ],
- "one-variable-per-declaration": [true,
- "ignore-for-loop",
- ],
- "quotemark": [true, "double", "avoid-escape"],
+ "one-line": {
+ options: [
+ "check-catch",
+ "check-else",
+ "check-finally",
+ "check-open-brace",
+ "check-whitespace",
+ ],
+ },
+ "one-variable-per-declaration": {
+ options: ["ignore-for-loop"],
+ },
+ "quotemark": {
+ options: [
+ "double",
+ "avoid-escape",
+ ],
+ },
"radix": true,
- "semicolon": [true, "always"],
+ "semicolon": {
+ options: ["always"],
+ },
"switch-default": true,
- "trailing-comma": [true, {
- "multiline": "always",
- "singleline": "never",
- }],
- "triple-equals": [true, "allow-null-check"],
+ "trailing-comma": {
+ options: {
+ multiline: "always",
+ singleline: "never",
+ },
+ },
+ "triple-equals": {
+ options: ["allow-null-check"],
+ },
"use-isnan": true,
- "variable-name": [true,
- "ban-keywords",
- "check-format",
- "allow-pascal-case",
- ],
- "whitespace": [true,
- "check-branch",
- "check-decl",
- "check-operator",
- "check-separator",
- "check-type",
- "check-typecast",
- ],
+ "variable-name": {
+ options: [
+ "ban-keywords",
+ "check-format",
+ "allow-pascal-case",
+ ],
+ },
+ "whitespace": {
+ options: [
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type",
+ "check-typecast",
+ ],
+ },
};
-/* tslint:enable:object-literal-key-quotes */
diff --git a/src/configuration.ts b/src/configuration.ts
index 8e48c507e47..7b3e9bc0ac8 100644
--- a/src/configuration.ts
+++ b/src/configuration.ts
@@ -21,16 +21,17 @@ import * as path from "path";
import * as resolve from "resolve";
import { FatalError } from "./error";
-import {arrayify, objectify, stripComments} from "./utils";
+import { IOptions, RuleSeverity } from "./language/rule/rule";
+import { arrayify, objectify, stripComments } from "./utils";
export interface IConfigurationFile {
- extends?: string | string[];
- jsRules?: any;
+ extends: string[];
+ jsRules: Map>;
linterOptions?: {
typeCheck?: boolean,
};
- rulesDirectory?: string | string[];
- rules?: any;
+ rulesDirectory: string[];
+ rules: Map>;
}
export interface IConfigurationLoadResult {
@@ -39,11 +40,20 @@ export interface IConfigurationLoadResult {
}
export const CONFIG_FILENAME = "tslint.json";
-/* tslint:disable:object-literal-key-quotes */
-export const DEFAULT_CONFIG = {
- "extends": "tslint:recommended",
+
+export const DEFAULT_CONFIG: IConfigurationFile = {
+ extends: ["tslint:recommended"],
+ jsRules: new Map>(),
+ rules: new Map>(),
+ rulesDirectory: [],
+};
+
+export const EMPTY_CONFIG: IConfigurationFile = {
+ extends: [],
+ jsRules: new Map>(),
+ rules: new Map>(),
+ rulesDirectory: [],
};
-/* tslint:enable:object-literal-key-quotes */
const BUILT_IN_CONFIG = /^tslint:(.*)$/;
@@ -117,28 +127,28 @@ export function loadConfigurationFromPath(configFilePath?: string): IConfigurati
return DEFAULT_CONFIG;
} else {
const resolvedConfigFilePath = resolveConfigurationPath(configFilePath);
- let configFile: IConfigurationFile;
+ let rawConfigFile: any;
if (path.extname(resolvedConfigFilePath) === ".json") {
const fileContent = stripComments(fs.readFileSync(resolvedConfigFilePath)
.toString()
.replace(/^\uFEFF/, ""));
- configFile = JSON.parse(fileContent);
+ rawConfigFile = JSON.parse(fileContent);
} else {
- configFile = require(resolvedConfigFilePath);
+ rawConfigFile = require(resolvedConfigFilePath);
delete require.cache[resolvedConfigFilePath];
}
const configFileDir = path.dirname(resolvedConfigFilePath);
+ const configFile = parseConfigFile(rawConfigFile, configFileDir);
- configFile.rulesDirectory = getRulesDirectories(configFile.rulesDirectory, configFileDir);
// load configurations, in order, using their identifiers or relative paths
// apply the current configuration last by placing it last in this array
- const configs = arrayify(configFile.extends).map((name) => {
+ const configs = configFile.extends.map((name) => {
const nextConfigFilePath = resolveConfigurationPath(name, configFileDir);
return loadConfigurationFromPath(nextConfigFilePath);
}).concat([configFile]);
- return configs.reduce(extendConfigurationFile, {});
+ return configs.reduce(extendConfigurationFile, EMPTY_CONFIG);
}
}
@@ -174,11 +184,6 @@ function resolveConfigurationPath(filePath: string, relativeTo?: string) {
export function extendConfigurationFile(targetConfig: IConfigurationFile,
nextConfigSource: IConfigurationFile): IConfigurationFile {
- const combinedConfig: IConfigurationFile = {};
-
- const configRulesDirectory = arrayify(targetConfig.rulesDirectory);
- const nextConfigRulesDirectory = arrayify(nextConfigSource.rulesDirectory);
- combinedConfig.rulesDirectory = configRulesDirectory.concat(nextConfigRulesDirectory);
const combineProperties = (targetProperty: any, nextProperty: any) => {
const combinedProperty: any = {};
@@ -192,11 +197,32 @@ export function extendConfigurationFile(targetConfig: IConfigurationFile,
return combinedProperty;
};
- combinedConfig.rules = combineProperties(targetConfig.rules, nextConfigSource.rules);
- combinedConfig.jsRules = combineProperties(targetConfig.jsRules, nextConfigSource.jsRules);
- combinedConfig.linterOptions = combineProperties(targetConfig.linterOptions, nextConfigSource.linterOptions);
+ const combineMaps = (target: Map>, next: Map>) => {
+ const combined = new Map>();
+ target.forEach((options, ruleName) => {
+ combined.set(ruleName, options);
+ });
+ next.forEach((options, ruleName) => {
+ const combinedRule = combined.get(ruleName);
+ if (combinedRule != null) {
+ combined.set(ruleName, combineProperties(combinedRule, options));
+ } else {
+ combined.set(ruleName, options);
+ }
+ });
+ return combined;
+ };
+
+ const combinedRulesDirs = targetConfig.rulesDirectory.concat(nextConfigSource.rulesDirectory);
+ const dedupedRulesDirs = Array.from(new Set(combinedRulesDirs));
- return combinedConfig;
+ return {
+ extends: [],
+ jsRules: combineMaps(targetConfig.jsRules, nextConfigSource.jsRules),
+ linterOptions: combineProperties(targetConfig.linterOptions, nextConfigSource.linterOptions),
+ rules: combineMaps(targetConfig.rules, nextConfigSource.rules),
+ rulesDirectory: dedupedRulesDirs,
+ };
}
function getHomeDir() {
@@ -244,3 +270,103 @@ export function getRulesDirectories(directories?: string | string[], relativeTo?
return rulesDirectories;
}
+
+/**
+ * Parses the options of a single rule and upgrades legacy settings such as `true`, `[true, "option"]`
+ *
+ * @param ruleConfigValue The raw option setting of a rule
+ */
+function parseRuleOptions(ruleConfigValue: any): Partial {
+ let ruleArguments: any[] | undefined;
+ let ruleSeverity: RuleSeverity | undefined;
+
+ if (ruleConfigValue == null) {
+ ruleArguments = [];
+ ruleSeverity = "off";
+ } else if (Array.isArray(ruleConfigValue) && ruleConfigValue.length > 0) {
+ // old style: array
+ ruleArguments = ruleConfigValue.slice(1);
+ ruleSeverity = ruleConfigValue[0] === true ? "error" : "off";
+ } else if (typeof ruleConfigValue === "boolean") {
+ // old style: boolean
+ ruleArguments = [];
+ ruleSeverity = ruleConfigValue === true ? "error" : "off";
+ } else if (ruleConfigValue.severity) {
+ switch (ruleConfigValue.severity.toLowerCase()) {
+ case "warn":
+ case "warning":
+ ruleSeverity = "warning";
+ break;
+ case "error":
+ ruleSeverity = "error";
+ break;
+ default:
+ ruleSeverity = "off";
+ }
+ } else if (typeof ruleConfigValue === "object") {
+ ruleSeverity = undefined;
+ } else {
+ ruleSeverity = "off";
+ }
+
+ if (ruleConfigValue && ruleConfigValue.options) {
+ ruleArguments = arrayify(ruleConfigValue.options);
+ }
+
+ return {
+ ruleArguments,
+ ruleSeverity,
+ };
+}
+
+/**
+ * Parses a config file and normalizes legacy config settings
+ *
+ * @param configFile The raw object read from the JSON of a config file
+ * @param configFileDir The directory of the config file
+ */
+export function parseConfigFile(configFile: any, configFileDir?: string): IConfigurationFile {
+ const rules = new Map>();
+ const jsRules = new Map>();
+
+ if (configFile.rules) {
+ for (const ruleName in configFile.rules) {
+ if (configFile.rules.hasOwnProperty(ruleName)) {
+ rules.set(ruleName, parseRuleOptions(configFile.rules[ruleName]));
+ }
+ }
+ }
+
+ if (configFile.jsRules) {
+ for (const ruleName in configFile.jsRules) {
+ if (configFile.jsRules.hasOwnProperty(ruleName)) {
+ jsRules.set(ruleName, parseRuleOptions(configFile.jsRules[ruleName]));
+ }
+ }
+ }
+
+ return {
+ extends: arrayify(configFile.extends),
+ jsRules,
+ linterOptions: configFile.linterOptions || {},
+ rulesDirectory: getRulesDirectories(configFile.rulesDirectory, configFileDir),
+ rules,
+ };
+}
+
+/**
+ * Fills in default values for `IOption` properties and outputs an array of `IOption`
+ */
+export function convertRuleOptions(ruleConfiguration: Map>): IOptions[] {
+ const output: IOptions[] = [];
+ ruleConfiguration.forEach((partialOptions, ruleName) => {
+ const options: IOptions = {
+ disabledIntervals: [],
+ ruleArguments: partialOptions.ruleArguments || [],
+ ruleName,
+ ruleSeverity: partialOptions.ruleSeverity || "error",
+ };
+ output.push(options);
+ });
+ return output;
+}
diff --git a/src/enableDisableRules.ts b/src/enableDisableRules.ts
index 7f6cb0279e9..64d4cdccfde 100644
--- a/src/enableDisableRules.ts
+++ b/src/enableDisableRules.ts
@@ -17,26 +17,24 @@
import * as utils from "tsutils";
import * as ts from "typescript";
+import { IOptions } from "./language/rule/rule";
-import {AbstractRule} from "./language/rule/abstractRule";
-import {IEnableDisablePosition} from "./ruleLoader";
+import { IEnableDisablePosition } from "./ruleLoader";
export class EnableDisableRulesWalker {
- private enableDisableRuleMap: {[rulename: string]: IEnableDisablePosition[]};
+ private enableDisableRuleMap: Map;
private enabledRules: string[];
- constructor(private sourceFile: ts.SourceFile, rules: {[name: string]: any}) {
- this.enableDisableRuleMap = {};
+ constructor(private sourceFile: ts.SourceFile, ruleOptionsList: IOptions[]) {
+ this.enableDisableRuleMap = new Map();
this.enabledRules = [];
- if (rules) {
- for (const rule of Object.keys(rules)) {
- if (AbstractRule.isRuleEnabled(rules[rule])) {
- this.enabledRules.push(rule);
- this.enableDisableRuleMap[rule] = [{
- isEnabled: true,
- position: 0,
- }];
- }
+ for (const ruleOptions of ruleOptionsList) {
+ if (ruleOptions.ruleSeverity !== "off") {
+ this.enabledRules.push(ruleOptions.ruleName);
+ this.enableDisableRuleMap.set(ruleOptions.ruleName, [{
+ isEnabled: true,
+ position: 0,
+ }]);
}
}
}
@@ -64,7 +62,7 @@ export class EnableDisableRulesWalker {
}
private switchRuleState(ruleName: string, isEnabled: boolean, start: number, end?: number): void {
- const ruleStateMap = this.enableDisableRuleMap[ruleName];
+ const ruleStateMap = this.enableDisableRuleMap.get(ruleName);
if (ruleStateMap === undefined || // skip switches for unknown or disabled rules
isEnabled === ruleStateMap[ruleStateMap.length - 1].isEnabled // no need to add switch points if there is no change
) {
@@ -97,8 +95,8 @@ export class EnableDisableRulesWalker {
// split at whitespaces
// filter empty items coming from whitespaces at start, at end or empty list
let rulesList = commentText.substr(match[0].length)
- .split(/\s+/)
- .filter((rule) => !!rule);
+ .split(/\s+/)
+ .filter((rule) => !!rule);
if (rulesList.length === 0 && match[3] === ":") {
// nothing to do here: an explicit separator was specified but no rules to switch
return;
diff --git a/src/formatters/checkstyleFormatter.ts b/src/formatters/checkstyleFormatter.ts
index c38405391b6..5d8912ebc55 100644
--- a/src/formatters/checkstyleFormatter.ts
+++ b/src/formatters/checkstyleFormatter.ts
@@ -17,7 +17,7 @@
import {AbstractFormatter} from "../language/formatter/abstractFormatter";
import {IFormatterMetadata} from "../language/formatter/formatter";
-import {RuleFailure} from "../language/rule/rule";
+import { RuleFailure } from "../language/rule/rule";
import * as Utils from "../utils";
@@ -48,6 +48,7 @@ export class Formatter extends AbstractFormatter {
});
let previousFilename: string | null = null;
for (const failure of failuresSorted) {
+ const severity = failure.getRuleSeverity();
if (failure.getFileName() !== previousFilename) {
if (previousFilename) {
output += "";
@@ -57,7 +58,7 @@ export class Formatter extends AbstractFormatter {
}
output += "dotdot
output += "source=\"failure.tslint." + this.escapeXml(failure.getRuleName()) + "\" />";
diff --git a/src/formatters/msbuildFormatter.ts b/src/formatters/msbuildFormatter.ts
index 8af372d9602..0afb73216a8 100644
--- a/src/formatters/msbuildFormatter.ts
+++ b/src/formatters/msbuildFormatter.ts
@@ -17,7 +17,7 @@
import {AbstractFormatter} from "../language/formatter/abstractFormatter";
import {IFormatterMetadata} from "../language/formatter/formatter";
-import {RuleFailure} from "../language/rule/rule";
+import { RuleFailure } from "../language/rule/rule";
import {camelize, dedent} from "../utils";
@@ -42,8 +42,9 @@ export class Formatter extends AbstractFormatter {
const lineAndCharacter = failure.getStartPosition().getLineAndCharacter();
const positionTuple = `(${lineAndCharacter.line + 1},${lineAndCharacter.character + 1})`;
+ const severity = failure.getRuleSeverity();
- return `${fileName}${positionTuple}: warning ${camelizedRule}: ${failureString}`;
+ return `${fileName}${positionTuple}: ${severity} ${camelizedRule}: ${failureString}`;
});
return outputLines.join("\n") + "\n";
diff --git a/src/formatters/pmdFormatter.ts b/src/formatters/pmdFormatter.ts
index 1caa3595502..fe475df7bca 100644
--- a/src/formatters/pmdFormatter.ts
+++ b/src/formatters/pmdFormatter.ts
@@ -17,7 +17,7 @@
import {AbstractFormatter} from "../language/formatter/abstractFormatter";
import {IFormatterMetadata} from "../language/formatter/formatter";
-import {RuleFailure} from "../language/rule/rule";
+import { RuleFailure } from "../language/rule/rule";
import * as Utils from "../utils";
@@ -30,7 +30,7 @@ export class Formatter extends AbstractFormatter {
sample: Utils.dedent`
-
+
`,
consumer: "machine",
@@ -49,11 +49,12 @@ export class Formatter extends AbstractFormatter {
.replace(/"/g, """);
const lineAndCharacter = failure.getStartPosition().getLineAndCharacter();
+ const priority = failure.getRuleSeverity() === "warning" ? 4 : 3;
output += " ";
}
diff --git a/src/formatters/proseFormatter.ts b/src/formatters/proseFormatter.ts
index 997412c388f..bc750aca49a 100644
--- a/src/formatters/proseFormatter.ts
+++ b/src/formatters/proseFormatter.ts
@@ -24,14 +24,14 @@ export class Formatter extends AbstractFormatter {
public static metadata: IFormatterMetadata = {
formatterName: "prose",
description: "The default formatter which outputs simple human-readable messages.",
- sample: "myFile.ts[1, 14]: Missing semicolon",
+ sample: "ERROR: myFile.ts[1, 14]: Missing semicolon",
consumer: "human",
};
/* tslint:enable:object-literal-sort-keys */
public format(failures: RuleFailure[], fixes?: RuleFailure[]): string {
if (failures.length === 0 && (!fixes || fixes.length === 0)) {
- return "";
+ return "\n";
}
const fixLines: string[] = [];
@@ -54,7 +54,7 @@ export class Formatter extends AbstractFormatter {
const lineAndCharacter = failure.getStartPosition().getLineAndCharacter();
const positionTuple = `[${lineAndCharacter.line + 1}, ${lineAndCharacter.character + 1}]`;
- return `${fileName}${positionTuple}: ${failureString}`;
+ return `${failure.getRuleSeverity().toUpperCase()}: ${fileName}${positionTuple}: ${failureString}`;
});
return fixLines.concat(errorLines).join("\n") + "\n";
diff --git a/src/formatters/stylishFormatter.ts b/src/formatters/stylishFormatter.ts
index 771fcb61cb6..36a240dd0f5 100644
--- a/src/formatters/stylishFormatter.ts
+++ b/src/formatters/stylishFormatter.ts
@@ -17,7 +17,7 @@
import {AbstractFormatter} from "../language/formatter/abstractFormatter";
import {IFormatterMetadata} from "../language/formatter/formatter";
-import {RuleFailure} from "../language/rule/rule";
+import { RuleFailure } from "../language/rule/rule";
import * as colors from "colors";
@@ -39,10 +39,20 @@ export class Formatter extends AbstractFormatter {
/* tslint:enable:object-literal-sort-keys */
public format(failures: RuleFailure[]): string {
- if (typeof failures[0] === "undefined") {
- return "\n";
+ const outputLines = this.mapToMessages(failures);
+
+ // Removes initial blank line
+ if (outputLines[0] === "") {
+ outputLines.shift();
}
+ return outputLines.join("\n") + "\n";
+ }
+
+ private mapToMessages(failures: RuleFailure[]): string[] {
+ if (!failures) {
+ return [];
+ }
const outputLines: string[] = [];
const positionMaxSize = this.getPositionMaxSize(failures);
const ruleMaxSize = this.getRuleMaxSize(failures);
@@ -71,21 +81,20 @@ export class Formatter extends AbstractFormatter {
const lineAndCharacter = failure.getStartPosition().getLineAndCharacter();
let positionTuple = `${lineAndCharacter.line + 1}:${lineAndCharacter.character + 1}`;
- positionTuple = this.pad(positionTuple, positionMaxSize);
- positionTuple = colors.red(positionTuple);
+ positionTuple = this.pad(positionTuple, positionMaxSize);
- // Ouput
+ if (failure.getRuleSeverity() === "warning") {
+ positionTuple = colors.blue(failure.getRuleSeverity().toUpperCase() + ": " + positionTuple);
+ } else {
+ positionTuple = colors.red(failure.getRuleSeverity().toUpperCase() + ": " + positionTuple);
+ }
+
+ // Output
const output = `${positionTuple} ${ruleName} ${failureString}`;
outputLines.push(output);
}
-
- // Removes initial blank line
- if (outputLines[0] === "") {
- outputLines.shift();
- }
-
- return outputLines.join("\n") + "\n\n";
+ return outputLines;
}
private pad(str: string, len: number): string {
diff --git a/src/formatters/verboseFormatter.ts b/src/formatters/verboseFormatter.ts
index fad23a9fad0..2ea696f64af 100644
--- a/src/formatters/verboseFormatter.ts
+++ b/src/formatters/verboseFormatter.ts
@@ -17,7 +17,7 @@
import {AbstractFormatter} from "../language/formatter/abstractFormatter";
import {IFormatterMetadata} from "../language/formatter/formatter";
-import {RuleFailure} from "../language/rule/rule";
+import { RuleFailure } from "../language/rule/rule";
export class Formatter extends AbstractFormatter {
/* tslint:disable:object-literal-sort-keys */
@@ -25,13 +25,19 @@ export class Formatter extends AbstractFormatter {
formatterName: "verbose",
description: "The human-readable formatter which includes the rule name in messages.",
descriptionDetails: "The output is the same as the prose formatter with the rule name included",
- sample: "(semicolon) myFile.ts[1, 14]: Missing semicolon",
+ sample: "ERROR: (semicolon) myFile.ts[1, 14]: Missing semicolon",
consumer: "human",
};
/* tslint:enable:object-literal-sort-keys */
public format(failures: RuleFailure[]): string {
- const outputLines = failures.map((failure: RuleFailure) => {
+
+ return this.mapToMessages(failures)
+ .join("\n") + "\n";
+ }
+
+ private mapToMessages(failures: RuleFailure[]): string[] {
+ return failures.map((failure: RuleFailure) => {
const fileName = failure.getFileName();
const failureString = failure.getFailure();
const ruleName = failure.getRuleName();
@@ -39,9 +45,8 @@ export class Formatter extends AbstractFormatter {
const lineAndCharacter = failure.getStartPosition().getLineAndCharacter();
const positionTuple = "[" + (lineAndCharacter.line + 1) + ", " + (lineAndCharacter.character + 1) + "]";
- return `(${ruleName}) ${fileName}${positionTuple}: ${failureString}`;
+ return `${failure.getRuleSeverity().toUpperCase()}: (${ruleName}) ${fileName}${positionTuple}: ${failureString}`;
});
- return outputLines.join("\n") + "\n";
}
}
diff --git a/src/formatters/vsoFormatter.ts b/src/formatters/vsoFormatter.ts
index d7763f5b7b0..90949496be4 100644
--- a/src/formatters/vsoFormatter.ts
+++ b/src/formatters/vsoFormatter.ts
@@ -34,8 +34,10 @@ export class Formatter extends AbstractFormatter {
};
/* tslint:enable:object-literal-sort-keys */
- public format(failures: RuleFailure[]): string {
- const outputLines = failures.map((failure: RuleFailure) => {
+ public format(failures: RuleFailure[], warnings: RuleFailure[] = []): string {
+ const all = failures.concat(warnings);
+
+ const outputLines = all.map((failure: RuleFailure) => {
const fileName = failure.getFileName();
const failureString = failure.getFailure();
const lineAndCharacter = failure.getStartPosition().getLineAndCharacter();
diff --git a/src/index.ts b/src/index.ts
index 835ac72fc15..df8cd5c934f 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -35,7 +35,8 @@ export * from "./language/walker";
export * from "./language/formatter/formatter";
export interface LintResult {
- failureCount: number;
+ errorCount: number;
+ warningCount: number;
failures: RuleFailure[];
fixes?: RuleFailure[];
format: string | FormatterFunction;
diff --git a/src/language/formatter/formatter.ts b/src/language/formatter/formatter.ts
index 7801a9a510b..ff3cecbf2d2 100644
--- a/src/language/formatter/formatter.ts
+++ b/src/language/formatter/formatter.ts
@@ -49,8 +49,8 @@ export type ConsumerType = "human" | "machine";
export interface IFormatter {
/**
* Formats linter results
- * @param {RuleFailure[]} failures Linter errors that were not fixed
- * @param {RuleFailure[]} fixes Fixed linter errors. Available when the `--fix` argument is used on the command line
+ * @param {RuleFailure[]} failures Linter failures that were not fixed
+ * @param {RuleFailure[]} fixes Fixed linter failures. Available when the `--fix` argument is used on the command line
*/
format(failures: RuleFailure[], fixes?: RuleFailure[]): string;
}
diff --git a/src/language/rule/abstractRule.ts b/src/language/rule/abstractRule.ts
index 3a051a6ecbd..6942b4e00e0 100644
--- a/src/language/rule/abstractRule.ts
+++ b/src/language/rule/abstractRule.ts
@@ -19,38 +19,22 @@ import * as ts from "typescript";
import {doesIntersect} from "../utils";
import {IWalker, WalkContext} from "../walker";
-import {IDisabledInterval, IOptions, IRule, IRuleMetadata, RuleFailure} from "./rule";
+import { IOptions, IRule, IRuleMetadata, RuleFailure, RuleSeverity } from "./rule";
export abstract class AbstractRule implements IRule {
public static metadata: IRuleMetadata;
protected readonly ruleArguments: any[];
+ protected readonly ruleSeverity: RuleSeverity;
+ public ruleName: string;
- public static isRuleEnabled(ruleConfigValue: any): boolean {
- if (typeof ruleConfigValue === "boolean") {
- return ruleConfigValue;
- }
-
- if (Array.isArray(ruleConfigValue) && ruleConfigValue.length > 0) {
- return ruleConfigValue[0];
- }
-
- return false;
- }
-
- constructor(public readonly ruleName: string, private value: any, private disabledIntervals: IDisabledInterval[]) {
- if (Array.isArray(value) && value.length > 1) {
- this.ruleArguments = value.slice(1);
- } else {
- this.ruleArguments = [];
- }
+ constructor(private options: IOptions) {
+ this.ruleName = options.ruleName;
+ this.ruleArguments = options.ruleArguments;
+ this.ruleSeverity = options.ruleSeverity;
}
public getOptions(): IOptions {
- return {
- disabledIntervals: this.disabledIntervals,
- ruleArguments: this.ruleArguments,
- ruleName: this.ruleName,
- };
+ return this.options;
}
public abstract apply(sourceFile: ts.SourceFile, languageService: ts.LanguageService): RuleFailure[];
@@ -61,7 +45,7 @@ export abstract class AbstractRule implements IRule {
}
public isEnabled(): boolean {
- return AbstractRule.isRuleEnabled(this.value);
+ return this.ruleSeverity !== "off";
}
protected applyWithFunction(sourceFile: ts.SourceFile, walkFn: (ctx: WalkContext) => void): RuleFailure[];
@@ -76,7 +60,7 @@ export abstract class AbstractRule implements IRule {
const result: RuleFailure[] = [];
for (const failure of failures) {
// don't add failures for a rule if the failure intersects an interval where that rule is disabled
- if (!doesIntersect(failure, this.disabledIntervals) && !result.some((f) => f.equals(failure))) {
+ if (!doesIntersect(failure, this.options.disabledIntervals) && !result.some((f) => f.equals(failure))) {
result.push(failure);
}
}
diff --git a/src/language/rule/rule.ts b/src/language/rule/rule.ts
index 26ec45b85a3..4af0147221c 100644
--- a/src/language/rule/rule.ts
+++ b/src/language/rule/rule.ts
@@ -86,8 +86,11 @@ export interface IRuleMetadata {
export type RuleType = "functionality" | "maintainability" | "style" | "typescript";
+export type RuleSeverity = "warning" | "error" | "off";
+
export interface IOptions {
ruleArguments: any[];
+ ruleSeverity: RuleSeverity;
ruleName: string;
disabledIntervals: IDisabledInterval[];
}
@@ -109,6 +112,7 @@ export interface IRuleFailureJson {
failure: string;
fix?: Fix;
name: string;
+ ruleSeverity: string;
ruleName: string;
startPosition: IRuleFailurePositionJson;
}
@@ -227,6 +231,7 @@ export class RuleFailure {
private startPosition: RuleFailurePosition;
private endPosition: RuleFailurePosition;
private rawLines: string;
+ private ruleSeverity: RuleSeverity;
constructor(private sourceFile: ts.SourceFile,
start: number,
@@ -239,6 +244,7 @@ export class RuleFailure {
this.startPosition = this.createFailurePosition(start);
this.endPosition = this.createFailurePosition(end);
this.rawLines = sourceFile.text;
+ this.ruleSeverity = "error";
}
public getFileName() {
@@ -273,6 +279,14 @@ export class RuleFailure {
return this.rawLines;
}
+ public getRuleSeverity() {
+ return this.ruleSeverity;
+ }
+
+ public setRuleSeverity(value: RuleSeverity) {
+ this.ruleSeverity = value;
+ }
+
public toJson(): IRuleFailureJson {
return {
endPosition: this.endPosition.toJson(),
@@ -280,6 +294,7 @@ export class RuleFailure {
fix: this.fix,
name: this.fileName,
ruleName: this.ruleName,
+ ruleSeverity: this.ruleSeverity.toUpperCase(),
startPosition: this.startPosition.toJson(),
};
}
diff --git a/src/language/utils.ts b/src/language/utils.ts
index 58c43f1d885..039ddea4d78 100644
--- a/src/language/utils.ts
+++ b/src/language/utils.ts
@@ -107,7 +107,7 @@ export function isBlockScopedBindingElement(node: ts.BindingElement): boolean {
}
export function getBindingElementVariableDeclaration(node: ts.BindingElement): ts.VariableDeclaration | null {
- let currentParent: ts.Node = node.parent!;
+ let currentParent = node.parent! as ts.Node;
while (currentParent.kind !== ts.SyntaxKind.VariableDeclaration) {
if (currentParent.parent == null) {
return null; // function parameter, no variable declaration
diff --git a/src/language/walker/walkContext.ts b/src/language/walker/walkContext.ts
index 3af20a74c4b..f93b480c192 100644
--- a/src/language/walker/walkContext.ts
+++ b/src/language/walker/walkContext.ts
@@ -17,7 +17,7 @@
import * as ts from "typescript";
-import {Fix, Replacement, RuleFailure} from "../rule/rule";
+import { Fix, Replacement, RuleFailure } from "../rule/rule";
export class WalkContext {
public readonly failures: RuleFailure[] = [];
diff --git a/src/linter.ts b/src/linter.ts
index 096eb2dce18..78a2f540e33 100644
--- a/src/linter.ts
+++ b/src/linter.ts
@@ -20,6 +20,7 @@ import * as path from "path";
import * as ts from "typescript";
import {
+ convertRuleOptions,
DEFAULT_CONFIG,
findConfiguration,
findConfigurationPath,
@@ -34,7 +35,7 @@ import { findFormatter } from "./formatterLoader";
import { ILinterOptions, LintResult } from "./index";
import { IFormatter } from "./language/formatter/formatter";
import { createLanguageService, wrapProgram } from "./language/languageServiceHost";
-import { Fix, IRule, RuleFailure } from "./language/rule/rule";
+import { Fix, IRule, RuleFailure, RuleSeverity } from "./language/rule/rule";
import { TypedRule } from "./language/rule/typedRule";
import * as utils from "./language/utils";
import { loadRules } from "./ruleLoader";
@@ -136,6 +137,18 @@ class Linter {
}
}
this.failures = this.failures.concat(fileFailures);
+
+ // add rule severity to failures
+ const ruleSeverityMap = new Map(enabledRules.map((rule) => {
+ return [rule.getOptions().ruleName, rule.getOptions().ruleSeverity] as [string, RuleSeverity];
+ }));
+ for (const failure of this.failures) {
+ const severity = ruleSeverityMap.get(failure.getRuleName());
+ if (severity === undefined) {
+ throw new Error(`Severity for rule '${failure.getRuleName()} not found`);
+ }
+ failure.setRuleSeverity(severity);
+ }
}
public getResult(): LintResult {
@@ -154,12 +167,14 @@ class Linter {
const output = formatter.format(this.failures, this.fixes);
+ const errorCount = this.failures.filter((failure) => failure.getRuleSeverity() === "error").length;
return {
- failureCount: this.failures.length,
+ errorCount,
failures: this.failures,
fixes: this.fixes,
format: formatterName,
output,
+ warningCount: this.failures.length - errorCount,
};
}
@@ -189,14 +204,14 @@ class Linter {
}
private getEnabledRules(sourceFile: ts.SourceFile, configuration: IConfigurationFile = DEFAULT_CONFIG, isJs: boolean): IRule[] {
- const configurationRules = isJs ? configuration.jsRules : configuration.rules;
+ const ruleOptionsList = convertRuleOptions(isJs ? configuration.jsRules : configuration.rules);
// walk the code first to find all the intervals where rules are disabled
- const enableDisableRuleMap = new EnableDisableRulesWalker(sourceFile, configurationRules).getEnableDisableRuleMap();
+ const enableDisableRuleMap = new EnableDisableRulesWalker(sourceFile, ruleOptionsList).getEnableDisableRuleMap();
const rulesDirectories = arrayify(this.options.rulesDirectory)
.concat(arrayify(configuration.rulesDirectory));
- const configuredRules = loadRules(configurationRules, enableDisableRuleMap, rulesDirectories, isJs);
+ const configuredRules = loadRules(ruleOptionsList, enableDisableRuleMap, rulesDirectories, isJs);
return configuredRules.filter((r) => r.isEnabled());
}
diff --git a/src/ruleLoader.ts b/src/ruleLoader.ts
index f95f728a499..1fbc9ec0942 100644
--- a/src/ruleLoader.ts
+++ b/src/ruleLoader.ts
@@ -21,7 +21,7 @@ import * as path from "path";
import { getRelativePath } from "./configuration";
import { showWarningOnce } from "./error";
import { AbstractRule } from "./language/rule/abstractRule";
-import { IDisabledInterval, IRule } from "./language/rule/rule";
+import { IDisabledInterval, IOptions, IRule } from "./language/rule/rule";
import { arrayify, camelize, dedent } from "./utils";
const moduleDirectory = path.dirname(module.filename);
@@ -33,32 +33,31 @@ export interface IEnableDisablePosition {
position: number;
}
-export function loadRules(ruleConfiguration: {[name: string]: any},
- enableDisableRuleMap: {[rulename: string]: IEnableDisablePosition[]},
+export function loadRules(ruleOptionsList: IOptions[],
+ enableDisableRuleMap: Map,
rulesDirectories?: string | string[],
isJs?: boolean): IRule[] {
const rules: IRule[] = [];
const notFoundRules: string[] = [];
const notAllowedInJsRules: string[] = [];
- for (const ruleName in ruleConfiguration) {
- if (ruleConfiguration.hasOwnProperty(ruleName)) {
- const ruleValue = ruleConfiguration[ruleName];
- if (AbstractRule.isRuleEnabled(ruleValue) || enableDisableRuleMap.hasOwnProperty(ruleName)) {
- const Rule: (typeof AbstractRule) | null = findRule(ruleName, rulesDirectories);
- if (Rule == null) {
- notFoundRules.push(ruleName);
+ for (const ruleOptions of ruleOptionsList) {
+ const ruleName = ruleOptions.ruleName;
+ const enableDisableRules = enableDisableRuleMap.get(ruleName);
+ if (ruleOptions.ruleSeverity !== "off" || enableDisableRuleMap) {
+ const Rule: (typeof AbstractRule) | null = findRule(ruleName, rulesDirectories);
+ if (Rule == null) {
+ notFoundRules.push(ruleName);
+ } else {
+ if (isJs && Rule.metadata && Rule.metadata.typescriptOnly) {
+ notAllowedInJsRules.push(ruleName);
} else {
- if (isJs && Rule.metadata && Rule.metadata.typescriptOnly != null && Rule.metadata.typescriptOnly) {
- notAllowedInJsRules.push(ruleName);
- } else {
- const ruleSpecificList = (ruleName in enableDisableRuleMap ? enableDisableRuleMap[ruleName] : []);
- const disabledIntervals = buildDisabledIntervalsFromSwitches(ruleSpecificList);
- rules.push(new (Rule as any)(ruleName, ruleValue, disabledIntervals));
-
- if (Rule.metadata && Rule.metadata.deprecationMessage) {
- showWarningOnce(`${Rule.metadata.ruleName} is deprecated. ${Rule.metadata.deprecationMessage}`);
- }
+ const ruleSpecificList = enableDisableRules || [];
+ ruleOptions.disabledIntervals = buildDisabledIntervalsFromSwitches(ruleSpecificList);
+ rules.push(new (Rule as any)(ruleOptions));
+
+ if (Rule.metadata && Rule.metadata.deprecationMessage) {
+ showWarningOnce(`${Rule.metadata.ruleName} is deprecated. ${Rule.metadata.deprecationMessage}`);
}
}
}
diff --git a/src/rules/completedDocsRule.ts b/src/rules/completedDocsRule.ts
index 17dc0a44584..fa3847f250e 100644
--- a/src/rules/completedDocsRule.ts
+++ b/src/rules/completedDocsRule.ts
@@ -140,8 +140,8 @@ export class Rule extends Lint.Rules.TypedRule {
ruleName: "completed-docs",
description: "Enforces documentation for important items be filled out.",
optionsDescription: Lint.Utils.dedent`
- \`true\` to enable for ["${ARGUMENT_CLASSES}", "${ARGUMENT_FUNCTIONS}", "${ARGUMENT_METHODS}", "${ARGUMENT_PROPERTIES}"],
- or an array with each item in one of two formats:
+ \`true\` to enable for ["${ARGUMENT_CLASSES}", "${ARGUMENT_FUNCTIONS}", "${ARGUMENT_METHODS}", "${ARGUMENT_PROPERTIES}"],
+ or an array with each item in one of two formats:
* \`string\` to enable for that type
* \`object\` keying types to when their documentation is required:
diff --git a/src/rules/eoflineRule.ts b/src/rules/eoflineRule.ts
index 2442b943b0e..9331c9ae4a1 100644
--- a/src/rules/eoflineRule.ts
+++ b/src/rules/eoflineRule.ts
@@ -42,7 +42,8 @@ export class Rule extends Lint.Rules.AbstractRule {
}
return this.filterFailures([
- new Lint.RuleFailure(sourceFile, length, length, Rule.FAILURE_STRING, this.getOptions().ruleName),
+ new Lint.RuleFailure(sourceFile, length, length, Rule.FAILURE_STRING,
+ this.getOptions().ruleName),
]);
}
}
diff --git a/src/rules/maxFileLineCountRule.ts b/src/rules/maxFileLineCountRule.ts
index 2b3f8905354..0ae00b1abfe 100644
--- a/src/rules/maxFileLineCountRule.ts
+++ b/src/rules/maxFileLineCountRule.ts
@@ -24,7 +24,7 @@ export class Rule extends Lint.Rules.AbstractRule {
ruleName: "max-file-line-count",
description: "Requires files to remain under a certain number of lines",
rationale: Lint.Utils.dedent`
- Limiting the number of lines allowed in a file allows files to remain small,
+ Limiting the number of lines allowed in a file allows files to remain small,
single purpose, and maintainable.`,
optionsDescription: "An integer indicating the maximum number of lines.",
options: {
@@ -63,7 +63,8 @@ export class Rule extends Lint.Rules.AbstractRule {
if (lineCount > lineLimit && disabledIntervals.length === 0) {
const errorString = Rule.FAILURE_STRING_FACTORY(lineCount, lineLimit);
- ruleFailures.push(new Lint.RuleFailure(sourceFile, 0, 1, errorString, this.getOptions().ruleName));
+ ruleFailures.push(new Lint.RuleFailure(sourceFile, 0, 1, errorString,
+ this.getOptions().ruleName));
}
return ruleFailures;
}
diff --git a/src/rules/noImportSideEffectRule.ts b/src/rules/noImportSideEffectRule.ts
index b5e628325dc..899d77ae790 100644
--- a/src/rules/noImportSideEffectRule.ts
+++ b/src/rules/noImportSideEffectRule.ts
@@ -17,7 +17,7 @@
import * as ts from "typescript";
-import * as Lint from "tslint";
+import * as Lint from "../index";
const OPTION_IGNORE_MODULE = "ignore-module";
diff --git a/src/runner.ts b/src/runner.ts
index af8c1c24a58..77b5b8c7560 100644
--- a/src/runner.ts
+++ b/src/runner.ts
@@ -29,7 +29,6 @@ import {
import { FatalError } from "./error";
import * as Linter from "./linter";
import { consoleTestResultsHandler, runTests } from "./test";
-import { updateNotifierCheck } from "./updateNotifier";
export interface IRunnerOptions {
/**
@@ -251,16 +250,11 @@ export class Runner {
const lintResult = linter.getResult();
this.outputStream.write(lintResult.output, () => {
- if (lintResult.failureCount > 0) {
- onComplete(this.options.force ? 0 : 2);
- } else {
+ if (this.options.force || lintResult.errorCount === 0) {
onComplete(0);
+ } else {
+ onComplete(2);
}
});
-
- if (lintResult.format === "prose") {
- // Check to see if there are any updates available
- updateNotifierCheck();
- }
}
}
diff --git a/src/updateNotifier.ts b/src/updateNotifier.ts
deleted file mode 100644
index 314d42bdd18..00000000000
--- a/src/updateNotifier.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * @license
- * Copyright 2016 Palantir Technologies, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { dedent } from "./utils";
-import updateNotifier = require("update-notifier");
-
-export function updateNotifierCheck(): void {
- try {
- const pkg = require("../package.json");
- // Check every 3 days for a new version
- const cacheTime = 1000 * 60 * 60 * 24 * 3;
- const changeLogUrl = "https://github.com/palantir/tslint/blob/master/CHANGELOG.md";
- const notifier = updateNotifier({
- pkg,
- updateCheckInterval: cacheTime,
- });
-
- if (notifier.notify && notifier.update) {
- notifier.notify({
- message: dedent`
- TSLint update available v${notifier.update.current} → v${notifier.update.latest}.
- See ${changeLogUrl}`,
- });
- }
- } catch (error) {
- // ignore error
- }
-};
diff --git a/test/config/tslint-custom-rules-with-dir.json b/test/config/tslint-custom-rules-with-dir.json
index 8c4ae31b1e5..6467b260767 100644
--- a/test/config/tslint-custom-rules-with-dir.json
+++ b/test/config/tslint-custom-rules-with-dir.json
@@ -1,9 +1,13 @@
{
"rulesDirectory": "../files/custom-rules/",
"jsRules": {
- "always-fail": true
+ "always-fail": {
+ "severity": "error"
+ }
},
"rules": {
- "always-fail": true
+ "always-fail": {
+ "severity": "error"
+ }
}
}
diff --git a/test/config/tslint-custom-rules-with-two-dirs.json b/test/config/tslint-custom-rules-with-two-dirs.json
index a43cf3db773..76f2508e997 100644
--- a/test/config/tslint-custom-rules-with-two-dirs.json
+++ b/test/config/tslint-custom-rules-with-two-dirs.json
@@ -1,13 +1,25 @@
{
"rulesDirectory": ["../files/custom-rules-2", "../files/custom-rules/"],
"jsRules": {
- "always-fail": true,
- "no-fail": true,
- "rule-two": true
+ "always-fail": {
+ "severity": "error"
+ },
+ "no-fail": {
+ "severity": "error"
+ },
+ "rule-two": {
+ "severity": "error"
+ }
},
"rules": {
- "always-fail": true,
- "no-fail": true,
- "rule-two": true
+ "always-fail": {
+ "severity": "error"
+ },
+ "no-fail": {
+ "severity": "error"
+ },
+ "rule-two": {
+ "severity": "error"
+ }
}
}
diff --git a/test/config/tslint-custom-rules.json b/test/config/tslint-custom-rules.json
index 250eafcd974..de800c178ad 100644
--- a/test/config/tslint-custom-rules.json
+++ b/test/config/tslint-custom-rules.json
@@ -1,8 +1,14 @@
{
"jsRules": {
- "always-fail": true
+ "always-fail": {
+ "options": [1],
+ "severity": "error"
+ }
},
"rules": {
- "always-fail": true
+ "always-fail": {
+ "options": 1,
+ "severity": "error"
+ }
}
}
diff --git a/test/config/tslint-extends-builtin.json b/test/config/tslint-extends-builtin.json
index 4daad33a5c8..690e68c4ebb 100644
--- a/test/config/tslint-extends-builtin.json
+++ b/test/config/tslint-extends-builtin.json
@@ -1,9 +1,13 @@
{
"extends": "tslint:latest",
"jsRules": {
- "no-eval": false
+ "no-eval": {
+ "severity": "none"
+ }
},
"rules": {
- "no-eval": false
+ "no-eval": {
+ "severity": "none"
+ }
}
}
diff --git a/test/config/tslint-extends-package-array.json b/test/config/tslint-extends-package-array.json
index e52fb098a1d..31b053a7a79 100644
--- a/test/config/tslint-extends-package-array.json
+++ b/test/config/tslint-extends-package-array.json
@@ -4,9 +4,13 @@
"./tslint-custom-rules-with-two-dirs.json"
],
"jsRules": {
- "always-fail": false
+ "always-fail": {
+ "severity": "none"
+ }
},
"rules": {
- "always-fail": false
+ "always-fail": {
+ "severity": "none"
+ }
}
}
diff --git a/test/config/tslint-extends-package-boolean.json b/test/config/tslint-extends-package-boolean.json
new file mode 100644
index 00000000000..ed5eced16c4
--- /dev/null
+++ b/test/config/tslint-extends-package-boolean.json
@@ -0,0 +1,11 @@
+{
+ "extends": "tslint-test-custom-rules",
+ "jsRules": {
+ "rule-two": true,
+ "rule-three": false
+ },
+ "rules": {
+ "rule-two": true,
+ "rule-three": false
+ }
+}
diff --git a/test/config/tslint-extends-package-partial.json b/test/config/tslint-extends-package-partial.json
new file mode 100644
index 00000000000..eebddcc6419
--- /dev/null
+++ b/test/config/tslint-extends-package-partial.json
@@ -0,0 +1,13 @@
+{
+ "extends": "tslint-test-custom-rules",
+ "jsRules": {
+ "always-fail": {
+ "severity": "warning"
+ }
+ },
+ "rules": {
+ "always-fail": {
+ "options": [2]
+ }
+ }
+}
diff --git a/test/config/tslint-extends-package-two-levels.json b/test/config/tslint-extends-package-two-levels.json
index 2e2a12b63ac..2afc4f1cd0a 100644
--- a/test/config/tslint-extends-package-two-levels.json
+++ b/test/config/tslint-extends-package-two-levels.json
@@ -2,9 +2,13 @@
"extends": "tslint-test-config/tslint.json",
"rulesDirectory": "../files/custom-rules",
"jsRules": {
- "always-fail": false
+ "always-fail": {
+ "severity": "none"
+ }
},
"rules": {
- "always-fail": false
+ "always-fail": {
+ "severity": "none"
+ }
}
}
diff --git a/test/config/tslint-extends-package.json b/test/config/tslint-extends-package.json
index ed5eced16c4..8be210769c4 100644
--- a/test/config/tslint-extends-package.json
+++ b/test/config/tslint-extends-package.json
@@ -1,11 +1,19 @@
{
"extends": "tslint-test-custom-rules",
"jsRules": {
- "rule-two": true,
- "rule-three": false
+ "rule-two": {
+ "severity": "error"
+ },
+ "rule-three": {
+ "severity": "none"
+ }
},
"rules": {
- "rule-two": true,
- "rule-three": false
+ "rule-two": {
+ "severity": "error"
+ },
+ "rule-three": {
+ "severity": "none"
+ }
}
}
diff --git a/test/config/tslint-extends-relative.json b/test/config/tslint-extends-relative.json
index c53505e38af..d9cecc98f78 100644
--- a/test/config/tslint-extends-relative.json
+++ b/test/config/tslint-extends-relative.json
@@ -1,9 +1,13 @@
{
"extends": "./tslint-custom-rules-with-two-dirs.json",
"jsRules": {
- "always-fail": false
+ "always-fail": {
+ "severity": "none"
+ }
},
"rules": {
- "always-fail": false
+ "always-fail": {
+ "severity": "none"
+ }
}
}
diff --git a/test/config/tslint-with-comments.json b/test/config/tslint-with-comments.json
index ef12ab77da1..190049a66b7 100644
--- a/test/config/tslint-with-comments.json
+++ b/test/config/tslint-with-comments.json
@@ -4,17 +4,22 @@
/*
"rule-one": true,
*/
- "rule-two": true,
- "rule-three": "//not a comment",
- "rule-four": "/*also not a comment*/"
+ "rule-two": {
+ "severity": "error" // after comment
+ },
+ "rule-three": [true, "//not a comment"],
+ "rule-four": [true, "/*also not a comment*/"]
},
// a nice comment
"rules": {
/*
"rule-one": true,
*/
- "rule-two": true,
- "rule-three": "//not a comment",
- "rule-four": "/*also not a comment*/"
+ "rule-two": {
+ "severity": "error"
+ // after comment
+ },
+ "rule-three": [true, "//not a comment"],
+ "rule-four": [true, "/*also not a comment*/"]
}
}
diff --git a/test/config/tslint-with-jsrules.json b/test/config/tslint-with-jsrules.json
index dc4f5463b1c..5ce2f002bfd 100644
--- a/test/config/tslint-with-jsrules.json
+++ b/test/config/tslint-with-jsrules.json
@@ -1,5 +1,7 @@
{
"jsRules": {
- "rule": true
+ "rule": {
+ "severity": "error"
+ }
}
}
\ No newline at end of file
diff --git a/test/configurationTests.ts b/test/configurationTests.ts
index 819bf5871c2..6217d7dd871 100644
--- a/test/configurationTests.ts
+++ b/test/configurationTests.ts
@@ -16,115 +16,218 @@
import * as fs from "fs";
-import { extendConfigurationFile, IConfigurationFile, loadConfigurationFromPath } from "../src/configuration";
+import {
+ convertRuleOptions,
+ extendConfigurationFile,
+ IConfigurationFile,
+ loadConfigurationFromPath,
+ parseConfigFile,
+} from "../src/configuration";
+import { IOptions } from "./../src/language/rule/rule";
import { createTempFile } from "./utils";
-describe("Configuration", () => {
- it("extendConfigurationFile", () => {
- const EMPTY_CONFIG: IConfigurationFile = {
- jsRules: {},
- linterOptions: {},
- rules: {},
- rulesDirectory: [],
- };
-
- assert.deepEqual(extendConfigurationFile({}, {}), EMPTY_CONFIG);
- assert.deepEqual(extendConfigurationFile({}, EMPTY_CONFIG), EMPTY_CONFIG);
- assert.deepEqual(extendConfigurationFile(EMPTY_CONFIG, {}), EMPTY_CONFIG);
- assert.deepEqual(extendConfigurationFile({}, {
- jsRules: { row: "oar" },
- linterOptions: {},
- rules: { foo: "bar" },
- rulesDirectory: "foo",
- }), {
- jsRules: { row: "oar" },
- linterOptions: {},
- rules: {foo: "bar"},
- rulesDirectory: ["foo"],
- });
- const actualConfig = extendConfigurationFile({
- jsRules: { row: "oar" },
- linterOptions: {},
- rules: {
- a: 1,
- b: 1,
- },
- rulesDirectory: ["foo", "bar"],
- }, {
- jsRules: { fly: "wings" },
- linterOptions: {},
- rules: {
- b: 2,
- c: 3,
- },
- rulesDirectory: "baz",
+describe.only("Configuration", () => {
+ describe("parseConfigFile", () => {
+ it("parses empty config", () => {
+ const rawConfig = {
+ };
+ const expected = getEmptyConfig();
+ assertConfigEquals(parseConfigFile(rawConfig), expected);
+ });
+
+ it("arrayifies `extends`", () => {
+ const rawConfig = {
+ extends: "a",
+ };
+ const expected = getEmptyConfig();
+ expected.extends = ["a"];
+ assertConfigEquals(parseConfigFile(rawConfig), expected);
+ });
+
+ it("parses different ways of storing options", () => {
+ const rawConfig = {
+ rules: {
+ a: true,
+ b: [true],
+ c: false,
+ d: [false],
+ e: [true, 1],
+ f: [false, 2, 3],
+ g: { severity: "off"},
+ h: { severity: "warn"},
+ i: { severity: "warning"},
+ j: { severity: "error"},
+ k: { severity: "none" },
+ l: { options: 1 },
+ m: { options: [2] },
+ n: { options: [{ no: false }] },
+ o: { severity: "warn", options: 1 },
+ p: null,
+ q: {},
+ r: "garbage",
+ s: { junk: 1 },
+ },
+ };
+ const expected = getEmptyConfig();
+ expected.rules.set("a", { ruleArguments: [], ruleSeverity: "error" });
+ expected.rules.set("b", { ruleArguments: [], ruleSeverity: "error" });
+ expected.rules.set("c", { ruleArguments: [], ruleSeverity: "off" });
+ expected.rules.set("d", { ruleArguments: [], ruleSeverity: "off" });
+ expected.rules.set("e", { ruleArguments: [1], ruleSeverity: "error" });
+ expected.rules.set("f", { ruleArguments: [2, 3], ruleSeverity: "off" });
+ expected.rules.set("g", { ruleArguments: undefined, ruleSeverity: "off" });
+ expected.rules.set("h", { ruleArguments: undefined, ruleSeverity: "warning" });
+ expected.rules.set("i", { ruleArguments: undefined, ruleSeverity: "warning" });
+ expected.rules.set("j", { ruleArguments: undefined, ruleSeverity: "error" });
+ expected.rules.set("k", { ruleArguments: undefined, ruleSeverity: "off" });
+ expected.rules.set("l", { ruleArguments: [1], ruleSeverity: undefined });
+ expected.rules.set("m", { ruleArguments: [2], ruleSeverity: undefined });
+ expected.rules.set("n", { ruleArguments: [{ no: false }], ruleSeverity: undefined });
+ expected.rules.set("o", { ruleArguments: [1], ruleSeverity: "warning" });
+ expected.rules.set("p", { ruleArguments: [], ruleSeverity: "off" });
+ expected.rules.set("q", { ruleArguments: undefined, ruleSeverity: undefined });
+ expected.rules.set("r", { ruleArguments: undefined, ruleSeverity: "off" });
+ expected.rules.set("s", { ruleArguments: undefined, ruleSeverity: undefined });
+ assertConfigEquals(parseConfigFile(rawConfig), expected);
+ });
+
+ it("fills in default values", () => {
+ const initial = getEmptyConfig();
+ initial.rules.set("s", { ruleArguments: undefined, ruleSeverity: undefined });
+ assert.deepEqual(convertRuleOptions(initial.rules)[0], {
+ disabledIntervals: [],
+ ruleArguments: [],
+ ruleName: "s",
+ ruleSeverity: "error",
});
- /* tslint:disable:object-literal-sort-keys */
- const expectedConfig = {
- jsRules: {
- row: "oar",
- fly: "wings",
- },
- linterOptions: {},
- rules: {
- a: 1,
- b: 2,
- c: 3,
- },
- rulesDirectory: ["foo", "bar", "baz"],
- };
- assert.deepEqual(actualConfig, expectedConfig);
+ });
+ });
+
+ describe("extendConfigurationFile", () => {
+ const EMPTY_CONFIG = getEmptyConfig();
+
+ it("verifies that empty extending empty is empty", () => {
+ assertConfigEquals(extendConfigurationFile(EMPTY_CONFIG, EMPTY_CONFIG), EMPTY_CONFIG);
+ });
+
+ it("extends empty with non-empty", () => {
+ const config = getEmptyConfig();
+ config.jsRules.set("row", { ruleArguments: ["oar", "column"], ruleSeverity: "error" });
+ config.rules.set("foo", { ruleArguments: ["bar"], ruleSeverity: "off" });
+ config.rulesDirectory = ["foo"];
+ config.linterOptions = { typeCheck: true };
+ assertConfigEquals(extendConfigurationFile(EMPTY_CONFIG, config), config);
+ });
+
+ it("extends empty, with undefined ruleSeverity or ruleArguments", () => {
+ const config = getEmptyConfig();
+ config.jsRules.set("row", { ruleArguments: ["oar", "column"] });
+ config.rules.set("foo", { ruleSeverity: "off" });
+ config.linterOptions = { };
+ assertConfigEquals(extendConfigurationFile(EMPTY_CONFIG, config), config);
+ });
+
+ it ("unions values", () => {
+ const baseConfig = getEmptyConfig();
+ baseConfig.rules.set("foo", { ruleArguments: ["bar"], ruleSeverity: "off" });
+ baseConfig.jsRules.set("row", { ruleArguments: ["oar", "column"] });
+ baseConfig.rulesDirectory = ["foo"];
+
+ const extendingConfig = getEmptyConfig();
+ extendingConfig.rules.set("flow", { ruleArguments: ["river"] });
+ extendingConfig.jsRules.set("good", { ruleArguments: ["does"], ruleSeverity: "warning" });
+ extendingConfig.rulesDirectory = ["baz"];
+
+ const expectedConfig = getEmptyConfig();
+ expectedConfig.rules.set("foo", { ruleArguments: ["bar"], ruleSeverity: "off" });
+ expectedConfig.rules.set("flow", { ruleArguments: ["river"] });
+ expectedConfig.jsRules.set("row", { ruleArguments: ["oar", "column"] });
+ expectedConfig.jsRules.set("good", { ruleArguments: ["does"], ruleSeverity: "warning" });
+ expectedConfig.rulesDirectory = ["foo", "baz"];
+
+ const actualConfig = extendConfigurationFile(baseConfig, extendingConfig);
+ assertConfigEquals(actualConfig, expectedConfig);
+ });
+
+ it ("overrides values", () => {
+ const baseConfig = getEmptyConfig();
+ baseConfig.rules.set("foo", { ruleArguments: ["bar"], ruleSeverity: "off" });
+ baseConfig.jsRules.set("row", { ruleArguments: ["oar", "column"] });
+ baseConfig.rulesDirectory = ["foo"];
+
+ const extendingConfig = getEmptyConfig();
+ extendingConfig.rules.set("foo", { ruleSeverity: "warning" });
+ extendingConfig.jsRules.set("row", { ruleArguments: ["skid"] });
+ extendingConfig.rulesDirectory = ["foo"];
+
+ const expectedConfig = getEmptyConfig();
+ expectedConfig.rules.set("foo", { ruleArguments: ["bar"], ruleSeverity: "warning" });
+ expectedConfig.jsRules.set("row", { ruleArguments: ["skid"] });
+ expectedConfig.rulesDirectory = ["foo"];
+
+ const actualConfig = extendConfigurationFile(baseConfig, extendingConfig);
+ assertConfigEquals(actualConfig, expectedConfig);
+ });
});
describe("loadConfigurationFromPath", () => {
it("extends with relative path", () => {
const config = loadConfigurationFromPath("./test/config/tslint-extends-relative.json");
-
assert.isArray(config.rulesDirectory);
- assert.isTrue(config.rules["no-fail"], "did not pick up 'no-fail' in base config");
- assert.isFalse(config.rules["always-fail"], "did not set 'always-fail' in top config");
- assert.isTrue(config.jsRules["no-fail"]);
- assert.isFalse(config.jsRules["always-fail"]);
+ assert.equal("error", config.rules.get("no-fail")!.ruleSeverity, "did not pick up 'no-fail' in base config");
+ assert.equal("off", config.rules.get("always-fail")!.ruleSeverity, "did not set 'always-fail' in top config");
+ assert.equal("error", config.jsRules.get("no-fail")!.ruleSeverity);
+ assert.equal("off", config.jsRules.get("always-fail")!.ruleSeverity);
});
it("extends with package", () => {
const config = loadConfigurationFromPath("./test/config/tslint-extends-package.json");
+ const expectedConfig = getEmptyConfig();
+ expectedConfig.rules.set("rule-one", { ruleSeverity: "error" });
+ expectedConfig.rules.set("rule-two", { ruleSeverity: "off" });
+ expectedConfig.rules.set("rule-three", { ruleSeverity: "error" });
- assert.isArray(config.rulesDirectory);
- /* tslint:disable:object-literal-sort-keys */
- assert.deepEqual(config.jsRules, {
- "rule-one": true,
- "rule-three": false,
- "rule-two": true,
- });
- assert.deepEqual(config.rules, {
- "rule-one": true,
- "rule-three": false,
- "rule-two": true,
- });
- /* tslint:enable:object-literal-sort-keys */
+ assertConfigEquals(config.jsRules, expectedConfig.rules);
+ assertConfigEquals(config.rules, expectedConfig.rules);
+ });
+
+ it("extends with package - boolean configuration", () => {
+ const config = loadConfigurationFromPath("./test/config/tslint-extends-package-boolean.json");
+ const expectedConfig = getEmptyConfig();
+ expectedConfig.rules.set("rule-one", { ruleSeverity: "error" });
+ expectedConfig.rules.set("rule-two", { ruleSeverity: "error" });
+ expectedConfig.rules.set("rule-three", { ruleSeverity: "off" });
+
+ assertConfigEquals(config.jsRules, expectedConfig.rules);
+ assertConfigEquals(config.rules, expectedConfig.rules);
+ });
+
+ it("extends only severity or only arguments", () => {
+ const config = loadConfigurationFromPath("./test/config/tslint-extends-package-partial.json");
+ const expectedConfig = getEmptyConfig();
+ expectedConfig.rules.set("always-fail", { ruleSeverity: "error", ruleArguments: [2] });
+ expectedConfig.jsRules.set("always-fail", { ruleSeverity: "warning", ruleArguments: [1] });
+
+ assertConfigEquals(config.jsRules, expectedConfig.jsRules);
+ assertConfigEquals(config.rules, expectedConfig.rules);
});
it("extends with package without customization", () => {
const config = loadConfigurationFromPath("./test/config/tslint-extends-package-no-mod.json");
+ const expectedConfig = getEmptyConfig();
+ expectedConfig.rules.set("rule-one", { ruleSeverity: "error" });
+ expectedConfig.rules.set("rule-two", { ruleSeverity: "off" });
- assert.isArray(config.rulesDirectory);
- assert.deepEqual(config.jsRules, {
- "rule-one": true,
- "rule-two": false,
- });
- assert.deepEqual(config.rules, {
- "rule-one": true,
- "rule-two": false,
- });
+ assertConfigEquals(config.jsRules, expectedConfig.rules);
+ assertConfigEquals(config.rules, expectedConfig.rules);
});
it("extends with builtin", () => {
const config = loadConfigurationFromPath("./test/config/tslint-extends-builtin.json");
- assert.isUndefined(config.jsRules["no-var-keyword"]);
- assert.isFalse(config.jsRules["no-eval"]);
- assert.isTrue(config.rules["no-var-keyword"]);
- assert.isFalse(config.rules["no-eval"]);
+ assert.isUndefined(config.jsRules.get("no-var-keyword"));
+ assert.equal("off", config.jsRules.get("no-eval")!.ruleSeverity);
+ assert.equal("error", config.rules.get("no-var-keyword")!.ruleSeverity);
+ assert.equal("off", config.rules.get("no-eval")!.ruleSeverity);
});
describe("with config not relative to tslint", () => {
@@ -143,68 +246,53 @@ describe("Configuration", () => {
it("extends with package installed relative to tslint", () => {
fs.writeFileSync(tmpfile!, JSON.stringify({ extends: "tslint-test-config-non-relative" }));
const config = loadConfigurationFromPath(tmpfile!);
- assert.deepEqual(config.rules, {
- "class-name": true,
- });
+
+ const expectedConfig = getEmptyConfig();
+ expectedConfig.rules.set("class-name", { ruleSeverity: "error" });
+ assertConfigEquals(config.rules, expectedConfig.rules);
});
});
it("extends with package two levels (and relative path in rulesDirectory)", () => {
const config = loadConfigurationFromPath("./test/config/tslint-extends-package-two-levels.json");
- assert.isArray(config.rulesDirectory);
assert.lengthOf(config.rulesDirectory, 2);
assert.isTrue(fs.existsSync(config.rulesDirectory![0]));
assert.isTrue(fs.existsSync(config.rulesDirectory![1]));
- /* tslint:disable:object-literal-sort-keys */
- assert.deepEqual(config.jsRules, {
- "always-fail": false,
- "rule-one": true,
- "rule-two": true,
- "rule-four": true,
- });
- assert.deepEqual(config.rules, {
- "always-fail": false,
- "rule-one": true,
- "rule-two": true,
- "rule-four": true,
- });
- /* tslint:enable:object-literal-sort-keys */
+
+ const expectedConfig = getEmptyConfig();
+ expectedConfig.rules.set("always-fail", { ruleSeverity: "off" });
+ expectedConfig.rules.set("rule-one", { ruleSeverity: "error" });
+ expectedConfig.rules.set("rule-two", { ruleSeverity: "error" });
+ expectedConfig.rules.set("rule-four", { ruleSeverity: "error" });
+
+ assertConfigEquals(config.jsRules, expectedConfig.rules);
+ assertConfigEquals(config.rules, expectedConfig.rules);
});
it("extends with array", () => {
const config = loadConfigurationFromPath("./test/config/tslint-extends-package-array.json");
- assert.isArray(config.rulesDirectory);
- assert.deepEqual(config.jsRules, {
- "always-fail": false,
- "no-fail": true,
- "rule-one": true,
- "rule-two": true,
- });
- assert.deepEqual(config.rules, {
- "always-fail": false,
- "no-fail": true,
- "rule-one": true,
- "rule-two": true,
- });
+ const expectedConfig = getEmptyConfig();
+ expectedConfig.rules.set("always-fail", { ruleSeverity: "off" });
+ expectedConfig.rules.set("no-fail", { ruleSeverity: "error" });
+ expectedConfig.rules.set("rule-one", { ruleSeverity: "error" });
+ expectedConfig.rules.set("rule-two", { ruleSeverity: "error" });
+
+ assertConfigEquals(config.jsRules, expectedConfig.rules);
+ assertConfigEquals(config.rules, expectedConfig.rules);
});
it("can load .json files with comments", () => {
const config = loadConfigurationFromPath("./test/config/tslint-with-comments.json");
- /* tslint:disable:object-literal-sort-keys */
- assert.deepEqual(config.jsRules, {
- "rule-two": true,
- "rule-three": "//not a comment",
- "rule-four": "/*also not a comment*/",
- });
- assert.deepEqual(config.rules, {
- "rule-two": true,
- "rule-three": "//not a comment",
- "rule-four": "/*also not a comment*/",
- });
- /* tslint:enable:object-literal-sort-keys */
+ const expectedConfig = getEmptyConfig();
+ expectedConfig.rules.set("rule-two", { ruleSeverity: "error" });
+ expectedConfig.rules.set("rule-three", { ruleSeverity: "error", ruleArguments: ["//not a comment"] });
+ expectedConfig.rules.set("rule-four", { ruleSeverity: "error", ruleArguments: ["/*also not a comment*/"] });
+
+ assertConfigEquals(config.rules, expectedConfig.rules);
+ assertConfigEquals(config.jsRules, expectedConfig.rules);
});
it("can load .json files with BOM", () => {
@@ -213,8 +301,8 @@ describe("Configuration", () => {
it("can load a built-in configuration", () => {
const config = loadConfigurationFromPath("tslint:recommended");
- assert.isTrue(config.jsRules["no-eval"]);
- assert.isTrue(config.rules["no-eval"]);
+ assert.strictEqual("error", config.jsRules.get("no-eval")!.ruleSeverity);
+ assert.strictEqual("error", config.rules.get("no-eval")!.ruleSeverity);
});
it("throws on an invalid built-in configuration path", () => {
@@ -224,3 +312,33 @@ describe("Configuration", () => {
});
});
});
+
+function getEmptyConfig(): IConfigurationFile {
+ return {
+ extends: [],
+ jsRules: new Map>(),
+ linterOptions: {},
+ rules: new Map>(),
+ rulesDirectory: [],
+ };
+}
+
+function demap(map: Map) {
+ if (map == null) {
+ return map;
+ }
+ const output: { [key: string]: T } = {};
+ map.forEach((value, key) => {
+ output[key] = value;
+ });
+ return output;
+}
+
+// this is needed since `assertConfigEquals` doesn't go into Map object
+function assertConfigEquals(actual: any, expected: any) {
+ assert.deepEqual(actual, expected);
+ if (actual && (actual.jsRules || actual.rules)) {
+ assert.deepEqual(demap(actual.jsRules), demap(expected.jsRules));
+ assert.deepEqual(demap(actual.rules), demap(expected.rules));
+ }
+}
diff --git a/test/eofLineRuleTests.ts b/test/eofLineRuleTests.ts
index 800d4794bb3..69104a284a9 100644
--- a/test/eofLineRuleTests.ts
+++ b/test/eofLineRuleTests.ts
@@ -23,7 +23,7 @@ describe("", () => {
const failureString = Rule.FAILURE_STRING;
it("ensures a trailing newline at EOF", () => {
- const actualFailures = TestUtils.applyRuleOnFile(fileName, EofLineRule);
+ const actualFailures = TestUtils.applyRuleOnFile(fileName, EofLineRule!);
const expectedFailure = TestUtils.createFailure(fileName, [4, 38], [4, 38], failureString);
assert.equal(actualFailures.length, 1);
diff --git a/test/files/custom-rules/alwaysFailRule.js b/test/files/custom-rules/alwaysFailRule.js
index b6d3d25921c..4f1b0bf7f86 100644
--- a/test/files/custom-rules/alwaysFailRule.js
+++ b/test/files/custom-rules/alwaysFailRule.js
@@ -3,7 +3,7 @@ var __extends = (this && this.__extends) || function (d, b) {
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
-var Lint = require("tslint");
+var Lint = require('../../../lib/index');
var Rule = (function (_super) {
__extends(Rule, _super);
function Rule() {
diff --git a/test/formatters/checkstyleFormatterTests.ts b/test/formatters/checkstyleFormatterTests.ts
index d59749a19a9..be3a9a9cd52 100644
--- a/test/formatters/checkstyleFormatterTests.ts
+++ b/test/formatters/checkstyleFormatterTests.ts
@@ -17,7 +17,8 @@
import * as ts from "typescript";
-import {IFormatter, RuleFailure, TestUtils} from "../lint";
+import { IFormatter, TestUtils } from "../lint";
+import { createFailure } from "./utils";
describe("Checkstyle Formatter", () => {
const TEST_FILE_1 = "formatters/jsonFormatter.test.ts"; // reuse existing sample file
@@ -38,23 +39,23 @@ describe("Checkstyle Formatter", () => {
const maxPosition2 = sourceFile2.getFullWidth();
const failures = [
- new RuleFailure(sourceFile1, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile1, 2, 3, "&<>'\" should be escaped", "escape"),
- new RuleFailure(sourceFile1, maxPosition1 - 1, maxPosition1, "last failure", "last-name"),
- new RuleFailure(sourceFile2, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile2, 2, 3, "&<>'\" should be escaped", "escape"),
- new RuleFailure(sourceFile2, maxPosition2 - 1, maxPosition2, "last failure", "last-name"),
+ createFailure(sourceFile1, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile1, 2, 3, "&<>'\" should be escaped", "escape", undefined, "error"),
+ createFailure(sourceFile1, maxPosition1 - 1, maxPosition1, "last failure", "last-name", undefined, "error"),
+ createFailure(sourceFile2, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile2, 2, 3, "&<>'\" should be escaped", "escape", undefined, "warning"),
+ createFailure(sourceFile2, maxPosition2 - 1, maxPosition2, "last failure", "last-name", undefined, "warning"),
];
const expectedResult =
'' +
`` +
- '' +
- '' +
+ '' +
- '' +
+ '' +
"" +
`` +
- '' +
+ '' +
'' +
'' +
diff --git a/test/formatters/codeFrameFormatterTests.ts b/test/formatters/codeFrameFormatterTests.ts
index fb2e6820244..38f43db9d64 100644
--- a/test/formatters/codeFrameFormatterTests.ts
+++ b/test/formatters/codeFrameFormatterTests.ts
@@ -18,7 +18,8 @@ import * as colors from "colors";
import * as ts from "typescript";
-import {IFormatter, RuleFailure, TestUtils} from "../lint";
+import {IFormatter, TestUtils} from "../lint";
+import { createFailure } from "./utils";
describe("CodeFrame Formatter", () => {
const TEST_FILE = "formatters/codeFrameFormatter.test.ts";
@@ -36,10 +37,10 @@ describe("CodeFrame Formatter", () => {
const maxPosition = sourceFile.getFullWidth();
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, 2, 3, "&<>'\" should be escaped", "escape"),
- new RuleFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name"),
- new RuleFailure(sourceFile, 0, maxPosition, "full failure", "full-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, 2, 3, "&<>'\" should be escaped", "escape", undefined, "error"),
+ createFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name", undefined, "error"),
+ createFailure(sourceFile, 0, maxPosition, "full failure", "full-name", undefined, "error"),
];
const expectedResultPlain =
diff --git a/test/formatters/externalFormatterTests.ts b/test/formatters/externalFormatterTests.ts
index 12733cf73e5..e99b5ff8292 100644
--- a/test/formatters/externalFormatterTests.ts
+++ b/test/formatters/externalFormatterTests.ts
@@ -16,7 +16,8 @@
import * as ts from "typescript";
-import {IFormatter, RuleFailure, TestUtils} from "../lint";
+import { IFormatter, TestUtils } from "../lint";
+import { createFailure } from "./utils";
describe("External Formatter", () => {
const TEST_FILE = "formatters/externalFormatter.test.ts";
@@ -33,9 +34,9 @@ describe("External Formatter", () => {
it("formats failures", () => {
const maxPosition = sourceFile.getFullWidth();
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, 32, 36, "mid failure", "mid-name"),
- new RuleFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, 32, 36, "mid failure", "mid-name", undefined, "error"),
+ createFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name", undefined, "error"),
];
const expectedResult =
diff --git a/test/formatters/fileslistFormatterTests.ts b/test/formatters/fileslistFormatterTests.ts
index e77e444afe6..b2ec3304bda 100644
--- a/test/formatters/fileslistFormatterTests.ts
+++ b/test/formatters/fileslistFormatterTests.ts
@@ -16,7 +16,8 @@
import * as ts from "typescript";
-import {IFormatter, RuleFailure, TestUtils} from "../lint";
+import { IFormatter, TestUtils } from "../lint";
+import { createFailure } from "./utils";
describe("Files-list Formatter", () => {
const TEST_FILE = "formatters/fileslistFormatter.test.ts";
@@ -32,8 +33,8 @@ describe("Files-list Formatter", () => {
it("formats failures", () => {
// this part really doesn't matter, as long as we get some failure`
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, 32, 36, "last failure", "last-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, 32, 36, "last failure", "last-name", undefined, "error"),
];
// we only print file-names in this formatter
diff --git a/test/formatters/jsonFormatterTests.ts b/test/formatters/jsonFormatterTests.ts
index 1986e61572e..d485e22ec01 100644
--- a/test/formatters/jsonFormatterTests.ts
+++ b/test/formatters/jsonFormatterTests.ts
@@ -16,7 +16,8 @@
import * as ts from "typescript";
-import {Fix, IFormatter, Replacement, RuleFailure, TestUtils} from "../lint";
+import { Fix, IFormatter, Replacement, TestUtils } from "../lint";
+import { createFailure } from "./utils";
describe("JSON Formatter", () => {
const TEST_FILE = "formatters/jsonFormatter.test.ts";
@@ -33,12 +34,13 @@ describe("JSON Formatter", () => {
const maxPosition = sourceFile.getFullWidth();
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name"),
- new RuleFailure(sourceFile, 0, maxPosition, "full failure", "full-name",
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name", undefined, "error"),
+ createFailure(sourceFile, 0, maxPosition, "full failure", "full-name",
new Fix("full-name", [
new Replacement(0, 0, ""),
- ])),
+ ]),
+ "error"),
];
/* tslint:disable:object-literal-sort-keys */
@@ -56,6 +58,7 @@ describe("JSON Formatter", () => {
character: 1,
},
ruleName: "first-name",
+ ruleSeverity: "ERROR",
},
{
name: TEST_FILE,
@@ -71,6 +74,7 @@ describe("JSON Formatter", () => {
character: 0,
},
ruleName: "last-name",
+ ruleSeverity: "ERROR",
},
{
name: TEST_FILE,
@@ -96,6 +100,7 @@ describe("JSON Formatter", () => {
character: 0,
},
ruleName: "full-name",
+ ruleSeverity: "ERROR",
}];
/* tslint:enable:object-literal-sort-keys */
diff --git a/test/formatters/msbuildFormatterTests.ts b/test/formatters/msbuildFormatterTests.ts
index ef2fd8f4344..8de8d2aff3c 100644
--- a/test/formatters/msbuildFormatterTests.ts
+++ b/test/formatters/msbuildFormatterTests.ts
@@ -16,7 +16,8 @@
import * as ts from "typescript";
-import {IFormatter, RuleFailure, TestUtils} from "../lint";
+import { IFormatter, TestUtils } from "../lint";
+import { createFailure } from "./utils";
describe("MSBuild Formatter", () => {
const TEST_FILE = "formatters/msbuildFormatter.test.ts";
@@ -33,15 +34,15 @@ describe("MSBuild Formatter", () => {
const maxPosition = sourceFile.getFullWidth();
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, 32, 36, "mid failure", "mid-name"),
- new RuleFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, 32, 36, "mid failure", "mid-name", undefined, "error"),
+ createFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name", undefined, "warning"),
];
const expectedResult =
- getFailureString(TEST_FILE, 1, 1, "first failure", "firstName") +
- getFailureString(TEST_FILE, 2, 12, "mid failure", "midName") +
- getFailureString(TEST_FILE, 9, 2, "last failure", "lastName");
+ getFailureString(TEST_FILE, 1, 1, "first failure", "firstName", "error") +
+ getFailureString(TEST_FILE, 2, 12, "mid failure", "midName", "error") +
+ getFailureString(TEST_FILE, 9, 2, "last failure", "lastName", "warning");
const actualResult = formatter.format(failures);
assert.equal(actualResult, expectedResult);
@@ -52,7 +53,7 @@ describe("MSBuild Formatter", () => {
assert.equal(result, "\n");
});
- function getFailureString(file: string, line: number, character: number, reason: string, ruleCamelCase: string) {
- return `${file}(${line},${character}): warning ${ruleCamelCase}: ${reason}\n`;
+ function getFailureString(file: string, line: number, character: number, reason: string, ruleCamelCase: string, severity: string) {
+ return `${file}(${line},${character}): ${severity} ${ruleCamelCase}: ${reason}\n`;
}
});
diff --git a/test/formatters/pmdFormatterTests.ts b/test/formatters/pmdFormatterTests.ts
index 2e95f243b39..eeae2d209ad 100644
--- a/test/formatters/pmdFormatterTests.ts
+++ b/test/formatters/pmdFormatterTests.ts
@@ -16,7 +16,8 @@
import * as ts from "typescript";
-import {IFormatter, RuleFailure, TestUtils} from "../lint";
+import { IFormatter, TestUtils } from "../lint";
+import { createFailure } from "./utils";
describe("PMD Formatter", () => {
const TEST_FILE = "formatters/pmdFormatter.test.ts";
@@ -33,27 +34,27 @@ describe("PMD Formatter", () => {
const maxPosition = sourceFile.getFullWidth();
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, 2, 3, "&<>'\" should be escaped", "escape"),
- new RuleFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name"),
- new RuleFailure(sourceFile, 0, maxPosition, "full failure", "full-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, 2, 3, "&<>'\" should be escaped", "escape", undefined, "error"),
+ createFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name", undefined, "warning"),
+ createFailure(sourceFile, 0, maxPosition, "full failure", "full-name", undefined, "warning"),
];
const expectedResult =
"" +
"" +
- " " +
+ " " +
"" +
"" +
"" +
- " " +
+ " " +
"" +
"" +
"" +
- " " +
+ " " +
"" +
"" +
"" +
- " " +
+ " " +
"" +
"" +
"";
diff --git a/test/formatters/proseFormatterTests.ts b/test/formatters/proseFormatterTests.ts
index b83e550a6f1..fb5569b4c20 100644
--- a/test/formatters/proseFormatterTests.ts
+++ b/test/formatters/proseFormatterTests.ts
@@ -16,7 +16,8 @@
import * as ts from "typescript";
-import {IFormatter, RuleFailure, TestUtils} from "../lint";
+import { IFormatter, TestUtils } from "../lint";
+import { createFailure } from "./utils";
describe("Prose Formatter", () => {
const TEST_FILE = "formatters/proseFormatter.test.ts";
@@ -33,15 +34,15 @@ describe("Prose Formatter", () => {
const maxPosition = sourceFile.getFullWidth();
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, 32, 36, "mid failure", "mid-name"),
- new RuleFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, 32, 36, "mid failure", "mid-name", undefined, "error"),
+ createFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name", undefined, "warning"),
];
const expectedResult =
- TEST_FILE + getPositionString(1, 1) + "first failure\n" +
- TEST_FILE + getPositionString(2, 12) + "mid failure\n" +
- TEST_FILE + getPositionString(9, 2) + "last failure\n";
+ "ERROR: " + TEST_FILE + getPositionString(1, 1) + "first failure\n" +
+ "ERROR: " + TEST_FILE + getPositionString(2, 12) + "mid failure\n" +
+ "WARNING: " + TEST_FILE + getPositionString(9, 2) + "last failure\n";
const actualResult = formatter.format(failures);
assert.equal(actualResult, expectedResult);
@@ -49,21 +50,21 @@ describe("Prose Formatter", () => {
it("formats fixes", () => {
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
];
const mockFix = { getFileName: () => "file2" } as any;
const fixes = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, 32, 36, "mid failure", "mid-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, 32, 36, "mid failure", "mid-name", undefined, "error"),
mockFix,
];
const expectedResult =
`Fixed 2 error(s) in ${TEST_FILE}\n` +
`Fixed 1 error(s) in file2\n\n` +
- `${TEST_FILE}${getPositionString(1, 1)}first failure\n`;
+ `ERROR: ${TEST_FILE}${getPositionString(1, 1)}first failure\n`;
const actualResult = formatter.format(failures, fixes);
assert.equal(actualResult, expectedResult);
@@ -71,7 +72,7 @@ describe("Prose Formatter", () => {
it("handles no failures", () => {
const result = formatter.format([]);
- assert.equal(result, "");
+ assert.equal(result, "\n");
});
function getPositionString(line: number, character: number) {
diff --git a/test/formatters/stylishFormatterTests.ts b/test/formatters/stylishFormatterTests.ts
index a694ccf3e25..e20c777b749 100644
--- a/test/formatters/stylishFormatterTests.ts
+++ b/test/formatters/stylishFormatterTests.ts
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-import * as colors from "colors";
-
import * as ts from "typescript";
-import {IFormatter, RuleFailure, TestUtils} from "../lint";
+import { IFormatter, TestUtils } from "../lint";
+import { createFailure } from "./utils";
describe("Stylish Formatter", () => {
const TEST_FILE = "formatters/stylishFormatter.test.ts";
@@ -35,29 +34,21 @@ describe("Stylish Formatter", () => {
const maxPosition = sourceFile.getFullWidth();
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, 2, 3, "&<>'\" should be escaped", "escape"),
- new RuleFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name"),
- new RuleFailure(sourceFile, 0, maxPosition, "full failure", "full-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, 2, 3, "&<>'\" should be escaped", "escape", undefined, "error"),
+ createFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name", undefined, "error"),
+ createFailure(sourceFile, 0, maxPosition, "full failure", "full-name", undefined, "error"),
];
const maxPositionObj = sourceFile.getLineAndCharacterOfPosition(maxPosition - 1);
const maxPositionTuple = `${maxPositionObj.line + 1}:${maxPositionObj.character + 1}`;
- const expectedResult = colors.enabled ?
- "formatters/stylishFormatter.test.ts" + "\n" +
- "\u001b[31m1:1\u001b[39m \u001b[90mfirst-name\u001b[39m \u001b[33mfirst failure\u001b[39m" + "\n" +
- "\u001b[31m1:3\u001b[39m \u001b[90mescape \u001b[39m \u001b[33m&<>'\" should be escaped\u001b[39m" + "\n" +
- `\u001b[31m${maxPositionTuple}\u001b[39m \u001b[90mlast-name \u001b[39m \u001b[33mlast failure\u001b[39m` + "\n" +
- "\u001b[31m1:1\u001b[39m \u001b[90mfull-name \u001b[39m \u001b[33mfull failure\u001b[39m" + "\n" +
- "\n" :
- "formatters/stylishFormatter.test.ts" + "\n" +
- "1:1 first-name first failure" + "\n" +
- "1:3 escape &<>\'\" should be escaped" + "\n" +
- `${maxPositionTuple} last-name last failure` + "\n" +
- "1:1 full-name full failure" + "\n" +
- "\n";
+ const expectedResult = "formatters/stylishFormatter.test.ts" + "\n" +
+ "\u001b[31mERROR: 1:1\u001b[39m \u001b[90mfirst-name\u001b[39m \u001b[33mfirst failure\u001b[39m" + "\n" +
+ "\u001b[31mERROR: 1:3\u001b[39m \u001b[90mescape \u001b[39m \u001b[33m&<>'\" should be escaped\u001b[39m" + "\n" +
+ `\u001b[31mERROR: ${maxPositionTuple}\u001b[39m \u001b[90mlast-name \u001b[39m \u001b[33mlast failure\u001b[39m` + "\n" +
+ "\u001b[31mERROR: 1:1\u001b[39m \u001b[90mfull-name \u001b[39m \u001b[33mfull failure\u001b[39m" + "\n";
assert.equal(formatter.format(failures), expectedResult);
});
diff --git a/test/formatters/utils.ts b/test/formatters/utils.ts
new file mode 100644
index 00000000000..afa9f4d1c15
--- /dev/null
+++ b/test/formatters/utils.ts
@@ -0,0 +1,31 @@
+/**
+ * @license
+ * Copyright 2017 Palantir Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import * as ts from "typescript";
+import { Fix, RuleFailure, RuleSeverity } from "../../src/language/rule/rule";
+
+export function createFailure(sourceFile: ts.SourceFile,
+ start: number,
+ end: number,
+ failure: string,
+ ruleName: string,
+ fix?: Fix,
+ ruleSeverity: RuleSeverity = "warning") {
+
+ const rule = new RuleFailure(sourceFile, start, end, failure, ruleName, fix);
+ rule.setRuleSeverity(ruleSeverity);
+ return rule;
+}
diff --git a/test/formatters/verboseFormatterTests.ts b/test/formatters/verboseFormatterTests.ts
index 2cb494fa845..dab9237d705 100644
--- a/test/formatters/verboseFormatterTests.ts
+++ b/test/formatters/verboseFormatterTests.ts
@@ -16,7 +16,8 @@
import * as ts from "typescript";
-import {IFormatter, RuleFailure, TestUtils} from "../lint";
+import { IFormatter, TestUtils } from "../lint";
+import { createFailure } from "./utils";
describe("Verbose Formatter", () => {
const TEST_FILE = "formatters/proseFormatter.test.ts";
@@ -33,15 +34,15 @@ describe("Verbose Formatter", () => {
const maxPosition = sourceFile.getFullWidth();
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, 32, 36, "mid failure", "mid-name"),
- new RuleFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, 32, 36, "mid failure", "mid-name", undefined, "error"),
+ createFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name", undefined, "error"),
];
const expectedResult =
- "(first-name) " + TEST_FILE + getPositionString(1, 1) + "first failure\n" +
- "(mid-name) " + TEST_FILE + getPositionString(2, 12) + "mid failure\n" +
- "(last-name) " + TEST_FILE + getPositionString(9, 2) + "last failure\n";
+ "ERROR: (first-name) " + TEST_FILE + getPositionString(1, 1) + "first failure\n" +
+ "ERROR: (mid-name) " + TEST_FILE + getPositionString(2, 12) + "mid failure\n" +
+ "ERROR: (last-name) " + TEST_FILE + getPositionString(9, 2) + "last failure\n";
const actualResult = formatter.format(failures);
assert.equal(actualResult, expectedResult);
diff --git a/test/formatters/vsoFormatterTests.ts b/test/formatters/vsoFormatterTests.ts
index 77d01d26371..3f34bbe01c6 100644
--- a/test/formatters/vsoFormatterTests.ts
+++ b/test/formatters/vsoFormatterTests.ts
@@ -16,7 +16,8 @@
import * as ts from "typescript";
-import {IFormatter, RuleFailure, TestUtils} from "../lint";
+import { IFormatter, TestUtils } from "../lint";
+import { createFailure } from "./utils";
describe("VSO Formatter", () => {
const TEST_FILE = "formatters/vsoFormatter.test.ts";
@@ -33,9 +34,9 @@ describe("VSO Formatter", () => {
const maxPosition = sourceFile.getFullWidth();
const failures = [
- new RuleFailure(sourceFile, 0, 1, "first failure", "first-name"),
- new RuleFailure(sourceFile, 32, 36, "mid failure", "mid-name"),
- new RuleFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name"),
+ createFailure(sourceFile, 0, 1, "first failure", "first-name", undefined, "error"),
+ createFailure(sourceFile, 32, 36, "mid failure", "mid-name", undefined, "error"),
+ createFailure(sourceFile, maxPosition - 1, maxPosition, "last failure", "last-name", undefined, "error"),
];
const expectedResult =
diff --git a/test/ruleLoaderTests.ts b/test/ruleLoaderTests.ts
index 2c81f20b18f..cbdcfeb77fc 100644
--- a/test/ruleLoaderTests.ts
+++ b/test/ruleLoaderTests.ts
@@ -18,7 +18,9 @@
import * as diff from "diff";
import * as fs from "fs";
import * as path from "path";
+import { IEnableDisablePosition } from "../src/ruleLoader";
import { camelize } from "../src/utils";
+import { IOptions } from "./../src/language/rule/rule";
import { loadRules } from "./lint";
describe("Rule Loader", () => {
@@ -27,61 +29,72 @@ describe("Rule Loader", () => {
const testRulesDir = "test/rules";
it("loads core rules", () => {
- const validConfiguration: {[name: string]: any} = {
- "class-name": true,
- "eofline": true,
- "forin": false,
- "no-debugger": true,
- "quotemark": [true, "single"],
- };
-
- const rules = loadRules(validConfiguration, {}, builtRulesDir);
+ const validConfiguration: IOptions[] = [
+ { ruleName: "class-name", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ { ruleName: "eofline", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ { ruleName: "forin", ruleArguments: [], ruleSeverity: "off", disabledIntervals: [] },
+ { ruleName: "no-debugger", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ { ruleName: "quotemark", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ ];
+
+ const rules = loadRules(validConfiguration, new Map(), builtRulesDir);
assert.equal(rules.length, 4);
});
it("ignores invalid rules", () => {
- const invalidConfiguration: {[name: string]: any} = {
- "class-name": true,
- "invalidConfig1": true,
- "invalidConfig2": false,
- };
+ const invalidConfiguration: IOptions[] = [
+ { ruleName: "class-name", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ { ruleName: "invalidConfig1", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ { ruleName: "invalidConfig2", ruleArguments: [], ruleSeverity: "off", disabledIntervals: [] },
+ ];
- const rules = loadRules(invalidConfiguration, {}, [builtRulesDir]);
+ const rules = loadRules(invalidConfiguration, new Map(), [builtRulesDir]);
assert.equal(rules.length, 1);
});
+ it("properly sets rule severity with options", () => {
+ const withOptions: IOptions[] = [
+ { ruleName: "callable-types", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ { ruleName: "max-line-length", ruleArguments: [140], ruleSeverity: "warning", disabledIntervals: [] },
+ ];
+
+ const rules = loadRules(withOptions, new Map(), [builtRulesDir]);
+ assert.equal(rules.length, 2);
+ assert.equal(rules[0].getOptions().ruleSeverity, "error");
+ assert.equal(rules[1].getOptions().ruleSeverity, "warning");
+ });
+
it("loads disabled rules if rule in enableDisableRuleMap", () => {
- const validConfiguration: {[name: string]: any} = {
- "class-name": true,
- "eofline": true,
- "forin": false,
- "no-debugger": true,
- "quotemark": [true, "single"],
- };
-
- const rules = loadRules(validConfiguration, {forin: [{isEnabled: true, position: 4}]}, builtRulesDir);
- assert.equal(rules.length, 5);
+ const validConfiguration: IOptions[] = [
+ { ruleName: "forin", ruleArguments: [], ruleSeverity: "off", disabledIntervals: [] },
+ ];
+
+ const enableDisableMap = new Map();
+ enableDisableMap.set("forin", [{ isEnabled: true, position: 4 }]);
+ const rules = loadRules(validConfiguration, enableDisableMap, builtRulesDir);
+ assert.equal(rules.length, 1);
});
it("works with rulesDirectory argument as an Array", () => {
- const validConfiguration: {[name: string]: any} = {
- "class-name": true,
- "eofline": true,
- "forin": false,
- "no-debugger": true,
- "quotemark": [true, "single"],
- };
-
- const rules = loadRules(validConfiguration, {}, [builtRulesDir]);
+ const validConfiguration: IOptions[] = [
+ { ruleName: "class-name", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ { ruleName: "eofline", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ { ruleName: "forin", ruleArguments: [], ruleSeverity: "off", disabledIntervals: [] },
+ { ruleName: "no-debugger", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ { ruleName: "quotemark", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ ];
+
+ const rules = loadRules(validConfiguration, new Map(), [builtRulesDir]);
assert.equal(rules.length, 4);
});
it("loads js rules", () => {
- const validConfiguration: {[name: string]: any} = {
- "class-name": true,
- };
+ const validConfiguration: IOptions[] = [
+ { ruleName: "class-name", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ { ruleName: "await-promise", ruleArguments: [], ruleSeverity: "error", disabledIntervals: [] },
+ ];
- const rules = loadRules(validConfiguration, {}, builtRulesDir, true);
+ const rules = loadRules(validConfiguration, new Map(), builtRulesDir, true);
assert.equal(rules.length, 1);
});
diff --git a/test/utils.ts b/test/utils.ts
index 8aabe82f729..bc3ff88951f 100644
--- a/test/utils.ts
+++ b/test/utils.ts
@@ -38,9 +38,16 @@ export function getFormatter(formatterName: string) {
return Lint.findFormatter(formatterName, formattersDirectory);
}
-export function applyRuleOnFile(fileName: string, Rule: any, ruleValue: any = true): Lint.RuleFailure[] {
+// this function doesn't work with rules that use the language service
+export function applyRuleOnFile(fileName: string, Rule: any, ruleArguments: any[] = []): Lint.RuleFailure[] {
const sourceFile = getSourceFile(fileName);
- const rule = new Rule("", ruleValue, []);
+ const options = {
+ disabledIntervals: [],
+ ruleArguments,
+ ruleName: Rule.metadata.ruleName,
+ ruleSeverity: "error",
+ };
+ const rule = new Rule(options);
return rule.apply(sourceFile);
}
diff --git a/yarn.lock b/yarn.lock
index e1b1fc571af..137b81ec13b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7,8 +7,8 @@
resolved "https://registry.yarnpkg.com/@types/babel-code-frame/-/babel-code-frame-6.20.0.tgz#05477b2adab210785824881481a65917335e5b68"
"@types/chai@^3.4.34":
- version "3.4.34"
- resolved "https://registry.yarnpkg.com/@types/chai/-/chai-3.4.34.tgz#d5335792823bb09cddd5e38c3d211b709183854d"
+ version "3.4.35"
+ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-3.4.35.tgz#e8d65f83492d2944f816fc620741821c28a8c900"
"@types/colors@^0.6.33":
version "0.6.33"
@@ -44,12 +44,12 @@
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a"
"@types/mocha@^2.2.35":
- version "2.2.38"
- resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.38.tgz#8c188f6e34c2e7c3f1d0127d908d5a36e5a60dc9"
+ version "2.2.39"
+ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.39.tgz#f68d63db8b69c38e9558b4073525cf96c4f7a829"
"@types/node@*", "@types/node@^6.0.56":
- version "6.0.62"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.62.tgz#85222c077b54f25b57417bb708b9f877bda37f89"
+ version "6.0.64"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.64.tgz#cdc901411f6301e1437dfed23bc68f54442e4dc8"
"@types/optimist@0.0.29":
version "0.0.29"
@@ -61,10 +61,6 @@
dependencies:
"@types/node" "*"
-"@types/update-notifier@^1.0.0":
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/@types/update-notifier/-/update-notifier-1.0.0.tgz#3ae6206a6d67c01ffddb9a1eac4cd9b518d534ee"
-
agent-base@2:
version "2.0.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.0.1.tgz#bd8f9e86a8eb221fffa07bd14befd55df142815e"
@@ -120,20 +116,6 @@ balanced-match@^0.4.1:
version "0.4.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
-boxen@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/boxen/-/boxen-0.6.0.tgz#8364d4248ac34ff0ef1b2f2bf49a6c60ce0d81b6"
- dependencies:
- ansi-align "^1.1.0"
- camelcase "^2.1.0"
- chalk "^1.1.1"
- cli-boxes "^1.0.0"
- filled-array "^1.0.0"
- object-assign "^4.0.1"
- repeating "^2.0.0"
- string-width "^1.0.1"
- widest-line "^1.0.0"
-
boxen@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.0.0.tgz#b2694baf1f605f708ff0177c12193b22f29aaaab"
@@ -157,18 +139,10 @@ browser-stdout@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
-buffer-shims@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
-
builtin-modules@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
-camelcase@^2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
-
camelcase@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.0.0.tgz#8b0f90d44be5e281b903b9887349b92595ef07f2"
@@ -217,20 +191,6 @@ concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
-configstore@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/configstore/-/configstore-2.1.0.tgz#737a3a7036e9886102aa6099e47bb33ab1aba1a1"
- dependencies:
- dot-prop "^3.0.0"
- graceful-fs "^4.1.2"
- mkdirp "^0.5.0"
- object-assign "^4.0.1"
- os-tmpdir "^1.0.0"
- osenv "^0.1.0"
- uuid "^2.0.1"
- write-file-atomic "^1.1.2"
- xdg-basedir "^2.0.0"
-
configstore@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.0.0.tgz#e1b8669c1803ccc50b545e92f8e6e79aa80e0196"
@@ -242,11 +202,7 @@ configstore@^3.0.0:
write-file-atomic "^1.1.2"
xdg-basedir "^3.0.0"
-core-util-is@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
-
-create-error-class@^3.0.0, create-error-class@^3.0.1:
+create-error-class@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
dependencies:
@@ -270,7 +226,13 @@ crypto-random-string@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
-debug@2, debug@2.2.0, debug@^2.2.0:
+debug@2, debug@^2.2.0:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351"
+ dependencies:
+ ms "0.7.2"
+
+debug@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
dependencies:
@@ -301,24 +263,12 @@ diff@^3.0.1:
version "3.2.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
-dot-prop@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177"
- dependencies:
- is-obj "^1.0.0"
-
dot-prop@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.1.0.tgz#eb29eac57dfa31fda1edef50ea462ee3d38ff3ab"
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.1.1.tgz#a8493f0b7b5eeec82525b5c7587fa7de7ca859c1"
dependencies:
is-obj "^1.0.0"
-duplexer2@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
- dependencies:
- readable-stream "^2.0.2"
-
duplexer3@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
@@ -328,8 +278,8 @@ duplexer@~0.1.1:
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
error-ex@^1.2.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.0.tgz#e67b43f3e82c96ea3a584ffee0b9fc3325d802d9"
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
dependencies:
is-arrayish "^0.2.1"
@@ -354,9 +304,9 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
-esprima@^2.6.0:
- version "2.7.3"
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
+esprima@^3.1.1:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
esutils@^2.0.2:
version "2.0.2"
@@ -389,10 +339,6 @@ extend@3, extend@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4"
-filled-array@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/filled-array/-/filled-array-1.1.0.tgz#c3c4f6c663b923459a9aa29912d2d031f1507f84"
-
find-up@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
@@ -434,8 +380,8 @@ get-stream@^3.0.0:
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
github@^8.1.1:
- version "8.1.1"
- resolved "https://registry.yarnpkg.com/github/-/github-8.1.1.tgz#a078c61669b4d4b588bf1b2e2a591eb7c49feb36"
+ version "8.2.1"
+ resolved "https://registry.yarnpkg.com/github/-/github-8.2.1.tgz#616b2211fbcd1cc8631669aed67653e62eb53816"
dependencies:
follow-redirects "0.0.7"
https-proxy-agent "^1.0.0"
@@ -474,26 +420,6 @@ glob@~5.0.0:
once "^1.3.0"
path-is-absolute "^1.0.0"
-got@^5.0.0:
- version "5.7.1"
- resolved "https://registry.yarnpkg.com/got/-/got-5.7.1.tgz#5f81635a61e4a6589f180569ea4e381680a51f35"
- dependencies:
- create-error-class "^3.0.1"
- duplexer2 "^0.1.4"
- is-redirect "^1.0.0"
- is-retry-allowed "^1.0.0"
- is-stream "^1.0.0"
- lowercase-keys "^1.0.0"
- node-status-codes "^1.0.0"
- object-assign "^4.0.1"
- parse-json "^2.1.0"
- pinkie-promise "^2.0.0"
- read-all-stream "^3.0.0"
- readable-stream "^2.0.5"
- timed-out "^3.0.0"
- unzip-response "^1.0.2"
- url-parse-lax "^1.0.0"
-
got@^6.7.1:
version "6.7.1"
resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
@@ -532,9 +458,15 @@ has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+has@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
+ dependencies:
+ function-bind "^1.0.2"
+
hosted-git-info@^2.1.4:
- version "2.1.5"
- resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.1.5.tgz#0ba81d90da2e25ab34a332e6ec77936e1598118b"
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.2.0.tgz#7a0d097863d886c0fabbdcd37bf1758d8becf8a5"
https-proxy-agent@^1.0.0:
version "1.0.0"
@@ -555,7 +487,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@~2.0.1:
+inherits@2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
@@ -581,12 +513,6 @@ is-date-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
-is-finite@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
- dependencies:
- number-is-nan "^1.0.0"
-
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
@@ -610,8 +536,10 @@ is-redirect@^1.0.0:
resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
is-regex@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.3.tgz#0d55182bddf9f2fde278220aec3a75642c908637"
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
+ dependencies:
+ has "^1.0.1"
is-retry-allowed@^1.0.0:
version "1.1.0"
@@ -629,10 +557,6 @@ is-utf8@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
-isarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
-
isexe@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0"
@@ -642,11 +566,11 @@ js-tokens@^3.0.0:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
js-yaml@^3.7.0:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
+ version "3.8.2"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.2.tgz#02d3e2c0f6beab20248d412c352203827d786721"
dependencies:
argparse "^1.0.7"
- esprima "^2.6.0"
+ esprima "^3.1.1"
json3@3.3.2:
version "3.3.2"
@@ -656,22 +580,12 @@ jsonify@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
-latest-version@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-2.0.0.tgz#56f8d6139620847b8017f8f1f4d78e211324168b"
- dependencies:
- package-json "^2.0.0"
-
latest-version@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.0.0.tgz#3104f008c0c391084107f85a344bc61e38970649"
dependencies:
package-json "^3.0.0"
-lazy-req@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/lazy-req/-/lazy-req-1.1.0.tgz#bdaebead30f8d824039ce0ce149d4daa07ba1fac"
-
lazy-req@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/lazy-req/-/lazy-req-2.0.0.tgz#c9450a363ecdda2e6f0c70132ad4f37f8f06f2b4"
@@ -796,14 +710,14 @@ ms@0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
+ms@0.7.2:
+ version "0.7.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
+
netrc@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/netrc/-/netrc-0.1.4.tgz#6be94fcaca8d77ade0a9670dc460914c94472444"
-node-status-codes@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f"
-
normalize-package-data@^2.3.2:
version "2.3.5"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.5.tgz#8d924f142960e1777e7ffe170543631cc7cb02df"
@@ -859,40 +773,16 @@ optimist@~0.6.0:
minimist "~0.0.1"
wordwrap "~0.0.2"
-os-homedir@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
-
-os-tmpdir@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
-
-osenv@^0.1.0:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
- dependencies:
- os-homedir "^1.0.0"
- os-tmpdir "^1.0.0"
-
-package-json@^2.0.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/package-json/-/package-json-2.4.0.tgz#0d15bd67d1cbbddbb2ca222ff2edb86bcb31a8bb"
- dependencies:
- got "^5.0.0"
- registry-auth-token "^3.0.1"
- registry-url "^3.0.3"
- semver "^5.1.0"
-
package-json@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/package-json/-/package-json-3.0.0.tgz#dc11f79ebdb436e55fe2b9b294ee3f2a87a33b13"
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/package-json/-/package-json-3.1.0.tgz#ce281900fe8052150cc6709c6c006c18fdb2f379"
dependencies:
got "^6.7.1"
registry-auth-token "^3.0.1"
registry-url "^3.0.3"
semver "^5.1.0"
-parse-json@^2.1.0, parse-json@^2.2.0:
+parse-json@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
dependencies:
@@ -912,6 +802,10 @@ path-key@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-1.0.0.tgz#5d53d578019646c0d68800db4e146e6bdc2ac7af"
+path-parse@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
+
path-type@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
@@ -944,10 +838,6 @@ prepend-http@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
-process-nextick-args@~1.0.6:
- version "1.0.7"
- resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
-
ps-tree@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014"
@@ -959,20 +849,13 @@ pseudomap@^1.0.1:
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
rc@^1.0.1, rc@^1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9"
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.7.tgz#c5ea564bb07aff9fd3a5b32e906c1d3a65940fea"
dependencies:
deep-extend "~0.4.0"
ini "~1.3.0"
minimist "^1.2.0"
- strip-json-comments "~1.0.4"
-
-read-all-stream@^3.0.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/read-all-stream/-/read-all-stream-3.1.0.tgz#35c3e177f2078ef789ee4bfafa4373074eaef4fa"
- dependencies:
- pinkie-promise "^2.0.0"
- readable-stream "^2.0.0"
+ strip-json-comments "~2.0.1"
read-pkg-up@^1.0.1:
version "1.0.1"
@@ -989,18 +872,6 @@ read-pkg@^1.0.0, read-pkg@^1.1.0:
normalize-package-data "^2.3.2"
path-type "^1.0.0"
-readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e"
- dependencies:
- buffer-shims "^1.0.0"
- core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "~1.0.0"
- process-nextick-args "~1.0.6"
- string_decoder "~0.10.x"
- util-deprecate "~1.0.1"
-
registry-auth-token@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.1.0.tgz#997c08256e0c7999837b90e944db39d8a790276b"
@@ -1013,19 +884,15 @@ registry-url@^3.0.3:
dependencies:
rc "^1.0.1"
-repeating@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
- dependencies:
- is-finite "^1.0.0"
-
resolve@^1.1.7:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.2.0.tgz#9589c3f2f6149d1417a40becc1663db6ec6bc26c"
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.2.tgz#1f0442c9e0cbb8136e87b9305f932f46c7f28235"
+ dependencies:
+ path-parse "^1.0.5"
rimraf@^2.5.4:
- version "2.5.4"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04"
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
dependencies:
glob "^7.0.5"
@@ -1039,14 +906,14 @@ semver-diff@^2.0.0:
dependencies:
semver "^5.0.3"
-"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
-
-semver@~5.0.1:
+"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@~5.0.1:
version "5.0.3"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a"
+semver@^5.1.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+
shell-quote@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767"
@@ -1080,7 +947,7 @@ split@0.3:
dependencies:
through "2"
-sprintf-js@^1.0.3, sprintf-js@~1.0.2:
+sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
@@ -1117,10 +984,6 @@ string.prototype.padend@^3.0.0:
es-abstract "^1.4.3"
function-bind "^1.0.2"
-string_decoder@~0.10.x:
- version "0.10.31"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
-
strip-ansi@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
@@ -1137,9 +1000,9 @@ strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
-strip-json-comments@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
+strip-json-comments@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
supports-color@3.1.2:
version "3.1.2"
@@ -1161,10 +1024,6 @@ through@2, through@~2.3, through@~2.3.1:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
-timed-out@^3.0.0:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-3.1.3.tgz#95860bfcc5c76c277f8f8326fd0f5b2e20eba217"
-
timed-out@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
@@ -1173,8 +1032,8 @@ timed-out@^4.0.0:
version "0.0.1"
tslint@next:
- version "4.3.0-dev.0"
- resolved "https://registry.yarnpkg.com/tslint/-/tslint-4.3.0-dev.0.tgz#39b701168f2281760e7822389c3dced9f49e3954"
+ version "4.5.1-dev.0"
+ resolved "https://registry.yarnpkg.com/tslint/-/tslint-4.5.1-dev.0.tgz#3dd254afb323a4c0e666d178bab187c6c1f57f6b"
dependencies:
babel-code-frame "^6.20.0"
colors "^1.1.2"
@@ -1183,8 +1042,8 @@ tslint@next:
glob "^7.1.1"
optimist "~0.6.0"
resolve "^1.1.7"
- underscore.string "^3.3.4"
- update-notifier "^1.0.2"
+ tsutils "^1.1.0"
+ update-notifier "^2.0.0"
tsutils@^1.1.0:
version "1.1.0"
@@ -1202,43 +1061,19 @@ typescript@>=2.3.0-dev:
version "2.3.0-dev.20170303"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.0-dev.20170303.tgz#a94608c40d62f8675bafe5df7dc78a2a77bb71ba"
-underscore.string@^3.3.4:
- version "3.3.4"
- resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.4.tgz#2c2a3f9f83e64762fdc45e6ceac65142864213db"
- dependencies:
- sprintf-js "^1.0.3"
- util-deprecate "^1.0.2"
-
unique-string@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a"
dependencies:
crypto-random-string "^1.0.0"
-unzip-response@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe"
-
unzip-response@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
-update-notifier@^1.0.2:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-1.0.3.tgz#8f92c515482bd6831b7c93013e70f87552c7cf5a"
- dependencies:
- boxen "^0.6.0"
- chalk "^1.0.0"
- configstore "^2.0.0"
- is-npm "^1.0.0"
- latest-version "^2.0.0"
- lazy-req "^1.1.0"
- semver-diff "^2.0.0"
- xdg-basedir "^2.0.0"
-
update-notifier@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.0.0.tgz#1f2712fd2079f415980b5af95eb120e4aceea9a6"
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.1.0.tgz#ec0c1e53536b76647a24b77cb83966d9315123d9"
dependencies:
boxen "^1.0.0"
chalk "^1.0.0"
@@ -1255,14 +1090,6 @@ url-parse-lax@^1.0.0:
dependencies:
prepend-http "^1.0.1"
-util-deprecate@^1.0.2, util-deprecate@~1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
-
-uuid@^2.0.1:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
-
validate-npm-package-license@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
@@ -1298,12 +1125,6 @@ write-file-atomic@^1.1.2:
imurmurhash "^0.1.4"
slide "^1.1.5"
-xdg-basedir@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-2.0.0.tgz#edbc903cc385fc04523d966a335504b5504d1bd2"
- dependencies:
- os-homedir "^1.0.0"
-
xdg-basedir@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"