Merge: Useless type
authorJean Privat <jean@pryen.org>
Fri, 28 Nov 2014 21:19:31 +0000 (16:19 -0500)
committerJean Privat <jean@pryen.org>
Fri, 28 Nov 2014 21:19:31 +0000 (16:19 -0500)
Fix a wrong `useless-type` warning for attributes.
Extends the `useless-type` warning to local variables.

Pull-Request: #945

66 files changed:
contrib/jwrapper/src/javap_visitor.nit
contrib/nitiwiki/src/wiki_html.nit
doc/Makefile [new file with mode: 0644]
doc/README [deleted file]
doc/README.md [new file with mode: 0644]
lib/a_star.nit
lib/ai/backtrack.nit
lib/ai/examples/queens.nit
lib/ai/search.nit
lib/android/intent/intent_api10.nit
lib/android/notification/notification.nit
lib/android/sensors.nit
lib/android/shared_preferences/shared_preferences_api10.nit
lib/android/shared_preferences/shared_preferences_api11.nit
lib/android/ui.nit
lib/cpp.nit
lib/emscripten.nit
lib/geometry/boxes.nit
lib/gpio.nit
lib/hash_debug.nit
lib/json/dynamic.nit
lib/jvm.nit
lib/libevent.nit
lib/markdown/markdown.nit
lib/mnit/mnit_injected_input.nit
lib/mnit_display.nit
lib/more_collections.nit
lib/mpi.nit
lib/ordered_tree.nit
lib/pipeline.nit
lib/pnacl.nit
lib/poset.nit
lib/privileges.nit
lib/sax/helpers/sax_locator_impl.nit
lib/sax/xml_reader.nit
lib/scene2d.nit
lib/signals.nit
lib/sqlite3/sqlite3.nit
lib/standard/collection/abstract_collection.nit
lib/standard/string.nit
lib/string_experimentations/utf8.nit
lib/string_experimentations/utf8_noindex.nit
lib/template/macro.nit
lib/trees/bintree.nit
lib/trees/rbtree.nit
share/man/nitunit.md
src/astbuilder.nit
src/compiler/coloring.nit
src/docdown.nit
src/ffi/c.nit
src/model/model.nit
src/model_utils.nit
src/neo.nit
src/nitpretty.nit
src/testing/testing_doc.nit
src/testing/testing_suite.nit
src/transform.nit
src/vm.nit
tests/niti.skip
tests/nitunit.args
tests/sav/nitunit_args5.res [new file with mode: 0644]
tests/sav/test_docdown_args1.res
tests/sav/test_docdown_args2.res [new file with mode: 0644]
tests/test_doc2.nit [new file with mode: 0644]
tests/test_docdown.args [new file with mode: 0644]
tests/test_markdown.args [deleted file]

index 45edb3d..1ede6f0 100644 (file)
@@ -300,6 +300,7 @@ end
 #                                  #
 #    C L A S S     H E A D E R     #
 #                                  #
+
 redef class Nclass_header
        redef fun accept_visitor(v)
        do
index c984bc8..266e1d9 100644 (file)
@@ -121,15 +121,17 @@ redef class WikiSection
        #
        # The generated tree will be something like this:
        #
