-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Serialize (noncontextual) keyword named namespace members with export declarations in both declaration emitters #38982
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
Serialize (noncontextual) keyword named namespace members with export declarations in both declaration emitters #38982
Conversation
… declarations in both declaration emitters
@@ -139,7 +139,7 @@ export namespace f { | |||
* @template T | |||
* @param {T} a | |||
*/ | |||
export function self<T>(a: T): T; | |||
function self<T>(a: T): T; |
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.
While working on this, I found a need for the js declaration emitter to automatically add/strip export modifiers from nested namespace members as needed; so the result of this can be seen in some baseline updates like this - since every member of the containing namespace was export
ed, there was no need to explicitly have the export
modifiers. Now they get stripped, consistent with our transform-based declaration emitter.
@@ -73,7 +73,7 @@ declare class B3 implements A { | |||
} | |||
declare namespace Ns { | |||
export { C1 }; | |||
const C5: { | |||
export const C5: { |
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.
Yes, this was mistakenly missing an export
modifier before. (The export
statement above made it required, but the emitter never added it).
@@ -285,7 +285,7 @@ module.exports = x; | |||
}, | |||
"./obj.json": { | |||
"version": "2151907832-{\n \"val\": 42\n}", | |||
"signature": "-6323167306-export declare const val: number;\r\n", | |||
"signature": "-5546159834-export const val: number;\r\n", |
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.
So! Fun fact: We parse json documents essentially as export = { val: 42 }
. Previous to this change, we'd serialize it to
declare namespace export_ {
export declare const val: number;
}
export = _export;
then inline it to
export declare const val: number;
Now, we first make
declare namespace export_ {
const val: number;
}
export = _export;
since we can omit the export and declare modifiers, and inline to
const val: number;
which we then patch an export
modifier back onto (since we're inlining a namespace where everything was implicitly exported):
export const val: number;
so our frugality with the export
modifier has, in this case, also caused us to be more frugal with the declare
modifier, too. This should be fine, since everything in a .d.ts
file is already implicitly declare
'd anyway.
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.
The fix looks right. I have a few suggestions and one small question before you merge.
@@ -0,0 +1,84 @@ | |||
// @declaration: true |
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.
nitpick: shouldn't this test be named tsDeclarationsFunctionKeywordPropExhaustive to match the js test?
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.
I pulled this in from @a-tarasyuk 's PR and wanted to preserve his history.
declare namespace foo { | ||
export var x: number; | ||
export var y: number; | ||
var _a: number; |
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.
wwhy doesn't the ts version generate good names like _break? I guess it's because the JS declaration emit is purpose-built for this, but the TS code is pre-existing.
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.
Pretty much that. The TS code is just using getGeneratedNameForNode
(which is simple and uses these alphanumeric names), while the JS code has a lot of scope tracking machinery in getInternalSymbolName
to generate better names where possible.
/*modifiers*/ undefined, | ||
createNamedExports([createExportSpecifier(d.expression, createIdentifier(InternalSymbolName.Default))]) | ||
) : d); | ||
const exportModifierStripped = every(defaultReplaced, d => hasSyntacticModifier(d, ModifierFlags.Export)) ? map(defaultReplaced, removeExportModifier) : defaultReplaced; |
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.
Don't we have a mapSame
that would make this more succnctly expressed as
const exportModifierStripped = every(defaultReplaced, d => hasSyntacticModifier(d, ModifierFlags.Export)) ? map(defaultReplaced, removeExportModifier) : defaultReplaced; | |
const exportModifierStripped = mapSame(defaultReplaced, d => hasSyntacticModifier(d, ModifierFlags.Export) ? removeExportModifier(d) : d); | |
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.
Nope, that's not the same at all 😄
If and only if every export has an export modifier, then we can strip the export modifier from every export and retain the same meaning. With your suggestion, we'd remove export modifiers from everything, even if some things didn't have export modifiers, which is very wrong and would make privates public.
@@ -5936,6 +5939,13 @@ namespace ts { | |||
statement.modifierFlagsCache = 0; | |||
} | |||
|
|||
function removeExportModifier(statement: Statement) { |
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.
could this be defined closer to its usage?
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.
I prefer it to be here, next to it's cousin, addExportModifier
, whose implementation is nearly identical.
* upstream/master: (22 commits) Small fix in `getIsContextSensitiveAssignmentOrContextType` Simplify `visitObjectLiteralExpression` Fix handling of `aruments` in the emitter Fix declaration emit for property references of imported object literal types (microsoft#39055) Fix casing for wild card keys for implicit globs to get wild card directories to watch (microsoft#39049) DOM update 2020-06-12 fix(a11y): make ISSUE_TEMPLATE/Bug_report.md more accessible for folks with screen readers (microsoft#39013) Update request-pr-review script to latest version of octokit (microsoft#39031) pin version of octokit skip implements types with no symbols isDynamicName skips parentheses for element access Allow `e: unknown` in `catch` arguments Serialize (noncontextual) keyword named namespace members with export declarations in both declaration emitters (microsoft#38982) Patch to use this.timeout() > 0 rather than this.enableTimeout() to work with mocha 8+ Handle missing return type nodes and nested type references missing type arguments in existing jsdoc node serialization (microsoft#39011) Add containerName to CallHierarchyItem (microsoft#38997) Fix isSameEntityName (microsoft#38999) Fix typo for 'blocklist' (microsoft#39001) remove errant tab Switch to isSymbolAccessible for both. ...
Fixes #38750
cc @a-tarasyuk I pulled in your test from #38874; I went with a slightly different style of emit for the normal declaration emitter, and, well, the js declaration emitter was just another beast entirely (note for reviewers: I inlined one of the helper functions in the js declaration emitter, so the change isn't actually that large; I just had to inline the helper to set a condition in a branch of it).
Note that the OP in #38750 was hoping to also have non-identifier strings like
"foo bar"
also roundtrip; unfortunately, with this emit scheme (as @DanielRosenwasser proposed), such a thing is not possible (without amending syntax somewhere anyway).