Skip to content

Commit 203823a

Browse files
authored
Fix 'Extract to function' header selection state. (#11677)
* Fix 'Extract to function' header selection state. * Update changelog.
1 parent 10564f9 commit 203823a

File tree

2 files changed

+37
-16
lines changed

2 files changed

+37
-16
lines changed

Extension/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# C/C++ for Visual Studio Code Changelog
22

33
## Version 1.18.4: November 14, 2023
4-
### Bug Fix:
4+
### Bug Fixes:
5+
* Fix 'Extract to function' not scrolling to and selecting the added header declaration. [#11676](https://github.com/microsoft/vscode-cpptools/issues/11676)
56
* Fix the extension sometimes failing to activate with VS Code versions less than 1.18. [#11680](https://github.com/microsoft/vscode-cpptools/issues/11680)
67

78
## Version 1.18.3: November 13, 2023

Extension/src/LanguageServer/client.ts

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3495,11 +3495,13 @@ export class DefaultClient implements Client {
34953495
}
34963496

34973497
let workspaceEdits: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
3498-
let replaceEditRange: vscode.Range | undefined;
3499-
let hasProcessedReplace: boolean = false;
3498+
35003499
// NOTE: References to source/header are in reference to the more common case when it's
35013500
// invoked on the source file (alternatively named the first file). When invoked on the header file,
35023501
// the header file operates as if it were the source file (isSourceFile stays true).
3502+
let sourceReplaceEditRange: vscode.Range | undefined;
3503+
let headerReplaceEditRange: vscode.Range | undefined;
3504+
let hasProcessedReplace: boolean = false;
35033505
const sourceFormatUriAndRanges: VsCodeUriAndRange[] = [];
35043506
const headerFormatUriAndRanges: VsCodeUriAndRange[] = [];
35053507
let lineOffset: number = 0;
@@ -3575,7 +3577,7 @@ export class DefaultClient implements Client {
35753577
} else {
35763578
headerFormatUriAndRanges.push({uri, range: newRange});
35773579
}
3578-
if (isReplace) {
3580+
if (isReplace || !isSourceFile) {
35793581
// Handle additional declaration lines added before the new function call.
35803582
let currentText: string = edit.newText.substring(rangeStartCharacter);
35813583
let currentTextNextLineStart: number = currentText.indexOf("\n");
@@ -3596,35 +3598,38 @@ export class DefaultClient implements Client {
35963598
"Extract to function failed. An invalid edit was generated: '{0}'", edit.newText)}`);
35973599
continue;
35983600
}
3599-
replaceEditRange = new vscode.Range(
3601+
const replaceEditRange = new vscode.Range(
36003602
new vscode.Position(rangeStartLine, rangeStartCharacter),
36013603
new vscode.Position(rangeStartLine, rangeStartCharacter + functionName.length));
3604+
if (isSourceFile) {
3605+
sourceReplaceEditRange = replaceEditRange;
3606+
} else {
3607+
headerReplaceEditRange = replaceEditRange;
3608+
}
36023609
nextLineOffset -= range.end.line - range.start.line;
36033610
}
36043611
}
36053612
}
36063613

3607-
if (replaceEditRange === undefined || sourceFormatUriAndRanges.length === 0) {
3614+
if (sourceReplaceEditRange === undefined || sourceFormatUriAndRanges.length === 0) {
36083615
return;
36093616
}
36103617

3611-
if (headerFormatUriAndRanges.length > 0) {
3618+
// Apply the extract to function text edits.
3619+
await vscode.workspace.applyEdit(workspaceEdits, { isRefactoring: true });
3620+
3621+
if (headerFormatUriAndRanges.length > 0 && headerReplaceEditRange !== undefined) {
36123622
// The header needs to be open and shown or the formatting will fail
36133623
// (due to issues/requirements in the cpptools process).
36143624
// It also seems strange and undesirable to have the header modified
36153625
// without being opened because otherwise users may not realize that
36163626
// the header had changed (unless they view source control differences).
3617-
await vscode.window.showTextDocument(headerFormatUriAndRanges[0].uri, { preserveFocus: true });
3627+
await vscode.window.showTextDocument(headerFormatUriAndRanges[0].uri, {
3628+
selection: headerReplaceEditRange, preserveFocus: false });
36183629
}
36193630

3620-
// Apply the extract to function text edits.
3621-
await vscode.workspace.applyEdit(workspaceEdits, { isRefactoring: true });
3622-
3623-
// Select the replaced code.
3624-
await vscode.window.showTextDocument(sourceFormatUriAndRanges[0].uri, { selection: replaceEditRange, preserveFocus: false });
3625-
36263631
// Format the new text edits.
3627-
const formatEdits: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
3632+
let formatEdits: vscode.WorkspaceEdit = new vscode.WorkspaceEdit();
36283633
const formatRanges = async (formatUriAndRanges: VsCodeUriAndRange[]) => {
36293634
if (formatUriAndRanges.length === 0) {
36303635
return;
@@ -3670,7 +3675,22 @@ export class DefaultClient implements Client {
36703675
}
36713676
};
36723677

3673-
await formatRanges(headerFormatUriAndRanges);
3678+
if (headerFormatUriAndRanges.length > 0 && headerReplaceEditRange !== undefined) {
3679+
await formatRanges(headerFormatUriAndRanges);
3680+
if (formatEdits.size > 0) {
3681+
// This showTextDocument is required in order to get the selection to be
3682+
// correct after the formatting edit is applied. It could be a VS Code bug.
3683+
await vscode.window.showTextDocument(headerFormatUriAndRanges[0].uri, {
3684+
selection: headerReplaceEditRange, preserveFocus: false });
3685+
await vscode.workspace.applyEdit(formatEdits, { isRefactoring: true });
3686+
formatEdits = new vscode.WorkspaceEdit();
3687+
}
3688+
}
3689+
3690+
// Select the replaced code.
3691+
await vscode.window.showTextDocument(sourceFormatUriAndRanges[0].uri, {
3692+
selection: sourceReplaceEditRange, preserveFocus: false });
3693+
36743694
await formatRanges(sourceFormatUriAndRanges);
36753695
if (formatEdits.size > 0) {
36763696
await vscode.workspace.applyEdit(formatEdits, { isRefactoring: true });

0 commit comments

Comments
 (0)