Skip to content

Commit f11f305

Browse files
authored
Merge pull request #211 from bash-lsp/handle-broken-symlinks
Recover from file read errors
2 parents 64a356f + 52041dc commit f11f305

File tree

7 files changed

+86
-74
lines changed

7 files changed

+86
-74
lines changed

server/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Bash Language Server
22

3+
## 1.11.3
4+
5+
* Recover from file reading errors (https://github.com/bash-lsp/bash-language-server/pull/211)
6+
37
## 1.11.2
48

59
* Fix invalid documentHighlight response when word cannot be found (https://github.com/bash-lsp/bash-language-server/pull/209)

server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "A language server for Bash",
44
"author": "Mads Hartmann",
55
"license": "MIT",
6-
"version": "1.11.2",
6+
"version": "1.11.3",
77
"publisher": "mads-hartmann",
88
"main": "./out/server.js",
99
"typings": "./out/server.d.ts",

server/src/__tests__/analyzer.test.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import FIXTURES, { FIXTURE_FOLDER } from '../../../testing/fixtures'
2+
import { getMockConnection } from '../../../testing/mocks'
23
import Analyzer from '../analyser'
34
import { initializeParser } from '../parser'
45

@@ -113,11 +114,7 @@ describe('fromRoot', () => {
113114

114115
jest.spyOn(Date, 'now').mockImplementation(() => 0)
115116

116-
const connection: any = {
117-
console: {
118-
log: jest.fn(),
119-
},
120-
}
117+
const connection = getMockConnection()
121118

122119
const newAnalyzer = await Analyzer.fromRoot({
123120
connection,
@@ -127,7 +124,7 @@ describe('fromRoot', () => {
127124

128125
expect(newAnalyzer).toBeDefined()
129126

130-
const FIXTURE_FILES_MATCHING_GLOB = 9
127+
const FIXTURE_FILES_MATCHING_GLOB = 10
131128

132129
// Intro, stats on glob, one file skipped due to shebang, and outro
133130
const LOG_LINES = FIXTURE_FILES_MATCHING_GLOB + 4

server/src/__tests__/server.test.ts

Lines changed: 2 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,14 @@
11
import * as lsp from 'vscode-languageserver'
22

33
import { FIXTURE_FOLDER, FIXTURE_URI } from '../../../testing/fixtures'
4+
import { getMockConnection } from '../../../testing/mocks'
45
import LspServer from '../server'
56
import { CompletionItemDataType } from '../types'
67

78
async function initializeServer() {
89
const diagnostics: Array<lsp.PublishDiagnosticsParams | undefined> = undefined
9-
const console: any = {
10-
error: jest.fn(),
11-
warn: jest.fn(),
12-
info: jest.fn(),
13-
log: jest.fn(),
14-
}
1510

16-
const connection: jest.Mocked<lsp.Connection> = {
17-
client: {} as any,
18-
console,
19-
dispose: jest.fn(),
20-
listen: jest.fn(),
21-
onCodeAction: jest.fn(),
22-
onCodeLens: jest.fn(),
23-
onCodeLensResolve: jest.fn(),
24-
onColorPresentation: jest.fn(),
25-
onCompletion: jest.fn(),
26-
onCompletionResolve: jest.fn(),
27-
onDeclaration: jest.fn(),
28-
onDefinition: jest.fn(),
29-
onDidChangeConfiguration: jest.fn(),
30-
onDidChangeTextDocument: jest.fn(),
31-
onDidChangeWatchedFiles: jest.fn(),
32-
onDidCloseTextDocument: jest.fn(),
33-
onDidOpenTextDocument: jest.fn(),
34-
onDidSaveTextDocument: jest.fn(),
35-
onDocumentColor: jest.fn(),
36-
onDocumentFormatting: jest.fn(),
37-
onDocumentHighlight: jest.fn(),
38-
onDocumentLinkResolve: jest.fn(),
39-
onDocumentLinks: jest.fn(),
40-
onDocumentOnTypeFormatting: jest.fn(),
41-
onDocumentRangeFormatting: jest.fn(),
42-
onDocumentSymbol: jest.fn(),
43-
onExecuteCommand: jest.fn(),
44-
onExit: jest.fn(),
45-
onFoldingRanges: jest.fn(),
46-
onHover: jest.fn(),
47-
onImplementation: jest.fn(),
48-
onInitialize: jest.fn(),
49-
onInitialized: jest.fn(),
50-
onNotification: jest.fn(),
51-
onPrepareRename: jest.fn(),
52-
onReferences: jest.fn(),
53-
onRenameRequest: jest.fn(),
54-
onRequest: jest.fn(),
55-
onShutdown: jest.fn(),
56-
onSignatureHelp: jest.fn(),
57-
onTypeDefinition: jest.fn(),
58-
onWillSaveTextDocument: jest.fn(),
59-
onWillSaveTextDocumentWaitUntil: jest.fn(),
60-
onWorkspaceSymbol: jest.fn(),
61-
sendDiagnostics: jest.fn(),
62-
sendNotification: jest.fn(),
63-
sendRequest: jest.fn(),
64-
telemetry: {} as any,
65-
tracer: {} as any,
66-
window: {} as any,
67-
workspace: {} as any,
68-
}
11+
const connection = getMockConnection()
6912

7013
const server = await LspServer.initialize(connection, {
7114
rootPath: FIXTURE_FOLDER,

server/src/analyser.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,18 @@ export default class Analyzer {
6666
const uri = `file://${filePath}`
6767
connection.console.log(`Analyzing ${uri}`)
6868

69-
const fileContent = fs.readFileSync(filePath, 'utf8')
70-
71-
const shebang = getShebang(fileContent)
72-
if (shebang && !isBashShebang(shebang)) {
73-
connection.console.log(`Skipping file ${uri} with shebang "${shebang}"`)
74-
return
69+
try {
70+
const fileContent = fs.readFileSync(filePath, 'utf8')
71+
const shebang = getShebang(fileContent)
72+
if (shebang && !isBashShebang(shebang)) {
73+
connection.console.log(`Skipping file ${uri} with shebang "${shebang}"`)
74+
return
75+
}
76+
77+
analyzer.analyze(uri, LSP.TextDocument.create(uri, 'shell', 1, fileContent))
78+
} catch (error) {
79+
connection.console.warn(`Failed analyzing ${uri}. Error: ${error.message}`)
7580
}
76-
77-
analyzer.analyze(uri, LSP.TextDocument.create(uri, 'shell', 1, fileContent))
7881
})
7982

8083
connection.console.log(`Analyzer finished after ${getTimePassed()}`)

testing/fixtures/broken-symlink.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
x.sh

testing/mocks.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import * as lsp from 'vscode-languageserver'
2+
3+
export function getMockConnection(): jest.Mocked<lsp.Connection> {
4+
const console: any = {
5+
error: jest.fn(),
6+
warn: jest.fn(),
7+
info: jest.fn(),
8+
log: jest.fn(),
9+
}
10+
11+
return {
12+
client: {} as any,
13+
console,
14+
dispose: jest.fn(),
15+
listen: jest.fn(),
16+
onCodeAction: jest.fn(),
17+
onCodeLens: jest.fn(),
18+
onCodeLensResolve: jest.fn(),
19+
onColorPresentation: jest.fn(),
20+
onCompletion: jest.fn(),
21+
onCompletionResolve: jest.fn(),
22+
onDeclaration: jest.fn(),
23+
onDefinition: jest.fn(),
24+
onDidChangeConfiguration: jest.fn(),
25+
onDidChangeTextDocument: jest.fn(),
26+
onDidChangeWatchedFiles: jest.fn(),
27+
onDidCloseTextDocument: jest.fn(),
28+
onDidOpenTextDocument: jest.fn(),
29+
onDidSaveTextDocument: jest.fn(),
30+
onDocumentColor: jest.fn(),
31+
onDocumentFormatting: jest.fn(),
32+
onDocumentHighlight: jest.fn(),
33+
onDocumentLinkResolve: jest.fn(),
34+
onDocumentLinks: jest.fn(),
35+
onDocumentOnTypeFormatting: jest.fn(),
36+
onDocumentRangeFormatting: jest.fn(),
37+
onDocumentSymbol: jest.fn(),
38+
onExecuteCommand: jest.fn(),
39+
onExit: jest.fn(),
40+
onFoldingRanges: jest.fn(),
41+
onHover: jest.fn(),
42+
onImplementation: jest.fn(),
43+
onInitialize: jest.fn(),
44+
onInitialized: jest.fn(),
45+
onNotification: jest.fn(),
46+
onPrepareRename: jest.fn(),
47+
onReferences: jest.fn(),
48+
onRenameRequest: jest.fn(),
49+
onRequest: jest.fn(),
50+
onShutdown: jest.fn(),
51+
onSignatureHelp: jest.fn(),
52+
onTypeDefinition: jest.fn(),
53+
onWillSaveTextDocument: jest.fn(),
54+
onWillSaveTextDocumentWaitUntil: jest.fn(),
55+
onWorkspaceSymbol: jest.fn(),
56+
sendDiagnostics: jest.fn(),
57+
sendNotification: jest.fn(),
58+
sendRequest: jest.fn(),
59+
telemetry: {} as any,
60+
tracer: {} as any,
61+
window: {} as any,
62+
workspace: {} as any,
63+
}
64+
}

0 commit comments

Comments
 (0)