-       #    <ul>
-       #     <li>section 1</li>
-       #     <li>section 2
-       #      <ul>
-       #       <li>section 2.1</li>
-       #       <li>section 2.2</li>
-       #      </ul>
-       #     </li>
-       #    </ul>
+       # ~~~html
+       # <ul>
+       #  <li>section 1</li>
+       #  <li>section 2
+       #   <ul>
+       #    <li>section 2.1</li>
+       #    <li>section 2.2</li>
+       #   </ul>
+       #  </li>
+       # </ul>
+       # ~~~
        fun tpl_tree(limit: Int): Template do
                return tpl_tree_intern(limit, 1)
        end
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644 (file)
index 0000000..91ae0c8
--- /dev/null
@@ -0,0 +1,2 @@
+all:
+       ${MAKE} docs -C ..
diff --git a/doc/README b/doc/README
deleted file mode 100644 (file)
index 0e23e6a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-This directory contains various documentation for Nit
-
-* advanced_options [TXT]: documentation for advanced options of the compiler and run-time execution.
-* stdlib [HTML]: Autodocumentation for the Nit standard library.
-
-For more documentation, visit http://nitlanguage.org/doc/
diff --git a/doc/README.md b/doc/README.md
new file mode 100644 (file)
index 0000000..406cb02
--- /dev/null
@@ -0,0 +1,12 @@
+This directory contains auto-documentation generated by nitdoc.
+
+ * [stdlib](http://nitlanguage.org/doc/stdlib/): the Nit libraries (from `../lib/`).
+ * [nitc](http://nitlanguage.org/doc/nitc/): the Nit tools (from `../src/`).
+
+Run `make` to produce them.
+
+Specific documentation can be found elsewhere:
+
+ * The manpages of the Nit tools are in the directory `../share/man`
+ * The documentation of the other tools and programs are in their subdirectories in `../examples` and `../contrib`
+ * For more documentation, visit <http://nitlanguage.org/doc/>
index 4108268..97925ff 100644 (file)
@@ -57,14 +57,14 @@ module a_star
 
 # General graph node
 class Node
+       # Type of the others nodes in the `graph`
        type N: Node
 
        # parent graph
        var graph: Graph[N, Link]
 
-       init(graph: Graph[N, Link])
+       init
        do
-               self.graph = graph
                graph.add_node(self)
        end
 
@@ -186,29 +186,36 @@ end
 
 # Link between two nodes and associated to a graph
 class Link
+       # Type of the nodes in `graph`
        type N: Node
+
+       # Type of the other links in `graph`
        type L: Link
 
+       # The graph to which belongs `self`
        var graph: Graph[N, L]
 
+       # Origin of this link
        var from: N
+
+       # Endpoint of this link
        var to: N
 
-       init(graph: Graph[N, L], from, to: N)
+       init
        do
-               self.graph = graph
-               self.from = from
-               self.to = to
-
                graph.add_link(self)
        end
 end
 
 # General graph
 class Graph[N: Node, L: Link]
+       # Nodes in this graph
        var nodes: Set[N] = new HashSet[N]
+
+       # Links in this graph
        var links: Set[L] = new HashSet[L]
 
+       # Add a `node` to this graph
        fun add_node(node: N): N
        do
                nodes.add(node)
@@ -216,6 +223,7 @@ class Graph[N: Node, L: Link]
                return node
        end
 
+       # Add a `link` to this graph
        fun add_link(link: L): L
        do
                links.add(link)
@@ -225,20 +233,22 @@ class Graph[N: Node, L: Link]
                return link
        end
 
-       # used to check if nodes have been searched in one pathfinding
-       var pathfinding_current_evocation: Int = 0
+       # Used to check if nodes have been searched in one pathfinding
+       private var pathfinding_current_evocation: Int = 0
 end
 
-# Result from pathfinding, a walkable path
+# Result from path finding and a walkable path
 class Path[N]
 
+       # The total cost of this path
        var total_cost: Int
 
+       # The list of nodes composing this path
        var nodes = new List[N]
 
-       init (cost: Int) do total_cost = cost
+       private var at: Int = 0
 
-       var at: Int = 0
+       # Step on the path and get the next node to travel
        fun step: N
        do
                assert nodes.length >= at else print "a_star::Path::step failed, is at_end_of_path"
@@ -249,16 +259,22 @@ class Path[N]
                return s
        end
 
+       # Peek at the next step of the path
        fun peek_step: N do return nodes[at]
 
+       # Are we at the end of this path?
        fun at_end_of_path: Bool do return at >= nodes.length
 end
 
 # Context related to an evocation of pathfinding
 class PathContext
+       # Type of the nodes in `graph`
        type N: Node
+
+       # Type of the links in `graph`
        type L: Link
 
+       # Graph to which is associated `self`
        var graph: Graph[N, L]
 
        # Worst cost of all the link's costs
@@ -273,6 +289,7 @@ class PathContext
        # Heuristic
        fun heuristic_cost(a, b: N): Int is abstract
 
+       # The worst cost suggested by the heuristic
        fun worst_heuristic_cost: Int is abstract
 end
 
@@ -292,12 +309,13 @@ class ConstantPathContext
        redef fun worst_heuristic_cost do return 0
 end
 
+# A `PathContext` for graphs with `WeightedLink`
 class WeightedPathContext
        super PathContext
 
        redef type L: WeightedLink
 
-       init(graph: Graph[N, L])
+       init
        do
                super
 
@@ -309,7 +327,7 @@ class WeightedPathContext
                self.worst_cost = worst_cost
        end
 
-       redef var worst_cost: Int
+       redef var worst_cost: Int is noinit
 
        redef fun cost(l) do
                return l.weight
@@ -319,17 +337,12 @@ class WeightedPathContext
        redef fun worst_heuristic_cost do return 0
 end
 
+# A `Link` with a `weight`
 class WeightedLink
        super Link
 
+       # The `weight`, or cost, of this link
        var weight: Int
-
-       init(graph: Graph[N, L], from, to: N, weight: Int)
-       do
-               super
-
-               self.weight = weight
-       end
 end
 
 # Advanced path conditions with customizable accept states
index 0232b4c..550df10 100644 (file)
@@ -86,7 +86,7 @@ end
 # 2. Apply the method `run`, that will search and return a solution.
 # 3. Retrieve information from the solution.
 #
-# ~~~~
+# ~~~~nitish
 # var p: BacktrackProblem = new MyProblem
 # var solver = p.solve
 # var res = solver.run
index d25e129..0e86903 100644 (file)
@@ -14,7 +14,7 @@
 # The constraint is that two queens cannot be on the same row, column or diagonal.
 #
 # Eg. a solution to the 8-queens problem is
-# ~~~
+# ~~~raw
 # +--------+
 # |Q.......|
 # |....Q...|
index 21a349d..64904ee 100644 (file)
@@ -199,7 +199,7 @@ end
 # 2. Apply the method `run`, that will search and return a solution.
 # 3. Retrieve information from the solution.
 #
-# ~~~~
+# ~~~~nitish
 # var p: SearchProblem = new MyProblem
 # var res = p.astar.run
 # if res != null then print "Found plan with {res.depth} actions, that cost {res.cost}: {res.plan.join(", ")}"
index 20c85dc..005b475 100644 (file)
@@ -646,8 +646,8 @@ class Intent
 
        # The general action to be performed
        #
-       # Example :
-       # ~~~
+       # ~~~nitish
+       # # TODO better example
        # intent.action = intent_action.view.to_s
        # ~~~
        fun action=(action: String)
@@ -667,8 +667,8 @@ class Intent
        # Add category to the intent
        # Only activities providing all of the requested categories will be used
        #
-       # Example :
-       # ~~~
+       # ~~~nitish
+       # # TODO better example
        # intent.add_category(intent_category.home.to_s)
        # ~~~
        # Returns `self` allowing fluent programming
@@ -720,8 +720,8 @@ class Intent
 
        # Add a flag to be used by the intent
        #
-       # Example :
-       # ~~~
+       # ~~~nitish
+       # # TODO better example
        # intent.add_flags(intent_flag.activity_new_task)
        # ~~~
        # Returns `self` allowing fluent programming
index 07d1c00..a4d34d4 100644 (file)
@@ -16,7 +16,7 @@
 
 # Services to show notification in the Android status bar
 #
-# ~~~~
+# ~~~~nitish
 # # Create and show a notification
 # var notif = new Notification("My Title", "Some content")
 # notif.ticker = "Ticker text"
@@ -25,7 +25,7 @@
 # # Update the notification
 # notif.text = "New content!"
 # notif.ongoing = true # Make it un-dismissable
-# nofif.show
+# notif.show
 #
 # # Hide the notification
 # notif.cancel
index 4c28466..a38dd60 100644 (file)
@@ -18,7 +18,8 @@
 # The sensor support is implemented in android_app module, so the user can enable the type of sensor he wants to use.
 # There is an example of how you can use the android sensors in nit/examples/mnit_ballz :
 #
-# ~~~~
+# ~~~~nitish
+# #FIXME rewrite the example
 # var app = new MyApp
 # app.sensors_support_enabled = true
 # app.accelerometer.enabled = true
index 404aaea..94aac59 100644 (file)
@@ -205,15 +205,14 @@ class SharedPreferences
        #
        # User has to manage local stack deallocation himself
        #
-       # Example :
-       # ~~~
+       # ~~~nitish
        # var foo = new HashMap[JavaString, JavaObject]
        # # ...
        # for key, value in foo do
        #      key.delete_local_ref
        #      value.delete_local_ref
        # end
-       # ~~~
+       # ~~~
        # *You should use Nit getters instead and get each value one by one* 
        fun all: nullable HashMap[JavaString, JavaObject]
        do 
index 50d88e9..cb55acc 100644 (file)
@@ -73,10 +73,9 @@ redef class SharedPreferences
        #
        # User has to manage local stack deallocation himself
        #
-       # Example :
-       # ~~~
-       # var a_hash_set = shared_preferences.string_set("A key")
-       # ...
+       # ~~~nitish
+       # var a_hash_set = app.shared_preferences.string_set("A key")
+       # # ...
        # for element in a_hash_set do element.delete_local_ref
        # ~~~
        fun string_set(key: String): HashSet[JavaString] 
@@ -92,10 +91,9 @@ redef class SharedPreferences
        #
        # User has to manage local stack deallocation himself
        #
-       # Example :
-       # ~~~
+       # ~~~nitish
        # var foo = new HashSet[JavaString]
-       # shared_preferences.add_string_set("A key", foo)
+       # app.shared_preferences.add_string_set("A key", foo)
        # for element in foo do element.delete_local_ref
        # ~~~
        fun add_string_set(key: String, value: HashSet[JavaString]): SharedPreferences
index b4ed822..98ee444 100644 (file)
@@ -21,7 +21,7 @@
 # methods of the main thread to customize the response to a given event.
 #
 # This graph shows the path of a button click:
-# ~~~
+# ~~~raw
 #     UI Thread     #   Main thread
 #
 #       User
index 3d4daf6..6fe897a 100644 (file)
@@ -23,12 +23,14 @@ end
 extern class CppString in "C++" `{ std::string* `}
 end
 
-redef class String
-       fun to_cpp_string: CppString do return to_cstring.to_cpp_string
+redef class Text
+       # Get `self` as a `CppString`
+       fun to_cpp_string: CppString do return to_cstring.to_cpp_string(length)
 end
 
 redef class NativeString
-       fun to_cpp_string: CppString in "C++" `{
-               return new std::string(recv);
+       # Get `self` as a `CppString`
+       fun to_cpp_string(length: Int): CppString in "C++" `{
+               return new std::string(recv, length);
        `}
 end
index d46f4d1..3fd2fff 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Platform for the _emscripten_ framework
+#
+# Importing this module from your project will tell _nitg_ to compile
+# to JavaScript for the _emscripten_ framework.
 module emscripten is platform
 
 `{
@@ -21,12 +25,16 @@ module emscripten is platform
        #include <gc.h>
 `}
 
-redef class String
+redef class Text
+       # Run `self` as JavaScript code
        fun run_js do run_js_native(self.escape_to_js.to_cstring)
+
        private fun run_js_native(script: NativeString) `{ emscripten_run_script(script); `}
 
-       fun escape_to_js: String do return self.replace('\n', "\\n")
+       # Escape the content of `self` to pass to JavaScript code
+       fun escape_to_js: Text do return replace('\n', "\\n")
 
+       # Raise a JavaScript alert
        fun alert do "alert('{self.escape_to_js}')".run_js
 end
 
index 1596c1e..b8c9798 100644 (file)
@@ -75,12 +75,12 @@ interface Boxed[N: Numeric]
                        self.top >= other.bottom and other.top >= self.bottom
        end
 
-       # Create a bounding box that englobes the actual bounding box.
+       # Create a bounding box that encloses the actual bounding box.
        # `dist` is the distance between the inner boundaries and the outer boundaries.
        # ~~~
        # var p = new Point[Int](5,10)
        # var b = p.padded(3)
-       # assert b.top == 2 and b.bot = 8 and b.left == 7 and b.right == 13
+       # assert b.left == 2 and b.right == 8 and b.top == 13 and b.bottom == 7
        # ~~~
        fun padded(dist: N): Box[N] do return new Box[N].lrtb(left - dist, right + dist, top + dist, bottom - dist)
 end
index 820f608..cea53cb 100644 (file)
@@ -17,6 +17,8 @@
 # GPIO related functionnalities
 module gpio
 
+# A physical binary pin
 interface Pin
+       # Set the output of this pin
        fun write(high: Bool) is abstract
 end
index 8426097..1626437 100644 (file)
@@ -136,7 +136,7 @@ redef class HashCollection[K]
        # Count and update length of collisions for `node_at_idx`
        # Note for dynamic call-graph analysis: callers of this functions are
        # responsible of collisions.
-       private fun gt_collide(i: Int, k: K)
+       fun gt_collide(i: Int, k: K)
        do
                var c = _array[i]
                sys.gt_coll += 1
@@ -159,7 +159,7 @@ redef class HashCollection[K]
        # Count and update length of collisions for `store`
        # Note for dynamic call-graph analysis: callers of this functions are
        # responsible of collisions.
-       private fun st_collide(i: Int, n: N)
+       fun st_collide(i: Int, n: N)
        do
                var c = _array[i]
                sys.st_coll += 1
index d15ceb7..2f73fea 100644 (file)
@@ -74,8 +74,8 @@ class JsonValue
        #
        # require: `self.is_numeric`
        #
-       #     assert "1.234".to_json_value.to_numeric = 1.234
-       #     assert "1234".to_json_value.to_numeric = 1234
+       #     assert "1.234".to_json_value.to_numeric == 1.234
+       #     assert "1234".to_json_value.to_numeric == 1234
        fun to_numeric: Numeric
        do
                if is_int then return to_i
index 8012746..6063f23 100644 (file)
@@ -30,7 +30,8 @@ in "C Header" `{
 # Utility to select options to create the VM using `create_jvm`
 #
 # Usage example:
-# ~~~~
+#
+# ~~~~nitish
 # var builder = new JavaVMBuilder
 # builder.options.add "-Djava.class.path=."
 # var jvm = builder.create_jvm
index 525915c..9ff7ed0 100644 (file)
@@ -92,8 +92,9 @@ extern class NativeEventBase `{ struct event_base * `}
 
        # Create a new event_base to use with the rest of Libevent
        new `{ return event_base_new(); `}
+
+       # Has `self` been correctly initialized?
        fun is_valid: Bool do return not address_is_null
-       #fun creation_ok
 
        # Event dispatching loop
        #
@@ -154,7 +155,7 @@ class Connection
        # Write a string to the connection
        fun write(str: String)
        do
-               var res = native_buffer_event.write(str.to_cstring, str.length)
+               native_buffer_event.write(str.to_cstring, str.length)
        end
 
        # Write a file to the connection
@@ -175,6 +176,7 @@ end
 
 # A buffer event structure, strongly associated to a connection, an input buffer and an output_buffer
 extern class NativeBufferEvent `{ struct bufferevent * `}
+       # Write `length` bytes of `line`
        fun write(line: NativeString, length: Int): Int `{
                return bufferevent_write(recv, line, length);
        `}
@@ -205,6 +207,7 @@ extern class NativeEvBuffer `{ struct evbuffer * `}
        fun length: Int `{ return evbuffer_get_length(recv); `}
 end
 
+# An input buffer
 extern class InputNativeEvBuffer
        super NativeEvBuffer
 
@@ -212,6 +215,7 @@ extern class InputNativeEvBuffer
        fun drain(length: Int) `{ evbuffer_drain(recv, length); `}
 end
 
+# An output buffer
 extern class OutputNativeEvBuffer
        super NativeEvBuffer
 
@@ -270,6 +274,7 @@ end
 
 # Factory to listen on sockets and create new `Connection`
 class ConnectionFactory
+       # The `NativeEventBase` for the dispatch loop of this factory
        var event_base: NativeEventBase
 
        # On new connection, create the handler `Connection` object
index 2f675d6..3d0a0a1 100644 (file)
@@ -555,9 +555,9 @@ end
 # A Link Reference.
 # Links that are specified somewhere in the mardown document to be reused as shortcuts.
 #
-# Example:
-#
-#    [1]: http://example.com/ "Optional title"
+# ~~~raw
+# [1]: http://example.com/ "Optional title"
+# ~~~
 class LinkRef
 
        # Link href
index a72b34d..9d8a819 100644 (file)
@@ -24,7 +24,7 @@
 #
 # The input event file is made of event descriptions, one event by line.
 #
-# ~~~
+# ~~~raw
 # 10 click 10.0 20.0
 # 20 quit
 # ~~~
index 7e474b7..fad361e 100644 (file)
@@ -84,7 +84,7 @@ interface Drawable
        # Draw image by specifying the positon of each image corners
        # Corners are in counter-clockwise order stating top left
        # a is top left, b is bottom left, c is bottom right and d is top right
-       # ~~~
+       # ~~~raw
        # a-d
        # | |
        # b-c
index bd441a1..1bcc514 100644 (file)
@@ -48,13 +48,19 @@ class MultiHashMap[K: Object, V]
                self[key] = res
                return res
        end
-
-       init do end
 end
 
 # Simple way to store an `HashMap[K1, HashMap[K2, V]]`
+#
+# ~~~~
+# var hm2 = new HashMap2[Int, String, Float]
+# hm2[1, "one"] = 1.0
+# hm2[2, "two"] = 2.0
+# assert hm2[1, "one"] == 1.0
+# assert hm2[2, "not-two"] == null
+# ~~~~
 class HashMap2[K1: Object, K2: Object, V]
-       private var level1: HashMap[K1, HashMap[K2, V]] = new HashMap[K1, HashMap[K2, V]]
+       private var level1 = new HashMap[K1, HashMap[K2, V]]
 
        # Return the value associated to the keys `k1` and `k2`.
        # Return `null` if no such a value.
@@ -83,8 +89,16 @@ class HashMap2[K1: Object, K2: Object, V]
 end
 
 # Simple way to store an `HashMap[K1, HashMap[K2, HashMap[K3, V]]]`
