diff --git a/src/language-js/parse/postprocess/index.js b/src/language-js/parse/postprocess/index.js index cc07c76bc..d9b567eb6 100644 --- a/src/language-js/parse/postprocess/index.js +++ b/src/language-js/parse/postprocess/index.js @@ -112,6 +112,23 @@ function postprocess(ast, options) { } } break; + case "DeclareInterface": + case "InterfaceDeclaration": + case "TSInterfaceDeclaration": + if (isNonEmptyArray(node.mixins)) { + throwSyntaxError( + node.mixins[0], + "Interface declaration cannot have 'mixins' clause." + ); + } + if (isNonEmptyArray(node.implements)) { + throwSyntaxError( + node.implements[0], + "Interface declaration cannot have 'implements' clause." + ); + } + break; + case "TSPropertySignature": if (node.initializer) { throwSyntaxError( diff --git a/src/language-js/traverse/visitor-keys.evaluate.js b/src/language-js/traverse/visitor-keys.evaluate.js index a0181bb03..0680fbb17 100644 --- a/src/language-js/traverse/visitor-keys.evaluate.js +++ b/src/language-js/traverse/visitor-keys.evaluate.js @@ -57,6 +57,8 @@ const excludeKeys = { // TODO: Remove `types` when babel changes AST of `TupleTypeAnnotation` // Flow parser changed `.types` to `.elementTypes` https://github.com/facebook/flow/commit/5b60e6a81dc277dfab2e88fa3737a4dc9aafdcab // TupleTypeAnnotation: ["types"], + DeclareInterface: ["mixins", "implements"], + InterfaceDeclaration: ["mixins", "implements"], // TypeScript TSPropertySignature: ["initializer"], diff --git a/tests/format/misc/errors/flow/declare-export-interface/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/flow/declare-export-interface/__snapshots__/jsfmt.spec.js.snap deleted file mode 100644 index d7366192f..000000000 --- a/tests/format/misc/errors/flow/declare-export-interface/__snapshots__/jsfmt.spec.js.snap +++ /dev/null @@ -1,13 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`snippet: #0 [babel-flow] format 1`] = ` -"\`declare export interface\` is not supported. Use \`export interface\` instead. (1:16) -> 1 | declare export interface A {} - | ^" -`; - -exports[`snippet: #0 [flow] format 1`] = ` -"\`declare export interface\` is not supported. Use \`export interface\` instead. (1:16) -> 1 | declare export interface A {} - | ^^^^^^^^^" -`; diff --git a/tests/format/misc/errors/flow/declare-export-interface/jsfmt.spec.js b/tests/format/misc/errors/flow/declare-export-interface/jsfmt.spec.js deleted file mode 100644 index be0643c1b..000000000 --- a/tests/format/misc/errors/flow/declare-export-interface/jsfmt.spec.js +++ /dev/null @@ -1,7 +0,0 @@ -run_spec( - { - importMeta: import.meta, - snippets: ["declare export interface A {}"], - }, - ["flow", "babel-flow"] -); diff --git a/tests/format/misc/errors/flow/interface/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/flow/interface/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..0330abc95 --- /dev/null +++ b/tests/format/misc/errors/flow/interface/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,61 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`snippet: #0 [babel-flow] format 1`] = ` +"\`declare export interface\` is not supported. Use \`export interface\` instead. (1:16) +> 1 | declare export interface A {} + | ^" +`; + +exports[`snippet: #0 [flow] format 1`] = ` +"\`declare export interface\` is not supported. Use \`export interface\` instead. (1:16) +> 1 | declare export interface A {} + | ^^^^^^^^^" +`; + +exports[`snippet: #1 [babel-flow] format 1`] = ` +"Interface declaration cannot have 'mixins' clause. (1:20) +> 1 | interface A mixins B {} + | ^" +`; + +exports[`snippet: #1 [flow] format 1`] = ` +"Unexpected identifier, expected the token \`{\` (1:13) +> 1 | interface A mixins B {} + | ^^^^^^" +`; + +exports[`snippet: #2 [babel-flow] format 1`] = ` +"Interface declaration cannot have 'implements' clause. (1:24) +> 1 | interface A implements B {} + | ^" +`; + +exports[`snippet: #2 [flow] format 1`] = ` +"Unexpected identifier, expected the token \`{\` (1:13) +> 1 | interface A implements B {} + | ^^^^^^^^^^" +`; + +exports[`snippet: #3 [babel-flow] format 1`] = ` +"Interface declaration cannot have 'mixins' clause. (1:28) +> 1 | declare interface A mixins B {} + | ^" +`; + +exports[`snippet: #3 [flow] format 1`] = ` +"Unexpected identifier, expected the token \`{\` (1:21) +> 1 | declare interface A mixins B {} + | ^^^^^^" +`; + +exports[`snippet: #4 [babel-flow] format 1`] = ` +"Interface declaration cannot have 'implements' clause. (1:32) +> 1 | declare interface A implements B {} + | ^" +`; + +exports[`snippet: #4 [flow] format 1`] = ` +"Unexpected identifier, expected the token \`{\` (1:21) +> 1 | declare interface A implements B {} + | ^^^^^^^^^^" +`; diff --git a/tests/format/misc/errors/flow/interface/jsfmt.spec.js b/tests/format/misc/errors/flow/interface/jsfmt.spec.js new file mode 100644 index 000000000..787aab314 --- /dev/null +++ b/tests/format/misc/errors/flow/interface/jsfmt.spec.js @@ -0,0 +1,16 @@ +run_spec( + { + importMeta: import.meta, + snippets: [ + // Not allowed + "declare export interface A {}", + + // Can't have mixins nor implements + "interface A mixins B {}", + "interface A implements B {}", + "declare interface A mixins B {}", + "declare interface A implements B {}", + ], + }, + ["flow", "babel-flow"] +); diff --git a/tests/format/misc/errors/typescript/interface/__snapshots__/jsfmt.spec.js.snap b/tests/format/misc/errors/typescript/interface/__snapshots__/jsfmt.spec.js.snap index 37519d6f6..5e486bc57 100644 --- a/tests/format/misc/errors/typescript/interface/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/misc/errors/typescript/interface/__snapshots__/jsfmt.spec.js.snap @@ -11,3 +11,27 @@ exports[`snippet: #0 [typescript] format 1`] = ` > 1 | interface I { x: number = 1;} | ^" `; + +exports[`snippet: #1 [babel-ts] format 1`] = ` +"Unexpected token, expected "{" (1:13) +> 1 | interface A mixins B {} + | ^" +`; + +exports[`snippet: #1 [typescript] format 1`] = ` +"'{' expected. (1:13) +> 1 | interface A mixins B {} + | ^" +`; + +exports[`snippet: #2 [babel-ts] format 1`] = ` +"Unexpected token, expected "{" (1:13) +> 1 | interface A implements B {} + | ^" +`; + +exports[`snippet: #2 [typescript] format 1`] = ` +"Interface declaration cannot have 'implements' clause. (1:24) +> 1 | interface A implements B {} + | ^" +`; diff --git a/tests/format/misc/errors/typescript/interface/jsfmt.spec.js b/tests/format/misc/errors/typescript/interface/jsfmt.spec.js index a1d5dde7e..71ebb8528 100644 --- a/tests/format/misc/errors/typescript/interface/jsfmt.spec.js +++ b/tests/format/misc/errors/typescript/interface/jsfmt.spec.js @@ -4,6 +4,9 @@ run_spec( snippets: [ // Invalid initializer "interface I { x: number = 1;}", + // Can't have mixins nor implements + "interface A mixins B {}", + "interface A implements B {}", ], }, ["babel-ts", "typescript"] diff --git a/tests/unit/__snapshots__/visitor-keys.js.snap b/tests/unit/__snapshots__/visitor-keys.js.snap index a056505b4..7b25170c7 100644 --- a/tests/unit/__snapshots__/visitor-keys.js.snap +++ b/tests/unit/__snapshots__/visitor-keys.js.snap @@ -176,8 +176,6 @@ exports[`visitor keys estree 1`] = ` "id", "typeParameters", "extends", - "mixins", - "implements", "body", ], "DeclareModule": [ @@ -375,8 +373,6 @@ exports[`visitor keys estree 1`] = ` "id", "typeParameters", "extends", - "mixins", - "implements", "body", ], "InterfaceExtends": [