bash-language-server
Advanced tools
Comparing version 4.7.0 to 4.8.0
# Bash Language Server | ||
## 4.8.0 | ||
- Use ShellCheck directives when analyzing source commands https://github.com/bash-lsp/bash-language-server/pull/747 | ||
## 4.7.0 | ||
@@ -4,0 +8,0 @@ |
@@ -69,5 +69,6 @@ "use strict"; | ||
`Source command could not be analyzed: ${sourceCommand.error}.\n`, | ||
'Note that enabling the configuration flag "includeAllWorkspaceSymbols"', | ||
'would include all symbols in the workspace regardless of source commands.', | ||
'But be aware that this will lead to false positive suggestions.', | ||
'Consider adding a ShellCheck directive above this line to fix or ignore this:', | ||
'# shellcheck source=/my-file.sh # specify the file to source', | ||
'# shellcheck source-path=my_script_folder # specify the folder to search in', | ||
'# shellcheck source=/dev/null # to ignore the error', | ||
].join('\n'), LSP.DiagnosticSeverity.Information, undefined, 'bash-language-server')); | ||
@@ -74,0 +75,0 @@ }); |
@@ -6,2 +6,4 @@ "use strict"; | ||
const path = require("path"); | ||
const directive_1 = require("../shellcheck/directive"); | ||
const discriminate_1 = require("./discriminate"); | ||
const fs_1 = require("./fs"); | ||
@@ -33,2 +35,3 @@ const TreeSitterUtil = require("./tree-sitter"); | ||
function getSourcedPathInfoFromNode({ node, }) { | ||
var _a, _b, _c; | ||
if (node.type === 'command') { | ||
@@ -38,2 +41,28 @@ const [commandNameNode, argumentNode] = node.namedChildren; | ||
SOURCING_COMMANDS.includes(commandNameNode.text)) { | ||
const previousCommentNode = ((_a = node.previousSibling) === null || _a === void 0 ? void 0 : _a.type) === 'comment' ? node.previousSibling : null; | ||
if (previousCommentNode === null || previousCommentNode === void 0 ? void 0 : previousCommentNode.text.includes('shellcheck')) { | ||
const directives = (0, directive_1.parseShellCheckDirective)(previousCommentNode.text); | ||
const sourcedPath = (_b = directives.find((0, discriminate_1.discriminate)('type', 'source'))) === null || _b === void 0 ? void 0 : _b.path; | ||
if (sourcedPath === '/dev/null') { | ||
return null; | ||
} | ||
if (sourcedPath) { | ||
return { | ||
sourcedPath, | ||
}; | ||
} | ||
const isNotFollowErrorDisabled = !!directives | ||
.filter((0, discriminate_1.discriminate)('type', 'disable')) | ||
.flatMap(({ rules }) => rules) | ||
.find((rule) => rule === 'SC1091'); | ||
if (isNotFollowErrorDisabled) { | ||
return null; | ||
} | ||
const rootFolder = (_c = directives.find((0, discriminate_1.discriminate)('type', 'source-path'))) === null || _c === void 0 ? void 0 : _c.path; | ||
if (rootFolder && rootFolder !== 'SCRIPTDIR' && argumentNode.type === 'word') { | ||
return { | ||
sourcedPath: path.join(rootFolder, argumentNode.text), | ||
}; | ||
} | ||
} | ||
if (argumentNode.type === 'word') { | ||
@@ -40,0 +69,0 @@ return { |
@@ -6,3 +6,3 @@ { | ||
"license": "MIT", | ||
"version": "4.7.0", | ||
"version": "4.8.0", | ||
"main": "./out/server.js", | ||
@@ -28,3 +28,3 @@ "typings": "./out/server.d.ts", | ||
"web-tree-sitter": "0.20.7", | ||
"zod": "3.20.5" | ||
"zod": "3.20.6" | ||
}, | ||
@@ -31,0 +31,0 @@ "scripts": { |
@@ -101,5 +101,6 @@ import { pathToFileURL } from 'node:url' | ||
Note that enabling the configuration flag "includeAllWorkspaceSymbols" | ||
would include all symbols in the workspace regardless of source commands. | ||
But be aware that this will lead to false positive suggestions.", | ||
Consider adding a ShellCheck directive above this line to fix or ignore this: | ||
# shellcheck source=/my-file.sh # specify the file to source | ||
# shellcheck source-path=my_script_folder # specify the folder to search in | ||
# shellcheck source=/dev/null # to ignore the error", | ||
"range": { | ||
@@ -106,0 +107,0 @@ "end": { |
@@ -103,5 +103,6 @@ import * as fs from 'fs' | ||
`Source command could not be analyzed: ${sourceCommand.error}.\n`, | ||
'Note that enabling the configuration flag "includeAllWorkspaceSymbols"', | ||
'would include all symbols in the workspace regardless of source commands.', | ||
'But be aware that this will lead to false positive suggestions.', | ||
'Consider adding a ShellCheck directive above this line to fix or ignore this:', | ||
'# shellcheck source=/my-file.sh # specify the file to source', | ||
'# shellcheck source-path=my_script_folder # specify the folder to search in', | ||
'# shellcheck source=/dev/null # to ignore the error', | ||
].join('\n'), | ||
@@ -108,0 +109,0 @@ LSP.DiagnosticSeverity.Information, |
@@ -5,2 +5,3 @@ import * as fs from 'fs' | ||
import { REPO_ROOT_FOLDER } from '../../../../testing/fixtures' | ||
import { initializeParser } from '../../parser' | ||
@@ -17,4 +18,2 @@ import { getSourceCommands } from '../sourcing' | ||
jest.spyOn(fs, 'existsSync').mockImplementation(() => true) | ||
// mock os.homedir() to return a fixed path | ||
@@ -34,3 +33,5 @@ jest.spyOn(os, 'homedir').mockImplementation(() => '/Users/bash-user') | ||
it('returns a set of sourced files', () => { | ||
it('returns a set of sourced files (but ignores some unhandled cases)', () => { | ||
jest.spyOn(fs, 'existsSync').mockImplementation(() => true) | ||
const fileContent = ` | ||
@@ -79,3 +80,3 @@ source file-in-path.sh # does not contain a slash (i.e. is maybe somewhere on the path) | ||
# ====================================== | ||
# example of sourcing through a function | ||
# Example of sourcing through a function | ||
# ====================================== | ||
@@ -156,2 +157,65 @@ | ||
}) | ||
it('returns a set of sourced files and parses ShellCheck directives', () => { | ||
jest.restoreAllMocks() | ||
const fileContent = ` | ||
. ./scripts/release-client.sh | ||
source ./testing/fixtures/issue206.sh | ||
# shellcheck source=/dev/null | ||
source ./IM_NOT_THERE.sh | ||
# shellcheck source-path=testing/fixtures | ||
source missing-node.sh # source path by directive | ||
# shellcheck source=./testing/fixtures/install.sh | ||
source "$X" # source by directive | ||
# shellcheck source=./some-file-that-does-not-exist.sh | ||
source "$Y" # not source due to invalid directive | ||
# shellcheck source-path=SCRIPTDIR # note that this is already the behaviour of bash language server | ||
source ./testing/fixtures/issue101.sh | ||
` | ||
const sourceCommands = getSourceCommands({ | ||
fileUri, | ||
rootPath: REPO_ROOT_FOLDER, | ||
tree: parser.parse(fileContent), | ||
}) | ||
const sourcedUris = new Set( | ||
sourceCommands | ||
.map((sourceCommand) => sourceCommand.uri) | ||
.filter((uri) => uri !== null), | ||
) | ||
expect(sourcedUris).toEqual( | ||
new Set([ | ||
`file://${REPO_ROOT_FOLDER}/scripts/release-client.sh`, | ||
`file://${REPO_ROOT_FOLDER}/testing/fixtures/issue206.sh`, | ||
`file://${REPO_ROOT_FOLDER}/testing/fixtures/missing-node.sh`, | ||
`file://${REPO_ROOT_FOLDER}/testing/fixtures/install.sh`, | ||
`file://${REPO_ROOT_FOLDER}/testing/fixtures/issue101.sh`, | ||
]), | ||
) | ||
expect( | ||
sourceCommands | ||
.filter((command) => command.error) | ||
.map(({ error, range }) => ({ | ||
error, | ||
line: range.start.line, | ||
})), | ||
).toMatchInlineSnapshot(` | ||
[ | ||
{ | ||
"error": "failed to resolve path", | ||
"line": 15, | ||
}, | ||
] | ||
`) | ||
}) | ||
}) |
@@ -6,2 +6,4 @@ import * as fs from 'fs' | ||
import { parseShellCheckDirective } from '../shellcheck/directive' | ||
import { discriminate } from './discriminate' | ||
import { untildify } from './fs' | ||
@@ -65,2 +67,36 @@ import * as TreeSitterUtil from './tree-sitter' | ||
) { | ||
const previousCommentNode = | ||
node.previousSibling?.type === 'comment' ? node.previousSibling : null | ||
if (previousCommentNode?.text.includes('shellcheck')) { | ||
const directives = parseShellCheckDirective(previousCommentNode.text) | ||
const sourcedPath = directives.find(discriminate('type', 'source'))?.path | ||
if (sourcedPath === '/dev/null') { | ||
return null | ||
} | ||
if (sourcedPath) { | ||
return { | ||
sourcedPath, | ||
} | ||
} | ||
const isNotFollowErrorDisabled = !!directives | ||
.filter(discriminate('type', 'disable')) | ||
.flatMap(({ rules }) => rules) | ||
.find((rule) => rule === 'SC1091') | ||
if (isNotFollowErrorDisabled) { | ||
return null | ||
} | ||
const rootFolder = directives.find(discriminate('type', 'source-path'))?.path | ||
if (rootFolder && rootFolder !== 'SCRIPTDIR' && argumentNode.type === 'word') { | ||
return { | ||
sourcedPath: path.join(rootFolder, argumentNode.text), | ||
} | ||
} | ||
} | ||
if (argumentNode.type === 'word') { | ||
@@ -67,0 +103,0 @@ return { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
971534
127
9871
+ Addedzod@3.20.6(transitive)
- Removedzod@3.20.5(transitive)
Updatedzod@3.20.6