Handle flow comments with leading spaces (#9168)

* check for spaces and tabs before a flow comment

* fix issue with using string index and shift interchangably

* update tests

* Use update charcodes version

* Disallow flow-comments in flow-comments and check for unterminated comments
This commit is contained in:
Vikram Rangaraj 2018-12-13 22:10:01 -08:00 committed by Daniel Tschinder
parent b9340bc597
commit 72471aff63
25 changed files with 404 additions and 133 deletions

View File

@ -24,11 +24,11 @@
"babel-eslint": "^10.0.1",
"babel-jest": "^23.6.0",
"babel-loader": "^8.0.4",
"babel-plugin-transform-charcodes": "^0.1.0",
"babel-plugin-transform-charcodes": "^0.1.1",
"browserify": "^16.2.2",
"bundle-collapser": "^1.2.1",
"chalk": "^2.3.2",
"charcodes": "^0.1.0",
"charcodes": "^0.1.1",
"derequire": "^2.0.2",
"enhanced-resolve": "^3.0.0",
"eslint": "^5.9.0",

View File

@ -2697,21 +2697,34 @@ export default (superClass: Class<Parser>): Class<Parser> =>
super.readToken_mult_modulo(code);
}
parseTopLevel(file: N.File, program: N.Program): N.File {
const fileNode = super.parseTopLevel(file, program);
if (this.state.hasFlowComment) {
this.unexpected(null, "Unterminated flow-comment");
}
return fileNode;
}
skipBlockComment(): void {
if (
this.hasPlugin("flow") &&
this.hasPlugin("flowComments") &&
this.skipFlowComment()
) {
if (this.state.hasFlowComment) {
this.unexpected(
null,
"Cannot have a flow comment inside another flow comment",
);
}
this.hasFlowCommentCompletion();
this.state.pos += this.skipFlowComment();
this.state.hasFlowComment = true;
return;
}
let end;
if (this.hasPlugin("flow") && this.state.hasFlowComment) {
end = this.input.indexOf("*-/", (this.state.pos += 2));
const end = this.input.indexOf("*-/", (this.state.pos += 2));
if (end === -1) this.raise(this.state.pos - 2, "Unterminated comment");
this.state.pos = end + 3;
return;
@ -2721,17 +2734,32 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
skipFlowComment(): number | boolean {
const ch2 = this.input.charCodeAt(this.state.pos + 2);
const ch3 = this.input.charCodeAt(this.state.pos + 3);
const { pos } = this.state;
let shiftToFirstNonWhiteSpace = 2;
while (
[charCodes.space, charCodes.tab].includes(
this.input.charCodeAt(pos + shiftToFirstNonWhiteSpace),
)
) {
shiftToFirstNonWhiteSpace++;
}
const ch2 = this.input.charCodeAt(shiftToFirstNonWhiteSpace + pos);
const ch3 = this.input.charCodeAt(shiftToFirstNonWhiteSpace + pos + 1);
if (ch2 === charCodes.colon && ch3 === charCodes.colon) {
return 4; // check for /*::
return shiftToFirstNonWhiteSpace + 2; // check for /*::
}
if (this.input.slice(this.state.pos + 2, 14) === "flow-include") {
return 14; // check for /*flow-include
if (
this.input.slice(
shiftToFirstNonWhiteSpace + pos,
shiftToFirstNonWhiteSpace + pos + 12,
) === "flow-include"
) {
return shiftToFirstNonWhiteSpace + 12; // check for /*flow-include
}
if (ch2 === charCodes.colon && ch3 !== charCodes.colon) {
return 2; // check for /*:, advance only 2 steps
return shiftToFirstNonWhiteSpace; // check for /*:, advance up to :
}
return false;
}

View File

@ -1,3 +1,4 @@
class MyClass {
/*:: prop: string; */
/* :: foo: number; */
}

View File

@ -1,28 +1,28 @@
{
"type": "File",
"start": 0,
"end": 41,
"end": 68,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
"program": {
"type": "Program",
"start": 0,
"end": 41,
"end": 68,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
@ -32,14 +32,14 @@
{
"type": "ClassDeclaration",
"start": 0,
"end": 41,
"end": 68,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
@ -64,14 +64,14 @@
"body": {
"type": "ClassBody",
"start": 14,
"end": 41,
"end": 68,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
@ -92,6 +92,22 @@
"column": 23
}
}
},
{
"type": "CommentBlock",
"value": " :: foo: number; ",
"start": 42,
"end": 66,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 26
}
}
}
]
}
@ -115,6 +131,22 @@
"column": 23
}
}
},
{
"type": "CommentBlock",
"value": " :: foo: number; ",
"start": 42,
"end": 66,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 26
}
}
}
]
}

