From 27ad69d43fb38ab1ec1839f8ca407493f95229af Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Tue, 23 Aug 2016 23:29:23 +0200 Subject: [PATCH] Fix declare class with qualified type identifier (#97) This makes declare class extends behave the same way as in flow The ast-token after the extends keyword, might be either Identifier or QualifiedTypeIdentifier To do that this commits splits the parseGenericType into two functions, one for parsing genericType and on for qualifiedTypeIdentifier --- src/plugins/flow.js | 26 ++- .../flow/declare-statements/16/actual.js | 1 + .../flow/declare-statements/16/expected.json | 185 ++++++++++++++++++ 3 files changed, 203 insertions(+), 9 deletions(-) create mode 100644 test/fixtures/flow/declare-statements/16/actual.js create mode 100644 test/fixtures/flow/declare-statements/16/expected.json diff --git a/src/plugins/flow.js b/src/plugins/flow.js index 7172f31e70..69139859fc 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -165,7 +165,7 @@ pp.flowParseInterfaceish = function (node, allowStatic) { pp.flowParseInterfaceExtends = function () { let node = this.startNode(); - node.id = this.parseIdentifier(); + node.id = this.flowParseQualifiedTypeIdentifier(); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterInstantiation(); } else { @@ -394,18 +394,26 @@ pp.flowObjectTypeSemicolon = function () { } }; +pp.flowParseQualifiedTypeIdentifier = function (startPos, startLoc, id) { + startPos = startPos || this.state.start; + startLoc = startLoc || this.state.startLoc; + let node = id || this.parseIdentifier(); + + while (this.eat(tt.dot)) { + let node2 = this.startNodeAt(startPos, startLoc); + node2.qualification = node; + node2.id = this.parseIdentifier(); + node = this.finishNode(node2, "QualifiedTypeIdentifier"); + } + + return node; +}; + pp.flowParseGenericType = function (startPos, startLoc, id) { let node = this.startNodeAt(startPos, startLoc); node.typeParameters = null; - node.id = id; - - while (this.eat(tt.dot)) { - let node2 = this.startNodeAt(startPos, startLoc); - node2.qualification = node.id; - node2.id = this.parseIdentifier(); - node.id = this.finishNode(node2, "QualifiedTypeIdentifier"); - } + node.id = this.flowParseQualifiedTypeIdentifier(startPos, startLoc, id); if (this.isRelational("<")) { node.typeParameters = this.flowParseTypeParameterInstantiation(); diff --git a/test/fixtures/flow/declare-statements/16/actual.js b/test/fixtures/flow/declare-statements/16/actual.js new file mode 100644 index 0000000000..04861bb24a --- /dev/null +++ b/test/fixtures/flow/declare-statements/16/actual.js @@ -0,0 +1 @@ +declare class A extends C.B.D { } diff --git a/test/fixtures/flow/declare-statements/16/expected.json b/test/fixtures/flow/declare-statements/16/expected.json new file mode 100644 index 0000000000..4fbc1787d4 --- /dev/null +++ b/test/fixtures/flow/declare-statements/16/expected.json @@ -0,0 +1,185 @@ +{ + "type": "File", + "start": 0, + "end": 33, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 33 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 33, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 33 + } + }, + "sourceType": "module", + "body": [ + { + "type": "DeclareClass", + "start": 0, + "end": 33, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 33 + } + }, + "id": { + "type": "Identifier", + "start": 14, + "end": 15, + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 15 + }, + "identifierName": "A" + }, + "name": "A" + }, + "typeParameters": null, + "extends": [ + { + "type": "InterfaceExtends", + "start": 24, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 29 + } + }, + "id": { + "type": "QualifiedTypeIdentifier", + "start": 24, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 29 + } + }, + "qualification": { + "type": "QualifiedTypeIdentifier", + "start": 24, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 27 + } + }, + "qualification": { + "type": "Identifier", + "start": 24, + "end": 25, + "loc": { + "start": { + "line": 1, + "column": 24 + }, + "end": { + "line": 1, + "column": 25 + }, + "identifierName": "C" + }, + "name": "C" + }, + "id": { + "type": "Identifier", + "start": 26, + "end": 27, + "loc": { + "start": { + "line": 1, + "column": 26 + }, + "end": { + "line": 1, + "column": 27 + }, + "identifierName": "B" + }, + "name": "B" + } + }, + "id": { + "type": "Identifier", + "start": 28, + "end": 29, + "loc": { + "start": { + "line": 1, + "column": 28 + }, + "end": { + "line": 1, + "column": 29 + }, + "identifierName": "D" + }, + "name": "D" + } + }, + "typeParameters": null + } + ], + "mixins": [], + "body": { + "type": "ObjectTypeAnnotation", + "start": 30, + "end": 33, + "loc": { + "start": { + "line": 1, + "column": 30 + }, + "end": { + "line": 1, + "column": 33 + } + }, + "callProperties": [], + "properties": [], + "indexers": [] + } + } + ], + "directives": [] + } +} \ No newline at end of file