Merge: Use tagged-fences to discriminate docunits
authorJean Privat <jean@pryen.org>
Fri, 28 Nov 2014 19:51:34 +0000 (14:51 -0500)
committerJean Privat <jean@pryen.org>
Fri, 28 Nov 2014 19:51:34 +0000 (14:51 -0500)
Using heuristics to know what is a docunit and what is a raw block of code is not nice because syntax-errors in docunits happen and we do not want to silence them.

This PR introduces (and documents) the usage of tagged fences to force the programmer to explicit the role of the blocks of code.

By default (with indented block or untagged fences) code blocks are considered docunits to be checked by nitunit.
The tag `nit` does the same.
Any other tag cause docunit to ignore the whole block.

The special tag `nitish` makes docunit ignore the block but allows nitdoc to highlight it.

~~~~
~~~~

Pull-Request: #941
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

50 files changed:
contrib/jwrapper/src/javap_visitor.nit
contrib/nitiwiki/src/wiki_html.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/geometry/boxes.nit
lib/json/dynamic.nit
lib/jvm.nit
lib/markdown/markdown.nit
lib/mnit/mnit_injected_input.nit
lib/mnit_display.nit
lib/pnacl.nit
lib/poset.nit
lib/sax/helpers/sax_locator_impl.nit
lib/sax/xml_reader.nit
lib/scene2d.nit
lib/signals.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/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
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 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 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 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 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 c6fd1d2..e8f7e73 100644 (file)
@@ -366,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]
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 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 26251ce..62d5ddc 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 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