Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / toolcontext.nit
index 850781e..043e9ee 100644 (file)
@@ -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
@@ -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
@@ -225,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
@@ -257,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
@@ -286,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
@@ -325,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
 
@@ -334,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
@@ -360,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")
 
@@ -387,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_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)
+               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
@@ -484,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
@@ -526,9 +550,40 @@ The Nit language documentation and the source code of its tools and libraries ma
        end
 
        # The identified root directory of the Nit package
-       var nit_dir: String is noinit
+       #
+       # It is assignable but is automatically set by `process_options` with `locate_nit_dir`.
+       var nit_dir: nullable String = null is writable
 
-       private fun compute_nit_dir: String
+       # 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
+
+       # 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
@@ -561,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