@@ -3497,7 +3497,11 @@ export class DefaultClient implements Client {
34973497 let workspaceEdits : vscode . WorkspaceEdit = new vscode . WorkspaceEdit ( ) ;
34983498 let replaceEditRange : vscode . Range | undefined ;
34993499 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 [ ] = [ ] ;
35013505 let lineOffset : number = 0 ;
35023506 let headerFileLineOffset : number = 0 ;
35033507 let isSourceFile : boolean = true ;
@@ -3561,11 +3565,16 @@ export class DefaultClient implements Client {
35613565 rangeStartCharacter = 1 ;
35623566 rangeStartLine += 1 ;
35633567 }
3564- formatUriAndRanges . push ( { uri , range : new vscode . Range (
3568+ const newRange : vscode . Range = new vscode . Range (
35653569 new vscode . Position ( rangeStartLine + ( nextLineOffset < 0 ? nextLineOffset : 0 ) , range . start . character ) ,
35663570 new vscode . Position ( rangeStartLine + ( nextLineOffset < 0 ? 0 : nextLineOffset ) ,
35673571 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+ }
35693578 if ( isReplace ) {
35703579 // Handle additional declaration lines added before the new function call.
35713580 let currentText : string = edit . newText . substring ( rangeStartCharacter ) ;
@@ -3595,34 +3604,45 @@ export class DefaultClient implements Client {
35953604 }
35963605 }
35973606
3598- if ( replaceEditRange === undefined || formatUriAndRanges . length === 0 ) {
3607+ if ( replaceEditRange === undefined || sourceFormatUriAndRanges . length === 0 ) {
35993608 return ;
36003609 }
36013610
36023611 // Apply the extract to function text edits.
36033612 await vscode . workspace . applyEdit ( workspaceEdits , { isRefactoring : true } ) ;
36043613
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 } ) ;
36063616
36073617 // Format the new text edits.
36083618 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 ;
36103625 const settings : OtherSettings = new OtherSettings ( vscode . workspace . getWorkspaceFolder ( formatUriAndRange . uri ) ?. uri ) ;
36113626 const formatOptions : vscode . FormattingOptions = {
36123627 insertSpaces : settings . editorInsertSpaces ?? true ,
36133628 tabSize : settings . editorTabSize ?? 4 ,
3614- onChanges : true ,
3629+ onChanges : isMultipleFormatRanges ,
36153630 preserveFocus : true
36163631 } ;
36173632
3618- const doFormat = async ( ) => {
3633+ const tryFormat = async ( ) => {
36193634 const versionBeforeFormatting : number | undefined = openFileVersions . get ( formatUriAndRange . uri . toString ( ) ) ;
36203635 if ( versionBeforeFormatting === undefined ) {
36213636 return true ;
36223637 }
36233638
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+
36263646 if ( ! formatTextEdits || formatTextEdits . length === 0 || versionBeforeFormatting === undefined ) {
36273647 return true ;
36283648 }
@@ -3635,19 +3655,17 @@ export class DefaultClient implements Client {
36353655 formatEdits . set ( formatUriAndRange . uri , formatTextEdits ) ;
36363656 return true ;
36373657 } ;
3638- if ( ! await doFormat ( ) )
3658+ if ( ! await tryFormat ( ) )
36393659 {
3640- await doFormat ( ) ; // Try again;
3660+ await tryFormat ( ) ; // Try again;
36413661 }
3642- }
3662+ } ;
36433663
3664+ await formatRanges ( headerFormatUriAndRanges ) ;
3665+ await formatRanges ( sourceFormatUriAndRanges ) ;
36443666 if ( formatEdits . size > 0 ) {
36453667 await vscode . workspace . applyEdit ( formatEdits , { isRefactoring : true } ) ;
36463668 }
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 } ) ;
36513669 }
36523670
36533671 public onInterval ( ) : void {
0 commit comments