diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5e89159a5e78..f800e619f2dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,25 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.1...v2.7.0) (2019-11-11)
+
+
+### Bug Fixes
+
+* **eslint-plugin:** crash fixing readonly arrays to generic ([#1172](https://github.com/typescript-eslint/typescript-eslint/issues/1172)) ([2b2f2d7](https://github.com/typescript-eslint/typescript-eslint/commit/2b2f2d7))
+* **typescript-estree:** hash code to reduce update frequency ([#1179](https://github.com/typescript-eslint/typescript-eslint/issues/1179)) ([96d1cc3](https://github.com/typescript-eslint/typescript-eslint/commit/96d1cc3))
+* **typescript-estree:** reduce bundle footprint of tsutils ([#1177](https://github.com/typescript-eslint/typescript-eslint/issues/1177)) ([c8fe515](https://github.com/typescript-eslint/typescript-eslint/commit/c8fe515))
+
+
+### Features
+
+* **eslint-plugin:** [no-unused-expressions] extend for optional chaining ([#1175](https://github.com/typescript-eslint/typescript-eslint/issues/1175)) ([57d63b7](https://github.com/typescript-eslint/typescript-eslint/commit/57d63b7))
+* **parser:** handle optional chaining in scope analysis ([#1169](https://github.com/typescript-eslint/typescript-eslint/issues/1169)) ([026ceb9](https://github.com/typescript-eslint/typescript-eslint/commit/026ceb9))
+
+
+
+
+
## [2.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.0...v2.6.1) (2019-11-04)
diff --git a/lerna.json b/lerna.json
index f467fc228a1e..991899f51336 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,5 +1,5 @@
{
- "version": "2.6.1",
+ "version": "2.7.0",
"npmClient": "yarn",
"useWorkspaces": true,
"stream": true
diff --git a/packages/eslint-plugin-tslint/CHANGELOG.md b/packages/eslint-plugin-tslint/CHANGELOG.md
index bfbc5e387413..9613287c0606 100644
--- a/packages/eslint-plugin-tslint/CHANGELOG.md
+++ b/packages/eslint-plugin-tslint/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.1...v2.7.0) (2019-11-11)
+
+**Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint
+
+
+
+
+
## [2.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.0...v2.6.1) (2019-11-04)
**Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint
diff --git a/packages/eslint-plugin-tslint/package.json b/packages/eslint-plugin-tslint/package.json
index c0432f50ed1b..b23071880ad8 100644
--- a/packages/eslint-plugin-tslint/package.json
+++ b/packages/eslint-plugin-tslint/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/eslint-plugin-tslint",
- "version": "2.6.1",
+ "version": "2.7.0",
"main": "dist/index.js",
"typings": "src/index.ts",
"description": "TSLint wrapper plugin for ESLint",
@@ -31,7 +31,7 @@
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"dependencies": {
- "@typescript-eslint/experimental-utils": "2.6.1",
+ "@typescript-eslint/experimental-utils": "2.7.0",
"lodash.memoize": "^4.1.2"
},
"peerDependencies": {
@@ -41,6 +41,6 @@
},
"devDependencies": {
"@types/lodash.memoize": "^4.1.4",
- "@typescript-eslint/parser": "2.6.1"
+ "@typescript-eslint/parser": "2.7.0"
}
}
diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md
index bf30ed088fc7..1759b88a3c13 100644
--- a/packages/eslint-plugin/CHANGELOG.md
+++ b/packages/eslint-plugin/CHANGELOG.md
@@ -3,6 +3,23 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.1...v2.7.0) (2019-11-11)
+
+
+### Bug Fixes
+
+* **eslint-plugin:** crash fixing readonly arrays to generic ([#1172](https://github.com/typescript-eslint/typescript-eslint/issues/1172)) ([2b2f2d7](https://github.com/typescript-eslint/typescript-eslint/commit/2b2f2d7))
+
+
+### Features
+
+* **eslint-plugin:** [no-unused-expressions] extend for optional chaining ([#1175](https://github.com/typescript-eslint/typescript-eslint/issues/1175)) ([57d63b7](https://github.com/typescript-eslint/typescript-eslint/commit/57d63b7))
+* **parser:** handle optional chaining in scope analysis ([#1169](https://github.com/typescript-eslint/typescript-eslint/issues/1169)) ([026ceb9](https://github.com/typescript-eslint/typescript-eslint/commit/026ceb9))
+
+
+
+
+
## [2.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.0...v2.6.1) (2019-11-04)
**Note:** Version bump only for package @typescript-eslint/eslint-plugin
diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md
index baec8f2426e6..b616245454e6 100644
--- a/packages/eslint-plugin/README.md
+++ b/packages/eslint-plugin/README.md
@@ -10,7 +10,7 @@
## Installation
-Make sure you have TypeScript and @typescript-eslint/parser installed, then install the plugin:
+Make sure you have TypeScript and `@typescript-eslint/parser` installed, then install the plugin:
```sh
npm i @typescript-eslint/eslint-plugin --save-dev
@@ -145,7 +145,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e
| [`@typescript-eslint/await-thenable`](./docs/rules/await-thenable.md) | Disallows awaiting a value that is not a Thenable | :heavy_check_mark: | | :thought_balloon: |
| [`@typescript-eslint/ban-ts-ignore`](./docs/rules/ban-ts-ignore.md) | Bans “// @ts-ignore” comments from being used | :heavy_check_mark: | | |
| [`@typescript-eslint/ban-types`](./docs/rules/ban-types.md) | Bans specific types from being used | :heavy_check_mark: | :wrench: | |
-| [`@typescript-eslint/brace-style`](./docs/rules/brace-style.md) | Enforce consistent brace style for blocks | | :wrench: | |
+| [`@typescript-eslint/brace-style`](./docs/rules/brace-style.md) | Enforce consistent brace style for blocks | | :wrench: | |
| [`@typescript-eslint/camelcase`](./docs/rules/camelcase.md) | Enforce camelCase naming convention | :heavy_check_mark: | | |
| [`@typescript-eslint/class-name-casing`](./docs/rules/class-name-casing.md) | Require PascalCased class and interface names | :heavy_check_mark: | | |
| [`@typescript-eslint/consistent-type-assertions`](./docs/rules/consistent-type-assertions.md) | Enforces consistent usage of type assertions. | :heavy_check_mark: | | |
@@ -181,6 +181,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e
| [`@typescript-eslint/no-unnecessary-qualifier`](./docs/rules/no-unnecessary-qualifier.md) | Warns when a namespace qualifier is unnecessary | | :wrench: | :thought_balloon: |
| [`@typescript-eslint/no-unnecessary-type-arguments`](./docs/rules/no-unnecessary-type-arguments.md) | Warns if an explicitly specified type argument is the default for that type parameter | | :wrench: | :thought_balloon: |
| [`@typescript-eslint/no-unnecessary-type-assertion`](./docs/rules/no-unnecessary-type-assertion.md) | Warns if a type assertion does not change the type of an expression | :heavy_check_mark: | :wrench: | :thought_balloon: |
+| [`@typescript-eslint/no-unused-expressions`](./docs/rules/no-unused-expressions.md) | Disallow unused expressions | | | |
| [`@typescript-eslint/no-unused-vars`](./docs/rules/no-unused-vars.md) | Disallow unused variables | :heavy_check_mark: | | |
| [`@typescript-eslint/no-use-before-define`](./docs/rules/no-use-before-define.md) | Disallow the use of variables before they are defined | :heavy_check_mark: | | |
| [`@typescript-eslint/no-useless-constructor`](./docs/rules/no-useless-constructor.md) | Disallow unnecessary constructors | | | |
@@ -193,7 +194,7 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e
| [`@typescript-eslint/prefer-regexp-exec`](./docs/rules/prefer-regexp-exec.md) | Prefer RegExp#exec() over String#match() if no global flag is provided | :heavy_check_mark: | | :thought_balloon: |
| [`@typescript-eslint/prefer-string-starts-ends-with`](./docs/rules/prefer-string-starts-ends-with.md) | Enforce the use of `String#startsWith` and `String#endsWith` instead of other equivalent methods of checking substrings | :heavy_check_mark: | :wrench: | :thought_balloon: |
| [`@typescript-eslint/promise-function-async`](./docs/rules/promise-function-async.md) | Requires any function or method that returns a Promise to be marked async | | | :thought_balloon: |
-| [`@typescript-eslint/quotes`](./docs/rules/quotes.md) | Enforce the consistent use of either backticks, double, or single quotes | | :wrench: | |
+| [`@typescript-eslint/quotes`](./docs/rules/quotes.md) | Enforce the consistent use of either backticks, double, or single quotes | | :wrench: | |
| [`@typescript-eslint/require-array-sort-compare`](./docs/rules/require-array-sort-compare.md) | Enforce giving `compare` argument to `Array#sort` | | | :thought_balloon: |
| [`@typescript-eslint/require-await`](./docs/rules/require-await.md) | Disallow async functions which have no `await` expression | :heavy_check_mark: | | :thought_balloon: |
| [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string | | | :thought_balloon: |
diff --git a/packages/eslint-plugin/docs/rules/no-unused-expressions.md b/packages/eslint-plugin/docs/rules/no-unused-expressions.md
new file mode 100644
index 000000000000..7da998ab2c6c
--- /dev/null
+++ b/packages/eslint-plugin/docs/rules/no-unused-expressions.md
@@ -0,0 +1,25 @@
+# require or disallow semicolons instead of ASI (semi)
+
+This rule aims to eliminate unused expressions which have no effect on the state of the program.
+
+## Rule Details
+
+This rule extends the base [eslint/no-unused-expressions](https://eslint.org/docs/rules/no-unused-expressions) rule.
+It supports all options and features of the base rule.
+This version adds support for numerous typescript features.
+
+## How to use
+
+```cjson
+{
+ // note you must disable the base rule as it can report incorrect errors
+ "no-unused-expressions": "off",
+ "@typescript-eslint/no-unused-expressions": ["error"]
+}
+```
+
+## Options
+
+See [eslint/no-unused-expressions options](https://eslint.org/docs/rules/no-unused-expressions#options).
+
+Taken with ❤️ [from ESLint core](https://github.com/eslint/eslint/blob/master/docs/rules/no-unused-expressions.md)
diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json
index 75b4a0d903f6..b315da580591 100644
--- a/packages/eslint-plugin/package.json
+++ b/packages/eslint-plugin/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/eslint-plugin",
- "version": "2.6.1",
+ "version": "2.7.0",
"description": "TypeScript plugin for ESLint",
"keywords": [
"eslint",
@@ -40,7 +40,7 @@
"typecheck": "tsc -p tsconfig.json --noEmit"
},
"dependencies": {
- "@typescript-eslint/experimental-utils": "2.6.1",
+ "@typescript-eslint/experimental-utils": "2.7.0",
"eslint-utils": "^1.4.2",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^2.0.1",
diff --git a/packages/eslint-plugin/src/configs/all.json b/packages/eslint-plugin/src/configs/all.json
index 377f4b58f0e4..395c1af592ed 100644
--- a/packages/eslint-plugin/src/configs/all.json
+++ b/packages/eslint-plugin/src/configs/all.json
@@ -50,6 +50,7 @@
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-arguments": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
+ "@typescript-eslint/no-unused-expressions": "error",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
"no-use-before-define": "off",
diff --git a/packages/eslint-plugin/src/rules/array-type.ts b/packages/eslint-plugin/src/rules/array-type.ts
index b9977618c40c..0ed4266a240d 100644
--- a/packages/eslint-plugin/src/rules/array-type.ts
+++ b/packages/eslint-plugin/src/rules/array-type.ts
@@ -146,7 +146,8 @@ export default util.createRule({
return false;
}
- if (node.range[0] - prevToken.range[1] > 0) {
+ const nextToken = sourceCode.getTokenAfter(prevToken);
+ if (nextToken && sourceCode.isSpaceBetweenTokens(prevToken, nextToken)) {
return false;
}
@@ -168,6 +169,21 @@ export default util.createRule({
return 'T';
}
+ /**
+ * @param node the node to be evaluated
+ */
+ function getTypeOpNodeRange(
+ node: TSESTree.Node | null,
+ ): [number, number] | undefined {
+ if (!node) {
+ return undefined;
+ }
+
+ const firstToken = sourceCode.getFirstToken(node)!;
+ const nextToken = sourceCode.getTokenAfter(firstToken)!;
+ return [firstToken.range[0], nextToken.range[0]];
+ }
+
return {
TSArrayType(node): void {
if (
@@ -208,24 +224,27 @@ export default util.createRule({
type: getMessageType(node.elementType),
},
fix(fixer) {
- const startText = requireWhitespaceBefore(node);
const toFix = [
fixer.replaceTextRange([node.range[1] - 2, node.range[1]], '>'),
- fixer.insertTextBefore(
- node,
- `${startText ? ' ' : ''}${isReadonly ? 'Readonly' : ''}Array<`,
- ),
];
- if (typeOpNode) {
- // remove the readonly operator if it exists
- toFix.unshift(
- fixer.removeRange([
- typeOpNode.range[0],
- typeOpNode.range[0] + 'readonly '.length,
- ]),
+ const startText = requireWhitespaceBefore(node);
+ const typeOpNodeRange = getTypeOpNodeRange(typeOpNode);
+
+ if (typeOpNodeRange) {
+ toFix.unshift(fixer.removeRange(typeOpNodeRange));
+ } else {
+ toFix.push(
+ fixer.insertTextBefore(node, `${startText ? ' ' : ''}`),
);
}
+ toFix.push(
+ fixer.insertTextBefore(
+ node,
+ `${isReadonly ? 'Readonly' : ''}Array<`,
+ ),
+ );
+
if (node.elementType.type === AST_NODE_TYPES.TSParenthesizedType) {
const first = sourceCode.getFirstToken(node.elementType);
const last = sourceCode.getLastToken(node.elementType);
diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts
index 5302abd05de0..4aa8beea1f63 100644
--- a/packages/eslint-plugin/src/rules/index.ts
+++ b/packages/eslint-plugin/src/rules/index.ts
@@ -39,6 +39,7 @@ import noUnnecessaryCondition from './no-unnecessary-condition';
import noUnnecessaryQualifier from './no-unnecessary-qualifier';
import noUnnecessaryTypeAssertion from './no-unnecessary-type-assertion';
import noUnusedVars from './no-unused-vars';
+import noUnusedExpressions from './no-unused-expressions';
import noUseBeforeDefine from './no-use-before-define';
import noUselessConstructor from './no-useless-constructor';
import noVarRequires from './no-var-requires';
@@ -106,6 +107,7 @@ export default {
'no-unnecessary-type-arguments': useDefaultTypeParameter,
'no-unnecessary-type-assertion': noUnnecessaryTypeAssertion,
'no-unused-vars': noUnusedVars,
+ 'no-unused-expressions': noUnusedExpressions,
'no-use-before-define': noUseBeforeDefine,
'no-useless-constructor': noUselessConstructor,
'no-var-requires': noVarRequires,
diff --git a/packages/eslint-plugin/src/rules/no-unused-expressions.ts b/packages/eslint-plugin/src/rules/no-unused-expressions.ts
new file mode 100644
index 000000000000..f7d86f50c1c7
--- /dev/null
+++ b/packages/eslint-plugin/src/rules/no-unused-expressions.ts
@@ -0,0 +1,33 @@
+import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils';
+import baseRule from 'eslint/lib/rules/no-unused-expressions';
+import * as util from '../util';
+
+export default util.createRule({
+ name: 'no-unused-expressions',
+ meta: {
+ type: 'suggestion',
+ docs: {
+ description: 'Disallow unused expressions',
+ category: 'Best Practices',
+ recommended: false,
+ },
+ schema: baseRule.meta.schema,
+ messages: {
+ expected:
+ 'Expected an assignment or function call and instead saw an expression.',
+ },
+ },
+ defaultOptions: [],
+ create(context) {
+ const rules = baseRule.create(context);
+
+ return {
+ ExpressionStatement(node): void {
+ if (node.expression.type === AST_NODE_TYPES.OptionalCallExpression) {
+ return;
+ }
+ rules.ExpressionStatement(node);
+ },
+ };
+ },
+});
diff --git a/packages/eslint-plugin/tests/eslint-rules/no-restricted-globals.test.ts b/packages/eslint-plugin/tests/eslint-rules/no-restricted-globals.test.ts
index 40f3398fb7df..0cb6ec5d2919 100644
--- a/packages/eslint-plugin/tests/eslint-rules/no-restricted-globals.test.ts
+++ b/packages/eslint-plugin/tests/eslint-rules/no-restricted-globals.test.ts
@@ -30,6 +30,71 @@ type Handler = (event: string) => any
`,
options: ['event'],
},
+ {
+ code: `
+ const a = foo?.bar?.name
+ `,
+ },
+ {
+ code: `
+ const a = foo?.bar?.name ?? "foobar"
+ `,
+ },
+ {
+ code: `
+ const a = foo()?.bar;
+ `,
+ },
+ {
+ code: `
+ const a = foo()?.bar ?? true;
+ `,
+ },
+ ],
+ invalid: [
+ {
+ code: `
+function onClick() {
+ console.log(event);
+}
+
+fdescribe("foo", function() {
+});
+ `,
+ options: ['event'],
+ errors: [
+ {
+ message: "Unexpected use of 'event'.",
+ // the base rule doesn't use messageId
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } as any,
+ ],
+ },
+ {
+ code: `
+confirm("TEST");
+ `,
+ options: ['confirm'],
+ errors: [
+ {
+ message: "Unexpected use of 'confirm'.",
+ // the base rule doesn't use messageId
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } as any,
+ ],
+ },
+ {
+ code: `
+var a = confirm("TEST")?.a;
+ `,
+ options: ['confirm'],
+ errors: [
+ {
+ message: "Unexpected use of 'confirm'.",
+ // the base rule doesn't use messageId
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } as any,
+ ],
+ },
],
- invalid: [],
});
diff --git a/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts b/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts
index 84626c38201f..38d58b482fd3 100644
--- a/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts
+++ b/packages/eslint-plugin/tests/eslint-rules/no-undef.test.ts
@@ -68,6 +68,57 @@ function eachr(subject: Object | Array): typeof subject {
`
function eachr(subject: Map): typeof subject;
`,
+ `
+ var a = { b: 3 };
+ var c = a?.b;
+ `,
+ `
+ var a = { b: { c: 3 } };
+ var d = a?.["b"]?.c;
+ `,
+ `
+ var a = { b: 3 };
+ var c = { };
+ var d = (a || c)?.b;
+ `,
+ `
+ var a = { b: () => {} };
+ a?.b();
+ `,
+ ],
+ invalid: [
+ {
+ code: 'a = 5;',
+ errors: [
+ {
+ messageId: 'undef',
+ data: {
+ name: 'a',
+ },
+ },
+ ],
+ },
+ {
+ code: 'a?.b = 5;',
+ errors: [
+ {
+ messageId: 'undef',
+ data: {
+ name: 'a',
+ },
+ },
+ ],
+ },
+ {
+ code: 'a()?.b = 5;',
+ errors: [
+ {
+ messageId: 'undef',
+ data: {
+ name: 'a',
+ },
+ },
+ ],
+ },
],
- invalid: [],
});
diff --git a/packages/eslint-plugin/tests/eslint-rules/no-use-before-define.test.ts b/packages/eslint-plugin/tests/eslint-rules/no-use-before-define.test.ts
new file mode 100644
index 000000000000..4571cd04afbb
--- /dev/null
+++ b/packages/eslint-plugin/tests/eslint-rules/no-use-before-define.test.ts
@@ -0,0 +1,85 @@
+import rule from 'eslint/lib/rules/no-use-before-define';
+import { RuleTester } from '../RuleTester';
+
+const ruleTester = new RuleTester({
+ parserOptions: {
+ ecmaVersion: 6,
+ sourceType: 'module',
+ ecmaFeatures: {},
+ },
+ parser: '@typescript-eslint/parser',
+});
+
+ruleTester.run('no-use-before-define', rule, {
+ valid: [
+ `
+const updatedAt = data?.updatedAt;
+ `,
+ `
+function f() {
+ return function t() {};
+}
+f()?.();
+ `,
+ `
+var a = { b: 5 };
+alert(a?.b);
+ `,
+ ],
+ invalid: [
+ {
+ code: `
+f();
+function f() {}
+ `,
+ errors: [
+ {
+ message: "'f' was used before it was defined.",
+ // the base rule doesn't use messageId
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } as any,
+ ],
+ },
+ {
+ code: `
+alert(a);
+var a = 10;
+ `,
+ errors: [
+ {
+ message: "'a' was used before it was defined.",
+ // the base rule doesn't use messageId
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } as any,
+ ],
+ },
+ {
+ code: `
+f()?.();
+function f() {
+ return function t() {};
+}
+ `,
+ errors: [
+ {
+ message: "'f' was used before it was defined.",
+ // the base rule doesn't use messageId
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } as any,
+ ],
+ },
+ {
+ code: `
+alert(a?.b);
+var a = { b: 5 };
+ `,
+ errors: [
+ {
+ message: "'a' was used before it was defined.",
+ // the base rule doesn't use messageId
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } as any,
+ ],
+ },
+ ],
+});
diff --git a/packages/eslint-plugin/tests/rules/array-type.test.ts b/packages/eslint-plugin/tests/rules/array-type.test.ts
index 32de7e32c892..86cb1940826b 100644
--- a/packages/eslint-plugin/tests/rules/array-type.test.ts
+++ b/packages/eslint-plugin/tests/rules/array-type.test.ts
@@ -1071,5 +1071,35 @@ class Foo extends Bar implements Baz {
`let a: readonly Array[] = []`,
'array',
);
+ testOutput(
+ 'generic',
+ `type T = readonly(string)[]`,
+ `type T = ReadonlyArray`,
+ 'generic',
+ );
+ testOutput(
+ 'generic',
+ `let a: readonly(readonly string[])[] = []`,
+ `let a: ReadonlyArray> = []`,
+ 'generic',
+ );
+ testOutput(
+ 'generic',
+ `type T = readonly(readonly string[])[]`,
+ `type T = ReadonlyArray>`,
+ 'generic',
+ );
+ testOutput(
+ 'generic',
+ `type T = readonly (readonly string[])[]`,
+ `type T = ReadonlyArray>`,
+ 'generic',
+ );
+ testOutput(
+ 'generic',
+ `type T = readonly (readonly string[])[]`,
+ `type T = ReadonlyArray>`,
+ 'generic',
+ );
});
});
diff --git a/packages/eslint-plugin/tests/rules/no-unused-expressions.test.ts b/packages/eslint-plugin/tests/rules/no-unused-expressions.test.ts
new file mode 100644
index 000000000000..46653b30c663
--- /dev/null
+++ b/packages/eslint-plugin/tests/rules/no-unused-expressions.test.ts
@@ -0,0 +1,180 @@
+import rule from '../../src/rules/no-unused-expressions';
+import { RuleTester } from '../RuleTester';
+
+const ruleTester = new RuleTester({
+ parserOptions: {
+ ecmaVersion: 6,
+ sourceType: 'module',
+ ecmaFeatures: {},
+ },
+ parser: '@typescript-eslint/parser',
+});
+
+// the base rule doesn't have messageIds
+function error(
+ messages: { line: number; column: number }[],
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+): any[] {
+ return messages.map(message => ({
+ ...message,
+ message:
+ 'Expected an assignment or function call and instead saw an expression.',
+ }));
+}
+
+ruleTester.run('no-unused-expressions', rule, {
+ valid: [
+ `
+ test.age?.toLocaleString();
+ `,
+ `
+ let a = (a?.b).c;
+ `,
+ `
+ let b = a?.['b'];
+ `,
+ `
+ let c = one[2]?.[3][4];
+ `,
+ `
+ one[2]?.[3][4]?.();
+ `,
+ `
+ a?.['b']?.c();
+ `,
+ ],
+ invalid: [
+ {
+ code: `
+if(0) 0
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 7,
+ },
+ ]),
+ },
+ {
+ code: `
+f(0), {}
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ {
+ code: `
+a, b()
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ {
+ code: `
+a() && function namedFunctionInExpressionContext () {f();}
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ {
+ code: `
+a?.b
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ {
+ code: `
+(a?.b).c
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ {
+ code: `
+a?.['b']
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ {
+ code: `
+(a?.['b']).c
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ {
+ code: `
+a?.b()?.c
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ {
+ code: `
+(a?.b()).c
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ {
+ code: `
+one[2]?.[3][4];
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ {
+ code: `
+one.two?.three.four;
+ `,
+ errors: error([
+ {
+ line: 2,
+ column: 1,
+ },
+ ]),
+ },
+ ],
+});
diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts
index 120b11433cb9..c21b235be448 100644
--- a/packages/eslint-plugin/typings/eslint-rules.d.ts
+++ b/packages/eslint-plugin/typings/eslint-rules.d.ts
@@ -304,6 +304,26 @@ declare module 'eslint/lib/rules/no-unused-vars' {
export = rule;
}
+declare module 'eslint/lib/rules/no-unused-expressions' {
+ import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils';
+
+ const rule: TSESLint.RuleModule<
+ 'expected',
+ (
+ | 'all'
+ | 'local'
+ | {
+ allowShortCircuit?: boolean;
+ allowTernary?: boolean;
+ allowTaggedTemplates?: boolean;
+ })[],
+ {
+ ExpressionStatement(node: TSESTree.ExpressionStatement): void;
+ }
+ >;
+ export = rule;
+}
+
declare module 'eslint/lib/rules/no-use-before-define' {
import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils';
diff --git a/packages/experimental-utils/CHANGELOG.md b/packages/experimental-utils/CHANGELOG.md
index cabf42dd1a9b..fa483c6bd8f4 100644
--- a/packages/experimental-utils/CHANGELOG.md
+++ b/packages/experimental-utils/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.1...v2.7.0) (2019-11-11)
+
+**Note:** Version bump only for package @typescript-eslint/experimental-utils
+
+
+
+
+
## [2.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.0...v2.6.1) (2019-11-04)
**Note:** Version bump only for package @typescript-eslint/experimental-utils
diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json
index d05bf07280fb..2bbb6ddc9ec3 100644
--- a/packages/experimental-utils/package.json
+++ b/packages/experimental-utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/experimental-utils",
- "version": "2.6.1",
+ "version": "2.7.0",
"description": "(Experimental) Utilities for working with TypeScript + ESLint together",
"keywords": [
"eslint",
@@ -37,7 +37,7 @@
},
"dependencies": {
"@types/json-schema": "^7.0.3",
- "@typescript-eslint/typescript-estree": "2.6.1",
+ "@typescript-eslint/typescript-estree": "2.7.0",
"eslint-scope": "^5.0.0"
},
"peerDependencies": {
diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md
index b6b7fc716a62..45ba8b728f68 100644
--- a/packages/parser/CHANGELOG.md
+++ b/packages/parser/CHANGELOG.md
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.1...v2.7.0) (2019-11-11)
+
+
+### Features
+
+* **parser:** handle optional chaining in scope analysis ([#1169](https://github.com/typescript-eslint/typescript-eslint/issues/1169)) ([026ceb9](https://github.com/typescript-eslint/typescript-eslint/commit/026ceb9))
+
+
+
+
+
## [2.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.0...v2.6.1) (2019-11-04)
diff --git a/packages/parser/package.json b/packages/parser/package.json
index 8283ffd33030..549dda9e82fc 100644
--- a/packages/parser/package.json
+++ b/packages/parser/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/parser",
- "version": "2.6.1",
+ "version": "2.7.0",
"description": "An ESLint custom parser which leverages TypeScript ESTree",
"main": "dist/parser.js",
"types": "dist/parser.d.ts",
@@ -43,13 +43,13 @@
},
"dependencies": {
"@types/eslint-visitor-keys": "^1.0.0",
- "@typescript-eslint/experimental-utils": "2.6.1",
- "@typescript-eslint/typescript-estree": "2.6.1",
+ "@typescript-eslint/experimental-utils": "2.7.0",
+ "@typescript-eslint/typescript-estree": "2.7.0",
"eslint-visitor-keys": "^1.1.0"
},
"devDependencies": {
"@types/glob": "^7.1.1",
- "@typescript-eslint/shared-fixtures": "2.6.1",
+ "@typescript-eslint/shared-fixtures": "2.7.0",
"glob": "^7.1.4"
}
}
diff --git a/packages/parser/src/analyze-scope.ts b/packages/parser/src/analyze-scope.ts
index 1b98c064db09..27e90a46565d 100644
--- a/packages/parser/src/analyze-scope.ts
+++ b/packages/parser/src/analyze-scope.ts
@@ -344,6 +344,29 @@ class Referencer extends TSESLintScope.Referencer {
node.arguments.forEach(this.visit, this);
}
+ /**
+ * Visit optional member expression.
+ * @param node The OptionalMemberExpression node to visit.
+ */
+ OptionalMemberExpression(node: TSESTree.OptionalMemberExpression): void {
+ this.visit(node.object);
+ if (node.computed) {
+ this.visit(node.property);
+ }
+ }
+
+ /**
+ * Visit optional call expression.
+ * @param node The OptionalMemberExpression node to visit.
+ */
+ OptionalCallExpression(node: TSESTree.OptionalCallExpression): void {
+ this.visitTypeParameters(node);
+
+ this.visit(node.callee);
+
+ node.arguments.forEach(this.visit, this);
+ }
+
/**
* Define the variable of this function declaration only once.
* Because to avoid confusion of `no-redeclare` rule by overloading.
diff --git a/packages/parser/tests/lib/__snapshots__/typescript.ts.snap b/packages/parser/tests/lib/__snapshots__/typescript.ts.snap
index 3d94d81e424b..39f3da70df9c 100644
--- a/packages/parser/tests/lib/__snapshots__/typescript.ts.snap
+++ b/packages/parser/tests/lib/__snapshots__/typescript.ts.snap
@@ -22070,7 +22070,7 @@ Object {
exports[`typescript fixtures/basics/optional-chain.src 1`] = `
Object {
- "$id": 18,
+ "$id": 10,
"block": Object {
"range": Array [
0,
@@ -22080,7 +22080,7 @@ Object {
},
"childScopes": Array [
Object {
- "$id": 17,
+ "$id": 9,
"block": Object {
"range": Array [
0,
@@ -22090,7 +22090,7 @@ Object {
},
"childScopes": Array [
Object {
- "$id": 16,
+ "$id": 8,
"block": Object {
"range": Array [
0,
@@ -22105,7 +22105,7 @@ Object {
Object {
"$id": 3,
"from": Object {
- "$ref": 16,
+ "$ref": 8,
},
"identifier": Object {
"name": "one",
@@ -22124,24 +22124,7 @@ Object {
Object {
"$id": 4,
"from": Object {
- "$ref": 16,
- },
- "identifier": Object {
- "name": "two",
- "range": Array [
- 45,
- 48,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 5,
- "from": Object {
- "$ref": 16,
+ "$ref": 8,
},
"identifier": Object {
"name": "one",
@@ -22158,43 +22141,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 6,
- "from": Object {
- "$ref": 16,
- },
- "identifier": Object {
- "name": "two",
- "range": Array [
- 57,
- 60,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 7,
- "from": Object {
- "$ref": 16,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 61,
- 66,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 8,
+ "$id": 5,
"from": Object {
- "$ref": 16,
+ "$ref": 8,
},
"identifier": Object {
"name": "one",
@@ -22211,26 +22160,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 9,
- "from": Object {
- "$ref": 16,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 79,
- 84,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 10,
+ "$id": 6,
"from": Object {
- "$ref": 16,
+ "$ref": 8,
},
"identifier": Object {
"name": "one",
@@ -22247,43 +22179,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 11,
- "from": Object {
- "$ref": 16,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 97,
- 102,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 12,
- "from": Object {
- "$ref": 16,
- },
- "identifier": Object {
- "name": "four",
- "range": Array [
- 103,
- 107,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 13,
+ "$id": 7,
"from": Object {
- "$ref": 16,
+ "$ref": 8,
},
"identifier": Object {
"name": "one",
@@ -22299,70 +22197,11 @@ Object {
},
"writeExpr": undefined,
},
- Object {
- "$id": 14,
- "from": Object {
- "$ref": 16,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 120,
- 125,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 15,
- "from": Object {
- "$ref": 16,
- },
- "identifier": Object {
- "name": "four",
- "range": Array [
- 127,
- 131,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- ],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 7,
- },
- Object {
- "$ref": 9,
- },
- Object {
- "$ref": 11,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 14,
- },
- Object {
- "$ref": 15,
- },
],
+ "throughReferences": Array [],
"type": "function",
"upperScope": Object {
- "$ref": 17,
+ "$ref": 9,
},
"variableMap": Object {
"arguments": Object {
@@ -22373,7 +22212,7 @@ Object {
},
},
"variableScope": Object {
- "$ref": 16,
+ "$ref": 8,
},
"variables": Array [
Object {
@@ -22384,7 +22223,7 @@ Object {
"name": "arguments",
"references": Array [],
"scope": Object {
- "$ref": 16,
+ "$ref": 8,
},
},
Object {
@@ -22427,20 +22266,20 @@ Object {
"$ref": 3,
},
Object {
- "$ref": 5,
+ "$ref": 4,
},
Object {
- "$ref": 8,
+ "$ref": 5,
},
Object {
- "$ref": 10,
+ "$ref": 6,
},
Object {
- "$ref": 13,
+ "$ref": 7,
},
],
"scope": Object {
- "$ref": 16,
+ "$ref": 8,
},
},
],
@@ -22449,35 +22288,10 @@ Object {
"functionExpressionScope": false,
"isStrict": true,
"references": Array [],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 7,
- },
- Object {
- "$ref": 9,
- },
- Object {
- "$ref": 11,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 14,
- },
- Object {
- "$ref": 15,
- },
- ],
+ "throughReferences": Array [],
"type": "module",
"upperScope": Object {
- "$ref": 18,
+ "$ref": 10,
},
"variableMap": Object {
"processOptional": Object {
@@ -22485,7 +22299,7 @@ Object {
},
},
"variableScope": Object {
- "$ref": 17,
+ "$ref": 9,
},
"variables": Array [
Object {
@@ -22525,7 +22339,7 @@ Object {
"name": "processOptional",
"references": Array [],
"scope": Object {
- "$ref": 17,
+ "$ref": 9,
},
},
],
@@ -22534,37 +22348,12 @@ Object {
"functionExpressionScope": false,
"isStrict": false,
"references": Array [],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 7,
- },
- Object {
- "$ref": 9,
- },
- Object {
- "$ref": 11,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 14,
- },
- Object {
- "$ref": 15,
- },
- ],
+ "throughReferences": Array [],
"type": "global",
"upperScope": null,
"variableMap": Object {},
"variableScope": Object {
- "$ref": 18,
+ "$ref": 10,
},
"variables": Array [],
}
@@ -22572,7 +22361,7 @@ Object {
exports[`typescript fixtures/basics/optional-chain-call.src 1`] = `
Object {
- "$id": 23,
+ "$id": 14,
"block": Object {
"range": Array [
0,
@@ -22582,7 +22371,7 @@ Object {
},
"childScopes": Array [
Object {
- "$id": 22,
+ "$id": 13,
"block": Object {
"range": Array [
0,
@@ -22592,7 +22381,7 @@ Object {
},
"childScopes": Array [
Object {
- "$id": 21,
+ "$id": 12,
"block": Object {
"range": Array [
0,
@@ -22607,7 +22396,7 @@ Object {
Object {
"$id": 3,
"from": Object {
- "$ref": 21,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -22626,30 +22415,32 @@ Object {
Object {
"$id": 4,
"from": Object {
- "$ref": 21,
+ "$ref": 12,
},
"identifier": Object {
- "name": "fn",
+ "name": "one",
"range": Array [
- 49,
- 51,
+ 57,
+ 60,
],
"type": "Identifier",
},
"kind": "r",
- "resolved": null,
+ "resolved": Object {
+ "$ref": 2,
+ },
"writeExpr": undefined,
},
Object {
"$id": 5,
"from": Object {
- "$ref": 21,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
"range": Array [
- 57,
- 60,
+ 74,
+ 77,
],
"type": "Identifier",
},
@@ -22662,133 +22453,29 @@ Object {
Object {
"$id": 6,
"from": Object {
- "$ref": 21,
+ "$ref": 12,
},
"identifier": Object {
- "name": "two",
+ "name": "one",
"range": Array [
- 62,
- 65,
+ 91,
+ 94,
],
"type": "Identifier",
},
"kind": "r",
- "resolved": null,
+ "resolved": Object {
+ "$ref": 2,
+ },
"writeExpr": undefined,
},
Object {
"$id": 7,
"from": Object {
- "$ref": 21,
+ "$ref": 12,
},
"identifier": Object {
- "name": "fn",
- "range": Array [
- 66,
- 68,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 8,
- "from": Object {
- "$ref": 21,
- },
- "identifier": Object {
- "name": "one",
- "range": Array [
- 74,
- 77,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": Object {
- "$ref": 2,
- },
- "writeExpr": undefined,
- },
- Object {
- "$id": 9,
- "from": Object {
- "$ref": 21,
- },
- "identifier": Object {
- "name": "fn",
- "range": Array [
- 83,
- 85,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 10,
- "from": Object {
- "$ref": 21,
- },
- "identifier": Object {
- "name": "one",
- "range": Array [
- 91,
- 94,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": Object {
- "$ref": 2,
- },
- "writeExpr": undefined,
- },
- Object {
- "$id": 11,
- "from": Object {
- "$ref": 21,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 100,
- 105,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 12,
- "from": Object {
- "$ref": 21,
- },
- "identifier": Object {
- "name": "fn",
- "range": Array [
- 106,
- 108,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 13,
- "from": Object {
- "$ref": 21,
- },
- "identifier": Object {
- "name": "one",
+ "name": "one",
"range": Array [
114,
117,
@@ -22802,43 +22489,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 14,
- "from": Object {
- "$ref": 21,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 123,
- 128,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 15,
- "from": Object {
- "$ref": 21,
- },
- "identifier": Object {
- "name": "fn",
- "range": Array [
- 130,
- 132,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 16,
+ "$id": 8,
"from": Object {
- "$ref": 21,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -22855,9 +22508,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 17,
+ "$id": 9,
"from": Object {
- "$ref": 21,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -22874,9 +22527,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 18,
+ "$id": 10,
"from": Object {
- "$ref": 21,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -22893,9 +22546,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 19,
+ "$id": 11,
"from": Object {
- "$ref": 21,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -22911,56 +22564,11 @@ Object {
},
"writeExpr": undefined,
},
- Object {
- "$id": 20,
- "from": Object {
- "$ref": 21,
- },
- "identifier": Object {
- "name": "two",
- "range": Array [
- 187,
- 190,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- ],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 7,
- },
- Object {
- "$ref": 9,
- },
- Object {
- "$ref": 11,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 14,
- },
- Object {
- "$ref": 15,
- },
- Object {
- "$ref": 20,
- },
],
+ "throughReferences": Array [],
"type": "function",
"upperScope": Object {
- "$ref": 22,
+ "$ref": 13,
},
"variableMap": Object {
"arguments": Object {
@@ -22971,7 +22579,7 @@ Object {
},
},
"variableScope": Object {
- "$ref": 21,
+ "$ref": 12,
},
"variables": Array [
Object {
@@ -22982,7 +22590,7 @@ Object {
"name": "arguments",
"references": Array [],
"scope": Object {
- "$ref": 21,
+ "$ref": 12,
},
},
Object {
@@ -23025,32 +22633,32 @@ Object {
"$ref": 3,
},
Object {
- "$ref": 5,
+ "$ref": 4,
},
Object {
- "$ref": 8,
+ "$ref": 5,
},
Object {
- "$ref": 10,
+ "$ref": 6,
},
Object {
- "$ref": 13,
+ "$ref": 7,
},
Object {
- "$ref": 16,
+ "$ref": 8,
},
Object {
- "$ref": 17,
+ "$ref": 9,
},
Object {
- "$ref": 18,
+ "$ref": 10,
},
Object {
- "$ref": 19,
+ "$ref": 11,
},
],
"scope": Object {
- "$ref": 21,
+ "$ref": 12,
},
},
],
@@ -23059,38 +22667,10 @@ Object {
"functionExpressionScope": false,
"isStrict": true,
"references": Array [],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 7,
- },
- Object {
- "$ref": 9,
- },
- Object {
- "$ref": 11,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 14,
- },
- Object {
- "$ref": 15,
- },
- Object {
- "$ref": 20,
- },
- ],
+ "throughReferences": Array [],
"type": "module",
"upperScope": Object {
- "$ref": 23,
+ "$ref": 14,
},
"variableMap": Object {
"processOptionalCall": Object {
@@ -23098,7 +22678,7 @@ Object {
},
},
"variableScope": Object {
- "$ref": 22,
+ "$ref": 13,
},
"variables": Array [
Object {
@@ -23138,7 +22718,7 @@ Object {
"name": "processOptionalCall",
"references": Array [],
"scope": Object {
- "$ref": 22,
+ "$ref": 13,
},
},
],
@@ -23147,40 +22727,12 @@ Object {
"functionExpressionScope": false,
"isStrict": false,
"references": Array [],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 7,
- },
- Object {
- "$ref": 9,
- },
- Object {
- "$ref": 11,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 14,
- },
- Object {
- "$ref": 15,
- },
- Object {
- "$ref": 20,
- },
- ],
+ "throughReferences": Array [],
"type": "global",
"upperScope": null,
"variableMap": Object {},
"variableScope": Object {
- "$ref": 23,
+ "$ref": 14,
},
"variables": Array [],
}
@@ -23188,7 +22740,7 @@ Object {
exports[`typescript fixtures/basics/optional-chain-call-with-parens.src 1`] = `
Object {
- "$id": 20,
+ "$id": 14,
"block": Object {
"range": Array [
0,
@@ -23198,7 +22750,7 @@ Object {
},
"childScopes": Array [
Object {
- "$id": 19,
+ "$id": 13,
"block": Object {
"range": Array [
0,
@@ -23208,7 +22760,7 @@ Object {
},
"childScopes": Array [
Object {
- "$id": 18,
+ "$id": 12,
"block": Object {
"range": Array [
0,
@@ -23223,7 +22775,7 @@ Object {
Object {
"$id": 3,
"from": Object {
- "$ref": 18,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -23242,24 +22794,7 @@ Object {
Object {
"$id": 4,
"from": Object {
- "$ref": 18,
- },
- "identifier": Object {
- "name": "fn",
- "range": Array [
- 56,
- 58,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 5,
- "from": Object {
- "$ref": 18,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -23276,26 +22811,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 6,
- "from": Object {
- "$ref": 18,
- },
- "identifier": Object {
- "name": "two",
- "range": Array [
- 71,
- 74,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 7,
+ "$id": 5,
"from": Object {
- "$ref": 18,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -23312,26 +22830,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 8,
- "from": Object {
- "$ref": 18,
- },
- "identifier": Object {
- "name": "fn",
- "range": Array [
- 94,
- 96,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 9,
+ "$id": 6,
"from": Object {
- "$ref": 18,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -23348,26 +22849,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 10,
- "from": Object {
- "$ref": 18,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 113,
- 118,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 11,
+ "$id": 7,
"from": Object {
- "$ref": 18,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -23384,43 +22868,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 12,
- "from": Object {
- "$ref": 18,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 138,
- 143,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 13,
- "from": Object {
- "$ref": 18,
- },
- "identifier": Object {
- "name": "fn",
- "range": Array [
- 145,
- 147,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 14,
+ "$id": 8,
"from": Object {
- "$ref": 18,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -23437,9 +22887,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 15,
+ "$id": 9,
"from": Object {
- "$ref": 18,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -23456,9 +22906,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 16,
+ "$id": 10,
"from": Object {
- "$ref": 18,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -23475,9 +22925,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 17,
+ "$id": 11,
"from": Object {
- "$ref": 18,
+ "$ref": 12,
},
"identifier": Object {
"name": "one",
@@ -23494,29 +22944,10 @@ Object {
"writeExpr": undefined,
},
],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 8,
- },
- Object {
- "$ref": 10,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 13,
- },
- ],
+ "throughReferences": Array [],
"type": "function",
"upperScope": Object {
- "$ref": 19,
+ "$ref": 13,
},
"variableMap": Object {
"arguments": Object {
@@ -23527,7 +22958,7 @@ Object {
},
},
"variableScope": Object {
- "$ref": 18,
+ "$ref": 12,
},
"variables": Array [
Object {
@@ -23538,7 +22969,7 @@ Object {
"name": "arguments",
"references": Array [],
"scope": Object {
- "$ref": 18,
+ "$ref": 12,
},
},
Object {
@@ -23581,32 +23012,32 @@ Object {
"$ref": 3,
},
Object {
- "$ref": 5,
+ "$ref": 4,
},
Object {
- "$ref": 7,
+ "$ref": 5,
},
Object {
- "$ref": 9,
+ "$ref": 6,
},
Object {
- "$ref": 11,
+ "$ref": 7,
},
Object {
- "$ref": 14,
+ "$ref": 8,
},
Object {
- "$ref": 15,
+ "$ref": 9,
},
Object {
- "$ref": 16,
+ "$ref": 10,
},
Object {
- "$ref": 17,
+ "$ref": 11,
},
],
"scope": Object {
- "$ref": 18,
+ "$ref": 12,
},
},
],
@@ -23615,29 +23046,10 @@ Object {
"functionExpressionScope": false,
"isStrict": true,
"references": Array [],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 8,
- },
- Object {
- "$ref": 10,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 13,
- },
- ],
+ "throughReferences": Array [],
"type": "module",
"upperScope": Object {
- "$ref": 20,
+ "$ref": 14,
},
"variableMap": Object {
"processOptionalCallParens": Object {
@@ -23645,7 +23057,7 @@ Object {
},
},
"variableScope": Object {
- "$ref": 19,
+ "$ref": 13,
},
"variables": Array [
Object {
@@ -23676,49 +23088,30 @@ Object {
Object {
"name": "processOptionalCallParens",
"range": Array [
- 9,
- 34,
- ],
- "type": "Identifier",
- },
- ],
- "name": "processOptionalCallParens",
- "references": Array [],
- "scope": Object {
- "$ref": 19,
- },
- },
- ],
- },
- ],
- "functionExpressionScope": false,
- "isStrict": false,
- "references": Array [],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 8,
- },
- Object {
- "$ref": 10,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 13,
+ 9,
+ 34,
+ ],
+ "type": "Identifier",
+ },
+ ],
+ "name": "processOptionalCallParens",
+ "references": Array [],
+ "scope": Object {
+ "$ref": 13,
+ },
+ },
+ ],
},
],
+ "functionExpressionScope": false,
+ "isStrict": false,
+ "references": Array [],
+ "throughReferences": Array [],
"type": "global",
"upperScope": null,
"variableMap": Object {},
"variableScope": Object {
- "$ref": 20,
+ "$ref": 14,
},
"variables": Array [],
}
@@ -24352,7 +23745,7 @@ Object {
exports[`typescript fixtures/basics/optional-chain-with-parens.src 1`] = `
Object {
- "$id": 19,
+ "$id": 11,
"block": Object {
"range": Array [
0,
@@ -24362,7 +23755,7 @@ Object {
},
"childScopes": Array [
Object {
- "$id": 18,
+ "$id": 10,
"block": Object {
"range": Array [
0,
@@ -24372,7 +23765,7 @@ Object {
},
"childScopes": Array [
Object {
- "$id": 17,
+ "$id": 9,
"block": Object {
"range": Array [
0,
@@ -24387,7 +23780,7 @@ Object {
Object {
"$id": 3,
"from": Object {
- "$ref": 17,
+ "$ref": 9,
},
"identifier": Object {
"name": "one",
@@ -24406,24 +23799,7 @@ Object {
Object {
"$id": 4,
"from": Object {
- "$ref": 17,
- },
- "identifier": Object {
- "name": "two",
- "range": Array [
- 52,
- 55,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 5,
- "from": Object {
- "$ref": 17,
+ "$ref": 9,
},
"identifier": Object {
"name": "one",
@@ -24440,26 +23816,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 6,
- "from": Object {
- "$ref": 17,
- },
- "identifier": Object {
- "name": "two",
- "range": Array [
- 66,
- 69,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 7,
+ "$id": 5,
"from": Object {
- "$ref": 17,
+ "$ref": 9,
},
"identifier": Object {
"name": "one",
@@ -24476,26 +23835,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 8,
- "from": Object {
- "$ref": 17,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 90,
- 95,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 9,
+ "$id": 6,
"from": Object {
- "$ref": 17,
+ "$ref": 9,
},
"identifier": Object {
"name": "one",
@@ -24512,26 +23854,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 10,
- "from": Object {
- "$ref": 17,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 110,
- 115,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 11,
+ "$id": 7,
"from": Object {
- "$ref": 17,
+ "$ref": 9,
},
"identifier": Object {
"name": "one",
@@ -24548,43 +23873,9 @@ Object {
"writeExpr": undefined,
},
Object {
- "$id": 12,
- "from": Object {
- "$ref": 17,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 135,
- 140,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 13,
- "from": Object {
- "$ref": 17,
- },
- "identifier": Object {
- "name": "four",
- "range": Array [
- 142,
- 146,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 14,
+ "$id": 8,
"from": Object {
- "$ref": 17,
+ "$ref": 9,
},
"identifier": Object {
"name": "one",
@@ -24600,70 +23891,11 @@ Object {
},
"writeExpr": undefined,
},
- Object {
- "$id": 15,
- "from": Object {
- "$ref": 17,
- },
- "identifier": Object {
- "name": "three",
- "range": Array [
- 161,
- 166,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- Object {
- "$id": 16,
- "from": Object {
- "$ref": 17,
- },
- "identifier": Object {
- "name": "four",
- "range": Array [
- 168,
- 172,
- ],
- "type": "Identifier",
- },
- "kind": "r",
- "resolved": null,
- "writeExpr": undefined,
- },
- ],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 8,
- },
- Object {
- "$ref": 10,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 13,
- },
- Object {
- "$ref": 15,
- },
- Object {
- "$ref": 16,
- },
],
+ "throughReferences": Array [],
"type": "function",
"upperScope": Object {
- "$ref": 18,
+ "$ref": 10,
},
"variableMap": Object {
"arguments": Object {
@@ -24674,7 +23906,7 @@ Object {
},
},
"variableScope": Object {
- "$ref": 17,
+ "$ref": 9,
},
"variables": Array [
Object {
@@ -24685,7 +23917,7 @@ Object {
"name": "arguments",
"references": Array [],
"scope": Object {
- "$ref": 17,
+ "$ref": 9,
},
},
Object {
@@ -24728,23 +23960,23 @@ Object {
"$ref": 3,
},
Object {
- "$ref": 5,
+ "$ref": 4,
},
Object {
- "$ref": 7,
+ "$ref": 5,
},
Object {
- "$ref": 9,
+ "$ref": 6,
},
Object {
- "$ref": 11,
+ "$ref": 7,
},
Object {
- "$ref": 14,
+ "$ref": 8,
},
],
"scope": Object {
- "$ref": 17,
+ "$ref": 9,
},
},
],
@@ -24753,35 +23985,10 @@ Object {
"functionExpressionScope": false,
"isStrict": true,
"references": Array [],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 8,
- },
- Object {
- "$ref": 10,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 13,
- },
- Object {
- "$ref": 15,
- },
- Object {
- "$ref": 16,
- },
- ],
+ "throughReferences": Array [],
"type": "module",
"upperScope": Object {
- "$ref": 19,
+ "$ref": 11,
},
"variableMap": Object {
"processOptionalParens": Object {
@@ -24789,7 +23996,7 @@ Object {
},
},
"variableScope": Object {
- "$ref": 18,
+ "$ref": 10,
},
"variables": Array [
Object {
@@ -24829,7 +24036,7 @@ Object {
"name": "processOptionalParens",
"references": Array [],
"scope": Object {
- "$ref": 18,
+ "$ref": 10,
},
},
],
@@ -24838,37 +24045,12 @@ Object {
"functionExpressionScope": false,
"isStrict": false,
"references": Array [],
- "throughReferences": Array [
- Object {
- "$ref": 4,
- },
- Object {
- "$ref": 6,
- },
- Object {
- "$ref": 8,
- },
- Object {
- "$ref": 10,
- },
- Object {
- "$ref": 12,
- },
- Object {
- "$ref": 13,
- },
- Object {
- "$ref": 15,
- },
- Object {
- "$ref": 16,
- },
- ],
+ "throughReferences": Array [],
"type": "global",
"upperScope": null,
"variableMap": Object {},
"variableScope": Object {
- "$ref": 19,
+ "$ref": 11,
},
"variables": Array [],
}
diff --git a/packages/shared-fixtures/CHANGELOG.md b/packages/shared-fixtures/CHANGELOG.md
index 320f1ba9ed0c..aa253e3d46ee 100644
--- a/packages/shared-fixtures/CHANGELOG.md
+++ b/packages/shared-fixtures/CHANGELOG.md
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.1...v2.7.0) (2019-11-11)
+
+**Note:** Version bump only for package @typescript-eslint/shared-fixtures
+
+
+
+
+
## [2.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.0...v2.6.1) (2019-11-04)
**Note:** Version bump only for package @typescript-eslint/shared-fixtures
diff --git a/packages/shared-fixtures/package.json b/packages/shared-fixtures/package.json
index 9d94966b4e18..c457e83d4dd3 100644
--- a/packages/shared-fixtures/package.json
+++ b/packages/shared-fixtures/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/shared-fixtures",
- "version": "2.6.1",
+ "version": "2.7.0",
"private": true,
"scripts": {
"build": "tsc -b tsconfig.build.json",
diff --git a/packages/typescript-estree/CHANGELOG.md b/packages/typescript-estree/CHANGELOG.md
index c90a056ec276..28d91bddc6b1 100644
--- a/packages/typescript-estree/CHANGELOG.md
+++ b/packages/typescript-estree/CHANGELOG.md
@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+# [2.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.1...v2.7.0) (2019-11-11)
+
+
+### Bug Fixes
+
+* **typescript-estree:** hash code to reduce update frequency ([#1179](https://github.com/typescript-eslint/typescript-eslint/issues/1179)) ([96d1cc3](https://github.com/typescript-eslint/typescript-eslint/commit/96d1cc3))
+* **typescript-estree:** reduce bundle footprint of tsutils ([#1177](https://github.com/typescript-eslint/typescript-eslint/issues/1177)) ([c8fe515](https://github.com/typescript-eslint/typescript-eslint/commit/c8fe515))
+
+
+
+
+
## [2.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v2.6.0...v2.6.1) (2019-11-04)
diff --git a/packages/typescript-estree/package.json b/packages/typescript-estree/package.json
index 1104de8adbd7..85a3a2b92b10 100644
--- a/packages/typescript-estree/package.json
+++ b/packages/typescript-estree/package.json
@@ -1,6 +1,6 @@
{
"name": "@typescript-eslint/typescript-estree",
- "version": "2.6.1",
+ "version": "2.7.0",
"description": "A parser that converts TypeScript source code into an ESTree compatible form",
"main": "dist/parser.js",
"types": "dist/parser.d.ts",
@@ -58,7 +58,7 @@
"@types/lodash.unescape": "^4.0.4",
"@types/semver": "^6.0.1",
"@types/tmp": "^0.1.0",
- "@typescript-eslint/shared-fixtures": "2.6.1",
+ "@typescript-eslint/shared-fixtures": "2.7.0",
"babel-code-frame": "^6.26.0",
"glob": "^7.1.4",
"lodash.isplainobject": "4.0.6",
diff --git a/packages/typescript-estree/src/convert-comments.ts b/packages/typescript-estree/src/convert-comments.ts
index 9a7de3e112a7..a82d9941dbd3 100644
--- a/packages/typescript-estree/src/convert-comments.ts
+++ b/packages/typescript-estree/src/convert-comments.ts
@@ -1,5 +1,5 @@
import * as ts from 'typescript'; // leave this as * as ts so people using util package don't need syntheticDefaultImports
-import { forEachComment } from 'tsutils';
+import { forEachComment } from 'tsutils/util/util';
import { getLocFor } from './node-utils';
import { TSESTree } from './ts-estree';
diff --git a/packages/typescript-estree/src/create-program/createWatchProgram.ts b/packages/typescript-estree/src/create-program/createWatchProgram.ts
index beabcdd68886..9223107986af 100644
--- a/packages/typescript-estree/src/create-program/createWatchProgram.ts
+++ b/packages/typescript-estree/src/create-program/createWatchProgram.ts
@@ -45,7 +45,7 @@ const programFileListCache = new Map>();
*/
const tsconfigLastModifiedTimestampCache = new Map();
-const parsedFilesSeen = new Set();
+const parsedFilesSeenHash = new Map();
/**
* Clear all of the parser caches.
@@ -55,7 +55,7 @@ function clearCaches(): void {
knownWatchProgramMap.clear();
fileWatchCallbackTrackingMap.clear();
folderWatchCallbackTrackingMap.clear();
- parsedFilesSeen.clear();
+ parsedFilesSeenHash.clear();
programFileListCache.clear();
tsconfigLastModifiedTimestampCache.clear();
}
@@ -104,6 +104,19 @@ function diagnosticReporter(diagnostic: ts.Diagnostic): void {
);
}
+/**
+ * Hash content for compare content.
+ * @param content hashed contend
+ * @returns hashed result
+ */
+function createHash(content: string): string {
+ // No ts.sys in browser environments.
+ if (ts.sys && ts.sys.createHash) {
+ return ts.sys.createHash(content);
+ }
+ return content;
+}
+
/**
* Calculate project environments using options provided by consumer and paths from config
* @param code The code being linted
@@ -125,10 +138,10 @@ function getProgramsForProjects(
currentLintOperationState.filePath = filePath;
// Update file version if necessary
- // TODO: only update when necessary, currently marks as changed on every lint
const fileWatchCallbacks = fileWatchCallbackTrackingMap.get(filePath);
+ const codeHash = createHash(code);
if (
- parsedFilesSeen.has(filePath) &&
+ parsedFilesSeenHash.get(filePath) !== codeHash &&
fileWatchCallbacks &&
fileWatchCallbacks.size > 0
) {
@@ -232,11 +245,15 @@ function createWatchProgram(
const oldReadFile = watchCompilerHost.readFile;
watchCompilerHost.readFile = (filePathIn, encoding): string | undefined => {
const filePath = getCanonicalFileName(filePathIn);
- parsedFilesSeen.add(filePath);
- return path.normalize(filePath) ===
+ const fileContent =
+ path.normalize(filePath) ===
path.normalize(currentLintOperationState.filePath)
- ? currentLintOperationState.code
- : oldReadFile(filePath, encoding);
+ ? currentLintOperationState.code
+ : oldReadFile(filePath, encoding);
+ if (fileContent) {
+ parsedFilesSeenHash.set(filePath, createHash(fileContent));
+ }
+ return fileContent;
};
// ensure process reports error on failure instead of exiting process immediately