-
Notifications
You must be signed in to change notification settings - Fork 12.9k
fix(47821): Assertion failure on "convert to default export" in module augmentation #47829
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
Conversation
e7c7d2d
to
9cdea10
Compare
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.
A few questions.
tests/cases/fourslash/refactorConvertExport_namedToDefaultInModuleAugmentation1.ts
Outdated
Show resolved
Hide resolved
9cdea10
to
ae6b6da
Compare
ae6b6da
to
836c1da
Compare
The change looks correct to me and, in practice, there's only one caller, so whether the check is pushed upstream is mostly a hygiene thing. I think it's worth investigating, but I think the change is also acceptable as-is. |
It sounds like this is ready to go except (probably) unconditionally calling At least, I'm pretty sure that @weswigham is right in his concern, and also that there's no penalty for calling |
const parent = node.parent; | ||
if (isSourceFile(parent)) { | ||
return parent.symbol; | ||
} | ||
const symbol = parent.parent.symbol; | ||
if (symbol.valueDeclaration && isExternalModuleAugmentation(symbol.valueDeclaration)) { | ||
return checker.getMergedSymbol(symbol); | ||
} | ||
return symbol; |
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 think you just always want the merged symbol. Otherwise you won't correctly catch when an existing module augmentation adds a default export (which admittedly is very weird).
// @Filename: foo.ts
/////*a*/export function bar() {}/*b*/;
// @Filename: augmenter.ts
////import "./foo";
////declare module "./foo" {
//// export default function foo(): void;
////}
// @Filename: /b.ts
////import foo from "./foo";
So maybe just
const parent = node.parent; | |
if (isSourceFile(parent)) { | |
return parent.symbol; | |
} | |
const symbol = parent.parent.symbol; | |
if (symbol.valueDeclaration && isExternalModuleAugmentation(symbol.valueDeclaration)) { | |
return checker.getMergedSymbol(symbol); | |
} | |
return symbol; | |
const parent = node.parent; | |
const symbol = checker.getMergedSymbol(isSourceFile(parent) ? parent.symbol : parent.parent.symbol); | |
return symbol; |
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.
Import in /b.ts
will not be changed. Maybe need to use two symbols
, something like this
const parent = node.parent;
const symbol = isSourceFile(parent) ? parent.symbol : parent.parent.symbol;
const mergedSymbol = checker.getMergedSymbol(symbol);
return symbol === mergedSymbol ? [symbol] : [symbol, mergedSymbol];
or handle merged symbols directly in importTracker
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.
(edited my last comment to actually use a default import)
- import { foo } from "./foo";
+ import foo from "./foo";
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 think my previous comment also applies to default imports.
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’m sorry but I can’t actually tell what issue is being discussed here but it seems to be the one that’s preventing this from being merged. Is there a concrete failing test we can discuss?
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.
Changes should be made to the b.ts
and c.ts
files - @DanielRosenwasser am I right?
// @Filename: /a.ts
/////*a*/export function a() {}/*b*/;
// @Filename: /b.ts
////import "./a";
////declare module "./a" {
//// export function a(): void;
////}
// @Filename: /c.ts
////import { a } from "./a";
goTo.select("a", "b");
edit.applyRefactor({
refactorName: "Convert export",
actionName: "Convert named export to default export",
actionDescription: "Convert named export to default export",
newContent: {
"/a.ts":
`export default function a() {};`,
"/b.ts":
`import "./a";
declare module "./a" {
export default function a(): void;
}`,
"/c.ts":
`import a from "./a";`
}
});
If we use only the merged symbol, changes will only be made in the /b.ts
file. I see two ways how we can fix it -
- fix(47821): Assertion failure on "convert to default export" in module augmentation #47829 (comment),
FindAllReferences.Core.eachExportReference(program.getSourceFiles(), checker, cancellationToken, exportSymbol, exportingModuleSymbol, exportName.text, wasDefault, ref => {
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.
Changes should be made to the
b.ts
andc.ts
files
@a-tarasyuk that test shows no changes to b.ts
🤔
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.
@andrewbranch default
is useless in /b.ts
. I've changed that
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.
It’s actually not 100% clear to me what the expected behavior should be. This is a very weird edge case, and I think it could be unexpected to generate changes to a merged declaration of any export. Personally I would be fine with the refactor being unavailable here.
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.
What did the behavior of this hypothetical test end up being?
@andrewbranch @amcasey I got lost reading the PR history. I think this is ready to go, and that the last outstanding request from @andrewbranch -- that the refactor not apply in the weird case given by @DanielRosenwasser -- is already true. Did I read that right? |
@sandersn Fine by me |
… sharedmemory file (#49204) * feat(sharedmemory): Added file waitAsync function * fix: Adjusted promise return type * Fix(sharedmemory): Addressed PR comments * Fix: Removed unused @see at sharedmemory * Feat: Added tests to shared memory * Fix: fixed ordering in libs.json * Feat: Added shared memory to line parser * Update tests es2022SharedMemory.ts as sugested Co-authored-by: Eyal Halpern Shalev <[email protected]> * Update es2022SharedMemory.ts * feat: Accepted baselines * fix: Adjusted grammar changes in jsdoc * fix(47821): skip nodes with export modifiers (#47829) * Use symbolic GitHub Actions Node.js versions (#49403) * update baselines Co-authored-by: Eyal Halpern Shalev <[email protected]> Co-authored-by: Oleksandr T <[email protected]> Co-authored-by: Jack Bates <[email protected]> Co-authored-by: Nathan Shively-Sanders <[email protected]>
Fixes #47821