From 392a758ba5456dbe13582a222e839d098535caf5 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sat, 27 Jan 2018 18:48:47 -0800
Subject: [PATCH 01/23] Initial eslint type defintion
---
types/eslint/eslint-tests.ts | 99 ++++++++++++++++++
types/eslint/index.d.ts | 190 +++++++++++++++++++++++++++++++++++
types/eslint/tsconfig.json | 23 +++++
types/eslint/tslint.json | 1 +
4 files changed, 313 insertions(+)
create mode 100644 types/eslint/eslint-tests.ts
create mode 100644 types/eslint/index.d.ts
create mode 100644 types/eslint/tsconfig.json
create mode 100644 types/eslint/tslint.json
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
new file mode 100644
index 0000000000..6b60ef8757
--- /dev/null
+++ b/types/eslint/eslint-tests.ts
@@ -0,0 +1,99 @@
+import { SourceCode, Linter, CLIEngine, RuleTester } from 'eslint';
+
+// =============================================
+// Linter
+// =============================================
+
+const SOURCE = `var foo = bar;`;
+
+const sourceCode = new SourceCode(SOURCE, {});
+
+const linter = new Linter();
+
+linter.verify(SOURCE, {
+ rules: {
+ eqeqeq: 'off',
+ 'no-console': 'error',
+ quotes: ['error', 'double']
+ },
+}, {
+ filename: 'test.js',
+});
+
+linter.verifyAndFix(SOURCE, {
+ rules: {
+ 'no-console': 'error',
+ }
+}, {
+ filename: 'test.js',
+});
+
+linter.defineRule('my-fancy-rule', {
+ create() {},
+});
+
+linter.defineRules({
+ 'my-fancy-rule': { create() {} },
+ 'my-fancy-other-rule': { create() {} }
+});
+
+linter.getRules();
+
+linter.getSourceCode();
+
+// =============================================
+// CLI
+// =============================================
+
+const cli = new CLIEngine({
+ envs: ['browser', 'mocha'],
+ useEslintrc: false,
+ rules: {
+ semi: 2
+ }
+});
+
+cli.executeOnFiles(['myfile.js', 'lib/']);
+
+const report = cli.executeOnText(SOURCE, 'foo');
+
+cli.resolveFileGlobPatterns(['**/*']);
+
+cli.getConfigForFile('./config.json');
+
+cli.addPlugin('my-fancy-plugin', {});
+
+cli.isPathIgnored('./dist/index.js');
+
+const formatter = cli.getFormatter('codeframe');
+formatter(report.results);
+
+CLIEngine.getErrorResults(report.results);
+
+CLIEngine.outputFixes(report);
+
+// =============================================
+// RuleTester
+// =============================================
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
+
+ruleTester.run("my-rule", {}, {
+ valid: [
+ {
+ code: "var foo = true",
+ options: [{ allowFoo: true }]
+ }
+ ],
+
+ invalid: [
+ {
+ code: "var invalidVariable = true",
+ errors: [{ message: "Unexpected invalid variable." }]
+ },
+ {
+ code: "var invalidVariable = true",
+ errors: [{ message: /^Unexpected.+variable/ }]
+ }
+ ]
+});
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
new file mode 100644
index 0000000000..7e04f5ebc7
--- /dev/null
+++ b/types/eslint/index.d.ts
@@ -0,0 +1,190 @@
+// Type definitions for eslint 4.16
+// Project: https://eslint.org
+// Definitions by: Pierre-Marie Dartus
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+export class SourceCode {
+ text: string;
+ ast: any;
+ lines: string[];
+
+ constructor(text: string, ast: any);
+}
+
+export type RuleLevel = 'off' | 'warn' | 'error' | 0 | 1 | 2;
+
+export interface Config {
+ rules?: {
+ [name: string]: (RuleLevel | [RuleLevel, any])
+ };
+ parser?: string;
+ parserOptions?: any;
+ settings?: any;
+ env?: { [name: string]: boolean };
+ globals?: { [name: string]: boolean };
+}
+
+export interface LintOptions {
+ filename?: string;
+ preprocess?: (code: string) => string[];
+ postprocess?: (problemLists: LintMessage[][]) => LintMessage[];
+ allowInlineConfig?: boolean;
+ reportUnusedDisableDirectives?: boolean;
+}
+
+export type Severity = 1 | 2;
+
+export interface LintMessage {
+ column: number;
+ line: number;
+ endColumn?: number;
+ endLine?: number;
+ ruleId: string | null;
+ message: string;
+ nodeType: string;
+ fatal?: true;
+ severity: Severity;
+ fix?: Fix;
+ source: string | null;
+}
+
+export interface FixOptions extends LintOptions {
+ fix?: boolean;
+}
+
+export interface Fix {
+ range: [number, number];
+ text: string;
+}
+
+export interface FixReport {
+ fixed: boolean;
+ output: string;
+ messages: LintMessage[];
+}
+
+export type RuleModule = any;
+
+export type ParserModule = any;
+
+export class Linter {
+ version: string;
+
+ verify(code: SourceCode | string, config: Config, filename?: string): LintMessage[];
+ verify(code: SourceCode | string, config: Config, options: LintOptions): LintMessage[];
+
+ verifyAndFix(code: string, config: Config, filename?: string): FixReport;
+ verifyAndFix(code: string, config: Config, options: FixOptions): FixReport;
+
+ getSourceCode(): SourceCode;
+
+ defineRule(name: string, rule: RuleModule): void;
+
+ defineRules(rules: { [name: string]: RuleModule }): void;
+
+ getRules(): Map;
+
+ defineParser(name: string, parser: ParserModule): void;
+}
+
+export class CLIEngineOptions {
+ allowInlineConfig?: boolean;
+ baseConfig?: boolean;
+ cache?: boolean;
+ cacheFile?: string;
+ configFile?: string;
+ cwd?: string;
+ envs?: string[];
+ extensions?: string[];
+ fix?: boolean;
+ globals?: string[];
+ ignore?: boolean;
+ ignorePath?: string;
+ ignorePattern?: string;
+ useEslintrc?: boolean;
+ parser?: string;
+ parserOptions?: any;
+ plugins?: string[];
+ rules?: {
+ [name: string]: (RuleLevel | [RuleLevel, any]);
+ };
+ rulePaths?: string[];
+}
+
+export interface LintResult {
+ filePath: string;
+ messages: LintMessage[];
+ errorCount: number;
+ warningCount: number;
+ fixableErrorCount: number;
+ fixableWarningCount: number;
+ output?: string;
+ source?: string;
+}
+
+export interface LintReport {
+ results: LintResult[];
+ errorCount: number;
+ warningCount: number;
+ fixableErrorCount: number;
+ fixableWarningCount: number;
+}
+
+export type Formatter = (results: LintResult[]) => string;
+
+export class CLIEngine {
+ version: string;
+
+ constructor(options: CLIEngineOptions);
+
+ executeOnFiles(patterns: string[]): LintReport;
+
+ resolveFileGlobPatterns(patterns: string[]): string[];
+
+ getConfigForFile(filePath: string): Config;
+
+ executeOnText(text: string, filename?: string): LintReport;
+
+ addPlugin(name: string, pluginObject: any): void;
+
+ isPathIgnored(filePath: string): boolean;
+
+ getFormatter(format: string): Formatter;
+
+ static getErrorResults(results: LintResult[]): LintResult[];
+
+ static outputFixes(report: LintReport): void;
+
+ getRules(): Map;
+}
+
+export interface ValidTestCase {
+ code: string;
+ options?: any;
+ filename?: string;
+ parserOptions?: any;
+}
+
+export interface TestCaseError {
+ message?: string | RegExp;
+ type?: string;
+ line?: number;
+ column?: number;
+ endLine?: number;
+ endColumn?: number;
+}
+
+export interface InvalidTestCase extends ValidTestCase {
+ errors: number | Array;
+}
+
+export interface Test {
+ valid?: ValidTestCase[];
+ invalid: InvalidTestCase[];
+}
+
+export class RuleTester {
+ constructor(config?: any);
+
+ run(name: string, rule: any, tests: Test): void;
+}
diff --git a/types/eslint/tsconfig.json b/types/eslint/tsconfig.json
new file mode 100644
index 0000000000..2e820d4971
--- /dev/null
+++ b/types/eslint/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "lib": [
+ "es6"
+ ],
+ "noImplicitAny": true,
+ "noImplicitThis": true,
+ "strictNullChecks": true,
+ "strictFunctionTypes": true,
+ "baseUrl": "../",
+ "typeRoots": [
+ "../"
+ ],
+ "types": [],
+ "noEmit": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "index.d.ts",
+ "eslint-tests.ts"
+ ]
+}
diff --git a/types/eslint/tslint.json b/types/eslint/tslint.json
new file mode 100644
index 0000000000..3db14f85ea
--- /dev/null
+++ b/types/eslint/tslint.json
@@ -0,0 +1 @@
+{ "extends": "dtslint/dt.json" }
From fdedcdfaa5ecd49b243f53157e91410cfe50fabd Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sun, 28 Jan 2018 10:03:03 -0800
Subject: [PATCH 02/23] Add missing types to source code
---
types/eslint/eslint-tests.ts | 15 ++++-
types/eslint/index.d.ts | 119 +++++++++++++++++++++++++++++++++--
2 files changed, 127 insertions(+), 7 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index 6b60ef8757..2d4a4347d9 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -1,12 +1,23 @@
import { SourceCode, Linter, CLIEngine, RuleTester } from 'eslint';
// =============================================
-// Linter
+// SourceCode
// =============================================
const SOURCE = `var foo = bar;`;
-const sourceCode = new SourceCode(SOURCE, {});
+const ast = { comments: [], tokens: [], loc: {}, range: [] };
+const sourceCode = new SourceCode(SOURCE, ast);
+
+const text: string = sourceCode.getText();
+
+const lines: string[] = sourceCode.getLines();
+
+SourceCode.splitLines(SOURCE);
+
+// =============================================
+// Linter
+// =============================================
const linter = new Linter();
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 7e04f5ebc7..b4b0a921ed 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -3,12 +3,121 @@
// Definitions by: Pierre-Marie Dartus
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
-export class SourceCode {
- text: string;
- ast: any;
- lines: string[];
+export interface Ast {
+ comments: any[],
+ tokens: any[],
+ loc: any,
+ range: any[];
+}
- constructor(text: string, ast: any);
+export type AstNode = any;
+export type Token = any;
+export type Comment = any;
+
+export type FilterPredicate = (tokenOrComment: Token | Comment) => boolean;
+
+export type CursorWithSkipOptions = number | FilterPredicate | {
+ includeComments?: boolean;
+ filter?: FilterPredicate;
+ skip?: number;
+}
+
+export type CursorWithCountOptions = number | FilterPredicate | {
+ includeComments?: boolean;
+ filter?: FilterPredicate;
+ count?: number;
+}
+
+export class TokenStore {
+ getTokenByRangeStart(offset: number, options?: { includeComments?: boolean }): Token | null;
+
+ getFirstToken(node: AstNode, options: CursorWithSkipOptions): Token | null;
+
+ getFirstTokens(node: AstNode, options: CursorWithCountOptions): Token[];
+
+ getLastToken(node: AstNode, options: CursorWithSkipOptions): Token | null;
+
+ getLastTokens(node: AstNode, options: CursorWithCountOptions): Token[];
+
+ getTokenBefore(node: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
+
+ getTokensBefore(node: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
+
+ getTokenAfter(node: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
+
+ getTokensAfter(node: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
+
+ getFirstTokenBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
+
+ getFirstTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
+
+ getLastTokenBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
+
+ getLastTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
+
+ getTokens(node: AstNode, beforeCount?: number, afterCount?: number): Token[];
+ getTokens(node: AstNode, options: FilterPredicate | CursorWithCountOptions): Token[];
+
+ getTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, padding: number): Token[];
+ getTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, padding: FilterPredicate | CursorWithCountOptions): Token[];
+
+ commentsExistBetween(left: AstNode, right: AstNode): boolean;
+
+ getCommentsBefore(nodeOrToken: AstNode | Token): Comment[];
+
+ getCommentsAfter(nodeOrToken: AstNode | Token): Comment[];
+
+ getCommentsInside(node: AstNode): Comment[];
+}
+
+export interface SourceCodeConfig {
+ text: string;
+ ast: Ast;
+ parserServices?: ParserServices;
+ scopeManager?: ScopeManager;
+ visitorKeys?: VisitorKeys;
+}
+
+export interface Location {
+ line: number;
+ column: number;
+}
+
+type ParserServices = any;
+type ScopeManager = any;
+type VisitorKeys = any;
+
+export class SourceCode extends TokenStore {
+ text: string;
+ ast: Ast;
+ lines: string[];
+ hasBOM: boolean;
+ parserServices: ParserServices;
+ scopeManager: ScopeManager;
+ visitorKeys: VisitorKeys;
+
+ constructor(text: string, ast: Ast);
+ constructor(config: SourceCodeConfig);
+
+ static splitLines(text: string): string[];
+
+ getText(node?: AstNode, beforeCount?: number, afterCount?: number): string;
+
+ getLines(): string[];
+
+ getAllComments(): AstNode[];
+
+ getComments(node: AstNode): { leading: Comment[], trailing: Comment[] };
+
+ getJSDocComment(node: AstNode): Token | null;
+
+ getNodeByRangeIndex(index: number): AstNode | null;
+
+ isSpaceBetweenTokens(first: Token, second: Token): boolean;
+
+ getLocFromIndex(index: number): Location;
+
+ getIndexFromLoc(location: Location): number;
}
export type RuleLevel = 'off' | 'warn' | 'error' | 0 | 1 | 2;
From ba6ee11d7c9b1cfb8ea5058240f107b1289a9f79 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sun, 28 Jan 2018 10:59:55 -0800
Subject: [PATCH 03/23] Add RuleModule type defintion
---
types/eslint/index.d.ts | 72 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 70 insertions(+), 2 deletions(-)
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index b4b0a921ed..425f5f6c00 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -161,8 +161,10 @@ export interface FixOptions extends LintOptions {
fix?: boolean;
}
+export type Range = [number, number];
+
export interface Fix {
- range: [number, number];
+ range: Range;
text: string;
}
@@ -172,7 +174,73 @@ export interface FixReport {
messages: LintMessage[];
}
-export type RuleModule = any;
+export interface RuleModule {
+ create(context: RuleContext): any;
+ meta?: RuleMetaData;
+}
+
+export interface RuleMetaData {
+ docs?: {
+ description?: string;
+ category?: string;
+ recommended?: boolean;
+ url?: string;
+ }
+ messages?: { [messageId: string]: string };
+ fixable?: 'code' | 'whitespace';
+ schema?: any;
+ deprecated?: boolean;
+}
+
+interface RuleContext {
+ id: string;
+ options: any[];
+ settings: any;
+ parserPath: string;
+ parserOptions: any;
+ parserServices: any;
+
+ getAncestors(): AstNode[];
+
+ getDeclaredVariables(node: AstNode): any[];
+
+ getFilename(): string;
+
+ getScope(): any;
+
+ getSourceCode(): SourceCode;
+
+ markVariableAsUsed(name: string): boolean;
+
+ report(descriptor: ReportDescriptor): void;
+}
+
+type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
+type ReportDescriptorMessage = { message: string } | { messageId: string };
+type ReportDescriptorLocation = { node: AstNode } | { loc: { start: Location, end: Location } | { line: number, column: number } }
+type ReportDescriptorOptions = {
+ data?: any;
+
+ fix?(fixer: RuleFixer): null | Fix | IterableIterator;
+}
+
+interface RuleFixer {
+ insertTextAfter(nodeOrToken: AstNode | Token, text: string): Fix;
+
+ insertTextAfterRange(range: Range, text: string): Fix;
+
+ insertTextBefore(nodeOrToken: AstNode | Token, text: string): Fix;
+
+ insertTextBeforeRange(range: Range, text: string): Fix;
+
+ remove(nodeOrToken: AstNode | Token): Fix;
+
+ removeRange(range: Range): Fix;
+
+ replaceText(nodeOrToken: AstNode | Token, text: string): Fix;
+
+ replaceTextRange(range: Range, text: string): Fix;
+}
export type ParserModule = any;
From 4edc769299bfd486bda5b24141901b0bd00f3158 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sun, 28 Jan 2018 11:03:43 -0800
Subject: [PATCH 04/23] Add ParserModule types
---
types/eslint/index.d.ts | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 425f5f6c00..6fca406a62 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -242,7 +242,18 @@ interface RuleFixer {
replaceTextRange(range: Range, text: string): Fix;
}
-export type ParserModule = any;
+export type ParserModule = {
+ parse(text: string, options?: any): AstNode;
+} | {
+ parseForESLint(text: string, options?: any): ESLintParseResult;
+}
+
+export interface ESLintParseResult {
+ ast: AstNode;
+ parserServices?: any;
+ scopeManager?: any;
+ visitorKeys?: { [type: string]: string[] };
+}
export class Linter {
version: string;
From e1a8c9446c0dc88ec233ae43a956634451d195df Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sun, 28 Jan 2018 11:16:23 -0800
Subject: [PATCH 05/23] Add RuleTester missing types
---
types/eslint/index.d.ts | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 6fca406a62..80a19f144c 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -280,6 +280,7 @@ export class CLIEngineOptions {
baseConfig?: boolean;
cache?: boolean;
cacheFile?: string;
+ cacheLocation?: string;
configFile?: string;
cwd?: string;
envs?: string[];
@@ -297,6 +298,7 @@ export class CLIEngineOptions {
[name: string]: (RuleLevel | [RuleLevel, any]);
};
rulePaths?: string[];
+ reportUnusedDisableDirectives?: true;
}
export interface LintResult {
@@ -351,11 +353,16 @@ export interface ValidTestCase {
options?: any;
filename?: string;
parserOptions?: any;
+ settings?: any;
+ parser?: string;
+ globals?: { [name: string]: boolean };
}
export interface TestCaseError {
message?: string | RegExp;
+ messageId?: string;
type?: string;
+ data?: any;
line?: number;
column?: number;
endLine?: number;
@@ -364,6 +371,7 @@ export interface TestCaseError {
export interface InvalidTestCase extends ValidTestCase {
errors: number | Array;
+ output?: string;
}
export interface Test {
From d63e1610023551f14fff3a3be5792d4057dca6b6 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sun, 28 Jan 2018 19:24:57 -0800
Subject: [PATCH 06/23] Fix linting errors
---
types/eslint/index.d.ts | 43 ++++++++++++++++++++---------------------
1 file changed, 21 insertions(+), 22 deletions(-)
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 80a19f144c..d5c9556f65 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -4,9 +4,9 @@
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
export interface Ast {
- comments: any[],
- tokens: any[],
- loc: any,
+ comments: any[];
+ tokens: any[];
+ loc: any;
range: any[];
}
@@ -20,13 +20,13 @@ export type CursorWithSkipOptions = number | FilterPredicate | {
includeComments?: boolean;
filter?: FilterPredicate;
skip?: number;
-}
+};
export type CursorWithCountOptions = number | FilterPredicate | {
includeComments?: boolean;
filter?: FilterPredicate;
count?: number;
-}
+};
export class TokenStore {
getTokenByRangeStart(offset: number, options?: { includeComments?: boolean }): Token | null;
@@ -47,19 +47,18 @@ export class TokenStore {
getTokensAfter(node: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
- getFirstTokenBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
+ getFirstTokenBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
- getFirstTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
+ getFirstTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
- getLastTokenBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
+ getLastTokenBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
- getLastTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
+ getLastTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
getTokens(node: AstNode, beforeCount?: number, afterCount?: number): Token[];
getTokens(node: AstNode, options: FilterPredicate | CursorWithCountOptions): Token[];
- getTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, padding: number): Token[];
- getTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, padding: FilterPredicate | CursorWithCountOptions): Token[];
+ getTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, padding: number | FilterPredicate | CursorWithCountOptions): Token[];
commentsExistBetween(left: AstNode, right: AstNode): boolean;
@@ -83,9 +82,9 @@ export interface Location {
column: number;
}
-type ParserServices = any;
-type ScopeManager = any;
-type VisitorKeys = any;
+export type ParserServices = any;
+export type ScopeManager = any;
+export type VisitorKeys = any;
export class SourceCode extends TokenStore {
text: string;
@@ -185,14 +184,14 @@ export interface RuleMetaData {
category?: string;
recommended?: boolean;
url?: string;
- }
+ };
messages?: { [messageId: string]: string };
fixable?: 'code' | 'whitespace';
schema?: any;
deprecated?: boolean;
}
-interface RuleContext {
+export interface RuleContext {
id: string;
options: any[];
settings: any;
@@ -215,16 +214,16 @@ interface RuleContext {
report(descriptor: ReportDescriptor): void;
}
-type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
-type ReportDescriptorMessage = { message: string } | { messageId: string };
-type ReportDescriptorLocation = { node: AstNode } | { loc: { start: Location, end: Location } | { line: number, column: number } }
-type ReportDescriptorOptions = {
+export type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
+export type ReportDescriptorMessage = { message: string } | { messageId: string };
+export type ReportDescriptorLocation = { node: AstNode } | { loc: { start: Location, end: Location } | { line: number, column: number } };
+export interface ReportDescriptorOptions {
data?: any;
fix?(fixer: RuleFixer): null | Fix | IterableIterator;
}
-interface RuleFixer {
+export interface RuleFixer {
insertTextAfter(nodeOrToken: AstNode | Token, text: string): Fix;
insertTextAfterRange(range: Range, text: string): Fix;
@@ -246,7 +245,7 @@ export type ParserModule = {
parse(text: string, options?: any): AstNode;
} | {
parseForESLint(text: string, options?: any): ESLintParseResult;
-}
+};
export interface ESLintParseResult {
ast: AstNode;
From eedcaa68b89399e97131f19a63c994665584af9f Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Mon, 29 Jan 2018 07:48:41 -0800
Subject: [PATCH 07/23] Add types for ASTNode and scope namager
---
types/eslint/index.d.ts | 179 ++++++++++++++++++++++++++++------------
1 file changed, 128 insertions(+), 51 deletions(-)
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index d5c9556f65..5afa86d809 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -2,19 +2,21 @@
// Project: https://eslint.org
// Definitions by: Pierre-Marie Dartus
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+// TypeScript Version: 2.1
+
+import { JSONSchema4 } from 'json-schema';
+import * as ESTree from 'estree';
+
+export type Token = any;
export interface Ast {
- comments: any[];
+ comments: ESTree.Comment[];
tokens: any[];
loc: any;
range: any[];
}
-export type AstNode = any;
-export type Token = any;
-export type Comment = any;
-
-export type FilterPredicate = (tokenOrComment: Token | Comment) => boolean;
+export type FilterPredicate = (tokenOrComment: Token | ESTree.Comment) => boolean;
export type CursorWithSkipOptions = number | FilterPredicate | {
includeComments?: boolean;
@@ -31,42 +33,42 @@ export type CursorWithCountOptions = number | FilterPredicate | {
export class TokenStore {
getTokenByRangeStart(offset: number, options?: { includeComments?: boolean }): Token | null;
- getFirstToken(node: AstNode, options: CursorWithSkipOptions): Token | null;
+ getFirstToken(node: ESTree.Node, options: CursorWithSkipOptions): Token | null;
- getFirstTokens(node: AstNode, options: CursorWithCountOptions): Token[];
+ getFirstTokens(node: ESTree.Node, options: CursorWithCountOptions): Token[];
- getLastToken(node: AstNode, options: CursorWithSkipOptions): Token | null;
+ getLastToken(node: ESTree.Node, options: CursorWithSkipOptions): Token | null;
- getLastTokens(node: AstNode, options: CursorWithCountOptions): Token[];
+ getLastTokens(node: ESTree.Node, options: CursorWithCountOptions): Token[];
- getTokenBefore(node: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
+ getTokenBefore(node: ESTree.Node | Token | ESTree.Comment, options: CursorWithSkipOptions): Token | null;
- getTokensBefore(node: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
+ getTokensBefore(node: ESTree.Node | Token | ESTree.Comment, options: CursorWithCountOptions): Token[];
- getTokenAfter(node: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
+ getTokenAfter(node: ESTree.Node | Token | ESTree.Comment, options: CursorWithSkipOptions): Token | null;
- getTokensAfter(node: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
+ getTokensAfter(node: ESTree.Node | Token | ESTree.Comment, options: CursorWithCountOptions): Token[];
- getFirstTokenBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
+ getFirstTokenBetween(left: ESTree.Node | Token | ESTree.Comment, right: ESTree.Node | Token | ESTree.Comment, options: CursorWithSkipOptions): Token | null;
- getFirstTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
+ getFirstTokensBetween(left: ESTree.Node | Token | ESTree.Comment, right: ESTree.Node | Token | ESTree.Comment, options: CursorWithCountOptions): Token[];
- getLastTokenBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithSkipOptions): Token | null;
+ getLastTokenBetween(left: ESTree.Node | Token | ESTree.Comment, right: ESTree.Node | Token | ESTree.Comment, options: CursorWithSkipOptions): Token | null;
- getLastTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, options: CursorWithCountOptions): Token[];
+ getLastTokensBetween(left: ESTree.Node | Token | ESTree.Comment, right: ESTree.Node | Token | ESTree.Comment, options: CursorWithCountOptions): Token[];
- getTokens(node: AstNode, beforeCount?: number, afterCount?: number): Token[];
- getTokens(node: AstNode, options: FilterPredicate | CursorWithCountOptions): Token[];
+ getTokens(node: ESTree.Node, beforeCount?: number, afterCount?: number): Token[];
+ getTokens(node: ESTree.Node, options: FilterPredicate | CursorWithCountOptions): Token[];
- getTokensBetween(left: AstNode | Token | Comment, right: AstNode | Token | Comment, padding: number | FilterPredicate | CursorWithCountOptions): Token[];
+ getTokensBetween(left: ESTree.Node | Token | ESTree.Comment, right: ESTree.Node | Token | ESTree.Comment, padding: number | FilterPredicate | CursorWithCountOptions): Token[];
- commentsExistBetween(left: AstNode, right: AstNode): boolean;
+ commentsExistBetween(left: ESTree.Node, right: ESTree.Node): boolean;
- getCommentsBefore(nodeOrToken: AstNode | Token): Comment[];
+ getCommentsBefore(nodeOrToken: ESTree.Node | Token): ESTree.Comment[];
- getCommentsAfter(nodeOrToken: AstNode | Token): Comment[];
+ getCommentsAfter(nodeOrToken: ESTree.Node | Token): ESTree.Comment[];
- getCommentsInside(node: AstNode): Comment[];
+ getCommentsInside(node: ESTree.Node): ESTree.Comment[];
}
export interface SourceCodeConfig {
@@ -83,8 +85,70 @@ export interface Location {
}
export type ParserServices = any;
-export type ScopeManager = any;
-export type VisitorKeys = any;
+
+export interface ScopeManager {
+ scopes: Scope[];
+ globalScope: Scope | null;
+
+ acquire(node: ESTree.Node, inner?: boolean): Scope | null;
+
+ getDeclaredVariables(node: ESTree.Node): any[];
+}
+
+export interface Scope {
+ type: 'block' | 'catch' | 'class' | 'for' | 'function' | 'function-expression-name' | 'global' | 'module' | 'switch' | 'with' | 'TDZ';
+ isStrict: boolean;
+ upper: Scope | null;
+ childScopes: Scope[];
+ variableScope: Scope;
+ block: ESTree.Node;
+ variables: Variable[];
+ set: Map;
+ references: Reference[];
+ through: Reference[];
+ functionExpressionScope: boolean;
+}
+
+export interface Variable {
+ name: string;
+ identifiers: ESTree.Identifier;
+ references: Reference[];
+ defs: Definition[];
+}
+
+export interface Reference {
+ identifier: ESTree.Identifier;
+ from: Scope;
+ resolved: Variable | null;
+ writeExpr: ESTree.Node | null;
+ init: boolean;
+
+ isWrite(): boolean;
+
+ isRead(): boolean;
+
+ isWriteOnly(): boolean;
+
+ isReadOnly(): boolean;
+
+ isReadWrite(): boolean;
+}
+
+export type DefinitionType =
+ | { type: 'CatchClause', node: ESTree.CatchClause, parent: null }
+ | { type: 'ClassName', node: ESTree.ClassDeclaration | ESTree.ClassExpression, parent: null }
+ | { type: 'FunctionName', node: ESTree.FunctionDeclaration | ESTree.FunctionExpression, parent: null }
+ | { type: 'ImplicitGlobalVariable', node: ESTree.Program, parent: null }
+ | { type: 'ImportBinding', node: ESTree.ImportSpecifier | ESTree.ImportDefaultSpecifier | ESTree.ImportNamespaceSpecifier, parent: ESTree.ImportDeclaration }
+ | { type: 'Parameter', node: ESTree.FunctionDeclaration | ESTree.FunctionExpression | ESTree.ArrowFunctionExpression, parent: null }
+ | { type: 'TDZ', node: any, parent: null }
+ | { type: 'Variable', node: ESTree.VariableDeclarator, parent: ESTree.VariableDeclaration };
+
+export type Definition = DefinitionType & { name: ESTree.Identifier };
+
+export interface VisitorKeys {
+ [nodeType: string]: string[];
+}
export class SourceCode extends TokenStore {
text: string;
@@ -100,17 +164,17 @@ export class SourceCode extends TokenStore {
static splitLines(text: string): string[];
- getText(node?: AstNode, beforeCount?: number, afterCount?: number): string;
+ getText(node?: ESTree.Node, beforeCount?: number, afterCount?: number): string;
getLines(): string[];
- getAllComments(): AstNode[];
+ getAllComments(): ESTree.Node[];
- getComments(node: AstNode): { leading: Comment[], trailing: Comment[] };
+ getComments(node: ESTree.Node): { leading: ESTree.Comment[], trailing: ESTree.Comment[] };
- getJSDocComment(node: AstNode): Token | null;
+ getJSDocComment(node: ESTree.Node): Token | null;
- getNodeByRangeIndex(index: number): AstNode | null;
+ getNodeByRangeIndex(index: number): ESTree.Node | null;
isSpaceBetweenTokens(first: Token, second: Token): boolean;
@@ -121,13 +185,26 @@ export class SourceCode extends TokenStore {
export type RuleLevel = 'off' | 'warn' | 'error' | 0 | 1 | 2;
+export interface ParserOptions {
+ ecmaVersion?: 3 | 5 | 6 | 7 | 8 | 9 | 2015 | 2016 | 2017 | 2018;
+ sourceType?: 'script' | 'module';
+ ecmaFeatures?: {
+ globalReturn?: boolean;
+ impliedStrict?: boolean;
+ jsx?: boolean;
+ experimentalObjectRestSpread?: boolean;
+ [key: string]: any;
+ };
+ [key: string]: any;
+}
+
export interface Config {
rules?: {
[name: string]: (RuleLevel | [RuleLevel, any])
};
parser?: string;
- parserOptions?: any;
- settings?: any;
+ parserOptions?: ParserOptions;
+ settings?: { [name: string]: any };
env?: { [name: string]: boolean };
globals?: { [name: string]: boolean };
}
@@ -187,21 +264,21 @@ export interface RuleMetaData {
};
messages?: { [messageId: string]: string };
fixable?: 'code' | 'whitespace';
- schema?: any;
+ schema?: JSONSchema4 | JSONSchema4[];
deprecated?: boolean;
}
export interface RuleContext {
id: string;
options: any[];
- settings: any;
+ settings: { [name: string]: any };
parserPath: string;
- parserOptions: any;
+ parserOptions: ParserOptions;
parserServices: any;
- getAncestors(): AstNode[];
+ getAncestors(): ESTree.Node[];
- getDeclaredVariables(node: AstNode): any[];
+ getDeclaredVariables(node: ESTree.Node): any[];
getFilename(): string;
@@ -216,42 +293,42 @@ export interface RuleContext {
export type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
export type ReportDescriptorMessage = { message: string } | { messageId: string };
-export type ReportDescriptorLocation = { node: AstNode } | { loc: { start: Location, end: Location } | { line: number, column: number } };
+export type ReportDescriptorLocation = { node: ESTree.Node } | { loc: { start: Location, end: Location } | { line: number, column: number } };
export interface ReportDescriptorOptions {
- data?: any;
+ data?: { [key: string]: string };
fix?(fixer: RuleFixer): null | Fix | IterableIterator;
}
export interface RuleFixer {
- insertTextAfter(nodeOrToken: AstNode | Token, text: string): Fix;
+ insertTextAfter(nodeOrToken: ESTree.Node | Token, text: string): Fix;
insertTextAfterRange(range: Range, text: string): Fix;
- insertTextBefore(nodeOrToken: AstNode | Token, text: string): Fix;
+ insertTextBefore(nodeOrToken: ESTree.Node | Token, text: string): Fix;
insertTextBeforeRange(range: Range, text: string): Fix;
- remove(nodeOrToken: AstNode | Token): Fix;
+ remove(nodeOrToken: ESTree.Node | Token): Fix;
removeRange(range: Range): Fix;
- replaceText(nodeOrToken: AstNode | Token, text: string): Fix;
+ replaceText(nodeOrToken: ESTree.Node | Token, text: string): Fix;
replaceTextRange(range: Range, text: string): Fix;
}
export type ParserModule = {
- parse(text: string, options?: any): AstNode;
+ parse(text: string, options?: any): ESTree.Node;
} | {
parseForESLint(text: string, options?: any): ESLintParseResult;
};
export interface ESLintParseResult {
- ast: AstNode;
+ ast: ESTree.Node;
parserServices?: any;
scopeManager?: any;
- visitorKeys?: { [type: string]: string[] };
+ visitorKeys?: VisitorKeys;
}
export class Linter {
@@ -291,7 +368,7 @@ export class CLIEngineOptions {
ignorePattern?: string;
useEslintrc?: boolean;
parser?: string;
- parserOptions?: any;
+ parserOptions?: ParserOptions;
plugins?: string[];
rules?: {
[name: string]: (RuleLevel | [RuleLevel, any]);
@@ -351,8 +428,8 @@ export interface ValidTestCase {
code: string;
options?: any;
filename?: string;
- parserOptions?: any;
- settings?: any;
+ parserOptions?: ParserOptions;
+ settings?: { [name: string]: any };
parser?: string;
globals?: { [name: string]: boolean };
}
From 9526476d01730159e7bfe0187ebd2d5c300323b9 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Tue, 30 Jan 2018 07:33:19 -0800
Subject: [PATCH 08/23] Add RuleListener type
---
types/eslint/index.d.ts | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 5afa86d809..b4bb9e4e84 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -255,6 +255,43 @@ export interface RuleModule {
meta?: RuleMetaData;
}
+export interface RuleListener {
+ onCodePathStart?(codePath: CodePath, node: ESTree.Node): void;
+
+ onCodePathEnd?(codePath: CodePath, node: ESTree.Node): void;
+
+ onCodePathSegmentStart?(segment: CodePathSegment, node: ESTree.Node): void;
+
+ onCodePathSegmentEnd?(segment: CodePathSegment, node: ESTree.Node): void;
+
+ onCodePathSegmentLoop?(fromSegment: CodePathSegment, toSegment: CodePathSegment, node: ESTree.Node): void;
+
+ [key: string]:
+ | ((codePath: CodePath, node: ESTree.Node) => void)
+ | ((segment: CodePathSegment, node: ESTree.Node) => void)
+ | ((fromSegment: CodePathSegment, toSegment: CodePathSegment, node: ESTree.Node) => void)
+ | ((node: ESTree.Node) => void)
+ | undefined;
+}
+
+export interface CodePath {
+ id: string;
+ initialSegment: CodePathSegment;
+ finalSegments: CodePathSegment[];
+ returnedSegments: CodePathSegment[];
+ thrownSegments: CodePathSegment[];
+ currentSegments: CodePathSegment[];
+ upper: CodePath | null;
+ childCodePaths: CodePath[];
+}
+
+export interface CodePathSegment {
+ id: string;
+ nextSegments: CodePathSegment[];
+ prevSegments: CodePathSegment[];
+ reachable: boolean;
+}
+
export interface RuleMetaData {
docs?: {
description?: string;
From 48378a71f6e7d5b93143f8b2268acdd38fd399d9 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Tue, 30 Jan 2018 07:35:58 -0800
Subject: [PATCH 09/23] Bump min typescript version for json-schema
---
types/eslint/index.d.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index b4bb9e4e84..ee6b4eab0d 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -2,7 +2,7 @@
// Project: https://eslint.org
// Definitions by: Pierre-Marie Dartus
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
-// TypeScript Version: 2.1
+// TypeScript Version: 2.2
import { JSONSchema4 } from 'json-schema';
import * as ESTree from 'estree';
From 211e27a68e7d7666810d37a1290bc7c375c3708e Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Tue, 30 Jan 2018 21:53:07 -0800
Subject: [PATCH 10/23] Make type consistent
---
types/eslint/eslint-tests.ts | 4 +--
types/eslint/index.d.ts | 58 +++++++++++++++++++++++++-----------
2 files changed, 42 insertions(+), 20 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index 2d4a4347d9..a1c4ddbbc8 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -1,4 +1,4 @@
-import { SourceCode, Linter, CLIEngine, RuleTester } from 'eslint';
+import { SourceCode, Linter, CLIEngine, RuleTester, Ast } from 'eslint';
// =============================================
// SourceCode
@@ -6,7 +6,7 @@ import { SourceCode, Linter, CLIEngine, RuleTester } from 'eslint';
const SOURCE = `var foo = bar;`;
-const ast = { comments: [], tokens: [], loc: {}, range: [] };
+const ast: Ast = { comments: [], tokens: [], loc: { start: { line: 0, column: 0 }, end: { line: 0, column: 10 } }, range: [0, 17] };
const sourceCode = new SourceCode(SOURCE, ast);
const text: string = sourceCode.getText();
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index ee6b4eab0d..5ad0f7df8d 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -7,13 +7,42 @@
import { JSONSchema4 } from 'json-schema';
import * as ESTree from 'estree';
-export type Token = any;
+export type TokenType =
+ | 'Boolean'
+ | 'Null'
+ | 'Identifier'
+ | 'Keyword'
+ | 'Punctuator'
+ | 'JSXIdentifier'
+ | 'JSXText'
+ | 'Numeric'
+ | 'String'
+ | 'RegularExpression';
+
+export interface Token {
+ type: TokenType;
+ value: string;
+ range: Range;
+ loc: SourceLocation;
+}
+
+export interface SourceLocation {
+ start: Location;
+ end: Location;
+}
+
+export interface Location {
+ line: number;
+ column: number;
+}
+
+export type Range = [number, number];
export interface Ast {
comments: ESTree.Comment[];
- tokens: any[];
- loc: any;
- range: any[];
+ tokens: Token[];
+ loc: SourceLocation;
+ range: Range;
}
export type FilterPredicate = (tokenOrComment: Token | ESTree.Comment) => boolean;
@@ -79,11 +108,6 @@ export interface SourceCodeConfig {
visitorKeys?: VisitorKeys;
}
-export interface Location {
- line: number;
- column: number;
-}
-
export type ParserServices = any;
export interface ScopeManager {
@@ -92,7 +116,7 @@ export interface ScopeManager {
acquire(node: ESTree.Node, inner?: boolean): Scope | null;
- getDeclaredVariables(node: ESTree.Node): any[];
+ getDeclaredVariables(node: ESTree.Node): Variable[];
}
export interface Scope {
@@ -237,8 +261,6 @@ export interface FixOptions extends LintOptions {
fix?: boolean;
}
-export type Range = [number, number];
-
export interface Fix {
range: Range;
text: string;
@@ -311,15 +333,15 @@ export interface RuleContext {
settings: { [name: string]: any };
parserPath: string;
parserOptions: ParserOptions;
- parserServices: any;
+ parserServices: ParserServices;
getAncestors(): ESTree.Node[];
- getDeclaredVariables(node: ESTree.Node): any[];
+ getDeclaredVariables(node: ESTree.Node): Variable[];
getFilename(): string;
- getScope(): any;
+ getScope(): Scope;
getSourceCode(): SourceCode;
@@ -330,7 +352,7 @@ export interface RuleContext {
export type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
export type ReportDescriptorMessage = { message: string } | { messageId: string };
-export type ReportDescriptorLocation = { node: ESTree.Node } | { loc: { start: Location, end: Location } | { line: number, column: number } };
+export type ReportDescriptorLocation = { node: ESTree.Node } | { loc: SourceLocation | { line: number, column: number } };
export interface ReportDescriptorOptions {
data?: { [key: string]: string };
@@ -363,8 +385,8 @@ export type ParserModule = {
export interface ESLintParseResult {
ast: ESTree.Node;
- parserServices?: any;
- scopeManager?: any;
+ parserServices?: ParserServices;
+ scopeManager?: ScopeManager;
visitorKeys?: VisitorKeys;
}
From 581167305d724a2ca4e2bb2e40a91e4511b09805 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Tue, 30 Jan 2018 21:55:15 -0800
Subject: [PATCH 11/23] Add @j-f1 to the definition author list
---
types/eslint/index.d.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 5ad0f7df8d..d6326c4ad5 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -1,6 +1,7 @@
// Type definitions for eslint 4.16
// Project: https://eslint.org
// Definitions by: Pierre-Marie Dartus
+// Jed Fox
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.2
From 871c58a7b4c8ce83c8bfc94e51e1b13e9fe6fce9 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Wed, 31 Jan 2018 20:35:55 -0800
Subject: [PATCH 12/23] Refactor type defition to leverage namespaces
---
types/eslint/eslint-tests.ts | 8 +-
types/eslint/index.d.ts | 832 +++++++++++++++++++----------------
2 files changed, 450 insertions(+), 390 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index a1c4ddbbc8..46f960dbd4 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -15,6 +15,10 @@ const lines: string[] = sourceCode.getLines();
SourceCode.splitLines(SOURCE);
+class Foo {
+ foo = 1;
+}
+
// =============================================
// Linter
// =============================================
@@ -89,7 +93,9 @@ CLIEngine.outputFixes(report);
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
-ruleTester.run("my-rule", {}, {
+ruleTester.run("my-rule", {
+ create() {},
+}, {
valid: [
{
code: "var foo = true",
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index d6326c4ad5..d30abc5aa1 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -9,16 +9,16 @@ import { JSONSchema4 } from 'json-schema';
import * as ESTree from 'estree';
export type TokenType =
- | 'Boolean'
- | 'Null'
- | 'Identifier'
- | 'Keyword'
- | 'Punctuator'
- | 'JSXIdentifier'
- | 'JSXText'
- | 'Numeric'
- | 'String'
- | 'RegularExpression';
+ | 'Boolean'
+ | 'Null'
+ | 'Identifier'
+ | 'Keyword'
+ | 'Punctuator'
+ | 'JSXIdentifier'
+ | 'JSXText'
+ | 'Numeric'
+ | 'String'
+ | 'RegularExpression';
export interface Token {
type: TokenType;
@@ -46,146 +46,81 @@ export interface Ast {
range: Range;
}
-export type FilterPredicate = (tokenOrComment: Token | ESTree.Comment) => boolean;
+export namespace Scope {
+ interface ScopeManager {
+ scopes: Scope[];
+ globalScope: Scope | null;
-export type CursorWithSkipOptions = number | FilterPredicate | {
- includeComments?: boolean;
- filter?: FilterPredicate;
- skip?: number;
-};
+ acquire(node: ESTree.Node, inner?: boolean): Scope | null;
-export type CursorWithCountOptions = number | FilterPredicate | {
- includeComments?: boolean;
- filter?: FilterPredicate;
- count?: number;
-};
+ getDeclaredVariables(node: ESTree.Node): Variable[];
+ }
-export class TokenStore {
- getTokenByRangeStart(offset: number, options?: { includeComments?: boolean }): Token | null;
+ interface Scope {
+ type: 'block' | 'catch' | 'class' | 'for' | 'function' | 'function-expression-name' | 'global' | 'module' | 'switch' | 'with' | 'TDZ';
+ isStrict: boolean;
+ upper: Scope | null;
+ childScopes: Scope[];
+ variableScope: Scope;
+ block: ESTree.Node;
+ variables: Variable[];
+ set: Map;
+ references: Reference[];
+ through: Reference[];
+ functionExpressionScope: boolean;
+ }
- getFirstToken(node: ESTree.Node, options: CursorWithSkipOptions): Token | null;
+ interface Variable {
+ name: string;
+ identifiers: ESTree.Identifier;
+ references: Reference[];
+ defs: Definition[];
+ }
- getFirstTokens(node: ESTree.Node, options: CursorWithCountOptions): Token[];
+ interface Reference {
+ identifier: ESTree.Identifier;
+ from: Scope;
+ resolved: Variable | null;
+ writeExpr: ESTree.Node | null;
+ init: boolean;
- getLastToken(node: ESTree.Node, options: CursorWithSkipOptions): Token | null;
+ isWrite(): boolean;
- getLastTokens(node: ESTree.Node, options: CursorWithCountOptions): Token[];
+ isRead(): boolean;
- getTokenBefore(node: ESTree.Node | Token | ESTree.Comment, options: CursorWithSkipOptions): Token | null;
+ isWriteOnly(): boolean;
- getTokensBefore(node: ESTree.Node | Token | ESTree.Comment, options: CursorWithCountOptions): Token[];
+ isReadOnly(): boolean;
- getTokenAfter(node: ESTree.Node | Token | ESTree.Comment, options: CursorWithSkipOptions): Token | null;
+ isReadWrite(): boolean;
+ }
- getTokensAfter(node: ESTree.Node | Token | ESTree.Comment, options: CursorWithCountOptions): Token[];
+ type DefinitionType =
+ | { type: 'CatchClause', node: ESTree.CatchClause, parent: null }
+ | { type: 'ClassName', node: ESTree.ClassDeclaration | ESTree.ClassExpression, parent: null }
+ | { type: 'FunctionName', node: ESTree.FunctionDeclaration | ESTree.FunctionExpression, parent: null }
+ | { type: 'ImplicitGlobalVariable', node: ESTree.Program, parent: null }
+ | { type: 'ImportBinding', node: ESTree.ImportSpecifier | ESTree.ImportDefaultSpecifier | ESTree.ImportNamespaceSpecifier, parent: ESTree.ImportDeclaration }
+ | { type: 'Parameter', node: ESTree.FunctionDeclaration | ESTree.FunctionExpression | ESTree.ArrowFunctionExpression, parent: null }
+ | { type: 'TDZ', node: any, parent: null }
+ | { type: 'Variable', node: ESTree.VariableDeclarator, parent: ESTree.VariableDeclaration };
- getFirstTokenBetween(left: ESTree.Node | Token | ESTree.Comment, right: ESTree.Node | Token | ESTree.Comment, options: CursorWithSkipOptions): Token | null;
-
- getFirstTokensBetween(left: ESTree.Node | Token | ESTree.Comment, right: ESTree.Node | Token | ESTree.Comment, options: CursorWithCountOptions): Token[];
-
- getLastTokenBetween(left: ESTree.Node | Token | ESTree.Comment, right: ESTree.Node | Token | ESTree.Comment, options: CursorWithSkipOptions): Token | null;
-
- getLastTokensBetween(left: ESTree.Node | Token | ESTree.Comment, right: ESTree.Node | Token | ESTree.Comment, options: CursorWithCountOptions): Token[];
-
- getTokens(node: ESTree.Node, beforeCount?: number, afterCount?: number): Token[];
- getTokens(node: ESTree.Node, options: FilterPredicate | CursorWithCountOptions): Token[];
-
- getTokensBetween(left: ESTree.Node | Token | ESTree.Comment, right: ESTree.Node | Token | ESTree.Comment, padding: number | FilterPredicate | CursorWithCountOptions): Token[];
-
- commentsExistBetween(left: ESTree.Node, right: ESTree.Node): boolean;
-
- getCommentsBefore(nodeOrToken: ESTree.Node | Token): ESTree.Comment[];
-
- getCommentsAfter(nodeOrToken: ESTree.Node | Token): ESTree.Comment[];
-
- getCommentsInside(node: ESTree.Node): ESTree.Comment[];
+ type Definition = DefinitionType & { name: ESTree.Identifier };
}
-export interface SourceCodeConfig {
- text: string;
- ast: Ast;
- parserServices?: ParserServices;
- scopeManager?: ScopeManager;
- visitorKeys?: VisitorKeys;
-}
+//#region SourceCode
-export type ParserServices = any;
-
-export interface ScopeManager {
- scopes: Scope[];
- globalScope: Scope | null;
-
- acquire(node: ESTree.Node, inner?: boolean): Scope | null;
-
- getDeclaredVariables(node: ESTree.Node): Variable[];
-}
-
-export interface Scope {
- type: 'block' | 'catch' | 'class' | 'for' | 'function' | 'function-expression-name' | 'global' | 'module' | 'switch' | 'with' | 'TDZ';
- isStrict: boolean;
- upper: Scope | null;
- childScopes: Scope[];
- variableScope: Scope;
- block: ESTree.Node;
- variables: Variable[];
- set: Map;
- references: Reference[];
- through: Reference[];
- functionExpressionScope: boolean;
-}
-
-export interface Variable {
- name: string;
- identifiers: ESTree.Identifier;
- references: Reference[];
- defs: Definition[];
-}
-
-export interface Reference {
- identifier: ESTree.Identifier;
- from: Scope;
- resolved: Variable | null;
- writeExpr: ESTree.Node | null;
- init: boolean;
-
- isWrite(): boolean;
-
- isRead(): boolean;
-
- isWriteOnly(): boolean;
-
- isReadOnly(): boolean;
-
- isReadWrite(): boolean;
-}
-
-export type DefinitionType =
- | { type: 'CatchClause', node: ESTree.CatchClause, parent: null }
- | { type: 'ClassName', node: ESTree.ClassDeclaration | ESTree.ClassExpression, parent: null }
- | { type: 'FunctionName', node: ESTree.FunctionDeclaration | ESTree.FunctionExpression, parent: null }
- | { type: 'ImplicitGlobalVariable', node: ESTree.Program, parent: null }
- | { type: 'ImportBinding', node: ESTree.ImportSpecifier | ESTree.ImportDefaultSpecifier | ESTree.ImportNamespaceSpecifier, parent: ESTree.ImportDeclaration }
- | { type: 'Parameter', node: ESTree.FunctionDeclaration | ESTree.FunctionExpression | ESTree.ArrowFunctionExpression, parent: null }
- | { type: 'TDZ', node: any, parent: null }
- | { type: 'Variable', node: ESTree.VariableDeclarator, parent: ESTree.VariableDeclaration };
-
-export type Definition = DefinitionType & { name: ESTree.Identifier };
-
-export interface VisitorKeys {
- [nodeType: string]: string[];
-}
-
-export class SourceCode extends TokenStore {
+export class SourceCode {
text: string;
ast: Ast;
lines: string[];
hasBOM: boolean;
- parserServices: ParserServices;
- scopeManager: ScopeManager;
- visitorKeys: VisitorKeys;
+ parserServices: SourceCode.ParserServices;
+ scopeManager: Scope.ScopeManager;
+ visitorKeys: SourceCode.VisitorKeys;
constructor(text: string, ast: Ast);
- constructor(config: SourceCodeConfig);
+ constructor(config: SourceCode.Config);
static splitLines(text: string): string[];
@@ -206,317 +141,436 @@ export class SourceCode extends TokenStore {
getLocFromIndex(index: number): Location;
getIndexFromLoc(location: Location): number;
+
+ // Inherited methods from TokenStore
+ // ---------------------------------
+
+ getTokenByRangeStart(offset: number, options?: { includeComments?: boolean }): Token | null;
+
+ getFirstToken(node: ESTree.Node, options: SourceCode.CursorWithSkipOptions): Token | null;
+
+ getFirstTokens(node: ESTree.Node, options: SourceCode.CursorWithCountOptions): Token[];
+
+ getLastToken(node: ESTree.Node, options: SourceCode.CursorWithSkipOptions): Token | null;
+
+ getLastTokens(node: ESTree.Node, options: SourceCode.CursorWithCountOptions): Token[];
+
+ getTokenBefore(node: ESTree.Node | Token | ESTree.Comment, options: SourceCode.CursorWithSkipOptions): Token | null;
+
+ getTokensBefore(node: ESTree.Node | Token | ESTree.Comment, options: SourceCode.CursorWithCountOptions): Token[];
+
+ getTokenAfter(node: ESTree.Node | Token | ESTree.Comment, options: SourceCode.CursorWithSkipOptions): Token | null;
+
+ getTokensAfter(node: ESTree.Node | Token | ESTree.Comment, options: SourceCode.CursorWithCountOptions): Token[];
+
+ getFirstTokenBetween(
+ left: ESTree.Node | Token | ESTree.Comment,
+ right: ESTree.Node | Token | ESTree.Comment,
+ options: SourceCode.CursorWithSkipOptions
+ ): Token | null;
+
+ getFirstTokensBetween(
+ left: ESTree.Node | Token | ESTree.Comment,
+ right: ESTree.Node | Token | ESTree.Comment,
+ options: SourceCode.CursorWithCountOptions
+ ): Token[];
+
+ getLastTokenBetween(
+ left: ESTree.Node | Token | ESTree.Comment,
+ right: ESTree.Node | Token | ESTree.Comment,
+ options: SourceCode.CursorWithSkipOptions
+ ): Token | null;
+
+ getLastTokensBetween(
+ left: ESTree.Node | Token | ESTree.Comment,
+ right: ESTree.Node | Token | ESTree.Comment,
+ options: SourceCode.CursorWithCountOptions
+ ): Token[];
+
+ getTokensBetween(
+ left: ESTree.Node | Token | ESTree.Comment,
+ right: ESTree.Node | Token | ESTree.Comment,
+ padding: number | SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions
+ ): Token[];
+
+ getTokens(node: ESTree.Node, beforeCount?: number, afterCount?: number): Token[];
+ getTokens(node: ESTree.Node, options: SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions): Token[];
+
+ commentsExistBetween(left: ESTree.Node, right: ESTree.Node): boolean;
+
+ getCommentsBefore(nodeOrToken: ESTree.Node | Token): ESTree.Comment[];
+
+ getCommentsAfter(nodeOrToken: ESTree.Node | Token): ESTree.Comment[];
+
+ getCommentsInside(node: ESTree.Node): ESTree.Comment[];
}
-export type RuleLevel = 'off' | 'warn' | 'error' | 0 | 1 | 2;
+export namespace SourceCode {
+ interface Config {
+ text: string;
+ ast: Ast;
+ parserServices?: ParserServices;
+ scopeManager?: Scope.ScopeManager;
+ visitorKeys?: VisitorKeys;
+ }
-export interface ParserOptions {
- ecmaVersion?: 3 | 5 | 6 | 7 | 8 | 9 | 2015 | 2016 | 2017 | 2018;
- sourceType?: 'script' | 'module';
- ecmaFeatures?: {
- globalReturn?: boolean;
- impliedStrict?: boolean;
- jsx?: boolean;
- experimentalObjectRestSpread?: boolean;
- [key: string]: any;
+ type ParserServices = any;
+
+ interface VisitorKeys {
+ [nodeType: string]: string[];
+ }
+
+ type FilterPredicate = (tokenOrComment: Token | ESTree.Comment) => boolean;
+
+ type CursorWithSkipOptions = number | FilterPredicate | {
+ includeComments?: boolean;
+ filter?: FilterPredicate;
+ skip?: number;
};
- [key: string]: any;
-}
-export interface Config {
- rules?: {
- [name: string]: (RuleLevel | [RuleLevel, any])
+ type CursorWithCountOptions = number | FilterPredicate | {
+ includeComments?: boolean;
+ filter?: FilterPredicate;
+ count?: number;
};
- parser?: string;
- parserOptions?: ParserOptions;
- settings?: { [name: string]: any };
- env?: { [name: string]: boolean };
- globals?: { [name: string]: boolean };
}
-export interface LintOptions {
- filename?: string;
- preprocess?: (code: string) => string[];
- postprocess?: (problemLists: LintMessage[][]) => LintMessage[];
- allowInlineConfig?: boolean;
- reportUnusedDisableDirectives?: boolean;
+//#endregion
+
+export namespace Rule {
+ interface RuleModule {
+ create(context: RuleContext): any;
+ meta?: RuleMetaData;
+ }
+
+ interface RuleListener {
+ onCodePathStart?(codePath: CodePath, node: ESTree.Node): void;
+
+ onCodePathEnd?(codePath: CodePath, node: ESTree.Node): void;
+
+ onCodePathSegmentStart?(segment: CodePathSegment, node: ESTree.Node): void;
+
+ onCodePathSegmentEnd?(segment: CodePathSegment, node: ESTree.Node): void;
+
+ onCodePathSegmentLoop?(fromSegment: CodePathSegment, toSegment: CodePathSegment, node: ESTree.Node): void;
+
+ [key: string]:
+ | ((codePath: CodePath, node: ESTree.Node) => void)
+ | ((segment: CodePathSegment, node: ESTree.Node) => void)
+ | ((fromSegment: CodePathSegment, toSegment: CodePathSegment, node: ESTree.Node) => void)
+ | ((node: ESTree.Node) => void)
+ | undefined;
+ }
+
+ interface CodePath {
+ id: string;
+ initialSegment: CodePathSegment;
+ finalSegments: CodePathSegment[];
+ returnedSegments: CodePathSegment[];
+ thrownSegments: CodePathSegment[];
+ currentSegments: CodePathSegment[];
+ upper: CodePath | null;
+ childCodePaths: CodePath[];
+ }
+
+ interface CodePathSegment {
+ id: string;
+ nextSegments: CodePathSegment[];
+ prevSegments: CodePathSegment[];
+ reachable: boolean;
+ }
+
+ interface RuleMetaData {
+ docs?: {
+ description?: string;
+ category?: string;
+ recommended?: boolean;
+ url?: string;
+ };
+ messages?: { [messageId: string]: string };
+ fixable?: 'code' | 'whitespace';
+ schema?: JSONSchema4 | JSONSchema4[];
+ deprecated?: boolean;
+ }
+
+ interface RuleContext {
+ id: string;
+ options: any[];
+ settings: { [name: string]: any };
+ parserPath: string;
+ parserOptions: Linter.ParserOptions;
+ parserServices: SourceCode.ParserServices;
+
+ getAncestors(): ESTree.Node[];
+
+ getDeclaredVariables(node: ESTree.Node): Scope.Variable[];
+
+ getFilename(): string;
+
+ getScope(): Scope.Scope;
+
+ getSourceCode(): SourceCode;
+
+ markVariableAsUsed(name: string): boolean;
+
+ report(descriptor: ReportDescriptor): void;
+ }
+
+ type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
+ type ReportDescriptorMessage = { message: string } | { messageId: string };
+ type ReportDescriptorLocation = { node: ESTree.Node } | { loc: SourceLocation | { line: number, column: number } };
+ interface ReportDescriptorOptions {
+ data?: { [key: string]: string };
+
+ fix?(fixer: RuleFixer): null | Fix | IterableIterator;
+ }
+
+ interface RuleFixer {
+ insertTextAfter(nodeOrToken: ESTree.Node | Token, text: string): Fix;
+
+ insertTextAfterRange(range: Range, text: string): Fix;
+
+ insertTextBefore(nodeOrToken: ESTree.Node | Token, text: string): Fix;
+
+ insertTextBeforeRange(range: Range, text: string): Fix;
+
+ remove(nodeOrToken: ESTree.Node | Token): Fix;
+
+ removeRange(range: Range): Fix;
+
+ replaceText(nodeOrToken: ESTree.Node | Token, text: string): Fix;
+
+ replaceTextRange(range: Range, text: string): Fix;
+ }
+
+ interface Fix {
+ range: Range;
+ text: string;
+ }
}
-export type Severity = 1 | 2;
-
-export interface LintMessage {
- column: number;
- line: number;
- endColumn?: number;
- endLine?: number;
- ruleId: string | null;
- message: string;
- nodeType: string;
- fatal?: true;
- severity: Severity;
- fix?: Fix;
- source: string | null;
-}
-
-export interface FixOptions extends LintOptions {
- fix?: boolean;
-}
-
-export interface Fix {
- range: Range;
- text: string;
-}
-
-export interface FixReport {
- fixed: boolean;
- output: string;
- messages: LintMessage[];
-}
-
-export interface RuleModule {
- create(context: RuleContext): any;
- meta?: RuleMetaData;
-}
-
-export interface RuleListener {
- onCodePathStart?(codePath: CodePath, node: ESTree.Node): void;
-
- onCodePathEnd?(codePath: CodePath, node: ESTree.Node): void;
-
- onCodePathSegmentStart?(segment: CodePathSegment, node: ESTree.Node): void;
-
- onCodePathSegmentEnd?(segment: CodePathSegment, node: ESTree.Node): void;
-
- onCodePathSegmentLoop?(fromSegment: CodePathSegment, toSegment: CodePathSegment, node: ESTree.Node): void;
-
- [key: string]:
- | ((codePath: CodePath, node: ESTree.Node) => void)
- | ((segment: CodePathSegment, node: ESTree.Node) => void)
- | ((fromSegment: CodePathSegment, toSegment: CodePathSegment, node: ESTree.Node) => void)
- | ((node: ESTree.Node) => void)
- | undefined;
-}
-
-export interface CodePath {
- id: string;
- initialSegment: CodePathSegment;
- finalSegments: CodePathSegment[];
- returnedSegments: CodePathSegment[];
- thrownSegments: CodePathSegment[];
- currentSegments: CodePathSegment[];
- upper: CodePath | null;
- childCodePaths: CodePath[];
-}
-
-export interface CodePathSegment {
- id: string;
- nextSegments: CodePathSegment[];
- prevSegments: CodePathSegment[];
- reachable: boolean;
-}
-
-export interface RuleMetaData {
- docs?: {
- description?: string;
- category?: string;
- recommended?: boolean;
- url?: string;
- };
- messages?: { [messageId: string]: string };
- fixable?: 'code' | 'whitespace';
- schema?: JSONSchema4 | JSONSchema4[];
- deprecated?: boolean;
-}
-
-export interface RuleContext {
- id: string;
- options: any[];
- settings: { [name: string]: any };
- parserPath: string;
- parserOptions: ParserOptions;
- parserServices: ParserServices;
-
- getAncestors(): ESTree.Node[];
-
- getDeclaredVariables(node: ESTree.Node): Variable[];
-
- getFilename(): string;
-
- getScope(): Scope;
-
- getSourceCode(): SourceCode;
-
- markVariableAsUsed(name: string): boolean;
-
- report(descriptor: ReportDescriptor): void;
-}
-
-export type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
-export type ReportDescriptorMessage = { message: string } | { messageId: string };
-export type ReportDescriptorLocation = { node: ESTree.Node } | { loc: SourceLocation | { line: number, column: number } };
-export interface ReportDescriptorOptions {
- data?: { [key: string]: string };
-
- fix?(fixer: RuleFixer): null | Fix | IterableIterator;
-}
-
-export interface RuleFixer {
- insertTextAfter(nodeOrToken: ESTree.Node | Token, text: string): Fix;
-
- insertTextAfterRange(range: Range, text: string): Fix;
-
- insertTextBefore(nodeOrToken: ESTree.Node | Token, text: string): Fix;
-
- insertTextBeforeRange(range: Range, text: string): Fix;
-
- remove(nodeOrToken: ESTree.Node | Token): Fix;
-
- removeRange(range: Range): Fix;
-
- replaceText(nodeOrToken: ESTree.Node | Token, text: string): Fix;
-
- replaceTextRange(range: Range, text: string): Fix;
-}
-
-export type ParserModule = {
- parse(text: string, options?: any): ESTree.Node;
-} | {
- parseForESLint(text: string, options?: any): ESLintParseResult;
-};
-
-export interface ESLintParseResult {
- ast: ESTree.Node;
- parserServices?: ParserServices;
- scopeManager?: ScopeManager;
- visitorKeys?: VisitorKeys;
-}
+//#region Linter
export class Linter {
version: string;
- verify(code: SourceCode | string, config: Config, filename?: string): LintMessage[];
- verify(code: SourceCode | string, config: Config, options: LintOptions): LintMessage[];
+ verify(code: SourceCode | string, config: Linter.Config, filename?: string): Linter.LintMessage[];
+ verify(code: SourceCode | string, config: Linter.Config, options: Linter.LintOptions): Linter.LintMessage[];
- verifyAndFix(code: string, config: Config, filename?: string): FixReport;
- verifyAndFix(code: string, config: Config, options: FixOptions): FixReport;
+ verifyAndFix(code: string, config: Linter.Config, filename?: string): Linter.FixReport;
+ verifyAndFix(code: string, config: Linter.Config, options: Linter.FixOptions): Linter.FixReport;
getSourceCode(): SourceCode;
- defineRule(name: string, rule: RuleModule): void;
+ defineRule(name: string, rule: Rule.RuleModule): void;
- defineRules(rules: { [name: string]: RuleModule }): void;
+ defineRules(rules: { [name: string]: Rule.RuleModule }): void;
- getRules(): Map;
+ getRules(): Map;
- defineParser(name: string, parser: ParserModule): void;
+ defineParser(name: string, parser: Linter.ParserModule): void;
}
-export class CLIEngineOptions {
- allowInlineConfig?: boolean;
- baseConfig?: boolean;
- cache?: boolean;
- cacheFile?: string;
- cacheLocation?: string;
- configFile?: string;
- cwd?: string;
- envs?: string[];
- extensions?: string[];
- fix?: boolean;
- globals?: string[];
- ignore?: boolean;
- ignorePath?: string;
- ignorePattern?: string;
- useEslintrc?: boolean;
- parser?: string;
- parserOptions?: ParserOptions;
- plugins?: string[];
- rules?: {
- [name: string]: (RuleLevel | [RuleLevel, any]);
+export namespace Linter {
+ type Severity = 0 | 1 | 2;
+ type RuleLevel = Severity | 'off' | 'warn' | 'error';
+
+ interface RuleLevelAndOptions extends Array {
+ 0: RuleLevel;
+ }
+
+ interface Config {
+ rules?: {
+ [name: string]: RuleLevel | RuleLevelAndOptions
+ };
+ parser?: string;
+ parserOptions?: ParserOptions;
+ settings?: { [name: string]: any };
+ env?: { [name: string]: boolean };
+ globals?: { [name: string]: boolean };
+ }
+
+ interface ParserOptions {
+ ecmaVersion?: 3 | 5 | 6 | 7 | 8 | 9 | 2015 | 2016 | 2017 | 2018;
+ sourceType?: 'script' | 'module';
+ ecmaFeatures?: {
+ globalReturn?: boolean;
+ impliedStrict?: boolean;
+ jsx?: boolean;
+ experimentalObjectRestSpread?: boolean;
+ [key: string]: any;
+ };
+ [key: string]: any;
+ }
+
+ interface LintOptions {
+ filename?: string;
+ preprocess?: (code: string) => string[];
+ postprocess?: (problemLists: LintMessage[][]) => LintMessage[];
+ allowInlineConfig?: boolean;
+ reportUnusedDisableDirectives?: boolean;
+ }
+
+ interface LintMessage {
+ column: number;
+ line: number;
+ endColumn?: number;
+ endLine?: number;
+ ruleId: string | null;
+ message: string;
+ nodeType: string;
+ fatal?: true;
+ severity: Severity;
+ fix?: Rule.Fix;
+ source: string | null;
+ }
+
+ interface FixOptions extends LintOptions {
+ fix?: boolean;
+ }
+
+ interface FixReport {
+ fixed: boolean;
+ output: string;
+ messages: LintMessage[];
+ }
+
+ type ParserModule = {
+ parse(text: string, options?: any): ESTree.Node;
+ } | {
+ parseForESLint(text: string, options?: any): ESLintParseResult;
};
- rulePaths?: string[];
- reportUnusedDisableDirectives?: true;
+
+ interface ESLintParseResult {
+ ast: ESTree.Node;
+ parserServices?: SourceCode.ParserServices;
+ scopeManager?: Scope.ScopeManager;
+ visitorKeys?: SourceCode.VisitorKeys;
+ }
}
-export interface LintResult {
- filePath: string;
- messages: LintMessage[];
- errorCount: number;
- warningCount: number;
- fixableErrorCount: number;
- fixableWarningCount: number;
- output?: string;
- source?: string;
-}
+//#endregion
-export interface LintReport {
- results: LintResult[];
- errorCount: number;
- warningCount: number;
- fixableErrorCount: number;
- fixableWarningCount: number;
-}
-
-export type Formatter = (results: LintResult[]) => string;
+//#region CLIEngine
export class CLIEngine {
version: string;
- constructor(options: CLIEngineOptions);
+ constructor(options: CLIEngine.Options);
- executeOnFiles(patterns: string[]): LintReport;
+ executeOnFiles(patterns: string[]): CLIEngine.LintReport;
resolveFileGlobPatterns(patterns: string[]): string[];
- getConfigForFile(filePath: string): Config;
+ getConfigForFile(filePath: string): Linter.Config;
- executeOnText(text: string, filename?: string): LintReport;
+ executeOnText(text: string, filename?: string): CLIEngine.LintReport;
addPlugin(name: string, pluginObject: any): void;
isPathIgnored(filePath: string): boolean;
- getFormatter(format: string): Formatter;
+ getFormatter(format: string): CLIEngine.Formatter;
- static getErrorResults(results: LintResult[]): LintResult[];
+ getRules(): Map;
- static outputFixes(report: LintReport): void;
+ static getErrorResults(results: CLIEngine.LintResult[]): CLIEngine.LintResult[];
- getRules(): Map;
+ static outputFixes(report: CLIEngine.LintReport): void;
}
-export interface ValidTestCase {
- code: string;
- options?: any;
- filename?: string;
- parserOptions?: ParserOptions;
- settings?: { [name: string]: any };
- parser?: string;
- globals?: { [name: string]: boolean };
+export namespace CLIEngine {
+ class Options {
+ allowInlineConfig?: boolean;
+ baseConfig?: boolean;
+ cache?: boolean;
+ cacheFile?: string;
+ cacheLocation?: string;
+ configFile?: string;
+ cwd?: string;
+ envs?: string[];
+ extensions?: string[];
+ fix?: boolean;
+ globals?: string[];
+ ignore?: boolean;
+ ignorePath?: string;
+ ignorePattern?: string;
+ useEslintrc?: boolean;
+ parser?: string;
+ parserOptions?: Linter.ParserOptions;
+ plugins?: string[];
+ rules?: {
+ [name: string]: (Linter.RuleLevel | [Linter.RuleLevel, any]);
+ };
+ rulePaths?: string[];
+ reportUnusedDisableDirectives?: true;
+ }
+
+ interface LintResult {
+ filePath: string;
+ messages: Linter.LintMessage[];
+ errorCount: number;
+ warningCount: number;
+ fixableErrorCount: number;
+ fixableWarningCount: number;
+ output?: string;
+ source?: string;
+ }
+
+ interface LintReport {
+ results: LintResult[];
+ errorCount: number;
+ warningCount: number;
+ fixableErrorCount: number;
+ fixableWarningCount: number;
+ }
+
+ type Formatter = (results: LintResult[]) => string;
}
-export interface TestCaseError {
- message?: string | RegExp;
- messageId?: string;
- type?: string;
- data?: any;
- line?: number;
- column?: number;
- endLine?: number;
- endColumn?: number;
-}
+//#endregion
-export interface InvalidTestCase extends ValidTestCase {
- errors: number | Array;
- output?: string;
-}
-
-export interface Test {
- valid?: ValidTestCase[];
- invalid: InvalidTestCase[];
-}
+//#region RuleTester
export class RuleTester {
constructor(config?: any);
- run(name: string, rule: any, tests: Test): void;
+ run(
+ name: string,
+ rule: Rule.RuleModule,
+ tests: {
+ valid?: RuleTester.ValidTestCase[];
+ invalid?: RuleTester.InvalidTestCase[];
+ },
+ ): void;
}
+
+export namespace RuleTester {
+ interface ValidTestCase {
+ code: string;
+ options?: any;
+ filename?: string;
+ parserOptions?: Linter.ParserOptions;
+ settings?: { [name: string]: any };
+ parser?: string;
+ globals?: { [name: string]: boolean };
+ }
+
+ interface InvalidTestCase extends ValidTestCase {
+ errors: number | Array;
+ output?: string;
+ }
+
+ interface TestCaseError {
+ message?: string | RegExp;
+ messageId?: string;
+ type?: string;
+ data?: any;
+ line?: number;
+ column?: number;
+ endLine?: number;
+ endColumn?: number;
+ }
+}
+
+//#endregion
From 4e6dd4d9bc9736fcfe063ffec6850b2c298cebde Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Thu, 1 Feb 2018 07:27:21 -0800
Subject: [PATCH 13/23] Add namespace for AST and intrgrate misc feedback
---
types/eslint/index.d.ts | 161 ++++++++++++++++++++--------------------
1 file changed, 79 insertions(+), 82 deletions(-)
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index d30abc5aa1..2ef75b2612 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -8,42 +8,39 @@
import { JSONSchema4 } from 'json-schema';
import * as ESTree from 'estree';
-export type TokenType =
- | 'Boolean'
- | 'Null'
- | 'Identifier'
- | 'Keyword'
- | 'Punctuator'
- | 'JSXIdentifier'
- | 'JSXText'
- | 'Numeric'
- | 'String'
- | 'RegularExpression';
+export namespace AST {
+ export type TokenType =
+ | 'Boolean'
+ | 'Null'
+ | 'Identifier'
+ | 'Keyword'
+ | 'Punctuator'
+ | 'JSXIdentifier'
+ | 'JSXText'
+ | 'Numeric'
+ | 'String'
+ | 'RegularExpression';
-export interface Token {
- type: TokenType;
- value: string;
- range: Range;
- loc: SourceLocation;
-}
+ export interface Token {
+ type: TokenType;
+ value: string;
+ range: Range;
+ loc: SourceLocation;
+ }
-export interface SourceLocation {
- start: Location;
- end: Location;
-}
+ export interface SourceLocation {
+ start: ESTree.Position;
+ end: ESTree.Position;
+ }
-export interface Location {
- line: number;
- column: number;
-}
+ export type Range = [number, number];
-export type Range = [number, number];
-
-export interface Ast {
- comments: ESTree.Comment[];
- tokens: Token[];
- loc: SourceLocation;
- range: Range;
+ export interface Program extends ESTree.Program {
+ comments: ESTree.Comment[];
+ tokens: Token[];
+ loc: SourceLocation;
+ range: Range;
+ }
}
export namespace Scope {
@@ -112,14 +109,14 @@ export namespace Scope {
export class SourceCode {
text: string;
- ast: Ast;
+ ast: AST.Program;
lines: string[];
hasBOM: boolean;
parserServices: SourceCode.ParserServices;
scopeManager: Scope.ScopeManager;
visitorKeys: SourceCode.VisitorKeys;
- constructor(text: string, ast: Ast);
+ constructor(text: string, ast: AST.Program);
constructor(config: SourceCode.Config);
static splitLines(text: string): string[];
@@ -132,75 +129,75 @@ export class SourceCode {
getComments(node: ESTree.Node): { leading: ESTree.Comment[], trailing: ESTree.Comment[] };
- getJSDocComment(node: ESTree.Node): Token | null;
+ getJSDocComment(node: ESTree.Node): AST.Token | null;
getNodeByRangeIndex(index: number): ESTree.Node | null;
- isSpaceBetweenTokens(first: Token, second: Token): boolean;
+ isSpaceBetweenTokens(first: AST.Token, second: AST.Token): boolean;
- getLocFromIndex(index: number): Location;
+ getLocFromIndex(index: number): ESTree.SourceLocation;
- getIndexFromLoc(location: Location): number;
+ getIndexFromLoc(location: ESTree.SourceLocation): number;
// Inherited methods from TokenStore
// ---------------------------------
- getTokenByRangeStart(offset: number, options?: { includeComments?: boolean }): Token | null;
+ getTokenByRangeStart(offset: number, options?: { includeComments?: boolean }): AST.Token | null;
- getFirstToken(node: ESTree.Node, options: SourceCode.CursorWithSkipOptions): Token | null;
+ getFirstToken(node: ESTree.Node, options: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getFirstTokens(node: ESTree.Node, options: SourceCode.CursorWithCountOptions): Token[];
+ getFirstTokens(node: ESTree.Node, options: SourceCode.CursorWithCountOptions): AST.Token[];
- getLastToken(node: ESTree.Node, options: SourceCode.CursorWithSkipOptions): Token | null;
+ getLastToken(node: ESTree.Node, options: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getLastTokens(node: ESTree.Node, options: SourceCode.CursorWithCountOptions): Token[];
+ getLastTokens(node: ESTree.Node, options: SourceCode.CursorWithCountOptions): AST.Token[];
- getTokenBefore(node: ESTree.Node | Token | ESTree.Comment, options: SourceCode.CursorWithSkipOptions): Token | null;
+ getTokenBefore(node: ESTree.Node | AST.Token | ESTree.Comment, options: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getTokensBefore(node: ESTree.Node | Token | ESTree.Comment, options: SourceCode.CursorWithCountOptions): Token[];
+ getTokensBefore(node: ESTree.Node | AST.Token | ESTree.Comment, options: SourceCode.CursorWithCountOptions): AST.Token[];
- getTokenAfter(node: ESTree.Node | Token | ESTree.Comment, options: SourceCode.CursorWithSkipOptions): Token | null;
+ getTokenAfter(node: ESTree.Node | AST.Token | ESTree.Comment, options: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getTokensAfter(node: ESTree.Node | Token | ESTree.Comment, options: SourceCode.CursorWithCountOptions): Token[];
+ getTokensAfter(node: ESTree.Node | AST.Token | ESTree.Comment, options: SourceCode.CursorWithCountOptions): AST.Token[];
getFirstTokenBetween(
- left: ESTree.Node | Token | ESTree.Comment,
- right: ESTree.Node | Token | ESTree.Comment,
+ left: ESTree.Node | AST.Token | ESTree.Comment,
+ right: ESTree.Node | AST.Token | ESTree.Comment,
options: SourceCode.CursorWithSkipOptions
- ): Token | null;
+ ): AST.Token | null;
getFirstTokensBetween(
- left: ESTree.Node | Token | ESTree.Comment,
- right: ESTree.Node | Token | ESTree.Comment,
+ left: ESTree.Node | AST.Token | ESTree.Comment,
+ right: ESTree.Node | AST.Token | ESTree.Comment,
options: SourceCode.CursorWithCountOptions
- ): Token[];
+ ): AST.Token[];
getLastTokenBetween(
- left: ESTree.Node | Token | ESTree.Comment,
- right: ESTree.Node | Token | ESTree.Comment,
+ left: ESTree.Node | AST.Token | ESTree.Comment,
+ right: ESTree.Node | AST.Token | ESTree.Comment,
options: SourceCode.CursorWithSkipOptions
- ): Token | null;
+ ): AST.Token | null;
getLastTokensBetween(
- left: ESTree.Node | Token | ESTree.Comment,
- right: ESTree.Node | Token | ESTree.Comment,
+ left: ESTree.Node | AST.Token | ESTree.Comment,
+ right: ESTree.Node | AST.Token | ESTree.Comment,
options: SourceCode.CursorWithCountOptions
- ): Token[];
+ ): AST.Token[];
getTokensBetween(
- left: ESTree.Node | Token | ESTree.Comment,
- right: ESTree.Node | Token | ESTree.Comment,
+ left: ESTree.Node | AST.Token | ESTree.Comment,
+ right: ESTree.Node | AST.Token | ESTree.Comment,
padding: number | SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions
- ): Token[];
+ ): AST.Token[];
- getTokens(node: ESTree.Node, beforeCount?: number, afterCount?: number): Token[];
- getTokens(node: ESTree.Node, options: SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions): Token[];
+ getTokens(node: ESTree.Node, beforeCount?: number, afterCount?: number): AST.Token[];
+ getTokens(node: ESTree.Node, options: SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions): AST.Token[];
commentsExistBetween(left: ESTree.Node, right: ESTree.Node): boolean;
- getCommentsBefore(nodeOrToken: ESTree.Node | Token): ESTree.Comment[];
+ getCommentsBefore(nodeOrToken: ESTree.Node | AST.Token): ESTree.Comment[];
- getCommentsAfter(nodeOrToken: ESTree.Node | Token): ESTree.Comment[];
+ getCommentsAfter(nodeOrToken: ESTree.Node | AST.Token): ESTree.Comment[];
getCommentsInside(node: ESTree.Node): ESTree.Comment[];
}
@@ -208,7 +205,7 @@ export class SourceCode {
export namespace SourceCode {
interface Config {
text: string;
- ast: Ast;
+ ast: AST.Program;
parserServices?: ParserServices;
scopeManager?: Scope.ScopeManager;
visitorKeys?: VisitorKeys;
@@ -220,7 +217,7 @@ export namespace SourceCode {
[nodeType: string]: string[];
}
- type FilterPredicate = (tokenOrComment: Token | ESTree.Comment) => boolean;
+ type FilterPredicate = (tokenOrComment: AST.Token | ESTree.Comment) => boolean;
type CursorWithSkipOptions = number | FilterPredicate | {
includeComments?: boolean;
@@ -318,7 +315,7 @@ export namespace Rule {
type ReportDescriptor = ReportDescriptorMessage & ReportDescriptorLocation & ReportDescriptorOptions;
type ReportDescriptorMessage = { message: string } | { messageId: string };
- type ReportDescriptorLocation = { node: ESTree.Node } | { loc: SourceLocation | { line: number, column: number } };
+ type ReportDescriptorLocation = { node: ESTree.Node } | { loc: AST.SourceLocation | { line: number, column: number } };
interface ReportDescriptorOptions {
data?: { [key: string]: string };
@@ -326,25 +323,25 @@ export namespace Rule {
}
interface RuleFixer {
- insertTextAfter(nodeOrToken: ESTree.Node | Token, text: string): Fix;
+ insertTextAfter(nodeOrToken: ESTree.Node | AST.Token, text: string): Fix;
- insertTextAfterRange(range: Range, text: string): Fix;
+ insertTextAfterRange(range: AST.Range, text: string): Fix;
- insertTextBefore(nodeOrToken: ESTree.Node | Token, text: string): Fix;
+ insertTextBefore(nodeOrToken: ESTree.Node | AST.Token, text: string): Fix;
- insertTextBeforeRange(range: Range, text: string): Fix;
+ insertTextBeforeRange(range: AST.Range, text: string): Fix;
- remove(nodeOrToken: ESTree.Node | Token): Fix;
+ remove(nodeOrToken: ESTree.Node | AST.Token): Fix;
- removeRange(range: Range): Fix;
+ removeRange(range: AST.Range): Fix;
- replaceText(nodeOrToken: ESTree.Node | Token, text: string): Fix;
+ replaceText(nodeOrToken: ESTree.Node | AST.Token, text: string): Fix;
- replaceTextRange(range: Range, text: string): Fix;
+ replaceTextRange(range: AST.Range, text: string): Fix;
}
interface Fix {
- range: Range;
+ range: AST.Range;
text: string;
}
}
@@ -442,7 +439,7 @@ export namespace Linter {
};
interface ESLintParseResult {
- ast: ESTree.Node;
+ ast: AST.Program;
parserServices?: SourceCode.ParserServices;
scopeManager?: Scope.ScopeManager;
visitorKeys?: SourceCode.VisitorKeys;
@@ -500,10 +497,10 @@ export namespace CLIEngine {
parserOptions?: Linter.ParserOptions;
plugins?: string[];
rules?: {
- [name: string]: (Linter.RuleLevel | [Linter.RuleLevel, any]);
+ [name: string]: Linter.RuleLevel | Linter.RuleLevelAndOptions;
};
rulePaths?: string[];
- reportUnusedDisableDirectives?: true;
+ reportUnusedDisableDirectives?: boolean;
}
interface LintResult {
@@ -558,7 +555,7 @@ export namespace RuleTester {
interface InvalidTestCase extends ValidTestCase {
errors: number | Array;
- output?: string;
+ output?: string | null;
}
interface TestCaseError {
From 883e14890adacb1199d4e48785d11fabe9185415 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Fri, 2 Feb 2018 07:28:10 -0800
Subject: [PATCH 14/23] Add source code coverage
---
types/eslint/eslint-tests.ts | 233 +++++++++++++++++++++++++++++++----
types/eslint/index.d.ts | 14 +--
2 files changed, 219 insertions(+), 28 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index 46f960dbd4..65bfcc294d 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -1,27 +1,216 @@
-import { SourceCode, Linter, CLIEngine, RuleTester, Ast } from 'eslint';
-
-// =============================================
-// SourceCode
-// =============================================
+import { Comment } from 'estree';
+import { SourceCode, Linter, CLIEngine, RuleTester, AST } from 'eslint';
const SOURCE = `var foo = bar;`;
-const ast: Ast = { comments: [], tokens: [], loc: { start: { line: 0, column: 0 }, end: { line: 0, column: 10 } }, range: [0, 17] };
-const sourceCode = new SourceCode(SOURCE, ast);
+const AST: AST.Program = {
+ type: 'Program',
+ sourceType: 'module',
+ body: [],
+ comments: [],
+ tokens: [],
+ loc: {
+ start: { line: 0, column: 0 },
+ end: { line: 0, column: 0 }
+ },
+ range: [0, 0],
+};
-const text: string = sourceCode.getText();
+const TOKEN: AST.Token = {
+ type: 'Identifier',
+ value: 'foo',
+ loc: {
+ start: { line: 0, column: 0 },
+ end: { line: 0, column: 3 }
+ },
+ range: [0, 3]
+};
-const lines: string[] = sourceCode.getLines();
+const COMMENT: Comment = {
+ type: 'Block',
+ value: 'foo',
+ loc: {
+ start: { line: 0, column: 0 },
+ end: { line: 0, column: 0 }
+ },
+ range: [0, 0],
+};
+
+//#region SourceCode
+
+const sourceCode = new SourceCode(SOURCE, AST);
SourceCode.splitLines(SOURCE);
-class Foo {
- foo = 1;
-}
+sourceCode.getText();
+sourceCode.getText(AST);
+sourceCode.getText(AST, 0);
+sourceCode.getText(AST, 0, 0);
-// =============================================
-// Linter
-// =============================================
+sourceCode.getLines();
+
+sourceCode.getAllComments();
+
+sourceCode.getComments(AST).leading;
+sourceCode.getComments(AST).trailing;
+
+sourceCode.getJSDocComment(AST);
+
+sourceCode.getNodeByRangeIndex(0);
+
+sourceCode.getNodeByRangeIndex(0);
+
+sourceCode.isSpaceBetweenTokens(TOKEN, TOKEN);
+
+sourceCode.getLocFromIndex(0);
+
+sourceCode.getIndexFromLoc({ line: 0, column: 0 });
+
+sourceCode.getTokenByRangeStart(0);
+sourceCode.getTokenByRangeStart(0, { includeComments: true });
+
+// TODO: Should accept no second parameter?
+sourceCode.getFirstToken(AST, 0);
+sourceCode.getFirstToken(AST, { skip: 0 });
+sourceCode.getFirstToken(AST, t => t.type === 'Identifier');
+sourceCode.getFirstToken(AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getFirstToken(AST, { skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getFirstToken(AST, { includeComments: true });
+sourceCode.getFirstToken(AST, { includeComments: true, skip: 0 });
+sourceCode.getFirstToken(AST, { includeComments: true, skip: 0, filter: t => t.type === 'Identifier' });
+
+sourceCode.getFirstTokens(AST, 0);
+sourceCode.getFirstTokens(AST, { count: 0 });
+sourceCode.getFirstTokens(AST, t => t.type === 'Identifier');
+sourceCode.getFirstTokens(AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getFirstTokens(AST, { count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getFirstTokens(AST, { includeComments: true });
+sourceCode.getFirstTokens(AST, { includeComments: true, count: 0 });
+sourceCode.getFirstTokens(AST, { includeComments: true, count: 0, filter: t => t.type === 'Identifier' });
+
+sourceCode.getLastToken(AST, 0);
+sourceCode.getLastToken(AST, { skip: 0 });
+sourceCode.getLastToken(AST, t => t.type === 'Identifier');
+sourceCode.getLastToken(AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getLastToken(AST, { skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getLastToken(AST, { includeComments: true });
+sourceCode.getLastToken(AST, { includeComments: true, skip: 0 });
+sourceCode.getLastToken(AST, { includeComments: true, skip: 0, filter: t => t.type === 'Identifier' });
+
+sourceCode.getLastTokens(AST, 0);
+sourceCode.getLastTokens(AST, { count: 0 });
+sourceCode.getLastTokens(AST, t => t.type === 'Identifier');
+sourceCode.getLastTokens(AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getLastTokens(AST, { count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getLastTokens(AST, { includeComments: true });
+sourceCode.getLastTokens(AST, { includeComments: true, count: 0 });
+sourceCode.getLastTokens(AST, { includeComments: true, count: 0, filter: t => t.type === 'Identifier' });
+
+sourceCode.getTokenBefore(AST, 0);
+sourceCode.getTokenBefore(AST, { skip: 0 });
+sourceCode.getTokenBefore(AST, t => t.type === 'Identifier');
+sourceCode.getTokenBefore(AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getTokenBefore(AST, { skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getTokenBefore(AST, { includeComments: true });
+sourceCode.getTokenBefore(AST, { includeComments: true, skip: 0 });
+sourceCode.getTokenBefore(AST, { includeComments: true, skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getTokenBefore(TOKEN, 0);
+sourceCode.getTokenBefore(COMMENT, 0);
+
+sourceCode.getTokensBefore(AST, 0);
+sourceCode.getTokensBefore(AST, { count: 0 });
+sourceCode.getTokensBefore(AST, t => t.type === 'Identifier');
+sourceCode.getTokensBefore(AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getTokensBefore(AST, { count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getTokensBefore(AST, { includeComments: true });
+sourceCode.getTokensBefore(AST, { includeComments: true, count: 0 });
+sourceCode.getTokensBefore(AST, { includeComments: true, count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getTokensBefore(TOKEN, 0);
+sourceCode.getTokensBefore(COMMENT, 0);
+
+sourceCode.getTokenAfter(AST, 0);
+sourceCode.getTokenAfter(AST, { skip: 0 });
+sourceCode.getTokenAfter(AST, t => t.type === 'Identifier');
+sourceCode.getTokenAfter(AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getTokenAfter(AST, { skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getTokenAfter(AST, { includeComments: true });
+sourceCode.getTokenAfter(AST, { includeComments: true, skip: 0 });
+sourceCode.getTokenAfter(AST, { includeComments: true, skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getTokenAfter(TOKEN, 0);
+sourceCode.getTokenAfter(COMMENT, 0);
+
+sourceCode.getTokensAfter(AST, 0);
+sourceCode.getTokensAfter(AST, { count: 0 });
+sourceCode.getTokensAfter(AST, t => t.type === 'Identifier');
+sourceCode.getTokensAfter(AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getTokensAfter(AST, { count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getTokensAfter(AST, { includeComments: true });
+sourceCode.getTokensAfter(AST, { includeComments: true, count: 0 });
+sourceCode.getTokensAfter(AST, { includeComments: true, count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getTokensAfter(TOKEN, 0);
+sourceCode.getTokensAfter(COMMENT, 0);
+
+sourceCode.getFirstTokenBetween(AST, AST, 0);
+sourceCode.getFirstTokenBetween(AST, AST, { skip: 0 });
+sourceCode.getFirstTokenBetween(AST, AST, t => t.type === 'Identifier');
+sourceCode.getFirstTokenBetween(AST, AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getFirstTokenBetween(AST, AST, { skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getFirstTokenBetween(AST, AST, { includeComments: true });
+sourceCode.getFirstTokenBetween(AST, AST, { includeComments: true, skip: 0 });
+sourceCode.getFirstTokenBetween(AST, AST, { includeComments: true, skip: 0, filter: t => t.type === 'Identifier' });
+
+sourceCode.getFirstTokensBetween(AST, AST, 0);
+sourceCode.getFirstTokensBetween(AST, AST, { count: 0 });
+sourceCode.getFirstTokensBetween(AST, AST, t => t.type === 'Identifier');
+sourceCode.getFirstTokensBetween(AST, AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getFirstTokensBetween(AST, AST, { count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getFirstTokensBetween(AST, AST, { includeComments: true });
+sourceCode.getFirstTokensBetween(AST, AST, { includeComments: true, count: 0 });
+sourceCode.getFirstTokensBetween(AST, AST, { includeComments: true, count: 0, filter: t => t.type === 'Identifier' });
+
+sourceCode.getLastTokenBetween(AST, AST, 0);
+sourceCode.getLastTokenBetween(AST, AST, { skip: 0 });
+sourceCode.getLastTokenBetween(AST, AST, t => t.type === 'Identifier');
+sourceCode.getLastTokenBetween(AST, AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getLastTokenBetween(AST, AST, { skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getLastTokenBetween(AST, AST, { includeComments: true });
+sourceCode.getLastTokenBetween(AST, AST, { includeComments: true, skip: 0 });
+sourceCode.getLastTokenBetween(AST, AST, { includeComments: true, skip: 0, filter: t => t.type === 'Identifier' });
+
+sourceCode.getLastTokensBetween(AST, AST, 0);
+sourceCode.getLastTokensBetween(AST, AST, { count: 0 });
+sourceCode.getLastTokensBetween(AST, AST, t => t.type === 'Identifier');
+sourceCode.getLastTokensBetween(AST, AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getLastTokensBetween(AST, AST, { count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getLastTokensBetween(AST, AST, { includeComments: true });
+sourceCode.getLastTokensBetween(AST, AST, { includeComments: true, count: 0 });
+sourceCode.getLastTokensBetween(AST, AST, { includeComments: true, count: 0, filter: t => t.type === 'Identifier' });
+
+sourceCode.getTokensBetween(AST, AST, 0);
+
+sourceCode.getTokens(AST);
+sourceCode.getTokens(AST, 0);
+sourceCode.getTokens(AST, 0, 0);
+sourceCode.getTokens(AST, t => t.type === 'Identifier');
+sourceCode.getTokens(AST, { filter: t => t.type === 'Identifier' });
+sourceCode.getTokens(AST, { includeComments: true });
+sourceCode.getTokens(AST, { includeComments: true, filter: t => t.type === 'Identifier' });
+
+// TODO: Is it token or Node ?
+sourceCode.commentsExistBetween(AST, AST);
+
+sourceCode.getCommentsBefore(AST);
+sourceCode.getCommentsBefore(TOKEN);
+
+sourceCode.getCommentsAfter(AST);
+sourceCode.getCommentsAfter(TOKEN);
+
+// TODO: Should it support also token?
+sourceCode.getCommentsInside(AST);
+
+//#endregion
+
+//#region Linter
const linter = new Linter();
@@ -56,9 +245,9 @@ linter.getRules();
linter.getSourceCode();
-// =============================================
-// CLI
-// =============================================
+//#endregion
+
+//#region CLIEngine
const cli = new CLIEngine({
envs: ['browser', 'mocha'],
@@ -87,9 +276,9 @@ CLIEngine.getErrorResults(report.results);
CLIEngine.outputFixes(report);
-// =============================================
-// RuleTester
-// =============================================
+//#endregion
+
+//#region RuleTester
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
@@ -114,3 +303,5 @@ ruleTester.run("my-rule", {
}
]
});
+
+//#endregion
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 2ef75b2612..1a0ec2b8f4 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -9,7 +9,7 @@ import { JSONSchema4 } from 'json-schema';
import * as ESTree from 'estree';
export namespace AST {
- export type TokenType =
+ type TokenType =
| 'Boolean'
| 'Null'
| 'Identifier'
@@ -21,21 +21,21 @@ export namespace AST {
| 'String'
| 'RegularExpression';
- export interface Token {
+ interface Token {
type: TokenType;
value: string;
range: Range;
loc: SourceLocation;
}
- export interface SourceLocation {
+ interface SourceLocation {
start: ESTree.Position;
end: ESTree.Position;
}
- export type Range = [number, number];
+ type Range = [number, number];
- export interface Program extends ESTree.Program {
+ interface Program extends ESTree.Program {
comments: ESTree.Comment[];
tokens: Token[];
loc: SourceLocation;
@@ -125,7 +125,7 @@ export class SourceCode {
getLines(): string[];
- getAllComments(): ESTree.Node[];
+ getAllComments(): ESTree.Comment[];
getComments(node: ESTree.Node): { leading: ESTree.Comment[], trailing: ESTree.Comment[] };
@@ -137,7 +137,7 @@ export class SourceCode {
getLocFromIndex(index: number): ESTree.SourceLocation;
- getIndexFromLoc(location: ESTree.SourceLocation): number;
+ getIndexFromLoc(location: ESTree.Position): number;
// Inherited methods from TokenStore
// ---------------------------------
From f960c08627d257113c1755e45628c85cbeef87a3 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sat, 3 Feb 2018 08:59:40 -0800
Subject: [PATCH 15/23] Test for rules and fix
---
types/eslint/eslint-tests.ts | 151 +++++++++++++++++++++++++++++------
types/eslint/index.d.ts | 3 +-
2 files changed, 128 insertions(+), 26 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index 65bfcc294d..5f15b21039 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -1,5 +1,5 @@
import { Comment } from 'estree';
-import { SourceCode, Linter, CLIEngine, RuleTester, AST } from 'eslint';
+import { AST, SourceCode, Rule, Linter, CLIEngine, RuleTester } from 'eslint';
const SOURCE = `var foo = bar;`;
@@ -210,40 +210,143 @@ sourceCode.getCommentsInside(AST);
//#endregion
+//#region Rule
+
+let rule: Rule.RuleModule;
+
+rule = { create(context) { return {}; } };
+rule = { create(context) { return {}; }, meta: {} };
+rule = { create(context) { return {}; }, meta: {
+ docs: {
+ description: 'disallow the use of `console`',
+ category: 'Possible Errors',
+ recommended: true,
+ url: 'https://eslint.org/docs/rules/no-console',
+ }
+}};
+rule = { create(context) { return {}; }, meta: { fixable: 'whitespace' }};
+rule = { create(context) { return {}; }, meta: { fixable: 'code' }};
+rule = { create(context) { return {}; }, meta: { schema: [{ enum: ['always', 'never'] }] }};
+rule = { create(context) { return {}; }, meta: { deprecated: true }};
+
+rule = {
+ create(context) {
+ context.getAncestors();
+
+ context.getDeclaredVariables(AST);
+
+ context.getFilename();
+
+ context.getSourceCode();
+
+ // TODO: Add test for scope
+ context.getScope();
+
+ context.markVariableAsUsed('foo');
+
+ context.report({ message: 'foo', node: AST });
+ context.report({ message: 'foo', loc: { line: 0, column: 0 } });
+ context.report({ message: 'foo', node: AST, data: { foo: 'bar' } });
+ context.report({ message: 'foo', node: AST, fix: () => null });
+ context.report({ message: 'foo', node: AST, fix: ruleFixer => ruleFixer.replaceText(AST, 'foo') });
+
+ context.report({
+ message: 'foo',
+ node: AST,
+ fix: ruleFixer => {
+ ruleFixer.insertTextAfter(AST, 'foo');
+ ruleFixer.insertTextAfter(TOKEN, 'foo');
+
+ ruleFixer.insertTextAfterRange([0, 0], 'foo');
+
+ ruleFixer.insertTextBefore(AST, 'foo');
+ ruleFixer.insertTextBefore(TOKEN, 'foo');
+
+ ruleFixer.insertTextBeforeRange([0, 0], 'foo');
+
+ ruleFixer.remove(AST);
+ ruleFixer.remove(TOKEN);
+
+ ruleFixer.removeRange([0, 0]);
+
+ ruleFixer.replaceText(AST, 'foo');
+ ruleFixer.replaceText(TOKEN, 'foo');
+
+ ruleFixer.replaceTextRange([0, 0], 'foo');
+
+ return null;
+ }
+ });
+
+ return {
+ onCodePathStart(codePath, node) {},
+ onCodePathEnd(codePath, node) {},
+ onCodePathSegmentStart(segment, node) {},
+ onCodePathSegmentEnd(segment, node) {},
+ onCodePathSegmentLoop(fromSegment, toSegment, node) {},
+ 'Program:exit'() {},
+ };
+ },
+};
+
+//#endregion
+
//#region Linter
const linter = new Linter();
-linter.verify(SOURCE, {
- rules: {
- eqeqeq: 'off',
- 'no-console': 'error',
- quotes: ['error', 'double']
- },
-}, {
- filename: 'test.js',
-});
+linter.version;
-linter.verifyAndFix(SOURCE, {
- rules: {
- 'no-console': 'error',
- }
-}, {
- filename: 'test.js',
-});
+linter.verify(SOURCE, {});
+linter.verify(new SourceCode(SOURCE, AST), {});
-linter.defineRule('my-fancy-rule', {
- create() {},
+linter.verify(SOURCE, {}, 'test.js');
+linter.verify(SOURCE, {}, {});
+linter.verify(SOURCE, {}, { filename: 'test.js' });
+linter.verify(SOURCE, {}, { allowInlineConfig: false });
+linter.verify(SOURCE, {}, { reportUnusedDisableDirectives: true });
+linter.verify(SOURCE, {}, { preprocess: input => input.split(' ') });
+linter.verify(SOURCE, {}, { postprocess: problemList => problemList[0] });
+
+linter.verify(SOURCE, { parserOptions: { ecmaVersion: 6 } }, 'test.js');
+linter.verify(SOURCE, { parserOptions: { ecmaVersion: 6, ecmaFeatures: { globalReturn: true } } }, 'test.js');
+linter.verify(SOURCE, { parserOptions: { ecmaVersion: 6, ecmaFeatures: { experimentalObjectRestSpread: true } } }, 'test.js');
+linter.verify(SOURCE, { env: { node: true } }, 'test.js');
+linter.verify(SOURCE, { globals: { foo: true } }, 'test.js');
+linter.verify(SOURCE, { parser: 'custom-parser' }, 'test.js');
+linter.verify(SOURCE, { settings: { info: 'foo' } }, 'test.js');
+
+linter.verify(SOURCE, { rules: {} }, 'test.js');
+linter.verify(SOURCE, { rules: { quotes: 2 } }, 'test.js');
+linter.verify(SOURCE, { rules: { quotes: [2, 'double'] } }, 'test.js');
+linter.verify(SOURCE, { rules: { 'no-unused-vars': [2, { vars: "all" }] } }, 'test.js');
+linter.verify(SOURCE, { rules: { 'no-console': 1 } }, 'test.js');
+linter.verify(SOURCE, { rules: { 'no-console': 0 } }, 'test.js');
+linter.verify(SOURCE, { rules: { 'no-console': 'error' } }, 'test.js');
+linter.verify(SOURCE, { rules: { 'no-console': 'warn' } }, 'test.js');
+linter.verify(SOURCE, { rules: { 'no-console': 'off' } }, 'test.js');
+
+linter.verifyAndFix(SOURCE, {});
+linter.verifyAndFix(SOURCE, {}, 'test.js');
+linter.verifyAndFix(SOURCE, {}, { fix: false });
+
+linter.getSourceCode();
+
+// TODO: Fix me
+linter.defineRule('test', {
+ create() => {},
});
+// TODO: Fix me
linter.defineRules({
- 'my-fancy-rule': { create() {} },
- 'my-fancy-other-rule': { create() {} }
+ 'test': { create() => {} },
+ 'test-2': { create() => {} },
});
linter.getRules();
-linter.getSourceCode();
+// TODO: Fix me
+linter.defineParser('cutom-parser', );
//#endregion
@@ -282,9 +385,7 @@ CLIEngine.outputFixes(report);
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
-ruleTester.run("my-rule", {
- create() {},
-}, {
+ruleTester.run("my-rule", rule, {
valid: [
{
code: "var foo = true",
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 1a0ec2b8f4..26f2452fe2 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -236,7 +236,7 @@ export namespace SourceCode {
export namespace Rule {
interface RuleModule {
- create(context: RuleContext): any;
+ create(context: RuleContext): RuleListener;
meta?: RuleMetaData;
}
@@ -284,6 +284,7 @@ export namespace Rule {
recommended?: boolean;
url?: string;
};
+ //TODO: Find usage of message field
messages?: { [messageId: string]: string };
fixable?: 'code' | 'whitespace';
schema?: JSONSchema4 | JSONSchema4[];
From 317a828a2fd4fb2ea2072fb50f7dc161a36584d3 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sat, 3 Feb 2018 10:40:45 -0800
Subject: [PATCH 16/23] Close gaps in scope and linter tests
---
types/eslint/eslint-tests.ts | 103 +++++++++++++++++++++++++++++++----
types/eslint/index.d.ts | 2 +-
2 files changed, 92 insertions(+), 13 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index 5f15b21039..57a58d475e 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -1,5 +1,5 @@
import { Comment } from 'estree';
-import { AST, SourceCode, Rule, Linter, CLIEngine, RuleTester } from 'eslint';
+import { AST, SourceCode, Rule, Linter, CLIEngine, RuleTester, Scope } from 'eslint';
const SOURCE = `var foo = bar;`;
@@ -38,7 +38,7 @@ const COMMENT: Comment = {
//#region SourceCode
-const sourceCode = new SourceCode(SOURCE, AST);
+let sourceCode = new SourceCode(SOURCE, AST);
SourceCode.splitLines(SOURCE);
@@ -210,6 +210,48 @@ sourceCode.getCommentsInside(AST);
//#endregion
+//#region Scope
+
+const scopeManager: Scope.ScopeManager = {
+ scopes: [],
+ globalScope: null,
+ acquire(node, inner) {
+ return this.scopes[0];
+ },
+ getDeclaredVariables() {
+ return [];
+ }
+};
+
+const scope = scopeManager.scopes[0];
+
+const variable = scope.variables[0];
+
+variable.name = 'foo';
+
+variable.identifiers[0].type = 'Identifier';
+
+variable.defs[0].name.type = 'Identifier';
+variable.defs[0].type;
+variable.defs[0].node;
+variable.defs[0].parent;
+
+const reference = scope.references[0];
+
+reference.from = scope;
+reference.identifier.type = 'Identifier';
+reference.resolved = variable;
+reference.writeExpr = AST;
+reference.init = true;
+
+reference.isRead();
+reference.isReadOnly();
+reference.isWrite();
+reference.isWriteOnly();
+reference.isReadWrite();
+
+//#endregion
+
//#region Rule
let rule: Rule.RuleModule;
@@ -326,27 +368,64 @@ linter.verify(SOURCE, { rules: { 'no-console': 'error' } }, 'test.js');
linter.verify(SOURCE, { rules: { 'no-console': 'warn' } }, 'test.js');
linter.verify(SOURCE, { rules: { 'no-console': 'off' } }, 'test.js');
+const lintingResult = linter.verify(SOURCE, {});
+
+for (const msg of lintingResult) {
+ msg.severity = 1;
+ msg.severity = 2;
+
+ msg.ruleId = 'foo';
+
+ msg.fatal = true;
+
+ msg.line = 0;
+ msg.endLine = 0;
+ msg.column = 0;
+ msg.endColumn = 0;
+
+ msg.source = SOURCE;
+
+ if (msg.fix) {
+ msg.fix.text = 'foo';
+ msg.fix.range = [0, 0];
+ }
+}
+
linter.verifyAndFix(SOURCE, {});
linter.verifyAndFix(SOURCE, {}, 'test.js');
linter.verifyAndFix(SOURCE, {}, { fix: false });
-linter.getSourceCode();
+const fixResult = linter.verifyAndFix(SOURCE, {});
-// TODO: Fix me
-linter.defineRule('test', {
- create() => {},
-});
+fixResult.fixed = true;
+fixResult.output = 'foo';
+
+for (const msg of fixResult.messages) {
+ msg.ruleId = 'foo';
+}
+
+sourceCode = linter.getSourceCode();
+
+linter.defineRule('test', rule);
-// TODO: Fix me
linter.defineRules({
- 'test': { create() => {} },
- 'test-2': { create() => {} },
+ foo: rule,
+ bar: rule,
});
linter.getRules();
-// TODO: Fix me
-linter.defineParser('cutom-parser', );
+linter.defineParser('custom-parser', { parse: (src, opts) => AST });
+linter.defineParser('custom-parser', {
+ parseForESLint(src, opts) {
+ return {
+ ast: AST,
+ visitorKeys: {},
+ parserServices: {},
+ scopeManager,
+ };
+ }
+});
//#endregion
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 26f2452fe2..4ba910329c 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -69,7 +69,7 @@ export namespace Scope {
interface Variable {
name: string;
- identifiers: ESTree.Identifier;
+ identifiers: ESTree.Identifier[];
references: Reference[];
defs: Definition[];
}
From 164beef44424ec8561966d584ecd2c7e2a3a2865 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sat, 3 Feb 2018 10:42:48 -0800
Subject: [PATCH 17/23] Fix linting errors
---
types/eslint/eslint-tests.ts | 2 +-
types/eslint/index.d.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index 57a58d475e..a7aa0e3ba6 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -216,7 +216,7 @@ const scopeManager: Scope.ScopeManager = {
scopes: [],
globalScope: null,
acquire(node, inner) {
- return this.scopes[0];
+ return scopeManager.scopes[0];
},
getDeclaredVariables() {
return [];
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 4ba910329c..84503a2b40 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -284,7 +284,7 @@ export namespace Rule {
recommended?: boolean;
url?: string;
};
- //TODO: Find usage of message field
+ // TODO: Find usage of message field
messages?: { [messageId: string]: string };
fixable?: 'code' | 'whitespace';
schema?: JSONSchema4 | JSONSchema4[];
From 70945527bcadbbb5458eabc86bc9ae1b85b9b2fc Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sat, 3 Feb 2018 11:59:34 -0800
Subject: [PATCH 18/23] Add tests for RuleTester
---
types/eslint/eslint-tests.ts | 89 +++++++++++++++++++++++++-----------
1 file changed, 63 insertions(+), 26 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index a7aa0e3ba6..6b4b19e463 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -361,7 +361,7 @@ linter.verify(SOURCE, { settings: { info: 'foo' } }, 'test.js');
linter.verify(SOURCE, { rules: {} }, 'test.js');
linter.verify(SOURCE, { rules: { quotes: 2 } }, 'test.js');
linter.verify(SOURCE, { rules: { quotes: [2, 'double'] } }, 'test.js');
-linter.verify(SOURCE, { rules: { 'no-unused-vars': [2, { vars: "all" }] } }, 'test.js');
+linter.verify(SOURCE, { rules: { 'no-unused-vars': [2, { vars: 'all' }] } }, 'test.js');
linter.verify(SOURCE, { rules: { 'no-console': 1 } }, 'test.js');
linter.verify(SOURCE, { rules: { 'no-console': 0 } }, 'test.js');
linter.verify(SOURCE, { rules: { 'no-console': 'error' } }, 'test.js');
@@ -431,17 +431,31 @@ linter.defineParser('custom-parser', {
//#region CLIEngine
-const cli = new CLIEngine({
- envs: ['browser', 'mocha'],
- useEslintrc: false,
- rules: {
- semi: 2
- }
-});
+let cli: CLIEngine;
-cli.executeOnFiles(['myfile.js', 'lib/']);
+cli = new CLIEngine({ allowInlineConfig: false });
+cli = new CLIEngine({ baseConfig: false });
+cli = new CLIEngine({ cache: true });
+cli = new CLIEngine({ cacheFile: 'foo' });
+cli = new CLIEngine({ configFile: 'foo' });
+cli = new CLIEngine({ cwd: 'foo' });
+cli = new CLIEngine({ envs: ['browser'] });
+cli = new CLIEngine({ extensions: ['js'] });
+cli = new CLIEngine({ fix: true });
+cli = new CLIEngine({ globals: ['foo'] });
+cli = new CLIEngine({ ignore: true });
+cli = new CLIEngine({ ignorePath: 'foo' });
+cli = new CLIEngine({ ignorePattern: 'foo' });
+cli = new CLIEngine({ useEslintrc: false });
+cli = new CLIEngine({ parserOptions: {} });
+cli = new CLIEngine({ plugins: ['foo'] });
+cli = new CLIEngine({ rules: { 'test/example-rule': 1 } });
+cli = new CLIEngine({ rulePaths: ['foo'] });
+cli = new CLIEngine({ reportUnusedDisableDirectives: true });
-const report = cli.executeOnText(SOURCE, 'foo');
+let cliReport = cli.executeOnFiles(['myfile.js', 'lib/']);
+
+cliReport = cli.executeOnText(SOURCE, 'foo');
cli.resolveFileGlobPatterns(['**/*']);
@@ -452,11 +466,33 @@ cli.addPlugin('my-fancy-plugin', {});
cli.isPathIgnored('./dist/index.js');
const formatter = cli.getFormatter('codeframe');
-formatter(report.results);
-CLIEngine.getErrorResults(report.results);
+formatter(cliReport.results);
-CLIEngine.outputFixes(report);
+CLIEngine.getErrorResults(cliReport.results);
+
+CLIEngine.outputFixes(cliReport);
+
+cliReport.errorCount = 0;
+cliReport.warningCount = 0;
+cliReport.fixableErrorCount = 0;
+cliReport.fixableWarningCount = 0;
+
+for (const file of cliReport.results) {
+ file.filePath = 'foo.js';
+
+ file.errorCount = 0;
+ file.warningCount = 0;
+ file.fixableErrorCount = 0;
+ file.fixableWarningCount = 0;
+
+ file.source = 'foo';
+ file.output = 'foo';
+
+ for (const message of file.messages) {
+ message.ruleId = 'foo';
+ }
+}
//#endregion
@@ -464,23 +500,24 @@ CLIEngine.outputFixes(report);
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
-ruleTester.run("my-rule", rule, {
+ruleTester.run('my-rule', rule, {
valid: [
- {
- code: "var foo = true",
- options: [{ allowFoo: true }]
- }
+ { code: 'foo' },
+ { code: 'foo', options: [{ allowFoo: true }] },
+ { code: 'foo', filename: 'test.js' },
+ { code: 'foo', parserOptions: {} },
+ { code: 'foo', settings: { foo: true } },
+ { code: 'foo', parser: 'foo' },
+ { code: 'foo', globals: { foo: true } },
],
invalid: [
- {
- code: "var invalidVariable = true",
- errors: [{ message: "Unexpected invalid variable." }]
- },
- {
- code: "var invalidVariable = true",
- errors: [{ message: /^Unexpected.+variable/ }]
- }
+ { code: 'foo', errors: 1 },
+ { code: 'foo', errors: ['foo'] },
+ { code: 'foo', errors: [{ message: 'foo' }] },
+ { code: 'foo', errors: [{ message: 'foo', type: 'foo' }] },
+ { code: 'foo', errors: [{ message: 'foo', data: { foo: true } }] },
+ { code: 'foo', errors: [{ message: 'foo', line: 0 }] },
]
});
From 25d95f9e69d120ae213a09d0784c1a5426b8a271 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sat, 3 Feb 2018 12:08:36 -0800
Subject: [PATCH 19/23] Resolve trailing TODOs
---
types/eslint/eslint-tests.ts | 17 +++++++++++++----
types/eslint/index.d.ts | 27 +++++++++++++--------------
2 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index 6b4b19e463..624d438ea7 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -69,7 +69,7 @@ sourceCode.getIndexFromLoc({ line: 0, column: 0 });
sourceCode.getTokenByRangeStart(0);
sourceCode.getTokenByRangeStart(0, { includeComments: true });
-// TODO: Should accept no second parameter?
+sourceCode.getFirstToken(AST);
sourceCode.getFirstToken(AST, 0);
sourceCode.getFirstToken(AST, { skip: 0 });
sourceCode.getFirstToken(AST, t => t.type === 'Identifier');
@@ -79,6 +79,7 @@ sourceCode.getFirstToken(AST, { includeComments: true });
sourceCode.getFirstToken(AST, { includeComments: true, skip: 0 });
sourceCode.getFirstToken(AST, { includeComments: true, skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getFirstTokens(AST);
sourceCode.getFirstTokens(AST, 0);
sourceCode.getFirstTokens(AST, { count: 0 });
sourceCode.getFirstTokens(AST, t => t.type === 'Identifier');
@@ -88,6 +89,7 @@ sourceCode.getFirstTokens(AST, { includeComments: true });
sourceCode.getFirstTokens(AST, { includeComments: true, count: 0 });
sourceCode.getFirstTokens(AST, { includeComments: true, count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getLastToken(AST);
sourceCode.getLastToken(AST, 0);
sourceCode.getLastToken(AST, { skip: 0 });
sourceCode.getLastToken(AST, t => t.type === 'Identifier');
@@ -97,6 +99,7 @@ sourceCode.getLastToken(AST, { includeComments: true });
sourceCode.getLastToken(AST, { includeComments: true, skip: 0 });
sourceCode.getLastToken(AST, { includeComments: true, skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getLastTokens(AST);
sourceCode.getLastTokens(AST, 0);
sourceCode.getLastTokens(AST, { count: 0 });
sourceCode.getLastTokens(AST, t => t.type === 'Identifier');
@@ -106,6 +109,7 @@ sourceCode.getLastTokens(AST, { includeComments: true });
sourceCode.getLastTokens(AST, { includeComments: true, count: 0 });
sourceCode.getLastTokens(AST, { includeComments: true, count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getTokenBefore(AST);
sourceCode.getTokenBefore(AST, 0);
sourceCode.getTokenBefore(AST, { skip: 0 });
sourceCode.getTokenBefore(AST, t => t.type === 'Identifier');
@@ -117,6 +121,7 @@ sourceCode.getTokenBefore(AST, { includeComments: true, skip: 0, filter: t => t.
sourceCode.getTokenBefore(TOKEN, 0);
sourceCode.getTokenBefore(COMMENT, 0);
+sourceCode.getTokensBefore(AST);
sourceCode.getTokensBefore(AST, 0);
sourceCode.getTokensBefore(AST, { count: 0 });
sourceCode.getTokensBefore(AST, t => t.type === 'Identifier');
@@ -128,6 +133,7 @@ sourceCode.getTokensBefore(AST, { includeComments: true, count: 0, filter: t =>
sourceCode.getTokensBefore(TOKEN, 0);
sourceCode.getTokensBefore(COMMENT, 0);
+sourceCode.getTokenAfter(AST);
sourceCode.getTokenAfter(AST, 0);
sourceCode.getTokenAfter(AST, { skip: 0 });
sourceCode.getTokenAfter(AST, t => t.type === 'Identifier');
@@ -139,6 +145,7 @@ sourceCode.getTokenAfter(AST, { includeComments: true, skip: 0, filter: t => t.t
sourceCode.getTokenAfter(TOKEN, 0);
sourceCode.getTokenAfter(COMMENT, 0);
+sourceCode.getTokensAfter(AST);
sourceCode.getTokensAfter(AST, 0);
sourceCode.getTokensAfter(AST, { count: 0 });
sourceCode.getTokensAfter(AST, t => t.type === 'Identifier');
@@ -150,6 +157,7 @@ sourceCode.getTokensAfter(AST, { includeComments: true, count: 0, filter: t => t
sourceCode.getTokensAfter(TOKEN, 0);
sourceCode.getTokensAfter(COMMENT, 0);
+sourceCode.getFirstTokenBetween(AST, AST);
sourceCode.getFirstTokenBetween(AST, AST, 0);
sourceCode.getFirstTokenBetween(AST, AST, { skip: 0 });
sourceCode.getFirstTokenBetween(AST, AST, t => t.type === 'Identifier');
@@ -159,6 +167,7 @@ sourceCode.getFirstTokenBetween(AST, AST, { includeComments: true });
sourceCode.getFirstTokenBetween(AST, AST, { includeComments: true, skip: 0 });
sourceCode.getFirstTokenBetween(AST, AST, { includeComments: true, skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getFirstTokensBetween(AST, AST);
sourceCode.getFirstTokensBetween(AST, AST, 0);
sourceCode.getFirstTokensBetween(AST, AST, { count: 0 });
sourceCode.getFirstTokensBetween(AST, AST, t => t.type === 'Identifier');
@@ -168,6 +177,7 @@ sourceCode.getFirstTokensBetween(AST, AST, { includeComments: true });
sourceCode.getFirstTokensBetween(AST, AST, { includeComments: true, count: 0 });
sourceCode.getFirstTokensBetween(AST, AST, { includeComments: true, count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getLastTokenBetween(AST, AST);
sourceCode.getLastTokenBetween(AST, AST, 0);
sourceCode.getLastTokenBetween(AST, AST, { skip: 0 });
sourceCode.getLastTokenBetween(AST, AST, t => t.type === 'Identifier');
@@ -177,6 +187,7 @@ sourceCode.getLastTokenBetween(AST, AST, { includeComments: true });
sourceCode.getLastTokenBetween(AST, AST, { includeComments: true, skip: 0 });
sourceCode.getLastTokenBetween(AST, AST, { includeComments: true, skip: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getLastTokensBetween(AST, AST);
sourceCode.getLastTokensBetween(AST, AST, 0);
sourceCode.getLastTokensBetween(AST, AST, { count: 0 });
sourceCode.getLastTokensBetween(AST, AST, t => t.type === 'Identifier');
@@ -186,6 +197,7 @@ sourceCode.getLastTokensBetween(AST, AST, { includeComments: true });
sourceCode.getLastTokensBetween(AST, AST, { includeComments: true, count: 0 });
sourceCode.getLastTokensBetween(AST, AST, { includeComments: true, count: 0, filter: t => t.type === 'Identifier' });
+sourceCode.getTokensBetween(AST, AST);
sourceCode.getTokensBetween(AST, AST, 0);
sourceCode.getTokens(AST);
@@ -196,7 +208,6 @@ sourceCode.getTokens(AST, { filter: t => t.type === 'Identifier' });
sourceCode.getTokens(AST, { includeComments: true });
sourceCode.getTokens(AST, { includeComments: true, filter: t => t.type === 'Identifier' });
-// TODO: Is it token or Node ?
sourceCode.commentsExistBetween(AST, AST);
sourceCode.getCommentsBefore(AST);
@@ -205,7 +216,6 @@ sourceCode.getCommentsBefore(TOKEN);
sourceCode.getCommentsAfter(AST);
sourceCode.getCommentsAfter(TOKEN);
-// TODO: Should it support also token?
sourceCode.getCommentsInside(AST);
//#endregion
@@ -281,7 +291,6 @@ rule = {
context.getSourceCode();
- // TODO: Add test for scope
context.getScope();
context.markVariableAsUsed('foo');
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 84503a2b40..abe7b7ce90 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -144,50 +144,50 @@ export class SourceCode {
getTokenByRangeStart(offset: number, options?: { includeComments?: boolean }): AST.Token | null;
- getFirstToken(node: ESTree.Node, options: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getFirstToken(node: ESTree.Node, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getFirstTokens(node: ESTree.Node, options: SourceCode.CursorWithCountOptions): AST.Token[];
+ getFirstTokens(node: ESTree.Node, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getLastToken(node: ESTree.Node, options: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getLastToken(node: ESTree.Node, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getLastTokens(node: ESTree.Node, options: SourceCode.CursorWithCountOptions): AST.Token[];
+ getLastTokens(node: ESTree.Node, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getTokenBefore(node: ESTree.Node | AST.Token | ESTree.Comment, options: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getTokenBefore(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getTokensBefore(node: ESTree.Node | AST.Token | ESTree.Comment, options: SourceCode.CursorWithCountOptions): AST.Token[];
+ getTokensBefore(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getTokenAfter(node: ESTree.Node | AST.Token | ESTree.Comment, options: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getTokenAfter(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getTokensAfter(node: ESTree.Node | AST.Token | ESTree.Comment, options: SourceCode.CursorWithCountOptions): AST.Token[];
+ getTokensAfter(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithCountOptions): AST.Token[];
getFirstTokenBetween(
left: ESTree.Node | AST.Token | ESTree.Comment,
right: ESTree.Node | AST.Token | ESTree.Comment,
- options: SourceCode.CursorWithSkipOptions
+ options?: SourceCode.CursorWithSkipOptions
): AST.Token | null;
getFirstTokensBetween(
left: ESTree.Node | AST.Token | ESTree.Comment,
right: ESTree.Node | AST.Token | ESTree.Comment,
- options: SourceCode.CursorWithCountOptions
+ options?: SourceCode.CursorWithCountOptions
): AST.Token[];
getLastTokenBetween(
left: ESTree.Node | AST.Token | ESTree.Comment,
right: ESTree.Node | AST.Token | ESTree.Comment,
- options: SourceCode.CursorWithSkipOptions
+ options?: SourceCode.CursorWithSkipOptions
): AST.Token | null;
getLastTokensBetween(
left: ESTree.Node | AST.Token | ESTree.Comment,
right: ESTree.Node | AST.Token | ESTree.Comment,
- options: SourceCode.CursorWithCountOptions
+ options?: SourceCode.CursorWithCountOptions
): AST.Token[];
getTokensBetween(
left: ESTree.Node | AST.Token | ESTree.Comment,
right: ESTree.Node | AST.Token | ESTree.Comment,
- padding: number | SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions
+ padding?: number | SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions
): AST.Token[];
getTokens(node: ESTree.Node, beforeCount?: number, afterCount?: number): AST.Token[];
@@ -284,7 +284,6 @@ export namespace Rule {
recommended?: boolean;
url?: string;
};
- // TODO: Find usage of message field
messages?: { [messageId: string]: string };
fixable?: 'code' | 'whitespace';
schema?: JSONSchema4 | JSONSchema4[];
From f2ce6a9bb436ba43b6f352fa20a07422972bc5a1 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sun, 4 Feb 2018 08:01:41 -0800
Subject: [PATCH 20/23] Fix commentsExistBetween signature and make parse
return Program
---
types/eslint/eslint-tests.ts | 1 +
types/eslint/index.d.ts | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index 624d438ea7..376cdf0a92 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -209,6 +209,7 @@ sourceCode.getTokens(AST, { includeComments: true });
sourceCode.getTokens(AST, { includeComments: true, filter: t => t.type === 'Identifier' });
sourceCode.commentsExistBetween(AST, AST);
+sourceCode.commentsExistBetween(TOKEN, TOKEN);
sourceCode.getCommentsBefore(AST);
sourceCode.getCommentsBefore(TOKEN);
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index abe7b7ce90..9e0e68af0b 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -193,7 +193,7 @@ export class SourceCode {
getTokens(node: ESTree.Node, beforeCount?: number, afterCount?: number): AST.Token[];
getTokens(node: ESTree.Node, options: SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions): AST.Token[];
- commentsExistBetween(left: ESTree.Node, right: ESTree.Node): boolean;
+ commentsExistBetween(left: ESTree.Node | AST.Token, right: ESTree.Node | AST.Token): boolean;
getCommentsBefore(nodeOrToken: ESTree.Node | AST.Token): ESTree.Comment[];
@@ -433,7 +433,7 @@ export namespace Linter {
}
type ParserModule = {
- parse(text: string, options?: any): ESTree.Node;
+ parse(text: string, options?: any): AST.Program;
} | {
parseForESLint(text: string, options?: any): ESLintParseResult;
};
From c84b2631309e1421913fc24666e6a32758b36d19 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Mon, 5 Feb 2018 06:46:30 -0800
Subject: [PATCH 21/23] Add Ranged interface
---
types/eslint/eslint-tests.ts | 3 +-
types/eslint/index.d.ts | 66 +++++++++++++++---------------------
2 files changed, 28 insertions(+), 41 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index 376cdf0a92..425f14580b 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -1,4 +1,3 @@
-import { Comment } from 'estree';
import { AST, SourceCode, Rule, Linter, CLIEngine, RuleTester, Scope } from 'eslint';
const SOURCE = `var foo = bar;`;
@@ -26,7 +25,7 @@ const TOKEN: AST.Token = {
range: [0, 3]
};
-const COMMENT: Comment = {
+const COMMENT: AST.Comment = {
type: 'Block',
value: 'foo',
loc: {
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 9e0e68af0b..81f3c875c8 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -35,12 +35,20 @@ export namespace AST {
type Range = [number, number];
+ interface Ranged {
+ range: Range;
+ }
+
interface Program extends ESTree.Program {
comments: ESTree.Comment[];
tokens: Token[];
loc: SourceLocation;
range: Range;
}
+
+ interface Comment extends ESTree.Comment {
+ range: Range;
+ }
}
export namespace Scope {
@@ -144,62 +152,42 @@ export class SourceCode {
getTokenByRangeStart(offset: number, options?: { includeComments?: boolean }): AST.Token | null;
- getFirstToken(node: ESTree.Node, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getFirstToken(node: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getFirstTokens(node: ESTree.Node, options?: SourceCode.CursorWithCountOptions): AST.Token[];
+ getFirstTokens(node: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getLastToken(node: ESTree.Node, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getLastToken(node: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getLastTokens(node: ESTree.Node, options?: SourceCode.CursorWithCountOptions): AST.Token[];
+ getLastTokens(node: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getTokenBefore(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getTokenBefore(node: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getTokensBefore(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithCountOptions): AST.Token[];
+ getTokensBefore(node: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getTokenAfter(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getTokenAfter(node: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getTokensAfter(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithCountOptions): AST.Token[];
+ getTokensAfter(node: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getFirstTokenBetween(
- left: ESTree.Node | AST.Token | ESTree.Comment,
- right: ESTree.Node | AST.Token | ESTree.Comment,
- options?: SourceCode.CursorWithSkipOptions
- ): AST.Token | null;
+ getFirstTokenBetween(left: AST.Ranged, right: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getFirstTokensBetween(
- left: ESTree.Node | AST.Token | ESTree.Comment,
- right: ESTree.Node | AST.Token | ESTree.Comment,
- options?: SourceCode.CursorWithCountOptions
- ): AST.Token[];
+ getFirstTokensBetween(left: AST.Ranged, right: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getLastTokenBetween(
- left: ESTree.Node | AST.Token | ESTree.Comment,
- right: ESTree.Node | AST.Token | ESTree.Comment,
- options?: SourceCode.CursorWithSkipOptions
- ): AST.Token | null;
+ getLastTokenBetween(left: AST.Ranged, right: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getLastTokensBetween(
- left: ESTree.Node | AST.Token | ESTree.Comment,
- right: ESTree.Node | AST.Token | ESTree.Comment,
- options?: SourceCode.CursorWithCountOptions
- ): AST.Token[];
+ getLastTokensBetween(left: AST.Ranged, right: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getTokensBetween(
- left: ESTree.Node | AST.Token | ESTree.Comment,
- right: ESTree.Node | AST.Token | ESTree.Comment,
- padding?: number | SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions
- ): AST.Token[];
+ getTokensBetween(left: AST.Ranged, right: AST.Ranged, padding?: number | SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions): AST.Token[];
- getTokens(node: ESTree.Node, beforeCount?: number, afterCount?: number): AST.Token[];
- getTokens(node: ESTree.Node, options: SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions): AST.Token[];
+ getTokens(node: AST.Ranged, beforeCount?: number, afterCount?: number): AST.Token[];
+ getTokens(node: AST.Ranged, options: SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions): AST.Token[];
- commentsExistBetween(left: ESTree.Node | AST.Token, right: ESTree.Node | AST.Token): boolean;
+ commentsExistBetween(left: AST.Ranged, right: AST.Ranged): boolean;
- getCommentsBefore(nodeOrToken: ESTree.Node | AST.Token): ESTree.Comment[];
+ getCommentsBefore(nodeOrToken: AST.Ranged): ESTree.Comment[];
- getCommentsAfter(nodeOrToken: ESTree.Node | AST.Token): ESTree.Comment[];
+ getCommentsAfter(nodeOrToken: AST.Ranged): ESTree.Comment[];
- getCommentsInside(node: ESTree.Node): ESTree.Comment[];
+ getCommentsInside(node: AST.Ranged): ESTree.Comment[];
}
export namespace SourceCode {
From fb4adda46f35dac66760505c209f10d4308ab255 Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sat, 10 Feb 2018 09:46:07 -0800
Subject: [PATCH 22/23] Revert "Add Ranged interface"
This reverts commit c84b2631309e1421913fc24666e6a32758b36d19.
---
types/eslint/eslint-tests.ts | 3 +-
types/eslint/index.d.ts | 66 +++++++++++++++++++++---------------
2 files changed, 41 insertions(+), 28 deletions(-)
diff --git a/types/eslint/eslint-tests.ts b/types/eslint/eslint-tests.ts
index 425f14580b..376cdf0a92 100644
--- a/types/eslint/eslint-tests.ts
+++ b/types/eslint/eslint-tests.ts
@@ -1,3 +1,4 @@
+import { Comment } from 'estree';
import { AST, SourceCode, Rule, Linter, CLIEngine, RuleTester, Scope } from 'eslint';
const SOURCE = `var foo = bar;`;
@@ -25,7 +26,7 @@ const TOKEN: AST.Token = {
range: [0, 3]
};
-const COMMENT: AST.Comment = {
+const COMMENT: Comment = {
type: 'Block',
value: 'foo',
loc: {
diff --git a/types/eslint/index.d.ts b/types/eslint/index.d.ts
index 81f3c875c8..9e0e68af0b 100644
--- a/types/eslint/index.d.ts
+++ b/types/eslint/index.d.ts
@@ -35,20 +35,12 @@ export namespace AST {
type Range = [number, number];
- interface Ranged {
- range: Range;
- }
-
interface Program extends ESTree.Program {
comments: ESTree.Comment[];
tokens: Token[];
loc: SourceLocation;
range: Range;
}
-
- interface Comment extends ESTree.Comment {
- range: Range;
- }
}
export namespace Scope {
@@ -152,42 +144,62 @@ export class SourceCode {
getTokenByRangeStart(offset: number, options?: { includeComments?: boolean }): AST.Token | null;
- getFirstToken(node: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getFirstToken(node: ESTree.Node, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getFirstTokens(node: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
+ getFirstTokens(node: ESTree.Node, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getLastToken(node: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getLastToken(node: ESTree.Node, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getLastTokens(node: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
+ getLastTokens(node: ESTree.Node, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getTokenBefore(node: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getTokenBefore(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getTokensBefore(node: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
+ getTokensBefore(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getTokenAfter(node: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getTokenAfter(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
- getTokensAfter(node: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
+ getTokensAfter(node: ESTree.Node | AST.Token | ESTree.Comment, options?: SourceCode.CursorWithCountOptions): AST.Token[];
- getFirstTokenBetween(left: AST.Ranged, right: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getFirstTokenBetween(
+ left: ESTree.Node | AST.Token | ESTree.Comment,
+ right: ESTree.Node | AST.Token | ESTree.Comment,
+ options?: SourceCode.CursorWithSkipOptions
+ ): AST.Token | null;
- getFirstTokensBetween(left: AST.Ranged, right: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
+ getFirstTokensBetween(
+ left: ESTree.Node | AST.Token | ESTree.Comment,
+ right: ESTree.Node | AST.Token | ESTree.Comment,
+ options?: SourceCode.CursorWithCountOptions
+ ): AST.Token[];
- getLastTokenBetween(left: AST.Ranged, right: AST.Ranged, options?: SourceCode.CursorWithSkipOptions): AST.Token | null;
+ getLastTokenBetween(
+ left: ESTree.Node | AST.Token | ESTree.Comment,
+ right: ESTree.Node | AST.Token | ESTree.Comment,
+ options?: SourceCode.CursorWithSkipOptions
+ ): AST.Token | null;
- getLastTokensBetween(left: AST.Ranged, right: AST.Ranged, options?: SourceCode.CursorWithCountOptions): AST.Token[];
+ getLastTokensBetween(
+ left: ESTree.Node | AST.Token | ESTree.Comment,
+ right: ESTree.Node | AST.Token | ESTree.Comment,
+ options?: SourceCode.CursorWithCountOptions
+ ): AST.Token[];
- getTokensBetween(left: AST.Ranged, right: AST.Ranged, padding?: number | SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions): AST.Token[];
+ getTokensBetween(
+ left: ESTree.Node | AST.Token | ESTree.Comment,
+ right: ESTree.Node | AST.Token | ESTree.Comment,
+ padding?: number | SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions
+ ): AST.Token[];
- getTokens(node: AST.Ranged, beforeCount?: number, afterCount?: number): AST.Token[];
- getTokens(node: AST.Ranged, options: SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions): AST.Token[];
+ getTokens(node: ESTree.Node, beforeCount?: number, afterCount?: number): AST.Token[];
+ getTokens(node: ESTree.Node, options: SourceCode.FilterPredicate | SourceCode.CursorWithCountOptions): AST.Token[];
- commentsExistBetween(left: AST.Ranged, right: AST.Ranged): boolean;
+ commentsExistBetween(left: ESTree.Node | AST.Token, right: ESTree.Node | AST.Token): boolean;
- getCommentsBefore(nodeOrToken: AST.Ranged): ESTree.Comment[];
+ getCommentsBefore(nodeOrToken: ESTree.Node | AST.Token): ESTree.Comment[];
- getCommentsAfter(nodeOrToken: AST.Ranged): ESTree.Comment[];
+ getCommentsAfter(nodeOrToken: ESTree.Node | AST.Token): ESTree.Comment[];
- getCommentsInside(node: AST.Ranged): ESTree.Comment[];
+ getCommentsInside(node: ESTree.Node): ESTree.Comment[];
}
export namespace SourceCode {
From 7ed9c988abf562c033e62a29dc8cbce84da4132f Mon Sep 17 00:00:00 2001
From: Pierre-Marie
Date: Sat, 10 Feb 2018 10:10:53 -0800
Subject: [PATCH 23/23] Set esModuleInterop to true to fix new test
requirements
---
types/eslint/tsconfig.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/types/eslint/tsconfig.json b/types/eslint/tsconfig.json
index 2e820d4971..4f53b4a06b 100644
--- a/types/eslint/tsconfig.json
+++ b/types/eslint/tsconfig.json
@@ -14,7 +14,8 @@
],
"types": [],
"noEmit": true,
- "forceConsistentCasingInFileNames": true
+ "forceConsistentCasingInFileNames": true,
+ "esModuleInterop": true
},
"files": [
"index.d.ts",