View File

@ -1,4 +1,4 @@
/*flow-include
/* flow-include
type Foo = {
foo: number,
bar: boolean,

View File

@ -1,7 +1,7 @@
{
"type": "File",
"start": 0,
"end": 78,
"end": 79,
"loc": {
"start": {
"line": 1,
@ -15,7 +15,7 @@
"program": {
"type": "Program",
"start": 0,
"end": 78,
"end": 79,
"loc": {
"start": {
"line": 1,
@ -33,9 +33,9 @@
"innerComments": [
{
"type": "CommentBlock",
"value": "flow-include\ntype Foo = {\n foo: number,\n bar: boolean,\n baz: string\n};\n",
"value": " flow-include\ntype Foo = {\n foo: number,\n bar: boolean,\n baz: string\n};\n",
"start": 0,
"end": 78,
"end": 79,
"loc": {
"start": {
"line": 1,
@ -52,9 +52,9 @@
"comments": [
{
"type": "CommentBlock",
"value": "flow-include\ntype Foo = {\n foo: number,\n bar: boolean,\n baz: string\n};\n",
"value": " flow-include\ntype Foo = {\n foo: number,\n bar: boolean,\n baz: string\n};\n",
"start": 0,
"end": 78,
"end": 79,
"loc": {
"start": {
"line": 1,

View File

@ -1,3 +1,4 @@
class MyClass {
/*flow-include prop: string; */
/* flow-include foo: number; */
}

View File

@ -1,28 +1,28 @@
{
"type": "File",
"start": 0,
"end": 51,
"end": 90,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
"program": {
"type": "Program",
"start": 0,
"end": 51,
"end": 90,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
@ -32,14 +32,14 @@
{
"type": "ClassDeclaration",
"start": 0,
"end": 51,
"end": 90,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
@ -64,14 +64,14 @@
"body": {
"type": "ClassBody",
"start": 14,
"end": 51,
"end": 90,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
@ -92,6 +92,22 @@
"column": 33
}
}
},
{
"type": "CommentBlock",
"value": " flow-include foo: number; ",
"start": 52,
"end": 88,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 38
}
}
}
]
}
@ -115,6 +131,22 @@
"column": 33
}
}
},
{
"type": "CommentBlock",
"value": " flow-include foo: number; ",
"start": 52,
"end": 88,
"loc": {
"start": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 38
}
}
}
]
}

View File

@ -1,3 +1,4 @@
class MyClass {
/*:: prop: string; */
/* :: prop: string; */
/* :: prop2: number; */
}

View File

