Skip to content

feat(53656): Add support for the updated import attributes proposal #54242

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 23 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
152 changes: 76 additions & 76 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

42 changes: 33 additions & 9 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1472,7 +1472,7 @@
"category": "Message",
"code": 1449
},
"Dynamic imports can only accept a module specifier and an optional assertion as arguments": {
"Dynamic imports can only accept a module specifier and an optional set of attributes as arguments": {
"category": "Message",
"code": 1450
},
Expand Down Expand Up @@ -1520,6 +1520,18 @@
"category": "Message",
"code": 1461
},
"The 'resolution-mode' attribute is only supported when 'moduleResolution' is 'node16' or 'nodenext'.": {
"category": "Error",
"code": 1462
},
"'resolution-mode' is the only valid key for type import attributes.": {
"category": "Error",
"code": 1463
},
"Type import attributes should have exactly one key - 'resolution-mode' - with value 'import' or 'require'.": {
"category": "Error",
"code": 1464
},

"The 'import.meta' meta-property is not allowed in files which will build into CommonJS output.": {
"category": "Error",
Expand Down Expand Up @@ -1625,6 +1637,10 @@
"category": "Error",
"code": 1495
},
"Identifier, string literal, or number literal expected.": {
"category": "Error",
"code": 1496
},

"The types of '{0}' are incompatible between these types.": {
"category": "Error",
Expand Down Expand Up @@ -3579,6 +3595,10 @@
"category": "Error",
"code": 2822
},
"Import attributes are only supported when the '--module' option is set to 'esnext' or 'nodenext'.": {
"category": "Error",
"code": 2823
},
"Cannot find namespace '{0}'. Did you mean '{1}'?": {
"category": "Error",
"code": 2833
Expand Down Expand Up @@ -3611,10 +3631,6 @@
"category": "Error",
"code": 2840
},
"The type of this expression cannot be named without a 'resolution-mode' assertion, which is an unstable feature. Use nightly TypeScript to silence this error. Try updating with 'npm install -D typescript@next'.": {
"category": "Error",
"code": 2841
},
"'{0}' is an unused renaming of '{1}'. Did you intend to use it as a type annotation?": {
"category": "Error",
"code": 2842
Expand Down Expand Up @@ -3667,6 +3683,18 @@
"category": "Error",
"code": 2855
},
"Import attributes are not allowed on statements that transpile to CommonJS 'require' calls.": {
"category": "Error",
"code": 2856
},
"Import attributes cannot be used with type-only imports or exports.": {
"category": "Error",
"code": 2857
},
"Import attribute values must be string literal expressions.": {
"category": "Error",
"code": 2858
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down Expand Up @@ -4100,10 +4128,6 @@
"category": "Error",
"code": 4124
},
"'resolution-mode' assertions are unstable. Use nightly TypeScript to silence this error. Try updating with 'npm install -D typescript@next'.": {
"category": "Error",
"code": 4125
},

