Skip to content

Commit 81f519c

Browse files
committed
feat: add repro for palantir/tslint#3455
0 parents  commit 81f519c

File tree

7 files changed

+381
-0
lines changed

7 files changed

+381
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# no-void-expression-bug
2+
3+
> no-void-expression misses errors when no-unused-variable is listed first
4+
[palantir/tslint/issues/3455](https://github.com/palantir/tslint/issues/3455)
5+
6+
### Bug Report
7+
8+
- __TSLint version__: 5.8.0
9+
- __TypeScript version__: 2.6.1
10+
- __Running TSLint via__: CLI
11+
12+
#### TypeScript code being linted
13+
14+
```ts
15+
import { EventEmitter } from '@angular/core';
16+
import { Observable } from 'rxjs/Observable';
17+
import { Subject } from 'rxjs/Subject';
18+
import 'rxjs/add/observable/of';
19+
import 'rxjs/add/operator/do';
20+
21+
export const f1 = () => returnsVoid(); // error
22+
export const obs1 = Observable.of(undefined).do(() => returnsVoid()); // error
23+
24+
export class Component {
25+
subject = new Subject<void>();
26+
event = new EventEmitter<void>();
27+
28+
obs3 = Observable.of(undefined).do(() => this.subject.next()); // error
29+
obs2 = Observable.of(undefined).do(() => this.event.next()); // no error, but should be
30+
}
31+
32+
function returnsVoid() { }
33+
```
34+
35+
with `tslint.json` configuration:
36+
37+
```json
38+
{
39+
"rules": {
40+
"no-unused-variable": [
41+
true,
42+
"check-parameters", {
43+
"ignore-pattern": "^_"
44+
}
45+
],
46+
"no-void-expression": true
47+
}
48+
}
49+
```
50+
51+
#### Actual behavior
52+
The `no-void-expression` rule does not report an error on line 15 when the `no-unused-variable`
53+
variable is enabled. But if you disable the `no-unused-variable` rule or move it after the
54+
`no-void-expression` rule, the `no-void-expression` rule correctly reports all four errors.
55+
56+
#### Expected behavior
57+
The `no-void-expression` rule should report an error on four of the noted lines regardless of which
58+
other rules are enabled or the order the rules.
59+
60+
### Commentary
61+
This is odd because the angular `EventEmitter` extends the rxjs `Subject`, so the two expressions
62+
should be evaluated as exactly the same type.
63+
64+
If I were to guess the cause of this behavior, I would say that `no-unused-variable` the rule seems
65+
to be mutating the TypeScript AST or some other shared state somehow.

package.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "no-void-expression-bug",
3+
"version": "1.0.0",
4+
"main": "index.ts",
5+
"author": "Kevin Phelps <[email protected]>",
6+
"license": "MIT",
7+
"scripts": {
8+
"lint": "tslint --project tsconfig.json"
9+
},
10+
"devDependencies": {
11+
"tslint": "5.8.0",
12+
"typescript": "2.6.1"
13+
},
14+
"dependencies": {
15+
"@angular/core": "5.0.0",
16+
"rxjs": "5.5.2",
17+
"zone.js": "0.8.18"
18+
}
19+
}

src/index.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { EventEmitter } from '@angular/core';
2+
import { Observable } from 'rxjs/Observable';
3+
import { Subject } from 'rxjs/Subject';
4+
import 'rxjs/add/observable/of';
5+
import 'rxjs/add/operator/do';
6+
7+
export const f1 = () => returnsVoid(); // error
8+
export const obs1 = Observable.of(undefined).do(() => returnsVoid()); // error
9+
10+
export class Component {
11+
subject = new Subject<void>();
12+
event = new EventEmitter<void>();
13+
14+
obs3 = Observable.of(undefined).do(() => this.subject.next()); // error
15+
obs2 = Observable.of(undefined).do(() => this.event.next()); // no error, but should be
16+
}
17+
18+
function returnsVoid() { }

