Skip to content

Commit

Permalink
Add parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Kingwl committed Sep 22, 2020
1 parent 7c6462a commit e1b3b78
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 33 deletions.
14 changes: 9 additions & 5 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6130,7 +6130,7 @@ namespace ts {

function inlineExportModifiers(statements: Statement[]) {
// Pass 3: Move all `export {}`'s to `export` modifiers where possible
const index = findIndex(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !!d.exportClause && isNamedExports(d.exportClause));
const index = findIndex(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !d.assertClause && !!d.exportClause && isNamedExports(d.exportClause));
if (index >= 0) {
const exportDecl = statements[index] as ExportDeclaration & { readonly exportClause: NamedExports };
const replacements = mapDefined(exportDecl.exportClause.elements, e => {
Expand Down Expand Up @@ -6162,7 +6162,8 @@ namespace ts {
exportDecl.exportClause,
replacements
),
exportDecl.moduleSpecifier
exportDecl.moduleSpecifier,
exportDecl.assertClause
);
}
}
Expand Down Expand Up @@ -6798,15 +6799,17 @@ namespace ts {
// We use `target.parent || target` below as `target.parent` is unset when the target is a module which has been export assigned
// And then made into a default by the `esModuleInterop` or `allowSyntheticDefaultImports` flag
// In such cases, the `target` refers to the module itself already
factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context))
factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)),
/*assertClause*/ undefined
), ModifierFlags.None);
break;
case SyntaxKind.NamespaceImport:
addResult(factory.createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
factory.createImportClause(/*isTypeOnly*/ false, /*importClause*/ undefined, factory.createNamespaceImport(factory.createIdentifier(localName))),
factory.createStringLiteral(getSpecifierForModuleSymbol(target, context))
factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)),
/*assertClause*/ undefined
), ModifierFlags.None);
break;
case SyntaxKind.NamespaceExport:
Expand All @@ -6831,7 +6834,8 @@ namespace ts {
factory.createIdentifier(localName)
)
])),
factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context))
factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)),
/*assertClause*/ undefined
), ModifierFlags.None);
break;
case SyntaxKind.ExportSpecifier:
Expand Down
60 changes: 52 additions & 8 deletions src/compiler/factory/nodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ namespace ts {
updateImportDeclaration,
createImportClause,
updateImportClause,
createAssertClause,
updateAssertClause,
createAssertEntry,
updateAssertEntry,
createNamespaceImport,
updateNamespaceImport,
createNamespaceExport,
Expand Down Expand Up @@ -3790,7 +3794,8 @@ namespace ts {
decorators: readonly Decorator[] | undefined,
modifiers: readonly Modifier[] | undefined,
importClause: ImportClause | undefined,
moduleSpecifier: Expression
moduleSpecifier: Expression,
assertClause: AssertClause | undefined
): ImportDeclaration {
const node = createBaseDeclaration<ImportDeclaration>(
SyntaxKind.ImportDeclaration,
Expand All @@ -3799,6 +3804,7 @@ namespace ts {
);
node.importClause = importClause;
node.moduleSpecifier = moduleSpecifier;
node.assertClause = assertClause;
node.transformFlags |=
propagateChildFlags(node.importClause) |
propagateChildFlags(node.moduleSpecifier);
Expand All @@ -3812,13 +3818,15 @@ namespace ts {
decorators: readonly Decorator[] | undefined,
modifiers: readonly Modifier[] | undefined,
importClause: ImportClause | undefined,
moduleSpecifier: Expression
moduleSpecifier: Expression,
assertClause: AssertClause | undefined
) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.importClause !== importClause
|| node.moduleSpecifier !== moduleSpecifier
? update(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier), node)
|| node.assertClause !== assertClause
? update(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier, assertClause), node)
: node;
}

Expand Down Expand Up @@ -3847,6 +3855,38 @@ namespace ts {
: node;
}

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

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

// @api
function createAssertEntry(name: AssertionKey, value: StringLiteral): AssertEntry {
const node = createBaseNode<AssertEntry>(SyntaxKind.AssertEntry);
node.name = name;
node.value = value;
node.transformFlags |= TransformFlags.ContainsESNext;
return node;
}