+#
+# ~~~~
+# var hm3 = new HashMap3[Int, String, Int, Float]
+# hm3[1, "one", 11] = 1.0
+# hm3[2, "two", 22] = 2.0
+# assert hm3[1, "one", 11] == 1.0
+# assert hm3[2, "not-two", 22] == null
+# ~~~~
 class HashMap3[K1: Object, K2: Object, K3: Object, V]
-       private var level1: HashMap[K1, HashMap2[K2, K3, V]] = new HashMap[K1, HashMap2[K2, K3, V]]
+       private var level1 = new HashMap[K1, HashMap2[K2, K3, V]]
 
        # Return the value associated to the keys `k1`, `k2`, and `k3`.
        # Return `null` if no such a value.
@@ -112,6 +126,45 @@ class HashMap3[K1: Object, K2: Object, K3: Object, V]
 end
 
 # A map with a default value.
+#
+# ~~~~
+# var dm = new DefaultMap[String, Int](10)
+# assert dm["a"] == 10
+# ~~~~
+#
+# The default value is used when the key is not present.
+# And getting a default value does not register the key.
+#
+# ~~~~
+# assert dm["a"] == 10
+# assert dm.length == 0
+# assert dm.has_key("a") == false
+# ~~~~
+#
+# It also means that removed key retrieve the default value.
+#
+# ~~~~
+# dm["a"] = 2
+# assert dm["a"] == 2
+# dm.keys.remove("a")
+# assert dm["a"] == 10
+# ~~~~
+#
+# Warning: the default value is used as is, so using mutable object might
+# cause side-effects.
+#
+# ~~~~
+# var dma = new DefaultMap[String, Array[Int]](new Array[Int])
+#
+# dma["a"].add(65)
+# assert dma["a"] == [65]
+# assert dma.default == [65]
+# assert dma["c"] == [65]
+#
+# dma["b"] += [66]
+# assert dma["b"] == [65, 66]
+# assert dma.default == [65]
+# ~~~~
 class DefaultMap[K: Object, V]
        super HashMap[K, V]
 
index 20ff9af..1d8c406 100644 (file)
@@ -123,26 +123,34 @@ class MPI
                return deserialized
        end
 
+       # Send an empty buffer, only for the `tag`
        fun send_empty(dest: Rank, tag: Tag, comm: Comm): SuccessOrError
        `{
                return MPI_Send(NULL, 0, MPI_CHAR, dest, tag, comm);
        `}
 
+       # Receive an empty buffer, only for the `tag`
        fun recv_empty(dest: Rank, tag: Tag, comm: Comm): SuccessOrError
        `{
                return MPI_Recv(NULL, 0, MPI_CHAR, dest, tag, comm, MPI_STATUS_IGNORE);
        `}
 
-       fun native_send(data: NativeCArray, count: Int, data_type: DataType, dest: Rank, tag: Tag, comm: Comm): SuccessOrError
+       # Send a `NativeCArray` `buffer` with a given `count` of `data_type`
+       fun native_send(buffer: NativeCArray, count: Int, data_type: DataType, dest: Rank, tag: Tag, comm: Comm): SuccessOrError
        `{
-               return MPI_Send(data, count, data_type, dest, tag, comm);
+               return MPI_Send(buffer, count, data_type, dest, tag, comm);
        `}
 
-       fun native_recv(data: NativeCArray, count: Int, data_type: DataType, dest: Rank, tag: Tag, comm: Comm, status: Status): SuccessOrError
+       # Receive into a `NativeCArray` `buffer` with a given `count` of `data_type`
+       fun native_recv(buffer: NativeCArray, count: Int, data_type: DataType, dest: Rank, tag: Tag, comm: Comm, status: Status): SuccessOrError
        `{
-               return MPI_Recv(data, count, data_type, dest, tag, comm, status);
+               return MPI_Recv(buffer, count, data_type, dest, tag, comm, status);
        `}
 
