From f8f0c41b20cfa55ae857ac6b97d68108a1e7e683 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 25 Nov 2022 17:52:42 +0800 Subject: [PATCH] TypeScript: Throw errors for invalid modifiers (#13877) Fixes https://github.com/prettier/prettier/issues/9760 --- src/language-js/parse/babel.js | 2 - .../postprocess/ts-syntax-kind.evaluate.js | 11 - .../parse/postprocess/typescript.js | 176 ++- src/language-js/parse/typescript.js | 2 +- src/language-js/print/class.js | 8 - .../__snapshots__/jsfmt.spec.js.snap | 76 +- .../babel-ts/__snapshots__/jsfmt.spec.js.snap | 64 - .../errors/typescript/babel-ts/jsfmt.spec.js | 18 - .../misc/errors/typescript/jsfmt.spec.js | 18 - .../__snapshots__/jsfmt.spec.js.snap | 1186 +++++++++++++++++ .../errors/typescript/modifiers/jsfmt.spec.js | 93 ++ .../__snapshots__/jsfmt.spec.js.snap | 20 - .../invalid-modifiers.ts | 4 - .../__snapshots__/jsfmt.spec.js.snap | 22 - .../misc/typescript-only/invalid-modifiers.ts | 5 - .../keywords/__snapshots__/jsfmt.spec.js.snap | 69 +- .../format/typescript/keywords/jsfmt.spec.js | 2 +- tests/format/typescript/keywords/keywords.ts | 13 - tests/format/typescript/keywords/module.ts | 7 +- 19 files changed, 1410 insertions(+), 386 deletions(-) delete mode 100644 src/language-js/parse/postprocess/ts-syntax-kind.evaluate.js create mode 100644 tests/format/misc/errors/typescript/modifiers/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/format/misc/errors/typescript/modifiers/jsfmt.spec.js delete mode 100644 tests/format/misc/typescript-babel-only/invalid-modifiers.ts delete mode 100644 tests/format/misc/typescript-only/invalid-modifiers.ts diff --git a/src/language-js/parse/babel.js b/src/language-js/parse/babel.js index f93834041..5261c758f 100644 --- a/src/language-js/parse/babel.js +++ b/src/language-js/parse/babel.js @@ -207,8 +207,6 @@ const allowedMessageCodes = new Set([ "InvalidTupleMemberLabel", "NonClassMethodPropertyHasAbstractModifer", - "ClassMethodHasDeclare", - "ClassMethodHasReadonly", "DuplicateAccessibilityModifier", "IndexSignatureHasDeclare", diff --git a/src/language-js/parse/postprocess/ts-syntax-kind.evaluate.js b/src/language-js/parse/postprocess/ts-syntax-kind.evaluate.js deleted file mode 100644 index 44d8a1574..000000000 --- a/src/language-js/parse/postprocess/ts-syntax-kind.evaluate.js +++ /dev/null @@ -1,11 +0,0 @@ -import ts from "typescript"; - -export const { - AbstractKeyword, - SourceFile, - DeclareKeyword, - PropertyDeclaration, - InKeyword, - OutKeyword, - MethodSignature, -} = ts.SyntaxKind; diff --git a/src/language-js/parse/postprocess/typescript.js b/src/language-js/parse/postprocess/typescript.js index b4ccd02ef..2d3bda826 100644 --- a/src/language-js/parse/postprocess/typescript.js +++ b/src/language-js/parse/postprocess/typescript.js @@ -1,10 +1,11 @@ import isNonEmptyArray from "../../../utils/is-non-empty-array.js"; import visitNode from "./visit-node.js"; import throwTsSyntaxError from "./throw-ts-syntax-error.js"; -import * as SyntaxKind from "./ts-syntax-kind.evaluate.js"; + +let ts; function getTsNodeLocation(nodeOrToken) { - const sourceFile = getSourceFileOfNode(nodeOrToken); + const sourceFile = ts.getSourceFileOfNode(nodeOrToken); const [start, end] = [nodeOrToken.pos, nodeOrToken.end].map((position) => { const { line, character: column } = sourceFile.getLineAndCharacterOfPosition(position); @@ -14,12 +15,8 @@ function getTsNodeLocation(nodeOrToken) { return { start, end }; } -// Copied from https://unpkg.com/typescript@4.8.2/lib/typescript.js -function getSourceFileOfNode(node) { - while (node && node.kind !== SyntaxKind.SourceFile) { - node = node.parent; - } - return node; +function throwErrorOnTsNode(node, message) { + throwTsSyntaxError({ loc: getTsNodeLocation(node) }, message); } // Invalid decorators are removed since `@typescript-eslint/typescript-estree` v4 @@ -33,10 +30,7 @@ function throwErrorForInvalidDecorator(tsNode) { const [{ expression }] = illegalDecorators; - throwTsSyntaxError( - { loc: getTsNodeLocation(expression) }, - "Decorators are not valid here." - ); + throwErrorOnTsNode(expression, "Decorators are not valid here."); } // Values of abstract property is removed since `@typescript-eslint/typescript-estree` v5 @@ -44,11 +38,11 @@ function throwErrorForInvalidDecorator(tsNode) { function throwErrorForInvalidAbstractProperty(tsNode, esTreeNode) { if ( !( - tsNode.kind === SyntaxKind.PropertyDeclaration && + tsNode.kind === ts.SyntaxKind.PropertyDeclaration && tsNode.initializer && esTreeNode.value === null && tsNode.modifiers?.some( - (modifier) => modifier.kind === SyntaxKind.AbstractKeyword + (modifier) => modifier.kind === ts.SyntaxKind.AbstractKeyword ) ) ) { @@ -61,55 +55,86 @@ function throwErrorForInvalidAbstractProperty(tsNode, esTreeNode) { ); } -function throwErrorForInvalidDeclare(tsNode, esTreeNode) { - if ( - !( - esTreeNode.type === "MethodDefinition" && - (esTreeNode.kind === "get" || esTreeNode.kind === "set") - ) - ) { +// Based on `checkGrammarModifiers` function in `typescript` +function throwErrorForInvalidModifier(node) { + const { modifiers } = node; + if (!isNonEmptyArray(modifiers)) { return; } - const declareKeyword = tsNode.modifiers?.find( - (modifier) => modifier.kind === SyntaxKind.DeclareKeyword - ); + const { SyntaxKind } = ts; - if (!declareKeyword) { - return; + for (const modifier of modifiers) { + if (ts.isDecorator(modifier)) { + continue; + } + + if (modifier.kind !== SyntaxKind.ReadonlyKeyword) { + if ( + node.kind === SyntaxKind.PropertySignature || + node.kind === SyntaxKind.MethodSignature + ) { + throwErrorOnTsNode( + modifier, + `'${ts.tokenToString( + modifier.kind + )}' modifier cannot appear on a type member` + ); + } + + if ( + node.kind === SyntaxKind.IndexSignature && + (modifier.kind !== SyntaxKind.StaticKeyword || + !ts.isClassLike(node.parent)) + ) { + throwErrorOnTsNode( + modifier, + `'${ts.tokenToString( + modifier.kind + )}' modifier cannot appear on an index signature` + ); + } + } + + if ( + modifier.kind !== SyntaxKind.InKeyword && + modifier.kind !== SyntaxKind.OutKeyword && + node.kind === SyntaxKind.TypeParameter + ) { + throwErrorOnTsNode( + modifier, + `'${ts.tokenToString( + modifier.kind + )}' modifier cannot appear on a type parameter` + ); + } + + if ( + modifier.kind === SyntaxKind.ReadonlyKeyword && + node.kind !== SyntaxKind.PropertyDeclaration && + node.kind !== SyntaxKind.PropertySignature && + node.kind !== SyntaxKind.IndexSignature && + node.kind !== SyntaxKind.Parameter + ) { + throwErrorOnTsNode( + modifier, + "'readonly' modifier can only appear on a property declaration or index signature." + ); + } + + if ( + modifier.kind === SyntaxKind.DeclareKeyword && + ts.isClassLike(node.parent) && + !ts.isPropertyDeclaration(node) + ) { + throwErrorOnTsNode( + modifier, + `'${ts.tokenToString( + modifier.kind + )}' modifier cannot appear on class elements of this kind.` + ); + } } - - throwTsSyntaxError( - { loc: getTsNodeLocation(declareKeyword) }, - /* cspell:disable-next-line */ - `'declare' is not allowed in ${esTreeNode.kind}ters.` - ); -} - -function throwErrorForInvalidModifierOnTypeParameter(tsNode, esTreeNode) { - if ( - esTreeNode.type !== "TSMethodSignature" || - tsNode.kind !== SyntaxKind.MethodSignature - ) { - return; - } - - const invalidModifier = tsNode.modifiers?.find( - (modifier) => - !( - modifier.kind === SyntaxKind.InKeyword || - modifier.kind === SyntaxKind.OutKeyword - ) - ); - - if (!invalidModifier) { - return; - } - - throwTsSyntaxError( - { loc: getTsNodeLocation(invalidModifier) }, - "This modifier cannot appear on a type member" - ); } function getTsNode(node, tsParseResult) { @@ -127,27 +152,46 @@ function getTsNode(node, tsParseResult) { return tsNode; } -function throwErrorForInvalidNodes(tsParseResult, options) { +async function throwErrorForInvalidNodes(tsParseResult, options) { if ( - // decorators - // abstract properties - // declare in accessor - // modifiers on type parameter - !/@|abstract|declare|interface/.test(options.originalText) + // decorators and modifiers + !new RegExp( + [ + "@", + "abstract", + "accessor", + "async", + "const", + "declare", + "default", + "export", + "static", + "in", + "out", + "override", + "public", + "private", + "protected", + "readonly", + ].join("|") + ).test(options.originalText) ) { return; } + if (!ts) { + ({ default: ts } = await import("typescript")); + } + visitNode(tsParseResult.ast, (esTreeNode) => { const tsNode = getTsNode(esTreeNode, tsParseResult); if (!tsNode) { return; } - throwErrorForInvalidDeclare(tsNode, esTreeNode); throwErrorForInvalidDecorator(tsNode); throwErrorForInvalidAbstractProperty(tsNode, esTreeNode); - throwErrorForInvalidModifierOnTypeParameter(tsNode, esTreeNode); + throwErrorForInvalidModifier(tsNode); }); } diff --git a/src/language-js/parse/typescript.js b/src/language-js/parse/typescript.js index 2bc351280..e1c7763e6 100644 --- a/src/language-js/parse/typescript.js +++ b/src/language-js/parse/typescript.js @@ -57,7 +57,7 @@ async function parse(text, options = {}) { options.originalText = text; - throwErrorForInvalidNodes(result, options); + await throwErrorForInvalidNodes(result, options); return postprocess(result.ast, options); } diff --git a/src/language-js/print/class.js b/src/language-js/print/class.js index 41d2ae2b5..5dd0bd0e8 100644 --- a/src/language-js/print/class.js +++ b/src/language-js/print/class.js @@ -165,14 +165,6 @@ function printClassMethod(path, options, print) { if (node.accessibility) { parts.push(node.accessibility + " "); } - // "readonly" and "declare" are supported by only "babel-ts" - // https://github.com/prettier/prettier/issues/9760 - if (node.readonly) { - parts.push("readonly "); - } - if (node.declare) { - parts.push("declare "); - } if (node.static) { parts.push("static "); diff --git a/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap index 66304e422..a93ba4a55 100644 --- a/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/errors/typescript/__snapshots__/jsfmt.spec.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`declare-getter.ts [typescript] format 1`] = ` -"'declare' is not allowed in getters. (1:12) +"'declare' modifier cannot appear on class elements of this kind. (1:12) > 1 | class Foo { | ^ > 2 | declare get foo() @@ -11,7 +11,7 @@ exports[`declare-getter.ts [typescript] format 1`] = ` `; exports[`declare-setter.ts [typescript] format 1`] = ` -"'declare' is not allowed in setters. (1:12) +"'declare' modifier cannot appear on class elements of this kind. (1:12) > 1 | class Foo { | ^ > 2 | declare set foo(v) @@ -94,78 +94,6 @@ exports[`snippet: #5 [typescript] format 1`] = ` | ^" `; -exports[`snippet: #6 [typescript] format 1`] = ` -"This modifier cannot appear on a type member (1:16) -> 1 | interface Foo { - | ^ -> 2 | abstract e(); - | ^^^^^^^^^^^ - 3 | }" -`; - -exports[`snippet: #7 [typescript] format 1`] = ` -"This modifier cannot appear on a type member (1:16) -> 1 | interface Foo { - | ^ -> 2 | declare e(); - | ^^^^^^^^^^ - 3 | }" -`; - -exports[`snippet: #8 [typescript] format 1`] = ` -"This modifier cannot appear on a type member (1:16) -> 1 | interface Foo { - | ^ -> 2 | export e(); - | ^^^^^^^^^ - 3 | }" -`; - -exports[`snippet: #9 [typescript] format 1`] = ` -"This modifier cannot appear on a type member (1:16) -> 1 | interface Foo { - | ^ -> 2 | static e(); - | ^^^^^^^^^ - 3 | }" -`; - -exports[`snippet: #10 [typescript] format 1`] = ` -"This modifier cannot appear on a type member (1:16) -> 1 | interface Foo { - | ^ -> 2 | private e(); - | ^^^^^^^^^^ - 3 | }" -`; - -exports[`snippet: #11 [typescript] format 1`] = ` -"This modifier cannot appear on a type member (1:16) -> 1 | interface Foo { - | ^ -> 2 | protected e(); - | ^^^^^^^^^^^^ - 3 | }" -`; - -exports[`snippet: #12 [typescript] format 1`] = ` -"This modifier cannot appear on a type member (1:16) -> 1 | interface Foo { - | ^ -> 2 | public e(); - | ^^^^^^^^^ - 3 | }" -`; - -exports[`snippet: #13 [typescript] format 1`] = ` -"This modifier cannot appear on a type member (1:16) -> 1 | interface Foo { - | ^ -> 2 | readonly e(); - | ^^^^^^^^^^^ - 3 | }" -`; - exports[`value-of-abstract-property.ts [typescript] format 1`] = ` "Abstract property cannot have an initializer (2:3) 1 | abstract class Foo { diff --git a/tests/format/misc/errors/typescript/babel-ts/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/typescript/babel-ts/__snapshots__/jsfmt.spec.js.snap index 839762482..c0cb2df8c 100644 --- a/tests/format/misc/errors/typescript/babel-ts/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/errors/typescript/babel-ts/__snapshots__/jsfmt.spec.js.snap @@ -43,67 +43,3 @@ exports[`snippet: #2 [babel-ts] format 1`] = ` > 1 | foo = '100'; | ^" `; - -exports[`snippet: #3 [babel-ts] format 1`] = ` -"'abstract' modifier cannot appear on a type member. (2:3) - 1 | interface Foo { -> 2 | abstract e(); - | ^ - 3 | }" -`; - -exports[`snippet: #4 [babel-ts] format 1`] = ` -"'declare' modifier cannot appear on a type member. (2:3) - 1 | interface Foo { -> 2 | declare e(); - | ^ - 3 | }" -`; - -exports[`snippet: #5 [babel-ts] format 1`] = ` -"Unexpected token, expected ";" (2:10) - 1 | interface Foo { -> 2 | export e(); - | ^ - 3 | }" -`; - -exports[`snippet: #6 [babel-ts] format 1`] = ` -"'static' modifier cannot appear on a type member. (2:3) - 1 | interface Foo { -> 2 | static e(); - | ^ - 3 | }" -`; - -exports[`snippet: #7 [babel-ts] format 1`] = ` -"'private' modifier cannot appear on a type member. (2:3) - 1 | interface Foo { -> 2 | private e(); - | ^ - 3 | }" -`; - -exports[`snippet: #8 [babel-ts] format 1`] = ` -"'protected' modifier cannot appear on a type member. (2:3) - 1 | interface Foo { -> 2 | protected e(); - | ^ - 3 | }" -`; - -exports[`snippet: #9 [babel-ts] format 1`] = ` -"'public' modifier cannot appear on a type member. (2:3) - 1 | interface Foo { -> 2 | public e(); - | ^ - 3 | }" -`; - -exports[`snippet: #10 [babel-ts] format 1`] = ` -"'readonly' modifier can only appear on a property declaration or index signature. (2:3) - 1 | interface Foo { -> 2 | readonly e(); - | ^ - 3 | }" -`; diff --git a/tests/format/misc/errors/typescript/babel-ts/jsfmt.spec.js b/tests/format/misc/errors/typescript/babel-ts/jsfmt.spec.js index d418fe69f..c4dcd3b77 100644 --- a/tests/format/misc/errors/typescript/babel-ts/jsfmt.spec.js +++ b/tests/format/misc/errors/typescript/babel-ts/jsfmt.spec.js @@ -1,5 +1,3 @@ -import { outdent } from "outdent"; - run_spec( { importMeta: import.meta, @@ -7,22 +5,6 @@ run_spec( "foo as any = 10;", "({ a: b as any = 2000 } = x);", "foo = '100';", - ...[ - "abstract", - "declare", - "export", - "static", - "private", - "protected", - "public", - "readonly", - ].map( - (modifier) => outdent` - interface Foo { - ${modifier} e(); - } - ` - ), ], }, ["babel-ts"] diff --git a/tests/format/misc/errors/typescript/jsfmt.spec.js b/tests/format/misc/errors/typescript/jsfmt.spec.js index 3c9f2fa56..8cfd9c7b4 100644 --- a/tests/format/misc/errors/typescript/jsfmt.spec.js +++ b/tests/format/misc/errors/typescript/jsfmt.spec.js @@ -1,5 +1,3 @@ -import { outdent } from "outdent"; - run_spec( { importMeta: import.meta, @@ -10,22 +8,6 @@ run_spec( 'let x4 =
{"foo"}>
;', 'let x5 =
}{"foo"}
;', 'let x6 =
>{"foo"}
;', - ...[ - "abstract", - "declare", - "export", - "static", - "private", - "protected", - "public", - "readonly", - ].map( - (modifier) => outdent` - interface Foo { - ${modifier} e(); - } - ` - ), ], }, ["typescript"] diff --git a/tests/format/misc/errors/typescript/modifiers/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/typescript/modifiers/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..0654c7847 --- /dev/null +++ b/tests/format/misc/errors/typescript/modifiers/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,1186 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`snippet: #0 [babel-ts] format 1`] = ` +"'abstract' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | abstract method(); + | ^ + 3 | }" +`; + +exports[`snippet: #0 [typescript] format 1`] = ` +"'abstract' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | abstract method(); + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #1 [babel-ts] format 1`] = ` +"'abstract' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | abstract property; + | ^ + 3 | }" +`; + +exports[`snippet: #1 [typescript] format 1`] = ` +"'abstract' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | abstract property; + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #2 [babel-ts] format 1`] = ` +"'abstract' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | abstract [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #2 [typescript] format 1`] = ` +"'abstract' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | abstract [index: string]: number + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #3 [babel-ts] format 1`] = ` +"'abstract' modifier cannot appear on a type member. (2:3) + 1 | const foo: { +> 2 | abstract [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #3 [typescript] format 1`] = ` +"'abstract' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | abstract [index: string] : string + | ^^^^^^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #4 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:12) + 1 | interface Foo { +> 2 | accessor method(); + | ^ + 3 | }" +`; + +exports[`snippet: #4 [typescript] format 1`] = ` +"'accessor' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | accessor method(); + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #5 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:12) + 1 | interface Foo { +> 2 | accessor property; + | ^ + 3 | }" +`; + +exports[`snippet: #5 [typescript] format 1`] = ` +"'accessor' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | accessor property; + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #6 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:12) + 1 | interface Foo { +> 2 | accessor [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #6 [typescript] format 1`] = ` +"'accessor' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | accessor [index: string]: number + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #7 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:12) + 1 | const foo: { +> 2 | accessor [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #7 [typescript] format 1`] = ` +"'accessor' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | accessor [index: string] : string + | ^^^^^^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #8 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:9) + 1 | interface Foo { +> 2 | async method(); + | ^ + 3 | }" +`; + +exports[`snippet: #8 [typescript] format 1`] = ` +"'async' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | async method(); + | ^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #9 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:9) + 1 | interface Foo { +> 2 | async property; + | ^ + 3 | }" +`; + +exports[`snippet: #9 [typescript] format 1`] = ` +"'async' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | async property; + | ^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #10 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:9) + 1 | interface Foo { +> 2 | async [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #10 [typescript] format 1`] = ` +"'async' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | async [index: string]: number + | ^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #11 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:9) + 1 | const foo: { +> 2 | async [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #11 [typescript] format 1`] = ` +"'async' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | async [index: string] : string + | ^^^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #12 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:9) + 1 | interface Foo { +> 2 | const method(); + | ^ + 3 | }" +`; + +exports[`snippet: #12 [typescript] format 1`] = ` +"';' expected. (2:9) + 1 | interface Foo { +> 2 | const method(); + | ^ + 3 | }" +`; + +exports[`snippet: #13 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:9) + 1 | interface Foo { +> 2 | const property; + | ^ + 3 | }" +`; + +exports[`snippet: #13 [typescript] format 1`] = ` +"';' expected. (2:9) + 1 | interface Foo { +> 2 | const property; + | ^ + 3 | }" +`; + +exports[`snippet: #14 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:9) + 1 | interface Foo { +> 2 | const [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #14 [typescript] format 1`] = ` +"';' expected. (2:9) + 1 | interface Foo { +> 2 | const [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #15 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:9) + 1 | const foo: { +> 2 | const [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #15 [typescript] format 1`] = ` +"';' expected. (2:9) + 1 | const foo: { +> 2 | const [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #16 [babel-ts] format 1`] = ` +"'declare' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | declare method(); + | ^ + 3 | }" +`; + +exports[`snippet: #16 [typescript] format 1`] = ` +"'declare' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | declare method(); + | ^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #17 [babel-ts] format 1`] = ` +"'declare' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | declare property; + | ^ + 3 | }" +`; + +exports[`snippet: #17 [typescript] format 1`] = ` +"'declare' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | declare property; + | ^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #18 [babel-ts] format 1`] = ` +"'declare' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | declare [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #18 [typescript] format 1`] = ` +"'declare' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | declare [index: string]: number + | ^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #19 [babel-ts] format 1`] = ` +"'declare' modifier cannot appear on a type member. (2:3) + 1 | const foo: { +> 2 | declare [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #19 [typescript] format 1`] = ` +"'declare' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | declare [index: string] : string + | ^^^^^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #20 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:11) + 1 | interface Foo { +> 2 | default method(); + | ^ + 3 | }" +`; + +exports[`snippet: #20 [typescript] format 1`] = ` +"';' expected. (2:11) + 1 | interface Foo { +> 2 | default method(); + | ^ + 3 | }" +`; + +exports[`snippet: #21 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:11) + 1 | interface Foo { +> 2 | default property; + | ^ + 3 | }" +`; + +exports[`snippet: #21 [typescript] format 1`] = ` +"';' expected. (2:11) + 1 | interface Foo { +> 2 | default property; + | ^ + 3 | }" +`; + +exports[`snippet: #22 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:11) + 1 | interface Foo { +> 2 | default [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #22 [typescript] format 1`] = ` +"';' expected. (2:11) + 1 | interface Foo { +> 2 | default [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #23 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:11) + 1 | const foo: { +> 2 | default [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #23 [typescript] format 1`] = ` +"';' expected. (2:11) + 1 | const foo: { +> 2 | default [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #24 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:10) + 1 | interface Foo { +> 2 | export method(); + | ^ + 3 | }" +`; + +exports[`snippet: #24 [typescript] format 1`] = ` +"'export' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | export method(); + | ^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #25 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:10) + 1 | interface Foo { +> 2 | export property; + | ^ + 3 | }" +`; + +exports[`snippet: #25 [typescript] format 1`] = ` +"'export' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | export property; + | ^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #26 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:10) + 1 | interface Foo { +> 2 | export [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #26 [typescript] format 1`] = ` +"'export' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | export [index: string]: number + | ^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #27 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:10) + 1 | const foo: { +> 2 | export [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #27 [typescript] format 1`] = ` +"'export' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | export [index: string] : string + | ^^^^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #28 [babel-ts] format 1`] = ` +"'static' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | static method(); + | ^ + 3 | }" +`; + +exports[`snippet: #28 [typescript] format 1`] = ` +"'static' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | static method(); + | ^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #29 [babel-ts] format 1`] = ` +"'static' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | static property; + | ^ + 3 | }" +`; + +exports[`snippet: #29 [typescript] format 1`] = ` +"'static' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | static property; + | ^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #30 [babel-ts] format 1`] = ` +"'static' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | static [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #30 [typescript] format 1`] = ` +"'static' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | static [index: string]: number + | ^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #31 [babel-ts] format 1`] = ` +"'static' modifier cannot appear on a type member. (2:3) + 1 | const foo: { +> 2 | static [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #31 [typescript] format 1`] = ` +"'static' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | static [index: string] : string + | ^^^^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #32 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:6) + 1 | interface Foo { +> 2 | in method(); + | ^ + 3 | }" +`; + +exports[`snippet: #32 [typescript] format 1`] = ` +"'in' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | in method(); + | ^^^^^ + 3 | }" +`; + +exports[`snippet: #33 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:6) + 1 | interface Foo { +> 2 | in property; + | ^ + 3 | }" +`; + +exports[`snippet: #33 [typescript] format 1`] = ` +"'in' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | in property; + | ^^^^^ + 3 | }" +`; + +exports[`snippet: #34 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:6) + 1 | interface Foo { +> 2 | in [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #34 [typescript] format 1`] = ` +"'in' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | in [index: string]: number + | ^^^^^ + 3 | }" +`; + +exports[`snippet: #35 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:6) + 1 | const foo: { +> 2 | in [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #35 [typescript] format 1`] = ` +"'in' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | in [index: string] : string + | ^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #36 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:7) + 1 | interface Foo { +> 2 | out method(); + | ^ + 3 | }" +`; + +exports[`snippet: #36 [typescript] format 1`] = ` +"'out' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | out method(); + | ^^^^^^ + 3 | }" +`; + +exports[`snippet: #37 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:7) + 1 | interface Foo { +> 2 | out property; + | ^ + 3 | }" +`; + +exports[`snippet: #37 [typescript] format 1`] = ` +"'out' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | out property; + | ^^^^^^ + 3 | }" +`; + +exports[`snippet: #38 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:7) + 1 | interface Foo { +> 2 | out [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #38 [typescript] format 1`] = ` +"'out' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | out [index: string]: number + | ^^^^^^ + 3 | }" +`; + +exports[`snippet: #39 [babel-ts] format 1`] = ` +"Unexpected token, expected ";" (2:7) + 1 | const foo: { +> 2 | out [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #39 [typescript] format 1`] = ` +"'out' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | out [index: string] : string + | ^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #40 [babel-ts] format 1`] = ` +"'override' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | override method(); + | ^ + 3 | }" +`; + +exports[`snippet: #40 [typescript] format 1`] = ` +"'override' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | override method(); + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #41 [babel-ts] format 1`] = ` +"'override' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | override property; + | ^ + 3 | }" +`; + +exports[`snippet: #41 [typescript] format 1`] = ` +"'override' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | override property; + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #42 [babel-ts] format 1`] = ` +"'override' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | override [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #42 [typescript] format 1`] = ` +"'override' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | override [index: string]: number + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #43 [babel-ts] format 1`] = ` +"'override' modifier cannot appear on a type member. (2:3) + 1 | const foo: { +> 2 | override [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #43 [typescript] format 1`] = ` +"'override' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | override [index: string] : string + | ^^^^^^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #44 [babel-ts] format 1`] = ` +"'public' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | public method(); + | ^ + 3 | }" +`; + +exports[`snippet: #44 [typescript] format 1`] = ` +"'public' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | public method(); + | ^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #45 [babel-ts] format 1`] = ` +"'public' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | public property; + | ^ + 3 | }" +`; + +exports[`snippet: #45 [typescript] format 1`] = ` +"'public' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | public property; + | ^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #46 [babel-ts] format 1`] = ` +"'public' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | public [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #46 [typescript] format 1`] = ` +"'public' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | public [index: string]: number + | ^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #47 [babel-ts] format 1`] = ` +"'public' modifier cannot appear on a type member. (2:3) + 1 | const foo: { +> 2 | public [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #47 [typescript] format 1`] = ` +"'public' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | public [index: string] : string + | ^^^^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #48 [babel-ts] format 1`] = ` +"'private' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | private method(); + | ^ + 3 | }" +`; + +exports[`snippet: #48 [typescript] format 1`] = ` +"'private' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | private method(); + | ^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #49 [babel-ts] format 1`] = ` +"'private' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | private property; + | ^ + 3 | }" +`; + +exports[`snippet: #49 [typescript] format 1`] = ` +"'private' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | private property; + | ^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #50 [babel-ts] format 1`] = ` +"'private' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | private [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #50 [typescript] format 1`] = ` +"'private' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | private [index: string]: number + | ^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #51 [babel-ts] format 1`] = ` +"'private' modifier cannot appear on a type member. (2:3) + 1 | const foo: { +> 2 | private [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #51 [typescript] format 1`] = ` +"'private' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | private [index: string] : string + | ^^^^^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #52 [babel-ts] format 1`] = ` +"'protected' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | protected method(); + | ^ + 3 | }" +`; + +exports[`snippet: #52 [typescript] format 1`] = ` +"'protected' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | protected method(); + | ^^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #53 [babel-ts] format 1`] = ` +"'protected' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | protected property; + | ^ + 3 | }" +`; + +exports[`snippet: #53 [typescript] format 1`] = ` +"'protected' modifier cannot appear on a type member (1:16) +> 1 | interface Foo { + | ^ +> 2 | protected property; + | ^^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #54 [babel-ts] format 1`] = ` +"'protected' modifier cannot appear on a type member. (2:3) + 1 | interface Foo { +> 2 | protected [index: string]: number + | ^ + 3 | }" +`; + +exports[`snippet: #54 [typescript] format 1`] = ` +"'protected' modifier cannot appear on an index signature (1:16) +> 1 | interface Foo { + | ^ +> 2 | protected [index: string]: number + | ^^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #55 [babel-ts] format 1`] = ` +"'protected' modifier cannot appear on a type member. (2:3) + 1 | const foo: { +> 2 | protected [index: string] : string + | ^ + 3 | } = {};" +`; + +exports[`snippet: #55 [typescript] format 1`] = ` +"'protected' modifier cannot appear on an index signature (1:13) +> 1 | const foo: { + | ^ +> 2 | protected [index: string] : string + | ^^^^^^^^^^^^ + 3 | } = {};" +`; + +exports[`snippet: #56 [babel-ts] format 1`] = ` +"'readonly' modifier can only appear on a property declaration or index signature. (2:3) + 1 | interface Foo { +> 2 | readonly method(); + | ^ + 3 | }" +`; + +exports[`snippet: #56 [typescript] format 1`] = ` +"'readonly' modifier can only appear on a property declaration or index signature. (1:16) +> 1 | interface Foo { + | ^ +> 2 | readonly method(); + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #57 [babel-ts] format 1`] = ` +"'abstract' modifier cannot appear on a type parameter. (1:15) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #57 [typescript] format 1`] = ` +"'abstract' modifier cannot appear on a type parameter (1:15) +> 1 | interface Foo {} + | ^^^^^^^^" +`; + +exports[`snippet: #58 [babel-ts] format 1`] = ` +"Unexpected token, expected "," (1:24) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #58 [typescript] format 1`] = ` +"'accessor' modifier cannot appear on a type parameter (1:15) +> 1 | interface Foo {} + | ^^^^^^^^" +`; + +exports[`snippet: #59 [babel-ts] format 1`] = ` +"Unexpected token, expected "," (1:21) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #59 [typescript] format 1`] = ` +"'async' modifier cannot appear on a type parameter (1:15) +> 1 | interface Foo {} + | ^^^^^" +`; + +exports[`snippet: #60 [babel-ts] format 1`] = ` +"Unexpected token, expected "," (1:21) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #60 [typescript] format 1`] = ` +"Type parameter declaration expected. (1:15) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #61 [babel-ts] format 1`] = ` +"'declare' modifier cannot appear on a type parameter. (1:15) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #61 [typescript] format 1`] = ` +"'declare' modifier cannot appear on a type parameter (1:15) +> 1 | interface Foo {} + | ^^^^^^^" +`; + +exports[`snippet: #62 [babel-ts] format 1`] = ` +"Unexpected token, expected "," (1:23) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #62 [typescript] format 1`] = ` +"Type parameter declaration expected. (1:15) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #63 [babel-ts] format 1`] = ` +"Unexpected token, expected "," (1:22) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #63 [typescript] format 1`] = ` +"Type parameter declaration expected. (1:15) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #64 [babel-ts] format 1`] = ` +"Unexpected token, expected "," (1:22) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #64 [typescript] format 1`] = ` +"'static' modifier cannot appear on a type parameter (1:15) +> 1 | interface Foo {} + | ^^^^^^" +`; + +exports[`snippet: #65 [babel-ts] format 1`] = ` +"'override' modifier cannot appear on a type parameter. (1:15) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #65 [typescript] format 1`] = ` +"'override' modifier cannot appear on a type parameter (1:15) +> 1 | interface Foo {} + | ^^^^^^^^" +`; + +exports[`snippet: #66 [babel-ts] format 1`] = ` +"'public' modifier cannot appear on a type parameter. (1:15) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #66 [typescript] format 1`] = ` +"'public' modifier cannot appear on a type parameter (1:15) +> 1 | interface Foo {} + | ^^^^^^" +`; + +exports[`snippet: #67 [babel-ts] format 1`] = ` +"'private' modifier cannot appear on a type parameter. (1:15) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #67 [typescript] format 1`] = ` +"'private' modifier cannot appear on a type parameter (1:15) +> 1 | interface Foo {} + | ^^^^^^^" +`; + +exports[`snippet: #68 [babel-ts] format 1`] = ` +"'protected' modifier cannot appear on a type parameter. (1:15) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #68 [typescript] format 1`] = ` +"'protected' modifier cannot appear on a type parameter (1:15) +> 1 | interface Foo {} + | ^^^^^^^^^" +`; + +exports[`snippet: #69 [babel-ts] format 1`] = ` +"'readonly' modifier cannot appear on a type parameter. (1:15) +> 1 | interface Foo {} + | ^" +`; + +exports[`snippet: #69 [typescript] format 1`] = ` +"'readonly' modifier cannot appear on a type parameter (1:15) +> 1 | interface Foo {} + | ^^^^^^^^" +`; + +exports[`snippet: #70 [babel-ts] format 1`] = ` +"Class methods cannot have the 'declare' modifier. (2:3) + 1 | class Foo { +> 2 | declare method() {} + | ^ + 3 | }" +`; + +exports[`snippet: #70 [typescript] format 1`] = ` +"'declare' modifier cannot appear on class elements of this kind. (1:12) +> 1 | class Foo { + | ^ +> 2 | declare method() {} + | ^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #71 [babel-ts] format 1`] = ` +"Class methods cannot have the 'readonly' modifier. (2:3) + 1 | class Foo { +> 2 | readonly method() {} + | ^ + 3 | }" +`; + +exports[`snippet: #71 [typescript] format 1`] = ` +"'readonly' modifier can only appear on a property declaration or index signature. (1:12) +> 1 | class Foo { + | ^ +> 2 | readonly method() {} + | ^^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #72 [babel-ts] format 1`] = ` +"'declare' is not allowed in getters. (2:3) + 1 | class Foo { +> 2 | declare get getter() {} + | ^ + 3 | }" +`; + +exports[`snippet: #72 [typescript] format 1`] = ` +"'declare' modifier cannot appear on class elements of this kind. (1:12) +> 1 | class Foo { + | ^ +> 2 | declare get getter() {} + | ^^^^^^^^^^ + 3 | }" +`; + +exports[`snippet: #73 [babel-ts] format 1`] = ` +"'declare' is not allowed in setters. (2:3) + 1 | class Foo { +> 2 | declare set setter(v) {} + | ^ + 3 | }" +`; + +exports[`snippet: #73 [typescript] format 1`] = ` +"'declare' modifier cannot appear on class elements of this kind. (1:12) +> 1 | class Foo { + | ^ +> 2 | declare set setter(v) {} + | ^^^^^^^^^^ + 3 | }" +`; diff --git a/tests/format/misc/errors/typescript/modifiers/jsfmt.spec.js b/tests/format/misc/errors/typescript/modifiers/jsfmt.spec.js new file mode 100644 index 000000000..d90d90834 --- /dev/null +++ b/tests/format/misc/errors/typescript/modifiers/jsfmt.spec.js @@ -0,0 +1,93 @@ +import { outdent } from "outdent"; + +const POSSIBLE_MODIFIERS = [ + "abstract", + "accessor", + "async", + "const", + "declare", + "default", + "export", + "static", + "in", + "out", + "override", + "public", + "private", + "protected", + "readonly", +]; + +run_spec( + { + importMeta: import.meta, + snippets: [ + // Only `readonly` allowed in some places + ...POSSIBLE_MODIFIERS.filter( + (modifier) => modifier !== "readonly" + ).flatMap((modifier) => [ + outdent` + interface Foo { + ${modifier} method(); + } + `, + outdent` + interface Foo { + ${modifier} property; + } + `, + // index signature + outdent` + interface Foo { + ${modifier} [index: string]: number + } + `, + outdent` + const foo: { + ${modifier} [index: string] : string + } = {}; + `, + ]), + outdent` + interface Foo { + readonly method(); + } + `, + + // TODO[@fisker]: Fix these tests + // ...["abstract", "static", "private", "protected", "public"].map( + // (modifier) => + // outdent` + // module Foo { + // ${modifier} module Bar {} + // } + // ` + // ), + + // Only `in` and `out` allowed in type parameter + ...POSSIBLE_MODIFIERS.filter( + (modifier) => modifier !== "in" && modifier !== "out" + ).map((modifier) => `interface Foo<${modifier} T> {}`), + + ...["declare", "readonly"].map( + (modifier) => + outdent` + class Foo { + ${modifier} method() {} + } + ` + ), + outdent` + class Foo { + declare get getter() {} + } + `, + outdent` + class Foo { + declare set setter(v) {} + } + `, + ], + }, + ["babel-ts", "typescript"] +); diff --git a/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap index 88600baab..9eec9daa3 100644 --- a/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/typescript-babel-only/__snapshots__/jsfmt.spec.js.snap @@ -20,26 +20,6 @@ class C { ================================================================================ `; -exports[`invalid-modifiers.ts format 1`] = ` -====================================options===================================== -parsers: ["babel-ts"] -printWidth: 80 - | printWidth -=====================================input====================================== -class Bar { - declare e() {}; - readonly g() {}; -} - -=====================================output===================================== -class Bar { - declare e() {} - readonly g() {} -} - -================================================================================ -`; - exports[`parenthesized-decorators-call-expression.ts format 1`] = ` ====================================options===================================== parsers: ["babel-ts"] diff --git a/tests/format/misc/typescript-babel-only/invalid-modifiers.ts b/tests/format/misc/typescript-babel-only/invalid-modifiers.ts deleted file mode 100644 index 34b1182c2..000000000 --- a/tests/format/misc/typescript-babel-only/invalid-modifiers.ts +++ /dev/null @@ -1,4 +0,0 @@ -class Bar { - declare e() {}; - readonly g() {}; -} diff --git a/tests/format/misc/typescript-only/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/typescript-only/__snapshots__/jsfmt.spec.js.snap index fb9a7c9b1..9bd328a5e 100644 --- a/tests/format/misc/typescript-only/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/typescript-only/__snapshots__/jsfmt.spec.js.snap @@ -51,28 +51,6 @@ await 0; ================================================================================ `; -exports[`invalid-modifiers.ts format 1`] = ` -====================================options===================================== -parsers: ["typescript"] -printWidth: 80 - | printWidth -=====================================input====================================== -class Bar { - declare e() {}; - abstract f() {}; - readonly g() {}; -} - -=====================================output===================================== -class Bar { - e() {} - abstract f() {} - g() {} -} - -================================================================================ -`; - exports[`parenthesized-decorators-call-expression.ts format 1`] = ` ====================================options===================================== parsers: ["typescript"] diff --git a/tests/format/misc/typescript-only/invalid-modifiers.ts b/tests/format/misc/typescript-only/invalid-modifiers.ts deleted file mode 100644 index 9f287a99f..000000000 --- a/tests/format/misc/typescript-only/invalid-modifiers.ts +++ /dev/null @@ -1,5 +0,0 @@ -class Bar { - declare e() {}; - abstract f() {}; - readonly g() {}; -} diff --git a/tests/format/typescript/keywords/__snapshots__/jsfmt.spec.js.snap b/tests/format/typescript/keywords/__snapshots__/jsfmt.spec.js.snap index e3ee77eac..8336bced7 100644 --- a/tests/format/typescript/keywords/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/typescript/keywords/__snapshots__/jsfmt.spec.js.snap @@ -1,14 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`keywords.ts [babel-ts] format 1`] = ` -"Unexpected token, expected "{" (9:12) - 7 | - 8 | // Apparently this parses :P -> 9 | export private public protected static readonly abstract async enum X { } - | ^ - 10 | - 11 | interface x { - 12 | export private static readonly [x: any]: any;" +"Missing semicolon. (4:11) + 2 | + 3 | module Y4 { +> 4 | public enum Color { Blue, Red } + | ^ + 5 | } + 6 | + 7 | module YY3 {" `; exports[`keywords.ts format 1`] = ` @@ -19,19 +19,6 @@ printWidth: 80 =====================================input====================================== // All of these should be an error -module Y3 { - public module Module { - class A { s: string } - } - - // Apparently this parses :P - export private public protected static readonly abstract async enum X { } - - interface x { - export private static readonly [x: any]: any; - } -} - module Y4 { public enum Color { Blue, Red } } @@ -59,21 +46,6 @@ module YYY4 { =====================================output===================================== // All of these should be an error -module Y3 { - public module Module { - class A { - s: string; - } - } - - // Apparently this parses :P - export private public protected static readonly abstract async enum X {} - - interface x { - export private static readonly [x: any]: any; - } -} - module Y4 { public enum Color { Blue, @@ -195,17 +167,6 @@ class G { ================================================================================ `; -exports[`module.ts [babel-ts] format 1`] = ` -"Unexpected token, expected "{" (7:10) - 5 | - 6 | // Apparently this parses :P -> 7 | export private public protected static readonly abstract async enum X { } - | ^ - 8 | - 9 | interface x { - 10 | export private static readonly [x: any]: any;" -`; - exports[`module.ts format 1`] = ` ====================================options===================================== parsers: ["typescript"] @@ -213,31 +174,29 @@ printWidth: 80 | printWidth =====================================input====================================== module Y3 { - public module Module { + module Module { class A { s: string } } - // Apparently this parses :P - export private public protected static readonly abstract async enum X { } + export enum X { } interface x { - export private static readonly [x: any]: any; + readonly [x: any]: any; } } =====================================output===================================== module Y3 { - public module Module { + module Module { class A { s: string; } } - // Apparently this parses :P - export private public protected static readonly abstract async enum X {} + export enum X {} interface x { - export private static readonly [x: any]: any; + readonly [x: any]: any; } } diff --git a/tests/format/typescript/keywords/jsfmt.spec.js b/tests/format/typescript/keywords/jsfmt.spec.js index 83b8f4c9f..c07a43dfb 100644 --- a/tests/format/typescript/keywords/jsfmt.spec.js +++ b/tests/format/typescript/keywords/jsfmt.spec.js @@ -1,3 +1,3 @@ run_spec(import.meta, ["typescript"], { - errors: { "babel-ts": ["module.ts", "keywords.ts"] }, + errors: { "babel-ts": ["keywords.ts"] }, }); diff --git a/tests/format/typescript/keywords/keywords.ts b/tests/format/typescript/keywords/keywords.ts index 9dd210282..25a76af75 100644 --- a/tests/format/typescript/keywords/keywords.ts +++ b/tests/format/typescript/keywords/keywords.ts @@ -1,18 +1,5 @@ // All of these should be an error -module Y3 { - public module Module { - class A { s: string } - } - - // Apparently this parses :P - export private public protected static readonly abstract async enum X { } - - interface x { - export private static readonly [x: any]: any; - } -} - module Y4 { public enum Color { Blue, Red } } diff --git a/tests/format/typescript/keywords/module.ts b/tests/format/typescript/keywords/module.ts index f4bd5c9f5..d9e253d35 100644 --- a/tests/format/typescript/keywords/module.ts +++ b/tests/format/typescript/keywords/module.ts @@ -1,12 +1,11 @@ module Y3 { - public module Module { + module Module { class A { s: string } } - // Apparently this parses :P - export private public protected static readonly abstract async enum X { } + export enum X { } interface x { - export private static readonly [x: any]: any; + readonly [x: any]: any; } }