@ -1,28 +1,28 @@
{
"type": "File",
"start": 0,
"end": 41,
"end": 74,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
"program": {
"type": "Program",
"start": 0,
"end": 41,
"end": 74,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
@ -32,14 +32,14 @@
{
"type": "ClassDeclaration",
"start": 0,
"end": 41,
"end": 74,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
@ -64,45 +64,45 @@
"body": {
"type": "ClassBody",
"start": 14,
"end": 41,
"end": 74,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
"body": [
{
"type": "ClassProperty",
"start": 23,
"end": 36,
"start": 26,
"end": 39,
"loc": {
"start": {
"line": 2,
"column": 7
"column": 10
},
"end": {
"line": 2,
"column": 20
"column": 23
}
},
"static": false,
"key": {
"type": "Identifier",
"start": 23,
"end": 27,
"start": 26,
"end": 30,
"loc": {
"start": {
"line": 2,
"column": 7
"column": 10
},
"end": {
"line": 2,
"column": 11
"column": 14
},
"identifierName": "prop"
},
@ -112,30 +112,96 @@
"variance": null,
"typeAnnotation": {
"type": "TypeAnnotation",
"start": 27,
"end": 35,
"start": 30,
"end": 38,
"loc": {
"start": {
"line": 2,
"column": 11
"column": 14
},
"end": {
"line": 2,
"column": 19
"column": 22
}
},
"typeAnnotation": {
"type": "StringTypeAnnotation",
"start": 29,
"end": 35,
"start": 32,
"end": 38,
"loc": {
"start": {
"line": 2,
"column": 13
"column": 16
},
"end": {
"line": 2,
"column": 22
}
}
}
},
"value": null
},
{
"type": "ClassProperty",
"start": 55,
"end": 69,
"loc": {
"start": {
"line": 3,
"column": 12
},
"end": {
"line": 3,
"column": 26
}
},
"static": false,
"key": {
"type": "Identifier",
"start": 55,
"end": 60,
"loc": {
"start": {
"line": 3,
"column": 12
},
"end": {
"line": 3,
"column": 17
},
"identifierName": "prop2"
},
"name": "prop2"
},
"computed": false,
"variance": null,
"typeAnnotation": {
"type": "TypeAnnotation",
"start": 60,
"end": 68,
"loc": {
"start": {
"line": 3,
"column": 17
},
"end": {
"line": 3,
"column": 25
}
},
"typeAnnotation": {
"type": "NumberTypeAnnotation",
"start": 62,
"end": 68,
"loc": {
"start": {
"line": 3,
"column": 19
},
"end": {
"line": 3,
"column": 25
}
}
}

View File

@ -1,4 +1,4 @@
/*flow-include
/* flow-include
type Foo = {
foo: number,
bar: boolean,

View File

@ -1,7 +1,7 @@
{
"type": "File",
"start": 0,
"end": 78,
"end": 79,
"loc": {
"start": {
"line": 1,
@ -15,7 +15,7 @@
"program": {
"type": "Program",
"start": 0,
"end": 78,
"end": 79,
"loc": {
"start": {
"line": 1,
@ -31,8 +31,8 @@
"body": [
{
"type": "TypeAlias",
"start": 15,
"end": 75,
"start": 16,
"end": 76,
"loc": {
"start": {
"line": 2,
@ -45,8 +45,8 @@
},
"id": {
"type": "Identifier",
"start": 20,
"end": 23,
"start": 21,
"end": 24,
"loc": {
"start": {
"line": 2,
@ -63,8 +63,8 @@
"typeParameters": null,
"right": {
"type": "ObjectTypeAnnotation",
"start": 26,
"end": 74,
"start": 27,
"end": 75,
"loc": {
"start": {
"line": 2,
@ -79,8 +79,8 @@
"properties": [
{
"type": "ObjectTypeProperty",
"start": 30,
"end": 41,
"start": 31,
"end": 42,
"loc": {
"start": {
"line": 3,
@ -93,8 +93,8 @@
},
"key": {
"type": "Identifier",
"start": 30,
"end": 33,
"start": 31,
"end": 34,
"loc": {
"start": {
"line": 3,
@ -114,8 +114,8 @@
"method": false,
"value": {
"type": "NumberTypeAnnotation",
"start": 35,
"end": 41,
"start": 36,
"end": 42,
"loc": {
"start": {
"line": 3,
@ -132,8 +132,8 @@
},
{
"type": "ObjectTypeProperty",
"start": 45,
"end": 57,
"start": 46,
"end": 58,
"loc": {
"start": {
"line": 4,
@ -146,8 +146,8 @@
},
"key": {
"type": "Identifier",
"start": 45,
"end": 48,
"start": 46,
"end": 49,
"loc": {
"start": {
"line": 4,
@ -167,8 +167,8 @@
"method": false,
"value": {
"type": "BooleanTypeAnnotation",
"start": 50,
"end": 57,
"start": 51,
"end": 58,
"loc": {
"start": {
"line": 4,
@ -185,8 +185,8 @@
},
{
"type": "ObjectTypeProperty",
"start": 61,
"end": 72,
"start": 62,
"end": 73,
"loc": {
"start": {
"line": 5,
@ -199,8 +199,8 @@
},
"key": {
"type": "Identifier",
"start": 61,
"end": 64,
"start": 62,
"end": 65,
"loc": {
"start": {
"line": 5,
@ -220,8 +220,8 @@
"method": false,
"value": {
"type": "StringTypeAnnotation",
"start": 66,
"end": 72,
"start": 67,
"end": 73,
"loc": {
"start": {
"line": 5,

View File

@ -1,3 +1,4 @@
class MyClass {
/*flow-include prop: string; */
/* flow-include prop: string; */
/* flow-include prop2: number; */
}

View File

@ -1,28 +1,28 @@
{
"type": "File",
"start": 0,
"end": 51,
"end": 99,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
"program": {
"type": "Program",
"start": 0,
"end": 51,
"end": 99,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
@ -32,14 +32,14 @@
{
"type": "ClassDeclaration",
"start": 0,
"end": 51,
"end": 99,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
@ -64,57 +64,154 @@
"body": {
"type": "ClassBody",
"start": 14,
"end": 51,
"end": 99,
"loc": {
"start": {
"line": 1,
"column": 14
},
"end": {
"line": 3,
"line": 4,
"column": 1
}
},
"body": [],
"innerComments": [
"body": [
{
"type": "CommentBlock",
"value": "flow-include prop: string; ",
"start": 18,
"end": 49,
"type": "ClassProperty",
"start": 39,
"end": 52,
"loc": {
"start": {
"line": 2,
"column": 2
"column": 23
},
"end": {
"line": 2,
"column": 33
"column": 36
}
},
"static": false,
"key": {
"type": "Identifier",
"start": 39,
"end": 43,
"loc": {
"start": {
"line": 2,
"column": 23
},
"end": {
"line": 2,
"column": 27
},
"identifierName": "prop"
},
"name": "prop"
},
"computed": false,
"variance": null,
"typeAnnotation": {
"type": "TypeAnnotation",
"start": 43,
"end": 51,
"loc": {
"start": {
"line": 2,
"column": 27
},
"end": {
"line": 2,
"column": 35
}
},
"typeAnnotation": {
"type": "StringTypeAnnotation",
"start": 45,
"end": 51,
"loc": {
"start": {
"line": 2,
"column": 29
},
"end": {
"line": 2,
"column": 35
}
}
}
},
"value": null
},
{
"type": "ClassProperty",
"start": 80,
"end": 94,
"loc": {
"start": {
"line": 3,
"column": 24
},
"end": {
"line": 3,
"column": 38
}
},
"static": false,
"key": {
"type": "Identifier",
"start": 80,
"end": 85,
"loc": {
"start": {
"line": 3,
"column": 24
},
"end": {
"line": 3,
"column": 29
},
"identifierName": "prop2"
},
"name": "prop2"
},
"computed": false,
"variance": null,
"typeAnnotation": {
"type": "TypeAnnotation",
"start": 85,
"end": 93,
"loc": {
"start": {
"line": 3,
"column": 29
},
"end": {
"line": 3,
"column": 37
}
},
"typeAnnotation": {
"type": "NumberTypeAnnotation",
"start": 87,
"end": 93,
"loc": {
"start": {
"line": 3,
"column": 31
},
"end": {
"line": 3,
"column": 37
}
}
}
},
"value": null
}
]
}
}
],
"directives": []
},
"comments": [
{
"type": "CommentBlock",
"value": "flow-include prop: string; ",
"start": 18,
"end": 49,
"loc": {
"start": {
"line": 2,
"column": 2
},
"end": {
"line": 2,
"column": 33
}
}
}
]
}

View File

@ -1,3 +1,3 @@
class MyClass {
/*:: prop: string;
/* :: prop: string;
}

View File

@ -1,4 +1,4 @@
/*flow-include
/* flow-include
type Foo = {
foo: number,
bar: boolean,

View File

@ -0,0 +1 @@
/*:: /*asd */

View File

@ -0,0 +1,3 @@
{
"throws": "Unterminated comment (1:5)"
}

View File

@ -0,0 +1 @@
/*:: //asd */

View File

@ -0,0 +1,3 @@
{
"throws": "Unterminated flow-comment (1:13)"
}

View File

@ -0,0 +1 @@
/*:: /*flow-include */

View File

@ -0,0 +1,3 @@
{
"throws": "Cannot have a flow comment inside another flow comment (1:0)"
}

View File

@ -27,7 +27,6 @@ decorators/migrated_0007.js
private_class_properties/multiple.js
private_class_properties/super.js
types/annotations/migrated_0001.js
types/annotations_in_comments_invalid/migrated_0003.js
types/annotations/void_is_reserved_param.js
types/member/reserved_words.js
types/parameter_defaults/migrated_0032.js
@ -38,3 +37,4 @@ numbers/underscored_float_whole.js
numbers/underscored_hex.js
numbers/underscored_number.js
numbers/underscored_oct.js
types/annotations_in_comments/migrated_0001.js

View File

@ -98,7 +98,7 @@ function update_whitelist(summary) {
);
});
const newLines = disallowed
const newLines = summary.disallowed.failure
.map(({ test }) => test.file)
.filter(test => oldLines.indexOf(test) === -1);

View File

@ -1651,10 +1651,10 @@ babel-plugin-syntax-object-rest-spread@^6.13.0:
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=
babel-plugin-transform-charcodes@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-charcodes/-/babel-plugin-transform-charcodes-0.1.0.tgz#c71b301019c90615b940faf0f15f275ec5c81a3d"
integrity sha512-RUBYwMpIEAnQeIgE03DCn8JViDIPkwO6+0uHU4fgou4I/U5ml/zsa7xJ8KqTPVBAKvJAV2cFGoc4W/t8q1Zntg==
babel-plugin-transform-charcodes@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-charcodes/-/babel-plugin-transform-charcodes-0.1.1.tgz#6b186ebd25e0932aba9c82820edd711992b66952"
integrity sha512-wMKC2+F8NByAFLp5+5fObJQtgp2Wuj2/bTWA8uHSE5eOVTy3PdMAwMKElEICFS9pXHWiq2hB+MK1gt4SGR+oYw==
dependencies:
"@babel/traverse" "^7.0.0-beta.31"
babylon "^7.0.0-beta.31"
@ -2238,10 +2238,10 @@ chalk@^2.3.1, chalk@^2.4.1:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
charcodes@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/charcodes/-/charcodes-0.1.0.tgz#61f8c244fc7f94f186fe74f31078901a3ed7928e"
integrity sha512-m4ne5Zw6XsdHhM5teBUHvu5s1SeJnwP0ljQ+IrGyZZ6U1TMohi+pVtsvgSgEsj5CPY6PLd/vMknFRuXdifdk+g==
charcodes@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/charcodes/-/charcodes-0.1.1.tgz#c463f6506cdb3b26a7f2d3fd4399abd363dd632a"
integrity sha512-6aaMfQtn61TsnFc7rQ9RXZ2LqMoLlWr0kJWvPMtH1n+XArQByvZEaIwwUmeGPoutvJOr0qGa3/NL/hqM4BI+uQ==
chardet@^0.4.0:
version "0.4.2"