Fix import assertion occurrences crash and make import assertion parsing more generous (#47535)

This commit is contained in:
Wesley Wigham 2022-01-20 14:08:47 -08:00 committed by GitHub
parent 04d77fe900
commit bae0f50818
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 154 additions and 14 deletions

View File

@ -39786,6 +39786,16 @@ namespace ts {
return false;
}
}
if (!isImportEqualsDeclaration(node) && node.assertClause) {
let hasError = false;
for (const clause of node.assertClause.elements) {
if (!isStringLiteral(clause.value)) {
hasError = true;
error(clause.value, Diagnostics.Import_assertion_values_must_be_string_literal_expressions);
}
}
return !hasError;
}
return true;
}

View File

@ -3369,6 +3369,10 @@
"category": "Error",
"code": 2836
},
"Import assertion values must be string literal expressions.": {
"category": "Error",
"code": 2837
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",

View File

@ -4024,7 +4024,7 @@ namespace ts {
}
// @api
function createAssertEntry(name: AssertionKey, value: StringLiteral): AssertEntry {
function createAssertEntry(name: AssertionKey, value: Expression): AssertEntry {
const node = createBaseNode<AssertEntry>(SyntaxKind.AssertEntry);
node.name = name;
node.value = value;
@ -4033,7 +4033,7 @@ namespace ts {
}
// @api
function updateAssertEntry(node: AssertEntry, name: AssertionKey, value: StringLiteral): AssertEntry {
function updateAssertEntry(node: AssertEntry, name: AssertionKey, value: Expression): AssertEntry {
return node.name !== name
|| node.value !== value
? update(createAssertEntry(name, value), node)

View File

@ -7281,7 +7281,7 @@ namespace ts {
const pos = getNodePos();
const name = tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() : parseLiteralLikeNode(SyntaxKind.StringLiteral) as StringLiteral;
parseExpected(SyntaxKind.ColonToken);
const value = parseLiteralLikeNode(SyntaxKind.StringLiteral) as StringLiteral;
const value = parseAssignmentExpressionOrHigher();
return finishNode(factory.createAssertEntry(name, value), pos);
}

View File

@ -3055,7 +3055,7 @@ namespace ts {
readonly kind: SyntaxKind.AssertEntry;
readonly parent: AssertClause;
readonly name: AssertionKey;
readonly value: StringLiteral;
readonly value: Expression;
}
export interface AssertClause extends Node {
@ -7446,8 +7446,8 @@ namespace ts {
updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause;
createAssertClause(elements: NodeArray<AssertEntry>, multiLine?: boolean): AssertClause;
updateAssertClause(node: AssertClause, elements: NodeArray<AssertEntry>, multiLine?: boolean): AssertClause;
createAssertEntry(name: AssertionKey, value: StringLiteral): AssertEntry;
updateAssertEntry (node: AssertEntry, name: AssertionKey, value: StringLiteral): AssertEntry;
createAssertEntry(name: AssertionKey, value: Expression): AssertEntry;
updateAssertEntry(node: AssertEntry, name: AssertionKey, value: Expression): AssertEntry;
createNamespaceImport(name: Identifier): NamespaceImport;
updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport;
createNamespaceExport(name: Identifier): NamespaceExport;

View File

@ -1090,7 +1090,7 @@ namespace ts {
Debug.type<AssertEntry>(node);
return factory.updateAssertEntry(node,
nodeVisitor(node.name, visitor, isAssertionKey),
nodeVisitor(node.value, visitor, isStringLiteral));
nodeVisitor(node.value, visitor, isExpressionNode));
case SyntaxKind.ImportClause:
Debug.type<ImportClause>(node);

View File

@ -526,7 +526,7 @@ namespace ts.FindAllReferences {
function getTextSpan(node: Node, sourceFile: SourceFile, endNode?: Node): TextSpan {
let start = node.getStart(sourceFile);
let end = (endNode || node).getEnd();
if (isStringLiteralLike(node)) {
if (isStringLiteralLike(node) && (end - start) > 2) {
Debug.assert(endNode === undefined);
start += 1;
end -= 1;

View File

@ -1652,7 +1652,7 @@ declare namespace ts {
readonly kind: SyntaxKind.AssertEntry;
readonly parent: AssertClause;
readonly name: AssertionKey;
readonly value: StringLiteral;
readonly value: Expression;
}
export interface AssertClause extends Node {
readonly kind: SyntaxKind.AssertClause;
@ -3576,8 +3576,8 @@ declare namespace ts {
updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause;
createAssertClause(elements: NodeArray<AssertEntry>, multiLine?: boolean): AssertClause;
updateAssertClause(node: AssertClause, elements: NodeArray<AssertEntry>, multiLine?: boolean): AssertClause;
createAssertEntry(name: AssertionKey, value: StringLiteral): AssertEntry;
updateAssertEntry(node: AssertEntry, name: AssertionKey, value: StringLiteral): AssertEntry;
createAssertEntry(name: AssertionKey, value: Expression): AssertEntry;
updateAssertEntry(node: AssertEntry, name: AssertionKey, value: Expression): AssertEntry;
createNamespaceImport(name: Identifier): NamespaceImport;
updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport;
createNamespaceExport(name: Identifier): NamespaceExport;

View File

@ -1652,7 +1652,7 @@ declare namespace ts {
readonly kind: SyntaxKind.AssertEntry;
readonly parent: AssertClause;
readonly name: AssertionKey;
readonly value: StringLiteral;
readonly value: Expression;
}
export interface AssertClause extends Node {
readonly kind: SyntaxKind.AssertClause;
@ -3576,8 +3576,8 @@ declare namespace ts {
updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause;
createAssertClause(elements: NodeArray<AssertEntry>, multiLine?: boolean): AssertClause;
updateAssertClause(node: AssertClause, elements: NodeArray<AssertEntry>, multiLine?: boolean): AssertClause;
createAssertEntry(name: AssertionKey, value: StringLiteral): AssertEntry;
updateAssertEntry(node: AssertEntry, name: AssertionKey, value: StringLiteral): AssertEntry;
createAssertEntry(name: AssertionKey, value: Expression): AssertEntry;
updateAssertEntry(node: AssertEntry, name: AssertionKey, value: Expression): AssertEntry;
createNamespaceImport(name: Identifier): NamespaceImport;
updateNamespaceImport(node: NamespaceImport, name: Identifier): NamespaceImport;
createNamespaceExport(name: Identifier): NamespaceExport;

View File

@ -0,0 +1,32 @@
tests/cases/compiler/mod.mts(1,52): error TS2837: Import assertion values must be string literal expressions.
tests/cases/compiler/mod.mts(3,52): error TS2837: Import assertion values must be string literal expressions.
tests/cases/compiler/mod.mts(5,52): error TS2837: Import assertion values must be string literal expressions.
tests/cases/compiler/mod.mts(7,52): error TS2837: Import assertion values must be string literal expressions.
tests/cases/compiler/mod.mts(9,52): error TS2837: Import assertion values must be string literal expressions.
tests/cases/compiler/mod.mts(11,66): error TS2837: Import assertion values must be string literal expressions.
==== tests/cases/compiler/mod.mts (6 errors) ====
import * as thing1 from "./mod.mjs" assert {field: 0};
~
!!! error TS2837: Import assertion values must be string literal expressions.
import * as thing2 from "./mod.mjs" assert {field: `a`};
~~~
!!! error TS2837: Import assertion values must be string literal expressions.
import * as thing3 from "./mod.mjs" assert {field: /a/g};
~~~~
!!! error TS2837: Import assertion values must be string literal expressions.
import * as thing4 from "./mod.mjs" assert {field: ["a"]};
~~~~~
!!! error TS2837: Import assertion values must be string literal expressions.
import * as thing5 from "./mod.mjs" assert {field: { a: 0 }};
~~~~~~~~
!!! error TS2837: Import assertion values must be string literal expressions.
import * as thing6 from "./mod.mjs" assert {type: "json", field: 0..toString()}
~~~~~~~~~~~~~
!!! error TS2837: Import assertion values must be string literal expressions.

View File

@ -0,0 +1,15 @@
//// [mod.mts]
import * as thing1 from "./mod.mjs" assert {field: 0};
import * as thing2 from "./mod.mjs" assert {field: `a`};
import * as thing3 from "./mod.mjs" assert {field: /a/g};
import * as thing4 from "./mod.mjs" assert {field: ["a"]};
import * as thing5 from "./mod.mjs" assert {field: { a: 0 }};
import * as thing6 from "./mod.mjs" assert {type: "json", field: 0..toString()}
//// [mod.mjs]
export {};

View File

@ -0,0 +1,22 @@
=== tests/cases/compiler/mod.mts ===
import * as thing1 from "./mod.mjs" assert {field: 0};
>thing1 : Symbol(thing1, Decl(mod.mts, 0, 6))
import * as thing2 from "./mod.mjs" assert {field: `a`};
>thing2 : Symbol(thing2, Decl(mod.mts, 2, 6))
import * as thing3 from "./mod.mjs" assert {field: /a/g};
>thing3 : Symbol(thing3, Decl(mod.mts, 4, 6))
import * as thing4 from "./mod.mjs" assert {field: ["a"]};
>thing4 : Symbol(thing4, Decl(mod.mts, 6, 6))
import * as thing5 from "./mod.mjs" assert {field: { a: 0 }};
>thing5 : Symbol(thing5, Decl(mod.mts, 8, 6))
>a : Symbol(a, Decl(mod.mts, 8, 52))
import * as thing6 from "./mod.mjs" assert {type: "json", field: 0..toString()}
>thing6 : Symbol(thing6, Decl(mod.mts, 10, 6))
>0..toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))

View File

@ -0,0 +1,36 @@
=== tests/cases/compiler/mod.mts ===
import * as thing1 from "./mod.mjs" assert {field: 0};
>thing1 : typeof thing1
>field : any
import * as thing2 from "./mod.mjs" assert {field: `a`};
>thing2 : typeof thing1
>field : any
import * as thing3 from "./mod.mjs" assert {field: /a/g};
>thing3 : typeof thing1
>field : any
>/a/g : RegExp
import * as thing4 from "./mod.mjs" assert {field: ["a"]};
>thing4 : typeof thing1
>field : any
>["a"] : string[]
>"a" : "a"
import * as thing5 from "./mod.mjs" assert {field: { a: 0 }};
>thing5 : typeof thing1
>field : any
>{ a: 0 } : { a: number; }
>a : number
>0 : 0
import * as thing6 from "./mod.mjs" assert {type: "json", field: 0..toString()}
>thing6 : typeof thing1
>type : any
>field : any
>0..toString() : string
>0..toString : (radix?: number) => string
>0. : 0
>toString : (radix?: number) => string

View File

@ -0,0 +1,13 @@
// @module: nodenext
// @filename: mod.mts
import * as thing1 from "./mod.mjs" assert {field: 0};
import * as thing2 from "./mod.mjs" assert {field: `a`};
import * as thing3 from "./mod.mjs" assert {field: /a/g};
import * as thing4 from "./mod.mjs" assert {field: ["a"]};
import * as thing5 from "./mod.mjs" assert {field: { a: 0 }};
import * as thing6 from "./mod.mjs" assert {type: "json", field: 0..toString()}

View File

@ -0,0 +1,8 @@
/// <reference path="fourslash.ts" />
// @module: nodenext
////import * as react from "react" assert { cache: /**/0 };
////react.Children;
goTo.marker();
verify.occurrencesAtPositionCount(0);