+ end
+
+ # Create and fill the header of a unit file `file`.
+ #
+ # A unit file is a Nit source file generated from one
+ # or more docunits that will be compiled and executed.
+ #
+ # The handled on the file is returned and must be completed and closed.
+ #
+ # `file` should be a valid filepath for a Nit source file.
+ private fun create_unitfile(file: String): Writer
+ do
+ var dir = file.dirname
+ if dir != "" then dir.mkdir
+ var f
+ f = new FileWriter.open(file)
+ f.write("# GENERATED FILE\n")
+ f.write("# Docunits extracted from comments\n")
+ if mmodule != null then
+ f.write("import {mmodule.name}\n")
+ end
+ f.write("\n")
+ return f
+ end
+
+ # Compile an unit file and return the compiler return code
+ #
+ # Can terminate the program if the compiler is not found
+ private fun compile_unitfile(file: String): Int
+ do
+ var nitc = toolcontext.find_nitc
+ var opts = new Array[String]
+ if mmodule != null then
+ opts.add "-I {mmodule.filepath.dirname}"
+ end
+ var cmd = "{nitc} --ignore-visibility --no-color -q '{file}' {opts.join(" ")} >'{file}.out1' 2>&1 </dev/null -o '{file}.bin'"
+ var res = toolcontext.safe_exec(cmd)
+ return res
+ end
+end
+
+private class NitunitDecorator
+ super HTMLDecorator
+
+ var executor: NitUnitExecutor
+
+ redef fun add_code(v, block) do
+ var code = block.raw_content
+ var meta = block.meta or else "nit"
+ # Do not try to test non-nit code.
+ if meta != "nit" then return
+ # Try to parse code blocks
+ var ast = executor.toolcontext.parse_something(code)
+
+ var mdoc = executor.mdoc
+ assert mdoc != null
+
+ # Skip pure comments
+ if ast isa TComment then return
+
+ # The location is computed according to the starts of the mdoc and the block
+ # Note, the following assumes that all the comments of the mdoc are correctly aligned.
+ var loc = block.block.location
+ var line_offset = loc.line_start + mdoc.location.line_start - 2
+ var column_offset = loc.column_start + mdoc.location.column_start
+ # Hack to handle precise location in blocks
+ # TODO remove when markdown is more reliable
+ if block isa BlockFence then
+ # Skip the starting fence
+ line_offset += 1
+ else
+ # Account a standard 4 space indentation
+ column_offset += 4
+ end