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
7a05f24
feat(53656): Add support for the revised import attributes proposal
a-tarasyuk Aug 25, 2023
6489c39
update diagnostic message
a-tarasyuk Aug 25, 2023
4c8bad1
update baseline
a-tarasyuk Aug 25, 2023
1a0fb93
mark util function as internal
a-tarasyuk Aug 26, 2023
642667e
emit import attributes
a-tarasyuk Aug 26, 2023
fc2093c
update baseline
a-tarasyuk Aug 26, 2023
4a16bf2
add deprecation diagnostic message
a-tarasyuk Aug 29, 2023
dbd7eb5
update baseline
a-tarasyuk Aug 29, 2023
bebf687
update diagnostic message
a-tarasyuk Sep 12, 2023
a387700
remove the nightly-only restriction of resolution mode override
a-tarasyuk Sep 14, 2023
78a01bd
Merge branch 'main' of https://github.com/microsoft/TypeScript into f…
a-tarasyuk Sep 14, 2023
0113dfe
remove unused diagnostic message
a-tarasyuk Sep 14, 2023
14c6226
AssertClause -> ImportAttributes
a-tarasyuk Sep 21, 2023
2569ec3
fix formatting
a-tarasyuk Sep 21, 2023
8482633
fix tests
a-tarasyuk Sep 21, 2023
ba1f979
baseline update
a-tarasyuk Sep 21, 2023
11d556a
remove token param from public API
a-tarasyuk Sep 21, 2023
e0afc4a
fix factory api signatures
a-tarasyuk Sep 21, 2023
3d3939a
update diagnostic messages
a-tarasyuk Sep 22, 2023
bf36343
rid of ImportTypeAttributes interface
a-tarasyuk Sep 22, 2023
a990ddd
remove deprecation diagnostic message
a-tarasyuk Sep 22, 2023
de897d4
update baseline
a-tarasyuk Sep 22, 2023
82e078f
Merge branch 'main' of https://github.com/microsoft/TypeScript into f…
a-tarasyuk Sep 23, 2023
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