Skip to content

Commit faca4b5

Browse files
committed
fix(linter/plugins): tokenize let, static and yield as Keywords (#18368)
Espree (ESLint's parser) has the surprising behavior that it produces `Keyword` tokens for identifiers called `let`, `static`, and `yield`. Fix our tokens to match Espree. #18345 skipped 4 conformance tests for `no-extra-parens` rule. These tests now don't need to be skipped and they pass. Related: typescript-eslint/typescript-eslint#11989
1 parent 52b5003 commit faca4b5

5 files changed

Lines changed: 319 additions & 13 deletions

File tree

apps/oxlint/conformance/snapshot.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
| Status | Count | % |
1919
| ----------- | ----- | ------ |
2020
| Total tests | 33090 | 100.0% |
21-
| Passing | 32799 | 99.1% |
21+
| Passing | 32803 | 99.1% |
2222
| Failing | 6 | 0.0% |
23-
| Skipped | 285 | 0.9% |
23+
| Skipped | 281 | 0.8% |
2424

2525
## Fully Passing Rules
2626

@@ -142,7 +142,7 @@
142142
- `no-extra-bind` (43 tests)
143143
- `no-extra-boolean-cast` (501 tests) (1 skipped)
144144
- `no-extra-label` (34 tests)
145-
- `no-extra-parens` (1072 tests) (5 skipped)
145+
- `no-extra-parens` (1072 tests) (1 skipped)
146146
- `no-extra-semi` (53 tests)
147147
- `no-fallthrough` (87 tests) (1 skipped)
148148
- `no-floating-decimal` (8 tests)

apps/oxlint/conformance/src/capture.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,14 +171,6 @@ function shouldSkipTest(ruleName: string, test: TestCase, code: string, err: Err
171171
return true;
172172
}
173173

174-
// TypeScript parser incorrectly tokenizes `let` as a `Keyword` instead of an `Identifier` token
175-
if (
176-
ruleName === "no-extra-parens" &&
177-
["(let[a] = b);", "(let)\nfoo", "(let[foo]) = 1", "(let)[foo]"].includes(code)
178-
) {
179-
return true;
180-
}
181-
182174
return false;
183175
}
184176

apps/oxlint/src-js/plugins/tokens_parse.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,13 @@ function getTokenType(token: ts.Identifier | ts.Token<ts.SyntaxKind>): Token["ty
244244
) {
245245
return "JSXIdentifier";
246246
}
247+
248+
// `espree` (ESLint's parser) produces `Keyword` tokens for `let`, `static`, and `yield`.
249+
// TS-ESLint parser produces `Identifier` tokens for these keywords, but we go with ESLint's behavior.
250+
// https://github.com/typescript-eslint/typescript-eslint/issues/11989
251+
// @ts-expect-error - `escapedText` is not public
252+
const name = token.escapedText;
253+
if (name === "let" || name === "static" || name === "yield") return "Keyword";
247254
}
248255

249256
/*
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const obj = {
2+
// Identifier tokens
3+
foo: foo,
4+
async: async,
5+
// Keyword tokens
6+
let: let,
7+
static: static,
8+
yield: yield,
9+
};

apps/oxlint/test/fixtures/tokens/output.snap.md

Lines changed: 300 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -772,8 +772,306 @@
772772
: ^
773773
`----
774774
775-
Found 0 warnings and 79 errors.
776-
Finished in Xms on 3 files with 1 rules using X threads.
775+
x tokens-plugin(tokens): Keyword ("const")
776+
,-[files/keywords.js:1:1]
777+
1 | const obj = {
778+
: ^^^^^
779+
2 | // Identifier tokens
780+
`----
781+
782+
x tokens-plugin(tokens): Tokens:
783+
| Keyword loc= 1:0 - 1:5 range= 0-5 "const"
784+
| Identifier loc= 1:6 - 1:9 range= 6-9 "obj"
785+
| Punctuator loc= 1:10 - 1:11 range= 10-11 "="
786+
| Punctuator loc= 1:12 - 1:13 range= 12-13 "{"
787+
| Identifier loc= 3:2 - 3:5 range= 39-42 "foo"
788+
| Punctuator loc= 3:5 - 3:6 range= 42-43 ":"
789+
| Identifier loc= 3:7 - 3:10 range= 44-47 "foo"
790+
| Punctuator loc= 3:10 - 3:11 range= 47-48 ","
791+
| Identifier loc= 4:2 - 4:7 range= 51-56 "async"
792+
| Punctuator loc= 4:7 - 4:8 range= 56-57 ":"
793+
| Identifier loc= 4:9 - 4:14 range= 58-63 "async"
794+
| Punctuator loc= 4:14 - 4:15 range= 63-64 ","
795+
| Keyword loc= 6:2 - 6:5 range= 87-90 "let"
796+
| Punctuator loc= 6:5 - 6:6 range= 90-91 ":"
797+
| Keyword loc= 6:7 - 6:10 range= 92-95 "let"
798+
| Punctuator loc= 6:10 - 6:11 range= 95-96 ","
799+
| Keyword loc= 7:2 - 7:8 range= 99-105 "static"
800+
| Punctuator loc= 7:8 - 7:9 range= 105-106 ":"
801+
| Keyword loc= 7:10 - 7:16 range= 107-113 "static"
802+
| Punctuator loc= 7:16 - 7:17 range= 113-114 ","
803+
| Keyword loc= 8:2 - 8:7 range= 117-122 "yield"
804+
| Punctuator loc= 8:7 - 8:8 range= 122-123 ":"
805+
| Keyword loc= 8:9 - 8:14 range= 124-129 "yield"
806+
| Punctuator loc= 8:14 - 8:15 range= 129-130 ","
807+
| Punctuator loc= 9:0 - 9:1 range= 131-132 "}"
808+
| Punctuator loc= 9:1 - 9:2 range= 132-133 ";"
809+
,-[files/keywords.js:1:1]
810+
1 | ,-> const obj = {
811+
2 | | // Identifier tokens
812+
3 | | foo: foo,
813+
4 | | async: async,
814+
5 | | // Keyword tokens
815+
6 | | let: let,
816+
7 | | static: static,
817+
8 | | yield: yield,
818+
9 | `-> };
819+
`----
820+
821+
x tokens-plugin(tokens): Tokens and comments:
822+
| Keyword loc= 1:0 - 1:5 range= 0-5 "const"
823+
| Identifier loc= 1:6 - 1:9 range= 6-9 "obj"
824+
| Punctuator loc= 1:10 - 1:11 range= 10-11 "="
825+
| Punctuator loc= 1:12 - 1:13 range= 12-13 "{"
826+
| Line loc= 2:2 - 2:22 range= 16-36 " Identifier tokens"
827+
| Identifier loc= 3:2 - 3:5 range= 39-42 "foo"
828+
| Punctuator loc= 3:5 - 3:6 range= 42-43 ":"
829+
| Identifier loc= 3:7 - 3:10 range= 44-47 "foo"
830+
| Punctuator loc= 3:10 - 3:11 range= 47-48 ","
831+
| Identifier loc= 4:2 - 4:7 range= 51-56 "async"
832+
| Punctuator loc= 4:7 - 4:8 range= 56-57 ":"
833+
| Identifier loc= 4:9 - 4:14 range= 58-63 "async"
834+
| Punctuator loc= 4:14 - 4:15 range= 63-64 ","
835+
| Line loc= 5:2 - 5:19 range= 67-84 " Keyword tokens"
836+
| Keyword loc= 6:2 - 6:5 range= 87-90 "let"
837+
| Punctuator loc= 6:5 - 6:6 range= 90-91 ":"
838+
| Keyword loc= 6:7 - 6:10 range= 92-95 "let"
839+
| Punctuator loc= 6:10 - 6:11 range= 95-96 ","
840+
| Keyword loc= 7:2 - 7:8 range= 99-105 "static"
841+
| Punctuator loc= 7:8 - 7:9 range= 105-106 ":"
842+
| Keyword loc= 7:10 - 7:16 range= 107-113 "static"
843+
| Punctuator loc= 7:16 - 7:17 range= 113-114 ","
844+
| Keyword loc= 8:2 - 8:7 range= 117-122 "yield"
845+
| Punctuator loc= 8:7 - 8:8 range= 122-123 ":"
846+
| Keyword loc= 8:9 - 8:14 range= 124-129 "yield"
847+
| Punctuator loc= 8:14 - 8:15 range= 129-130 ","
848+
| Punctuator loc= 9:0 - 9:1 range= 131-132 "}"
849+
| Punctuator loc= 9:1 - 9:2 range= 132-133 ";"
850+
,-[files/keywords.js:1:1]
851+
1 | ,-> const obj = {
852+
2 | | // Identifier tokens
853+
3 | | foo: foo,
854+
4 | | async: async,
855+
5 | | // Keyword tokens
856+
6 | | let: let,
857+
7 | | static: static,
858+
8 | | yield: yield,
859+
9 | `-> };
860+
`----
861+
862+
x tokens-plugin(tokens): Identifier ("obj")
863+
,-[files/keywords.js:1:7]
864+
1 | const obj = {
865+
: ^^^
866+
2 | // Identifier tokens
867+
`----
868+
869+
x tokens-plugin(tokens): Punctuator ("=")
870+
,-[files/keywords.js:1:11]
871+
1 | const obj = {
872+
: ^
873+
2 | // Identifier tokens
874+
`----
875+
876+
x tokens-plugin(tokens): Punctuator ("{")
877+
,-[files/keywords.js:1:13]
878+
1 | const obj = {
879+
: ^
880+
2 | // Identifier tokens
881+
`----
882+
883+
x tokens-plugin(tokens): Line (" Identifier tokens")
884+
,-[files/keywords.js:2:3]
885+
1 | const obj = {
886+
2 | // Identifier tokens
887+
: ^^^^^^^^^^^^^^^^^^^^
888+
3 | foo: foo,
889+
`----
890+
891+
x tokens-plugin(tokens): Identifier ("foo")
892+
,-[files/keywords.js:3:3]
893+
2 | // Identifier tokens
894+
3 | foo: foo,
895+
: ^^^
896+
4 | async: async,
897+
`----
898+
899+
x tokens-plugin(tokens): Punctuator (":")
900+
,-[files/keywords.js:3:6]
901+
2 | // Identifier tokens
902+
3 | foo: foo,
903+
: ^
904+
4 | async: async,
905+
`----
906+
907+
x tokens-plugin(tokens): Identifier ("foo")
908+
,-[files/keywords.js:3:8]
909+
2 | // Identifier tokens
910+
3 | foo: foo,
911+
: ^^^
912+
4 | async: async,
913+
`----
914+
915+
x tokens-plugin(tokens): Punctuator (",")
916+
,-[files/keywords.js:3:11]
917+
2 | // Identifier tokens
918+
3 | foo: foo,
919+
: ^
920+
4 | async: async,
921+
`----
922+
923+
x tokens-plugin(tokens): Identifier ("async")
924+
,-[files/keywords.js:4:3]
925+
3 | foo: foo,
926+
4 | async: async,
927+
: ^^^^^
928+
5 | // Keyword tokens
929+
`----
930+
931+
x tokens-plugin(tokens): Punctuator (":")
932+
,-[files/keywords.js:4:8]
933+
3 | foo: foo,
934+
4 | async: async,
935+
: ^
936+
5 | // Keyword tokens
937+
`----
938+
939+
x tokens-plugin(tokens): Identifier ("async")
940+
,-[files/keywords.js:4:10]
941+
3 | foo: foo,
942+
4 | async: async,
943+
: ^^^^^
944+
5 | // Keyword tokens
945+
`----
946+
947+
x tokens-plugin(tokens): Punctuator (",")
948+
,-[files/keywords.js:4:15]
949+
3 | foo: foo,
950+
4 | async: async,
951+
: ^
952+
5 | // Keyword tokens
953+
`----
954+
955+
x tokens-plugin(tokens): Line (" Keyword tokens")
956+
,-[files/keywords.js:5:3]
957+
4 | async: async,
958+
5 | // Keyword tokens
959+
: ^^^^^^^^^^^^^^^^^
960+
6 | let: let,
961+
`----
962+
963+
x tokens-plugin(tokens): Keyword ("let")
964+
,-[files/keywords.js:6:3]
965+
5 | // Keyword tokens
966+
6 | let: let,
967+
: ^^^
968+
7 | static: static,
969+
`----
970+
971+
x tokens-plugin(tokens): Punctuator (":")
972+
,-[files/keywords.js:6:6]
973+
5 | // Keyword tokens
974+
6 | let: let,
975+
: ^
976+
7 | static: static,
977+
`----
978+
979+
x tokens-plugin(tokens): Keyword ("let")
980+
,-[files/keywords.js:6:8]
981+
5 | // Keyword tokens
982+
6 | let: let,
983+
: ^^^
984+
7 | static: static,
985+
`----
986+
987+
x tokens-plugin(tokens): Punctuator (",")
988+
,-[files/keywords.js:6:11]
989+
5 | // Keyword tokens
990+
6 | let: let,
991+
: ^
992+
7 | static: static,
993+
`----
994+
995+
x tokens-plugin(tokens): Keyword ("static")
996+
,-[files/keywords.js:7:3]
997+
6 | let: let,
998+
7 | static: static,
999+
: ^^^^^^
1000+
8 | yield: yield,
1001+
`----
1002+
1003+
x tokens-plugin(tokens): Punctuator (":")
1004+
,-[files/keywords.js:7:9]
1005+
6 | let: let,
1006+
7 | static: static,
1007+
: ^
1008+
8 | yield: yield,
1009+
`----
1010+
1011+
x tokens-plugin(tokens): Keyword ("static")
1012+
,-[files/keywords.js:7:11]
1013+
6 | let: let,
1014+
7 | static: static,
1015+
: ^^^^^^
1016+
8 | yield: yield,
1017+
`----
1018+
1019+
x tokens-plugin(tokens): Punctuator (",")
1020+
,-[files/keywords.js:7:17]
1021+
6 | let: let,
1022+
7 | static: static,
1023+
: ^
1024+
8 | yield: yield,
1025+
`----
1026+
1027+
x tokens-plugin(tokens): Keyword ("yield")
1028+
,-[files/keywords.js:8:3]
1029+
7 | static: static,
1030+
8 | yield: yield,
1031+
: ^^^^^
1032+
9 | };
1033+
`----
1034+
1035+
x tokens-plugin(tokens): Punctuator (":")
1036+
,-[files/keywords.js:8:8]
1037+
7 | static: static,
1038+
8 | yield: yield,
1039+
: ^
1040+
9 | };
1041+
`----
1042+
1043+
x tokens-plugin(tokens): Keyword ("yield")
1044+
,-[files/keywords.js:8:10]
1045+
7 | static: static,
1046+
8 | yield: yield,
1047+
: ^^^^^
1048+
9 | };
1049+
`----
1050+
1051+
x tokens-plugin(tokens): Punctuator (",")
1052+
,-[files/keywords.js:8:15]
1053+
7 | static: static,
1054+
8 | yield: yield,
1055+
: ^
1056+
9 | };
1057+
`----
1058+
1059+
x tokens-plugin(tokens): Punctuator ("}")
1060+
,-[files/keywords.js:9:1]
1061+
8 | yield: yield,
1062+
9 | };
1063+
: ^
1064+
`----
1065+
1066+
x tokens-plugin(tokens): Punctuator (";")
1067+
,-[files/keywords.js:9:2]
1068+
8 | yield: yield,
1069+
9 | };
1070+
: ^
1071+
`----
1072+
1073+
Found 0 warnings and 109 errors.
1074+
Finished in Xms on 4 files with 1 rules using X threads.
7771075
```
7781076

7791077
# stderr

0 commit comments

Comments
 (0)