Skip to content

Import assertion #40698

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e1b3b78
Add parsing
Kingwl Sep 22, 2020
66d2273
fix all api
Kingwl Sep 22, 2020
5f3cea6
check gramma of import call
Kingwl Sep 22, 2020
5a1af04
Add more part of assertion
Kingwl Sep 22, 2020
4b51ca9
Add some case
Kingwl Sep 22, 2020
375b433
Add baseline
Kingwl Sep 22, 2020
41a881c
use module insted of target
Kingwl Sep 23, 2020
46a3eb1
strip assertion in d.ts
Kingwl Sep 23, 2020
a484ea2
Merge branch 'master' into import_assertion
Kingwl Sep 23, 2020
d64f7ba
Merge branch 'master' into import_assertion
Kingwl Nov 12, 2020
68c8c5d
Merge branch 'master' into import_assertion
Kingwl Dec 31, 2020
29fe0d3
Merge branch 'master' into import_assertion
Kingwl Jan 7, 2021
adcfd1b
Update new baseline
Kingwl Jan 7, 2021
fb01eb3
Merge branch 'master' into import_assertion
Kingwl Mar 8, 2021
4f22a60
accept baseline
Kingwl Mar 8, 2021
f5e594d
Revert error number changes
Kingwl Mar 9, 2021
60434d1
Update diagnostic message
Kingwl Mar 9, 2021
ff87d3e
Accept baseline
Kingwl Mar 9, 2021
43b67b9
Merge branch 'master' into import_assertion
Kingwl Mar 15, 2021
c69a05b
rename path
Kingwl Mar 15, 2021
d1c48b5
Fix cr issues
Kingwl Mar 15, 2021
d14f93a
Accept baseline
Kingwl Mar 15, 2021
aa8b856
Accept baseline
Kingwl Mar 15, 2021
7a5ec34
Merge branch 'master' into import_assertion
Kingwl Mar 18, 2021
9cea9cf
Error if assertion and typeonly import
Kingwl Mar 18, 2021
6337a7e
Merge branch 'main' into import_assertion
Kingwl Jun 17, 2021
eee2cab
Accept baseline
Kingwl Jun 17, 2021
2857d69
Merge branch 'main' into import_assertion
Kingwl Jul 9, 2021
88e39d5
Make lint happy
Kingwl Jul 9, 2021
f941d92
Merge branch 'main' into import_assertion
Kingwl Aug 13, 2021
106ff06
Add some comment
Kingwl Aug 13, 2021
7df4964
Merge branch 'main' into import_assertion
Kingwl Sep 14, 2021
6ea3c55
Fix cr issues
Kingwl Sep 14, 2021
fc51c42
Fix more issue
Kingwl Sep 14, 2021
bf7ca71
Incorporate PR feedback, fix module resolution for import()
rbuckton Sep 17, 2021
463138a
Merge branch 'main' into import_assertion
rbuckton Sep 17, 2021
b07c6e9
Add contextual type and completions for ImportCall options argument
rbuckton Sep 20, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add some case
  • Loading branch information
Kingwl committed Sep 22, 2020
commit 4b51ca9dd846e7bb657e1b11aed00193ee297d7b
6 changes: 3 additions & 3 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39882,11 +39882,11 @@ namespace ts {
checkGrammarForDisallowedTrailingComma(nodeArguments);
}
else {
if (nodeArguments.length > 2) {
if (nodeArguments.length !== 1 && nodeArguments.length !== 2) {
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_must_have_a_specifier_as_arguments_and_an_optional_assertion);
}
}
return false
return false;
}