// @api
function updateAssertEntry (node: AssertEntry, name: AssertionKey, value: StringLiteral): AssertEntry {
return node.name !== name
|| node.value !== value
? update(createAssertEntry(name, value), node)
: node;
}

// @api
function createNamespaceImport(name: Identifier): NamespaceImport {
const node = createBaseNode<NamespaceImport>(SyntaxKind.NamespaceImport);
Expand Down Expand Up @@ -3958,7 +3998,8 @@ namespace ts {
modifiers: readonly Modifier[] | undefined,
isTypeOnly: boolean,
exportClause: NamedExportBindings | undefined,
moduleSpecifier?: Expression
moduleSpecifier?: Expression,
assertClause?: AssertClause
) {
const node = createBaseDeclaration<ExportDeclaration>(
SyntaxKind.ExportDeclaration,
Expand All @@ -3968,6 +4009,7 @@ namespace ts {
node.isTypeOnly = isTypeOnly;
node.exportClause = exportClause;
node.moduleSpecifier = moduleSpecifier;
node.assertClause = assertClause;
node.transformFlags |=
propagateChildFlags(node.exportClause) |
propagateChildFlags(node.moduleSpecifier);
Expand All @@ -3982,14 +4024,16 @@ namespace ts {
modifiers: readonly Modifier[] | undefined,
isTypeOnly: boolean,
exportClause: NamedExportBindings | undefined,
moduleSpecifier: Expression | undefined
moduleSpecifier: Expression | undefined,
assertClause: AssertClause | undefined
) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.isTypeOnly !== isTypeOnly
|| node.exportClause !== exportClause
|| node.moduleSpecifier !== moduleSpecifier
? update(createExportDeclaration(decorators, modifiers, isTypeOnly, exportClause, moduleSpecifier), node)
|| node.assertClause !== assertClause
? update(createExportDeclaration(decorators, modifiers, isTypeOnly, exportClause, moduleSpecifier, assertClause), node)
: node;
}

Expand Down Expand Up @@ -5776,9 +5820,9 @@ namespace ts {
isEnumDeclaration(node) ? updateEnumDeclaration(node, node.decorators, modifiers, node.name, node.members) :
isModuleDeclaration(node) ? updateModuleDeclaration(node, node.decorators, modifiers, node.name, node.body) :
isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, node.decorators, modifiers, node.name, node.moduleReference) :
isImportDeclaration(node) ? updateImportDeclaration(node, node.decorators, modifiers, node.importClause, node.moduleSpecifier) :
isImportDeclaration(node) ? updateImportDeclaration(node, node.decorators, modifiers, node.importClause, node.moduleSpecifier, node.assertClause) :
isExportAssignment(node) ? updateExportAssignment(node, node.decorators, modifiers, node.expression) :
isExportDeclaration(node) ? updateExportDeclaration(node, node.decorators, modifiers, node.isTypeOnly, node.exportClause, node.moduleSpecifier) :
isExportDeclaration(node) ? updateExportDeclaration(node, node.decorators, modifiers, node.isTypeOnly, node.exportClause, node.moduleSpecifier, node.assertClause) :
Debug.assertNever(node);
}

Expand Down
8 changes: 8 additions & 0 deletions src/compiler/factory/nodeTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,14 @@ namespace ts {
return node.kind === SyntaxKind.ImportClause;
}

export function isAssertClause(node: Node): node is AssertClause {
return node.kind === SyntaxKind.AssertClause;
}

export function isAssertEntry(node: Node): node is AssertEntry {
return node.kind === SyntaxKind.AssertEntry;
}

export function isNamespaceImport(node: Node): node is NamespaceImport {
return node.kind === SyntaxKind.NamespaceImport;
}
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/factory/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,8 @@ namespace ts {
/*decorators*/ undefined,
/*modifiers*/ undefined,
nodeFactory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, namedBindings),
nodeFactory.createStringLiteral(externalHelpersModuleNameText)
nodeFactory.createStringLiteral(externalHelpersModuleNameText),
/*assertClause*/ undefined
);
addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper);
return externalHelpersImportDeclaration;
Expand Down
42 changes: 38 additions & 4 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1690,6 +1690,11 @@ namespace ts {
token() === SyntaxKind.NumericLiteral;
}

