mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-03-15 14:05:47 -05:00
move eslint rules from eslint-plugin-microsoft-typescript to scripts/eslint
This commit is contained in:
105
scripts/eslint/rules/boolean-trivia.ts
Normal file
105
scripts/eslint/rules/boolean-trivia.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { SyntaxKind } from "typescript";
|
||||
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/experimental-utils";
|
||||
import { getEsTreeNodeToTSNodeMap, createRule } from "./utils";
|
||||
|
||||
export = createRule({
|
||||
name: "boolean-trivia",
|
||||
meta: {
|
||||
docs: {
|
||||
description: ``,
|
||||
category: "Best Practices",
|
||||
recommended: "error",
|
||||
},
|
||||
messages: {
|
||||
booleanTriviaArgumentError: `Tag argument with parameter name`,
|
||||
booleanTriviaArgumentSpaceError: `There should be 1 space between an argument and its comment`,
|
||||
},
|
||||
schema: [],
|
||||
type: "problem",
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
const esTreeNodeToTSNodeMap = getEsTreeNodeToTSNodeMap(context.parserServices);
|
||||
const sourceCode = context.getSourceCode();
|
||||
const sourceCodeText = sourceCode.getText();
|
||||
|
||||
const isSetOrAssert = (name: string): boolean => name.startsWith("set") || name.startsWith("assert");
|
||||
const isTrivia = (node: TSESTree.Expression): boolean => {
|
||||
const tsNode = esTreeNodeToTSNodeMap.get(node);
|
||||
|
||||
if (tsNode.kind === SyntaxKind.Identifier) {
|
||||
return tsNode.originalKeywordKind === SyntaxKind.UndefinedKeyword;
|
||||
}
|
||||
|
||||
return [SyntaxKind.TrueKeyword, SyntaxKind.FalseKeyword, SyntaxKind.NullKeyword].indexOf(tsNode.kind) >= 0;
|
||||
};
|
||||
|
||||
const shouldIgnoreCalledExpression = (node: TSESTree.CallExpression): boolean => {
|
||||
if (node.callee && node.callee.type === AST_NODE_TYPES.MemberExpression) {
|
||||
const methodName = node.callee.property.type === AST_NODE_TYPES.Identifier
|
||||
? node.callee.property.name
|
||||
: "";
|
||||
|
||||
if (isSetOrAssert(methodName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ["apply", "call", "equal", "fail", "isTrue", "output", "stringify", "push"].indexOf(methodName) >= 0;
|
||||
}
|
||||
|
||||
if (node.callee && node.callee.type === AST_NODE_TYPES.Identifier) {
|
||||
const functionName = node.callee.name;
|
||||
|
||||
if (isSetOrAssert(functionName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return [
|
||||
"createImportSpecifier",
|
||||
"createAnonymousType",
|
||||
"createSignature",
|
||||
"createProperty",
|
||||
"resolveName",
|
||||
"contains",
|
||||
].indexOf(functionName) >= 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const checkArg = (node: TSESTree.Expression): void => {
|
||||
if (!isTrivia(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const comments = sourceCode.getCommentsBefore(node);
|
||||
if (!comments || comments.length !== 1 || comments[0].type !== "Block") {
|
||||
context.report({ messageId: "booleanTriviaArgumentError", node });
|
||||
return;
|
||||
}
|
||||
|
||||
const argRangeStart = node.range[0];
|
||||
const commentRangeEnd = comments[0].range[1];
|
||||
const hasNewLine = sourceCodeText.slice(commentRangeEnd, argRangeStart).indexOf("\n") >= 0;
|
||||
|
||||
if (argRangeStart !== commentRangeEnd + 1 && !hasNewLine) {
|
||||
context.report({ messageId: "booleanTriviaArgumentSpaceError", node });
|
||||
}
|
||||
};
|
||||
|
||||
const checkBooleanTrivia = (node: TSESTree.CallExpression) => {
|
||||
if (shouldIgnoreCalledExpression(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const arg of node.arguments) {
|
||||
checkArg(arg);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
CallExpression: checkBooleanTrivia,
|
||||
};
|
||||
},
|
||||
});
|
||||
60
scripts/eslint/rules/debug-assert.ts
Normal file
60
scripts/eslint/rules/debug-assert.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/experimental-utils";
|
||||
import { createRule } from "./utils";
|
||||
|
||||
export = createRule({
|
||||
name: "debug-assert",
|
||||
meta: {
|
||||
docs: {
|
||||
description: ``,
|
||||
category: "Possible Errors",
|
||||
recommended: "error",
|
||||
},
|
||||
messages: {
|
||||
secondArgumentDebugAssertError: `Second argument to 'Debug.assert' should be a string literal`,
|
||||
thirdArgumentDebugAssertError: `Third argument to 'Debug.assert' should be a string literal or arrow function`,
|
||||
},
|
||||
schema: [],
|
||||
type: "problem",
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
const isArrowFunction = (node: TSESTree.Node) => node.type === AST_NODE_TYPES.ArrowFunctionExpression;
|
||||
const isStringLiteral = (node: TSESTree.Node): boolean => (
|
||||
(node.type === AST_NODE_TYPES.Literal && typeof node.value === "string") || node.type === AST_NODE_TYPES.TemplateLiteral
|
||||
);
|
||||
|
||||
const isDebugAssert = (node: TSESTree.MemberExpression): boolean => (
|
||||
node.object.type === AST_NODE_TYPES.Identifier
|
||||
&& node.object.name === "Debug"
|
||||
&& node.property.type === AST_NODE_TYPES.Identifier
|
||||
&& node.property.name === "assert"
|
||||
);
|
||||
|
||||
const checkDebugAssert = (node: TSESTree.CallExpression) => {
|
||||
const args = node.arguments;
|
||||
const argsLen = args.length;
|
||||
if (!(node.callee.type === AST_NODE_TYPES.MemberExpression && isDebugAssert(node.callee)) || argsLen < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message1Node = args[1];
|
||||
if (message1Node && !isStringLiteral(message1Node)) {
|
||||
context.report({ messageId: "secondArgumentDebugAssertError", node: message1Node });
|
||||
}
|
||||
|
||||
if (argsLen < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message2Node = args[2];
|
||||
if (message2Node && (!isStringLiteral(message2Node) && !isArrowFunction(message2Node))) {
|
||||
context.report({ messageId: "thirdArgumentDebugAssertError", node: message2Node });
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
CallExpression: checkDebugAssert,
|
||||
};
|
||||
},
|
||||
});
|
||||
81
scripts/eslint/rules/no-double-space.ts
Normal file
81
scripts/eslint/rules/no-double-space.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { TSESTree } from "@typescript-eslint/experimental-utils";
|
||||
import { SyntaxKind } from "typescript";
|
||||
import { getEsTreeNodeToTSNodeMap, createRule } from "./utils";
|
||||
|
||||
export = createRule({
|
||||
name: "no-double-space",
|
||||
meta: {
|
||||
docs: {
|
||||
description: ``,
|
||||
category: "Stylistic Issues",
|
||||
recommended: "error",
|
||||
},
|
||||
messages: {
|
||||
noDoubleSpaceError: `Use only one space`,
|
||||
},
|
||||
schema: [],
|
||||
type: "problem",
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
const esTreeNodeToTSNodeMap = getEsTreeNodeToTSNodeMap(context.parserServices);
|
||||
const sourceCode = context.getSourceCode();
|
||||
const lines = sourceCode.getLines();
|
||||
|
||||
const isLiteral = (node: TSESTree.Node | null) => {
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const tsNode = esTreeNodeToTSNodeMap.get(node);
|
||||
if (!tsNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return [
|
||||
SyntaxKind.NoSubstitutionTemplateLiteral,
|
||||
SyntaxKind.RegularExpressionLiteral,
|
||||
SyntaxKind.TemplateMiddle,
|
||||
SyntaxKind.StringLiteral,
|
||||
SyntaxKind.TemplateHead,
|
||||
SyntaxKind.TemplateTail,
|
||||
].indexOf(tsNode.kind) >= 0;
|
||||
};
|
||||
|
||||
const checkDoubleSpace = (node: TSESTree.Node) => {
|
||||
lines.forEach((line, index) => {
|
||||
const firstNonSpace = /\S/.exec(line);
|
||||
if (!firstNonSpace || line.includes("@param")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow common uses of double spaces
|
||||
// * To align `=` or `!=` signs
|
||||
// * To align comments at the end of lines
|
||||
// * To indent inside a comment
|
||||
// * To use two spaces after a period
|
||||
// * To include aligned `->` in a comment
|
||||
const rgx = /[^/*. ][ ]{2}[^-!/= ]/g;
|
||||
rgx.lastIndex = firstNonSpace.index;
|
||||
const doubleSpace = rgx.exec(line);
|
||||
|
||||
if (!doubleSpace) {
|
||||
return;
|
||||
}
|
||||
|
||||
const locIndex = sourceCode.getIndexFromLoc({ column: doubleSpace.index, line: index + 1 });
|
||||
const sourceNode = sourceCode.getNodeByRangeIndex(locIndex);
|
||||
if (isLiteral(sourceNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.report({ messageId: "noDoubleSpaceError", node, loc: { line: index + 1, column: doubleSpace.index + 1 } });
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
Program: checkDoubleSpace,
|
||||
};
|
||||
},
|
||||
});
|
||||
32
scripts/eslint/rules/no-in-operator.ts
Normal file
32
scripts/eslint/rules/no-in-operator.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { TSESTree } from "@typescript-eslint/experimental-utils";
|
||||
import { createRule } from "./utils";
|
||||
|
||||
export = createRule({
|
||||
name: "no-in-operator",
|
||||
meta: {
|
||||
docs: {
|
||||
description: ``,
|
||||
category: "Best Practices",
|
||||
recommended: "error",
|
||||
},
|
||||
messages: {
|
||||
noInOperatorError: `Don't use the 'in' keyword - use 'hasProperty' to check for key presence instead`,
|
||||
},
|
||||
schema: [],
|
||||
type: "suggestion",
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
const IN_OPERATOR = "in";
|
||||
const checkInOperator = (node: TSESTree.BinaryExpression) => {
|
||||
if (node.operator === IN_OPERATOR) {
|
||||
context.report({ messageId: "noInOperatorError", node });
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
BinaryExpression: checkInOperator,
|
||||
};
|
||||
},
|
||||
});
|
||||
70
scripts/eslint/rules/no-keywords.ts
Normal file
70
scripts/eslint/rules/no-keywords.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { TSESTree, AST_NODE_TYPES } from "@typescript-eslint/experimental-utils";
|
||||
import { createRule } from "./utils";
|
||||
|
||||
export = createRule({
|
||||
name: "no-keywords",
|
||||
meta: {
|
||||
docs: {
|
||||
description: `disallows the use of certain TypeScript keywords as variable or parameter names`,
|
||||
category: "Stylistic Issues",
|
||||
recommended: "error",
|
||||
},
|
||||
messages: {
|
||||
noKeywordsError: `{{ name }} clashes with keyword/type`,
|
||||
},
|
||||
schema: [{
|
||||
properties: {
|
||||
properties: { type: "boolean" },
|
||||
keywords: { type: "boolean" },
|
||||
},
|
||||
type: "object",
|
||||
}],
|
||||
type: "suggestion",
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
const keywords = [
|
||||
"Undefined",
|
||||
"undefined",
|
||||
"Boolean",
|
||||
"boolean",
|
||||
"String",
|
||||
"string",
|
||||
"Number",
|
||||
"number",
|
||||
"any",
|
||||
];
|
||||
|
||||
const hasKeyword = (name: string) => keywords.includes(name);
|
||||
|
||||
const shouldReport = (node: TSESTree.Identifier) => {
|
||||
if (!node || !node.parent || !hasKeyword(node.name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const parent = node.parent;
|
||||
if (parent.type === AST_NODE_TYPES.FunctionDeclaration || parent.type === AST_NODE_TYPES.FunctionExpression) {
|
||||
return !(parent.id && hasKeyword(parent.id.name));
|
||||
}
|
||||
|
||||
if (parent.type === AST_NODE_TYPES.TSMethodSignature && parent.key.type === AST_NODE_TYPES.Identifier) {
|
||||
return !(parent.key && hasKeyword(parent.key.name));
|
||||
}
|
||||
|
||||
return [
|
||||
AST_NODE_TYPES.ArrowFunctionExpression,
|
||||
AST_NODE_TYPES.VariableDeclarator,
|
||||
AST_NODE_TYPES.TSFunctionType,
|
||||
].includes(node.parent.type);
|
||||
};
|
||||
|
||||
const check = (node: TSESTree.Identifier) => {
|
||||
if (shouldReport(node)) {
|
||||
context.report({ messageId: "noKeywordsError", data: { name: node.name }, node });
|
||||
}
|
||||
};
|
||||
|
||||
return { Identifier: check };
|
||||
},
|
||||
});
|
||||
43
scripts/eslint/rules/no-type-assertion-whitespace.ts
Normal file
43
scripts/eslint/rules/no-type-assertion-whitespace.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { TSESTree } from "@typescript-eslint/experimental-utils";
|
||||
import { createRule } from "./utils";
|
||||
|
||||
export = createRule({
|
||||
name: "no-type-assertion-whitespace",
|
||||
meta: {
|
||||
docs: {
|
||||
description: ``,
|
||||
category: "Stylistic Issues",
|
||||
recommended: "error",
|
||||
},
|
||||
messages: {
|
||||
noTypeAssertionWhitespace: `Excess trailing whitespace found around type assertion`,
|
||||
},
|
||||
schema: [],
|
||||
type: "problem",
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
const checkTypeAssertionWhitespace = (node: TSESTree.TSTypeAssertion) => {
|
||||
const leftToken = sourceCode.getLastToken(node.typeAnnotation);
|
||||
const rightToken = sourceCode.getFirstToken(node.expression);
|
||||
|
||||
if (!leftToken || !rightToken) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) {
|
||||
context.report({
|
||||
messageId: "noTypeAssertionWhitespace",
|
||||
node,
|
||||
loc: { column: leftToken.loc.end.column + 1, line: leftToken.loc.end.line },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
TSTypeAssertion: checkTypeAssertionWhitespace,
|
||||
};
|
||||
},
|
||||
});
|
||||
71
scripts/eslint/rules/object-literal-surrounding-space.ts
Normal file
71
scripts/eslint/rules/object-literal-surrounding-space.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { TSESTree } from "@typescript-eslint/experimental-utils";
|
||||
import { createRule } from "./utils";
|
||||
|
||||
export = createRule({
|
||||
name: "object-literal-surrounding-space",
|
||||
meta: {
|
||||
docs: {
|
||||
description: ``,
|
||||
category: "Stylistic Issues",
|
||||
recommended: "error",
|
||||
},
|
||||
messages: {
|
||||
leadingExcessStringError: `No trailing whitespace found on single-line object literal`,
|
||||
leadingStringError: `No leading whitespace found on single-line object literal`,
|
||||
|
||||
trailingExcessStringError: `Excess trailing whitespace found on single-line object literal.`,
|
||||
trailingStringError: `No trailing whitespace found on single-line object literal`,
|
||||
},
|
||||
schema: [],
|
||||
type: "suggestion",
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
const SPACE_SYMBOL = " ";
|
||||
const CLOSE_SYMBOL = "}";
|
||||
const OPEN_SYMBOL = "{";
|
||||
|
||||
const manySpaces = (text: string, startIndex: number): boolean => (
|
||||
[startIndex, startIndex + 1].every(i => text.charAt(i) === SPACE_SYMBOL)
|
||||
);
|
||||
|
||||
const checkObjectLiteralSurroundingSpace = (node: TSESTree.ObjectExpression) => {
|
||||
const text = sourceCode.getText(node);
|
||||
const startLine = node.loc.start.line;
|
||||
const endLine = node.loc.end.line;
|
||||
|
||||
if (!node.properties.length || !text.match(/^{[^\n]+}$/g)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (text.charAt(0) === OPEN_SYMBOL) {
|
||||
if (text.charAt(1) !== SPACE_SYMBOL) {
|
||||
context.report({ messageId: "leadingStringError", node });
|
||||
}
|
||||
|
||||
if (manySpaces(text, 1)) {
|
||||
context.report({ messageId: "leadingExcessStringError", node, loc: { column: node.loc.start.column + 1, line: startLine } });
|
||||
}
|
||||
}
|
||||
|
||||
if (text.charAt(text.length - 1) === CLOSE_SYMBOL) {
|
||||
const index = text.length - 2;
|
||||
const endColumn = node.loc.end.column;
|
||||
|
||||
if (text.charAt(index) !== SPACE_SYMBOL) {
|
||||
context.report({ messageId: "trailingStringError", node, loc: { column: endColumn - 1, line: endLine } });
|
||||
}
|
||||
|
||||
if (manySpaces(text, index - 1)) {
|
||||
context.report({ messageId: "trailingExcessStringError", node, loc: { column: endColumn - 2, line: endLine } });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
ObjectExpression: checkObjectLiteralSurroundingSpace,
|
||||
};
|
||||
},
|
||||
});
|
||||
91
scripts/eslint/rules/only-arrow-functions.ts
Normal file
91
scripts/eslint/rules/only-arrow-functions.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/experimental-utils";
|
||||
import { createRule } from "./utils";
|
||||
|
||||
type MessageId = "onlyArrowFunctionsError";
|
||||
type Options = [{
|
||||
allowNamedFunctions?: boolean;
|
||||
allowDeclarations?: boolean;
|
||||
}];
|
||||
|
||||
export = createRule<Options, MessageId>({
|
||||
name: "only-arrow-functions",
|
||||
meta: {
|
||||
docs: {
|
||||
description: `Disallows traditional (non-arrow) function expressions.`,
|
||||
category: "Best Practices",
|
||||
recommended: "error",
|
||||
},
|
||||
messages: {
|
||||
onlyArrowFunctionsError: "non-arrow functions are forbidden",
|
||||
},
|
||||
schema: [{
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
allowNamedFunctions: { type: "boolean" },
|
||||
allowDeclarations: { type: "boolean" },
|
||||
},
|
||||
type: "object",
|
||||
}],
|
||||
type: "suggestion",
|
||||
},
|
||||
defaultOptions: [{
|
||||
allowNamedFunctions: false,
|
||||
allowDeclarations: false,
|
||||
}],
|
||||
|
||||
create(context, [{ allowNamedFunctions, allowDeclarations }]) {
|
||||
|
||||
const isThisParameter = (node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression) => (
|
||||
node.params.length && !!node.params.find(param => param.type === AST_NODE_TYPES.Identifier && param.name === "this")
|
||||
);
|
||||
|
||||
const isMethodType = (node: TSESTree.Node) => {
|
||||
const types = [
|
||||
AST_NODE_TYPES.MethodDefinition,
|
||||
AST_NODE_TYPES.Property,
|
||||
];
|
||||
|
||||
const parent = node.parent;
|
||||
if (!parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return node.type === AST_NODE_TYPES.FunctionExpression && types.includes(parent.type);
|
||||
};
|
||||
|
||||
const stack: boolean[] = [];
|
||||
const enterFunction = () => {
|
||||
stack.push(false);
|
||||
};
|
||||
|
||||
const markThisUsed = () => {
|
||||
if (stack.length) {
|
||||
stack[stack.length - 1] = true;
|
||||
}
|
||||
};
|
||||
|
||||
const exitFunction = (node: TSESTree.FunctionDeclaration | TSESTree.FunctionExpression) => {
|
||||
const methodUsesThis = stack.pop();
|
||||
|
||||
if (node.type === AST_NODE_TYPES.FunctionDeclaration && allowDeclarations) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((allowNamedFunctions && node.id !== null) || isMethodType(node)) { // eslint-disable-line no-null/no-null
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(node.generator || methodUsesThis || isThisParameter(node))) {
|
||||
context.report({ messageId: "onlyArrowFunctionsError", node });
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
"FunctionDeclaration": enterFunction,
|
||||
"FunctionDeclaration:exit": exitFunction,
|
||||
"FunctionExpression": enterFunction,
|
||||
"FunctionExpression:exit": exitFunction,
|
||||
"ThisExpression": markThisUsed,
|
||||
};
|
||||
},
|
||||
});
|
||||
44
scripts/eslint/rules/type-operator-spacing.ts
Normal file
44
scripts/eslint/rules/type-operator-spacing.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { TSESTree, AST_TOKEN_TYPES } from "@typescript-eslint/experimental-utils";
|
||||
import { createRule } from "./utils";
|
||||
|
||||
export = createRule({
|
||||
name: "type-operator-spacing",
|
||||
meta: {
|
||||
docs: {
|
||||
description: ``,
|
||||
category: "Stylistic Issues",
|
||||
recommended: "error",
|
||||
},
|
||||
messages: {
|
||||
typeOperatorSpacingError: `The '|' and '&' operators must be surrounded by spaces`,
|
||||
},
|
||||
schema: [],
|
||||
type: "suggestion",
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
const tokens = ["|", "&"];
|
||||
const text = sourceCode.getText();
|
||||
|
||||
const checkTypeOperatorSpacing = (node: TSESTree.TSIntersectionType | TSESTree.TSUnionType) => {
|
||||
node.types.forEach(node => {
|
||||
const token = sourceCode.getTokenBefore(node);
|
||||
|
||||
if (!!token && token.type === AST_TOKEN_TYPES.Punctuator && tokens.indexOf(token.value) >= 0) {
|
||||
const [start, end] = token.range;
|
||||
|
||||
if (/\S/.test(text[start - 1]) || /\S/.test(text[end])) {
|
||||
context.report({ messageId: "typeOperatorSpacingError", node: token });
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
TSIntersectionType: checkTypeOperatorSpacing,
|
||||
TSUnionType: checkTypeOperatorSpacing,
|
||||
};
|
||||
},
|
||||
});
|
||||
18
scripts/eslint/rules/utils.ts
Normal file
18
scripts/eslint/rules/utils.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { ParserServices, ESLintUtils } from "@typescript-eslint/experimental-utils";
|
||||
export const createRule = ESLintUtils.RuleCreator(() => "");
|
||||
|
||||
export const getTypeChecker = (parserServices: ParserServices | undefined) => {
|
||||
if (!parserServices || !parserServices.program || !parserServices.program.getTypeChecker) {
|
||||
throw new Error("'typeChecker' was not found");
|
||||
}
|
||||
|
||||
return parserServices.program.getTypeChecker();
|
||||
};
|
||||
|
||||
export const getEsTreeNodeToTSNodeMap = (parserServices: ParserServices | undefined) => {
|
||||
if (!parserServices || !parserServices.esTreeNodeToTSNodeMap) {
|
||||
throw new Error("'esTreeNodeToTSNodeMap' was not found");
|
||||
}
|
||||
|
||||
return parserServices.esTreeNodeToTSNodeMap;
|
||||
};
|
||||
73
scripts/eslint/tests/boolean-trivia.test.ts
Normal file
73
scripts/eslint/tests/boolean-trivia.test.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { RuleTester, ROOT_DIR } from "./support/RuleTester";
|
||||
import rule = require("../rules/boolean-trivia");
|
||||
|
||||
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
tsconfigRootDir: ROOT_DIR,
|
||||
ecmaFeatures: {},
|
||||
ecmaVersion: 6,
|
||||
sourceType: "module",
|
||||
project: "./tsconfig.json",
|
||||
},
|
||||
parser: require.resolve("@typescript-eslint/parser"),
|
||||
});
|
||||
|
||||
ruleTester.run("boolean-trivia", rule, {
|
||||
valid: [{
|
||||
code: `
|
||||
const fn = (prop: boolean) => {};
|
||||
fn(/* boolean prop */ true);
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
const fn = (prop: null) => {};
|
||||
fn(/* null prop */ null);
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
const fn = (prop: null) => {};
|
||||
fn(/*null prop*/ null);
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
const fn = (prop: boolean) => {};
|
||||
fn(/* comment */
|
||||
false
|
||||
);
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
const fn = (prop: boolean) => {};
|
||||
fn.apply(null, true);
|
||||
`,
|
||||
}],
|
||||
|
||||
invalid: [{
|
||||
code: `
|
||||
const fn = (prop: null) => {};
|
||||
fn(null);
|
||||
`,
|
||||
errors: [{ messageId: "booleanTriviaArgumentError" }],
|
||||
}, {
|
||||
code: `
|
||||
const fn = (prop: boolean) => {};
|
||||
fn(false);
|
||||
`,
|
||||
errors: [{ messageId: "booleanTriviaArgumentError" }],
|
||||
}, {
|
||||
code: `
|
||||
const fn = (prop: boolean) => {};
|
||||
fn(/* boolean arg */false);
|
||||
`,
|
||||
errors: [{ messageId: "booleanTriviaArgumentSpaceError" }],
|
||||
}, {
|
||||
code: `
|
||||
const fn = (prop: boolean) => {};
|
||||
fn(/* first comment */ /* second comment */ false);
|
||||
`,
|
||||
errors: [{ messageId: "booleanTriviaArgumentError" }],
|
||||
}],
|
||||
});
|
||||
40
scripts/eslint/tests/debug-assert.test.ts
Normal file
40
scripts/eslint/tests/debug-assert.test.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { RuleTester } from "./support/RuleTester";
|
||||
import rule = require("../rules/debug-assert");
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
},
|
||||
parser: require.resolve("@typescript-eslint/parser"),
|
||||
});
|
||||
|
||||
ruleTester.run("debug-assert", rule, {
|
||||
valid: [{
|
||||
code: `Debug.assert(true)`,
|
||||
}, {
|
||||
code: `Debug.assert(true, 'error message')`,
|
||||
}, {
|
||||
code: `Debug.assert(true, 'error message 1', 'error message 2')`,
|
||||
}, {
|
||||
code: `Debug.assert(true, 'error message 1', () => {})`,
|
||||
}, {
|
||||
code: "Debug.assert(true, `error message 1`, () => {})",
|
||||
}, {
|
||||
code: `Debug.assert(true, "error message 1", () => {})`,
|
||||
}],
|
||||
|
||||
invalid: [{
|
||||
code: `Debug.assert(true, 1)`,
|
||||
errors: [{ messageId: "secondArgumentDebugAssertError" }],
|
||||
}, {
|
||||
code: `Debug.assert(true, 'error message', 1)`,
|
||||
errors: [{ messageId: "thirdArgumentDebugAssertError" }],
|
||||
}, {
|
||||
code: `Debug.assert(true, null, 1)`,
|
||||
errors: [{
|
||||
messageId: "secondArgumentDebugAssertError",
|
||||
}, {
|
||||
messageId: "thirdArgumentDebugAssertError",
|
||||
}],
|
||||
}],
|
||||
});
|
||||
115
scripts/eslint/tests/no-double-space.test.ts
Normal file
115
scripts/eslint/tests/no-double-space.test.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { RuleTester, ROOT_DIR } from "./support/RuleTester";
|
||||
import rule = require("../rules/no-double-space");
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parser: require.resolve("@typescript-eslint/parser"),
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
tsconfigRootDir: ROOT_DIR,
|
||||
ecmaFeatures: {},
|
||||
ecmaVersion: 6,
|
||||
sourceType: "module",
|
||||
project: "./tsconfig.json",
|
||||
},
|
||||
});
|
||||
|
||||
ruleTester.run("no-double-space", rule, {
|
||||
valid: [{
|
||||
code: `const a = {};`,
|
||||
}, {
|
||||
code: `function fn() {}`,
|
||||
}, {
|
||||
code: `const a = " ";`,
|
||||
}, {
|
||||
code: `// ^ ^`,
|
||||
}, {
|
||||
code: `class Cl {}`,
|
||||
}, {
|
||||
code: `// comment `,
|
||||
}, {
|
||||
code: `/* comment */`,
|
||||
}, {
|
||||
code: `" string ";`,
|
||||
}, {
|
||||
code: `/ regexp /g;`,
|
||||
}, {
|
||||
code: `const rgx = / regexp /g;`,
|
||||
}, {
|
||||
code: "const str = ` string template`;",
|
||||
}, {
|
||||
code: ` // comment`,
|
||||
}, {
|
||||
code: ` /* comment */`,
|
||||
}, {
|
||||
code: `// `,
|
||||
}, {
|
||||
code: `
|
||||
const a =
|
||||
1;
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
/**
|
||||
* comment
|
||||
*/
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
// comment
|
||||
// - comment
|
||||
// - comment
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
interface Props {
|
||||
prop: string[]; // comment prop
|
||||
propB: string[]; // comment propB
|
||||
}
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
/**
|
||||
* Returns a JSON-encoded value of the type: string[]
|
||||
*
|
||||
* @param exclude A JSON encoded string[] containing the paths to exclude
|
||||
* when enumerating the directory.
|
||||
*/
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
const obj = {
|
||||
content: "function f() { 1; }",
|
||||
};
|
||||
`,
|
||||
}],
|
||||
|
||||
invalid: [{
|
||||
code: `const a = {};`,
|
||||
errors: [{ messageId: "noDoubleSpaceError", line: 1, column: 6 }],
|
||||
}, {
|
||||
code: `function fn() {}`,
|
||||
errors: [{ messageId: "noDoubleSpaceError", line: 1, column: 9 }],
|
||||
}, {
|
||||
code: `class Cl {}`,
|
||||
errors: [{ messageId: "noDoubleSpaceError", line: 1, column: 6 }],
|
||||
}, {
|
||||
code: "const str = ` string template`;",
|
||||
errors: [{ messageId: "noDoubleSpaceError", line: 1, column: 12 }],
|
||||
}, {
|
||||
code: `/** comment */`,
|
||||
errors: [{ messageId: "noDoubleSpaceError", line: 1, column: 12 }],
|
||||
}, {
|
||||
code: `/** comment with many spaces */`,
|
||||
errors: [{ messageId: "noDoubleSpaceError", line: 1, column: 12 }],
|
||||
}, {
|
||||
code: `// comment with many spaces`,
|
||||
errors: [{ messageId: "noDoubleSpaceError", line: 1, column: 11 }],
|
||||
}, {
|
||||
code: `
|
||||
const a = 1;
|
||||
const b = 2;
|
||||
const c = 3;
|
||||
`.trim(),
|
||||
errors: [{ messageId: "noDoubleSpaceError", line: 3, column: 10 }],
|
||||
}],
|
||||
});
|
||||
26
scripts/eslint/tests/no-in-operator.test.ts
Normal file
26
scripts/eslint/tests/no-in-operator.test.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { RuleTester } from "./support/RuleTester";
|
||||
import rule = require("../rules/no-in-operator");
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
},
|
||||
parser: require.resolve("@typescript-eslint/parser"),
|
||||
});
|
||||
|
||||
ruleTester.run("no-in-operator", rule, {
|
||||
valid: [{
|
||||
code: `
|
||||
const prop = {};
|
||||
prop.hasProperty('a');
|
||||
`,
|
||||
}],
|
||||
|
||||
invalid: [{
|
||||
code: `
|
||||
const prop = {};
|
||||
prop in 'a';
|
||||
`,
|
||||
errors: [{ messageId: "noInOperatorError" }],
|
||||
}],
|
||||
});
|
||||
77
scripts/eslint/tests/no-keywords.test.ts
Normal file
77
scripts/eslint/tests/no-keywords.test.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { RuleTester } from "./support/RuleTester";
|
||||
import rule = require("../rules/no-keywords");
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
},
|
||||
parser: require.resolve("@typescript-eslint/parser"),
|
||||
});
|
||||
|
||||
ruleTester.run("no-keywords", rule, {
|
||||
valid: [{
|
||||
code: `const a = {};`,
|
||||
}, {
|
||||
code: `function a() {};`,
|
||||
}, {
|
||||
code: `const x = function string() {};`,
|
||||
}, {
|
||||
code: `const y = function () {};`,
|
||||
}, {
|
||||
code: `const y = () => {};`,
|
||||
}, {
|
||||
code: `
|
||||
class A {
|
||||
b = () => {}
|
||||
a() {}
|
||||
number() {}
|
||||
}
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
interface A {
|
||||
b(): void;
|
||||
}
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
const obj = {
|
||||
a: null,
|
||||
b() {},
|
||||
c: function (c: number) {},
|
||||
string: function d (d: string) {},
|
||||
e: () => {},
|
||||
};
|
||||
`,
|
||||
}],
|
||||
|
||||
invalid: [{
|
||||
code: `const number = 1;`,
|
||||
errors: [{ messageId: "noKeywordsError" }],
|
||||
}, {
|
||||
code: `function x(number: number) {};`,
|
||||
errors: [{ messageId: "noKeywordsError" }],
|
||||
}, {
|
||||
code: `const y = function (number: number) {};`,
|
||||
errors: [{ messageId: "noKeywordsError" }],
|
||||
}, {
|
||||
code: `const y = (number: number) => {};`,
|
||||
errors: [{ messageId: "noKeywordsError" }],
|
||||
}, {
|
||||
code: `
|
||||
class A {
|
||||
b = function (any: any) {};
|
||||
a(number: number) {}
|
||||
}
|
||||
`,
|
||||
errors: [{ messageId: "noKeywordsError" }, { messageId: "noKeywordsError" }],
|
||||
}, {
|
||||
code: `
|
||||
interface A {
|
||||
a(number: number): void;
|
||||
b: (any: any) => void;
|
||||
}
|
||||
`,
|
||||
errors: [{ messageId: "noKeywordsError" }, { messageId: "noKeywordsError" }],
|
||||
}],
|
||||
});
|
||||
31
scripts/eslint/tests/no-type-assertion-whitespace.test.ts
Normal file
31
scripts/eslint/tests/no-type-assertion-whitespace.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { RuleTester } from "./support/RuleTester";
|
||||
import rule = require("../rules/no-type-assertion-whitespace");
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
},
|
||||
parser: require.resolve("@typescript-eslint/parser"),
|
||||
});
|
||||
|
||||
ruleTester.run("no-type-assertion-whitespace", rule, {
|
||||
valid: [{
|
||||
code: `const a = <number>1`,
|
||||
}, {
|
||||
code: `const s = <Type>(new Symbol(1, 'name'));`,
|
||||
}],
|
||||
|
||||
invalid: [{
|
||||
code: `const a = <number> 1`,
|
||||
errors: [{ messageId: "noTypeAssertionWhitespace", column: 19, line: 1 }],
|
||||
}, {
|
||||
code: `const a = <number> 1`,
|
||||
errors: [{ messageId: "noTypeAssertionWhitespace", column: 19, line: 1 }],
|
||||
}, {
|
||||
code: `const a = <number> 1`,
|
||||
errors: [{ messageId: "noTypeAssertionWhitespace", column: 19, line: 1 }],
|
||||
}, {
|
||||
code: `const s = <Type> (new Symbol(1, 'name'));`,
|
||||
errors: [{ messageId: "noTypeAssertionWhitespace", column: 17, line: 1 }],
|
||||
}],
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import { RuleTester } from "./support/RuleTester";
|
||||
import rule = require("../rules/object-literal-surrounding-space");
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
},
|
||||
parser: require.resolve("@typescript-eslint/parser"),
|
||||
});
|
||||
|
||||
ruleTester.run("object-literal-surrounding-space", rule, {
|
||||
valid: [{
|
||||
code: `const prop = {}`,
|
||||
}, {
|
||||
code: `const prop = { }`,
|
||||
}, {
|
||||
code: `const prop = { x: 1 }`,
|
||||
}],
|
||||
|
||||
invalid: [{
|
||||
code: `const prop = {x: 1}`,
|
||||
errors: [{
|
||||
messageId: "leadingStringError",
|
||||
}, {
|
||||
messageId: "trailingStringError",
|
||||
}],
|
||||
}, {
|
||||
code: `const prop = { x: 1 }`,
|
||||
errors: [{ messageId: "leadingExcessStringError" }],
|
||||
}, {
|
||||
code: `const prop = { x: 1 }`,
|
||||
errors: [{ messageId: "trailingExcessStringError" }],
|
||||
}, {
|
||||
code: `const prop = { x: 1}`,
|
||||
errors: [{ messageId: "trailingStringError" }],
|
||||
}, {
|
||||
code: `const prop = {x: 1 }`,
|
||||
errors: [{ messageId: "leadingStringError" }],
|
||||
}],
|
||||
});
|
||||
101
scripts/eslint/tests/only-arrow-functions.test.ts
Normal file
101
scripts/eslint/tests/only-arrow-functions.test.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { RuleTester } from "./support/RuleTester";
|
||||
import rule = require("../rules/only-arrow-functions");
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
},
|
||||
parser: require.resolve("@typescript-eslint/parser"),
|
||||
});
|
||||
|
||||
ruleTester.run("only-arrow-functions", rule, {
|
||||
valid: [{
|
||||
code: `const a = () => {};`,
|
||||
}, {
|
||||
code: `((func) => func())(() => {});`,
|
||||
}, {
|
||||
code: `function* generator() {}`,
|
||||
}, {
|
||||
code: `let generator = function*() {}`,
|
||||
}, {
|
||||
code: `function hasThisParameter(this) {}`,
|
||||
}, {
|
||||
code: `let hasThisParameter = function(this) {}`,
|
||||
}, {
|
||||
code: `let usesThis = function() { this; }`,
|
||||
}, {
|
||||
code: `let usesThis2 = function(foo = this) {}`,
|
||||
}, {
|
||||
code: `
|
||||
let fn = function fn() {};
|
||||
function z() {};
|
||||
`,
|
||||
options: [{ allowNamedFunctions: true }],
|
||||
}, {
|
||||
code: `
|
||||
function fn() {};
|
||||
let generator = function*() {}
|
||||
function hasThisParameter(this) {}
|
||||
let hasThisParameter = function(this) {}
|
||||
`,
|
||||
options: [{ allowDeclarations: true }],
|
||||
}, {
|
||||
code: `
|
||||
class A {
|
||||
test() {}
|
||||
}
|
||||
`,
|
||||
}, {
|
||||
code: `
|
||||
const obj = {
|
||||
test() {}
|
||||
}
|
||||
`,
|
||||
}],
|
||||
|
||||
invalid: [{
|
||||
code: `function foo(a: any): any {}`,
|
||||
errors: [{ messageId: "onlyArrowFunctionsError" }],
|
||||
}, {
|
||||
code: `let b = function () {};`,
|
||||
errors: [{ messageId: "onlyArrowFunctionsError" }],
|
||||
}, {
|
||||
code: `function c() {}`,
|
||||
errors: [{ messageId: "onlyArrowFunctionsError" }],
|
||||
}, {
|
||||
code: `((func) => func())(function e(): void {});`,
|
||||
errors: [{ messageId: "onlyArrowFunctionsError" }],
|
||||
}, {
|
||||
code: `
|
||||
let notUsesThis = function() {
|
||||
function f() { this; }
|
||||
}
|
||||
`,
|
||||
errors: [{ messageId: "onlyArrowFunctionsError" }],
|
||||
}, {
|
||||
code: `
|
||||
let notUsesThis2 = function() {
|
||||
return class { method() { this; } }
|
||||
}
|
||||
`,
|
||||
errors: [{ messageId: "onlyArrowFunctionsError" }],
|
||||
}, {
|
||||
code: `export function exported() {}`,
|
||||
errors: [{ messageId: "onlyArrowFunctionsError" }],
|
||||
}, {
|
||||
code: `async function asyncFunction() {}`,
|
||||
errors: [{ messageId: "onlyArrowFunctionsError" }],
|
||||
}, {
|
||||
code: `
|
||||
let b = function () {};
|
||||
((func) => func())(function e(): void {});
|
||||
`,
|
||||
options: [{ allowDeclarations: true }],
|
||||
errors: [{ messageId: "onlyArrowFunctionsError" }, { messageId: "onlyArrowFunctionsError" }],
|
||||
}, {
|
||||
code: `const x = function() {}`,
|
||||
options: [{ allowNamedFunctions: true }],
|
||||
errors: [{ messageId: "onlyArrowFunctionsError" }],
|
||||
}],
|
||||
});
|
||||
|
||||
5
scripts/eslint/tests/support/RuleTester.ts
Normal file
5
scripts/eslint/tests/support/RuleTester.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import * as path from "path";
|
||||
import { TSESLint } from "@typescript-eslint/experimental-utils";
|
||||
|
||||
export const ROOT_DIR = path.resolve(__dirname);
|
||||
export const RuleTester = TSESLint.RuleTester;
|
||||
9
scripts/eslint/tests/support/tsconfig.json
Normal file
9
scripts/eslint/tests/support/tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"strict": true,
|
||||
"lib": ["es2015", "es2017", "esnext"]
|
||||
}
|
||||
}
|
||||
35
scripts/eslint/tests/type-operator-spacing.test.ts
Normal file
35
scripts/eslint/tests/type-operator-spacing.test.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { RuleTester } from "./support/RuleTester";
|
||||
import rule = require("../rules/type-operator-spacing");
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
parserOptions: {
|
||||
warnOnUnsupportedTypeScriptVersion: false,
|
||||
},
|
||||
parser: require.resolve("@typescript-eslint/parser"),
|
||||
});
|
||||
|
||||
ruleTester.run("type-operator-spacing", rule, {
|
||||
valid: [{
|
||||
code: `type T = string | number`,
|
||||
}, {
|
||||
code: `type T = string & number`,
|
||||
}, {
|
||||
code: `function fn(): string | number {}`,
|
||||
}, {
|
||||
code: `function fn(): string & number {}`,
|
||||
}],
|
||||
|
||||
invalid: [{
|
||||
code: `type T = string|number`,
|
||||
errors: [{ messageId: "typeOperatorSpacingError" }],
|
||||
}, {
|
||||
code: `type T = string&number`,
|
||||
errors: [{ messageId: "typeOperatorSpacingError" }],
|
||||
}, {
|
||||
code: `function fn(): string|number {}`,
|
||||
errors: [{ messageId: "typeOperatorSpacingError" }],
|
||||
}, {
|
||||
code: `function fn(): string&number {}`,
|
||||
errors: [{ messageId: "typeOperatorSpacingError" }],
|
||||
}],
|
||||
});
|
||||
28
scripts/eslint/tsconfig.json
Normal file
28
scripts/eslint/tsconfig.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitReturns": true,
|
||||
"resolveJsonModule": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitAny": true,
|
||||
"skipLibCheck": true,
|
||||
"declaration": false,
|
||||
"noResolve": false,
|
||||
"strict": true,
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"outDir": "../../built/eslint",
|
||||
"lib": ["es2015", "es2016"]
|
||||
},
|
||||
|
||||
"include": [
|
||||
"rules",
|
||||
"tests",
|
||||
"tests/support/*.json"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user