Severely improved support for rustfmt 0.5
rustfmt will now be run within the actual working directory instead of a temporary one. This will allow rustfmt to correctly look up referenced modules.
This commit is contained in:
parent
852c356551
commit
458fdb62e2
|
@ -113,7 +113,7 @@ module.exports = class Beautifier
|
|||
_envCacheDate: null
|
||||
_envCacheExpiry: 10000 # 10 seconds
|
||||
getShellEnvironment: ->
|
||||
return new @Promise((resolve, reject) =>
|
||||
return new Promise((resolve, reject) =>
|
||||
# Check Cache
|
||||
if @_envCache? and @_envCacheDate?
|
||||
# Check if Cache is old
|
||||
|
@ -248,71 +248,78 @@ module.exports = class Beautifier
|
|||
###
|
||||
Run command-line interface command
|
||||
###
|
||||
run: (executable, args, {ignoreReturnCode, help} = {}) ->
|
||||
run: (executable, args, {cwd, ignoreReturnCode, help, onStdin} = {}) ->
|
||||
# Flatten args first
|
||||
args = _.flatten(args)
|
||||
|
||||
# Resolve executable and all args
|
||||
Promise.all([executable, Promise.all(args)])
|
||||
.then(([exeName, args]) =>
|
||||
@debug('exeName, args:', exeName, args)
|
||||
return new Promise((resolve, reject) =>
|
||||
.then(([exeName, args]) =>
|
||||
@debug('exeName, args:', exeName, args)
|
||||
|
||||
# Remove undefined/null values
|
||||
args = _.without(args, undefined)
|
||||
args = _.without(args, null)
|
||||
|
||||
# Get PATH and other environment variables
|
||||
Promise.all([@getShellEnvironment(), @which(exeName)])
|
||||
.then(([env, exePath]) =>
|
||||
@debug('exePath, env:', exePath, env)
|
||||
exe = exePath ? exeName
|
||||
# Spawn command
|
||||
options = {
|
||||
env: env
|
||||
}
|
||||
cmd = @spawn(exe, args, options)
|
||||
.then(({returnCode, stdout, stderr}) =>
|
||||
@verbose('spawn result', returnCode, stdout, stderr)
|
||||
# If return code is not 0 then error occured
|
||||
if not ignoreReturnCode and returnCode isnt 0
|
||||
err = new Error(stderr)
|
||||
windowsProgramNotFoundMsg = "is not recognized as an \
|
||||
internal or external command" # operable program or batch file
|
||||
@verbose(stderr, windowsProgramNotFoundMsg)
|
||||
if @isWindows and returnCode is 1 and \
|
||||
stderr.indexOf(windowsProgramNotFoundMsg) isnt -1
|
||||
err = @commandNotFoundError(exeName, help)
|
||||
reject(err)
|
||||
else
|
||||
resolve(stdout)
|
||||
)
|
||||
.catch((err) =>
|
||||
@debug('error', err)
|
||||
# Check if error is ENOENT
|
||||
# (command could not be found)
|
||||
if err.code is 'ENOENT' or err.errno is 'ENOENT'
|
||||
reject(@commandNotFoundError(exeName, help))
|
||||
else
|
||||
# continue as normal error
|
||||
reject(err)
|
||||
)
|
||||
)
|
||||
Promise.all([exeName, @getShellEnvironment(), @which(exeName)])
|
||||
)
|
||||
.then(([exeName, env, exePath]) =>
|
||||
@debug('exePath, env:', exePath, env)
|
||||
|
||||
exe = exePath ? exeName
|
||||
options = {
|
||||
cwd: cwd
|
||||
env: env
|
||||
}
|
||||
|
||||
@spawn(exe, args, options, onStdin)
|
||||
.then(({returnCode, stdout, stderr}) =>
|
||||
@verbose('spawn result', returnCode, stdout, stderr)
|
||||
|
||||
# If return code is not 0 then error occured
|
||||
if not ignoreReturnCode and returnCode isnt 0
|
||||
# operable program or batch file
|
||||
windowsProgramNotFoundMsg = "is not recognized as an internal or external command"
|
||||
|
||||
@verbose(stderr, windowsProgramNotFoundMsg)
|
||||
|
||||
if @isWindows and returnCode is 1 and stderr.indexOf(windowsProgramNotFoundMsg) isnt -1
|
||||
throw @commandNotFoundError(exeName, help)
|
||||
else
|
||||
throw new Error(stderr)
|
||||
else
|
||||
stdout
|
||||
)
|
||||
.catch((err) =>
|
||||
@debug('error', err)
|
||||
|
||||
# Check if error is ENOENT (command could not be found)
|
||||
if err.code is 'ENOENT' or err.errno is 'ENOENT'
|
||||
throw @commandNotFoundError(exeName, help)
|
||||
else
|
||||
# continue as normal error
|
||||
throw err
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
###
|
||||
Spawn
|
||||
###
|
||||
spawn: (exe, args, options) ->
|
||||
spawn: (exe, args, options, onStdin) ->
|
||||
return new Promise((resolve, reject) =>
|
||||
@debug('spawn', exe, args)
|
||||
|
||||
cmd = spawn(exe, args, options)
|
||||
# add a 'data' event listener for the spawn instance
|
||||
stdout = ""
|
||||
stderr = ""
|
||||
cmd.stdout.on('data', (data) -> stdout += data )
|
||||
cmd.stderr.on('data', (data) -> stderr += data )
|
||||
# when the spawn child process exits,
|
||||
# check if there were any errors and
|
||||
# close the writeable stream
|
||||
|
||||
cmd.stdout.on('data', (data) ->
|
||||
stdout += data
|
||||
)
|
||||
cmd.stderr.on('data', (data) ->
|
||||
stderr += data
|
||||
)
|
||||
cmd.on('close', (returnCode) =>
|
||||
@debug('spawn done', returnCode, stderr, stdout)
|
||||
resolve({returnCode, stdout, stderr})
|
||||
|
@ -321,6 +328,8 @@ module.exports = class Beautifier
|
|||
@debug('error', err)
|
||||
reject(err)
|
||||
)
|
||||
|
||||
onStdin cmd.stdin if onStdin
|
||||
)
|
||||
|
||||
###
|
||||
|
|
|
@ -4,9 +4,11 @@ Requires https://github.com/nrc/rustfmt
|
|||
|
||||
"use strict"
|
||||
Beautifier = require('./beautifier')
|
||||
path = require('path')
|
||||
|
||||
versionCheckState = false
|
||||
|
||||
module.exports = class Rustfmt extends Beautifier
|
||||
|
||||
name: "rustfmt"
|
||||
|
||||
options: {
|
||||
|
@ -14,24 +16,38 @@ module.exports = class Rustfmt extends Beautifier
|
|||
}
|
||||
|
||||
beautify: (text, language, options) ->
|
||||
|
||||
# get file path which is the search path for rustfmt.toml as
|
||||
# the beautifier runs rustfmt in a tmp directory.
|
||||
# This will pick up any rustfmt.toml defined in the crate root
|
||||
|
||||
editor = atom.workspace.getActivePaneItem()
|
||||
file = editor?.buffer.file
|
||||
filePath = file?.path
|
||||
buffer = editor.getBuffer?()
|
||||
filePath = buffer.getPath?()
|
||||
cwd = if filePath then path.dirname filePath else undefined
|
||||
program = options.rustfmt_path or "rustfmt"
|
||||
@run(program, [
|
||||
tmpFile = @tempFile("tmp", text)
|
||||
["--write-mode", "overwrite"]
|
||||
["--config-path", filePath]
|
||||
], help: {
|
||||
link: "https://github.com/nrc/rustfmt"
|
||||
program: "rustfmt"
|
||||
pathOption: "Rust - Rustfmt Path"
|
||||
help = {
|
||||
link: "https://github.com/nrc/rustfmt"
|
||||
program: "rustfmt"
|
||||
pathOption: "Rust - Rustfmt Path"
|
||||
}
|
||||
|
||||
# 0.5.0 is a relatively new version at the point of writing,
|
||||
# but is essential for this to work with stdin.
|
||||
# => Check for it specifically.
|
||||
p = if versionCheckState == program
|
||||
@Promise.resolve()
|
||||
else
|
||||
@run(program, ["--version"], help: help)
|
||||
.then((stdout) ->
|
||||
if /^0\.(?:[0-4]\.[0-9])/.test(stdout.trim())
|
||||
versionCheckState = false
|
||||
throw new Error("rustfmt version 0.5.0 or newer required")
|
||||
else
|
||||
versionCheckState = program
|
||||
undefined
|
||||
)
|
||||
|
||||
p.then(=>
|
||||
@run(program, [], {
|
||||
cwd: cwd
|
||||
help: help
|
||||
onStdin: (stdin) ->
|
||||
stdin.end text
|
||||
})
|
||||
.then(=>
|
||||
@readFile(tmpFile)
|
||||
)
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue