Skip to content

Don't use text change's createNewFile for existing empty file - #54358

Merged
Gabriela Araujo Britto (gabritto) merged 4 commits into
mainfrom
gabritto/issue54285
May 24, 2023
Merged

Don't use text change's createNewFile for existing empty file#54358
Gabriela Araujo Britto (gabritto) merged 4 commits into
mainfrom
gabritto/issue54285

Conversation

@gabritto

@gabrittoGabriela Araujo Britto (gabritto) commented May 23, 2023

Copy link
Copy Markdown
Member

Fixes#54285.

This fix updates our handling of move to file when the target file already exists, but doesn't yet have any statements (i.e. is "empty"). Previously, we'd treat this empty file as a new file for the purposes of writing text changes to it, but this caused the reported crash, and it also had the consequence of us overwriting possibly existing comments in this empty target file.

This fix, however, uncovered a problem with how new lines are handled when we insert imports into a target file in move to file. The issue was already present, but now it also occurs when the target is an empty file. The issue is that we end up with extra new lines between the import statements the refactoring inserts, as witnessed by the test baselines that changed in this PR. There is also an inconsistency between choice of quotes that shows up in the tests. Both problems seem to be caused by us using ImportAdder to add some of the imports in the target file, but also adding imports not using the ImportAdder, and it seems like ideally we'd unify that so that we're consistent with new lines and quotes.

Comment threadsrc/harness/client.ts
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange): ApplicableRefactorInfo[] {
const args = this.createFileLocationOrRangeRequestArgs(positionOrRange, fileName);

getApplicableRefactors(

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fourslash server tests previously didn't work with move to file

Comment threadsrc/services/types.ts
* arguments for any interactive action before offering it.
*/
getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string, includeInteractiveActions?: boolean): ApplicableRefactorInfo[];
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined, includeInteractiveActions?: InteractiveRefactorArguments): RefactorEditInfo | undefined;

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drive-by fix, I thought this parameter had a misleading name, since it's not a boolean.

changes.insertNodesAtEndOfFile(targetFile, body, /*blankLineBetween*/ false);
}
if (imports.length > 0) {
insertImports(changes, targetFile, imports, /*blankLineBetween*/ true, preferences);

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the extra new lines, we could also change this code to pass blankLineBetween: false, and the consequence would be that we'd sometimes not have an empty line between the import blocks and the moved statements in the target file, e.g.:

import{a}from"./a";constx=2;

instead of

import{a}from"./a";constx=2;

Comment threadsrc/harness/client.ts Outdated
@@ -1,3 +1,4 @@
import { GetApplicableRefactorsRequestArgs, GetEditsForRefactorRequestArgs } from "../server/protocol.js";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: protocol is already imported from a namespace file, and I think that may still matter for initialization order in some cases.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did a .js extension show up here?

(I would use the existing import if possible)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this was auto-imports with non-default VS Code settings (importModuleSpecifierEnding=js)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I had importModuleSpecifierEnding set to js on my user settings (I think I accidentally changed the user one while trying to repro a bug in the past). Thanks for pointing that out

@gabritto

Copy link
Copy Markdown
MemberAuthor

Issue that tracks the problems I uncovered and mentioned in this PR description: #54375, #54376.

@DanielRosenwasser

Copy link
Copy Markdown
Member

TypeScript Bot (@typescript-bot) cherry-pick this to release-5.1

@typescript-bot

TypeScript Bot (typescript-bot) commented May 29, 2023

Copy link
Copy Markdown
Contributor

Heya Daniel Rosenwasser (@DanielRosenwasser), I've started to run the task to cherry-pick this into release-5.1 on this PR at 3dd77cf. You can monitor the build here.

@typescript-bot

Copy link
Copy Markdown
Contributor

Hey Daniel Rosenwasser (@DanielRosenwasser), I've opened #54444 for you.

TypeScript Bot (typescript-bot) pushed a commit to typescript-bot/TypeScript that referenced this pull request May 29, 2023
Component commits:
062fdfd don't use text change's create new file for existing empty file
9176b4a minor fixes
d1d9174 fix suffix newline
3dd77cf fix import
Daniel Rosenwasser (DanielRosenwasser) pushed a commit that referenced this pull request May 30, 2023
…e-5.1 (#54444)
Co-authored-by: Gabriela Araujo Britto <gabrielaa@microsoft.com>
@microsoftMicrosoft (microsoft) locked as resolved and limited conversation to collaborators Oct 22, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Author: TeamFor Milestone BugPRs that fix a bug with a specific milestone

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move to file fails when selecting existing with: Expected isNewFile for (only) new files

5 participants

@gabritto@DanielRosenwasser@typescript-bot@andrewbranch@jakebailey