Skip to content
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

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

Merged
merged 23 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from 10 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
143 changes: 79 additions & 64 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

42 changes: 37 additions & 5 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
"category": "Error",
"code": 1007
},
"The 'assert' keyword in import attributes is deprecated and has been replaced by the 'with' keyword.": {
andrewbranch marked this conversation as resolved.
Show resolved Hide resolved
"category": "Error",
"code": 1008
},
"Trailing comma not allowed.": {
"category": "Error",
"code": 1009
Expand Down Expand Up @@ -1472,7 +1476,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 +1524,18 @@
"category": "Message",
"code": 1461
},
"'resolution-mode' attribute are only supported when `moduleResolution` is `node16` or `nodenext`.": {
andrewbranch marked this conversation as resolved.
Show resolved Hide resolved
"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`.": {
andrewbranch marked this conversation as resolved.
Show resolved Hide resolved
"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 +1641,10 @@
"category": "Error",
"code": 1495
},
"Identifier, string literal or number literal expected.": {
andrewbranch marked this conversation as resolved.
Show resolved Hide resolved
"category": "Error",
"code": 1496
},

"The types of '{0}' are incompatible between these types.": {
"category": "Error",
Expand Down Expand Up @@ -3579,6 +3599,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 @@ -3663,6 +3687,18 @@
"category": "Error",
"code": 2854
},
"Import attributes are not allowed on statements that transpile to CommonJS 'require' calls.": {
a-tarasyuk marked this conversation as resolved.
Show resolved Hide resolved
"category": "Error",
"code": 2855
},
"Import attributes cannot be used with type-only imports or exports.": {
"category": "Error",
"code": 2856
},
"Import attribute values must be string literal expressions.": {
"category": "Error",
"code": 2857
},

"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
Expand Down Expand Up @@ -4096,10 +4132,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
48 changes: 44 additions & 4 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ import {
Identifier,
idText,
IfStatement,
ImportAttribute,
ImportAttributes,
ImportClause,
ImportDeclaration,
ImportEqualsDeclaration,
Expand Down Expand Up @@ -2058,6 +2060,10 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
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 @@ -2960,6 +2966,19 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
writeSpace();
writePunctuation("}");
}
if (node.attributes) {
writePunctuation(",");
writeSpace();
writePunctuation("{");
writeSpace();
writeKeyword("with");
writePunctuation(":");
writeSpace();
const elements = node.attributes.attributes.elements;
emitList(node.attributes.attributes, elements, ListFormat.ImportAttributes);
writeSpace();
writePunctuation("}");
}
writePunctuation(")");
if (node.qualifier) {
writePunctuation(".");
Expand Down Expand Up @@ -3991,8 +4010,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
writeSpace();
}
emitExpression(node.moduleSpecifier);
if (node.assertClause) {
emitWithLeadingSpace(node.assertClause);
if (node.attributes || node.assertClause) {
emitWithLeadingSpace(node.attributes || node.assertClause);
}
writeTrailingSemicolon();
}
Expand Down Expand Up @@ -4066,8 +4085,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
writeSpace();
emitExpression(node.moduleSpecifier);
}
if (node.assertClause) {
emitWithLeadingSpace(node.assertClause);
if (node.attributes || node.assertClause) {
emitWithLeadingSpace(node.attributes || node.assertClause);
}
writeTrailingSemicolon();
}
Expand All @@ -4093,6 +4112,27 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
emit(value);
}

function emitImportAttributes(node: ImportAttributes) {
emitTokenWithComment(SyntaxKind.WithKeyword, node.pos, writeKeyword, node);
writeSpace();
const elements = node.elements;
emitList(node, elements, ListFormat.ImportAttributes);
}

function emitImportAttribute(node: ImportAttribute) {
emit(node.name);
writePunctuation(":");
writeSpace();

const value = node.value;
/** @see {emitPropertyAssignment} */
if ((getEmitFlags(value) & EmitFlags.NoLeadingComments) === 0) {
const commentRange = getCommentRange(value);
emitTrailingCommentsOfPosition(commentRange.pos);
}
emit(value);
}

