diff --git a/CHANGELOG.md b/CHANGELOG.md
index f0e1947c46b..9f1797a9cb5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,42 @@
Change Log
===
+
+
v4.5.1
---
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/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/src/configuration.ts b/src/configuration.ts
index 8e48c507e47..2039dea15f5 100644
--- a/src/configuration.ts
+++ b/src/configuration.ts
@@ -21,7 +21,7 @@ import * as path from "path";
import * as resolve from "resolve";
import { FatalError } from "./error";
-import {arrayify, objectify, stripComments} from "./utils";
+import { arrayify, objectify, stripComments } from "./utils";
export interface IConfigurationFile {
extends?: string | string[];
@@ -39,11 +39,9 @@ export interface IConfigurationLoadResult {
}
export const CONFIG_FILENAME = "tslint.json";
-/* tslint:disable:object-literal-key-quotes */
export const DEFAULT_CONFIG = {
- "extends": "tslint:recommended",
+ extends: "tslint:recommended",
};
-/* tslint:enable:object-literal-key-quotes */
const BUILT_IN_CONFIG = /^tslint:(.*)$/;
@@ -244,3 +242,30 @@ export function getRulesDirectories(directories?: string | string[], relativeTo?
return rulesDirectories;
}
+
+export function isRuleEnabled(ruleConfigValue: any): boolean {
+ if (typeof ruleConfigValue === "boolean") {
+ return ruleConfigValue;
+ }
+
+ if (Array.isArray(ruleConfigValue) && ruleConfigValue.length > 0) {
+ return ruleConfigValue[0];
+ }
+
+ if (ruleConfigValue.severity !== "off" && ruleConfigValue.severity !== "none") {
+ return true;
+ }
+
+ return false;
+}
+
+export function getRuleSeverity(ruleConfigValue: any) {
+ if (ruleConfigValue.severity &&
+ (ruleConfigValue.severity.toLowerCase() === "warn" ||
+ ruleConfigValue.severity.toLowerCase() === "warning")) {
+
+ return "warning";
+ }
+
+ return "error";
+}
diff --git a/src/enableDisableRules.ts b/src/enableDisableRules.ts
index 7f6cb0279e9..ac585208ec5 100644
--- a/src/enableDisableRules.ts
+++ b/src/enableDisableRules.ts
@@ -18,7 +18,7 @@
import * as utils from "tsutils";
import * as ts from "typescript";
-import {AbstractRule} from "./language/rule/abstractRule";
+import {isRuleEnabled} from "./configuration";
import {IEnableDisablePosition} from "./ruleLoader";
export class EnableDisableRulesWalker {
@@ -30,7 +30,7 @@ export class EnableDisableRulesWalker {
this.enabledRules = [];
if (rules) {
for (const rule of Object.keys(rules)) {
- if (AbstractRule.isRuleEnabled(rules[rule])) {
+ if (isRuleEnabled(rules[rule])) {
this.enabledRules.push(rule);
this.enableDisableRuleMap[rule] = [{
isEnabled: true,
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..33bff73978e 100644
--- a/src/language/rule/abstractRule.ts
+++ b/src/language/rule/abstractRule.ts
@@ -17,25 +17,16 @@
import * as ts from "typescript";
+import { getRuleSeverity, isRuleEnabled } from "../../configuration";
+import {arrayify} from "../../utils";
import {doesIntersect} from "../utils";
import {IWalker, WalkContext} from "../walker";
-import {IDisabledInterval, IOptions, IRule, IRuleMetadata, RuleFailure} from "./rule";
+import { IDisabledInterval, IOptions, IRule, IRuleMetadata, RuleFailure, RuleSeverity } from "./rule";
export abstract class AbstractRule implements IRule {
public static metadata: IRuleMetadata;
protected readonly ruleArguments: any[];
-
- public static isRuleEnabled(ruleConfigValue: any): boolean {
- if (typeof ruleConfigValue === "boolean") {
- return ruleConfigValue;
- }
-
- if (Array.isArray(ruleConfigValue) && ruleConfigValue.length > 0) {
- return ruleConfigValue[0];
- }
-
- return false;
- }
+ protected readonly ruleSeverity: RuleSeverity;
constructor(public readonly ruleName: string, private value: any, private disabledIntervals: IDisabledInterval[]) {
if (Array.isArray(value) && value.length > 1) {
@@ -43,6 +34,12 @@ export abstract class AbstractRule implements IRule {
} else {
this.ruleArguments = [];
}
+
+ if (value.options) {
+ this.ruleArguments = arrayify(value.options);
+ }
+
+ this.ruleSeverity = getRuleSeverity(value);
}
public getOptions(): IOptions {
@@ -50,6 +47,7 @@ export abstract class AbstractRule implements IRule {
disabledIntervals: this.disabledIntervals,
ruleArguments: this.ruleArguments,
ruleName: this.ruleName,
+ ruleSeverity: this.ruleSeverity,
};
}
@@ -61,7 +59,7 @@ export abstract class AbstractRule implements IRule {
}
public isEnabled(): boolean {
- return AbstractRule.isRuleEnabled(this.value);
+ return isRuleEnabled(this.value);
}
protected applyWithFunction(sourceFile: ts.SourceFile, walkFn: (ctx: WalkContext) => void): RuleFailure[];
diff --git a/src/language/rule/rule.ts b/src/language/rule/rule.ts
index 26ec45b85a3..f9b2637baf3 100644
--- a/src/language/rule/rule.ts
+++ b/src/language/rule/rule.ts
@@ -86,8 +86,12 @@ export interface IRuleMetadata {
export type RuleType = "functionality" | "maintainability" | "style" | "typescript";
+export type RuleSeverity = "warning" | "error";
+
export interface IOptions {
ruleArguments: any[];
+ ruleSeverity: RuleSeverity;
+
ruleName: string;
disabledIntervals: IDisabledInterval[];
}
@@ -109,6 +113,7 @@ export interface IRuleFailureJson {
failure: string;
fix?: Fix;
name: string;
+ ruleSeverity: string;
ruleName: string;
startPosition: IRuleFailurePositionJson;
}
@@ -227,6 +232,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 +245,7 @@ export class RuleFailure {
this.startPosition = this.createFailurePosition(start);
this.endPosition = this.createFailurePosition(end);
this.rawLines = sourceFile.text;
+ this.ruleSeverity = "warning";
}
public getFileName() {
@@ -273,6 +280,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 +295,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/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 4e947e8f734..dc725a833ce 100644
--- a/src/linter.ts
+++ b/src/linter.ts
@@ -34,7 +34,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 +136,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 {
@@ -152,12 +164,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,
};
}
diff --git a/src/ruleLoader.ts b/src/ruleLoader.ts
index f95f728a499..4ace0397ab8 100644
--- a/src/ruleLoader.ts
+++ b/src/ruleLoader.ts
@@ -18,7 +18,7 @@
import * as fs from "fs";
import * as path from "path";
-import { getRelativePath } from "./configuration";
+import { getRelativePath, isRuleEnabled } from "./configuration";
import { showWarningOnce } from "./error";
import { AbstractRule } from "./language/rule/abstractRule";
import { IDisabledInterval, IRule } from "./language/rule/rule";
@@ -44,7 +44,7 @@ export function loadRules(ruleConfiguration: {[name: string]: any},
for (const ruleName in ruleConfiguration) {
if (ruleConfiguration.hasOwnProperty(ruleName)) {
const ruleValue = ruleConfiguration[ruleName];
- if (AbstractRule.isRuleEnabled(ruleValue) || enableDisableRuleMap.hasOwnProperty(ruleName)) {
+ if (isRuleEnabled(ruleValue) || enableDisableRuleMap.hasOwnProperty(ruleName)) {
const Rule: (typeof AbstractRule) | null = findRule(ruleName, rulesDirectories);
if (Rule == null) {
notFoundRules.push(ruleName);
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..deaba9a0c33 100644
--- a/src/runner.ts
+++ b/src/runner.ts
@@ -251,10 +251,10 @@ 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);
}
});
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..ce5d5273980 100644
--- a/test/config/tslint-custom-rules.json
+++ b/test/config/tslint-custom-rules.json
@@ -1,8 +1,12 @@
{
"jsRules": {
- "always-fail": true
+ "always-fail": {
+ "severity": "error"
+ }
},
"rules": {
- "always-fail": true
+ "always-fail": {
+ "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-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..157a5f63515 100644
--- a/test/config/tslint-with-comments.json
+++ b/test/config/tslint-with-comments.json
@@ -4,7 +4,9 @@
/*
"rule-one": true,
*/
- "rule-two": true,
+ "rule-two": {
+ "severity": "error" // after comment
+ },
"rule-three": "//not a comment",
"rule-four": "/*also not a comment*/"
},
@@ -13,7 +15,10 @@
/*
"rule-one": true,
*/
- "rule-two": true,
+ "rule-two": {
+ "severity": "error"
+ // after comment
+ },
"rule-three": "//not a comment",
"rule-four": "/*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..e2c716e16cf 100644
--- a/test/configurationTests.ts
+++ b/test/configurationTests.ts
@@ -81,15 +81,41 @@ describe("Configuration", () => {
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["no-fail"].severity, "did not pick up 'no-fail' in base config");
+ assert.equal("none", config.rules["always-fail"].severity, "did not set 'always-fail' in top config");
+ assert.equal("error", config.jsRules["no-fail"].severity);
+ assert.equal("none", config.jsRules["always-fail"].severity);
});
it("extends with package", () => {
const config = loadConfigurationFromPath("./test/config/tslint-extends-package.json");
+ assert.isArray(config.rulesDirectory);
+ /* tslint:disable:object-literal-sort-keys */
+ assert.deepEqual(config.jsRules, {
+ "rule-one": true,
+ "rule-three": {
+ severity: "none",
+ },
+ "rule-two": {
+ severity: "error",
+ },
+ });
+ assert.deepEqual(config.rules, {
+ "rule-one": true,
+ "rule-three": {
+ severity: "none",
+ },
+ "rule-two": {
+ severity: "error",
+ },
+ });
+ /* tslint:enable:object-literal-sort-keys */
+ });
+
+ it("extends with package - boolean configuration", () => {
+ const config = loadConfigurationFromPath("./test/config/tslint-extends-package-boolean.json");
+
assert.isArray(config.rulesDirectory);
/* tslint:disable:object-literal-sort-keys */
assert.deepEqual(config.jsRules, {
@@ -122,9 +148,9 @@ describe("Configuration", () => {
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.equal("none", config.jsRules["no-eval"].severity);
assert.isTrue(config.rules["no-var-keyword"]);
- assert.isFalse(config.rules["no-eval"]);
+ assert.equal("none", config.rules["no-eval"].severity);
});
describe("with config not relative to tslint", () => {
@@ -158,13 +184,17 @@ describe("Configuration", () => {
assert.isTrue(fs.existsSync(config.rulesDirectory![1]));
/* tslint:disable:object-literal-sort-keys */
assert.deepEqual(config.jsRules, {
- "always-fail": false,
+ "always-fail": {
+ severity: "none",
+ },
"rule-one": true,
"rule-two": true,
"rule-four": true,
});
assert.deepEqual(config.rules, {
- "always-fail": false,
+ "always-fail": {
+ severity: "none",
+ },
"rule-one": true,
"rule-two": true,
"rule-four": true,
@@ -177,16 +207,28 @@ describe("Configuration", () => {
assert.isArray(config.rulesDirectory);
assert.deepEqual(config.jsRules, {
- "always-fail": false,
- "no-fail": true,
+ "always-fail": {
+ severity: "none",
+ },
+ "no-fail": {
+ severity: "error",
+ },
"rule-one": true,
- "rule-two": true,
+ "rule-two": {
+ severity: "error",
+ },
});
assert.deepEqual(config.rules, {
- "always-fail": false,
- "no-fail": true,
+ "always-fail": {
+ severity: "none",
+ },
+ "no-fail": {
+ severity: "error",
+ },
"rule-one": true,
- "rule-two": true,
+ "rule-two": {
+ severity: "error",
+ },
});
});
@@ -195,12 +237,16 @@ describe("Configuration", () => {
/* tslint:disable:object-literal-sort-keys */
assert.deepEqual(config.jsRules, {
- "rule-two": true,
+ "rule-two": {
+ severity: "error",
+ },
"rule-three": "//not a comment",
"rule-four": "/*also not a comment*/",
});
assert.deepEqual(config.rules, {
- "rule-two": true,
+ "rule-two": {
+ severity: "error",
+ },
"rule-three": "//not a comment",
"rule-four": "/*also not a comment*/",
});
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..4a2778189f0 100644
--- a/test/ruleLoaderTests.ts
+++ b/test/ruleLoaderTests.ts
@@ -50,6 +50,49 @@ describe("Rule Loader", () => {
assert.equal(rules.length, 1);
});
+ it("properly sets rule severity with options", () => {
+ const withOptions = {
+ "callable-types": true,
+ "max-line-length": {
+ options: 140,
+ severity: "warning",
+ },
+ };
+
+ const rules = loadRules(withOptions, {}, [builtRulesDir]);
+ assert.equal(rules.length, 2);
+ assert.equal(rules[0].getOptions().ruleSeverity, "error");
+ assert.equal(rules[1].getOptions().ruleSeverity, "warning");
+ });
+
+ it("properly sets rule severity with no options", () => {
+ const noOptions = {
+ "callable-types": true,
+ "interface-name": {
+ severity: "warning",
+ },
+ };
+
+ const rules = loadRules(noOptions, {}, [builtRulesDir]);
+ assert.equal(rules.length, 2);
+ assert.equal(rules[0].getOptions().ruleSeverity, "error");
+ assert.equal(rules[1].getOptions().ruleSeverity, "warning");
+ });
+
+ it("properly sets rule severity with options but no severity", () => {
+ const noSeverity = {
+ "callable-types": true,
+ "max-line-length": {
+ options: 140,
+ },
+ };
+
+ const rules = loadRules(noSeverity, {}, [builtRulesDir]);
+ assert.equal(rules.length, 2);
+ assert.equal(rules[0].getOptions().ruleSeverity, "error");
+ assert.equal(rules[1].getOptions().ruleSeverity, "error");
+ });
+
it("loads disabled rules if rule in enableDisableRuleMap", () => {
const validConfiguration: {[name: string]: any} = {
"class-name": true,