"The current host does not support the '{0}' option.": {
"category": "Error",
Expand Down
36 changes: 18 additions & 18 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import {
ArrayTypeNode,
ArrowFunction,
AsExpression,
AssertClause,
AssertEntry,
AwaitExpression,
base64encode,
BigIntLiteral,
Expand Down Expand Up @@ -191,6 +189,8 @@ import {
Identifier,
idText,
IfStatement,
ImportAttribute,
ImportAttributes,
ImportClause,
ImportDeclaration,
ImportEqualsDeclaration,
Expand Down Expand Up @@ -2055,10 +2055,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
return emitNamedExports(node as NamedExports);
case SyntaxKind.ExportSpecifier:
return emitExportSpecifier(node as ExportSpecifier);
case SyntaxKind.AssertClause:
return emitAssertClause(node as AssertClause);
case SyntaxKind.AssertEntry:
return emitAssertEntry(node as AssertEntry);
case SyntaxKind.ImportAttributes:
return emitImportAttributes(node as ImportAttributes);
case SyntaxKind.ImportAttribute:
return emitImportAttribute(node as ImportAttribute);
case SyntaxKind.MissingDeclaration:
return;

Expand Down Expand Up @@ -2948,16 +2948,16 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
writeKeyword("import");
writePunctuation("(");
emit(node.argument);
if (node.assertions) {
if (node.attributes) {
writePunctuation(",");
writeSpace();
writePunctuation("{");
writeSpace();
writeKeyword("assert");
writeKeyword(node.attributes.token === SyntaxKind.AssertKeyword ? "assert" : "with");
writePunctuation(":");
writeSpace();
const elements = node.assertions.assertClause.elements;
emitList(node.assertions.assertClause, elements, ListFormat.ImportClauseEntries);
const elements = node.attributes.elements;
emitList(node.attributes, elements, ListFormat.ImportAttributes);
writeSpace();
writePunctuation("}");
}
Expand Down Expand Up @@ -4003,8 +4003,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
writeSpace();
}
emitExpression(node.moduleSpecifier);
if (node.assertClause) {
emitWithLeadingSpace(node.assertClause);
if (node.attributes) {
emitWithLeadingSpace(node.attributes);
}
writeTrailingSemicolon();
}
Expand Down Expand Up @@ -4078,20 +4078,20 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
writeSpace();
emitExpression(node.moduleSpecifier);
}
if (node.assertClause) {
emitWithLeadingSpace(node.assertClause);
if (node.attributes) {
emitWithLeadingSpace(node.attributes);
}
writeTrailingSemicolon();
}

function emitAssertClause(node: AssertClause) {
emitTokenWithComment(SyntaxKind.AssertKeyword, node.pos, writeKeyword, node);
function emitImportAttributes(node: ImportAttributes) {
emitTokenWithComment(node.token, node.pos, writeKeyword, node);
writeSpace();
const elements = node.elements;
emitList(node, elements, ListFormat.ImportClauseEntries);
emitList(node, elements, ListFormat.ImportAttributes);
}

function emitAssertEntry(node: AssertEntry) {
function emitImportAttribute(node: ImportAttribute) {
emit(node.name);
writePunctuation(":");
writeSpace();
Expand Down
82 changes: 65 additions & 17 deletions src/compiler/factory/nodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ import {
IfStatement,
ImmediatelyInvokedArrowFunction,
ImmediatelyInvokedFunctionExpression,
ImportAttribute,
ImportAttributeName,
ImportAttributes,
ImportClause,
ImportDeclaration,
ImportEqualsDeclaration,
Expand Down Expand Up @@ -791,6 +794,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
updateAssertEntry,
createImportTypeAssertionContainer,
updateImportTypeAssertionContainer,
createImportAttributes,
updateImportAttributes,
createImportAttribute,
updateImportAttribute,
createNamespaceImport,
updateNamespaceImport,
createNamespaceExport,
Expand Down Expand Up @@ -2643,14 +2650,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
// @api
function createImportTypeNode(
argument: TypeNode,
assertions?: ImportTypeAssertionContainer,
attributes?: ImportAttributes,
qualifier?: EntityName,
typeArguments?: readonly TypeNode[],
isTypeOf = false,
): ImportTypeNode {
const node = createBaseNode<ImportTypeNode>(SyntaxKind.ImportType);
node.argument = argument;
node.assertions = assertions;
node.attributes = attributes;
if (node.assertions && node.assertions.assertClause && node.attributes) {
(node.assertions as Mutable<ImportTypeAssertionContainer>).assertClause = node.attributes;
}
node.qualifier = qualifier;
node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments);
node.isTypeOf = isTypeOf;
Expand All @@ -2662,17 +2672,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
function updateImportTypeNode(
node: ImportTypeNode,
argument: TypeNode,
assertions: ImportTypeAssertionContainer | undefined,
attributes: ImportAttributes | undefined,
qualifier: EntityName | undefined,
typeArguments: readonly TypeNode[] | undefined,
isTypeOf: boolean = node.isTypeOf,
): ImportTypeNode {
return node.argument !== argument
|| node.assertions !== assertions
|| node.attributes !== attributes
|| node.qualifier !== qualifier
|| node.typeArguments !== typeArguments
|| node.isTypeOf !== isTypeOf
? update(createImportTypeNode(argument, assertions, qualifier, typeArguments, isTypeOf), node)
? update(createImportTypeNode(argument, attributes, qualifier, typeArguments, isTypeOf), node)
: node;
}

Expand Down Expand Up @@ -4696,13 +4706,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
modifiers: readonly ModifierLike[] | undefined,
importClause: ImportClause | undefined,
moduleSpecifier: Expression,
assertClause: AssertClause | undefined,
attributes: ImportAttributes | undefined,
): ImportDeclaration {
const node = createBaseNode<ImportDeclaration>(SyntaxKind.ImportDeclaration);
node.modifiers = asNodeArray(modifiers);
node.importClause = importClause;
node.moduleSpecifier = moduleSpecifier;
node.assertClause = assertClause;
node.attributes = node.assertClause = attributes;
node.transformFlags |= propagateChildFlags(node.importClause) |
propagateChildFlags(node.moduleSpecifier);
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
Expand All @@ -4717,13 +4727,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
modifiers: readonly ModifierLike[] | undefined,
importClause: ImportClause | undefined,
moduleSpecifier: Expression,
assertClause: AssertClause | undefined,
attributes: ImportAttributes | undefined,
) {
return node.modifiers !== modifiers
|| node.importClause !== importClause
|| node.moduleSpecifier !== moduleSpecifier
|| node.assertClause !== assertClause
? update(createImportDeclaration(modifiers, importClause, moduleSpecifier, assertClause), node)
|| node.attributes !== attributes
? update(createImportDeclaration(modifiers, importClause, moduleSpecifier, attributes), node)
: node;
}

Expand Down Expand Up @@ -4756,6 +4766,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
const node = createBaseNode<AssertClause>(SyntaxKind.AssertClause);
node.elements = createNodeArray(elements);
node.multiLine = multiLine;
node.token = SyntaxKind.AssertKeyword;
node.transformFlags |= TransformFlags.ContainsESNext;
return node;
}
Expand Down Expand Up @@ -4801,6 +4812,43 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
: node;
}

// @api
function createImportAttributes(elements: readonly ImportAttribute[], multiLine?: boolean): ImportAttributes;
function createImportAttributes(elements: readonly ImportAttribute[], multiLine?: boolean, token?: ImportAttributes["token"]): ImportAttributes;
function createImportAttributes(elements: readonly ImportAttribute[], multiLine?: boolean, token?: ImportAttributes["token"]): ImportAttributes {
const node = createBaseNode<ImportAttributes>(SyntaxKind.ImportAttributes);
node.token = token ?? SyntaxKind.WithKeyword;
node.elements = createNodeArray(elements);
node.multiLine = multiLine;
node.transformFlags |= TransformFlags.ContainsESNext;
return node;
}

// @api
function updateImportAttributes(node: ImportAttributes, elements: readonly ImportAttribute[], multiLine?: boolean): ImportAttributes {
return node.elements !== elements
|| node.multiLine !== multiLine
? update(createImportAttributes(elements, multiLine, node.token), node)
: node;
}

// @api
function createImportAttribute(name: ImportAttributeName, value: Expression): ImportAttribute {
const node = createBaseNode<ImportAttribute>(SyntaxKind.ImportAttribute);
node.name = name;
node.value = value;
node.transformFlags |= TransformFlags.ContainsESNext;
return node;
}

// @api
function updateImportAttribute(node: ImportAttribute, name: ImportAttributeName, value: Expression): ImportAttribute {
return node.name !== name
|| node.value !== value
? update(createImportAttribute(name, value), node)
: node;
}

// @api
function createNamespaceImport(name: Identifier): NamespaceImport {
const node = createBaseDeclaration<NamespaceImport>(SyntaxKind.NamespaceImport);
Expand Down Expand Up @@ -4908,14 +4956,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
isTypeOnly: boolean,
exportClause: NamedExportBindings | undefined,
moduleSpecifier?: Expression,
assertClause?: AssertClause,
attributes?: ImportAttributes,
) {
const node = createBaseDeclaration<ExportDeclaration>(SyntaxKind.ExportDeclaration);
node.modifiers = asNodeArray(modifiers);
node.isTypeOnly = isTypeOnly;
node.exportClause = exportClause;
node.moduleSpecifier = moduleSpecifier;
node.assertClause = assertClause;
node.attributes = node.assertClause = attributes;
node.transformFlags |= propagateChildrenFlags(node.modifiers) |
propagateChildFlags(node.exportClause) |
propagateChildFlags(node.moduleSpecifier);
Expand All @@ -4932,14 +4980,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
isTypeOnly: boolean,
exportClause: NamedExportBindings | undefined,
moduleSpecifier: Expression | undefined,
assertClause: AssertClause | undefined,
attributes: ImportAttributes | undefined,
) {
return node.modifiers !== modifiers
|| node.isTypeOnly !== isTypeOnly
|| node.exportClause !== exportClause
|| node.moduleSpecifier !== moduleSpecifier
|| node.assertClause !== assertClause
? finishUpdateExportDeclaration(createExportDeclaration(modifiers, isTypeOnly, exportClause, moduleSpecifier, assertClause), node)
|| node.attributes !== attributes
? finishUpdateExportDeclaration(createExportDeclaration(modifiers, isTypeOnly, exportClause, moduleSpecifier, attributes), node)
: node;
}

Expand Down Expand Up @@ -7083,9 +7131,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
isEnumDeclaration(node) ? updateEnumDeclaration(node, modifierArray, node.name, node.members) :
isModuleDeclaration(node) ? updateModuleDeclaration(node, modifierArray, node.name, node.body) :
isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, modifierArray, node.isTypeOnly, node.name, node.moduleReference) :
isImportDeclaration(node) ? updateImportDeclaration(node, modifierArray, node.importClause, node.moduleSpecifier, node.assertClause) :
isImportDeclaration(node) ? updateImportDeclaration(node, modifierArray, node.importClause, node.moduleSpecifier, node.attributes) :
isExportAssignment(node) ? updateExportAssignment(node, modifierArray, node.expression) :
isExportDeclaration(node) ? updateExportDeclaration(node, modifierArray, node.isTypeOnly, node.exportClause, node.moduleSpecifier, node.assertClause) :
isExportDeclaration(node) ? updateExportDeclaration(node, modifierArray, node.isTypeOnly, node.exportClause, node.moduleSpecifier, node.attributes) :
Debug.assertNever(node);
}

Expand Down
Loading