diff --git a/lib/init.coffee b/lib/init.coffee
index cd08abd..2499a2d 100644
--- a/lib/init.coffee
+++ b/lib/init.coffee
@@ -26,6 +26,7 @@ module.exports =
'test all'
'rustc'
'clippy'
+ 'clippy all'
]
description: """`cargo` command to run.
- Use **build** to simply compile the code.
@@ -33,6 +34,7 @@ module.exports =
- Use **check all** for fast linting of all packages in the project.
- Use **check tests** to also include \`#[cfg(test)]\` code in linting.
- Use **clippy** to increase amount of available lints (you need to install \`clippy\`).
+ - Use **clippy all** to increase amount of available lints (you need to install \`clippy\`) for all packages in the project.
- Use **test** to run tests (note that once the tests are built, lints stop showing).
- Use **test all** run tests for all packages in the project.
- Use **rustc** for linting with Rust pre-1.23.
diff --git a/lib/linter-rust.coffee b/lib/linter-rust.coffee
index 3d91bbb..9d20a63 100644
--- a/lib/linter-rust.coffee
+++ b/lib/linter-rust.coffee
@@ -32,6 +32,7 @@ class LinterRust
@subscriptions.add atom.config.observe 'linter-rust.cargoCommand',
(cargoCommand) =>
@cargoCommand = cargoCommand
+ @useWorkspaceManifest = cargoCommand.endsWith('all')
@subscriptions.add atom.config.observe 'linter-rust.rustcBuildTest',
(rustcBuildTest) =>
@@ -75,6 +76,9 @@ class LinterRust
cmdPath = if cmd[0]? then path.dirname cmd[0] else __dirname
args = cmd.slice 1
env.PATH = cmdPath + path.delimiter + env.PATH
+ editingDir = path.dirname textEditor.getPath()
+ cargoWorkspaceManifestFile = @locateCargoWorkspace editingDir
+ cargoCrateManifestFile = @locateCargoCrate editingDir
# we set flags only for intermediate json support
if errorMode == errorModes.FLAGS_JSON_CARGO
@@ -88,8 +92,14 @@ class LinterRust
stream: 'both'
execOpts.timeout = Infinity if @disableExecTimeout
- atom_linter.exec(command, args, execOpts)
- .then (result) =>
+ Promise.all [atom_linter.exec(command, args, execOpts), cargoWorkspaceManifestFile]
+ .then (promiseReturns) ->
+ result = promiseReturns[0]
+ cargoWorkspaceManifestFile = promiseReturns[1]
+
+ cargoCrateManifestDir = path.dirname cargoCrateManifestFile
+ cargoWorkspaceManifestDir = path.dirname cargoWorkspaceManifestFile
+
{stdout, stderr, exitCode} = result
# first, check if an output says specified features are invalid
if stderr.indexOf('does not have these features') >= 0
@@ -116,7 +126,9 @@ class LinterRust
# correct file paths
messages.forEach (message) ->
if !(path.isAbsolute message.location.file)
- message.location.file = path.join curDir, message.location.file
+ message.location.file = path.join curDir, message.location.file if fs.existsSync path.join curDir, message.location.file
+ message.location.file = path.join cargoCrateManifestDir, message.location.file if fs.existsSync path.join cargoCrateManifestDir, message.location.file
+ message.location.file = path.join cargoWorkspaceManifestDir, message.location.file if fs.existsSync path.join cargoWorkspaceManifestDir, message.location.file
messages
else
# whoops, we're in trouble -- let's output as much as we can
@@ -137,15 +149,15 @@ class LinterRust
initCmd: (editingFile) =>
curDir = if editingFile? then path.dirname editingFile else __dirname
- cargoManifestPath = @locateCargo curDir
- if not @useCargo or not cargoManifestPath
- @decideErrorMode(curDir, 'rustc').then (mode) =>
- mode.buildArguments(this, [editingFile, cargoManifestPath]).then (cmd) ->
- [cmd, mode]
- else
- @decideErrorMode(curDir, 'cargo').then (mode) =>
- mode.buildArguments(this, cargoManifestPath).then (cmd) ->
- [cmd, mode]
+ @locateCargo(curDir).then (cargoManifestPath) =>
+ if not @useCargo or not cargoManifestPath
+ @decideErrorMode(curDir, 'rustc').then (mode) =>
+ mode.buildArguments(this, [editingFile, cargoManifestPath]).then (cmd) ->
+ [cmd, mode]
+ else
+ @decideErrorMode(curDir, 'cargo').then (mode) =>
+ mode.buildArguments(this, cargoManifestPath).then (cmd) ->
+ [cmd, mode]
compilationFeatures: (cargo) =>
if @specifiedFeatures.length > 0
@@ -196,13 +208,34 @@ class LinterRust
@cachedErrorMode = result
result
- locateCargo: (curDir) =>
+ locateCargoCrate: (curDir) =>
root_dir = if /^win/.test process.platform then /^.:\\$/ else /^\/$/
directory = path.resolve curDir
loop
- return path.join directory, @cargoManifestFilename if fs.existsSync path.join directory, @cargoManifestFilename
+ return path.join directory , @cargoManifestFilename if fs.existsSync path.join directory, @cargoManifestFilename
break if root_dir.test directory
directory = path.resolve path.join(directory, '..')
return false
+ locateCargoWorkspace: (curDir) =>
+ crate_level_manifest = @locateCargoCrate(curDir)
+ if @useWorkspaceManifest and @useCargo
+ execOpts =
+ env: JSON.parse JSON.stringify process.env
+ cwd: curDir
+ stream: 'both'
+
+ return atom_linter.exec('cargo', ['locate-project', '--workspace', '--manifest-path=' + crate_level_manifest], execOpts)
+ .then (result) =>
+ {stdout, stderr, exitCode} = result
+ json = JSON.parse stdout
+ return json.root
+ .catch (error) ->
+ return crate_level_manifest
+ else
+ return crate_level_manifest
+
+ locateCargo: (curDir) =>
+ return @locateCargoWorkspace curDir
+
module.exports = LinterRust
diff --git a/lib/mode.coffee b/lib/mode.coffee
index 50f96a6..d2df0a8 100644
--- a/lib/mode.coffee
+++ b/lib/mode.coffee
@@ -165,7 +165,7 @@ buildCargoArguments = (linter, cargoManifestPath) ->
.catch ->
result: false
usingMultitoolForClippy.then (canUseMultirust) ->
- if cargoCommand == 'clippy' and canUseMultirust.result
+ if (cargoCommand == 'clippy' or cargoCommand == 'clippy all') and canUseMultirust.result
[canUseMultirust.tool, 'run', 'nightly', 'cargo']
else
[cargoPath]
@@ -175,12 +175,13 @@ buildCargoArguments = (linter, cargoManifestPath) ->
cargoArgs = switch linter.cargoCommand
when 'check' then ['check']
- when 'check all' then ['check', '--all']
+ when 'check all' then ['check', '--all', '--all-targets']
when 'check tests' then ['check', '--tests']
when 'test' then ['test', '--no-run']
- when 'test all' then ['test', '--no-run', '--all']
+ when 'test all' then ['test', '--no-run', '--all', '--all-targets']
when 'rustc' then ['rustc', '--color', 'never']
when 'clippy' then ['clippy']
+ when 'clippy all' then ['clippy', '--workspace', '--all-targets']
else ['build']
compilationFeatures = linter.compilationFeatures(true)