See #394. Improve error message when program cannot be found
This commit is contained in:
parent
a0e07c232d
commit
2663b41505
|
@ -62,6 +62,118 @@ describe "Atom-Beautify", ->
|
|||
expect(v).not.toBe(null)
|
||||
expect(v instanceof Error).toBe(true)
|
||||
expect(v.code).toBe("CommandNotFound")
|
||||
expect(v.description).toBe(undefined, \
|
||||
'Error should not have a description.')
|
||||
return v
|
||||
p.then(cb, cb)
|
||||
return p
|
||||
|
||||
it "should error with help description \
|
||||
when beautifier's program not found", ->
|
||||
expect(beautifier).not.toBe(null)
|
||||
expect(beautifier instanceof Beautifier).toBe(true)
|
||||
|
||||
waitsForPromise shouldReject: true, ->
|
||||
help = {
|
||||
link: "http://test.com"
|
||||
program: "test-program"
|
||||
pathOption: "Lang - Test Program Path"
|
||||
}
|
||||
p = beautifier.run("program", [], help: help)
|
||||
expect(p).not.toBe(null)
|
||||
expect(p instanceof beautifier.Promise).toBe(true)
|
||||
cb = (v) ->
|
||||
# console.log(v)
|
||||
expect(v).not.toBe(null)
|
||||
expect(v instanceof Error).toBe(true)
|
||||
expect(v.code).toBe("CommandNotFound")
|
||||
expect(v.description).not.toBe(null)
|
||||
expect(v.description.indexOf(help.link)).not.toBe(-1)
|
||||
expect(v.description.indexOf(help.program)).not.toBe(-1)
|
||||
expect(v.description
|
||||
.indexOf(help.pathOption)).not.toBe(-1, \
|
||||
"Error should have a description.")
|
||||
return v
|
||||
p.then(cb, cb)
|
||||
return p
|
||||
|
||||
it "should error with Windows-specific help description \
|
||||
when beautifier's program not found", ->
|
||||
expect(beautifier).not.toBe(null)
|
||||
expect(beautifier instanceof Beautifier).toBe(true)
|
||||
|
||||
waitsForPromise shouldReject: true, ->
|
||||
help = {
|
||||
link: "http://test.com"
|
||||
program: "test-program"
|
||||
pathOption: "Lang - Test Program Path"
|
||||
}
|
||||
# Force to be Windows
|
||||
beautifier.isWindows = true
|
||||
terminal = 'CMD prompt'
|
||||
whichCmd = "where.exe"
|
||||
# Process
|
||||
p = beautifier.run("program", [], help: help)
|
||||
expect(p).not.toBe(null)
|
||||
expect(p instanceof beautifier.Promise).toBe(true)
|
||||
cb = (v) ->
|
||||
# console.log(v)
|
||||
expect(v).not.toBe(null)
|
||||
expect(v instanceof Error).toBe(true)
|
||||
expect(v.code).toBe("CommandNotFound")
|
||||
expect(v.description).not.toBe(null)
|
||||
expect(v.description.indexOf(help.link)).not.toBe(-1)
|
||||
expect(v.description.indexOf(help.program)).not.toBe(-1)
|
||||
expect(v.description
|
||||
.indexOf(help.pathOption)).not.toBe(-1, \
|
||||
"Error should have a description.")
|
||||
expect(v.description
|
||||
.indexOf(terminal)).not.toBe(-1, \
|
||||
"Error should have a description including \
|
||||
'#{terminal}' in message.")
|
||||
expect(v.description
|
||||
.indexOf(whichCmd)).not.toBe(-1, \
|
||||
"Error should have a description including \
|
||||
'#{whichCmd}' in message.")
|
||||
return v
|
||||
p.then(cb, cb)
|
||||
return p
|
||||
|
||||
it "should error with Mac/Linux-specific help description \
|
||||
when beautifier's program not found", ->
|
||||
expect(beautifier).not.toBe(null)
|
||||
expect(beautifier instanceof Beautifier).toBe(true)
|
||||
|
||||
waitsForPromise shouldReject: true, ->
|
||||
help = {
|
||||
link: "http://test.com"
|
||||
program: "test-program"
|
||||
pathOption: "Lang - Test Program Path"
|
||||
}
|
||||
# Force to be Mac/Linux (not Windows)
|
||||
beautifier.isWindows = false
|
||||
terminal = "Terminal"
|
||||
whichCmd = "which"
|
||||
# Process
|
||||
p = beautifier.run("program", [], help: help)
|
||||
expect(p).not.toBe(null)
|
||||
expect(p instanceof beautifier.Promise).toBe(true)
|
||||
cb = (v) ->
|
||||
# console.log(v)
|
||||
expect(v).not.toBe(null)
|
||||
expect(v instanceof Error).toBe(true)
|
||||
expect(v.code).toBe("CommandNotFound")
|
||||
expect(v.description).not.toBe(null)
|
||||
expect(v.description.indexOf(help.link)).not.toBe(-1)
|
||||
expect(v.description.indexOf(help.program)).not.toBe(-1)
|
||||
expect(v.description
|
||||
.indexOf(terminal)).not.toBe(-1, \
|
||||
"Error should have a description including \
|
||||
'#{terminal}' in message.")
|
||||
expect(v.description
|
||||
.indexOf(whichCmd)).not.toBe(-1, \
|
||||
"Error should have a description including \
|
||||
'#{whichCmd}' in message.")
|
||||
return v
|
||||
p.then(cb, cb)
|
||||
return p
|
|
@ -0,0 +1,84 @@
|
|||
PHPCSFixer = require "../src/beautifiers/php-cs-fixer"
|
||||
Beautifier = require "../src/beautifiers/beautifier"
|
||||
|
||||
# Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs.
|
||||
#
|
||||
# To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit`
|
||||
# or `fdescribe`). Remove the `f` to unfocus the block.
|
||||
|
||||
describe "PHP-CS-Fixer Beautifier", ->
|
||||
|
||||
beforeEach ->
|
||||
|
||||
# Activate package
|
||||
waitsForPromise ->
|
||||
activationPromise = atom.packages.activatePackage('atom-beautify')
|
||||
# Force activate package
|
||||
pack = atom.packages.getLoadedPackage("atom-beautify")
|
||||
pack.activateNow()
|
||||
# Change logger level
|
||||
# atom.config.set('atom-beautify._loggerLevel', 'verbose')
|
||||
# Return promise
|
||||
return activationPromise
|
||||
|
||||
describe "Beautifier::beautify", ->
|
||||
|
||||
beautifier = null
|
||||
|
||||
beforeEach ->
|
||||
beautifier = new PHPCSFixer()
|
||||
|
||||
it "should error when beautifier's program not found", ->
|
||||
expect(beautifier).not.toBe(null)
|
||||
expect(beautifier instanceof Beautifier).toBe(true)
|
||||
|
||||
waitsForPromise shouldReject: true, ->
|
||||
text = ""
|
||||
language = "PHP"
|
||||
options = {
|
||||
fixers: ""
|
||||
levels: ""
|
||||
}
|
||||
# Mock
|
||||
beautifier.getShellEnvironment = -> Promise.resolve("")
|
||||
#
|
||||
p = beautifier.beautify(text, language, options)
|
||||
expect(p).not.toBe(null)
|
||||
expect(p instanceof beautifier.Promise).toBe(true)
|
||||
cb = (v) ->
|
||||
console.log(v)
|
||||
expect(v).not.toBe(null)
|
||||
expect(v instanceof Error).toBe(true)
|
||||
expect(v.code).toBe("CommandNotFound")
|
||||
return v
|
||||
p.then(cb, cb)
|
||||
return p
|
||||
|
||||
# it "should error with help description \
|
||||
# when beautifier's program not found", ->
|
||||
# expect(beautifier).not.toBe(null)
|
||||
# expect(beautifier instanceof Beautifier).toBe(true)
|
||||
#
|
||||
# waitsForPromise shouldReject: true, ->
|
||||
# help = {
|
||||
# link: "http://test.com"
|
||||
# program: "test-program"
|
||||
# pathOption: "Lang - Test Program Path"
|
||||
# }
|
||||
# p = beautifier.run("program", [], help: help)
|
||||
# expect(p).not.toBe(null)
|
||||
# expect(p instanceof beautifier.Promise).toBe(true)
|
||||
# cb = (v) ->
|
||||
# # console.log(v)
|
||||
# expect(v).not.toBe(null)
|
||||
# expect(v instanceof Error).toBe(true)
|
||||
# expect(v.code).toBe("CommandNotFound")
|
||||
# expect(v.description).not.toBe(null)
|
||||
# expect(v.description.indexOf(help.link)).not.toBe(-1)
|
||||
# expect(v.description.indexOf(help.program)).not.toBe(-1)
|
||||
# expect(v.description
|
||||
# .indexOf(help.pathOption)).not.toBe(-1, \
|
||||
# "Error should have a description.")
|
||||
# return v
|
||||
# p.then(cb, cb)
|
||||
# return p
|
|
@ -80,6 +80,12 @@ module.exports = class Beautifier
|
|||
return readFile(filePath, "utf8")
|
||||
)
|
||||
|
||||
###
|
||||
If platform is Windows
|
||||
###
|
||||
isWindows: do ->
|
||||
return /^win/.test(process.platform)
|
||||
|
||||
###
|
||||
Get Shell Environment variables
|
||||
|
||||
|
@ -99,8 +105,7 @@ module.exports = class Beautifier
|
|||
return resolve(@_envCache)
|
||||
|
||||
# Check if Windows
|
||||
isWin = /^win/.test(process.platform)
|
||||
if isWin
|
||||
if @isWindows
|
||||
# Windows
|
||||
# Use default
|
||||
resolve(process.env)
|
||||
|
@ -154,6 +159,70 @@ module.exports = class Beautifier
|
|||
)
|
||||
)
|
||||
|
||||
###
|
||||
Add help to error.description
|
||||
|
||||
Note: error.description is not officially used in JavaScript,
|
||||
however it is used internally for Atom Beautify when displaying errors.
|
||||
###
|
||||
commandNotFoundError: (exe, help) ->
|
||||
# Create new improved error
|
||||
# notify user that it may not be
|
||||
# installed or in path
|
||||
message = "Could not find '#{exe}'. \
|
||||
The program may not be installed."
|
||||
er = new Error(message)
|
||||
er.code = 'CommandNotFound'
|
||||
er.errno = er.code
|
||||
er.syscall = 'beautifier::run'
|
||||
er.file = exe
|
||||
if help?
|
||||
if typeof help is "object"
|
||||
# Basic notice
|
||||
helpStr = "See #{help.link} for program \
|
||||
installation instructions.\n"
|
||||
# Help to configure Atom Beautify for program's path
|
||||
helpStr += "You can configure Atom Beautify \
|
||||
with the absolute path \
|
||||
to '#{help.program or exe}' by setting \
|
||||
'#{help.pathOption}' in \
|
||||
the Atom Beautify package settings.\n" if help.pathOption
|
||||
# Optional, additional help
|
||||
helpStr += help.additional if help.additional
|
||||
# Common Help
|
||||
issueSearchLink =
|
||||
"https://github.com/Glavin001/atom-beautify/\
|
||||
search?q=#{exe}&type=Issues"
|
||||
docsLink = "https://github.com/Glavin001/\
|
||||
atom-beautify/tree/master/docs"
|
||||
helpStr += "Your program is properly installed if running \
|
||||
'#{if @isWindows then 'where.exe' \
|
||||
else 'which'} #{exe}' \
|
||||
in your #{if @isWindows then 'CMD prompt' \
|
||||
else 'Terminal'} \
|
||||
returns an absolute path to the executable. \
|
||||
If this does not work then you have not \
|
||||
installed the program correctly and so \
|
||||
Atom Beautify will not find the program. \
|
||||
Atom Beautify requires that the program be \
|
||||
found in your PATH environment variable. \n\
|
||||
Note that this is not an Atom Beautify issue \
|
||||
if beautification does not work and the above \
|
||||
command also does not work: this is expected \
|
||||
behaviour, since you have not properly installed \
|
||||
your program. Please properly setup the program \
|
||||
and search through existing Atom Beautify issues \
|
||||
before creating a new issue. \
|
||||
See #{issueSearchLink} for related Issues and \
|
||||
#{docsLink} for documentation. \
|
||||
If you are still unable to resolve this issue on \
|
||||
your own then please create a new issue and \
|
||||
ask for help.\n"
|
||||
er.description = helpStr
|
||||
else #if typeof help is "string"
|
||||
er.description = help
|
||||
return er
|
||||
|
||||
###
|
||||
Run command-line interface command
|
||||
###
|
||||
|
@ -200,27 +269,7 @@ module.exports = class Beautifier
|
|||
# Check if error is ENOENT
|
||||
# (command could not be found)
|
||||
if err.code is 'ENOENT' or err.errno is 'ENOENT'
|
||||
# Create new improved error
|
||||
# notify user that it may not be
|
||||
# installed or in path
|
||||
message = "Could not find '#{exe}'. \
|
||||
The program may not be installed."
|
||||
er = new Error(message)
|
||||
if help?
|
||||
if typeof help is "object"
|
||||
helpStr = "See #{help.link} for program installation instructions.\n"
|
||||
helpStr += "You can configure Atom Beautify with the absolute path \
|
||||
to '#{help.program or exe}' by setting '#{help.pathOption}' in \
|
||||
the Atom Beautify package settings.\n" if help.pathOption
|
||||
helpStr += help.additional if help.additional
|
||||
er.description = helpStr
|
||||
else #if typeof help is "string"
|
||||
er.description = help
|
||||
er.code = 'CommandNotFound'
|
||||
er.errno = er.code
|
||||
er.syscall = 'beautifier::run'
|
||||
er.file = exe
|
||||
reject(er)
|
||||
reject(@commandNotFoundError(exeName, help))
|
||||
else
|
||||
# continue as normal error
|
||||
reject(err)
|
||||
|
|
|
@ -15,26 +15,48 @@ module.exports = class PHPCSFixer extends Beautifier
|
|||
beautify: (text, language, options) ->
|
||||
@debug('php-cs-fixer', options)
|
||||
|
||||
isWin = /^win/.test(process.platform)
|
||||
|
||||
isWin = @isWindows
|
||||
if isWin
|
||||
@run("php", [
|
||||
options.cs_fixer_path or "php-cs-fixer.phar"
|
||||
"fix"
|
||||
"--level=#{options.level}" if options.level
|
||||
"--fixers=#{options.fixers}" if options.fixers
|
||||
tempFile = @tempFile("temp", text)
|
||||
], {
|
||||
ignoreReturnCode: true
|
||||
help: {
|
||||
# Find php-cs-fixer.phar script
|
||||
@Promise.all([
|
||||
@which(options.cs_fixer_path)
|
||||
@which('php-cs-fixer')
|
||||
@which('php-cs-fixer.phar')
|
||||
]).then((paths...)=>
|
||||
@debug('php-cs-fixer paths', paths)
|
||||
path = require('path')
|
||||
# Get first valid path
|
||||
phpCSFixerPath = _.find(paths, (p) -> path.isAbsolute(p) )
|
||||
@debug('phpCSFixerPath', phpCSFixerPath)
|
||||
# Check if PHP-CS-Fixer path was found
|
||||
if phpCSFixerPath?
|
||||
# Found PHP-CS-Fixer path
|
||||
@run("php", [
|
||||
phpCSFixerPath
|
||||
"fix"
|
||||
"--level=#{options.level}" if options.level
|
||||
"--fixers=#{options.fixers}" if options.fixers
|
||||
tempFile = @tempFile("temp", text)
|
||||
], {
|
||||
ignoreReturnCode: true
|
||||
help: {
|
||||
link: "http://php.net/manual/en/install.php"
|
||||
}
|
||||
})
|
||||
.then(=>
|
||||
@readFile(tempFile)
|
||||
)
|
||||
else
|
||||
# could not find PHP-CS-Fixer path
|
||||
@Promise.reject(@commandNotFoundError(
|
||||
'php-cs-fixer'
|
||||
{
|
||||
link: "https://github.com/FriendsOfPHP/PHP-CS-Fixer"
|
||||
program: "php-cs-fixer.phar"
|
||||
pathOption: "PHP - CS Fixer Path"
|
||||
}
|
||||
})
|
||||
.then(=>
|
||||
@readFile(tempFile)
|
||||
)
|
||||
})
|
||||
)
|
||||
)
|
||||
else
|
||||
@run("php-cs-fixer", [
|
||||
"fix"
|
||||
|
@ -42,12 +64,10 @@ module.exports = class PHPCSFixer extends Beautifier
|
|||
"--fixers=#{options.fixers}" if options.fixers
|
||||
tempFile = @tempFile("temp", text)
|
||||
], {
|
||||
ignoreReturnCode: true
|
||||
help: {
|
||||
link: "https://github.com/FriendsOfPHP/PHP-CS-Fixer"
|
||||
program: "php-cs-fixer.phar"
|
||||
pathOption: "PHP - CS Fixer Path"
|
||||
}
|
||||
ignoreReturnCode: true
|
||||
help: {
|
||||
link: "https://github.com/FriendsOfPHP/PHP-CS-Fixer"
|
||||
}
|
||||
})
|
||||
.then(=>
|
||||
@readFile(tempFile)
|
||||
|
|
Loading…
Reference in New Issue