From 253e87bcc3febe9f5b627ffb924b178ecf3fc4be Mon Sep 17 00:00:00 2001 From: Armano Date: Mon, 14 Jan 2019 00:48:09 +0100 Subject: [PATCH] fix: mark only leading string expressions as directives - all leading string expressions in blocks should be marked as directives unless there is expression of different type before it - directives does not have to be unique --- packages/typescript-estree/src/convert.ts | 25 +- .../directives/first-expression.src.js | 4 + .../directives/non-unique-directive.src.js | 3 + .../lib/__snapshots__/javascript.ts.snap | 395 ++++++++++++++++++ .../semantic-diagnostics-enabled.ts.snap | 4 + 5 files changed, 418 insertions(+), 13 deletions(-) create mode 100644 packages/typescript-estree/tests/fixtures/javascript/directives/first-expression.src.js create mode 100644 packages/typescript-estree/tests/fixtures/javascript/directives/non-unique-directive.src.js diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index 0e22cf4cbef7..009bfdcdcb73 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -183,25 +183,24 @@ export default function convert(config: ConvertConfig): ESTreeNode | null { function convertBodyExpressions( nodes: ts.NodeArray ): ESTreeNode[] { - // directives has to be unique, if directive is registered twice pick only first one - const unique: string[] = []; - const allowDirectives = canContainDirective(node); + let allowDirectives = canContainDirective(node); return ( nodes .map(statement => { const child = convertChild(statement); - if ( - allowDirectives && - child && - child.expression && - ts.isExpressionStatement(statement) && - ts.isStringLiteral(statement.expression) - ) { - const raw = child.expression.raw!; - if (!unique.includes(raw)) { + if (allowDirectives) { + if ( + child && + child.expression && + ts.isExpressionStatement(statement) && + ts.isStringLiteral(statement.expression) + ) { + const raw = child.expression.raw!; child.directive = raw.slice(1, -1); - unique.push(raw); + return child!; // child can be null but it's filtered below + } else { + allowDirectives = false; } } return child!; // child can be null but it's filtered below diff --git a/packages/typescript-estree/tests/fixtures/javascript/directives/first-expression.src.js b/packages/typescript-estree/tests/fixtures/javascript/directives/first-expression.src.js new file mode 100644 index 000000000000..94045f6dab92 --- /dev/null +++ b/packages/typescript-estree/tests/fixtures/javascript/directives/first-expression.src.js @@ -0,0 +1,4 @@ +// Prevent strings from being parsed as directives +// See https://github.com/prettier/prettier/pull/1560#issue-227225960 +0; +"abc" diff --git a/packages/typescript-estree/tests/fixtures/javascript/directives/non-unique-directive.src.js b/packages/typescript-estree/tests/fixtures/javascript/directives/non-unique-directive.src.js new file mode 100644 index 000000000000..0ae940ac0c7f --- /dev/null +++ b/packages/typescript-estree/tests/fixtures/javascript/directives/non-unique-directive.src.js @@ -0,0 +1,3 @@ +"use strict"; +"use strict"; +"test"; diff --git a/packages/typescript-estree/tests/lib/__snapshots__/javascript.ts.snap b/packages/typescript-estree/tests/lib/__snapshots__/javascript.ts.snap index f6c0c507868c..44ce6eaf9987 100644 --- a/packages/typescript-estree/tests/lib/__snapshots__/javascript.ts.snap +++ b/packages/typescript-estree/tests/lib/__snapshots__/javascript.ts.snap @@ -74285,6 +74285,157 @@ Object { } `; +exports[`javascript fixtures/directives/first-expression.src 1`] = ` +Object { + "body": Array [ + Object { + "expression": Object { + "loc": Object { + "end": Object { + "column": 1, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 121, + 122, + ], + "raw": "0", + "type": "Literal", + "value": 0, + }, + "loc": Object { + "end": Object { + "column": 2, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 121, + 123, + ], + "type": "ExpressionStatement", + }, + Object { + "expression": Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 4, + }, + "start": Object { + "column": 0, + "line": 4, + }, + }, + "range": Array [ + 124, + 129, + ], + "raw": "\\"abc\\"", + "type": "Literal", + "value": "abc", + }, + "loc": Object { + "end": Object { + "column": 5, + "line": 4, + }, + "start": Object { + "column": 0, + "line": 4, + }, + }, + "range": Array [ + 124, + 129, + ], + "type": "ExpressionStatement", + }, + ], + "loc": Object { + "end": Object { + "column": 0, + "line": 5, + }, + "start": Object { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 121, + 130, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 1, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 121, + 122, + ], + "type": "Numeric", + "value": "0", + }, + Object { + "loc": Object { + "end": Object { + "column": 2, + "line": 3, + }, + "start": Object { + "column": 1, + "line": 3, + }, + }, + "range": Array [ + 122, + 123, + ], + "type": "Punctuator", + "value": ";", + }, + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 4, + }, + "start": Object { + "column": 0, + "line": 4, + }, + }, + "range": Array [ + 124, + 129, + ], + "type": "String", + "value": "\\"abc\\"", + }, + ], + "type": "Program", +} +`; + exports[`javascript fixtures/directives/function-non-strict.src 1`] = ` Object { "body": Array [ @@ -75648,6 +75799,250 @@ Object { } `; +exports[`javascript fixtures/directives/non-unique-directive.src 1`] = ` +Object { + "body": Array [ + Object { + "directive": "use strict", + "expression": Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 12, + ], + "raw": "\\"use strict\\"", + "type": "Literal", + "value": "use strict", + }, + "loc": Object { + "end": Object { + "column": 13, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 13, + ], + "type": "ExpressionStatement", + }, + Object { + "directive": "use strict", + "expression": Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 2, + }, + "start": Object { + "column": 0, + "line": 2, + }, + }, + "range": Array [ + 14, + 26, + ], + "raw": "\\"use strict\\"", + "type": "Literal", + "value": "use strict", + }, + "loc": Object { + "end": Object { + "column": 13, + "line": 2, + }, + "start": Object { + "column": 0, + "line": 2, + }, + }, + "range": Array [ + 14, + 27, + ], + "type": "ExpressionStatement", + }, + Object { + "directive": "test", + "expression": Object { + "loc": Object { + "end": Object { + "column": 6, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 28, + 34, + ], + "raw": "\\"test\\"", + "type": "Literal", + "value": "test", + }, + "loc": Object { + "end": Object { + "column": 7, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 28, + 35, + ], + "type": "ExpressionStatement", + }, + ], + "loc": Object { + "end": Object { + "column": 0, + "line": 4, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 36, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 12, + ], + "type": "String", + "value": "\\"use strict\\"", + }, + Object { + "loc": Object { + "end": Object { + "column": 13, + "line": 1, + }, + "start": Object { + "column": 12, + "line": 1, + }, + }, + "range": Array [ + 12, + 13, + ], + "type": "Punctuator", + "value": ";", + }, + Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 2, + }, + "start": Object { + "column": 0, + "line": 2, + }, + }, + "range": Array [ + 14, + 26, + ], + "type": "String", + "value": "\\"use strict\\"", + }, + Object { + "loc": Object { + "end": Object { + "column": 13, + "line": 2, + }, + "start": Object { + "column": 12, + "line": 2, + }, + }, + "range": Array [ + 26, + 27, + ], + "type": "Punctuator", + "value": ";", + }, + Object { + "loc": Object { + "end": Object { + "column": 6, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 28, + 34, + ], + "type": "String", + "value": "\\"test\\"", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 3, + }, + "start": Object { + "column": 6, + "line": 3, + }, + }, + "range": Array [ + 34, + 35, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", +} +`; + exports[`javascript fixtures/directives/program.src 1`] = ` Object { "body": Array [ diff --git a/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.ts.snap b/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.ts.snap index e9c8b96707e9..c562892371e9 100644 --- a/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.ts.snap +++ b/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.ts.snap @@ -587,10 +587,14 @@ exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" e exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/directives/directive-in-class.src.js.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; +exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/directives/first-expression.src.js.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; + exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/directives/function-non-strict.src.js.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/directives/non-directive-string.src.js.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; +exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/directives/non-unique-directive.src.js.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; + exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/directives/program.src.js.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/javascript/directives/program-order.src.js.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`;