tsconfig.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"compileOnSave": false,
3+
"compilerOptions": {
4+
"outDir": "./dist/out-tsc",
5+
"sourceMap": true,
6+
"declaration": false,
7+
"moduleResolution": "node",
8+
"emitDecoratorMetadata": true,
9+
"experimentalDecorators": true,
10+
"target": "es5",
11+
"typeRoots": [
12+
"node_modules/@types"
13+
],
14+
"lib": [
15+
"es2017",
16+
"dom"
17+
]
18+
}
19+
}

tslint.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"rules": {
3+
"no-unused-variable": [
4+
true,
5+
"check-parameters", {
6+
"ignore-pattern": "^_"
7+
}
8+
],
9+
"no-void-expression": true
10+
}
11+
}
12+
13+
// It works if you disable the 'no-unused-variable' rule.
14+
// {
15+
// "rules": {
16+
// "no-void-expression": true
17+
// }
18+
// }
19+
20+
// Or if you reorder the rules.
21+
// {
22+
// "rules": {
23+
// "no-void-expression": true,
24+
// "no-unused-variable": [
25+
// true,
26+
// "check-parameters", {
27+
// "ignore-pattern": "^_"
28+
// }
29+
// ]
30+
// }
31+
// }

yarn.lock

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+
# yarn lockfile v1
3+
4+
5+
"@angular/[email protected]":
6+
version "5.0.0"
7+
resolved "https://registry.yarnpkg.com/@angular/core/-/core-5.0.0.tgz#4f976a225f7dddf34992f2cad824c9543a46f4c8"
8+
dependencies:
9+
tslib "^1.7.1"
10+
11+
ansi-regex@^2.0.0:
12+
version "2.1.1"
13+
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
14+
15+
ansi-styles@^2.2.1:
16+
version "2.2.1"
17+
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
18+
19+
ansi-styles@^3.1.0:
20+
version "3.2.0"
21+
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88"
22+
dependencies:
23+
color-convert "^1.9.0"
24+
25+
babel-code-frame@^6.22.0:
26+
version "6.26.0"
27+
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
28+
dependencies:
29+
chalk "^1.1.3"
30+
esutils "^2.0.2"
31+
js-tokens "^3.0.2"
32+
33+
balanced-match@^1.0.0:
34+
version "1.0.0"
35+
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
36+
37+
brace-expansion@^1.1.7:
38+
version "1.1.8"
39+
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
40+
dependencies:
41+
balanced-match "^1.0.0"
42+
concat-map "0.0.1"
43+
44+
builtin-modules@^1.1.1:
45+
version "1.1.1"
46+
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
47+
48+
chalk@^1.1.3:
49+
version "1.1.3"
50+
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
51+
dependencies:
52+
ansi-styles "^2.2.1"
53+
escape-string-regexp "^1.0.2"
54+
has-ansi "^2.0.0"
55+
strip-ansi "^3.0.0"
56+
supports-color "^2.0.0"
57+
58+
chalk@^2.1.0:
59+
version "2.3.0"
60+
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
61+
dependencies:
62+
ansi-styles "^3.1.0"
63+
escape-string-regexp "^1.0.5"
64+
supports-color "^4.0.0"
65+
66+
color-convert@^1.9.0:
67+
version "1.9.0"
68+
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a"
69+
dependencies:
70+
color-name "^1.1.1"
71+
72+
color-name@^1.1.1:
73+
version "1.1.3"
74+
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
75+
76+
commander@^2.9.0:
77+
version "2.11.0"
78+
resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
79+
80+
81+
version "0.0.1"
82+
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
83+
84+
diff@^3.2.0:
85+
version "3.4.0"
86+
resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c"
87+
88+
escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
89+
version "1.0.5"
90+
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
91+
92+
esutils@^2.0.2:
93+
version "2.0.2"
94+
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
95+
96+
fs.realpath@^1.0.0:
97+
version "1.0.0"
98+
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
99+
100+
glob@^7.1.1:
101+
version "7.1.2"
102+
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
103+
dependencies:
104+
fs.realpath "^1.0.0"
105+
inflight "^1.0.4"
106+
inherits "2"
107+
minimatch "^3.0.4"
108+
once "^1.3.0"
109+
path-is-absolute "^1.0.0"
110+
111+
has-ansi@^2.0.0:
112+
version "2.0.0"
113+
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
114+
dependencies:
115+
ansi-regex "^2.0.0"
116+
117+
has-flag@^2.0.0:
118+
version "2.0.0"
119+
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
120+
121+
inflight@^1.0.4:
122+
version "1.0.6"
123+
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
124+
dependencies:
125+
once "^1.3.0"
126+
wrappy "1"
127+
128+
inherits@2:
129+
version "2.0.3"
130+
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
131+
132+
js-tokens@^3.0.2:
133+
version "3.0.2"
134+
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
135+
136+
minimatch@^3.0.4:
137+
version "3.0.4"
138+
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
139+
dependencies:
140+
brace-expansion "^1.1.7"
141+
142+
once@^1.3.0:
143+
version "1.4.0"
144+
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
145+
dependencies:
146+
wrappy "1"
147+
148+
path-is-absolute@^1.0.0:
149+
version "1.0.1"
150+
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
151+
152+
path-parse@^1.0.5:
153+
version "1.0.5"
154+
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
155+
156+
resolve@^1.3.2:
157+
version "1.5.0"
158+
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36"
159+
dependencies:
160+
path-parse "^1.0.5"
161+
162+
163+
version "5.5.2"
164+
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.2.tgz#28d403f0071121967f18ad665563255d54236ac3"
165+
dependencies:
166+
symbol-observable "^1.0.1"
167+
168+
semver@^5.3.0:
169+
version "5.4.1"
170+
resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
171+
172+
strip-ansi@^3.0.0:
173+
version "3.0.1"
174+
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
175+
dependencies:
176+
ansi-regex "^2.0.0"
177+
178+
supports-color@^2.0.0:
179+
version "2.0.0"
180+
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
181+
182+
supports-color@^4.0.0:
183+
version "4.5.0"
184+
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b"
185+
dependencies:
186+
has-flag "^2.0.0"
187+
188+
symbol-observable@^1.0.1:
189+
version "1.0.4"
190+
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d"
191+
192+
tslib@^1.7.1:
193+
version "1.8.0"
194+
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.8.0.tgz#dc604ebad64bcbf696d613da6c954aa0e7ea1eb6"
195+
196+
197+
version "5.8.0"
198+
resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.8.0.tgz#1f49ad5b2e77c76c3af4ddcae552ae4e3612eb13"
199+
dependencies:
200+
babel-code-frame "^6.22.0"
201+
builtin-modules "^1.1.1"
202+
chalk "^2.1.0"
203+
commander "^2.9.0"
204+
diff "^3.2.0"
205+
glob "^7.1.1"
206+
minimatch "^3.0.4"
207+
resolve "^1.3.2"
208+
semver "^5.3.0"
209+
tslib "^1.7.1"
210+
tsutils "^2.12.1"
211+
212+
tsutils@^2.12.1:
213+
version "2.12.2"
214+
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.12.2.tgz#ad58a4865d17ec3ddb6631b6ca53be14a5656ff3"
215+
dependencies:
216+
tslib "^1.7.1"
217+
218+
219+
version "2.6.1"
220+
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.1.tgz#ef39cdea27abac0b500242d6726ab90e0c846631"
221+
222+
wrappy@1:
223+
version "1.0.2"
224+
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
225+
226+
227+
version "0.8.18"
228+
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.18.tgz#8cecb3977fcd1b3090562ff4570e2847e752b48d"

0 commit comments

Comments
 (0)