X-Git-Url: http://nitlanguage.org?ds=sidebyside diff --git a/src/toolcontext.nit b/src/toolcontext.nit index 645038e..043e9ee 100644 --- a/src/toolcontext.nit +++ b/src/toolcontext.nit @@ -58,6 +58,13 @@ class Message # * 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 @@ -84,7 +91,7 @@ class Message # 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" @@ -123,13 +130,20 @@ redef class Location 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 - var error_count: Int = 0 + var error_count: Int = 0 is writable # Number of warnings var warning_count: Int = 0 @@ -169,6 +183,16 @@ class ToolContext 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. @@ -215,9 +239,10 @@ class ToolContext # 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 + if opt_warn.value <= -1 then return m messages.add m error_count = error_count + 1 if opt_stop_on_first_error.value then check_errors @@ -247,12 +272,12 @@ class ToolContext # 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 @@ -276,12 +301,12 @@ class ToolContext # 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 @@ -315,7 +340,7 @@ class ToolContext proc_which.wait var res = proc_which.status if res != 0 then - print "{error}: executable \"{prog}\" not found" + print_error "{error}: executable \"{prog}\" not found" exit 1 end @@ -324,7 +349,7 @@ class ToolContext proc.wait res = proc.status if res != 0 then - print "{error}: execution of \"{prog} {args.join(" ")}\" failed" + print_error "{error}: execution of \"{prog} {args.join(" ")}\" failed" exit 1 end end @@ -333,7 +358,7 @@ class ToolContext 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") @@ -350,6 +375,9 @@ class ToolContext # Option --nit-dir var opt_nit_dir = new OptionString("Base directory of the Nit installation", "--nit-dir") + # Option --share-dir + var opt_share_dir = new OptionString("Directory containing tools assets", "--share-dir") + # Option --help var opt_help = new OptionBool("Show Help (This screen)", "-h", "-?", "--help") @@ -360,10 +388,13 @@ class ToolContext 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") @@ -374,12 +405,18 @@ class ToolContext # Option --stub-man var opt_stub_man = new OptionBool("Generate a stub manpage in pandoc markdown format", "--stub-man") + # Option --no-contract + var opt_no_contract = new OptionBool("Disable the contracts usage", "--no-contract") + + # Option --full-contract + var opt_full_contract = new OptionBool("Enable all contracts usage", "--full-contract") + # Verbose level var verbose_level: Int = 0 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, opt_no_contract, opt_full_contract) # Hide some internal options opt_stub_man.hidden = true @@ -437,26 +474,23 @@ class ToolContext 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 """ @@ -466,7 +500,7 @@ The Nit language documentation and the source code of its tools and libraries ma 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 @@ -474,7 +508,7 @@ The Nit language documentation and the source code of its tools and libraries ma exit 1 end - nit_dir = compute_nit_dir + nit_dir = locate_nit_dir if option_context.rest.is_empty and not accept_no_arguments then print tooldescription @@ -485,6 +519,8 @@ The Nit language documentation and the source code of its tools and libraries ma # 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) @@ -510,13 +546,44 @@ The Nit language documentation and the source code of its tools and libraries ma 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 - var nit_dir: String is noinit + # The identified root directory of the Nit package + # + # It is assignable but is automatically set by `process_options` with `locate_nit_dir`. + var nit_dir: nullable String = null is writable + + # Shared files directory. + # + # Most often `nit/share/`. + var share_dir: String is lazy do + var sharedir = opt_share_dir.value + if sharedir == null then + sharedir = nit_dir / "share" + if not sharedir.file_exists then + fatal_error(null, "Fatal Error: cannot locate shared files directory in {sharedir}. Uses --share-dir to define it's location.") + end + end + return sharedir + end - private fun compute_nit_dir: String + # Guess a possible nit_dir. + # + # It uses, in order: + # + # * the option `opt_nit_dir` + # * the environment variable `NIT_DIR` + # * the runpath of the program from argv[0] + # * the runpath of the process from /proc + # * the search in PATH + # + # If there is errors (e.g. the indicated path is invalid) or if no + # path is found, then an error is displayed and the program exits. + # + # The result is returned without being assigned to `nit_dir`. + # This function is automatically called by `process_options` + fun locate_nit_dir: String do # the option has precedence var res = opt_nit_dir.value @@ -549,7 +616,8 @@ The Nit language documentation and the source code of its tools and libraries ma end # search in the PATH - var ps = "PATH".environ.split(":") + var path_sep = if is_windows then ";" else ":" + var ps = "PATH".environ.split(path_sep) for p in ps do res = p/".." if check_nit_dir(res) then return res.simplify_path @@ -569,16 +637,18 @@ 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`.