function isAssertionKey(): boolean {
return tokenIsIdentifierOrKeyword(token()) ||
token() === SyntaxKind.StringLiteral;
}

function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName {
if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) {
const node = <StringLiteral | NumericLiteral>parseLiteralNode();
Expand Down Expand Up @@ -1854,6 +1859,8 @@ namespace ts {
return isLiteralPropertyName();
case ParsingContext.ObjectBindingElements:
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
case ParsingContext.AssertEntries:
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 @@ -1974,6 +1981,7 @@ namespace ts {
case ParsingContext.ObjectLiteralMembers:
case ParsingContext.ObjectBindingElements:
case ParsingContext.ImportOrExportSpecifiers:
case ParsingContext.AssertEntries:
return token() === SyntaxKind.CloseBraceToken;
case ParsingContext.SwitchClauseStatements:
return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
Expand Down Expand Up @@ -6901,13 +6909,33 @@ namespace ts {
importClause = parseImportClause(identifier, afterImportPos, isTypeOnly);
parseExpected(SyntaxKind.FromKeyword);
}

const moduleSpecifier = parseModuleSpecifier();
const afterSpecifierPos = scanner.getStartPos();

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

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

function parseAssertEntry () {
const pos = getNodePos();
const name = tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() : parseLiteralLikeNode(SyntaxKind.StringLiteral) as StringLiteral;
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 tokenAfterImportDefinitelyProducesImportDeclaration() {
return token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.OpenBraceToken;
}
Expand Down Expand Up @@ -7058,6 +7086,7 @@ namespace ts {
setAwaitContext(/*value*/ true);
let exportClause: NamedExportBindings | undefined;
let moduleSpecifier: Expression | undefined;
let assertClause: AssertClause | undefined;
const isTypeOnly = parseOptional(SyntaxKind.TypeKeyword);
const namespaceExportPos = getNodePos();
if (parseOptional(SyntaxKind.AsteriskToken)) {
Expand All @@ -7077,9 +7106,13 @@ namespace ts {
moduleSpecifier = parseModuleSpecifier();
}
}
if (token() === SyntaxKind.AssertKeyword && !scanner.hasPrecedingLineBreak()) {
const posAfterSpecifier = getNodePos();
assertClause = parseAssertClause(posAfterSpecifier);
}
parseSemicolon();
setAwaitContext(savedAwaitContext);
const node = factory.createExportDeclaration(decorators, modifiers, isTypeOnly, exportClause, moduleSpecifier);
const node = factory.createExportDeclaration(decorators, modifiers, isTypeOnly, exportClause, moduleSpecifier, assertClause);
return withJSDoc(finishNode(node, pos), hasJSDoc);
}

Expand Down Expand Up @@ -7159,7 +7192,8 @@ namespace ts {
TypeArguments, // Type arguments in type argument list
TupleElementTypes, // Element types in tuple element type list
HeritageClauses, // Heritage clauses for a class or interface declaration.
ImportOrExportSpecifiers, // Named import clause's import specifier list
ImportOrExportSpecifiers, // Named import clause's import specifier list,
AssertEntries, // Import entries list.
Count // Number of parsing contexts
}

Expand Down
2 changes: 1 addition & 1 deletion src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2120,7 +2120,7 @@ namespace ts {
&& !file.isDeclarationFile) {
// synthesize 'import "tslib"' declaration
const externalHelpersModuleReference = factory.createStringLiteral(externalHelpersModuleNameText);
const importDecl = factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference);
const importDecl = factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference, /*assertClause*/ undefined);
addEmitFlags(importDecl, EmitFlags.NeverApplyImportHelper);
setParent(externalHelpersModuleReference, importDecl);
setParent(importDecl, file);
Expand Down
Loading

0 comments on commit e1b3b78

Please sign in to comment.