@@ -3497,7 +3497,11 @@ export class DefaultClient implements Client {
3497
3497
let workspaceEdits : vscode . WorkspaceEdit = new vscode . WorkspaceEdit ( ) ;
3498
3498
let replaceEditRange : vscode . Range | undefined ;
3499
3499
let hasProcessedReplace : boolean = false ;
3500
- const formatUriAndRanges : VsCodeUriAndRange [ ] = [ ] ;
3500
+ // NOTE: References to source/header are in reference to the more common case when it's
3501
+ // invoked on the source file (alternatively named the first file). When invoked on the header file,
3502
+ // the header file operates as if it were the source file (isSourceFile stays true).
3503
+ const sourceFormatUriAndRanges : VsCodeUriAndRange [ ] = [ ] ;
3504
+ const headerFormatUriAndRanges : VsCodeUriAndRange [ ] = [ ] ;
3501
3505
let lineOffset : number = 0 ;
3502
3506
let headerFileLineOffset : number = 0 ;
3503
3507
let isSourceFile : boolean = true ;
@@ -3561,11 +3565,16 @@ export class DefaultClient implements Client {
3561
3565
rangeStartCharacter = 1 ;
3562
3566
rangeStartLine += 1 ;
3563
3567
}
3564
- formatUriAndRanges . push ( { uri , range : new vscode . Range (
3568
+ const newRange : vscode . Range = new vscode . Range (
3565
3569
new vscode . Position ( rangeStartLine + ( nextLineOffset < 0 ? nextLineOffset : 0 ) , range . start . character ) ,
3566
3570
new vscode . Position ( rangeStartLine + ( nextLineOffset < 0 ? 0 : nextLineOffset ) ,
3567
3571
isReplace ? range . end . character :
3568
- range . end . character + edit . newText . length - rangeStartCharacter ) ) } ) ;
3572
+ range . end . character + edit . newText . length - rangeStartCharacter ) ) ;
3573
+ if ( isSourceFile ) {
3574
+ sourceFormatUriAndRanges . push ( { uri, range : newRange } ) ;
3575
+ } else {
3576
+ headerFormatUriAndRanges . push ( { uri, range : newRange } ) ;
3577
+ }
3569
3578
if ( isReplace ) {
3570
3579
// Handle additional declaration lines added before the new function call.
3571
3580
let currentText : string = edit . newText . substring ( rangeStartCharacter ) ;
@@ -3595,34 +3604,45 @@ export class DefaultClient implements Client {
3595
3604
}
3596
3605
}
3597
3606
3598
- if ( replaceEditRange === undefined || formatUriAndRanges . length === 0 ) {
3607
+ if ( replaceEditRange === undefined || sourceFormatUriAndRanges . length === 0 ) {
3599
3608
return ;
3600
3609
}
3601
3610
3602
3611
// Apply the extract to function text edits.
3603
3612
await vscode . workspace . applyEdit ( workspaceEdits , { isRefactoring : true } ) ;
3604
3613
3605
- const firstUri : vscode . Uri = formatUriAndRanges [ 0 ] . uri ;
3614
+ // Select the replaced code.
3615
+ await vscode . window . showTextDocument ( sourceFormatUriAndRanges [ 0 ] . uri , { selection : replaceEditRange , preserveFocus : false } ) ;
3606
3616
3607
3617
// Format the new text edits.
3608
3618
const formatEdits : vscode . WorkspaceEdit = new vscode . WorkspaceEdit ( ) ;
3609
- for ( const formatUriAndRange of formatUriAndRanges ) {
3619
+ const formatRanges = async ( formatUriAndRanges : VsCodeUriAndRange [ ] ) => {
3620
+ if ( formatUriAndRanges . length === 0 ) {
3621
+ return ;
3622
+ }
3623
+ const formatUriAndRange : VsCodeUriAndRange = formatUriAndRanges [ 0 ] ;
3624
+ const isMultipleFormatRanges : boolean = formatUriAndRanges . length > 1 ;
3610
3625
const settings : OtherSettings = new OtherSettings ( vscode . workspace . getWorkspaceFolder ( formatUriAndRange . uri ) ?. uri ) ;
3611
3626
const formatOptions : vscode . FormattingOptions = {
3612
3627
insertSpaces : settings . editorInsertSpaces ?? true ,
3613
3628
tabSize : settings . editorTabSize ?? 4 ,
3614
- onChanges : true ,
3629
+ onChanges : isMultipleFormatRanges ,
3615
3630
preserveFocus : true
3616
3631
} ;
3617
3632
3618
- const doFormat = async ( ) => {
3633
+ const tryFormat = async ( ) => {
3619
3634
const versionBeforeFormatting : number | undefined = openFileVersions . get ( formatUriAndRange . uri . toString ( ) ) ;
3620
3635
if ( versionBeforeFormatting === undefined ) {
3621
3636
return true ;
3622
3637
}
3623
3638
3624
- const formatTextEdits : vscode . TextEdit [ ] | undefined = await vscode . commands . executeCommand < vscode . TextEdit [ ] | undefined > (
3625
- "vscode.executeFormatDocumentProvider" , formatUriAndRange . uri , formatOptions ) ;
3639
+ // Only use document (onChange) formatting when there are multiple ranges.
3640
+ const formatTextEdits : vscode . TextEdit [ ] | undefined = isMultipleFormatRanges ?
3641
+ await vscode . commands . executeCommand < vscode . TextEdit [ ] | undefined > (
3642
+ "vscode.executeFormatDocumentProvider" , formatUriAndRange . uri , formatOptions ) :
3643
+ await vscode . commands . executeCommand < vscode . TextEdit [ ] | undefined > (
3644
+ "vscode.executeFormatRangeProvider" , formatUriAndRange . uri , formatUriAndRange . range , formatOptions ) ;
3645
+
3626
3646
if ( ! formatTextEdits || formatTextEdits . length === 0 || versionBeforeFormatting === undefined ) {
3627
3647
return true ;
3628
3648
}
@@ -3635,19 +3655,17 @@ export class DefaultClient implements Client {
3635
3655
formatEdits . set ( formatUriAndRange . uri , formatTextEdits ) ;
3636
3656
return true ;
3637
3657
} ;
3638
- if ( ! await doFormat ( ) )
3658
+ if ( ! await tryFormat ( ) )
3639
3659
{
3640
- await doFormat ( ) ; // Try again;
3660
+ await tryFormat ( ) ; // Try again;
3641
3661
}
3642
- }
3662
+ } ;
3643
3663
3664
+ await formatRanges ( headerFormatUriAndRanges ) ;
3665
+ await formatRanges ( sourceFormatUriAndRanges ) ;
3644
3666
if ( formatEdits . size > 0 ) {
3645
3667
await vscode . workspace . applyEdit ( formatEdits , { isRefactoring : true } ) ;
3646
3668
}
3647
-
3648
- // This is required to be done after the formatting is done, because that can trigger the
3649
- // active document to switch to the wrong file (the header).
3650
- await vscode . window . showTextDocument ( firstUri , { selection : replaceEditRange , preserveFocus : false } ) ;
3651
3669
}
3652
3670
3653
3671
public onInterval ( ) : void {
0 commit comments