+       # Probe for the next data to receive, store the result in `status`
+       #
+       # Note: If you encounter an error where the next receive does not correspond
+       # to the last `probe`, call this method twice to ensure a correct result.
        fun probe(source: Rank, tag: Tag, comm: Comm, status: Status): SuccessOrError
        `{
                return MPI_Probe(source, tag, comm, status);
@@ -157,8 +165,13 @@ end
 
 # An MPI communicator
 extern class Comm `{ MPI_Comm `}
+       # The _null_ communicator, targeting no processors
        new null_ `{ return MPI_COMM_NULL; `}
+
+       # The _world_ communicator, targeting all processors
        new world `{ return MPI_COMM_WORLD; `}
+
+       # The _self_ communicator, targeting this processor only
        new self_ `{ return MPI_COMM_SELF; `}
 
        # Number of processors in this communicator
@@ -278,6 +291,7 @@ end
 
 # An MPI rank within a communcator
 extern class Rank `{ int `}
+       # Special rank accepting any processor
        new any `{ return MPI_ANY_SOURCE; `}
 
        # This Rank as an `Int`
@@ -287,6 +301,7 @@ end
 
 # An MPI tag, can be defined using `Int::tag`
 extern class Tag `{ int `}
+       # Special tag accepting any tag
        new any `{ return MPI_ANY_TAG; `}
 
        # This tag as an `Int`
index 34ca522..5c42f46 100644 (file)
@@ -21,24 +21,57 @@ module ordered_tree
 #
 # Ordered tree are tree where the elements of a same parent are in a specific order
 #
-# The class can be used as it to work with generic tree.
-# The class can also be specialized to provide more specific behavior.
+# Elements of the trees are added with the `add` method that takes a parent and
+# a sub-element.
+# If the parent is `null`, then the element is considered a root.
+#
+# ~~~~
+# var t = new OrderedTree[String]
+# t.add(null, "root")
+# t.add("root", "child1")
+# t.add("root", "child2")
+# t.add("child1", "grand-child")
+# assert t.length == 4
+# ~~~~
+#
+# By default, the elements with a same parent
+# are visited in the order they are added.
+#
+# ~~~
+# assert t.to_a == ["root", "child1", "grand-child", "child2"]
+# assert t.write_to_string == """
+# root
+# |--child1
+# |  `--grand-child
+# `--child2
+# """
+# ~~~
+#
+# The `sort_with` method can be used reorder elements
+#
+# ~~~
+# t.add("root", "aaa")
+# assert t.to_a == ["root", "child1", "grand-child", "child2", "aaa"]
+# t.sort_with(alpha_comparator)
+# assert t.to_a == ["root", "aaa", "child1", "grand-child", "child2"]
+# ~~~
+#
+# This class can be used as it to work with generic trees but can also be specialized to provide more specific
+# behavior or display. It is why the internal attributes are mutable.
 class OrderedTree[E: Object]
        super Streamable
        super Collection[E]
 
-       # Sequence
+       # The roots of the tree (in sequence)
        var roots = new Array[E]
+
+       # The branches of the trees.
+       # For each element, the ordered array of its direct sub-elements.
        var sub = new HashMap[E, Array[E]]
 
-       # Add a new element `e` in the tree
+       # Add a new element `e` in the tree.
        # `p` is the parent of `e`.
        # if `p` is null, then `e` is a root element.
-       #
-       # By defauld, the elements with a same parent 
-       # are displayed in the order they are added.
-       #
-       # The `sort_with` method can be used reorder elements
        fun add(p: nullable E, e: E)
        do
                if p == null then
@@ -54,7 +87,6 @@ class OrderedTree[E: Object]
        # Write a ASCII-style tree and use the `display` method to label elements
        redef fun write_to(stream: OStream)
        do
-               var last = roots.last
                for r in roots do
                        stream.write display(r)
                        stream.write "\n"
index 31d007b..be553ad 100644 (file)
@@ -14,9 +14,8 @@
 
 # Pipelined filters and operations on iterators.
 #
-# This module enhance `Iterator`s with some methods that enable a
-# pipeline-like programing that offers the manupulation of
-# collections trough connected filters with reasonable memory constraints.
+# This module enhances `Iterator` with some methods that enable a pipeline-like programing.
+# The processing of elements in a pipeline is done trough connected filters that are implemented with reasonable memory constraints.
 module pipeline
 
 redef interface Iterator[E]
@@ -35,6 +34,8 @@ redef interface Iterator[E]
 
        # Filter: sort with a given `comparator`.
        # Important: require O(n) memory.
+       #
+       #    assert ["a", "c", "b"].iterator.sort_with(alpha_comparator).to_a  == ["a", "b", "c"]
        fun sort_with(comparator: Comparator): Iterator[E]
        do
                var a = self.to_a
index bc876c0..4008422 100644 (file)
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
-# Targets the PNaCl platform
+
+# Provides PNaCl support for Nit.
 #
 # To use this module and compile for PNaCl, you must install the
 # NaCl SDK (This file is based on Pepper 33).
 # If NACL_SDK_ROOT is not set in your PATH, you have to work in
 # 'nacl_sdk/pepper_your_pepper_version/getting_started/your_project_folder'.
-#
-# Provides PNaCl support for Nit.
 module pnacl is platform
 
 import standard
index 9549e48..e8f7e73 100644 (file)
 # Pre order sets and partial order set (ie hierarchies)
 module poset
 
-# Preorder set graph.
-# This class modelize an incremental preorder graph where new node and edges can be added (but no removal)
-# Preorder graph has two caracteristics:
+# Pre-order set graph.
+# This class models an incremental pre-order graph where new nodes and edges can be added (but not removed).
+# Pre-order graph has two characteristics:
 #  * reflexivity: an element is in relation with itself (ie `self.has(e) implies self.has_edge(e,e)`)
 #  * transitivity: `(self.has_edge(e,f) and self.has_edge(f,g)) implies self.has_edge(e,g)`
+#
+# Nodes and edges are added to the POSet.
+#
+# ~~~
+# var pos = new POSet[String]
+# pos.add_edge("A", "B") # add A->B
+# pos.add_edge("B", "C") # add B->C
+# pos.add_node("D") # add unconnected node "D"
+#
+# # A -> B -> C    D
+#
+# assert pos.has_edge("A", "B") == true  # direct
+# ~~~
+#
+# Since a poset is transitive, direct and indirect edges are considered by default.
+# Direct edges (transitive-reduction) can also be considered independently.
+#
+# ~~~
+# assert pos.has_edge("A", "C") == true  # indirect
+# assert pos.has_edge("A", "D") == false # no edge
+# assert pos.has_edge("B", "A") == false # edges are directed
+#
+# assert pos.has_direct_edge("A", "B") == true  # direct
+# assert pos.has_direct_edge("A", "C") == false # indirect
+# ~~~
+#
+# POSet are dynamic.
+# It means that the transitivity is updated while new nodes and edges are added.
+# The transitive-reduction (*direct edges*)) is also updated,
+# so adding new edges can make some direct edge to disappear.
+#
+# ~~~
+# pos.add_edge("A","D")
+# pos.add_edge("D","B")
+# pos.add_edge("A","E")
+# pos.add_edge("E","C")
+#
+# # A -> D -> B
+# # |         |
+# # v         v
+# # E ------> C
+#
+# assert pos.has_edge("D", "C") == true # new indirect edge
+# assert pos.has_edge("A", "B") == true # still an edge
+# assert pos.has_direct_edge("A", "B") == false  # but no-more a direct one
+# ~~~
+#
+# Thanks to the `[]` method, elements can be considered relatively to the poset.
+# SEE `POSetElement`
 class POSet[E: Object]
        super Collection[E]
        super Comparator
@@ -31,7 +80,7 @@ class POSet[E: Object]
        redef fun iterator do return elements.keys.iterator
 
        # All the nodes
-       private var elements: HashMap[E, POSetElement[E]] = new HashMap[E, POSetElement[E]]
+       private var elements = new HashMap[E, POSetElement[E]]
 
        redef fun has(e) do return self.elements.keys.has(e)
 
@@ -50,14 +99,15 @@ class POSet[E: Object]
        end
 
        # Return a view of `e` in the poset.
-       # This allows to asks manipulate elements in thier relation with others elements.
+       # This allows to view the elements in their relation with others elements.
        #
-       #     var poset: POSet[Something] # ...
-       #     for x in poset do
-       #         for y in poset[x].direct_greaters do
-       #             print "{x} -> {y}"
-       #         end
-       #     end
+       #     var poset = new POSet[String]
+       #     poset.add_chain(["A", "B", "D"])
+       #     poset.add_chain(["A", "C", "D"])
+       #     var a = poset["A"]
+       #     assert a.direct_greaters.has_exactly(["B", "C"])
+       #     assert a.greaters.has_exactly(["A", "B", "C", "D"])
+       #     assert a.direct_smallers.is_empty
        #
        # REQUIRE: has(e)
        fun [](e: E): POSetElement[E]
@@ -69,9 +119,18 @@ class POSet[E: Object]
        # Add an edge from `f` to `t`.
        # Because a POSet is transitive, all transitive edges are also added to the graph.
        # If the edge already exists, the this function does nothing.
+       #
+       # ~~~
+       # var pos = new POSet[String]
+       # pos.add_edge("A", "B") # add A->B
+       # assert pos.has_edge("A", "C") == false
+       # pos.add_edge("B", "C") # add B->C
+       # assert pos.has_edge("A", "C") == true
+       # ~~~
+       #
        # If a reverse edge (from `t` to `f`) already exists, a loop is created.
        #
-       # FIXME: Do somethind clever to manage loops.
+       # FIXME: Do something clever to manage loops.
        fun add_edge(f, t: E)
        do
                var fe = add_node(f)
@@ -108,8 +167,38 @@ class POSet[E: Object]
                te.dfroms.add f
        end
 
+       # Add an edge between all elements of `es` in order.
+       #
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D"])
+       # assert pos.has_direct_edge("A", "B")
+       # assert pos.has_direct_edge("B", "C")
+       # assert pos.has_direct_edge("C", "D")
+       # ~~~~
+       fun add_chain(es: SequenceRead[E])
+       do
+               if es.is_empty then return
+               var i = es.iterator
+               var e = i.item
+               i.next
+               for f in i do
+                       add_edge(e, f)
+                       e = f
+               end
+       end
+
        # Is there an edge (transitive or not) from `f` to `t`?
+       #
+       # SEE: `add_edge`
+       #
        # Since the POSet is reflexive, true is returned if `f == t`.
+       #
+       # ~~~
+       # var pos = new POSet[String]
+       # pos.add_node("A")
+       # assert pos.has_edge("A", "A") == true
+       # ~~~
        fun has_edge(f,t: E): Bool
        do
                if not elements.keys.has(f) then return false
@@ -118,6 +207,15 @@ class POSet[E: Object]
        end
 
        # Is there a direct edge from `f` to `t`?
+       #
+       # ~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C"]) # add A->B->C
+       # assert pos.has_direct_edge("A", "B") == true
+       # assert pos.has_direct_edge("A", "C") == false
+       # assert pos.has_edge("A", "C")        == true
+       # ~~~
+       #
        # Note that because of loops, the result may not be the expected one.
        fun has_direct_edge(f,t: E): Bool
        do
@@ -163,12 +261,32 @@ class POSet[E: Object]
        end
 
        # Compare two elements in an arbitrary total order.
-       # Tis function is mainly used to sort elements of the set in an arbitrary linear extension.
-       # if a<b then return -1
-       # if a>b then return 1
+       #
+       # This function is mainly used to sort elements of the set in an coherent way.
+       #
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D", "E"])
+       # pos.add_chain(["A", "X", "C", "Y", "E"])
+       # var a = ["X", "C", "E", "A", "D"]
+       # pos.sort(a)
+       # assert a == ["E", "D", "C", "X", "A"]
+       # ~~~~
+       #
+       # POSet are not necessarily total orders because some distinct elements may be incomparable (neither greater or smaller).
+       # Therefore this method relies on arbitrary linear extension.
+       # This linear extension is a lawful total order (transitive, anti-symmetric, reflexive, and total), so can be used to compare the elements.
+       #
+       # The abstract behavior of the method is thus the following:
+       #
+       # ~~~~nitish
        # if a == b then return 0
-       # else return -1 or 1
-       # The total order is stable unless a new node or a new edge is added
+       # if has_edge(b, a) then return -1
+       # if has_edge(a, b) then return 1
+       # return -1 or 1 # according to the linear extension.
+       # ~~~~
+       #
+       # Note that the linear extension is stable, unless a new node or a new edge is added.
        redef fun compare(a, b: E): Int
        do
                var ae = self.elements[a]
@@ -203,6 +321,8 @@ class POSet[E: Object]
                return res
        end
 
+       # Filter elements to return only the greatest ones
+       #
        # ~~~
        # var s = new POSet[String]
        # s.add_edge("B", "A")
@@ -213,7 +333,6 @@ class POSet[E: Object]
        # assert s.select_greatest(["A", "B", "C"]) == ["A"]
        # assert s.select_greatest(["B", "C", "D"]) == ["B", "C"]
        # ~~~
-       # Filter elements to return only the greatest ones
        fun select_greatest(elements: Collection[E]): Array[E]
        do
                var res = new Array[E]
@@ -228,6 +347,13 @@ class POSet[E: Object]
        end
 
        # Sort a sorted array of poset elements using linearization order
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D", "E"])
+       # pos.add_chain(["A", "X", "C", "Y", "E"])
+       # var a = pos.linearize(["X", "C", "E", "A", "D"])
+       # assert a == ["E", "D", "C", "X", "A"]
+       # ~~~~
        fun linearize(elements: Collection[E]): Array[E] do
                var lin = elements.to_a
                sort(lin)
@@ -240,13 +366,15 @@ end
 #
 # For instance, one common usage is to add a specific attribute for each poset a class belong.
 #
-#     class Thing
-#         var in_some_relation: POSetElement[Thing]
-#         var in_other_relation: POSetElement[Thing]
-#     end
-#     var t: Thing # ...
-#     t.in_some_relation.greaters
-#
+# ~~~nitish
+# class Thing
+#     var in_some_relation: POSetElement[Thing]
+#     var in_other_relation: POSetElement[Thing]
+# end
+# var t: Thing
+# # ...
+# t.in_some_relation.greaters
+# ~~~
 class POSetElement[E: Object]
        # The poset self belong to
        var poset: POSet[E]
@@ -265,12 +393,24 @@ class POSetElement[E: Object]
 
        # Return the set of all elements `t` that have an edge from `element` to `t`.
        # Since the POSet is reflexive, element is included in the set.
+       #
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D"])
+       # assert pos["B"].greaters.has_exactly(["B", "C", "D"])
+       # ~~~~
        fun greaters: Collection[E]
        do
                return self.tos
        end
 
        # Return the set of all elements `t` that have a direct edge from `element` to `t`.
+       #
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D"])
+       # assert pos["B"].direct_greaters.has_exactly(["C"])
+       # ~~~~
        fun direct_greaters: Collection[E]
        do
                return self.dtos
@@ -278,30 +418,67 @@ class POSetElement[E: Object]
 
        # Return the set of all elements `f` that have an edge from `f` to `element`.
        # Since the POSet is reflexive, element is included in the set.
+       #
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D"])
+       # assert pos["C"].smallers.has_exactly(["A", "B", "C"])
+       # ~~~~
        fun smallers: Collection[E]
        do
                return self.froms
        end
 
        # Return the set of all elements `f` that have an edge from `f` to `element`.
+       #
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D"])
+       # assert pos["C"].direct_smallers.has_exactly(["B"])
+       # ~~~~
        fun direct_smallers: Collection[E]
        do
                return self.dfroms
        end
 
        # Is there an edge from `element` to `t`?
+       #
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D"])
+       # assert     pos["B"] <= "D"
+       # assert     pos["B"] <= "C"
+       # assert     pos["B"] <= "B"
+       # assert not pos["B"] <= "A"
+       # ~~~~
        fun <=(t: E): Bool
        do
                return self.tos.has(t)
        end
 
        # Is `t != element` and is there an edge from `element` to `t`?
+       #
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D"])
+       # assert     pos["B"] < "D"
+       # assert     pos["B"] < "C"
+       # assert not pos["B"] < "B"
+       # assert not pos["B"] < "A"
+       # ~~~~
        fun <(t: E): Bool
        do
                return t != self.element and self.tos.has(t)
        end
 
        # The length of the shortest path to the root of the poset hierarchy
+       #
+       # ~~~~
+       # var pos = new POSet[String]
+       # pos.add_chain(["A", "B", "C", "D"])
+       # assert pos["A"].depth == 3
+       # assert pos["D"].depth == 0
+       # ~~~~
        fun depth: Int do
                if direct_greaters.is_empty then
                        return 0
index 7a5503f..f17a28e 100644 (file)
@@ -75,8 +75,11 @@ class OptionUserAndGroup
 
        redef type VALUE: nullable UserGroup
 
-       init for_dropping_privileges do init("Drop privileges to user:group or simply user", "-u", "--usergroup")
-       init(help: String, names: String...) do super(help, null, names)
+       # Create an `OptionUserAndGroup` for dropping privileges
+       init for_dropping_privileges
+       do
+               init("Drop privileges to user:group or simply user", null, ["-u", "--usergroup"])
+       end
 
        redef fun convert(str)
        do
@@ -87,8 +90,7 @@ class OptionUserAndGroup
                        return new UserGroup(words[0], words[1])
                else
                        errors.add("Option {names.join(", ")} expected parameter in the format \"user:group\" or simply \"user\".\n")
-                       abort # FIXME only for nitc, remove and replace with next line when FFI is working in nitg
-                       #return null
+                       return null
                end
        end
 end
index c736a46..eb04677 100644 (file)
@@ -19,24 +19,17 @@ import sax::sax_locator
 # can use it to make a persistent snapshot of a locator at any
 # point during a document parse:
 #
-#     module example
-#     #
-#     import sax::helpers::SAXLocatorImpl
-#     import sax::ContentHandler
-#     #
+#     import sax::helpers::sax_locator_impl
+#     import sax::content_handler
+#
 #     class Example super ContentHandler
-#      private var _locator: nullable SAXLocator = null
+#      private var locator: SAXLocator
 #      private var start_loc: nullable SAXLocator = null
-#     #
-#      fun locator=(Locator locator) do
-#              # note the locator
-#              _locator = locator
-#      end
-#     #
-#      fun start_document do
+#
+#      redef fun start_document do
 #              # save the location of the start of the document
 #              # for future use.
-#              start_loc = new SAXLocatorImpl.from(locator)
+#              start_loc = new SAXLocatorImpl.with(locator)
 #      end
 #     end
 #
index c158532..6f80e77 100644 (file)
@@ -275,9 +275,11 @@ interface XMLReader
        # document from a system identifier. It is the exact
        # equivalent of the following:
        #
-       #     var source = new InputSouce
-       #     source.system_id = system_id
-       #     parse(source)
+       # ~~~nitish
+       # var source = new InputSouce
+       # source.system_id = system_id
+       # parse(source)
+       # ~~~
        #
        # If the system identifier is a URL, it must be fully resolved
        # by the application before it is passed to the parser.
index ac5a571..b01c3e5 100644 (file)
@@ -151,8 +151,8 @@ interface View
        # This method must be implemented for each specific view.
        # A traditional way of implementation is to use a double-dispatch mechanism
        #
-       # Exemple:
        #     class MyView
+       #         super View
        #         redef fun draw_sprite(s) do s.draw_on_myview(self)
        #     end
        #     redef class Sprite
index f1044e8..f9709da 100644 (file)
@@ -47,7 +47,7 @@
 # r.handle_signal(sigint, true)
 # r.handle_signal(sigalarm, true)
 #
-# Ask system to receive a `sigalarm` signal in 1 second
+# # Ask system to receive a `sigalarm` signal in 1 second
 # set_alarm(1)
 #
 # loop
index 05cbed0..23b1ef7 100644 (file)
@@ -114,8 +114,6 @@ end
 class Statement
        private var native_statement: NativeStatement
 
-       private init(ns: NativeStatement) do self.native_statement = ns
-
        # Is this statement usable?
        var is_open = true
 
@@ -134,12 +132,11 @@ class Statement
        end
 end
 
+# A row from a `Statement`
 class StatementRow
        # Statement linked to `self`
        var statement: Statement
 
-       private init(s: Statement) do self.statement = s
-
        # Number of entries in this row
        #
        # require: `self.statement.is_open`
@@ -161,12 +158,6 @@ class StatementEntry
 
        private var index: Int
 
-       private init(s: Statement, i: Int)
-       do
-               self.statement = s
-               self.index = i
-       end
-
        # Name of the column
        #
        # require: `self.statement.is_open`
@@ -258,17 +249,15 @@ class StatementIterator
        # Statement linked to `self`
        var statement: Statement
 
-       private init(s: Statement)
+       init
        do
-               self.statement = s
-               self.item = new StatementRow(s)
-
+               self.item = new StatementRow(statement)
                self.is_ok = statement.native_statement.step.is_row
        end
 
-       redef var item: StatementRow
+       redef var item: StatementRow is noinit
 
-       redef var is_ok: Bool
+       redef var is_ok: Bool is noinit
 
        # require: `self.statement.is_open`
        redef fun next
@@ -310,12 +299,9 @@ end
 class Blob
        super Sqlite3Data
 
-       private init(pointer: Pointer, length: Int)
-       do
-               self.pointer = pointer
-               self.length = length
-       end
-
+       # Pointer to the beginning of the blob
        var pointer: Pointer
+
+       # Size of the blob
        var length: Int
 end
index fa16295..3b7f908 100644 (file)
@@ -33,25 +33,29 @@ import kernel
 # Subclasses often provide a more efficient implementation.
 #
 # Because of the `iterator` method, Collections instances can use
-# the `for` control structure:
+# the `for` control structure.
 #
-#         var x: Collection[U]
-#         # ...
-#         for u in x do
-#             # u is a U
-#             # ...
-#         end
+# ~~~nitish
+# var x: Collection[U]
+# # ...
+# for u in x do
+#     # u is a U
+#     # ...
+# end
+# ~~~
 #
-# that is equivalent with
+# that is equivalent with the following:
 #
-#         var x: Collection[U]
-#         # ...
-#         var i = x.iterator
-#         while i.is_ok do
-#             var u = i.item # u is a U
-#             # ...
-#             i.next
-#         end
+# ~~~nitish
+# var x: Collection[U]
+# # ...
+# var i = x.iterator
+#     while i.is_ok do
+#     var u = i.item # u is a U
+#     # ...
+#     i.next
+# end
+# ~~~
 interface Collection[E]
        # Get a new iterator on the collection.
        fun iterator: Iterator[E] is abstract
index 558d9eb..e17d2cf 100644 (file)
@@ -1405,7 +1405,7 @@ abstract class Buffer
        #
        # SEE: `Char::is_letter` for the definition of a letter.
        #
-       #    var b = new FlatBuffer.from("jAVAsCriPt")"
+       #    var b = new FlatBuffer.from("jAVAsCriPt")
        #    b.capitalize
        #    assert b == "Javascript"
        #    b = new FlatBuffer.from("i am root")
index b7a74ce..34edd00 100644 (file)
@@ -47,6 +47,7 @@ extern class UnicodeChar `{ UTF8Char* `}
        #
        # As per the specification :
        #
+       # ~~~raw
        #  Length  |        UTF-8 octet sequence
        #          |              (binary)
        # ---------+-------------------------------------------------
@@ -54,6 +55,7 @@ extern class UnicodeChar `{ UTF8Char* `}
        #  2       | 110xxxxx 10xxxxxx
        #  3       | 1110xxxx 10xxxxxx 10xxxxxx
        #  4       | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+       # ~~~
        private fun len: Int `{
                char* ns = recv->ns;
                int pos = recv->pos;
index db51f0a..547cbf7 100644 (file)
@@ -53,6 +53,7 @@ extern class UnicodeChar `{ uint32_t* `}
        #
        # As per the specification :
        #
+       # ~~~raw
        #  Length  |        UTF-8 octet sequence
        #          |              (binary)
        # ---------+-------------------------------------------------
@@ -60,6 +61,7 @@ extern class UnicodeChar `{ uint32_t* `}
        #  2       | 110xxxxx 10xxxxxx
        #  3       | 1110xxxx 10xxxxxx 10xxxxxx
        #  4       | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+       # ~~~
        fun len: Int `{
                uint32_t s = *recv;
                if(s <= 127) {return 1;}
index 0b1c9e4..2796a3c 100644 (file)
@@ -47,16 +47,18 @@ import template
 #
 # In external file `example.tpl`:
 #
-#    <!DOCTYPE html>
-#    <html lang="en">
-#     <head>
-#      <title>%TITLE%</title>
-#     </head>
-#     <body>
-#      <h1>%TITLE%</h1>
-#      <p>%ARTICLE%</p>
-#     </body>
-#    </html>
+# ~~~html
+# <!DOCTYPE html>
+# <html lang="en">
+#  <head>
+#   <title>%TITLE%</title>
+#  </head>
+#  <body>
+#   <h1>%TITLE%</h1>
+#   <p>%ARTICLE%</p>
+#  </body>
+# </html>
+# ~~~
 #
 # Loading the template file using `TemplateString`:
 #
index 4c647b3..feb9671 100644 (file)
@@ -244,11 +244,13 @@ class BinTreeMap[K: Comparable, E]
 
        # Perform left rotation on `node`
        #
+       # ~~~raw
        #     N             Y
        #    / \     >     / \
        #   a   Y         N   c
        #      / \   <   / \
        #     b   c     a   b
+       # ~~~
        #
        protected fun rotate_left(node: N) do
                var y = node.right
@@ -270,11 +272,13 @@ class BinTreeMap[K: Comparable, E]
 
        # Perform right rotation on `node`
        #
+       # ~~~raw
        #     N             Y
        #    / \     >     / \
        #   a   Y         N   c
        #      / \   <   / \
        #     b   c     a   b
+       # ~~~
        #
        protected fun rotate_right(node: N) do
                var y = node.left
index e1fe413..51ddfc0 100644 (file)
@@ -32,17 +32,17 @@ import bintree
 
 # Red-Black Tree Map
 # Properties of a Red-Black tree map:
-#  * every node is either red or black
-#  * root is black
-#  * every leaf (null) is black
-#  * if a node is red, then both its children are black
-#  * for each node, all simple path from the node to descendant
-#    leaves contain the same number of black nodes
+# * every node is either red or black
+# * root is black
+# * every leaf (null) is black
+# * if a node is red, then both its children are black
+# * for each node, all simple path from the node to descendant
+#   leaves contain the same number of black nodes
 #
 # Operations:
-#  * search average O(lg n) worst O(lg n)
-#  * insert average O(lg n) worst O(lg n)
-#  * delete average O(lg n) worst O(lg n)
+# * search average O(lg n) worst O(lg n)
+# * insert average O(lg n) worst O(lg n)
+# * delete average O(lg n) worst O(lg n)
 class RBTreeMap[K: Comparable, E]
        super BinTreeMap[K, E]
 
index 4737fa9..4f45562 100644 (file)
@@ -25,8 +25,8 @@ They contain a list of test methods called TestCase.
 
 ## Working with `DocUnits`
 
-With DocUnits, executable code can be placed in comments of modules, classes and properties.
-The execution can be verified using `assert`
+DocUnits are blocks of executable code placed in comments of modules, classes and properties.
+The execution can be verified using `assert`.
 
 Example with a class:
 
@@ -49,6 +49,59 @@ To test a method you have to instantiate its class:
         fun baz(a, b: Int) do return a + b
     end
 
+In a single piece of documentation, each docunit is considered a part of a single module, thus regrouped when
+tested.
+Therefore, it is possible (and recommended) to split docunits in small parts if it make the explanation easier.
+
+~~~~
+# Some example of grouped docunits
+#
+# Declare and initialize a variable `a`.
+#
+#     var a = 1
+#
+# So the value of `a` can be used
+#
+#     assert a == 1
+#
+# even in complex operations
+#
+#     assert a + 1 == 2
+fun foo do end
+~~~~
+
+Sometime, some blocks of code has to be included in documentation but not considered by `nitunit`.
+Those blocks are distinguished by their tagged fences (untagged fences or fences tagged `nit` are considered to be docunits).
+
+~~~~
+# Some ASCII drawing
+#
+# ~~~~raw
+#   @<
+# <__)
+# ~~~~
+fun foo do end
+~~~~
+
+The special fence-tag `nitish` could also be used to indicate pseudo-nit that will be ignored by nitunit but highlighted by nitdoc.
+Such `nitish` piece of code can be used to enclose examples that cannot compile or that one do not want to be automatically executed.
+
+~~~~
+# Some pseudo-nit
+#
+# ~~~~nitish
+# var a: Int = someting
+# # ...
+# if a == 1 then something else something-else
+# ~~~~
+#
+# Some code to not try to execute automatically
+#
+# ~~~~nitish
+# system("rm -rf /")
+# ~~~~
+~~~~
+
 The `nitunit` command is used to test Nit files:
 
     $ nitunit foo.nit
index 620bf49..8aa0295 100644 (file)
@@ -134,11 +134,13 @@ redef class AExpr
        # To create the new node `n`, we need to attach the child to it.
        # But, to put `n` where `c` was in `p`, the place has to be remembered.
        #
-       #     var p: AExpr
-       #     var c = p.c
-       #     var h = c.detach_with_placeholder
-       #     var n = astbuilder.make_XXX(c)
-       #     h.replace_with(n)
+       # ~~~nitish
+       # var p: AExpr
+       # var c = p.c
+       # var h = c.detach_with_placeholder
+       # var n = astbuilder.make_XXX(c)
+       # h.replace_with(n)
+       # ~~~
        fun detach_with_placeholder: AExpr
        do
                var h = new APlaceholderExpr.make
index bf8dc30..b2f4837 100644 (file)
@@ -124,6 +124,8 @@ end
 # Two elements from a POSet cannot have the same color if they share common subelements
 #
 # Example:
+#
+# ~~~raw
 #       A
 #     / | \
 #    /  |  \
@@ -134,22 +136,26 @@ end
 #   E   F   G
 #   |
 #   H
+# ~~~
+#
 # Conflicts:
-#   A: {B, C, D, E, F, G, H}
-#   B: {A, C, E, H}
-#   C: {A, E, H, F}
-#   D: {A, G}
-#   E: {A, B, C, H}
-#   F: {A, C}
-#   G: {A, D}
-#   H: {A, B, C, E}
+#
+# * A: {B, C, D, E, F, G, H}
+# * B: {A, C, E, H}
+# * C: {A, E, H, F}
+# * D: {A, G}
+# * E: {A, B, C, H}
+# * F: {A, C}
+# * G: {A, D}
+# * H: {A, B, C, E}
+#
 # Possible colors:
-#   A:0, B:1, C: 2, D: 1, E: 3, F:3, G:2, H:4
 #
-# see:
-#      Ducournau, R. (2011).
-#      Coloring, a versatile technique for implementing object-oriented languages.
-#      Software: Practice and Experience, 41(6), 627–659.
+# * A:0, B:1, C: 2, D: 1, E: 3, F:3, G:2, H:4
+#
+# see: Ducournau, R. (2011).
+# Coloring, a versatile technique for implementing object-oriented languages.
+# Software: Practice and Experience, 41(6), 627–659.
 class POSetColorer[E: Object]
 
        # Is the poset already colored?
index 7df46fe..08a776e 100644 (file)
@@ -30,6 +30,9 @@ private class Doc2Mdwn
        # Count empty lines between code blocks
        var empty_lines = 0
 
+       # Optional tag for a fence
+       var fence_tag = ""
+
        fun work(mdoc: MDoc): HTMLTag
        do
                var root = new HTMLTag("div")
@@ -77,6 +80,7 @@ private class Doc2Mdwn
                                empty_lines = 0
                                # to allows 4 spaces including the one that follows the #
                                curblock.add(text)
+                               fence_tag = ""
                                continue
                        end
 
@@ -88,6 +92,8 @@ private class Doc2Mdwn
                                var l = 3
                                while l < text.length and text.chars[l] == '~' do l += 1
                                in_fence = text.substring(0, l)
+                               while l < text.length and (text.chars[l] == '.' or text.chars[l] == ' ') do l += 1
+                               fence_tag = text.substring_from(l)
                                continue
                        end
 
@@ -187,7 +193,7 @@ private class Doc2Mdwn
                                # Code part
                                var n2 = new HTMLTag("code")
                                n.add(n2)
-                               process_code(n2, part)
+                               process_code(n2, part, null)
                        end
                        is_text = not is_text
                end
@@ -222,13 +228,20 @@ private class Doc2Mdwn
                        # add the node
                        var n = new HTMLTag("pre")
                        root.add(n)
-                       process_code(n, btext.to_s)
+                       process_code(n, btext.to_s, fence_tag)
                        curblock.clear
                end
        end
 
-       fun process_code(n: HTMLTag, text: String)
+       fun process_code(n: HTMLTag, text: String, tag: nullable String)
        do
+               # Do not try to highlight non-nit code.
+               if tag != null and tag != "" and tag != "nit" and tag != "nitish" then
+                       n.append text
+                       n.add_class("rawcode")
+                       return
+               end
+
                # Try to parse it
                var ast = toolcontext.parse_something(text)
 
index 6fba61a..8ae08b9 100644 (file)
@@ -68,7 +68,7 @@ redef class AExternCodeBlock
 end
 
 redef class Location
-       fun as_line_pragma: String do return "#line {line_start} \"{file.filename}\"\n"
+       fun as_line_pragma: String do return "#line {line_start-1} \"{file.filename}\"\n"
 end
 
 redef class MModule
index f5582d8..9be5738 100644 (file)
@@ -732,6 +732,7 @@ abstract class MType
        # types to their bounds.
        #
        # Example
+       #
        #     class A end
        #     class B super A end
        #     class X end
@@ -743,6 +744,7 @@ abstract class MType
        #       super G[B]
        #       redef type U: Y
        #     end
+       #
        # Map[T,U]  anchor_to  H  #->  Map[B,Y]
        #
        # Explanation of the example:
@@ -771,9 +773,13 @@ abstract class MType
        # In Nit, for each super-class of a type, there is a equivalent super-type.
        #
        # Example:
+       #
+       # ~~~nitish
        #     class G[T, U] end
        #     class H[V] super G[V, Bool] end
+       #
        # H[Int]  supertype_to  G  #->  G[Int, Bool]
+       # ~~~
        #
        # REQUIRE: `super_mclass` is a super-class of `self`
        # REQUIRE: `self.need_anchor implies anchor != null and self.can_resolve_for(anchor, null, mmodule)`
@@ -807,9 +813,11 @@ abstract class MType
        #
        # ## Example 1
        #
-       #     class G[E] end
-       #     class H[F] super G[F] end
-       #     class X[Z] end
+       # ~~~
+       # class G[E] end
+       # class H[F] super G[F] end
+       # class X[Z] end
+       # ~~~
        #
        #  * Array[E].resolve_for(H[Int])  #->  Array[Int]
        #  * Array[E].resolve_for(G[Z], X[Int]) #->  Array[Z]
@@ -827,30 +835,34 @@ abstract class MType
        #
        # ## Example 2
        #
-       #     class A[E]
-       #         fun foo(e:E):E is abstract
-       #     end
-       #     class B super A[Int] end
+       # ~~~
+       # class A[E]
+       #     fun foo(e:E):E is abstract
+       # end
+       # class B super A[Int] end
+       # ~~~
        #
        # The signature on foo is (e: E): E
        # If we resolve the signature for B, we get (e:Int):Int
        #
        # ## Example 3
        #
-       #     class A[E]
-       #         fun foo(e:E) is abstract
-       #     end
-       #     class B[F]
-       #         var a: A[Array[F]]
-       #         fun bar do a.foo(x) # <- x is here
-       #     end
+       # ~~~nitish
+       # class A[E]
+       #     fun foo(e:E):E is abstract
+       # end
+       # class C[F]
+       #     var a: A[Array[F]]
+       #     fun bar do a.foo(x) # <- x is here
+       # end
+       # ~~~
        #
        # The first question is: is foo available on `a`?
        #
        # The static type of a is `A[Array[F]]`, that is an open type.
        # in order to find a method `foo`, whe must look at a resolved type.
        #
-       #   A[Array[F]].anchor_to(B[nullable Object])  #->  A[Array[nullable Object]]
+       #   A[Array[F]].anchor_to(C[nullable Object])  #->  A[Array[nullable Object]]
        #
        # the method `foo` exists in `A[Array[nullable Object]]`, therefore `foo` exists for `a`.
        #
@@ -858,7 +870,7 @@ abstract class MType
        #
        # the signature of `foo` is `foo(e:E)`, thus we must resolve the type E
        #
-       #   E.resolve_for(A[Array[F]],B[nullable Object])  #->  Array[F]
+       #   E.resolve_for(A[Array[F]],C[nullable Object])  #->  Array[F]
        #
        # The resolution can be done because `E` make sense for the class A (see `can_resolve_for`)
        #
@@ -880,11 +892,15 @@ abstract class MType
        #     class B[F]
        #     end
        #
-       #  * E.can_resolve_for(A[Int])  #->  true, E make sense in A
-       #  * E.can_resolve_for(B[Int])  #->  false, E does not make sense in B
-       #  * B[E].can_resolve_for(A[F], B[Object])  #->  true,
-       #    B[E] is a red hearing only the E is important,
-       #    E make sense in A
+       # ~~~nitish
+       # E.can_resolve_for(A[Int])  #->  true, E make sense in A
+       #
+       # E.can_resolve_for(B[Int])  #->  false, E does not make sense in B
+       #
+       # B[E].can_resolve_for(A[F], B[Object])  #->  true,
+       # # B[E] is a red hearing only the E is important,
+       # # E make sense in A
+       # ~~~
        #
        # REQUIRE: `anchor != null implies not anchor.need_anchor`
        # REQUIRE: `mtype.need_anchor implies anchor != null and mtype.can_resolve_for(anchor, null, mmodule)`
@@ -1254,12 +1270,14 @@ end
 # directly to the parameter types of the super-classes.
 #
 # Example:
+#
 #     class A[E]
 #         fun e: E is abstract
 #     end
 #     class B[F]
 #         super A[Array[F]]
 #     end
+#
 # In the class definition B[F], `F` is a valid type but `E` is not.
 # However, `self.e` is a valid method call, and the signature of `e` is
 # declared `e: E`.
index 9297793..7af444d 100644 (file)
@@ -535,7 +535,9 @@ end
 #
 # Comparison is made with the formula:
 #
-#     a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_ran
+# ~~~nitish
+# a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_ran
+# ~~~
 #
 # If both `a` and `b` have the same ranking,
 # ordering is based on lexicographic comparison of `a.name` and `b.name`
index a566f31..eebd408 100644 (file)
 #
 # For example, if the source code contains:
 #
+# ~~~nitish
 #     fun foo(a: A, b: B, c: C)
+# ~~~
 #
 # The `MSignature` node will contain a property
 # `parameter_names = ["a", "b", "c"]` so the MSignature can be reconstructed
index 32294c2..141ef1b 100644 (file)
 # `Licence comments` are attached to the top of the file
 # no blank line before, one after.
 #
-#     # This is a licence comment
+# ~~~nitish
+# # This is a licence comment
 #
-#     # Documentation for module `foo`
-#     module foo
+# # Documentation for module `foo`
+# module foo
+# ~~~
 #
 # `ADoc` are documentation comments attached to a `AModule`, `AClassdef`, `APropdef`.
 #
 # They are printed before the definition with a blank line before and no after
 # at the same indentation level than the definition.
 #
-#     # Documentation for module `foo`
-#     module foo
+# ~~~nitish
+# # Documentation for module `foo`
+# module foo
 #
-#     # Documentation for class `Bar`
-#     class Bar
-#          # Documentation for method `baz`
-#          fun baz do end
-#     end
+# # Documentation for class `Bar`
+# class Bar
+#      # Documentation for method `baz`
+#      fun baz do end
+# end
+# ~~~
 #
 # `Block comments` are comments composed of one or more line rattached to nothing.
 # They are displayed with one blank line before and after at current indent level.
 #
-#     <blank>
-#     # block
-#     # comment
-#     <blank>
+# ~~~nitish
+# <blank>
+# # block
+# # comment
+# <blank>
+# ~~~
 #
 # `Attached comments` are comments attached to a production.
 # They are printed as this.
 #
-#     fun foo do # attached comment
-#     end
+# ~~~nitish
+# fun foo do # attached comment
+# end
+# ~~~
 #
 # `nitpretty` automatically remove multiple blanks between comments:
 #
-#     # Licence
-#     # ...
-#     <blank>
-#     # Block comment
+# ~~~nitish
+# # Licence
+# # ...
+# <blank>
+# # Block comment
+# ~~~
 #
 # ### Inlining
 #
 # * There is a blank between each class definition
 # * There is no blank line at the end of the module
 #
-#     # Documentation for module `foo`
-#     module foo
+# ~~~nitish
+# # Documentation for module `foo`
+# module foo
 #
-#     import a
-#     # import b
-#     import c
+# import a
+# # import b
+# import c
 #
-#     # Documentation for class `Bar`
-#     class Bar end
+# # Documentation for class `Bar`
+# class Bar end
 #
-#     class Baz end # not a `ADoc` comment
+# class Baz end # not a `ADoc` comment
+# ~~~
 #
 #
 # ### Classes
 # * There is a blank between each block definition
 # * There no blank line at the end of the class definition
 #
-#     # Documentation for class `Bar`
-#     class Bar end
+# ~~~nitish
+# # Documentation for class `Bar`
+# class Bar end
 #
-#     class Baz
-#          super Bar
+# class Baz
+#     super Bar
 #
-#          fun a is abstract
-#          private fun b do end
+#      fun a is abstract
+#      private fun b do end
 #
-#          fun c do
-#               # ...
-#          end
-#     end
+#      fun c do
+#           # ...
+#      end
+# end
+# ~~~
 #
-# Generic types have no espace after or before brackets and are separated by a comma and a space:
+# Generic types have no space after or before brackets and are separated by a comma and a space:
 #
-#     class A[E: Type1, F: Type1] do end
+# ~~~nitish
+# class A[E: Type1, F: Type1] end
+# ~~~
 #
 # ### Blocks
 #
 # * Inlined productions have no blank lines between them
 # * Block productions have a blank before and after
 #
-#     var a = 10
-#     var b = 0
+# ~~~nitish
+# var a = 10
+# var b = 0
 #
-#     if a > b then
-#          # is positive
-#          print "positive"
-#     end
+# if a > b then
+#      # is positive
+#      print "positive"
+# end
 #
-#     print "end"
+# print "end"
+# ~~~
 #
 # ### Calls and Binary Ops
 #
 # Arguments are always printed separated with a comma and a space:
 #
-#     foo(a, b, c)
+# ~~~nitish
+# foo(a, b, c)
+# ~~~
 #
 # Binary ops are always printed wrapped with spaces:
 #
-#     var c = 1 + 2
+# ~~~nitish
+# var c = 1 + 2
+# ~~~
 #
 # Calls and binary ops can be splitted to fit the `max-size` constraint.
 # Breaking priority is given to arguments declaration after the comma.
 #
-#     return foo("aaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbb",
-#        "cccccccccccccccccccccccccc")
+# ~~~nitish
+# return foo("aaaaaaaaaaaaaaaaaaaaaaaaaa", "bbbbbbbbbbbbbbbbbbbbbbbbbbb",
+#     "cccccccccccccccccccccccccc")
+# ~~~
 #
 # Binary ops can also be broken to fit the `max-size` limit:
 #
-#     return "aaaaaaaaaaaaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbbbbbbbbbbbbb" +
-#        "cccccccccccccccccccccccccc"
-#
+# ~~~nitish
+# return "aaaaaaaaaaaaaaaaaaaaaaaaaa" + "bbbbbbbbbbbbbbbbbbbbbbbbbbb" +
+#     "cccccccccccccccccccccccccc"
+# ~~~
 module nitpretty
 
 import template
index e612902..27e6fac 100644 (file)
@@ -34,32 +34,31 @@ class NitUnitExecutor
        # All blocks of code from a same `ADoc`
        var blocks = new Array[Array[String]]
 
-       redef fun process_code(n: HTMLTag, text: String)
+       # All failures from a same `ADoc`
+       var failures = new Array[String]
+
+       redef fun process_code(n: HTMLTag, text: String, tag: nullable String)
        do
                # Skip non-blocks
                if n.tag != "pre" then return
 
+               # Skip strict non-nit
+               if tag != null and tag != "nit" and tag != "" then
+                       return
+               end
+
                # Try to parse it
                var ast = toolcontext.parse_something(text)
 
+               # Skip pure comments
+               if ast isa TComment then return
+
                # We want executable code
                if not (ast isa AModule or ast isa ABlockExpr or ast isa AExpr) then
-                       if ndoc != null and n.tag == "pre" and toolcontext.opt_warn.value > 1 then
-                               toolcontext.warning(ndoc.location, "invalid-block", "Warning: There is a block of code that is not valid Nit, thus not considered a nitunit")
-                               if ast isa AError then toolcontext.warning(ast.location, "syntax-error", ast.message)
-                               ndoc = null # To avoid multiple warning in the same node
-                       end
-                       return
-               end
-
-               # Search `assert` in the AST
-               var v = new SearchAssertVisitor
-               v.enter_visit(ast)
-               if not v.foundit then
-                       if ndoc != null and n.tag == "pre" and toolcontext.opt_warn.value > 1 then
-                               toolcontext.warning(ndoc.location, "invalid-block", "Warning: There is a block of Nit code without `assert`, thus not considered a nitunit")
-                               ndoc = null # To avoid multiple warning in the same node
-                       end
+                       var message = ""
+                       if ast isa AError then message = " At {ast.location}: {ast.message}."
+                       toolcontext.warning(ndoc.location, "invalid-block", "Error: There is a block of code that is not valid Nit, thus not considered a nitunit. To suppress this warning, enclose the block with a fence tagged `nitish` or `raw` (see `man nitdoc`).{message}")
+                       failures.add("{ndoc.location}: Invalid block of code.{message}")
                        return
                end
 
@@ -84,12 +83,24 @@ class NitUnitExecutor
        fun extract(ndoc: ADoc, tc: HTMLTag)
        do
                blocks.clear
+               failures.clear
 
                self.ndoc = ndoc
 
                work(ndoc.to_mdoc)
+
                toolcontext.check_errors
 
+               if not failures.is_empty then
+                       for msg in failures do
+                               var ne = new HTMLTag("failure")
+                               ne.attr("message", msg)
+                               tc.add ne
+                               toolcontext.modelbuilder.failed_entities += 1
+                       end
+                       if blocks.is_empty then testsuite.add(tc)
+               end
+
                if blocks.is_empty then return
 
                for block in blocks do test_block(ndoc, tc, block)
index 1a3006d..0f1b117 100644 (file)
@@ -383,13 +383,13 @@ redef class ModelBuilder
                        test_file = "{include_dir}/{test_file}"
                end
                if not test_file.file_exists then
-                       toolcontext.info("Skip test for {mmodule}, no file {test_file} found", 1)
+                       toolcontext.info("Skip test for {mmodule}, no file {test_file} found", 2)
                        return ts
                end
                var tester = new NitUnitTester(self)
                var res = tester.test_module_unit(test_file)
                if res == null then
-                       toolcontext.info("Skip test for {mmodule}, no test suite found", 1)
+                       toolcontext.info("Skip test for {mmodule}, no test suite found", 2)
                        return ts
                end
                return res.to_xml
index 2212380..07acefb 100644 (file)
@@ -272,10 +272,12 @@ end
 redef class AArrayExpr
        # `[x,y]` is replaced with
        #
-       #     var t = new Array[X].with_capacity(2)
-       #     t.add(x)
-       #     t.add(y)
-       #     t
+       # ~~~nitish
+       # var t = new Array[X].with_capacity(2)
+       # t.add(x)
+       # t.add(y)
+       # t
+       # ~~~
        redef fun accept_transform_visitor(v)
        do
                var nblock = v.builder.make_block
@@ -323,11 +325,15 @@ end
 redef class ASendReassignFormExpr
        # `x.foo(y)+=z` is replaced with
        #
-       #     x.foo(y) = x.foo(y) + z
+       # ~~~nitish
+       # x.foo(y) = x.foo(y) + z
+       # ~~~
        #
        # witch is, in reality:
        #
-       #     x."foo="(y, x.foo(y)."+"(z))
+       # ~~~nitish
+       # x."foo="(y, x.foo(y)."+"(z))
+       # ~~~
        redef fun accept_transform_visitor(v)
        do
                var nblock = v.builder.make_block
index 9e9c778..75868c6 100644 (file)
@@ -242,11 +242,11 @@ class VirtualMachine super NaiveInterpreter
        end
 
        # Return the attribute value in `instance` with a sequence of perfect_hashing
-       #     `instance` is the attributes array of the receiver
-       #     `vtable` is the pointer to the virtual table of the class (of the receiver)
-       #     `mask` is the perfect hashing mask of the class
-       #     `id` is the identifier of the class
-       #     `offset` is the relative offset of this attribute
+       # * `instance` is the attributes array of the receiver
+       # * `vtable` is the pointer to the virtual table of the class (of the receiver)
+       # * `mask` is the perfect hashing mask of the class
+       # * `id` is the identifier of the class
+       # * `offset` is the relative offset of this attribute
        private fun read_attribute_ph(instance: Pointer, vtable: Pointer, mask: Int, id: Int, offset: Int): Instance `{
                // Perfect hashing position
                int hv = mask & id;
@@ -273,12 +273,12 @@ class VirtualMachine super NaiveInterpreter
        end
 
        # Replace the value of an attribute in an instance
-       #     `instance` is the attributes array of the receiver
-       #     `vtable` is the pointer to the virtual table of the class (of the receiver)
-       #     `mask` is the perfect hashing mask of the class
-       #     `id` is the identifier of the class
-       #     `offset` is the relative offset of this attribute
-       #     `value` is the new value for this attribute
+       # * `instance` is the attributes array of the receiver
+       # * `vtable` is the pointer to the virtual table of the class (of the receiver)
+       # * `mask` is the perfect hashing mask of the class
+       # * `id` is the identifier of the class
+       # * `offset` is the relative offset of this attribute
+       # * `value` is the new value for this attribute
        private fun write_attribute_ph(instance: Pointer, vtable: Pointer, mask: Int, id: Int, offset: Int, value: Instance) `{
                // Perfect hashing position
                int hv = mask & id;
@@ -378,11 +378,11 @@ redef class MClass
        end
 
        # Allocate a single vtable
-       #     `ids : Array of superclasses identifiers
-       #     `nb_methods : Array which contain the number of introduced methods for each class in ids
-       #     `nb_attributes : Array which contain the number of introduced attributes for each class in ids
-       #     `offset_attributes : Offset from the beginning of the table of the group of attributes
-       #     `offset_methods : Offset from the beginning of the table of the group of methods
+       # * `ids : Array of superclasses identifiers
+       # * `nb_methods : Array which contain the number of introduced methods for each class in ids
+       # * `nb_attributes : Array which contain the number of introduced attributes for each class in ids
+       # * `offset_attributes : Offset from the beginning of the table of the group of attributes
+       # * `offset_methods : Offset from the beginning of the table of the group of methods
        private fun allocate_vtable(v: VirtualMachine, ids: Array[Int], nb_methods: Array[Int], nb_attributes: Array[Int],
                        offset_attributes: Int, offset_methods: Int)
        do
@@ -437,8 +437,8 @@ redef class MClass
        end
 
        # Fill the vtable with methods of `self` class
-       #     `v` : Current instance of the VirtualMachine
-       #     `table` : the table of self class, will be filled with its methods
+       # * `v` : Current instance of the VirtualMachine
+       # * `table` : the table of self class, will be filled with its methods
        private fun fill_vtable(v:VirtualMachine, table: VTable, cl: MClass)
        do
                var methods = new Array[MMethodDef]
@@ -456,8 +456,8 @@ redef class MClass
 
        # Computes delta for each class
        # A delta represents the offset for this group of attributes in the object
-       #     `nb_attributes` : number of attributes for each class (classes are linearized from Object to current)
-       #     return deltas for each class
+       # *`nb_attributes` : number of attributes for each class (classes are linearized from Object to current)
+       # * return deltas for each class
        private fun calculate_delta(nb_attributes: Array[Int]): Array[Int]
        do
                var deltas = new Array[Int]
@@ -491,8 +491,8 @@ redef class MClass
        end
 
        # A kind of Depth-First-Search for superclasses ordering
-       #     `v` : the current executed instance of VirtualMachine
-       #     `res` : Result Array, ie current superclasses ordering
+       # *`v` : the current executed instance of VirtualMachine
+       # * `res` : Result Array, ie current superclasses ordering
        private fun dfs(v: VirtualMachine, res: Array[MClass]): Array[MClass]
        do
                # Add this class at the beginning
@@ -548,8 +548,8 @@ redef class MClass
        end
 
        # Update positions of self class in `parent`
-       #     `attributes_offset`: absolute offset of introduced attributes
-       #     `methods_offset`: absolute offset of introduced methods
+       # * `attributes_offset`: absolute offset of introduced attributes
+       # * `methods_offset`: absolute offset of introduced methods
        private fun update_positions(attributes_offsets: Int, methods_offset:Int, parent: MClass)
        do
                parent.positions_attributes[self] = attributes_offsets
@@ -682,10 +682,10 @@ class MemoryManager
        `}
 
        # Put implementation of methods of a class in `vtable`
-       # `vtable` : Pointer to the C-virtual table
-       # `mask` : perfect-hashing mask of the class corresponding to the vtable
-       # `id` : id of the target class
-       # `methods` : array of MMethodDef of the target class
+       # * `vtable` : Pointer to the C-virtual table
+       # * `mask` : perfect-hashing mask of the class corresponding to the vtable
+       # * `id` : id of the target class
+       # * `methods` : array of MMethodDef of the target class
        fun put_methods(vtable: Pointer, mask: Int, id: Int, methods: Array[MMethodDef])
                import Array[MMethodDef].length, Array[MMethodDef].[] `{
 
index 1fec913..bf8ea1b 100644 (file)
@@ -12,7 +12,8 @@ nitg_args3
 nitg_args5
 nitg_args6
 nitg_args8
-test_markdown_args1
+nitunit_args
+test_docdown_args
 pep8analysis
 emscripten
 nitserial_args
index 70d5027..f93e9d7 100644 (file)
@@ -2,3 +2,4 @@ test_nitunit.nit --no-color -o $WRITE
 test_nitunit.nit --gen-suite --only-show
 test_nitunit.nit --gen-suite --only-show --private
 test_nitunit2.nit -o $WRITE
+test_doc2.nit --no-color -o $WRITE
diff --git a/tests/sav/nitunit_args5.res b/tests/sav/nitunit_args5.res
new file mode 100644 (file)
index 0000000..7019ad0
--- /dev/null
@@ -0,0 +1,11 @@
+DocUnits:
+DocUnits Success
+Entities: 6; Documented ones: 5; With nitunits: 3; Failures: 0
+
+TestSuites:
+No test cases found
+Class suites: 0; Test Cases: 0; Failures: 0
+<testsuites><testsuite package="test_doc2"><testcase classname="nitunit.test_doc2.standard::kernel::Object" name="test_doc2::Object::foo1"><system-err></system-err><system-out>assert true # tested
+</system-out></testcase><testcase classname="nitunit.test_doc2.standard::kernel::Object" name="test_doc2::Object::foo2"><system-err></system-err><system-out>assert true # tested
+</system-out></testcase><testcase classname="nitunit.test_doc2.standard::kernel::Object" name="test_doc2::Object::foo3"><system-err></system-err><system-out>assert true # tested
+</system-out></testcase></testsuite><testsuite></testsuite></testsuites>
\ No newline at end of file
index 23ae886..d3ab2e0 100644 (file)
@@ -22,9 +22,9 @@ border-color: red;
 h5 {font-weight:bold;}
 .nitcode a { color: inherit; cursor:pointer; }
 .nitcode .popupable:hover { text-decoration: underline; cursor:help; } /* underline titles */
-pre.nitcode .foldable { display: block } /* for block productions*/
-pre.nitcode .line{ display: block } /* for lines */
-pre.nitcode .line:hover{ background-color: #FFFFE0; } /* current line */
+.nitcode .foldable { display: block } /* for block productions*/
+.nitcode .line{ display: block } /* for lines */
+.nitcode .line:hover{ background-color: #FFFFE0; } /* current line */
 .nitcode :target { background-color: #FFF3C2 } /* target highlight*/
 /* lexical raw tokens. independent of usage or semantic: */
 .nitcode .nc_c { color: gray; font-style: italic; } /* comment */
diff --git a/tests/sav/test_docdown_args2.res b/tests/sav/test_docdown_args2.res
new file mode 100644 (file)
index 0000000..51196e3
--- /dev/null
@@ -0,0 +1,65 @@
+<html><head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
+<style type="text/css">
+code {margin: 0 2px;
+padding: 0px 5px;
+border: 1px solid #ddd;
+background-color: #f8f8f8;
+border-radius: 3px;}
+pre {
+background-color: #f8f8f8;
+border: 1px solid #ddd;
+font-size: 13px;
+line-height: 19px;
+overflow: auto;
+padding: 6px 6px;
+border-radius: 3px;
+}
+.rawcode[title] {
+border-color: red;
+}
+h5 {font-weight:bold;}
+.nitcode a { color: inherit; cursor:pointer; }
+.nitcode .popupable:hover { text-decoration: underline; cursor:help; } /* underline titles */
+.nitcode .foldable { display: block } /* for block productions*/
+.nitcode .line{ display: block } /* for lines */
+.nitcode .line:hover{ background-color: #FFFFE0; } /* current line */
+.nitcode :target { background-color: #FFF3C2 } /* target highlight*/
+/* lexical raw tokens. independent of usage or semantic: */
+.nitcode .nc_c { color: gray; font-style: italic; } /* comment */
+.nitcode .nc_d { color: #3D8127; font-style: italic; } /* documentation comments */
+.nitcode .nc_k { font-weight: bold; } /* keyword */
+.nitcode .nc_o {} /* operator */
+.nitcode .nc_i {} /* standard identifier */
+.nitcode .nc_t { color: #445588; font-weight: bold; } /* type/class identifier */
+.nitcode .nc_a { color: #445588; font-style: italic; } /* old style attribute identifier */
+.nitcode .nc_l { color: #009999; } /* char and number literal */
+.nitcode .nc_s { color: #8F1546; } /* string literal */
+/* syntactic token usage. added because of their position in the AST */
+.nitcode .nc_ast { color: blue; } /* assert label */
+.nitcode .nc_la { color: blue; } /* break/continue label */
+.nitcode .nc_m { color: #445588; } /* module name */
+/* syntactic groups */
+.nitcode .nc_def { font-weight: bold; color: blue; } /* name used in a definition */
+  .nitcode .nc_def.nc_a { color: blue; } /* name used in a attribute definition */
+  .nitcode .nc_def.nc_t { color: blue; } /* name used in a class or vt definition */
+.nitcode .nc_ss { color: #9E6BEB; } /* superstrings */
+.nitcode .nc_cdef {} /* A whole class definition */
+.nitcode .nc_pdef {} /* A whole property definition */
+/* semantic token usage */
+.nitcode .nc_v { font-style: italic; } /* local variable or parameter */
+.nitcode .nc_vt { font-style: italic; } /* virtual type or formal type */
+
+.nitcode .nc_error { border: 1px red solid;} /* not used */
+.popover { max-width: 800px !important; }
+
+</style>
+</head><body><h3 id='test_doc2'>module test_doc2</h1><h5 id='test_doc2#Object#foo1'>prop test_doc2#Object#foo1</h3><div class="nitdoc"><p class="synopsys">Test code</p><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_k">assert</span> <span class="nc_k">true</span> <span># tested
+</span></span><span class="line" id="L2"><span></span></span></span></pre></div><h5 id='test_doc2#Object#foo2'>prop test_doc2#Object#foo2</h3><div class="nitdoc"><p class="synopsys">Test code</p><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_k">assert</span> <span class="nc_k">true</span> <span># tested
+</span></span><span class="line" id="L2"><span></span></span></span></pre></div><h5 id='test_doc2#Object#foo3'>prop test_doc2#Object#foo3</h3><div class="nitdoc"><p class="synopsys">Test code</p><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_k">assert</span> <span class="nc_k">true</span> <span># tested
+</span></span><span class="line" id="L2"><span></span></span></span></pre></div><h5 id='test_doc2#Object#foo4'>prop test_doc2#Object#foo4</h3><div class="nitdoc"><p class="synopsys">Test code</p><pre class="rawcode">assert false # not tested (and not highlighted)
+</pre></div><h5 id='test_doc2#Object#foo5'>prop test_doc2#Object#foo5</h3><div class="nitdoc"><p class="synopsys">Test code</p><pre class="nitcode"><span class="nitcode"><span class="line" id="L1"><span class="nc_k">assert</span> <span class="nc_k">false</span> <span># not tested (but highlighted)
+</span></span><span class="line" id="L2"><span></span></span></span></pre></div><script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
+<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
+<script>$(".popupable").popover({html:true, placement:'top'})/*initialize bootstrap popover*/</script></body></html>
\ No newline at end of file
diff --git a/tests/test_doc2.nit b/tests/test_doc2.nit
new file mode 100644 (file)
index 0000000..70e266c
--- /dev/null
@@ -0,0 +1,46 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Test code
+#
+#     assert true # tested
+fun foo1 do end
+
+# Test code
+#
+# ~~~~
+# assert true # tested
+# ~~~~
+fun foo2 do end
+
+# Test code
+#
+# ~~~~nit
+# assert true # tested
+# ~~~~
+fun foo3 do end
+
+# Test code
+#
+# ~~~~raw
+# assert false # not tested (and not highlighted)
+# ~~~~
+fun foo4 do end
+
+# Test code
+#
+# ~~~~nitish
+# assert false # not tested (but highlighted)
+# ~~~~
+fun foo5 do end
diff --git a/tests/test_docdown.args b/tests/test_docdown.args
new file mode 100644 (file)
index 0000000..b10baba
--- /dev/null
@@ -0,0 +1,2 @@
+test_doc.nit
+test_doc2.nit
diff --git a/tests/test_markdown.args b/tests/test_markdown.args
deleted file mode 100644 (file)
index 79d2034..0000000
+++ /dev/null
@@ -1 +0,0 @@
-test_doc.nit