Skip to content

Commit da8dd97

Browse files
committed
Default to shellcheck binary found on path
1 parent aab3728 commit da8dd97

File tree

4 files changed

+26
-7
lines changed

4 files changed

+26
-7
lines changed

server/src/__tests__/linter.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as path from 'path'
22
import * as LSP from 'vscode-languageserver'
33

44
import { FIXTURE_DOCUMENT, FIXTURE_FOLDER } from '../../../testing/fixtures'
5-
import Linter, { assertShellcheckResult } from '../linter'
5+
import { assertShellcheckResult, Linter } from '../linter'
66

77
function textToDoc(txt: string) {
88
return LSP.TextDocument.create('foo', 'bar', 0, txt)

server/src/linter.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { spawn } from 'child_process'
22
import * as LSP from 'vscode-languageserver'
33

4+
import * as config from './config'
5+
import { execShellScript } from './util/sh'
6+
47
function formatMessage(comment: ShellcheckComment): string {
58
return (comment.code ? `SC${comment.code}: ` : '') + comment.message
69
}
@@ -10,8 +13,23 @@ type LinterOptions = {
1013
cwd?: string
1114
}
1215

13-
export default class Linter {
14-
private executablePath: string | null
16+
export async function getLinterExecutablePath(): Promise<string | null> {
17+
const pathFromConfig = config.getShellcheckPath()
18+
19+
if (pathFromConfig) {
20+
return pathFromConfig
21+
}
22+
23+
try {
24+
const path = (await execShellScript('which shellcheck')).trim()
25+
return path === '' ? null : path
26+
} catch (e) {
27+
return null
28+
}
29+
}
30+
31+
export class Linter {
32+
public executablePath: string | null
1533
private cwd: string
1634
_canLint: boolean
1735

server/src/server.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Analyzer from './analyser'
88
import * as Builtins from './builtins'
99
import * as config from './config'
1010
import Executables from './executables'
11-
import Linter from './linter'
11+
import { getLinterExecutablePath, Linter } from './linter'
1212
import { initializeParser } from './parser'
1313
import * as ReservedWords from './reservedWords'
1414
import { BashCompletionItem, CompletionItemDataType } from './types'
@@ -41,8 +41,9 @@ export default class BashServer {
4141
return Promise.all([
4242
Executables.fromPath(PATH),
4343
Analyzer.fromRoot({ connection, rootPath, parser }),
44-
new Linter({ executablePath: config.getShellcheckPath() }),
45-
]).then(([executables, analyzer, linter]) => {
44+
getLinterExecutablePath(),
45+
]).then(([executables, analyzer, linterExecutablePath]) => {
46+
const linter = new Linter({ executablePath: linterExecutablePath })
4647
return new BashServer(connection, executables, analyzer, linter, capabilities)
4748
})
4849
}

server/src/util/sh.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function execShellScript(body: string, cmd = 'bash'): Promise<string> {
2929

3030
// Currently only reserved words where documentation doesn't make sense.
3131
// At least on OS X these just return the builtin man. On ubuntu there
32-
// are no documentaiton for them.
32+
// are no documentation for them.
3333
const WORDS_WITHOUT_DOCUMENTATION = new Set([
3434
'else',
3535
'fi',

0 commit comments

Comments
 (0)