-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Allow export default const enum, export default enum, export default … #18628
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -426,6 +426,15 @@ namespace ts { | |
symbol = createSymbol(SymbolFlags.None, name); | ||
} | ||
} | ||
else if (isDefaultExport && parent && symbol.declarations && symbol.declarations.length) { | ||
// && parent because we only want to check the export default symbol. | ||
// if there is already an export default declaration, make sure that their local names are the same. | ||
if (symbol.declarations[0].localSymbol !== node.localSymbol) { | ||
const message = Diagnostics.Merged_default_exports_must_have_the_same_name; | ||
file.bindDiagnostics.push(createDiagnosticForNode(getNameOfDeclaration(symbol.declarations[0]) || symbol.declarations[0], message)); | ||
file.bindDiagnostics.push(createDiagnosticForNode(getNameOfDeclaration(node) || node, message)); | ||
} | ||
} | ||
} | ||
|
||
addDeclarationToSymbol(symbol, node, includes); | ||
|
@@ -472,8 +481,8 @@ namespace ts { | |
} | ||
const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0; | ||
const local = declareSymbol(container.locals!, /*parent*/ undefined, node, exportKind, symbolExcludes); | ||
local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); | ||
node.localSymbol = local; | ||
local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); | ||
return local; | ||
} | ||
else { | ||
|
@@ -1381,7 +1390,7 @@ namespace ts { | |
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag) { | ||
if (node.fullName) { | ||
setParentPointers(node, node.fullName); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The indentation here is wrong. |
||
} | ||
|
||
function bindCallExpressionFlow(node: CallExpression) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1414,11 +1414,11 @@ namespace ts { | |
case SyntaxKind.ExportKeyword: | ||
nextToken(); | ||
if (token() === SyntaxKind.DefaultKeyword) { | ||
return lookAhead(nextTokenCanFollowDefaultKeyword); | ||
return lookAhead(nextTokenCanFollowDefaultModifier); | ||
} | ||
return token() !== SyntaxKind.AsteriskToken && token() !== SyntaxKind.AsKeyword && token() !== SyntaxKind.OpenBraceToken && canFollowModifier(); | ||
case SyntaxKind.DefaultKeyword: | ||
return nextTokenCanFollowDefaultKeyword(); | ||
return nextTokenCanFollowDefaultModifier(); | ||
case SyntaxKind.StaticKeyword: | ||
case SyntaxKind.GetKeyword: | ||
case SyntaxKind.SetKeyword: | ||
|
@@ -1441,12 +1441,37 @@ namespace ts { | |
|| isLiteralPropertyName(); | ||
} | ||
|
||
function nextTokenCanFollowDefaultKeyword(): boolean { | ||
/** | ||
* For export default assignments like | ||
* "export default foo" | ||
* "export default async" | ||
* no modifiers should be parsed. | ||
*/ | ||
function nextTokenCanFollowDefaultModifier(): boolean { | ||
nextToken(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nextTokenCanFollowDefaultKeyword doesn't really seem like an accurate name considering it's looking at multiple? Same with nextTokenCanFollowModifier. Would something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the name is fine since it doesn't take a |
||
return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword || | ||
token() === SyntaxKind.InterfaceKeyword || | ||
(token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) || | ||
(token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); | ||
switch (token()) { | ||
case SyntaxKind.ClassKeyword: | ||
case SyntaxKind.FunctionKeyword: | ||
case SyntaxKind.EnumKeyword: | ||
case SyntaxKind.NamespaceKeyword: | ||
case SyntaxKind.ModuleKeyword: | ||
case SyntaxKind.ConstKeyword: | ||
return true; | ||
|
||
// The following keywords aren't reserved keywords and could be identifiers. | ||
// We need to look at the next token to make sure these should be parsed as a modifier keyword, | ||
// and not as an identifier. If they are followed by an identifier or a keyword on the same line, | ||
// the current statement is not an export default assignment. | ||
// See https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#221-reserved-words | ||
case SyntaxKind.InterfaceKeyword: | ||
case SyntaxKind.AbstractKeyword: | ||
case SyntaxKind.DeclareKeyword: | ||
case SyntaxKind.AsyncKeyword: | ||
case SyntaxKind.TypeKeyword: | ||
return lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rbuckton This simplified lookahead seems to be enough; see 5113249#diff-cc2127059a7624c4bd840e11d106cb81 |
||
default: | ||
return false; | ||
} | ||
} | ||
|
||
// True if positioned at the start of a list element | ||
|
@@ -4081,14 +4106,14 @@ namespace ts { | |
let expression: MemberExpression; | ||
if (token() === SyntaxKind.ImportKeyword) { | ||
if (lookAhead(nextTokenIsOpenParenOrLessThan)) { | ||
// We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "(" | ||
// For example: | ||
// var foo3 = require("subfolder | ||
// import * as foo1 from "module-from-node | ||
// We want this import to be a statement rather than import call expression | ||
sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport; | ||
expression = parseTokenNode<PrimaryExpression>(); | ||
} | ||
// We don't want to eagerly consume all import keyword as import call expression so we look a head to find "(" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The indentation here is wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// For example: | ||
// var foo3 = require("subfolder | ||
// import * as foo1 from "module-from-node | ||
// We want this import to be a statement rather than import call expression | ||
sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport; | ||
expression = parseTokenNode<PrimaryExpression>(); | ||
} | ||
else if (lookAhead(nextTokenIsDot)) { | ||
// This is an 'import.*' metaproperty (i.e. 'import.meta') | ||
const fullStart = scanner.getStartPos(); | ||
|
@@ -4101,7 +4126,7 @@ namespace ts { | |
|
||
sourceFile.flags |= NodeFlags.PossiblyContainsImportMeta; | ||
} | ||
else { | ||
else { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The indentation here is wrong. |
||
expression = parseMemberExpressionOrHigher(); | ||
} | ||
} | ||
|
@@ -5118,11 +5143,6 @@ namespace ts { | |
return tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak(); | ||
} | ||
|
||
function nextTokenIsClassKeywordOnSameLine() { | ||
nextToken(); | ||
return token() === SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak(); | ||
} | ||
|
||
function nextTokenIsFunctionKeywordOnSameLine() { | ||
nextToken(); | ||
return token() === SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak(); | ||
|
@@ -6233,7 +6253,7 @@ namespace ts { | |
sourceFile.externalModuleIndicator = | ||
forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) || | ||
getImportMetaIfNecessary(sourceFile); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The indentation here is wrong. |
||
|
||
function isAnExternalModuleIndicatorNode(node: Node) { | ||
return hasModifier(node, ModifierFlags.Export) | ||
|
@@ -6243,17 +6263,17 @@ namespace ts { | |
|| node.kind === SyntaxKind.ExportDeclaration | ||
? node | ||
: undefined; | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The indentation here is wrong. |
||
|
||
function getImportMetaIfNecessary(sourceFile: SourceFile) { | ||
return sourceFile.flags & NodeFlags.PossiblyContainsImportMeta ? | ||
walkTreeForExternalModuleIndicators(sourceFile) : | ||
undefined; | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The indentation here is wrong. |
||
|
||
function walkTreeForExternalModuleIndicators(node: Node): Node | undefined { | ||
return isImportMeta(node) ? node : forEachChild(node, walkTreeForExternalModuleIndicators); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The indentation here is wrong. |
||
|
||
function isImportMeta(node: Node): boolean { | ||
return isMetaProperty(node) && node.keywordToken === SyntaxKind.ImportKeyword && node.name.escapedText === "meta"; | ||
|
@@ -6468,7 +6488,7 @@ namespace ts { | |
break; | ||
} | ||
nextJSDocToken(); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The indentation here is wrong. |
||
removeLeadingNewlines(comments); | ||
removeTrailingWhitespace(comments); | ||
return createJSDocComment(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.