function emitNamespaceExportDeclaration(node: NamespaceExportDeclaration) {
let nextPos = emitTokenWithComment(SyntaxKind.ExportKeyword, node.pos, writeKeyword, node);
writeSpace();
Expand Down
82 changes: 77 additions & 5 deletions src/compiler/factory/nodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,15 @@ import {
IfStatement,
ImmediatelyInvokedArrowFunction,
ImmediatelyInvokedFunctionExpression,
ImportAttribute,
ImportAttributeName,
ImportAttributes,
ImportClause,
ImportDeclaration,
ImportEqualsDeclaration,
ImportSpecifier,
ImportTypeAssertionContainer,
ImportTypeAttributes,
ImportTypeNode,
IndexedAccessTypeNode,
IndexSignatureDeclaration,
Expand Down Expand Up @@ -791,6 +795,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
updateAssertEntry,
createImportTypeAssertionContainer,
updateImportTypeAssertionContainer,
createImportTypeAttributes,
updateImportTypeAttributes,
createImportAttributes,
updateImportAttributes,
createImportAttribute,
updateImportAttribute,
createNamespaceImport,
updateNamespaceImport,
createNamespaceExport,
Expand Down Expand Up @@ -2644,13 +2654,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
function createImportTypeNode(
argument: TypeNode,
assertions?: ImportTypeAssertionContainer,
attributes?: ImportTypeAttributes,
andrewbranch marked this conversation as resolved.
Show resolved Hide resolved
qualifier?: EntityName,
typeArguments?: readonly TypeNode[],
isTypeOf = false,
): ImportTypeNode {
const node = createBaseNode<ImportTypeNode>(SyntaxKind.ImportType);
node.argument = argument;
node.assertions = assertions;
node.attributes = attributes;
node.qualifier = qualifier;
node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments);
node.isTypeOf = isTypeOf;
Expand All @@ -2663,16 +2675,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
node: ImportTypeNode,
argument: TypeNode,
assertions: ImportTypeAssertionContainer | undefined,
attributes: ImportTypeAttributes | 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, assertions, attributes, qualifier, typeArguments, isTypeOf), node)
: node;
}

Expand Down Expand Up @@ -4697,12 +4711,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
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 = attributes;
node.transformFlags |= propagateChildFlags(node.importClause) |
propagateChildFlags(node.moduleSpecifier);
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
Expand All @@ -4718,12 +4734,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
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, assertClause, attributes), node)
: node;
}

Expand Down Expand Up @@ -4801,6 +4819,56 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
: node;
}

// @api
function createImportTypeAttributes(attributes: ImportAttributes, multiLine?: boolean): ImportTypeAttributes {
const node = createBaseNode<ImportTypeAttributes>(SyntaxKind.ImportTypeAttributes);
node.attributes = attributes;
node.multiLine = multiLine;
return node;
}

// @api
function updateImportTypeAttributes(node: ImportTypeAttributes, attributes: ImportAttributes, multiLine?: boolean): ImportTypeAttributes {
return node.attributes !== attributes
|| node.multiLine !== multiLine
? update(createImportTypeAttributes(attributes, multiLine), node)
: node;
}

// @api
function createImportAttributes(elements: readonly ImportAttribute[], multiLine?: boolean): ImportAttributes {
const node = createBaseNode<ImportAttributes>(SyntaxKind.ImportAttributes);
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)
: 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 @@ -4909,13 +4977,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
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 = attributes;
node.transformFlags |= propagateChildrenFlags(node.modifiers) |
propagateChildFlags(node.exportClause) |
propagateChildFlags(node.moduleSpecifier);
Expand All @@ -4933,13 +5003,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
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, assertClause, attributes), node)
: node;
}

Expand Down Expand Up @@ -7084,9 +7156,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.assertClause, 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.assertClause, node.attributes) :
Debug.assertNever(node);
}

Expand Down
Loading