@@ -13,6 +13,7 @@ import Executables from './executables'
1313import { initializeParser } from './parser'
1414import * as ReservedWords from './reserved-words'
1515import { Linter , LintingResult } from './shellcheck'
16+ import { Formatter } from './shfmt'
1617import { SNIPPETS } from './snippets'
1718import { BashCompletionItem , CompletionItemDataType } from './types'
1819import { uniqueBasedOnHash } from './util/array'
@@ -35,6 +36,7 @@ export default class BashServer {
3536 private documents : LSP . TextDocuments < TextDocument > = new LSP . TextDocuments ( TextDocument )
3637 private executables : Executables
3738 private linter ?: Linter
39+ private formatter ?: Formatter
3840 private workspaceFolder : string | null
3941 private uriToCodeActions : {
4042 [ uri : string ] : LintingResult [ 'codeActions' ] | undefined
@@ -46,20 +48,23 @@ export default class BashServer {
4648 connection,
4749 executables,
4850 linter,
51+ formatter,
4952 workspaceFolder,
5053 } : {
5154 analyzer : Analyzer
5255 capabilities : LSP . ClientCapabilities
5356 connection : LSP . Connection
5457 executables : Executables
5558 linter ?: Linter
59+ formatter ?: Formatter
5660 workspaceFolder : string | null
5761 } ) {
5862 this . analyzer = analyzer
5963 this . clientCapabilities = capabilities
6064 this . connection = connection
6165 this . executables = executables
6266 this . linter = linter
67+ this . formatter = formatter
6368 this . workspaceFolder = workspaceFolder
6469 this . config = { } as any // NOTE: configured in updateConfiguration
6570 this . updateConfiguration ( config . getDefaultConfiguration ( ) , true )
@@ -130,6 +135,7 @@ export default class BashServer {
130135 workDoneProgress : false ,
131136 } ,
132137 renameProvider : { prepareProvider : true } ,
138+ documentFormattingProvider : true ,
133139 }
134140 }
135141
@@ -172,6 +178,7 @@ export default class BashServer {
172178 connection . onWorkspaceSymbol ( this . onWorkspaceSymbol . bind ( this ) )
173179 connection . onPrepareRename ( this . onPrepareRename . bind ( this ) )
174180 connection . onRenameRequest ( this . onRenameRequest . bind ( this ) )
181+ connection . onDocumentFormatting ( this . onDocumentFormatting . bind ( this ) )
175182
176183 /**
177184 * The initialized notification is sent from the client to the server after
@@ -272,6 +279,14 @@ export default class BashServer {
272279 this . linter = new Linter ( { executablePath : shellcheckPath } )
273280 }
274281
282+ const { shfmtPath } = this . config
283+ if ( ! shfmtPath ) {
284+ logger . info ( 'Shfmt formatting is disabled as "shfmtPath" was not set' )
285+ this . formatter = undefined
286+ } else {
287+ this . formatter = new Formatter ( { executablePath : shfmtPath } )
288+ }
289+
275290 this . analyzer . setEnableSourceErrorDiagnostics (
276291 this . config . enableSourceErrorDiagnostics ,
277292 )
@@ -806,6 +821,26 @@ export default class BashServer {
806821 }
807822 return edits
808823 }
824+
825+ private async onDocumentFormatting (
826+ params : LSP . DocumentFormattingParams ,
827+ ) : Promise < LSP . TextEdit [ ] | null > {
828+ if ( this . formatter ) {
829+ try {
830+ const document = this . documents . get ( params . textDocument . uri )
831+ if ( ! document ) {
832+ logger . error ( `Error getting document: ${ params . textDocument . uri } ` )
833+ return null
834+ }
835+
836+ return await this . formatter . format ( document )
837+ } catch ( err ) {
838+ logger . error ( `Error while formatting: ${ err } ` )
839+ }
840+ }
841+
842+ return null
843+ }
809844}
810845
811846/**
0 commit comments