# The human-readable description of the message.
#
- # It should be short and fit on a single line.
- # It should also have meaningful information first in case
- # on truncation by an IDE for instance.
+ # eg. "Error: cannot find method `foo`."
+ #
+ # A good message should:
+ #
+ # * start with a message type like "Error:", "Syntax Error:", "Warning:".
+ # The type is capitalized and terminated by a column.
+ # The rest on the message starts with a lowercase letter and is terminated with a dot.
+ #
+ # * be short and fit on a single line.
+ #
+ # * have meaningful information first.
+ # This helps the reader and remain usable
+ # when truncated, by an IDE for instance.
+ #
+ # * enclose identifiers, keywords and pieces of code with back-quotes.
var text: String
+ # The severity level
+ #
+ # * 0 is advices (see `ToolContext::advice`)
+ # * 1 is warnings (see `ToolContext::warning`)
+ # * 2 is errors (see `ToolContext::error`)
+ var level: Int
+
# Comparisons are made on message locations.
redef fun <(other: OTHER): Bool do
if location == null then return true
return location.as(not null) < other.location.as(not null)
end
+ redef fun ==(other): Bool do
+ if not other isa Message then return false
+ return location == other.location and tag == other.tag and text == other.text
+ end
+
redef fun to_s: String
do
var l = location
# A colored version of the message including the original source line
fun to_color_string: String
do
- var esc = 27.ascii
+ var esc = 27.code_point
#var red = "{esc}[0;31m"
#var bred = "{esc}[1;31m"
#var green = "{esc}[0;32m"
messages = ms
end
ms.add m
+ var s = file
+ if s != null then s.messages.add m
end
end
+redef class SourceFile
+ # Errors and warnings associated to the whole source.
+ var messages = new Array[Message]
+end
+
# Global context for tools
class ToolContext
# Number of errors
return tags.has("all") or tags.has(tag)
end
+ # Output all current stacked messages, total and exit the program
+ #
+ # If there is no error, exit with 0, else exit with 1.
+ fun quit
+ do
+ check_errors
+ errors_info
+ if error_count > 0 then exit(1) else exit(0)
+ end
+
# Output all current stacked messages
#
# Return true if no errors occurred.
# Return the message (to add information)
fun error(l: nullable Location, s: String): Message
do
- var m = new Message(l,null,s)
+ var m = new Message(l, null, s, 2)
+ if messages.has(m) then return m
if l != null then l.add_message m
messages.add m
error_count = error_count + 1
# Return the message (to add information) or null if the warning is disabled
fun warning(l: nullable Location, tag: String, text: String): nullable Message
do
- if opt_warning.value.has("no-{tag}") then return null
- if not opt_warning.value.has(tag) and opt_warn.value == 0 then return null
if is_warning_blacklisted(l, tag) then return null
- var m = new Message(l, tag, text)
+ var m = new Message(l, tag, text, 1)
+ if messages.has(m) then return null
if l != null then l.add_message m
+ if opt_warning.value.has("no-{tag}") then return null
+ if not opt_warning.value.has(tag) and opt_warn.value == 0 then return null
messages.add m
warning_count = warning_count + 1
if opt_stop_on_first_error.value then check_errors
# Return the message (to add information) or null if the warning is disabled
fun advice(l: nullable Location, tag: String, text: String): nullable Message
do
- if opt_warning.value.has("no-{tag}") then return null
- if not opt_warning.value.has(tag) and opt_warn.value <= 1 then return null
if is_warning_blacklisted(l, tag) then return null
- var m = new Message(l, tag, text)
+ var m = new Message(l, tag, text, 0)
+ if messages.has(m) then return null
if l != null then l.add_message m
+ if opt_warning.value.has("no-{tag}") then return null
+ if not opt_warning.value.has(tag) and opt_warn.value <= 1 then return null
messages.add m
warning_count = warning_count + 1
if opt_stop_on_first_error.value then check_errors
var option_context = new OptionContext
# Option --warn
- var opt_warn = new OptionCount("Show more warnings", "-W", "--warn")
+ var opt_warn = new OptionCount("Show additional warnings (advices)", "-W", "--warn")
# Option --warning
var opt_warning = new OptionArray("Show/hide a specific warning", "-w", "--warning")
var opt_set_dummy_tool = new OptionBool("Set toolname and version to DUMMY. Useful for testing", "--set-dummy-tool")
# Option --verbose
- var opt_verbose = new OptionCount("Verbose", "-v", "--verbose")
+ var opt_verbose = new OptionCount("Additional messages from the tool", "-v", "--verbose")
# Option --stop-on-first-error
- var opt_stop_on_first_error = new OptionBool("Stop on first error", "--stop-on-first-error")
+ var opt_stop_on_first_error = new OptionBool("Just display the first encountered error then stop", "--stop-on-first-error")
+
+ # Option --keep-going
+ var opt_keep_going = new OptionBool("Continue after errors, whatever the consequences", "--keep-going")
# Option --no-color
var opt_no_color = new OptionBool("Do not use color to display errors and warnings", "--no-color")
init
do
- option_context.add_option(opt_warn, opt_warning, opt_quiet, opt_stop_on_first_error, opt_no_color, opt_log, opt_log_dir, opt_nit_dir, opt_help, opt_version, opt_set_dummy_tool, opt_verbose, opt_bash_completion, opt_stub_man)
+ option_context.add_option(opt_warn, opt_warning, opt_quiet, opt_stop_on_first_error, opt_keep_going, opt_no_color, opt_log, opt_log_dir, opt_nit_dir, opt_help, opt_version, opt_set_dummy_tool, opt_verbose, opt_bash_completion, opt_stub_man)
# Hide some internal options
opt_stub_man.hidden = true
if opt_stub_man.value then
print """
-% {{{toolname.to_upper}}}(1)
-
# NAME
{{{tooldescription.split("\n")[1]}}}
# SYNOPSYS
-{{{toolname}}} [*options*]...
-
# OPTIONS
"""
for o in option_context.options do
var first = true
+ printn "### "
for n in o.names do
if first then first = false else printn ", "
printn "`{n}`"
end
print ""
- print ": {o.helptext}"
+ print "{o.helptext}."
print ""
end
print """
exit 0
end
- var errors = option_context.get_errors
+ var errors = option_context.errors
if not errors.is_empty then
for e in errors do print "Error: {e}"
print tooldescription
# Set verbose level
verbose_level = opt_verbose.value
+ if opt_keep_going.value then keep_going = true
+
if self.opt_quiet.value then self.opt_warn.value = 0
if opt_log_dir.value != null then log_directory = opt_log_dir.value.as(not null)
if opt_set_dummy_tool.value then
return "DUMMY_TOOL"
end
- return sys.program_name.basename("")
+ return sys.program_name.basename
end
- # The identified root directory of the Nit project
+ # The identified root directory of the Nit package
var nit_dir: String is noinit
private fun compute_nit_dir: String
var res = opt_nit_dir.value
if res != null then
if not check_nit_dir(res) then
- fatal_error(null, "Fatal Error: the value of --nit-dir does not seem to be a valid base Nit directory: {res}")
+ fatal_error(null, "Fatal Error: the value of --nit-dir does not seem to be a valid base Nit directory: {res}.")
end
return res
end
res = "NIT_DIR".environ
if not res.is_empty then
if not check_nit_dir(res) then
- fatal_error(null, "Fatal Error: the value of NIT_DIR does not seem to be a valid base Nit directory: {res}")
+ fatal_error(null, "Fatal Error: the value of NIT_DIR does not seem to be a valid base Nit directory: {res}.")
end
return res
end
if check_nit_dir(res) then return res.simplify_path
end
- fatal_error(null, "Fatal Error: Cannot locate a valid base nit directory. It is quite unexpected. Try to set the environment variable `NIT_DIR` or to use the `--nit-dir` option.")
+ fatal_error(null, "Fatal Error: cannot locate a valid base Nit directory. It is quite unexpected. Try to set the environment variable `NIT_DIR` or to use the `--nit-dir` option.")
abort
end
#
# On some Linux systems `bash_completion` allow the program to control command line behaviour.
#
-# $ nitls [TAB][TAB]
-# file1.nit file2.nit file3.nit
+# ~~~sh
+# $ nitls [TAB][TAB]
+# file1.nit file2.nit file3.nit
#
-# $ nitls --[TAB][TAB]
-# --bash-toolname --keep --path --tree
-# --depends --log --project --verbose
-# --disable-phase --log-dir --quiet --version
-# --gen-bash-completion --no-color --recursive --warn
-# --help --only-metamodel --source
-# --ignore-visibility --only-parse --stop-on-first-error
+# $ nitls --[TAB][TAB]
+# --bash-toolname --keep --path --tree
+# --depends --log --package --verbose
+# --disable-phase --log-dir --quiet --version
+# --gen-bash-completion --no-color --recursive --warn
+# --help --only-metamodel --source
+# --ignore-visibility --only-parse --stop-on-first-error
+# ~~~
#
# Generated file can be placed in system bash_completion directory `/etc/bash_completion.d/`
# or source it in `~/.bash_completion`.