diff --git a/def/flow.ts b/def/flow.ts index 7df97cf8..94d44825 100644 --- a/def/flow.ts +++ b/def/flow.ts @@ -305,7 +305,7 @@ export default function (fork: Fork) { def("InterfaceExtends") .bases("Node") .build("id") - .field("id", def("Identifier")) + .field("id", or(def("Identifier"), def("QualifiedTypeIdentifier"))) .field("typeParameters", or(def("TypeParameterInstantiation"), null), defaults["null"]); diff --git a/gen/builders.ts b/gen/builders.ts index 3f5254ba..c2bca0c7 100644 --- a/gen/builders.ts +++ b/gen/builders.ts @@ -2122,11 +2122,11 @@ export interface InterfaceTypeAnnotationBuilder { } export interface InterfaceExtendsBuilder { - (id: K.IdentifierKind): namedTypes.InterfaceExtends; + (id: K.IdentifierKind | K.QualifiedTypeIdentifierKind): namedTypes.InterfaceExtends; from( params: { comments?: K.CommentKind[] | null, - id: K.IdentifierKind, + id: K.IdentifierKind | K.QualifiedTypeIdentifierKind, loc?: K.SourceLocationKind | null, typeParameters?: K.TypeParameterInstantiationKind | null } diff --git a/gen/namedTypes.ts b/gen/namedTypes.ts index a520ef45..7a3b5c3a 100644 --- a/gen/namedTypes.ts +++ b/gen/namedTypes.ts @@ -989,7 +989,7 @@ export namespace namedTypes { export interface InterfaceExtends extends Omit { type: "InterfaceExtends"; - id: K.IdentifierKind; + id: K.IdentifierKind | K.QualifiedTypeIdentifierKind; typeParameters?: K.TypeParameterInstantiationKind | null; } diff --git a/test/flow.ts b/test/flow.ts index daa6bd3c..6d2170cd 100644 --- a/test/flow.ts +++ b/test/flow.ts @@ -11,16 +11,16 @@ var types = forkFn([ flowDef, ]); +const parser = { + parse(code: string) { + return flowParser.parse(code, { + types: true, + }); + }, +}; + describe("flow types", function () { it("issue #242", function () { - const parser = { - parse(code: string) { - return flowParser.parse(code, { - types: true - }); - } - }; - const program = parser.parse([ "class A extends C {}", "function f() {}", @@ -46,14 +46,6 @@ describe("flow types", function () { }); it("issue #261", function () { - const parser = { - parse(code: string) { - return flowParser.parse(code, { - types: true - }); - } - }; - const program = parser.parse('declare module.exports: {};'); assert.strictEqual(program.body[0].type, 'DeclareModuleExports'); @@ -62,14 +54,6 @@ describe("flow types", function () { }); it("Explicit type arguments", function () { - const parser = { - parse(code: string) { - return flowParser.parse(code, { - types: true - }); - } - }; - const program = parser.parse([ 'test();', 'test();', @@ -128,14 +112,6 @@ describe("flow types", function () { } it("issue #294 - function declarations", function () { - const parser = { - parse(code: string) { - return require('flow-parser').parse(code, { - types: true - }); - } - }; - const program = parser.parse([ "function foo(): T { }", "let bar: T", @@ -154,14 +130,6 @@ describe("flow types", function () { }); it("issue #294 - function expressions", function () { - const parser = { - parse(code: string) { - return require('flow-parser').parse(code, { - types: true - }); - } - }; - const program = parser.parse([ "const foo = function (): T { }", "let bar: T", @@ -182,14 +150,6 @@ describe("flow types", function () { }); it("issue #294 - arrow function expressions", function () { - const parser = { - parse(code: string) { - return require('flow-parser').parse(code, { - types: true - }); - } - }; - const program = parser.parse([ "const foo = (): T => { }", "let bar: T" @@ -208,14 +168,6 @@ describe("flow types", function () { }); it("issue #294 - class declarations", function () { - const parser = { - parse(code: string) { - return require('flow-parser').parse(code, { - types: true - }); - } - }; - const program = parser.parse([ "class Foo extends Bar> { }", "let bar: T" @@ -234,14 +186,6 @@ describe("flow types", function () { }); it("issue #294 - class expressions", function () { - const parser = { - parse(code: string) { - return require('flow-parser').parse(code, { - types: true - }); - } - }; - const program = parser.parse([ "const foo = class Foo extends Bar> { }", "let bar: T" @@ -263,14 +207,6 @@ describe("flow types", function () { }); it("issue #296 - interface declarations", function () { - const parser = { - parse(code: string) { - return require('flow-parser').parse(code, { - types: true - }); - } - }; - const program = parser.parse([ "interface Foo extends Bar> { }", "let bar: T" @@ -288,4 +224,22 @@ describe("flow types", function () { } }); }); + + it("interface extends qualified name", function () { + const program = parser.parse([ + "interface I extends Module.J { }", + "declare interface I extends Module.J { }", + // Plain `class C extends A.B` gets a ClassDeclaration with superClass + // a MemberExpression. But with `declare`, it's a DeclareClass with + // `extends` containing an InterfaceExtends, much like on `interface`. + "declare class C extends React.Component<{||}> { }" + ].join("\n")); + + assertVisited(program, { + visitInterfaceExtends(path) { + types.builders.interfaceExtends.from(path.node); + this.traverse(path); + }, + }); + }); });