function checkGrammarImportCallExpression(node: ImportCall): boolean {
Expand All @@ -39904,7 +39904,7 @@ namespace ts {
}
// see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import.
// parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import.
if (isSpreadElement(nodeArguments[0])) {
if (nodeArguments.length && isSpreadElement(nodeArguments[0])) {
return grammarErrorOnNode(nodeArguments[0], Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element);
}
return false;
Expand Down
12 changes: 9 additions & 3 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3188,21 +3188,23 @@ namespace ts {
emitExpression(node.moduleSpecifier);
if (node.assertClause) {
writeSpace();
emit(node.assertClause)
emit(node.assertClause);
}
writeTrailingSemicolon();
}

function emitAssertClause(node: AssertClause) {
emitTokenWithComment(SyntaxKind.AssertKeyword, node.pos, writeKeyword, node);
writeSpace();
const elements = node.elements;
emitExpressionList(node, elements, ListFormat.ImportClauseEntries);
emitNodeList(emitAssertEntry, node, elements, ListFormat.ImportClauseEntries);
}

function emitAssertEntry(node: AssertEntry) {
emit(node.name);
writePunctuation(":");
writeSpace();

const value = node.value;
/** @see emitPropertyAssignment */
if (emitTrailingCommentsOfPosition && (getEmitFlags(value) & EmitFlags.NoLeadingComments) === 0) {
Expand Down Expand Up @@ -3275,6 +3277,10 @@ namespace ts {
writeSpace();
emitExpression(node.moduleSpecifier);
}
if (node.assertClause) {
writeSpace();
emit(node.assertClause);
}
writeTrailingSemicolon();
}

Expand Down
10 changes: 6 additions & 4 deletions src/compiler/factory/nodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3856,17 +3856,19 @@ namespace ts {
}

// @api
function createAssertClause(elements: NodeArray<AssertEntry> | undefined): AssertClause {
function createAssertClause(elements: NodeArray<AssertEntry>, multiLine?: boolean): AssertClause {
const node = createBaseNode<AssertClause>(SyntaxKind.AssertClause);
node.elements = elements;
node.multiLine = multiLine;
node.transformFlags |= TransformFlags.ContainsESNext;
return node;
}

// @api
function updateAssertClause(node: AssertClause, elements: NodeArray<AssertEntry> | undefined): AssertClause {
function updateAssertClause(node: AssertClause, elements: NodeArray<AssertEntry>, multiLine?: boolean): AssertClause {
return node.elements !== elements
? update(createAssertClause(elements), node)
|| node.multiLine !== multiLine
? update(createAssertClause(elements, multiLine), node)
: node;
}

Expand All @@ -3880,7 +3882,7 @@ namespace ts {
}

// @api
function updateAssertEntry (node: AssertEntry, name: AssertionKey, value: StringLiteral): AssertEntry {
function updateAssertEntry(node: AssertEntry, name: AssertionKey, value: StringLiteral): AssertEntry {
return node.name !== name
|| node.value !== value
? update(createAssertEntry(name, value), node)
Expand Down
43 changes: 28 additions & 15 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,8 @@ namespace ts {
return visitNodes(cbNode, cbNodes, node.decorators) ||
visitNodes(cbNode, cbNodes, node.modifiers) ||
visitNode(cbNode, (<ImportDeclaration>node).importClause) ||
visitNode(cbNode, (<ImportDeclaration>node).moduleSpecifier);
visitNode(cbNode, (<ImportDeclaration>node).moduleSpecifier) ||
visitNode(cbNode, (<ImportDeclaration>node).assertClause);
case SyntaxKind.ImportClause:
return visitNode(cbNode, (<ImportClause>node).name) ||
visitNode(cbNode, (<ImportClause>node).namedBindings);
Expand All @@ -417,7 +418,8 @@ namespace ts {
return visitNodes(cbNode, cbNodes, node.decorators) ||
visitNodes(cbNode, cbNodes, node.modifiers) ||
visitNode(cbNode, (<ExportDeclaration>node).exportClause) ||
visitNode(cbNode, (<ExportDeclaration>node).moduleSpecifier);
visitNode(cbNode, (<ExportDeclaration>node).moduleSpecifier) ||
visitNode(cbNode, (<ExportDeclaration>node).assertClause);
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
return visitNode(cbNode, (<ImportOrExportSpecifier>node).propertyName) ||
Expand Down Expand Up @@ -1698,7 +1700,7 @@ namespace ts {
function isAssertionKey(): boolean {
return tokenIsIdentifierOrKeyword(token()) ||
token() === SyntaxKind.StringLiteral;
}
}

function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName {
if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) {
Expand Down Expand Up @@ -1865,7 +1867,7 @@ namespace ts {
case ParsingContext.ObjectBindingElements:
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
case ParsingContext.AssertEntries:
return isAssertionKey()
return isAssertionKey();
case ParsingContext.HeritageClauseElement:
// If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{`
// That way we won't consume the body of a class in its heritage clause.
Expand Down Expand Up @@ -6915,30 +6917,42 @@ namespace ts {
parseExpected(SyntaxKind.FromKeyword);
}
const moduleSpecifier = parseModuleSpecifier();
const afterSpecifierPos = scanner.getStartPos();

let assertClause: AssertClause | undefined;
if (token() === SyntaxKind.AssertKeyword && !scanner.hasPrecedingLineBreak()) {
assertClause = parseAssertClause(afterSpecifierPos);
assertClause = parseAssertClause();
}

parseSemicolon();
const node = factory.createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier, assertClause);
return withJSDoc(finishNode(node, pos), hasJSDoc);
}

function parseAssertEntry () {
function parseAssertEntry() {
const pos = getNodePos();
const name = tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() : parseLiteralLikeNode(SyntaxKind.StringLiteral) as StringLiteral;
parseExpected(SyntaxKind.ColonToken)
parseExpected(SyntaxKind.ColonToken);
const value = parseLiteralLikeNode(SyntaxKind.StringLiteral) as StringLiteral;
return finishNode(factory.createAssertEntry(name, value), pos);
}

function parseAssertClause(pos: number) {
parseExpected(SyntaxKind.AssertKeyword)
const elements = parseList(ParsingContext.AssertEntries, parseAssertEntry)
return finishNode(factory.createAssertClause(elements), pos);
function parseAssertClause() {
const pos = getNodePos();
parseExpected(SyntaxKind.AssertKeyword);
const openBracePosition = scanner.getTokenPos();
parseExpected(SyntaxKind.OpenBraceToken);
const multiLine = scanner.hasPrecedingLineBreak();
const elements = parseDelimitedList(ParsingContext.AssertEntries, parseAssertEntry, /*considerSemicolonAsDelimiter*/ true);
if (!parseExpected(SyntaxKind.CloseBraceToken)) {
const lastError = lastOrUndefined(parseDiagnostics);
if (lastError && lastError.code === Diagnostics._0_expected.code) {
addRelatedInfo(
lastError,
createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_to_match_the_token_here)
);
}
}
return finishNode(factory.createAssertClause(elements, multiLine), pos);
}

function tokenAfterImportDefinitelyProducesImportDeclaration() {
Expand Down Expand Up @@ -7111,9 +7125,8 @@ namespace ts {
moduleSpecifier = parseModuleSpecifier();
}
}
if (token() === SyntaxKind.AssertKeyword && !scanner.hasPrecedingLineBreak()) {
const posAfterSpecifier = getNodePos();
assertClause = parseAssertClause(posAfterSpecifier);
if (moduleSpecifier && token() === SyntaxKind.AssertKeyword && !scanner.hasPrecedingLineBreak()) {
assertClause = parseAssertClause();
}
parseSemicolon();
setAwaitContext(savedAwaitContext);
Expand Down
1 change: 1 addition & 0 deletions src/compiler/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ namespace ts {
any: SyntaxKind.AnyKeyword,
as: SyntaxKind.AsKeyword,
asserts: SyntaxKind.AssertsKeyword,
assert: SyntaxKind.AssertKeyword,
bigint: SyntaxKind.BigIntKeyword,
boolean: SyntaxKind.BooleanKeyword,
break: SyntaxKind.BreakKeyword,
Expand Down
11 changes: 6 additions & 5 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2987,12 +2987,13 @@ namespace ts {
readonly parent: AssertClause;
readonly name: AssertionKey;
readonly value: StringLiteral;
}
}

export interface AssertClause extends Node {
export interface AssertClause extends Node {
readonly kind: SyntaxKind.AssertClause;
readonly parent: ImportDeclaration | ExportDeclaration
readonly elements?: NodeArray<AssertEntry>
readonly elements: NodeArray<AssertEntry>;
readonly multiLine?: boolean;
}

export interface NamespaceImport extends NamedDeclaration {
Expand Down Expand Up @@ -7009,8 +7010,8 @@ namespace ts {
updateImportDeclaration(node: ImportDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression, assertClause: AssertClause | undefined): ImportDeclaration;
createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause;
updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause;
createAssertClause(elements: NodeArray<AssertEntry> | undefined): AssertClause;
updateAssertClause(node: AssertClause, elements: NodeArray<AssertEntry> | undefined): AssertClause;
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;
createNamespaceImport(name: Identifier): NamespaceImport;
Expand Down
5 changes: 3 additions & 2 deletions src/compiler/visitorPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -946,13 +946,14 @@ namespace ts {

case SyntaxKind.AssertClause:
return factory.updateAssertClause(<AssertClause>node,
nodesVisitor((node as AssertClause).elements, visitor, isAssertEntry));
nodesVisitor((node as AssertClause).elements, visitor, isAssertEntry),
(node as AssertClause).multiLine);

case SyntaxKind.AssertEntry:
return factory.updateAssertEntry(<AssertEntry>node,
nodeVisitor((<AssertEntry>node).name, visitor, isAssertionKey),
nodeVisitor((<AssertEntry>node).value, visitor, isStringLiteral));

case SyntaxKind.NamespaceImport:
return factory.updateNamespaceImport(<NamespaceImport>node,
nodeVisitor((<NamespaceImport>node).name, visitor, isIdentifier));
Expand Down
5 changes: 3 additions & 2 deletions src/testRunner/unittests/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ namespace ts {
const exports = [{ name: "x" }];
const exportSpecifiers = exports.map(e => factory.createExportSpecifier(e.name, e.name));
const exportClause = factory.createNamedExports(exportSpecifiers);
const newEd = factory.updateExportDeclaration(ed, ed.decorators, ed.modifiers, ed.isTypeOnly, exportClause, ed.moduleSpecifier);
const newEd = factory.updateExportDeclaration(ed, ed.decorators, ed.modifiers, ed.isTypeOnly, exportClause, ed.moduleSpecifier, ed.assertClause);

return newEd as Node as T;
}
Expand Down Expand Up @@ -293,7 +293,8 @@ namespace ts {
/*name*/ undefined,
factory.createNamespaceImport(factory.createIdentifier("i0"))
),
/*moduleSpecifier*/ factory.createStringLiteral("./comp1"));
/*moduleSpecifier*/ factory.createStringLiteral("./comp1"),
/*assertClause*/ undefined);
return factory.updateSourceFile(sf, [importStar]);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
tests/cases/conformance/esnext/importAssertion/1.ts(1,14): error TS2796: Import assertions are not available when targeting lower than esnext.
tests/cases/conformance/esnext/importAssertion/1.ts(2,28): error TS2796: Import assertions are not available when targeting lower than esnext.
tests/cases/conformance/esnext/importAssertion/1.ts(3,28): error TS2796: Import assertions are not available when targeting lower than esnext.
tests/cases/conformance/esnext/importAssertion/2.ts(1,28): error TS2796: Import assertions are not available when targeting lower than esnext.
tests/cases/conformance/esnext/importAssertion/2.ts(2,38): error TS2796: Import assertions are not available when targeting lower than esnext.
tests/cases/conformance/esnext/importAssertion/3.ts(2,11): error TS1324: Dynamic import must have one specifier as an argument.
tests/cases/conformance/esnext/importAssertion/3.ts(3,11): error TS1324: Dynamic import must have one specifier as an argument.
tests/cases/conformance/esnext/importAssertion/3.ts(4,11): error TS1324: Dynamic import must have one specifier as an argument.
tests/cases/conformance/esnext/importAssertion/3.ts(6,11): error TS1324: Dynamic import must have one specifier as an argument.
tests/cases/conformance/esnext/importAssertion/3.ts(7,11): error TS1324: Dynamic import must have one specifier as an argument.
tests/cases/conformance/esnext/importAssertion/3.ts(8,11): error TS1324: Dynamic import must have one specifier as an argument.


==== tests/cases/conformance/esnext/importAssertion/0.ts (0 errors) ====
export const a = 1;
export const b = 2;

==== tests/cases/conformance/esnext/importAssertion/1.ts (3 errors) ====
import './0' assert { type: "json" }
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2796: Import assertions are not available when targeting lower than esnext.
import { a, b } from './0' assert { "type": "json" }
~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2796: Import assertions are not available when targeting lower than esnext.
import * as foo from './0' assert { type: "json" }
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2796: Import assertions are not available when targeting lower than esnext.
a;
b;
foo.a;
foo.b;

==== tests/cases/conformance/esnext/importAssertion/2.ts (2 errors) ====
import { a, b } from './0' assert {}
~~~~~~~~~
!!! error TS2796: Import assertions are not available when targeting lower than esnext.
import { a as c, b as d } from './0' assert { a: "a", b: "b", c: "c" }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2796: Import assertions are not available when targeting lower than esnext.
a;
b;
c;
d;

==== tests/cases/conformance/esnext/importAssertion/3.ts (6 errors) ====
const a = import('./0')
const b = import('./0', { type: "json" })
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1324: Dynamic import must have one specifier as an argument.
const c = import('./0', { type: "json", ttype: "typo" })
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1324: Dynamic import must have one specifier as an argument.
const d = import('./0', { })
~~~~~~~~~~~~~~~~~~
!!! error TS1324: Dynamic import must have one specifier as an argument.
declare function foo(): any;
const e = import('./0', foo())
~~~~~~~~~~~~~~~~~~~~
!!! error TS1324: Dynamic import must have one specifier as an argument.
const f = import()
~~~~~~~~
!!! error TS1324: Dynamic import must have one specifier as an argument.
const g = import('./0', {}, {})
~~~~~~~~~~~~~~~~~~~~~
!!! error TS1324: Dynamic import must have one specifier as an argument.

Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy