Merge: neo4j: Sanitize the inputs
authorJean Privat <jean@pryen.org>
Tue, 25 Nov 2014 22:56:49 +0000 (17:56 -0500)
committerJean Privat <jean@pryen.org>
Tue, 25 Nov 2014 22:56:49 +0000 (17:56 -0500)
![](http://imgs.xkcd.com/comics/exploits_of_a_mom.png )
— xkcd

Pull-Request: #930
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

172 files changed:
.gitignore
contrib/neo_doxygen/Makefile
contrib/neo_doxygen/README.md [new file with mode: 0644]
contrib/neo_doxygen/gen-all.sh
contrib/neo_doxygen/sh-lib/README.md [new file with mode: 0644]
contrib/neo_doxygen/sh-lib/more_sed.sh [new file with mode: 0644]
contrib/neo_doxygen/src/doxml/doc.nit
contrib/neo_doxygen/src/doxml/language_specific.nit
contrib/neo_doxygen/src/flush_stdout.nit [new file with mode: 0644]
contrib/neo_doxygen/src/graph_store.nit [new file with mode: 0644]
contrib/neo_doxygen/src/model/class_compound.nit
contrib/neo_doxygen/src/model/graph.nit
contrib/neo_doxygen/src/model/module_compound.nit
contrib/neo_doxygen/src/neo_doxygen.nit
contrib/neo_doxygen/src/tests/README.md [new file with mode: 0644]
contrib/neo_doxygen/src/tests/neo_doxygen_dump.nit [new file with mode: 0644]
contrib/neo_doxygen/src/tests/neo_doxygen_file_compound.nit [new file with mode: 0644]
contrib/neo_doxygen/src/tests/neo_doxygen_graph_empty_project.nit [new file with mode: 0644]
contrib/neo_doxygen/src/tests/neo_doxygen_member_resolve_introducer.nit [new file with mode: 0644]
contrib/neo_doxygen/src/tests/tests.nit [new file with mode: 0644]
contrib/neo_doxygen/tests/.gitattributes [new file with mode: 0644]
contrib/neo_doxygen/tests/Makefile [new file with mode: 0644]
contrib/neo_doxygen/tests/README.md [new file with mode: 0644]
contrib/neo_doxygen/tests/doxyproject.mk [new file with mode: 0644]
contrib/neo_doxygen/tests/empty-project/Doxyfile [new file with mode: 0644]
contrib/neo_doxygen/tests/empty-project/README.md [new file with mode: 0644]
contrib/neo_doxygen/tests/empty-project/src/org/example/foo/void.txt [new file with mode: 0644]
contrib/neo_doxygen/tests/empty-project/xml/combine.xslt [new file with mode: 0644]
contrib/neo_doxygen/tests/empty-project/xml/compound.xsd [new file with mode: 0644]
contrib/neo_doxygen/tests/empty-project/xml/index.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/empty-project/xml/index.xsd [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/Doxyfile [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/README.md [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/src/org/example/foo/A.java [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/src/org/example/foo/B.java [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/src/org/example/foo/C.java [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/src/org/example/foo/EmptyClass.java [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/_a_8java.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/_b_8java.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/_c_8java.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/_empty_class_8java.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/classorg_1_1example_1_1foo_1_1_a.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/classorg_1_1example_1_1foo_1_1_b.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/classorg_1_1example_1_1foo_1_1_empty_class.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/combine.xslt [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/compound.xsd [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/dir_68267d1309a1af8e8297ef4c3efbcdba.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/dir_8c35fc67c36f89d827afb23e8c52a418.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/dir_ad5d6582648a7bbb3a301939a41e6c0b.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/dir_b8e0663afee48cb679b74bbd21bdf843.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/index.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/index.xsd [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/interfaceorg_1_1example_1_1foo_1_1_c.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/namespaceorg.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/namespaceorg_1_1example.xml [new file with mode: 0644]
contrib/neo_doxygen/tests/java-project/xml/namespaceorg_1_1example_1_1foo.xml [new file with mode: 0644]
contrib/nitiwiki/.gitignore [new file with mode: 0644]
contrib/nitiwiki/Makefile [new file with mode: 0644]
contrib/nitiwiki/README.md [new file with mode: 0644]
contrib/nitiwiki/examples/default/config.ini [new file with mode: 0644]
contrib/nitiwiki/examples/default/pages/index.md [new file with mode: 0644]
contrib/nitiwiki/examples/default/templates/footer.html [new file with mode: 0644]
contrib/nitiwiki/examples/default/templates/header.html [new file with mode: 0644]
contrib/nitiwiki/examples/default/templates/menu.html [new file with mode: 0644]
contrib/nitiwiki/examples/default/templates/template.html [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/assets/css/main.css [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/assets/logo.png [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/config.ini [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/pages/index.md [new symlink]
contrib/nitiwiki/examples/nitiwiki/templates/footer.html [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/templates/header.html [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/templates/menu.html [new file with mode: 0644]
contrib/nitiwiki/examples/nitiwiki/templates/template.html [new file with mode: 0644]
contrib/nitiwiki/src/nitiwiki.nit [new file with mode: 0644]
contrib/nitiwiki/src/wiki_base.nit [new file with mode: 0644]
contrib/nitiwiki/src/wiki_html.nit [new file with mode: 0644]
contrib/nitiwiki/tests/Makefile [new file with mode: 0644]
contrib/nitiwiki/tests/nitiwiki.args [new file with mode: 0644]
contrib/nitiwiki/tests/nitiwiki_render.args [new file with mode: 0644]
contrib/nitiwiki/tests/nitiwiki_status.args [new file with mode: 0644]
contrib/nitiwiki/tests/res/nitiwiki.res [new file with mode: 0644]
contrib/nitiwiki/tests/res/nitiwiki_render.res [new file with mode: 0644]
contrib/nitiwiki/tests/res/nitiwiki_status.res [new file with mode: 0644]
contrib/nitiwiki/tests/tests.sh [new file with mode: 0755]
contrib/nitiwiki/tests/wiki1/assets/css/main.css [new file with mode: 0644]
contrib/nitiwiki/tests/wiki1/config.ini [new file with mode: 0644]
contrib/nitiwiki/tests/wiki1/config2.ini [new file with mode: 0644]
contrib/nitiwiki/tests/wiki1/pages/index.md [new file with mode: 0644]
contrib/nitiwiki/tests/wiki1/templates/footer.html [new file with mode: 0644]
contrib/nitiwiki/tests/wiki1/templates/header.html [new file with mode: 0644]
contrib/nitiwiki/tests/wiki1/templates/menu.html [new file with mode: 0644]
contrib/nitiwiki/tests/wiki1/templates/template.html [new file with mode: 0644]
lib/android/assets_and_resources.nit
lib/android/audio.nit
lib/android/bundle/bundle.nit
lib/android/intent/intent_api10.nit
lib/android/platform.nit
lib/android/shared_preferences/shared_preferences_api10.nit
lib/android/vibration.nit
lib/app/data_store.nit
lib/c.nit
lib/java/io.nit
lib/java/java.nit
lib/markdown/markdown.nit
lib/markdown/test_markdown.nit
lib/mnit_android/android_app.nit
lib/neo4j/jsonable.nit [new file with mode: 0644]
lib/pthreads/extra.nit [new file with mode: 0644]
lib/pthreads/pthreads.nit
lib/saxophonit/test_saxophonit.nit
lib/standard/collection/abstract_collection.nit
lib/standard/collection/array.nit
lib/standard/collection/collection.nit
lib/standard/collection/hash_collection.nit
lib/standard/collection/list.nit
lib/standard/collection/range.nit
lib/standard/exec.nit
lib/standard/file.nit
lib/standard/kernel.nit
lib/standard/math.nit
lib/standard/re.nit
lib/standard/ropes.nit
lib/standard/stream.nit
lib/standard/string.nit
lib/standard/string_search.nit
lib/standard/time.nit
lib/trees/abstract_tree.nit
lib/trees/bintree.nit
lib/trees/rbtree.nit
src/compiler/android_annotations.nit
src/compiler/android_platform.nit
src/doc/doc_model.nit
src/docdown.nit [moved from src/markdown.nit with 99% similarity]
src/interpreter/naive_interpreter.nit
src/modelize/modelize_property.nit
src/test_docdown.nit
src/testing/testing_doc.nit
tests/Makefile
tests/base_self_type.nit [new file with mode: 0644]
tests/listfull.sh
tests/neo_doxygen_dump.args [new file with mode: 0644]
tests/nitg-g.skip
tests/nitiwiki.args [new file with mode: 0644]
tests/sav/base_self_type.res [new file with mode: 0644]
tests/sav/base_self_type_alt1.res [new file with mode: 0644]
tests/sav/base_self_type_alt2.res [new file with mode: 0644]
tests/sav/base_self_type_alt3.res [new file with mode: 0644]
tests/sav/error_class_glob.res
tests/sav/neo_doxygen_dump.res [new file with mode: 0644]
tests/sav/neo_doxygen_dump_args1.res [new file with mode: 0644]
tests/sav/neo_doxygen_dump_args2.res [new file with mode: 0644]
tests/sav/neo_doxygen_dump_args3.res [new file with mode: 0644]
tests/sav/neo_doxygen_dump_args4.res [new file with mode: 0644]
tests/sav/neo_doxygen_dump_args5.res [new file with mode: 0644]
tests/sav/neo_doxygen_file_compound.res [new file with mode: 0644]
tests/sav/neo_doxygen_graph_empty_project.res [new file with mode: 0644]
tests/sav/neo_doxygen_member_resolve_introducer.res [new file with mode: 0644]
tests/sav/nitg-e/base_self_type.res [new file with mode: 0644]
tests/sav/nitg-e/base_self_type_alt2.res [new file with mode: 0644]
tests/sav/nitg-e/fixme/base_gen_reassign_alt4.res
tests/sav/nitg-e/fixme/base_gen_reassign_alt5.res
tests/sav/nitg-e/fixme/base_gen_reassign_alt6.res
tests/sav/nitiwiki.res [new file with mode: 0644]
tests/sav/nitiwiki_args1.res [new file with mode: 0644]
tests/sav/nitiwiki_args2.res [new file with mode: 0644]
tests/sav/nituml_args3.res
tests/sav/nituml_args4.res
tests/sav/test_c_alt1.res
tests/sav/test_c_alt2.res
tests/sav/test_c_alt3.res
tests/sav/test_c_alt4.res
tests/sav/test_new_native_alt1.res

index 65ac23a..62da951 100644 (file)
@@ -50,6 +50,8 @@ tests/out
 tests/*.xml
 tests/nitunit
 
+nitunit.xml
+
 *.stub.nit.[ch]
 
 .metadata/*
index ed82923..53383f7 100644 (file)
 NITG=../../bin/nitg
 NITG_FLAGS=--dir bin
 NEO4J_DIR=/var/lib/neo4j
+OLD_PWD=${PWD}
 
-.PHONY: bin reset-neo
+.PHONY: bin reset-neo run-tests tests
 
 # Compile the tool.
 bin:
        mkdir -p bin
-       ../../bin/nitg --dir bin src/neo_doxygen.nit
+       $(NITG) $(NITG_FLAGS) src/neo_doxygen.nit
 
 # Reset the local graph.
 reset-neo:
        sudo -u neo4j "${NEO4J_DIR}/bin/neo4j" stop \
        && sudo -u neo4j rm -rf "${NEO4J_DIR}/data/graph.db" \
        && sudo -u neo4j "${NEO4J_DIR}/bin/neo4j" start
+
+# Regenerate the XML documents in `tests`.
+tests:
+       $(MAKE) -C tests
+
+# Run the tests.
+run-tests:
+       cd ../../tests; \
+       ./tests.sh ../contrib/neo_doxygen/src/tests/neo_doxygen_*.nit ; \
+       cd "${OLD_PWD}"
diff --git a/contrib/neo_doxygen/README.md b/contrib/neo_doxygen/README.md
new file mode 100644 (file)
index 0000000..67b0e52
--- /dev/null
@@ -0,0 +1,71 @@
+# neo_doxygen
+
+This project provides a tool to convert a Doxygen XML output into a model in
+Neo4j that is readable by the `nx` tool.
+
+
+## Installation
+
+Ensure that you have a working version of `nitg` in `../../bin` then run `make`
+in the present directory. The executable will be then generated at
+`bin/neo_doxygen`.
+
+
+## Usage
+
+Here is the procedure to generate an HTML documentation of a project using the
+formatting of Nitdoc:
+
+1. First run Doxygen to generate an XML output of the documentation. In order to do
+this, you have to enable the `GENERATE_XML` option. Note that you can disable
+the `XML_PROGRAMLISTING` to speed up the process and save disk space.
+
+       <strong>Important</strong>
+
+       `neo_doxygen` do not read the `index.xml` file to know which file to load. As a
+       result, it may read files let by previous runs of Doxygen. To avoid producing
+       garbage, always clear the destination directory of the XML files before running
+       Doxygen.
+
+       Example: `rm -rf doxygen/xml && doxygen Doxyfile`
+
+2. Use `bin/neo_doxygen` to generate the Neo4j graph. For details, run
+`bin/neo_doxygen --help`.
+
+       <strong>Important</strong>
+
+       `neo_doxygen` do not remove what is already in the graph. So, you have to
+       manualy clear the graph (or at least, the subgraph contaning all the nodes
+       labelled with the specified project name) between each run.
+
+       For an example of how to delete an entire Neo4j database, see
+       `make reset-neo`.
+
+       Example: `make reset-neo && neo_doxygen my_project doxygen/xml`
+
+3. Use the `nx` tool to generate the HTML documentation from the previously
+generated graph.
+
+       Note: `nx` need to be configured before usage. For more details, refer to
+       the documentation of `nx`.
+
+       Example: `nx neo doc my_project`
+
+
+## Shell scripts
+
+The two shell scripts (`gen-one.sh` and `gen-all.sh`) are provided to automate
+the execution of `neo_doxygen` and `nx` for some typical cases and to give a
+starting for the development of similar scripts. In order for them to work,
+each project on which they operate **must** contain the following files:
+
+ * The `.nx_config` configuration file for the `nx` tool, located at the root
+       of the project.
+
+ * The XML documents generated by Doxygen, located in the `doxygen/xml`
+       directory.
+
+Also, they **must** be run with the current working directory set to the present
+directory. `gen-one.sh` handle only one project at a time while `gen-all.sh`
+works on a collection of projects grouped in a directory. For detail about how
+to invoke each script, see the comments in these scripts.
index b43ceab..4a19e9a 100755 (executable)
@@ -23,9 +23,6 @@
 # Also, every project must include the Doxygen XML output in its `doxygen/xml`
 # directory.
 
-NEO_DOXYGEN="${PWD}/bin/neo_doxygen"
-NX="${PWD}/../../bin/nx"
-
 for dir in "$2"/*; do
        if [ -d "$dir" ]; then
                if [ -f "$dir/.nx_config" ]; then
diff --git a/contrib/neo_doxygen/sh-lib/README.md b/contrib/neo_doxygen/sh-lib/README.md
new file mode 100644 (file)
index 0000000..ade333a
--- /dev/null
@@ -0,0 +1 @@
+Libraries used by shell scripts.
diff --git a/contrib/neo_doxygen/sh-lib/more_sed.sh b/contrib/neo_doxygen/sh-lib/more_sed.sh
new file mode 100644 (file)
index 0000000..db58b69
--- /dev/null
@@ -0,0 +1,37 @@
+#! /bin/sh
+
+# 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.
+
+# Functions related to the `sed` utility.
+
+# Replace `$1` by `$2` in the specified files (the rest of the arguments).
+#
+# Replacements are done in place.
+#
+# SETS: `local_1`
+# SETS: `local_2`
+replace() {
+       local_1=`escape_to_bre "$1"`
+       local_2=`escape_to_bre "$2"`
+       shift 2
+       sed -s -i -e s."${local_1}"."${local_2}".g -- "$@"
+       unset local_1
+       unset local_2
+}
+
+# Escape `$1` for inclusion in a POSIX BRE.
+escape_to_bre() {
+       echo "$1" | sed -e 's/\*\|\.\|\^\|\$\|\[\|\\/\\\0/g'
+}
index 84a880d..610bbf0 100644 (file)
@@ -25,6 +25,7 @@ class DocListener
 
        redef fun end_listening do
                super
-               doc.add(to_s)
+               var line = to_s.trim
+               if not line.is_empty then doc.add(line)
        end
 end
index bbc6410..10757ea 100644 (file)
@@ -162,7 +162,9 @@ class JavaSource
                # For abstract members, Doxygen put `abstract` at the beginning of the type.
                # We assume that Doxygen do not put annotations in the type (it seems to
                # be the case).
-               member.is_abstract = extract_keyword(type_text, "abstract")
+               if extract_keyword(type_text, "abstract") then
+                       member.is_abstract = true
+               end
                # TODO final
                # TODO void
                # TODO Avoid using `RawType` when possible. Only use `RawType` as a fallback.
diff --git a/contrib/neo_doxygen/src/flush_stdout.nit b/contrib/neo_doxygen/src/flush_stdout.nit
new file mode 100644 (file)
index 0000000..30be3fc
--- /dev/null
@@ -0,0 +1,25 @@
+# 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.
+
+# Add the ability to flush the standard output.
+module flush_stdout
+
+in "C Header" `{
+       #include <stdio.h>
+`}
+
+# Flush the standard output.
+fun flush_stdout in "C" `{
+       fflush(stdout);
+`}
diff --git a/contrib/neo_doxygen/src/graph_store.nit b/contrib/neo_doxygen/src/graph_store.nit
new file mode 100644 (file)
index 0000000..b15ae4f
--- /dev/null
@@ -0,0 +1,117 @@
+# 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.
+
+# A storage medium for a graph.
+module graph_store
+
+import neo4j
+import console
+import flush_stdout
+
+# A storage medium for a graph.
+#
+# Provides a way to save a Neo4j graph.
+abstract class GraphStore
+
+       # Escape control sequence to save the cursor position.
+       private var term_save_cursor: String = (new TermSaveCursor).to_s
+
+       # Escape control sequence to rewind to the last saved cursor position.
+       private var term_rewind: String = "{new TermRestoreCursor}{new TermEraseDisplayDown}"
+
+       # Is the storage medium already contains at least one node with the specified label?
+       fun has_node_label(name: String): Bool is abstract
+
+       # Save all specified Neo4j entities.
+       fun save_all(neo_entities: Collection[NeoEntity]) is abstract
+
+       # Prepare the output to show the progress.
+       #
+       # This method must be called before the first call to `show_progress` or
+       # `show_done`.
+       protected fun prepare_display do
+               printn "{term_save_cursor} "
+               flush_stdout
+       end
+
+       # Show the progress, in percentage.
+       #
+       # For use in the implementation of `save_all` only.
+       protected fun show_progress(progress: Int) do
+               printn "{term_rewind} {progress}% "
+               flush_stdout
+       end
+
+       # Show a message to indicate that the task finished with success.
+       #
+       # For use in the implementation of `save_all` only.
+       protected fun show_done do
+               print "{term_rewind} Done."
+               flush_stdout
+       end
+end
+
+# An actual Neo4j database as a storage medium.
+class Neo4jStore
+       super GraphStore
+
+       # How many operations can be executed in one batch?
+       private var batch_max_size = 1000
+
+       # The Neo4j client to use.
+       var client: Neo4jClient
+
+       redef fun has_node_label(name: String): Bool do
+               var query = new CypherQuery.from_string(
+                               "match n where \{name\} in labels(n) return count(n)")
+               query.params["name"] = name
+               var data = client.cypher(query).as(JsonObject)["data"]
+               var result = data.as(JsonArray).first.as(JsonArray).first.as(Int)
+               return result > 0
+       end
+
+       redef fun save_all(neo_entities: Collection[NeoEntity]) do
+               var batch = new NeoBatch(client)
+               var len = neo_entities.length
+               var sum = 0
+               var i = 1
+
+               prepare_display
+               for nentity in neo_entities do
+                       batch.save_entity(nentity)
+                       if i == batch_max_size then
+                               do_batch(batch)
+                               sum += batch_max_size
+                               show_progress(sum * 100 / len)
+                               batch = new NeoBatch(client)
+                               i = 1
+                       else
+                               i += 1
+                       end
+               end
+               do_batch(batch)
+               show_done
+       end
+
+       # Execute `batch` and check for errors.
+       #
+       # Abort if `batch.execute` returns errors.
+       private fun do_batch(batch: NeoBatch) do
+               var errors = batch.execute
+               if not errors.is_empty then
+                       for e in errors do sys.stderr.write("{sys.program_name}: {e}\n")
+                       exit(1)
+               end
+       end
+end
index 7663c0a..47a95f9 100644 (file)
@@ -72,8 +72,8 @@ class ClassCompound
                class_def["mdoc"] = doc
        end
 
-       redef fun declare_super(id: String, name: String, prot: String, virt: String) do
-               class_def.declare_super(id, name, prot, virt)
+       redef fun declare_super(id: String, full_name: String, prot: String, virt: String) do
+               class_def.declare_super(id, full_name, prot, virt)
        end
 
        redef fun declare_member(member: Member) do
@@ -119,8 +119,9 @@ class ClassDef
                self["is_intro"] = true
        end
 
-       fun declare_super(id: String, name: String, prot: String, virt: String) do
-               # TODO prot, virt, name
+       fun declare_super(id: String, full_name: String, prot: String,
+                       virt: String) do
+               # TODO prot, virt, full_name
                if "" != id then
                        supers.add(id)
                end
index e14d817..ffd4eec 100644 (file)
@@ -60,6 +60,7 @@ class ProjectGraph
 
        # Request to all nodes in the graph to add their related edges.
        fun put_edges do
+               all_edges.clear
                add_edge(project, "ROOT", by_id[""])
                for n in all_nodes do
                        if n isa Entity then
@@ -204,29 +205,37 @@ abstract class Compound
 
        # Declare an inner namespace.
        #
+       # Note: Althought Doxygen indicates that the name is optional,
+       # declarations with an empty name are not supported yet.
+       #
        # Parameters:
        #
        # * `id`: `model_id` of the inner namespace. May be empty.
-       # * `name`: string identifying the inner namespace. May be empty.
-       fun declare_namespace(id: String, name: String) do end
+       # * `full_name`: qualified name of the inner namespace.
+       fun declare_namespace(id: String, full_name: String) do end
 
        # Declare an inner class.
        #
+       # Note: Althought Doxygen indicates that both arguments are optional,
+       # declarations with either an empty name or an empty ID are not
+       # supported yet.
+       #
        # Parameters:
        #
-       # * `id`: `model_id` of the inner class. May be empty.
-       # * `name`: string identifying the inner class. May be empty.
-       fun declare_class(id: String, name: String) do end
+       # * `id`: `model_id` of the inner class.
+       # * `full_name`: qualified name of the inner class.
+       fun declare_class(id: String, full_name: String) do end
 
        # Declare a base compound (usually, a base class).
        #
        # Parameters:
        #
        # * `id`: `model_id` of the base compound. May be empty.
-       # * `name`: string identifying the base compound. May be empty.
+       # * `full_name`: qualified name of the base compound. May be empty.
        # * `prot`: visibility (proctection) of the relationship.
        # * `virt`: level of virtuality of the relationship.
-       fun declare_super(id: String, name: String, prot: String, virt: String) do end
+       fun declare_super(id: String, full_name: String, prot: String,
+                       virt: String) do end
 end
 
 # An unrecognized compound.
index 6629cc7..6cdd20e 100644 (file)
@@ -65,30 +65,39 @@ class FileCompound
                end
        end
 
-       redef fun declare_namespace(id: String, name: String) do
+       redef fun declare_namespace(id: String, full_name: String) do
                var m: Module
 
-               if inner_namespaces.keys.has(name) then
-                       m = inner_namespaces[name]
+               assert not full_name.is_empty else
+                       sys.stderr.write "Inner mamespace declarations without name are not yet supported.\n"
+               end
+               if inner_namespaces.keys.has(full_name) then
+                       m = inner_namespaces[full_name]
                        if id != "" then m.parent = id
                else
                        m = new Module(graph)
-                       m.full_name = "{name}{ns_separator}{basename}"
+                       m.full_name = "{full_name}{ns_separator}{basename}"
                        m.parent = id
                        m.location = self["location"].as(nullable Location)
-                       inner_namespaces[name] = m
+                       inner_namespaces[full_name] = m
                end
        end
 
-       redef fun declare_class(id: String, name: String) do
-               var match = name.search_last(ns_separator)
+       redef fun declare_class(id: String, full_name: String) do
+               assert not id.is_empty else
+                       sys.stderr.write "Inner class declarations without ID are not yet supported.\n"
+               end
+               assert not full_name.is_empty else
+                       sys.stderr.write "Inner class declarations without name are not yet supported.\n"
+               end
+               var match = full_name.search_last(ns_separator)
                var ns_name: String
                var m: Module
 
                if match == null then
                        ns_name = ""
                else
-                       ns_name = name.substring(0, match.from)
+                       ns_name = full_name.substring(0, match.from)
                end
                if inner_namespaces.keys.has(ns_name) then
                        m = inner_namespaces[ns_name]
@@ -96,7 +105,7 @@ class FileCompound
                        declare_namespace("", ns_name)
                        m = inner_namespaces[ns_name]
                end
-               m.declare_class(id, name)
+               m.declare_class(id, full_name)
        end
 
        redef fun put_in_graph do
@@ -124,7 +133,10 @@ class Module
                self.labels.add("MModule")
        end
 
-       redef fun declare_class(id: String, name: String) do
+       redef fun declare_class(id: String, full_name: String) do
+               assert not id.is_empty else
+                       sys.stderr.write "Inner class declarations without ID not supported yet.\n"
+               end
                inner_classes.add(id)
        end
 
index f26dfc2..d70f008 100644 (file)
@@ -20,21 +20,25 @@ module neo_doxygen
 
 import model
 import doxml
+import graph_store
 import console
+import flush_stdout
 import opts
 
 # An importation task.
 class NeoDoxygenJob
-       var client: Neo4jClient
-       var model: ProjectGraph is noinit
 
-       # How many operation can be executed in one batch?
-       private var batch_max_size = 1000
+       # The storage medium to use.
+       var store: GraphStore
+
+       # The loaded project graph.
+       var model: ProjectGraph is noinit
 
-       private var save_cursor: String = (new TermSaveCursor).to_s
+       # Escape control sequence to save the cursor position.
+       private var term_save_cursor: String = (new TermSaveCursor).to_s
 
-       # Escape control sequence to reset the current line.
-       private var reset_line: String = "{new TermRestoreCursor}{new TermEraseDisplayDown}"
+       # Escape control sequence to rewind to the last saved cursor position.
+       private var term_rewind: String = "{new TermRestoreCursor}{new TermEraseDisplayDown}"
 
        # Generate a graph from the specified project model.
        #
@@ -46,29 +50,45 @@ class NeoDoxygenJob
        fun load_project(name: String, dir: String, source: SourceLanguage) do
                check_name name
                model = new ProjectGraph(name)
-               # TODO Let the user select the language.
                var reader = new CompoundFileReader(model, source)
                # Queue for sub-directories.
                var directories = new Array[String]
+               var file_count = 0
 
-               if dir.length > 1 and dir.chars.last == "/" then
-                       dir = dir.substring(0, dir.length - 1)
+               if dir == "" then
+                       printn "Reading the current directory... "
+               else
+                       printn "Reading {dir}... "
                end
-               sys.stdout.write save_cursor
+               flush_stdout
                loop
-                       for f in dir.files do
+                       for f in list_files(dir) do
                                var path = dir/f
                                if path.file_stat.is_dir then
                                        directories.push(path)
                                else if f.has_suffix(".xml") and f != "index.xml" then
-                                       print "{reset_line}Reading {path}..."
                                        reader.read(path)
+                                       file_count += 1
                                end
                        end
                        if directories.length <= 0 then break
                        dir = directories.pop
                end
-               print "{reset_line}Reading... Done."
+               print "Done."
+               if file_count < 2 then
+                       print "{file_count} file read."
+               else
+                       print "{file_count} files read."
+               end
+               flush_stdout
+       end
+
+       # List files in a directory.
+       #
+       # This method may be redefined to force the order in which the files
+       # are read by `load_project`.
+       protected fun list_files(dir: String): Collection[String] do
+               return dir.files
        end
 
        # Check the project’s name.
@@ -77,11 +97,7 @@ class NeoDoxygenJob
                        sys.stderr.write("{sys.program_name}: The project’s name must not" +
                                        " begin with an upper case letter. Got `{name}`.\n")
                end
-               var query = new CypherQuery.from_string("match n where \{name\} in labels(n) return count(n)")
-               query.params["name"] = name
-               var data = client.cypher(query).as(JsonObject)["data"]
-               var result = data.as(JsonArray).first.as(JsonArray).first.as(Int)
-               assert name_unused: result == 0 else
+               assert name_unused: not store.has_node_label(name) else
                        sys.stderr.write("{sys.program_name}: The label `{name}` is already" +
                        " used in the specified graph.\n")
                end
@@ -89,49 +105,16 @@ class NeoDoxygenJob
 
        # Save the graph.
        fun save do
-               print "Linking nodes...{save_cursor}"
+               sys.stdout.write "Linking nodes...{term_save_cursor} "
+               flush_stdout
                model.put_edges
-               print "{reset_line} Done."
+               print "{term_rewind} Done."
                var nodes = model.all_nodes
-               print "Saving {nodes.length} nodes...{save_cursor}"
-               push_all(nodes)
+               sys.stdout.write "Saving {nodes.length} nodes..."
+               store.save_all(nodes)
                var edges = model.all_edges
-               print "Saving {edges.length} edges...{save_cursor}"
-               push_all(edges)
-       end
-
-       # Save `neo_entities` in the database using batch mode.
-       private fun push_all(neo_entities: Collection[NeoEntity]) do
-               var batch = new NeoBatch(client)
-               var len = neo_entities.length
-               var sum = 0
-               var i = 1
-
-               for nentity in neo_entities do
-                       batch.save_entity(nentity)
-                       if i == batch_max_size then
-                               do_batch(batch)
-                               sum += batch_max_size
-                               print("{reset_line} {sum * 100 / len}%")
-                               batch = new NeoBatch(client)
-                               i = 1
-                       else
-                               i += 1
-                       end
-               end
-               do_batch(batch)
-               print("{reset_line} Done.")
-       end
-
-       # Execute `batch` and check for errors.
-       #
-       # Abort if `batch.execute` returns errors.
-       private fun do_batch(batch: NeoBatch) do
-               var errors = batch.execute
-               if not errors.is_empty then
-                       for e in errors do sys.stderr.write("{sys.program_name}: {e}\n")
-                       exit(1)
-               end
+               sys.stdout.write "Saving {edges.length} edges..."
+               store.save_all(edges)
        end
 end
 
@@ -199,15 +182,15 @@ class NeoDoxygenCommand
                opt_dest.default_value = default_dest
                option_context.add_option(opt_dest)
 
+               opt_help = new OptionBool("Show the help (this page).",
+                               "-h", "--help")
+               option_context.add_option(opt_help)
+
                var keys = new Array[String].from(sources.keys)
                opt_src_lang = new OptionEnum(keys,
                                "The programming language to assume when processing chunk in the declarations left as-is by Doxygen. Use `any` (the default) to disable any language-specific processing.",
                                keys.index_of("any"), "--src-lang")
                option_context.add_option(opt_src_lang)
-
-               opt_help = new OptionBool("Show the help (this page).",
-                               "-h", "--help")
-               option_context.add_option(opt_help)
        end
 
        # Start the application.
@@ -238,13 +221,18 @@ class NeoDoxygenCommand
                var dest = opt_dest.value
                var project_name = rest[0]
                var dir = rest[1]
-               var neo = new NeoDoxygenJob(new Neo4jClient(dest or else default_dest))
+               var neo = new NeoDoxygenJob(create_store(dest or else default_dest))
 
                neo.load_project(project_name, dir, source)
                neo.save
                return 0
        end
 
+       # Create an instance of `GraphStore` for the specified destination.
+       protected fun create_store(dest: String): GraphStore do
+               return new Neo4jStore(new Neo4jClient(dest))
+       end
+
        # Show the help.
        fun show_help do
                option_context.usage
diff --git a/contrib/neo_doxygen/src/tests/README.md b/contrib/neo_doxygen/src/tests/README.md
new file mode 100644 (file)
index 0000000..fbb4393
--- /dev/null
@@ -0,0 +1,7 @@
+Test scripts for `neo_doxygen`.
+
+The name of each test script is prefixed by `neo_doxygen_` to avoid name
+conflicts in `/tests/sav` and `/tests/out`. The expected output of each script
+is saved as a `*.res` file in `/tests/sav`.
+
+Note: All paths indicated here are relative to the root of the repository.
diff --git a/contrib/neo_doxygen/src/tests/neo_doxygen_dump.nit b/contrib/neo_doxygen/src/tests/neo_doxygen_dump.nit
new file mode 100644 (file)
index 0000000..326a030
--- /dev/null
@@ -0,0 +1,55 @@
+# 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.
+
+# A variant of the `neo_doxygen` program that produces a debugging output of the graph instead of saving it.
+#
+# Note: The `--dest` option is ignored.
+module tests::neo_doxygen_dump
+
+import tests
+import neo_doxygen
+
+redef class Sys
+       redef fun program_name do return "%PROGRAM_NAME%"
+end
+
+redef class NeoDoxygenJob
+       redef fun list_files(dir) do
+               var a = super.to_a
+               default_comparator.sort(a)
+               return a
+       end
+end
+
+redef class NeoDoxygenCommand
+       redef fun create_store(url) do return new DebugStore
+end
+
+class DebugStore
+       super GraphStore
+
+       redef fun has_node_label(name) do return false
+
+       redef fun save_all(neo_entities) do
+               print ""
+               for n in neo_entities do
+                       if n isa NeoEdge then
+                               var buffer = new RopeBuffer
+                               n.debug buffer
+                               print buffer
+                       end
+               end
+               print "---===DONE===---"
+       end
+end
diff --git a/contrib/neo_doxygen/src/tests/neo_doxygen_file_compound.nit b/contrib/neo_doxygen/src/tests/neo_doxygen_file_compound.nit
new file mode 100644 (file)
index 0000000..c654bd4
--- /dev/null
@@ -0,0 +1,47 @@
+# 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.
+
+import tests
+import model::module_compound
+
+var graph = new ProjectGraph("foo")
+var file = new FileCompound(graph)
+var file_2 = new FileCompound(graph)
+var bar_class = new ClassCompound(graph)
+var c_ns = new Namespace(graph)
+var buffer = new RopeBuffer
+
+file.full_name = "Bar.java"
+file.model_id = "_Bar_8java"
+file.declare_class("classa_b_bar", "a::b::Bar")
+file.declare_namespace("", "a::b")
+file.put_in_graph
+
+file_2.full_name = "Bar.java"
+file_2.model_id = "_Bar_8java_2"
+file_2.declare_namespace("namespacec", "c")
+file_2.declare_namespace("", "d")
+file_2.put_in_graph
+
+bar_class.model_id = "classa_b_bar"
+bar_class.full_name = "a::b::Bar"
+bar_class.put_in_graph
+
+c_ns.model_id = "namespacec"
+c_ns.full_name = "c"
+c_ns.put_in_graph
+
+graph.put_edges
+graph.debug buffer
+print buffer
diff --git a/contrib/neo_doxygen/src/tests/neo_doxygen_graph_empty_project.nit b/contrib/neo_doxygen/src/tests/neo_doxygen_graph_empty_project.nit
new file mode 100644 (file)
index 0000000..f011ae8
--- /dev/null
@@ -0,0 +1,22 @@
+# 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.
+
+import tests
+
+var graph = new ProjectGraph("foo")
+var buffer = new RopeBuffer
+
+graph.put_edges
+graph.debug buffer
+print buffer
diff --git a/contrib/neo_doxygen/src/tests/neo_doxygen_member_resolve_introducer.nit b/contrib/neo_doxygen/src/tests/neo_doxygen_member_resolve_introducer.nit
new file mode 100644 (file)
index 0000000..4909e9d
--- /dev/null
@@ -0,0 +1,34 @@
+# 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.
+
+import model::member
+
+# Copied from the documentation of `Member::resolve_introducer`.
+
+var g = new ProjectGraph("foo")
+var m1 = new Attribute(g)
+var m2 = new Attribute(g)
+var m3 = new Attribute(g)
+
+m1.model_id = "1"
+m1.put_in_graph
+m2.reimplement("1")
+m2.put_in_graph
+assert m1.resolve_introducer == m1.introducer
+assert m2.resolve_introducer == m1.introducer
+
+m3.model_id = "3"
+m3.reimplement("3")
+m3.put_in_graph
+assert m3.resolve_introducer == null
diff --git a/contrib/neo_doxygen/src/tests/tests.nit b/contrib/neo_doxygen/src/tests/tests.nit
new file mode 100644 (file)
index 0000000..797886b
--- /dev/null
@@ -0,0 +1,83 @@
+# 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.
+
+# Base module for tests related to `neo_doxygen`.
+module tests::tests
+
+import model::graph
+
+# Adds debugging output to graphs.
+redef class NeoGraph
+
+       # Append the debugging output of all relationships to the specified buffer.
+       fun debug(buffer: Buffer) do
+               buffer.append "# Graph\n"
+               for edge in all_edges do
+                       edge.debug buffer
+               end
+       end
+end
+
+# Adds debugging output to relationships.
+redef class NeoEdge
+
+       # Append the debugging output of this relationship to the specified buffer.
+       #
+       # Append the relationship type, the properties, and the debugging output of
+       # both extremities.
+       fun debug(buffer: Buffer) do
+               var rel_type = self.rel_type or else "?"
+               buffer.append "Edge\n"
+               buffer.append "=type={rel_type.length}:{rel_type}\n"
+               buffer.append "=properties=JsonObject({properties.length}):\n"
+               buffer.append properties.to_json
+               buffer.append "\n----\n=from="
+               from.debug buffer
+               buffer.append "----\n=to="
+               to.debug buffer
+               buffer.append "\n"
+       end
+end
+
+# Adds debugging output to nodes.
+redef class NeoNode
+
+       # Append the debugging output of this node to the specified buffer.
+       #
+       # Append the labels and the properties.
+       fun debug(buffer: Buffer) do
+               buffer.append "Node\n"
+               buffer.append "=labels=Array({labels.length}):\n"
+               for lab in labels do buffer.append "{lab.length}:{lab}\n"
+               buffer.append "=properties=JsonObject({properties.length}):\n"
+               buffer.append properties.to_json
+               buffer.append "\n"
+       end
+end
+
+# Adds debugging output to entities.
+redef class Entity
+
+       # Append the debugging output of this entity to the specified buffer.
+       #
+       # Append the `model_id`, the labels and the properties.
+       redef fun debug(buffer: Buffer) do
+               buffer.append "Entity#{model_id.length}:{model_id}\n"
+               buffer.append "=labels=Array({labels.length}):\n"
+               for lab in labels do buffer.append "{lab.length}:{lab}\n"
+               buffer.append "=properties=JsonObject({properties.length}):\n"
+               buffer.append properties.to_json
+               buffer.append "\n"
+       end
+end
diff --git a/contrib/neo_doxygen/tests/.gitattributes b/contrib/neo_doxygen/tests/.gitattributes
new file mode 100644 (file)
index 0000000..ab22f42
--- /dev/null
@@ -0,0 +1 @@
+/*/xml/*       -diff
diff --git a/contrib/neo_doxygen/tests/Makefile b/contrib/neo_doxygen/tests/Makefile
new file mode 100644 (file)
index 0000000..d90195d
--- /dev/null
@@ -0,0 +1,29 @@
+# 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.
+
+# All the dummy projects.
+PROJECTS=$(dir $(wildcard ./*/Doxyfile))
+
+.PHONY: xml bootstrap
+
+# Regenerate the XML documents.
+xml: bootstrap
+       for p in $(PROJECTS); do $(MAKE) -C "$$p" xml || exit; done
+
+# Generate the Makefiles in the sub-directories.
+bootstrap:
+       for p in $(PROJECTS); do { \
+               echo '# FILE GENERATED BY ../Makefile'"\n" > "$$p/Makefile" || exit; \
+               cat doxyproject.mk >> "$$p/Makefile" || exit; \
+       } ; done
diff --git a/contrib/neo_doxygen/tests/README.md b/contrib/neo_doxygen/tests/README.md
new file mode 100644 (file)
index 0000000..6201ecd
--- /dev/null
@@ -0,0 +1,4 @@
+Data files for tests.
+
+For test scripts, see `../src/tests`. To regenerate the XML documents, run
+`make`.
diff --git a/contrib/neo_doxygen/tests/doxyproject.mk b/contrib/neo_doxygen/tests/doxyproject.mk
new file mode 100644 (file)
index 0000000..b6ce8e0
--- /dev/null
@@ -0,0 +1,35 @@
+# 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.
+
+.PHONY: clean doxygen strip_paths xml
+
+# Regenerate the XML documents.
+xml: strip_paths
+
+clean:
+       rm -rf xml
+
+doxygen: clean
+       doxygen Doxyfile
+
+# Get rid of the absolute paths in the generated files.
+#
+# Doxygen ignores the `STRIP_FROM_PATH` setting when generating a XML output.
+# So, we have to replace the paths manually in order to get reproducible
+# results.
+#
+# WARNING: FOR USE ON TEST DATA ONLY.
+strip_paths: doxygen
+       . ../../sh-lib/more_sed.sh; \
+       replace `readlink -f -- ./src` '%SOURCE_DIRECTORY%' xml/*.xml
diff --git a/contrib/neo_doxygen/tests/empty-project/Doxyfile b/contrib/neo_doxygen/tests/empty-project/Doxyfile
new file mode 100644 (file)
index 0000000..bd06324
--- /dev/null
@@ -0,0 +1,2381 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "Test Project"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = YES
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = src
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.idl \
+                         *.ddl \
+                         *.odl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.cs \
+                         *.d \
+                         *.php \
+                         *.php4 \
+                         *.php5 \
+                         *.phtml \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.f90 \
+                         *.f \
+                         *.for \
+                         *.tcl \
+                         *.vhd \
+                         *.vhdl \
+                         *.ucf \
+                         *.qsf \
+                         *.as \
+                         *.js
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = NO
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = YES
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH      =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
diff --git a/contrib/neo_doxygen/tests/empty-project/README.md b/contrib/neo_doxygen/tests/empty-project/README.md
new file mode 100644 (file)
index 0000000..85bf9fe
--- /dev/null
@@ -0,0 +1,5 @@
+This directory contains an empty project for testing purposes.
+
+To regenerate the XML output located in `xml`, run `make`. If the `Makefile`
+does not exists, you can regenerate it by running `make bootstrap` in the parent
+directory.
diff --git a/contrib/neo_doxygen/tests/empty-project/src/org/example/foo/void.txt b/contrib/neo_doxygen/tests/empty-project/src/org/example/foo/void.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/contrib/neo_doxygen/tests/empty-project/xml/combine.xslt b/contrib/neo_doxygen/tests/empty-project/xml/combine.xslt
new file mode 100644 (file)
index 0000000..c148ee4
--- /dev/null
@@ -0,0 +1,15 @@
+<!-- XSLT script to combine the generated output into a single file. 
+     If you have xsltproc you could use:
+     xsltproc combine.xslt index.xml >all.xml
+-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+  <xsl:output method="xml" version="1.0" indent="no" standalone="yes" />
+  <xsl:template match="/">
+    <doxygen version="{doxygenindex/@version}">
+      <!-- Load all doxgen generated xml files -->
+      <xsl:for-each select="doxygenindex/compound">
+        <xsl:copy-of select="document( concat( @refid, '.xml' ) )/doxygen/*" />
+      </xsl:for-each>
+    </doxygen>
+  </xsl:template>
+</xsl:stylesheet>
diff --git a/contrib/neo_doxygen/tests/empty-project/xml/compound.xsd b/contrib/neo_doxygen/tests/empty-project/xml/compound.xsd
new file mode 100644 (file)
index 0000000..86740f4
--- /dev/null
@@ -0,0 +1,1092 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <xsd:element name="doxygen" type="DoxygenType"/>
+
+  <!-- Complex types -->
+
+  <xsd:complexType name="DoxygenType">
+    <xsd:sequence maxOccurs="unbounded">
+      <xsd:element name="compounddef" type="compounddefType" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="version" type="DoxVersionNumber" use="required" />
+  </xsd:complexType>
+
+  <xsd:complexType name="compounddefType">
+    <xsd:sequence>
+      <xsd:element name="compoundname" type="xsd:string"/>
+      <xsd:element name="title" type="xsd:string" minOccurs="0" />
+      <xsd:element name="basecompoundref" type="compoundRefType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="derivedcompoundref" type="compoundRefType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="includes" type="incType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="includedby" type="incType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="incdepgraph" type="graphType" minOccurs="0" />
+      <xsd:element name="invincdepgraph" type="graphType" minOccurs="0" />
+      <xsd:element name="innerdir" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="innerfile" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="innerclass" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="innernamespace" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="innerpage" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="innergroup" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="templateparamlist" type="templateparamlistType" minOccurs="0" />
+      <xsd:element name="sectiondef" type="sectiondefType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="briefdescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="detaileddescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="inheritancegraph" type="graphType" minOccurs="0" />
+      <xsd:element name="collaborationgraph" type="graphType" minOccurs="0" />
+      <xsd:element name="programlisting" type="listingType" minOccurs="0" />
+      <xsd:element name="location" type="locationType" minOccurs="0" />
+      <xsd:element name="listofallmembers" type="listofallmembersType" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+    <xsd:attribute name="kind" type="DoxCompoundKind" />
+    <xsd:attribute name="prot" type="DoxProtectionKind" />
+    <xsd:attribute name="final" type="DoxBool" use="optional"/>
+    <xsd:attribute name="sealed" type="DoxBool" use="optional"/>
+    <xsd:attribute name="abstract" type="DoxBool" use="optional"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="listofallmembersType">
+    <xsd:sequence>
+      <xsd:element name="member" type="memberRefType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="memberRefType">
+    <xsd:sequence>
+      <xsd:element name="scope" />
+      <xsd:element name="name" />
+    </xsd:sequence>
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="prot" type="DoxProtectionKind" />
+    <xsd:attribute name="virt" type="DoxVirtualKind" />
+    <xsd:attribute name="ambiguityscope" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="compoundRefType">
+    <xsd:simpleContent>
+      <xsd:extension base="xsd:string">
+        <xsd:attribute name="refid" type="xsd:string" use="optional" />
+        <xsd:attribute name="prot" type="DoxProtectionKind" />
+        <xsd:attribute name="virt" type="DoxVirtualKind" />
+      </xsd:extension>
+    </xsd:simpleContent>
+  </xsd:complexType>
+
+  <xsd:complexType name="reimplementType">
+    <xsd:simpleContent>
+      <xsd:extension base="xsd:string">
+        <xsd:attribute name="refid" type="xsd:string" />
+      </xsd:extension>
+    </xsd:simpleContent>
+  </xsd:complexType>
+
+  <xsd:complexType name="incType">
+    <xsd:simpleContent>
+      <xsd:extension base="xsd:string">
+        <xsd:attribute name="refid" type="xsd:string" />
+        <xsd:attribute name="local" type="DoxBool" />
+      </xsd:extension>
+    </xsd:simpleContent>
+  </xsd:complexType>
+
+  <xsd:complexType name="refType">
+    <xsd:simpleContent>
+      <xsd:extension base="xsd:string">
+        <xsd:attribute name="refid" type="xsd:string" />
+        <xsd:attribute name="prot" type="DoxProtectionKind" use="optional"/>
+      </xsd:extension>
+    </xsd:simpleContent>
+  </xsd:complexType>
+
+  <xsd:complexType name="refTextType">
+    <xsd:simpleContent>
+      <xsd:extension base="xsd:string">
+       <xsd:attribute name="refid" type="xsd:string" />
+       <xsd:attribute name="kindref" type="DoxRefKind" />
+       <xsd:attribute name="external" type="xsd:string" use="optional"/>
+       <xsd:attribute name="tooltip" type="xsd:string" use="optional"/>
+      </xsd:extension>
+    </xsd:simpleContent>
+  </xsd:complexType>
+
+  <xsd:complexType name="sectiondefType">
+    <xsd:sequence>
+      <xsd:element name="header" type="xsd:string" minOccurs="0" />
+      <xsd:element name="description" type="descriptionType" minOccurs="0" />
+      <xsd:element name="memberdef" type="memberdefType" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="kind" type="DoxSectionKind" />
+  </xsd:complexType>
+
+  <xsd:complexType name="memberdefType">
+    <xsd:sequence>
+      <xsd:element name="templateparamlist" type="templateparamlistType" minOccurs="0" />
+      <xsd:element name="type" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="definition" minOccurs="0" />
+      <xsd:element name="argsstring" minOccurs="0" />
+      <xsd:element name="name" />
+      <xsd:element name="read" minOccurs="0" />
+      <xsd:element name="write" minOccurs="0" />
+      <xsd:element name="bitfield" minOccurs="0" />
+      <xsd:element name="reimplements" type="reimplementType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="reimplementedby" type="reimplementType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="param" type="paramType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="enumvalue" type="enumvalueType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="initializer" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="exceptions" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="briefdescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="detaileddescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="inbodydescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="location" type="locationType" />
+      <xsd:element name="references" type="referenceType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="referencedby" type="referenceType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="kind" type="DoxMemberKind" />
+    <xsd:attribute name="id" type="xsd:string" />
+    <xsd:attribute name="prot" type="DoxProtectionKind" />
+    <xsd:attribute name="static" type="DoxBool" />
+    <xsd:attribute name="const" type="DoxBool" use="optional"/>
+    <xsd:attribute name="explicit" type="DoxBool" use="optional"/>
+    <xsd:attribute name="inline" type="DoxBool" use="optional"/>
+    <xsd:attribute name="virt" type="DoxVirtualKind" use="optional"/>
+    <xsd:attribute name="volatile" type="DoxBool" use="optional"/>
+    <xsd:attribute name="mutable" type="DoxBool" use="optional"/>
+    <!-- Qt property -->
+    <xsd:attribute name="readable" type="DoxBool" use="optional"/>
+    <xsd:attribute name="writable" type="DoxBool" use="optional"/>
+    <!-- C++/CLI variable -->
+    <xsd:attribute name="initonly" type="DoxBool" use="optional"/>
+    <!-- C++/CLI and C# property -->
+    <xsd:attribute name="settable" type="DoxBool" use="optional"/>
+    <xsd:attribute name="gettable" type="DoxBool" use="optional"/>
+    <!-- C++/CLI function -->
+    <xsd:attribute name="final" type="DoxBool" use="optional"/>
+    <xsd:attribute name="sealed" type="DoxBool" use="optional"/>
+    <xsd:attribute name="new" type="DoxBool" use="optional"/>
+    <!-- C++/CLI event -->
+    <xsd:attribute name="add" type="DoxBool" use="optional"/>
+    <xsd:attribute name="remove" type="DoxBool" use="optional"/>
+    <xsd:attribute name="raise" type="DoxBool" use="optional"/>
+    <!-- Objective-C 2.0 protocol method -->
+    <xsd:attribute name="optional" type="DoxBool" use="optional"/>
+    <xsd:attribute name="required" type="DoxBool" use="optional"/>
+    <!-- Objective-C 2.0 property accessor -->
+    <xsd:attribute name="accessor" type="DoxAccessor" use="optional"/>
+    <!-- UNO IDL -->
+    <xsd:attribute name="attribute" type="DoxBool" use="optional"/>
+    <xsd:attribute name="property" type="DoxBool" use="optional"/>
+    <xsd:attribute name="readonly" type="DoxBool" use="optional"/>
+    <xsd:attribute name="bound" type="DoxBool" use="optional"/>
+    <xsd:attribute name="removable" type="DoxBool" use="optional"/>
+    <xsd:attribute name="contrained" type="DoxBool" use="optional"/>
+    <xsd:attribute name="transient" type="DoxBool" use="optional"/>
+    <xsd:attribute name="maybevoid" type="DoxBool" use="optional"/>
+    <xsd:attribute name="maybedefault" type="DoxBool" use="optional"/>
+    <xsd:attribute name="maybeambiguous" type="DoxBool" use="optional"/>
+
+  </xsd:complexType>
+
+  <xsd:complexType name="descriptionType" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="title" type="xsd:string" minOccurs="0"/>          
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect1" type="docSect1Type" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalType" minOccurs="0" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="enumvalueType" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="name" />
+      <xsd:element name="initializer" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="briefdescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="detaileddescription" type="descriptionType" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+    <xsd:attribute name="prot" type="DoxProtectionKind" />
+  </xsd:complexType>
+
+  <xsd:complexType name="templateparamlistType">
+    <xsd:sequence>
+      <xsd:element name="param" type="paramType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="paramType">
+    <xsd:sequence>
+      <xsd:element name="type" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="declname" minOccurs="0" />
+      <xsd:element name="defname" minOccurs="0" />
+      <xsd:element name="array" minOccurs="0" />
+      <xsd:element name="defval" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="briefdescription" type="descriptionType" minOccurs="0" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="linkedTextType" mixed="true">
+    <xsd:sequence>
+    <xsd:element name="ref" type="refTextType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="graphType">
+    <xsd:sequence>
+      <xsd:element name="node" type="nodeType" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="nodeType">
+    <xsd:sequence>
+      <xsd:element name="label" />
+      <xsd:element name="link" type="linkType" minOccurs="0" />
+      <xsd:element name="childnode" type="childnodeType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="childnodeType">
+    <xsd:sequence>
+      <xsd:element name="edgelabel" minOccurs="0" maxOccurs="unbounded"/>
+    </xsd:sequence>
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="relation" type="DoxGraphRelation" />
+  </xsd:complexType>
+
+  <xsd:complexType name="linkType">
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="external" type="xsd:string" use="optional"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="listingType">
+    <xsd:sequence>
+      <xsd:element name="codeline" type="codelineType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="codelineType">
+    <xsd:sequence>
+      <xsd:element name="highlight" type="highlightType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="lineno" type="xsd:integer" />
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="refkind" type="DoxRefKind" />
+    <xsd:attribute name="external" type="DoxBool" />
+  </xsd:complexType>
+
+  <xsd:complexType name="highlightType" mixed="true">
+    <xsd:choice minOccurs="0" maxOccurs="unbounded">
+      <xsd:element name="sp" />
+      <xsd:element name="ref" type="refTextType" />
+    </xsd:choice>
+    <xsd:attribute name="class" type="DoxHighlightClass" />
+  </xsd:complexType>
+
+  <xsd:complexType name="referenceType" mixed="true">
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="compoundref" type="xsd:string" use="optional" />
+    <xsd:attribute name="startline" type="xsd:integer" />
+    <xsd:attribute name="endline" type="xsd:integer" />
+  </xsd:complexType>
+
+  <xsd:complexType name="locationType">
+    <xsd:attribute name="file" type="xsd:string" />
+    <xsd:attribute name="line" type="xsd:integer" />
+    <xsd:attribute name="column" type="xsd:integer" use="optional"/>
+    <xsd:attribute name="bodyfile" type="xsd:string" />
+    <xsd:attribute name="bodystart" type="xsd:integer" />
+    <xsd:attribute name="bodyend" type="xsd:integer" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docSect1Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="title" type="xsd:string" />       
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect2" type="docSect2Type" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalS1Type" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docSect2Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="title" type="xsd:string" />       
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect3" type="docSect3Type" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalS2Type" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docSect3Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="title" type="xsd:string" />       
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect4" type="docSect4Type" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalS3Type" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docSect4Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="title" type="xsd:string" />       
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalS4Type" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docInternalType" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="para"  type="docParaType"  minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect1" type="docSect1Type" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docInternalS1Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="para"  type="docParaType"  minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect2" type="docSect2Type" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docInternalS2Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="para"  type="docParaType"  minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect3" type="docSect3Type" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docInternalS3Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="para"  type="docParaType"  minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect3" type="docSect4Type" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docInternalS4Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="para"  type="docParaType"  minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+  <xsd:group name="docTitleCmdGroup">
+    <xsd:choice>
+      <xsd:element name="ulink" type="docURLLink" />
+      <xsd:element name="bold" type="docMarkupType" />
+      <xsd:element name="emphasis" type="docMarkupType" />
+      <xsd:element name="computeroutput" type="docMarkupType" />
+      <xsd:element name="subscript" type="docMarkupType" />
+      <xsd:element name="superscript" type="docMarkupType" />
+      <xsd:element name="center" type="docMarkupType" />
+      <xsd:element name="small" type="docMarkupType" />
+      <xsd:element name="htmlonly" type="xsd:string" />
+      <xsd:element name="manonly" type="xsd:string" />
+      <xsd:element name="xmlonly" type="xsd:string" />
+      <xsd:element name="rtfonly" type="xsd:string" />
+      <xsd:element name="latexonly" type="xsd:string" />
+      <xsd:element name="dot" type="xsd:string" />
+      <xsd:element name="plantuml" type="xsd:string" />
+      <xsd:element name="anchor" type="docAnchorType" />
+      <xsd:element name="formula" type="docFormulaType" />
+      <xsd:element name="ref" type="docRefTextType" />
+      <xsd:element name="nonbreakablespace" type="docEmptyType" />
+      <xsd:element name="iexcl" type="docEmptyType" />
+      <xsd:element name="cent" type="docEmptyType" />
+      <xsd:element name="pound" type="docEmptyType" />
+      <xsd:element name="curren" type="docEmptyType" />
+      <xsd:element name="yen" type="docEmptyType" />
+      <xsd:element name="brvbar" type="docEmptyType" />
+      <xsd:element name="sect" type="docEmptyType" />
+      <xsd:element name="umlaut" type="docEmptyType" />
+      <xsd:element name="copy" type="docEmptyType" />
+      <xsd:element name="ordf" type="docEmptyType" />
+      <xsd:element name="laquo" type="docEmptyType" />
+      <xsd:element name="not" type="docEmptyType" />
+      <xsd:element name="shy" type="docEmptyType" />
+      <xsd:element name="registered" type="docEmptyType" />
+      <xsd:element name="macr" type="docEmptyType" />
+      <xsd:element name="deg" type="docEmptyType" />
+      <xsd:element name="plusmn" type="docEmptyType" />
+      <xsd:element name="sup2" type="docEmptyType" />
+      <xsd:element name="sup3" type="docEmptyType" />
+      <xsd:element name="acute" type="docEmptyType" />
+      <xsd:element name="micro" type="docEmptyType" />
+      <xsd:element name="para" type="docEmptyType" />
+      <xsd:element name="middot" type="docEmptyType" />
+      <xsd:element name="cedil" type="docEmptyType" />
+      <xsd:element name="sup1" type="docEmptyType" />
+      <xsd:element name="ordm" type="docEmptyType" />
+      <xsd:element name="raquo" type="docEmptyType" />
+      <xsd:element name="frac14" type="docEmptyType" />
+      <xsd:element name="frac12" type="docEmptyType" />
+      <xsd:element name="frac34" type="docEmptyType" />
+      <xsd:element name="iquest" type="docEmptyType" />
+      <xsd:element name="Agrave" type="docEmptyType" />
+      <xsd:element name="Aacute" type="docEmptyType" />
+      <xsd:element name="Acirc" type="docEmptyType" />
+      <xsd:element name="Atilde" type="docEmptyType" />
+      <xsd:element name="Aumlaut" type="docEmptyType" />
+      <xsd:element name="Aring" type="docEmptyType" />
+      <xsd:element name="AElig" type="docEmptyType" />
+      <xsd:element name="Ccedil" type="docEmptyType" />
+      <xsd:element name="Egrave" type="docEmptyType" />
+      <xsd:element name="Eacute" type="docEmptyType" />
+      <xsd:element name="Ecirc" type="docEmptyType" />
+      <xsd:element name="Eumlaut" type="docEmptyType" />
+      <xsd:element name="Igrave" type="docEmptyType" />
+      <xsd:element name="Iacute" type="docEmptyType" />
+      <xsd:element name="Icirc" type="docEmptyType" />
+      <xsd:element name="Iumlaut" type="docEmptyType" />
+      <xsd:element name="ETH" type="docEmptyType" />
+      <xsd:element name="Ntilde" type="docEmptyType" />
+      <xsd:element name="Ograve" type="docEmptyType" />
+      <xsd:element name="Oacute" type="docEmptyType" />
+      <xsd:element name="Ocirc" type="docEmptyType" />
+      <xsd:element name="Otilde" type="docEmptyType" />
+      <xsd:element name="Oumlaut" type="docEmptyType" />
+      <xsd:element name="times" type="docEmptyType" />
+      <xsd:element name="Oslash" type="docEmptyType" />
+      <xsd:element name="Ugrave" type="docEmptyType" />
+      <xsd:element name="Uacute" type="docEmptyType" />
+      <xsd:element name="Ucirc" type="docEmptyType" />
+      <xsd:element name="Uumlaut" type="docEmptyType" />
+      <xsd:element name="Yacute" type="docEmptyType" />
+      <xsd:element name="THORN" type="docEmptyType" />
+      <xsd:element name="szlig" type="docEmptyType" />
+      <xsd:element name="agrave" type="docEmptyType" />
+      <xsd:element name="aacute" type="docEmptyType" />
+      <xsd:element name="acirc" type="docEmptyType" />
+      <xsd:element name="atilde" type="docEmptyType" />
+      <xsd:element name="aumlaut" type="docEmptyType" />
+      <xsd:element name="aring" type="docEmptyType" />
+      <xsd:element name="aelig" type="docEmptyType" />
+      <xsd:element name="ccedil" type="docEmptyType" />
+      <xsd:element name="egrave" type="docEmptyType" />
+      <xsd:element name="eacute" type="docEmptyType" />
+      <xsd:element name="ecirc" type="docEmptyType" />
+      <xsd:element name="eumlaut" type="docEmptyType" />
+      <xsd:element name="igrave" type="docEmptyType" />
+      <xsd:element name="iacute" type="docEmptyType" />
+      <xsd:element name="icirc" type="docEmptyType" />
+      <xsd:element name="iumlaut" type="docEmptyType" />
+      <xsd:element name="eth" type="docEmptyType" />
+      <xsd:element name="ntilde" type="docEmptyType" />
+      <xsd:element name="ograve" type="docEmptyType" />
+      <xsd:element name="oacute" type="docEmptyType" />
+      <xsd:element name="ocirc" type="docEmptyType" />
+      <xsd:element name="otilde" type="docEmptyType" />
+      <xsd:element name="oumlaut" type="docEmptyType" />
+      <xsd:element name="divide" type="docEmptyType" />
+      <xsd:element name="oslash" type="docEmptyType" />
+      <xsd:element name="ugrave" type="docEmptyType" />
+      <xsd:element name="uacute" type="docEmptyType" />
+      <xsd:element name="ucirc" type="docEmptyType" />
+      <xsd:element name="uumlaut" type="docEmptyType" />
+      <xsd:element name="yacute" type="docEmptyType" />
+      <xsd:element name="thorn" type="docEmptyType" />
+      <xsd:element name="yumlaut" type="docEmptyType" />
+      <xsd:element name="fnof" type="docEmptyType" />
+      <xsd:element name="Alpha" type="docEmptyType" />
+      <xsd:element name="Beta" type="docEmptyType" />
+      <xsd:element name="Gamma" type="docEmptyType" />
+      <xsd:element name="Delta" type="docEmptyType" />
+      <xsd:element name="Epsilon" type="docEmptyType" />
+      <xsd:element name="Zeta" type="docEmptyType" />
+      <xsd:element name="Eta" type="docEmptyType" />
+      <xsd:element name="Theta" type="docEmptyType" />
+      <xsd:element name="Iota" type="docEmptyType" />
+      <xsd:element name="Kappa" type="docEmptyType" />
+      <xsd:element name="Lambda" type="docEmptyType" />
+      <xsd:element name="Mu" type="docEmptyType" />
+      <xsd:element name="Nu" type="docEmptyType" />
+      <xsd:element name="Xi" type="docEmptyType" />
+      <xsd:element name="Omicron" type="docEmptyType" />
+      <xsd:element name="Pi" type="docEmptyType" />
+      <xsd:element name="Rho" type="docEmptyType" />
+      <xsd:element name="Sigma" type="docEmptyType" />
+      <xsd:element name="Tau" type="docEmptyType" />
+      <xsd:element name="Upsilon" type="docEmptyType" />
+      <xsd:element name="Phi" type="docEmptyType" />
+      <xsd:element name="Chi" type="docEmptyType" />
+      <xsd:element name="Psi" type="docEmptyType" />
+      <xsd:element name="Omega" type="docEmptyType" />
+      <xsd:element name="alpha" type="docEmptyType" />
+      <xsd:element name="beta" type="docEmptyType" />
+      <xsd:element name="gamma" type="docEmptyType" />
+      <xsd:element name="delta" type="docEmptyType" />
+      <xsd:element name="epsilon" type="docEmptyType" />
+      <xsd:element name="zeta" type="docEmptyType" />
+      <xsd:element name="eta" type="docEmptyType" />
+      <xsd:element name="theta" type="docEmptyType" />
+      <xsd:element name="iota" type="docEmptyType" />
+      <xsd:element name="kappa" type="docEmptyType" />
+      <xsd:element name="lambda" type="docEmptyType" />
+      <xsd:element name="mu" type="docEmptyType" />
+      <xsd:element name="nu" type="docEmptyType" />
+      <xsd:element name="xi" type="docEmptyType" />
+      <xsd:element name="omicron" type="docEmptyType" />
+      <xsd:element name="pi" type="docEmptyType" />
+      <xsd:element name="rho" type="docEmptyType" />
+      <xsd:element name="sigmaf" type="docEmptyType" />
+      <xsd:element name="sigma" type="docEmptyType" />
+      <xsd:element name="tau" type="docEmptyType" />
+      <xsd:element name="upsilon" type="docEmptyType" />
+      <xsd:element name="phi" type="docEmptyType" />
+      <xsd:element name="chi" type="docEmptyType" />
+      <xsd:element name="psi" type="docEmptyType" />
+      <xsd:element name="omega" type="docEmptyType" />
+      <xsd:element name="thetasym" type="docEmptyType" />
+      <xsd:element name="upsih" type="docEmptyType" />
+      <xsd:element name="piv" type="docEmptyType" />
+      <xsd:element name="bull" type="docEmptyType" />
+      <xsd:element name="hellip" type="docEmptyType" />
+      <xsd:element name="prime" type="docEmptyType" />
+      <xsd:element name="Prime" type="docEmptyType" />
+      <xsd:element name="oline" type="docEmptyType" />
+      <xsd:element name="frasl" type="docEmptyType" />
+      <xsd:element name="weierp" type="docEmptyType" />
+      <xsd:element name="image" type="docEmptyType" />
+      <xsd:element name="real" type="docEmptyType" />
+      <xsd:element name="trademark" type="docEmptyType" />
+      <xsd:element name="alefsym" type="docEmptyType" />
+      <xsd:element name="larr" type="docEmptyType" />
+      <xsd:element name="uarr" type="docEmptyType" />
+      <xsd:element name="rarr" type="docEmptyType" />
+      <xsd:element name="darr" type="docEmptyType" />
+      <xsd:element name="harr" type="docEmptyType" />
+      <xsd:element name="crarr" type="docEmptyType" />
+      <xsd:element name="lArr" type="docEmptyType" />
+      <xsd:element name="uArr" type="docEmptyType" />
+      <xsd:element name="rArr" type="docEmptyType" />
+      <xsd:element name="dArr" type="docEmptyType" />
+      <xsd:element name="hArr" type="docEmptyType" />
+      <xsd:element name="forall" type="docEmptyType" />
+      <xsd:element name="part" type="docEmptyType" />
+      <xsd:element name="exist" type="docEmptyType" />
+      <xsd:element name="empty" type="docEmptyType" />
+      <xsd:element name="nabla" type="docEmptyType" />
+      <xsd:element name="isin" type="docEmptyType" />
+      <xsd:element name="notin" type="docEmptyType" />
+      <xsd:element name="ni" type="docEmptyType" />
+      <xsd:element name="prod" type="docEmptyType" />
+      <xsd:element name="sum" type="docEmptyType" />
+      <xsd:element name="minus" type="docEmptyType" />
+      <xsd:element name="lowast" type="docEmptyType" />
+      <xsd:element name="radic" type="docEmptyType" />
+      <xsd:element name="prop" type="docEmptyType" />
+      <xsd:element name="infin" type="docEmptyType" />
+      <xsd:element name="ang" type="docEmptyType" />
+      <xsd:element name="and" type="docEmptyType" />
+      <xsd:element name="or" type="docEmptyType" />
+      <xsd:element name="cap" type="docEmptyType" />
+      <xsd:element name="cup" type="docEmptyType" />
+      <xsd:element name="int" type="docEmptyType" />
+      <xsd:element name="there4" type="docEmptyType" />
+      <xsd:element name="sim" type="docEmptyType" />
+      <xsd:element name="cong" type="docEmptyType" />
+      <xsd:element name="asymp" type="docEmptyType" />
+      <xsd:element name="ne" type="docEmptyType" />
+      <xsd:element name="equiv" type="docEmptyType" />
+      <xsd:element name="le" type="docEmptyType" />
+      <xsd:element name="ge" type="docEmptyType" />
+      <xsd:element name="sub" type="docEmptyType" />
+      <xsd:element name="sup" type="docEmptyType" />
+      <xsd:element name="nsub" type="docEmptyType" />
+      <xsd:element name="sube" type="docEmptyType" />
+      <xsd:element name="supe" type="docEmptyType" />
+      <xsd:element name="oplus" type="docEmptyType" />
+      <xsd:element name="otimes" type="docEmptyType" />
+      <xsd:element name="perp" type="docEmptyType" />
+      <xsd:element name="sdot" type="docEmptyType" />
+      <xsd:element name="lceil" type="docEmptyType" />
+      <xsd:element name="rceil" type="docEmptyType" />
+      <xsd:element name="lfloor" type="docEmptyType" />
+      <xsd:element name="rfloor" type="docEmptyType" />
+      <xsd:element name="lang" type="docEmptyType" />
+      <xsd:element name="rang" type="docEmptyType" />
+      <xsd:element name="loz" type="docEmptyType" />
+      <xsd:element name="spades" type="docEmptyType" />
+      <xsd:element name="clubs" type="docEmptyType" />
+      <xsd:element name="hearts" type="docEmptyType" />
+      <xsd:element name="diams" type="docEmptyType" />
+      <xsd:element name="OElig" type="docEmptyType" />
+      <xsd:element name="oelig" type="docEmptyType" />
+      <xsd:element name="Scaron" type="docEmptyType" />
+      <xsd:element name="scaron" type="docEmptyType" />
+      <xsd:element name="Yumlaut" type="docEmptyType" />
+      <xsd:element name="circ" type="docEmptyType" />
+      <xsd:element name="tilde" type="docEmptyType" />
+      <xsd:element name="ensp" type="docEmptyType" />
+      <xsd:element name="emsp" type="docEmptyType" />
+      <xsd:element name="thinsp" type="docEmptyType" />
+      <xsd:element name="zwnj" type="docEmptyType" />
+      <xsd:element name="zwj" type="docEmptyType" />
+      <xsd:element name="lrm" type="docEmptyType" />
+      <xsd:element name="rlm" type="docEmptyType" />
+      <xsd:element name="ndash" type="docEmptyType" />
+      <xsd:element name="mdash" type="docEmptyType" />
+      <xsd:element name="lsquo" type="docEmptyType" />
+      <xsd:element name="rsquo" type="docEmptyType" />
+      <xsd:element name="sbquo" type="docEmptyType" />
+      <xsd:element name="ldquo" type="docEmptyType" />
+      <xsd:element name="rdquo" type="docEmptyType" />
+      <xsd:element name="bdquo" type="docEmptyType" />
+      <xsd:element name="dagger" type="docEmptyType" />
+      <xsd:element name="Dagger" type="docEmptyType" />
+      <xsd:element name="permil" type="docEmptyType" />
+      <xsd:element name="lsaquo" type="docEmptyType" />
+      <xsd:element name="rsaquo" type="docEmptyType" />
+      <xsd:element name="euro" type="docEmptyType" />
+      <xsd:element name="trademark" type="docEmptyType" />
+    </xsd:choice>
+  </xsd:group>
+
+  <xsd:complexType name="docTitleType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+  </xsd:complexType>
+
+  <xsd:group name="docCmdGroup">
+    <xsd:choice>
+      <xsd:group ref="docTitleCmdGroup"/>
+      <xsd:element name="linebreak" type="docEmptyType" />
+      <xsd:element name="hruler" type="docEmptyType" />
+      <xsd:element name="preformatted" type="docMarkupType" />
+      <xsd:element name="programlisting" type="listingType" />
+      <xsd:element name="verbatim" type="xsd:string" />
+      <xsd:element name="indexentry" type="docIndexEntryType" />
+      <xsd:element name="orderedlist" type="docListType" />
+      <xsd:element name="itemizedlist" type="docListType" />
+      <xsd:element name="simplesect" type="docSimpleSectType" />
+      <xsd:element name="title" type="docTitleType" />
+      <xsd:element name="variablelist" type="docVariableListType" />
+      <xsd:element name="table" type="docTableType" />
+      <xsd:element name="heading" type="docHeadingType" />
+      <xsd:element name="image" type="docImageType" />
+      <xsd:element name="dotfile" type="docFileType" />
+      <xsd:element name="mscfile" type="docFileType" />
+      <xsd:element name="diafile" type="docFileType" />
+      <xsd:element name="toclist" type="docTocListType" />
+      <xsd:element name="language" type="docLanguageType" />
+      <xsd:element name="parameterlist" type="docParamListType" />
+      <xsd:element name="xrefsect" type="docXRefSectType" />
+      <xsd:element name="copydoc" type="docCopyType" />
+      <xsd:element name="blockquote" type="docBlockQuoteType" />
+      <xsd:element name="parblock" type="docParBlockType" />
+    </xsd:choice>
+  </xsd:group>
+
+  <xsd:complexType name="docParaType" mixed="true">
+    <xsd:group ref="docCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docMarkupType" mixed="true">
+    <xsd:group ref="docCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docURLLink" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="url" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docAnchorType" mixed="true">
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docFormulaType" mixed="true">
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docIndexEntryType">
+    <xsd:sequence>
+      <xsd:element name="primaryie" type="xsd:string" />
+      <xsd:element name="secondaryie" type="xsd:string" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docListType">
+    <xsd:sequence>
+      <xsd:element name="listitem" type="docListItemType" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docListItemType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docSimpleSectType">
+    <xsd:sequence>
+      <xsd:element name="title" type="docTitleType" minOccurs="0" />
+      <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+        <xsd:element name="para" type="docParaType" minOccurs="1" maxOccurs="unbounded" />
+      </xsd:sequence>
+    </xsd:sequence>
+    <xsd:attribute name="kind" type="DoxSimpleSectKind" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docVarListEntryType">
+    <xsd:sequence>
+      <xsd:element name="term" type="docTitleType" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:group name="docVariableListGroup">
+    <xsd:sequence>
+      <xsd:element name="varlistentry" type="docVarListEntryType" />
+      <xsd:element name="listitem" type="docListItemType" />
+    </xsd:sequence>
+  </xsd:group>
+
+  <xsd:complexType name="docVariableListType">
+    <xsd:sequence>
+      <xsd:group ref="docVariableListGroup" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docRefTextType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="kindref" type="DoxRefKind" />
+    <xsd:attribute name="external" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docTableType">
+    <xsd:sequence>
+      <xsd:element name="row" type="docRowType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="caption" type="docCaptionType" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="rows" type="xsd:integer" />
+    <xsd:attribute name="cols" type="xsd:integer" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docRowType">
+    <xsd:sequence>
+      <xsd:element name="entry" type="docEntryType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docEntryType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="thead" type="DoxBool" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docCaptionType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docHeadingType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="level" type="xsd:integer" /> <!-- todo: range 1-6 -->
+  </xsd:complexType>
+
+  <xsd:complexType name="docImageType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="type" type="DoxImageKind" /> 
+    <xsd:attribute name="name" type="xsd:string" /> 
+    <xsd:attribute name="width" type="xsd:string" /> 
+    <xsd:attribute name="height" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docFileType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="name" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docTocItemType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="id" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docTocListType">
+    <xsd:sequence>
+      <xsd:element name="tocitem" type="docTocItemType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docLanguageType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="langid" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docParamListType">
+    <xsd:sequence>
+      <xsd:element name="parameteritem" type="docParamListItem" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="kind" type="DoxParamListKind" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docParamListItem">
+    <xsd:sequence>
+      <xsd:element name="parameternamelist" type="docParamNameList" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="parameterdescription" type="descriptionType" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docParamNameList">
+    <xsd:sequence>
+      <xsd:element name="parametertype" type="docParamType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="parametername" type="docParamName" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docParamType" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="ref" type="refTextType" minOccurs="0" maxOccurs="1" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docParamName" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="ref" type="refTextType" minOccurs="0" maxOccurs="1" />
+    </xsd:sequence>
+    <xsd:attribute name="direction" type="DoxParamDir" use="optional" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docXRefSectType">
+    <xsd:sequence>
+      <xsd:element name="xreftitle" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="xrefdescription" type="descriptionType" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docCopyType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect1" type="docSect1Type" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalType" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="link" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docBlockQuoteType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docParBlockType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docEmptyType"/>
+
+  <!-- Simple types -->
+
+  <xsd:simpleType name="DoxBool">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="yes" />
+      <xsd:enumeration value="no" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxGraphRelation">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="include" />
+      <xsd:enumeration value="usage" />
+      <xsd:enumeration value="template-instance" />
+      <xsd:enumeration value="public-inheritance" />
+      <xsd:enumeration value="protected-inheritance" />
+      <xsd:enumeration value="private-inheritance" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxRefKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="compound" />
+      <xsd:enumeration value="member" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxMemberKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="define" />
+      <xsd:enumeration value="property" />
+      <xsd:enumeration value="event" />
+      <xsd:enumeration value="variable" />
+      <xsd:enumeration value="typedef" />
+      <xsd:enumeration value="enum" />
+      <xsd:enumeration value="function" />
+      <xsd:enumeration value="signal" />
+      <xsd:enumeration value="prototype" />
+      <xsd:enumeration value="friend" />
+      <xsd:enumeration value="dcop" />
+      <xsd:enumeration value="slot" />
+      <xsd:enumeration value="interface" />
+      <xsd:enumeration value="service" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxProtectionKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="public" />
+      <xsd:enumeration value="protected" />
+      <xsd:enumeration value="private" />
+      <xsd:enumeration value="package" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxVirtualKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="non-virtual" />
+      <xsd:enumeration value="virtual" />
+      <xsd:enumeration value="pure-virtual" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxCompoundKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="class" />
+      <xsd:enumeration value="struct" />
+      <xsd:enumeration value="union" />
+      <xsd:enumeration value="interface" />
+      <xsd:enumeration value="protocol" />
+      <xsd:enumeration value="category" />
+      <xsd:enumeration value="exception" />
+      <xsd:enumeration value="service" />
+      <xsd:enumeration value="singleton" />
+      <xsd:enumeration value="module" />
+      <xsd:enumeration value="type" />
+      <xsd:enumeration value="file" />
+      <xsd:enumeration value="namespace" />
+      <xsd:enumeration value="group" />
+      <xsd:enumeration value="page" />
+      <xsd:enumeration value="example" />
+      <xsd:enumeration value="dir" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxSectionKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="user-defined" />
+      <xsd:enumeration value="public-type" />
+      <xsd:enumeration value="public-func" />
+      <xsd:enumeration value="public-attrib" />
+      <xsd:enumeration value="public-slot" />
+      <xsd:enumeration value="signal" />
+      <xsd:enumeration value="dcop-func" />
+      <xsd:enumeration value="property" />
+      <xsd:enumeration value="event" />
+      <xsd:enumeration value="public-static-func" />
+      <xsd:enumeration value="public-static-attrib" />
+      <xsd:enumeration value="protected-type" />
+      <xsd:enumeration value="protected-func" />
+      <xsd:enumeration value="protected-attrib" />
+      <xsd:enumeration value="protected-slot" />
+      <xsd:enumeration value="protected-static-func" />
+      <xsd:enumeration value="protected-static-attrib" />
+      <xsd:enumeration value="package-type" />
+      <xsd:enumeration value="package-func" />
+      <xsd:enumeration value="package-attrib" />
+      <xsd:enumeration value="package-static-func" />
+      <xsd:enumeration value="package-static-attrib" />
+      <xsd:enumeration value="private-type" />
+      <xsd:enumeration value="private-func" />
+      <xsd:enumeration value="private-attrib" />
+      <xsd:enumeration value="private-slot" />
+      <xsd:enumeration value="private-static-func" />
+      <xsd:enumeration value="private-static-attrib" />
+      <xsd:enumeration value="friend" />
+      <xsd:enumeration value="related" />
+      <xsd:enumeration value="define" />
+      <xsd:enumeration value="prototype" />
+      <xsd:enumeration value="typedef" />
+      <xsd:enumeration value="enum" />
+      <xsd:enumeration value="func" />
+      <xsd:enumeration value="var" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxHighlightClass">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="comment" />
+      <xsd:enumeration value="normal" />
+      <xsd:enumeration value="preprocessor" />
+      <xsd:enumeration value="keyword" />
+      <xsd:enumeration value="keywordtype" />
+      <xsd:enumeration value="keywordflow" />
+      <xsd:enumeration value="stringliteral" />
+      <xsd:enumeration value="charliteral" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxSimpleSectKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="see" />
+      <xsd:enumeration value="return" />
+      <xsd:enumeration value="author" />
+      <xsd:enumeration value="authors" />
+      <xsd:enumeration value="version" />
+      <xsd:enumeration value="since" />
+      <xsd:enumeration value="date" />
+      <xsd:enumeration value="note" />
+      <xsd:enumeration value="warning" />
+      <xsd:enumeration value="pre" />
+      <xsd:enumeration value="post" />
+      <xsd:enumeration value="copyright" />
+      <xsd:enumeration value="invariant" />
+      <xsd:enumeration value="remark" />
+      <xsd:enumeration value="attention" />
+      <xsd:enumeration value="par" />
+      <xsd:enumeration value="rcs" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxVersionNumber">
+    <xsd:restriction base="xsd:string">
+      <xsd:pattern value="\d+\.\d+.*" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxImageKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="html" />
+      <xsd:enumeration value="latex" />
+      <xsd:enumeration value="rtf" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxParamListKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="param" />
+      <xsd:enumeration value="retval" />
+      <xsd:enumeration value="exception" />
+      <xsd:enumeration value="templateparam" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxCharRange">
+    <xsd:restriction base="xsd:string">
+      <xsd:pattern value="[aeiouncAEIOUNC]" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxParamDir">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="in"/>
+      <xsd:enumeration value="out"/>
+      <xsd:enumeration value="inout"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxAccessor">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="retain"/>
+      <xsd:enumeration value="copy"/>
+      <xsd:enumeration value="assign"/>
+      <xsd:enumeration value="weak"/>
+      <xsd:enumeration value="strong"/>
+      <xsd:enumeration value="unretained"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+
+</xsd:schema>
+
diff --git a/contrib/neo_doxygen/tests/empty-project/xml/index.xml b/contrib/neo_doxygen/tests/empty-project/xml/index.xml
new file mode 100644 (file)
index 0000000..cb503f1
--- /dev/null
@@ -0,0 +1,3 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygenindex xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="index.xsd" version="1.8.8">
+</doxygenindex>
diff --git a/contrib/neo_doxygen/tests/empty-project/xml/index.xsd b/contrib/neo_doxygen/tests/empty-project/xml/index.xsd
new file mode 100644 (file)
index 0000000..d7ab2a9
--- /dev/null
@@ -0,0 +1,66 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <xsd:element name="doxygenindex" type="DoxygenType"/>
+
+  <xsd:complexType name="DoxygenType">
+    <xsd:sequence>
+      <xsd:element name="compound" type="CompoundType" minOccurs="0" maxOccurs="unbounded"/>
+    </xsd:sequence>
+    <xsd:attribute name="version" type="xsd:string" use="required"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="CompoundType">
+    <xsd:sequence>
+      <xsd:element name="name" type="xsd:string"/>
+      <xsd:element name="member" type="MemberType" minOccurs="0" maxOccurs="unbounded"/>
+    </xsd:sequence>
+    <xsd:attribute name="refid" type="xsd:string" use="required"/>
+    <xsd:attribute name="kind" type="CompoundKind" use="required"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="MemberType">
+    <xsd:sequence>
+      <xsd:element name="name" type="xsd:string"/>
+    </xsd:sequence>
+    <xsd:attribute name="refid" type="xsd:string" use="required"/>
+    <xsd:attribute name="kind" type="MemberKind" use="required"/>
+  </xsd:complexType>
+  
+  <xsd:simpleType name="CompoundKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="class"/>
+      <xsd:enumeration value="struct"/>
+      <xsd:enumeration value="union"/>
+      <xsd:enumeration value="interface"/>
+      <xsd:enumeration value="protocol"/>
+      <xsd:enumeration value="category"/>
+      <xsd:enumeration value="exception"/>
+      <xsd:enumeration value="file"/>
+      <xsd:enumeration value="namespace"/>
+      <xsd:enumeration value="group"/>
+      <xsd:enumeration value="page"/>
+      <xsd:enumeration value="example"/>
+      <xsd:enumeration value="dir"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="MemberKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="define"/>
+      <xsd:enumeration value="property"/>
+      <xsd:enumeration value="event"/>
+      <xsd:enumeration value="variable"/>
+      <xsd:enumeration value="typedef"/>
+      <xsd:enumeration value="enum"/>
+      <xsd:enumeration value="enumvalue"/>
+      <xsd:enumeration value="function"/>
+      <xsd:enumeration value="signal"/>
+      <xsd:enumeration value="prototype"/>
+      <xsd:enumeration value="friend"/>
+      <xsd:enumeration value="dcop"/>
+      <xsd:enumeration value="slot"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+
+</xsd:schema>
+
diff --git a/contrib/neo_doxygen/tests/java-project/Doxyfile b/contrib/neo_doxygen/tests/java-project/Doxyfile
new file mode 100644 (file)
index 0000000..bd06324
--- /dev/null
@@ -0,0 +1,2381 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "Test Project"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = YES
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  = src
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.idl \
+                         *.ddl \
+                         *.odl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.cs \
+                         *.d \
+                         *.php \
+                         *.php4 \
+                         *.php5 \
+                         *.phtml \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.f90 \
+                         *.f \
+                         *.for \
+                         *.tcl \
+                         *.vhd \
+                         *.vhdl \
+                         *.ucf \
+                         *.qsf \
+                         *.as \
+                         *.js
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = NO
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = YES
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH      =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
diff --git a/contrib/neo_doxygen/tests/java-project/README.md b/contrib/neo_doxygen/tests/java-project/README.md
new file mode 100644 (file)
index 0000000..2a87fc7
--- /dev/null
@@ -0,0 +1,5 @@
+This directory contains a dummy Java project for testing purposes.
+
+To regenerate the XML output located in `xml`, run `make`. If the `Makefile`
+does not exists, you can regenerate it by running `make bootstrap` in the parent
+directory.
diff --git a/contrib/neo_doxygen/tests/java-project/src/org/example/foo/A.java b/contrib/neo_doxygen/tests/java-project/src/org/example/foo/A.java
new file mode 100644 (file)
index 0000000..4bbd973
--- /dev/null
@@ -0,0 +1,23 @@
+/* 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.
+ */
+
+package org.example.foo;
+
+public abstract class A {
+       /**
+        * Does something...
+        */
+       public abstract boolean bar(int x, EmptyClass y);
+}
diff --git a/contrib/neo_doxygen/tests/java-project/src/org/example/foo/B.java b/contrib/neo_doxygen/tests/java-project/src/org/example/foo/B.java
new file mode 100644 (file)
index 0000000..0599e9d
--- /dev/null
@@ -0,0 +1,29 @@
+/* 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.
+ */
+
+package org.example.foo;
+
+public class B extends A implements C {
+       protected String qux = "quux";
+
+       public boolean bar(int x, EmptyClass y) {
+               return false;
+       }
+
+       /**
+        * Some overriden documentation.
+        */
+       public void baz() {}
+}
diff --git a/contrib/neo_doxygen/tests/java-project/src/org/example/foo/C.java b/contrib/neo_doxygen/tests/java-project/src/org/example/foo/C.java
new file mode 100644 (file)
index 0000000..42d95fa
--- /dev/null
@@ -0,0 +1,31 @@
+/* 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.
+ */
+
+package org.example.foo;
+
+/**
+ * An interface
+ */
+public interface C {
+       /**
+        * “Answer to the Ultimate Question of Life, the Universe, and Everything.“
+        */
+       public static final long THE_ANSWER = 42L;
+
+       /**
+        * A function with implicit modifiers.
+        */
+       void baz();
+}
diff --git a/contrib/neo_doxygen/tests/java-project/src/org/example/foo/EmptyClass.java b/contrib/neo_doxygen/tests/java-project/src/org/example/foo/EmptyClass.java
new file mode 100644 (file)
index 0000000..87ed89e
--- /dev/null
@@ -0,0 +1,21 @@
+/* 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.
+ */
+
+package org.example.foo;
+
+/**
+ * This class is empty and is only visible in this package.
+ */
+class EmptyClass {}
diff --git a/contrib/neo_doxygen/tests/java-project/xml/_a_8java.xml b/contrib/neo_doxygen/tests/java-project/xml/_a_8java.xml
new file mode 100644 (file)
index 0000000..5ce035d
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="_a_8java" kind="file">
+    <compoundname>A.java</compoundname>
+    <innerclass refid="classorg_1_1example_1_1foo_1_1_a" prot="public">org::example::foo::A</innerclass>
+    <innernamespace refid="namespaceorg_1_1example_1_1foo">org::example::foo</innernamespace>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="%SOURCE_DIRECTORY%/org/example/foo/A.java"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/_b_8java.xml b/contrib/neo_doxygen/tests/java-project/xml/_b_8java.xml
new file mode 100644 (file)
index 0000000..5d616b9
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="_b_8java" kind="file">
+    <compoundname>B.java</compoundname>
+    <innerclass refid="classorg_1_1example_1_1foo_1_1_b" prot="public">org::example::foo::B</innerclass>
+    <innernamespace refid="namespaceorg_1_1example_1_1foo">org::example::foo</innernamespace>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="%SOURCE_DIRECTORY%/org/example/foo/B.java"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/_c_8java.xml b/contrib/neo_doxygen/tests/java-project/xml/_c_8java.xml
new file mode 100644 (file)
index 0000000..d020a7a
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="_c_8java" kind="file">
+    <compoundname>C.java</compoundname>
+    <innerclass refid="interfaceorg_1_1example_1_1foo_1_1_c" prot="public">org::example::foo::C</innerclass>
+    <innernamespace refid="namespaceorg_1_1example_1_1foo">org::example::foo</innernamespace>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="%SOURCE_DIRECTORY%/org/example/foo/C.java"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/_empty_class_8java.xml b/contrib/neo_doxygen/tests/java-project/xml/_empty_class_8java.xml
new file mode 100644 (file)
index 0000000..82e6562
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="_empty_class_8java" kind="file">
+    <compoundname>EmptyClass.java</compoundname>
+    <innerclass refid="classorg_1_1example_1_1foo_1_1_empty_class" prot="package">org::example::foo::EmptyClass</innerclass>
+    <innernamespace refid="namespaceorg_1_1example_1_1foo">org::example::foo</innernamespace>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="%SOURCE_DIRECTORY%/org/example/foo/EmptyClass.java"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/classorg_1_1example_1_1foo_1_1_a.xml b/contrib/neo_doxygen/tests/java-project/xml/classorg_1_1example_1_1foo_1_1_a.xml
new file mode 100644 (file)
index 0000000..4475075
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="classorg_1_1example_1_1foo_1_1_a" kind="class" prot="public" abstract="yes">
+    <compoundname>org::example::foo::A</compoundname>
+    <derivedcompoundref refid="classorg_1_1example_1_1foo_1_1_b" prot="public" virt="non-virtual">org.example.foo.B</derivedcompoundref>
+      <sectiondef kind="public-func">
+      <memberdef kind="function" id="classorg_1_1example_1_1foo_1_1_a_1add415ae4129969055d678c7e7e048852" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual">
+        <type>abstract boolean</type>
+        <definition>abstract boolean org.example.foo.A.bar</definition>
+        <argsstring>(int x, EmptyClass y)</argsstring>
+        <name>bar</name>
+        <param>
+          <type>int</type>
+          <declname>x</declname>
+        </param>
+        <param>
+          <type>EmptyClass</type>
+          <declname>y</declname>
+        </param>
+        <briefdescription>
+        </briefdescription>
+        <detaileddescription>
+<para>Does something... </para>        </detaileddescription>
+        <inbodydescription>
+        </inbodydescription>
+        <location file="%SOURCE_DIRECTORY%/org/example/foo/A.java" line="22" column="1"/>
+      </memberdef>
+      </sectiondef>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <inheritancegraph>
+      <node id="0">
+        <label>org.example.foo.A</label>
+        <link refid="classorg_1_1example_1_1foo_1_1_a"/>
+      </node>
+      <node id="1">
+        <label>org.example.foo.B</label>
+        <link refid="classorg_1_1example_1_1foo_1_1_b"/>
+        <childnode refid="0" relation="public-inheritance">
+        </childnode>
+      </node>
+    </inheritancegraph>
+    <location file="%SOURCE_DIRECTORY%/org/example/foo/A.java" line="18" column="1" bodyfile="%SOURCE_DIRECTORY%/org/example/foo/A.java" bodystart="18" bodyend="23"/>
+    <listofallmembers>
+      <member refid="classorg_1_1example_1_1foo_1_1_a_1add415ae4129969055d678c7e7e048852" prot="public" virt="non-virtual"><scope>org::example::foo::A</scope><name>bar</name></member>
+    </listofallmembers>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/classorg_1_1example_1_1foo_1_1_b.xml b/contrib/neo_doxygen/tests/java-project/xml/classorg_1_1example_1_1foo_1_1_b.xml
new file mode 100644 (file)
index 0000000..eb1fd6c
--- /dev/null
@@ -0,0 +1,108 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="classorg_1_1example_1_1foo_1_1_b" kind="class" prot="public">
+    <compoundname>org::example::foo::B</compoundname>
+    <basecompoundref refid="classorg_1_1example_1_1foo_1_1_a" prot="public" virt="non-virtual">org.example.foo.A</basecompoundref>
+    <basecompoundref refid="interfaceorg_1_1example_1_1foo_1_1_c" prot="public" virt="non-virtual">org.example.foo.C</basecompoundref>
+      <sectiondef kind="protected-attrib">
+      <memberdef kind="variable" id="classorg_1_1example_1_1foo_1_1_b_1ac6b627949b10b9357eefc0cafcae1d87" prot="protected" static="no" mutable="no">
+        <type>String</type>
+        <definition>String org.example.foo.B.qux</definition>
+        <argsstring></argsstring>
+        <name>qux</name>
+        <initializer>= &quot;quux&quot;</initializer>
+        <briefdescription>
+        </briefdescription>
+        <detaileddescription>
+        </detaileddescription>
+        <inbodydescription>
+        </inbodydescription>
+        <location file="%SOURCE_DIRECTORY%/org/example/foo/B.java" line="19" column="1" bodyfile="%SOURCE_DIRECTORY%/org/example/foo/B.java" bodystart="19" bodyend="-1"/>
+      </memberdef>
+      </sectiondef>
+      <sectiondef kind="public-func">
+      <memberdef kind="function" id="classorg_1_1example_1_1foo_1_1_b_1a11e157943665cc9e3a9be1502ebeb3b5" prot="public" static="no" const="no" explicit="no" inline="yes" virt="non-virtual">
+        <type>boolean</type>
+        <definition>boolean org.example.foo.B.bar</definition>
+        <argsstring>(int x, EmptyClass y)</argsstring>
+        <name>bar</name>
+        <param>
+          <type>int</type>
+          <declname>x</declname>
+        </param>
+        <param>
+          <type>EmptyClass</type>
+          <declname>y</declname>
+        </param>
+        <briefdescription>
+        </briefdescription>
+        <detaileddescription>
+        </detaileddescription>
+        <inbodydescription>
+        </inbodydescription>
+        <location file="%SOURCE_DIRECTORY%/org/example/foo/B.java" line="21" column="1" bodyfile="%SOURCE_DIRECTORY%/org/example/foo/B.java" bodystart="21" bodyend="23"/>
+      </memberdef>
+      <memberdef kind="function" id="classorg_1_1example_1_1foo_1_1_b_1a733f4e076f29c7d0c41ed258199ea1d9" prot="public" static="no" const="no" explicit="no" inline="yes" virt="non-virtual">
+        <type>void</type>
+        <definition>void org.example.foo.B.baz</definition>
+        <argsstring>()</argsstring>
+        <name>baz</name>
+        <reimplements refid="interfaceorg_1_1example_1_1foo_1_1_c_1a28ac7ce349ebb3e4a7747a8dd951582b">baz</reimplements>
+        <briefdescription>
+        </briefdescription>
+        <detaileddescription>
+<para>Some overriden documentation. </para>        </detaileddescription>
+        <inbodydescription>
+        </inbodydescription>
+        <location file="%SOURCE_DIRECTORY%/org/example/foo/B.java" line="28" column="1" bodyfile="%SOURCE_DIRECTORY%/org/example/foo/B.java" bodystart="28" bodyend="28"/>
+      </memberdef>
+      </sectiondef>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <inheritancegraph>
+      <node id="4">
+        <label>org.example.foo.A</label>
+        <link refid="classorg_1_1example_1_1foo_1_1_a"/>
+      </node>
+      <node id="3">
+        <label>org.example.foo.B</label>
+        <link refid="classorg_1_1example_1_1foo_1_1_b"/>
+        <childnode refid="4" relation="public-inheritance">
+        </childnode>
+        <childnode refid="5" relation="public-inheritance">
+        </childnode>
+      </node>
+      <node id="5">
+        <label>org.example.foo.C</label>
+        <link refid="interfaceorg_1_1example_1_1foo_1_1_c"/>
+      </node>
+    </inheritancegraph>
+    <collaborationgraph>
+      <node id="7">
+        <label>org.example.foo.A</label>
+        <link refid="classorg_1_1example_1_1foo_1_1_a"/>
+      </node>
+      <node id="6">
+        <label>org.example.foo.B</label>
+        <link refid="classorg_1_1example_1_1foo_1_1_b"/>
+        <childnode refid="7" relation="public-inheritance">
+        </childnode>
+        <childnode refid="8" relation="public-inheritance">
+        </childnode>
+      </node>
+      <node id="8">
+        <label>org.example.foo.C</label>
+        <link refid="interfaceorg_1_1example_1_1foo_1_1_c"/>
+      </node>
+    </collaborationgraph>
+    <location file="%SOURCE_DIRECTORY%/org/example/foo/B.java" line="18" column="1" bodyfile="%SOURCE_DIRECTORY%/org/example/foo/B.java" bodystart="18" bodyend="29"/>
+    <listofallmembers>
+      <member refid="classorg_1_1example_1_1foo_1_1_b_1a11e157943665cc9e3a9be1502ebeb3b5" prot="public" virt="non-virtual"><scope>org::example::foo::B</scope><name>bar</name></member>
+      <member refid="classorg_1_1example_1_1foo_1_1_b_1a733f4e076f29c7d0c41ed258199ea1d9" prot="public" virt="non-virtual"><scope>org::example::foo::B</scope><name>baz</name></member>
+      <member refid="classorg_1_1example_1_1foo_1_1_b_1ac6b627949b10b9357eefc0cafcae1d87" prot="protected" virt="non-virtual"><scope>org::example::foo::B</scope><name>qux</name></member>
+      <member refid="interfaceorg_1_1example_1_1foo_1_1_c_1a4e97061eb40b045e820de05b33c43d21" prot="public" virt="non-virtual"><scope>org::example::foo::B</scope><name>THE_ANSWER</name></member>
+    </listofallmembers>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/classorg_1_1example_1_1foo_1_1_empty_class.xml b/contrib/neo_doxygen/tests/java-project/xml/classorg_1_1example_1_1foo_1_1_empty_class.xml
new file mode 100644 (file)
index 0000000..9aa6aa2
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="classorg_1_1example_1_1foo_1_1_empty_class" kind="class" prot="package">
+    <compoundname>org::example::foo::EmptyClass</compoundname>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+<para>This class is empty and is only visible in this package. </para>    </detaileddescription>
+    <location file="%SOURCE_DIRECTORY%/org/example/foo/EmptyClass.java" line="21" column="1" bodyfile="%SOURCE_DIRECTORY%/org/example/foo/EmptyClass.java" bodystart="21" bodyend="21"/>
+    <listofallmembers>
+    </listofallmembers>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/combine.xslt b/contrib/neo_doxygen/tests/java-project/xml/combine.xslt
new file mode 100644 (file)
index 0000000..c148ee4
--- /dev/null
@@ -0,0 +1,15 @@
+<!-- XSLT script to combine the generated output into a single file. 
+     If you have xsltproc you could use:
+     xsltproc combine.xslt index.xml >all.xml
+-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+  <xsl:output method="xml" version="1.0" indent="no" standalone="yes" />
+  <xsl:template match="/">
+    <doxygen version="{doxygenindex/@version}">
+      <!-- Load all doxgen generated xml files -->
+      <xsl:for-each select="doxygenindex/compound">
+        <xsl:copy-of select="document( concat( @refid, '.xml' ) )/doxygen/*" />
+      </xsl:for-each>
+    </doxygen>
+  </xsl:template>
+</xsl:stylesheet>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/compound.xsd b/contrib/neo_doxygen/tests/java-project/xml/compound.xsd
new file mode 100644 (file)
index 0000000..86740f4
--- /dev/null
@@ -0,0 +1,1092 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <xsd:element name="doxygen" type="DoxygenType"/>
+
+  <!-- Complex types -->
+
+  <xsd:complexType name="DoxygenType">
+    <xsd:sequence maxOccurs="unbounded">
+      <xsd:element name="compounddef" type="compounddefType" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="version" type="DoxVersionNumber" use="required" />
+  </xsd:complexType>
+
+  <xsd:complexType name="compounddefType">
+    <xsd:sequence>
+      <xsd:element name="compoundname" type="xsd:string"/>
+      <xsd:element name="title" type="xsd:string" minOccurs="0" />
+      <xsd:element name="basecompoundref" type="compoundRefType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="derivedcompoundref" type="compoundRefType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="includes" type="incType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="includedby" type="incType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="incdepgraph" type="graphType" minOccurs="0" />
+      <xsd:element name="invincdepgraph" type="graphType" minOccurs="0" />
+      <xsd:element name="innerdir" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="innerfile" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="innerclass" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="innernamespace" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="innerpage" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="innergroup" type="refType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="templateparamlist" type="templateparamlistType" minOccurs="0" />
+      <xsd:element name="sectiondef" type="sectiondefType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="briefdescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="detaileddescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="inheritancegraph" type="graphType" minOccurs="0" />
+      <xsd:element name="collaborationgraph" type="graphType" minOccurs="0" />
+      <xsd:element name="programlisting" type="listingType" minOccurs="0" />
+      <xsd:element name="location" type="locationType" minOccurs="0" />
+      <xsd:element name="listofallmembers" type="listofallmembersType" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+    <xsd:attribute name="kind" type="DoxCompoundKind" />
+    <xsd:attribute name="prot" type="DoxProtectionKind" />
+    <xsd:attribute name="final" type="DoxBool" use="optional"/>
+    <xsd:attribute name="sealed" type="DoxBool" use="optional"/>
+    <xsd:attribute name="abstract" type="DoxBool" use="optional"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="listofallmembersType">
+    <xsd:sequence>
+      <xsd:element name="member" type="memberRefType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="memberRefType">
+    <xsd:sequence>
+      <xsd:element name="scope" />
+      <xsd:element name="name" />
+    </xsd:sequence>
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="prot" type="DoxProtectionKind" />
+    <xsd:attribute name="virt" type="DoxVirtualKind" />
+    <xsd:attribute name="ambiguityscope" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="compoundRefType">
+    <xsd:simpleContent>
+      <xsd:extension base="xsd:string">
+        <xsd:attribute name="refid" type="xsd:string" use="optional" />
+        <xsd:attribute name="prot" type="DoxProtectionKind" />
+        <xsd:attribute name="virt" type="DoxVirtualKind" />
+      </xsd:extension>
+    </xsd:simpleContent>
+  </xsd:complexType>
+
+  <xsd:complexType name="reimplementType">
+    <xsd:simpleContent>
+      <xsd:extension base="xsd:string">
+        <xsd:attribute name="refid" type="xsd:string" />
+      </xsd:extension>
+    </xsd:simpleContent>
+  </xsd:complexType>
+
+  <xsd:complexType name="incType">
+    <xsd:simpleContent>
+      <xsd:extension base="xsd:string">
+        <xsd:attribute name="refid" type="xsd:string" />
+        <xsd:attribute name="local" type="DoxBool" />
+      </xsd:extension>
+    </xsd:simpleContent>
+  </xsd:complexType>
+
+  <xsd:complexType name="refType">
+    <xsd:simpleContent>
+      <xsd:extension base="xsd:string">
+        <xsd:attribute name="refid" type="xsd:string" />
+        <xsd:attribute name="prot" type="DoxProtectionKind" use="optional"/>
+      </xsd:extension>
+    </xsd:simpleContent>
+  </xsd:complexType>
+
+  <xsd:complexType name="refTextType">
+    <xsd:simpleContent>
+      <xsd:extension base="xsd:string">
+       <xsd:attribute name="refid" type="xsd:string" />
+       <xsd:attribute name="kindref" type="DoxRefKind" />
+       <xsd:attribute name="external" type="xsd:string" use="optional"/>
+       <xsd:attribute name="tooltip" type="xsd:string" use="optional"/>
+      </xsd:extension>
+    </xsd:simpleContent>
+  </xsd:complexType>
+
+  <xsd:complexType name="sectiondefType">
+    <xsd:sequence>
+      <xsd:element name="header" type="xsd:string" minOccurs="0" />
+      <xsd:element name="description" type="descriptionType" minOccurs="0" />
+      <xsd:element name="memberdef" type="memberdefType" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="kind" type="DoxSectionKind" />
+  </xsd:complexType>
+
+  <xsd:complexType name="memberdefType">
+    <xsd:sequence>
+      <xsd:element name="templateparamlist" type="templateparamlistType" minOccurs="0" />
+      <xsd:element name="type" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="definition" minOccurs="0" />
+      <xsd:element name="argsstring" minOccurs="0" />
+      <xsd:element name="name" />
+      <xsd:element name="read" minOccurs="0" />
+      <xsd:element name="write" minOccurs="0" />
+      <xsd:element name="bitfield" minOccurs="0" />
+      <xsd:element name="reimplements" type="reimplementType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="reimplementedby" type="reimplementType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="param" type="paramType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="enumvalue" type="enumvalueType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="initializer" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="exceptions" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="briefdescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="detaileddescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="inbodydescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="location" type="locationType" />
+      <xsd:element name="references" type="referenceType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="referencedby" type="referenceType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="kind" type="DoxMemberKind" />
+    <xsd:attribute name="id" type="xsd:string" />
+    <xsd:attribute name="prot" type="DoxProtectionKind" />
+    <xsd:attribute name="static" type="DoxBool" />
+    <xsd:attribute name="const" type="DoxBool" use="optional"/>
+    <xsd:attribute name="explicit" type="DoxBool" use="optional"/>
+    <xsd:attribute name="inline" type="DoxBool" use="optional"/>
+    <xsd:attribute name="virt" type="DoxVirtualKind" use="optional"/>
+    <xsd:attribute name="volatile" type="DoxBool" use="optional"/>
+    <xsd:attribute name="mutable" type="DoxBool" use="optional"/>
+    <!-- Qt property -->
+    <xsd:attribute name="readable" type="DoxBool" use="optional"/>
+    <xsd:attribute name="writable" type="DoxBool" use="optional"/>
+    <!-- C++/CLI variable -->
+    <xsd:attribute name="initonly" type="DoxBool" use="optional"/>
+    <!-- C++/CLI and C# property -->
+    <xsd:attribute name="settable" type="DoxBool" use="optional"/>
+    <xsd:attribute name="gettable" type="DoxBool" use="optional"/>
+    <!-- C++/CLI function -->
+    <xsd:attribute name="final" type="DoxBool" use="optional"/>
+    <xsd:attribute name="sealed" type="DoxBool" use="optional"/>
+    <xsd:attribute name="new" type="DoxBool" use="optional"/>
+    <!-- C++/CLI event -->
+    <xsd:attribute name="add" type="DoxBool" use="optional"/>
+    <xsd:attribute name="remove" type="DoxBool" use="optional"/>
+    <xsd:attribute name="raise" type="DoxBool" use="optional"/>
+    <!-- Objective-C 2.0 protocol method -->
+    <xsd:attribute name="optional" type="DoxBool" use="optional"/>
+    <xsd:attribute name="required" type="DoxBool" use="optional"/>
+    <!-- Objective-C 2.0 property accessor -->
+    <xsd:attribute name="accessor" type="DoxAccessor" use="optional"/>
+    <!-- UNO IDL -->
+    <xsd:attribute name="attribute" type="DoxBool" use="optional"/>
+    <xsd:attribute name="property" type="DoxBool" use="optional"/>
+    <xsd:attribute name="readonly" type="DoxBool" use="optional"/>
+    <xsd:attribute name="bound" type="DoxBool" use="optional"/>
+    <xsd:attribute name="removable" type="DoxBool" use="optional"/>
+    <xsd:attribute name="contrained" type="DoxBool" use="optional"/>
+    <xsd:attribute name="transient" type="DoxBool" use="optional"/>
+    <xsd:attribute name="maybevoid" type="DoxBool" use="optional"/>
+    <xsd:attribute name="maybedefault" type="DoxBool" use="optional"/>
+    <xsd:attribute name="maybeambiguous" type="DoxBool" use="optional"/>
+
+  </xsd:complexType>
+
+  <xsd:complexType name="descriptionType" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="title" type="xsd:string" minOccurs="0"/>          
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect1" type="docSect1Type" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalType" minOccurs="0" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="enumvalueType" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="name" />
+      <xsd:element name="initializer" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="briefdescription" type="descriptionType" minOccurs="0" />
+      <xsd:element name="detaileddescription" type="descriptionType" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+    <xsd:attribute name="prot" type="DoxProtectionKind" />
+  </xsd:complexType>
+
+  <xsd:complexType name="templateparamlistType">
+    <xsd:sequence>
+      <xsd:element name="param" type="paramType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="paramType">
+    <xsd:sequence>
+      <xsd:element name="type" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="declname" minOccurs="0" />
+      <xsd:element name="defname" minOccurs="0" />
+      <xsd:element name="array" minOccurs="0" />
+      <xsd:element name="defval" type="linkedTextType" minOccurs="0" />
+      <xsd:element name="briefdescription" type="descriptionType" minOccurs="0" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="linkedTextType" mixed="true">
+    <xsd:sequence>
+    <xsd:element name="ref" type="refTextType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="graphType">
+    <xsd:sequence>
+      <xsd:element name="node" type="nodeType" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="nodeType">
+    <xsd:sequence>
+      <xsd:element name="label" />
+      <xsd:element name="link" type="linkType" minOccurs="0" />
+      <xsd:element name="childnode" type="childnodeType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="childnodeType">
+    <xsd:sequence>
+      <xsd:element name="edgelabel" minOccurs="0" maxOccurs="unbounded"/>
+    </xsd:sequence>
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="relation" type="DoxGraphRelation" />
+  </xsd:complexType>
+
+  <xsd:complexType name="linkType">
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="external" type="xsd:string" use="optional"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="listingType">
+    <xsd:sequence>
+      <xsd:element name="codeline" type="codelineType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="codelineType">
+    <xsd:sequence>
+      <xsd:element name="highlight" type="highlightType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="lineno" type="xsd:integer" />
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="refkind" type="DoxRefKind" />
+    <xsd:attribute name="external" type="DoxBool" />
+  </xsd:complexType>
+
+  <xsd:complexType name="highlightType" mixed="true">
+    <xsd:choice minOccurs="0" maxOccurs="unbounded">
+      <xsd:element name="sp" />
+      <xsd:element name="ref" type="refTextType" />
+    </xsd:choice>
+    <xsd:attribute name="class" type="DoxHighlightClass" />
+  </xsd:complexType>
+
+  <xsd:complexType name="referenceType" mixed="true">
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="compoundref" type="xsd:string" use="optional" />
+    <xsd:attribute name="startline" type="xsd:integer" />
+    <xsd:attribute name="endline" type="xsd:integer" />
+  </xsd:complexType>
+
+  <xsd:complexType name="locationType">
+    <xsd:attribute name="file" type="xsd:string" />
+    <xsd:attribute name="line" type="xsd:integer" />
+    <xsd:attribute name="column" type="xsd:integer" use="optional"/>
+    <xsd:attribute name="bodyfile" type="xsd:string" />
+    <xsd:attribute name="bodystart" type="xsd:integer" />
+    <xsd:attribute name="bodyend" type="xsd:integer" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docSect1Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="title" type="xsd:string" />       
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect2" type="docSect2Type" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalS1Type" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docSect2Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="title" type="xsd:string" />       
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect3" type="docSect3Type" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalS2Type" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docSect3Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="title" type="xsd:string" />       
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect4" type="docSect4Type" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalS3Type" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docSect4Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="title" type="xsd:string" />       
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalS4Type" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docInternalType" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="para"  type="docParaType"  minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect1" type="docSect1Type" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docInternalS1Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="para"  type="docParaType"  minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect2" type="docSect2Type" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docInternalS2Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="para"  type="docParaType"  minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect3" type="docSect3Type" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docInternalS3Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="para"  type="docParaType"  minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect3" type="docSect4Type" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docInternalS4Type" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="para"  type="docParaType"  minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+  <xsd:group name="docTitleCmdGroup">
+    <xsd:choice>
+      <xsd:element name="ulink" type="docURLLink" />
+      <xsd:element name="bold" type="docMarkupType" />
+      <xsd:element name="emphasis" type="docMarkupType" />
+      <xsd:element name="computeroutput" type="docMarkupType" />
+      <xsd:element name="subscript" type="docMarkupType" />
+      <xsd:element name="superscript" type="docMarkupType" />
+      <xsd:element name="center" type="docMarkupType" />
+      <xsd:element name="small" type="docMarkupType" />
+      <xsd:element name="htmlonly" type="xsd:string" />
+      <xsd:element name="manonly" type="xsd:string" />
+      <xsd:element name="xmlonly" type="xsd:string" />
+      <xsd:element name="rtfonly" type="xsd:string" />
+      <xsd:element name="latexonly" type="xsd:string" />
+      <xsd:element name="dot" type="xsd:string" />
+      <xsd:element name="plantuml" type="xsd:string" />
+      <xsd:element name="anchor" type="docAnchorType" />
+      <xsd:element name="formula" type="docFormulaType" />
+      <xsd:element name="ref" type="docRefTextType" />
+      <xsd:element name="nonbreakablespace" type="docEmptyType" />
+      <xsd:element name="iexcl" type="docEmptyType" />
+      <xsd:element name="cent" type="docEmptyType" />
+      <xsd:element name="pound" type="docEmptyType" />
+      <xsd:element name="curren" type="docEmptyType" />
+      <xsd:element name="yen" type="docEmptyType" />
+      <xsd:element name="brvbar" type="docEmptyType" />
+      <xsd:element name="sect" type="docEmptyType" />
+      <xsd:element name="umlaut" type="docEmptyType" />
+      <xsd:element name="copy" type="docEmptyType" />
+      <xsd:element name="ordf" type="docEmptyType" />
+      <xsd:element name="laquo" type="docEmptyType" />
+      <xsd:element name="not" type="docEmptyType" />
+      <xsd:element name="shy" type="docEmptyType" />
+      <xsd:element name="registered" type="docEmptyType" />
+      <xsd:element name="macr" type="docEmptyType" />
+      <xsd:element name="deg" type="docEmptyType" />
+      <xsd:element name="plusmn" type="docEmptyType" />
+      <xsd:element name="sup2" type="docEmptyType" />
+      <xsd:element name="sup3" type="docEmptyType" />
+      <xsd:element name="acute" type="docEmptyType" />
+      <xsd:element name="micro" type="docEmptyType" />
+      <xsd:element name="para" type="docEmptyType" />
+      <xsd:element name="middot" type="docEmptyType" />
+      <xsd:element name="cedil" type="docEmptyType" />
+      <xsd:element name="sup1" type="docEmptyType" />
+      <xsd:element name="ordm" type="docEmptyType" />
+      <xsd:element name="raquo" type="docEmptyType" />
+      <xsd:element name="frac14" type="docEmptyType" />
+      <xsd:element name="frac12" type="docEmptyType" />
+      <xsd:element name="frac34" type="docEmptyType" />
+      <xsd:element name="iquest" type="docEmptyType" />
+      <xsd:element name="Agrave" type="docEmptyType" />
+      <xsd:element name="Aacute" type="docEmptyType" />
+      <xsd:element name="Acirc" type="docEmptyType" />
+      <xsd:element name="Atilde" type="docEmptyType" />
+      <xsd:element name="Aumlaut" type="docEmptyType" />
+      <xsd:element name="Aring" type="docEmptyType" />
+      <xsd:element name="AElig" type="docEmptyType" />
+      <xsd:element name="Ccedil" type="docEmptyType" />
+      <xsd:element name="Egrave" type="docEmptyType" />
+      <xsd:element name="Eacute" type="docEmptyType" />
+      <xsd:element name="Ecirc" type="docEmptyType" />
+      <xsd:element name="Eumlaut" type="docEmptyType" />
+      <xsd:element name="Igrave" type="docEmptyType" />
+      <xsd:element name="Iacute" type="docEmptyType" />
+      <xsd:element name="Icirc" type="docEmptyType" />
+      <xsd:element name="Iumlaut" type="docEmptyType" />
+      <xsd:element name="ETH" type="docEmptyType" />
+      <xsd:element name="Ntilde" type="docEmptyType" />
+      <xsd:element name="Ograve" type="docEmptyType" />
+      <xsd:element name="Oacute" type="docEmptyType" />
+      <xsd:element name="Ocirc" type="docEmptyType" />
+      <xsd:element name="Otilde" type="docEmptyType" />
+      <xsd:element name="Oumlaut" type="docEmptyType" />
+      <xsd:element name="times" type="docEmptyType" />
+      <xsd:element name="Oslash" type="docEmptyType" />
+      <xsd:element name="Ugrave" type="docEmptyType" />
+      <xsd:element name="Uacute" type="docEmptyType" />
+      <xsd:element name="Ucirc" type="docEmptyType" />
+      <xsd:element name="Uumlaut" type="docEmptyType" />
+      <xsd:element name="Yacute" type="docEmptyType" />
+      <xsd:element name="THORN" type="docEmptyType" />
+      <xsd:element name="szlig" type="docEmptyType" />
+      <xsd:element name="agrave" type="docEmptyType" />
+      <xsd:element name="aacute" type="docEmptyType" />
+      <xsd:element name="acirc" type="docEmptyType" />
+      <xsd:element name="atilde" type="docEmptyType" />
+      <xsd:element name="aumlaut" type="docEmptyType" />
+      <xsd:element name="aring" type="docEmptyType" />
+      <xsd:element name="aelig" type="docEmptyType" />
+      <xsd:element name="ccedil" type="docEmptyType" />
+      <xsd:element name="egrave" type="docEmptyType" />
+      <xsd:element name="eacute" type="docEmptyType" />
+      <xsd:element name="ecirc" type="docEmptyType" />
+      <xsd:element name="eumlaut" type="docEmptyType" />
+      <xsd:element name="igrave" type="docEmptyType" />
+      <xsd:element name="iacute" type="docEmptyType" />
+      <xsd:element name="icirc" type="docEmptyType" />
+      <xsd:element name="iumlaut" type="docEmptyType" />
+      <xsd:element name="eth" type="docEmptyType" />
+      <xsd:element name="ntilde" type="docEmptyType" />
+      <xsd:element name="ograve" type="docEmptyType" />
+      <xsd:element name="oacute" type="docEmptyType" />
+      <xsd:element name="ocirc" type="docEmptyType" />
+      <xsd:element name="otilde" type="docEmptyType" />
+      <xsd:element name="oumlaut" type="docEmptyType" />
+      <xsd:element name="divide" type="docEmptyType" />
+      <xsd:element name="oslash" type="docEmptyType" />
+      <xsd:element name="ugrave" type="docEmptyType" />
+      <xsd:element name="uacute" type="docEmptyType" />
+      <xsd:element name="ucirc" type="docEmptyType" />
+      <xsd:element name="uumlaut" type="docEmptyType" />
+      <xsd:element name="yacute" type="docEmptyType" />
+      <xsd:element name="thorn" type="docEmptyType" />
+      <xsd:element name="yumlaut" type="docEmptyType" />
+      <xsd:element name="fnof" type="docEmptyType" />
+      <xsd:element name="Alpha" type="docEmptyType" />
+      <xsd:element name="Beta" type="docEmptyType" />
+      <xsd:element name="Gamma" type="docEmptyType" />
+      <xsd:element name="Delta" type="docEmptyType" />
+      <xsd:element name="Epsilon" type="docEmptyType" />
+      <xsd:element name="Zeta" type="docEmptyType" />
+      <xsd:element name="Eta" type="docEmptyType" />
+      <xsd:element name="Theta" type="docEmptyType" />
+      <xsd:element name="Iota" type="docEmptyType" />
+      <xsd:element name="Kappa" type="docEmptyType" />
+      <xsd:element name="Lambda" type="docEmptyType" />
+      <xsd:element name="Mu" type="docEmptyType" />
+      <xsd:element name="Nu" type="docEmptyType" />
+      <xsd:element name="Xi" type="docEmptyType" />
+      <xsd:element name="Omicron" type="docEmptyType" />
+      <xsd:element name="Pi" type="docEmptyType" />
+      <xsd:element name="Rho" type="docEmptyType" />
+      <xsd:element name="Sigma" type="docEmptyType" />
+      <xsd:element name="Tau" type="docEmptyType" />
+      <xsd:element name="Upsilon" type="docEmptyType" />
+      <xsd:element name="Phi" type="docEmptyType" />
+      <xsd:element name="Chi" type="docEmptyType" />
+      <xsd:element name="Psi" type="docEmptyType" />
+      <xsd:element name="Omega" type="docEmptyType" />
+      <xsd:element name="alpha" type="docEmptyType" />
+      <xsd:element name="beta" type="docEmptyType" />
+      <xsd:element name="gamma" type="docEmptyType" />
+      <xsd:element name="delta" type="docEmptyType" />
+      <xsd:element name="epsilon" type="docEmptyType" />
+      <xsd:element name="zeta" type="docEmptyType" />
+      <xsd:element name="eta" type="docEmptyType" />
+      <xsd:element name="theta" type="docEmptyType" />
+      <xsd:element name="iota" type="docEmptyType" />
+      <xsd:element name="kappa" type="docEmptyType" />
+      <xsd:element name="lambda" type="docEmptyType" />
+      <xsd:element name="mu" type="docEmptyType" />
+      <xsd:element name="nu" type="docEmptyType" />
+      <xsd:element name="xi" type="docEmptyType" />
+      <xsd:element name="omicron" type="docEmptyType" />
+      <xsd:element name="pi" type="docEmptyType" />
+      <xsd:element name="rho" type="docEmptyType" />
+      <xsd:element name="sigmaf" type="docEmptyType" />
+      <xsd:element name="sigma" type="docEmptyType" />
+      <xsd:element name="tau" type="docEmptyType" />
+      <xsd:element name="upsilon" type="docEmptyType" />
+      <xsd:element name="phi" type="docEmptyType" />
+      <xsd:element name="chi" type="docEmptyType" />
+      <xsd:element name="psi" type="docEmptyType" />
+      <xsd:element name="omega" type="docEmptyType" />
+      <xsd:element name="thetasym" type="docEmptyType" />
+      <xsd:element name="upsih" type="docEmptyType" />
+      <xsd:element name="piv" type="docEmptyType" />
+      <xsd:element name="bull" type="docEmptyType" />
+      <xsd:element name="hellip" type="docEmptyType" />
+      <xsd:element name="prime" type="docEmptyType" />
+      <xsd:element name="Prime" type="docEmptyType" />
+      <xsd:element name="oline" type="docEmptyType" />
+      <xsd:element name="frasl" type="docEmptyType" />
+      <xsd:element name="weierp" type="docEmptyType" />
+      <xsd:element name="image" type="docEmptyType" />
+      <xsd:element name="real" type="docEmptyType" />
+      <xsd:element name="trademark" type="docEmptyType" />
+      <xsd:element name="alefsym" type="docEmptyType" />
+      <xsd:element name="larr" type="docEmptyType" />
+      <xsd:element name="uarr" type="docEmptyType" />
+      <xsd:element name="rarr" type="docEmptyType" />
+      <xsd:element name="darr" type="docEmptyType" />
+      <xsd:element name="harr" type="docEmptyType" />
+      <xsd:element name="crarr" type="docEmptyType" />
+      <xsd:element name="lArr" type="docEmptyType" />
+      <xsd:element name="uArr" type="docEmptyType" />
+      <xsd:element name="rArr" type="docEmptyType" />
+      <xsd:element name="dArr" type="docEmptyType" />
+      <xsd:element name="hArr" type="docEmptyType" />
+      <xsd:element name="forall" type="docEmptyType" />
+      <xsd:element name="part" type="docEmptyType" />
+      <xsd:element name="exist" type="docEmptyType" />
+      <xsd:element name="empty" type="docEmptyType" />
+      <xsd:element name="nabla" type="docEmptyType" />
+      <xsd:element name="isin" type="docEmptyType" />
+      <xsd:element name="notin" type="docEmptyType" />
+      <xsd:element name="ni" type="docEmptyType" />
+      <xsd:element name="prod" type="docEmptyType" />
+      <xsd:element name="sum" type="docEmptyType" />
+      <xsd:element name="minus" type="docEmptyType" />
+      <xsd:element name="lowast" type="docEmptyType" />
+      <xsd:element name="radic" type="docEmptyType" />
+      <xsd:element name="prop" type="docEmptyType" />
+      <xsd:element name="infin" type="docEmptyType" />
+      <xsd:element name="ang" type="docEmptyType" />
+      <xsd:element name="and" type="docEmptyType" />
+      <xsd:element name="or" type="docEmptyType" />
+      <xsd:element name="cap" type="docEmptyType" />
+      <xsd:element name="cup" type="docEmptyType" />
+      <xsd:element name="int" type="docEmptyType" />
+      <xsd:element name="there4" type="docEmptyType" />
+      <xsd:element name="sim" type="docEmptyType" />
+      <xsd:element name="cong" type="docEmptyType" />
+      <xsd:element name="asymp" type="docEmptyType" />
+      <xsd:element name="ne" type="docEmptyType" />
+      <xsd:element name="equiv" type="docEmptyType" />
+      <xsd:element name="le" type="docEmptyType" />
+      <xsd:element name="ge" type="docEmptyType" />
+      <xsd:element name="sub" type="docEmptyType" />
+      <xsd:element name="sup" type="docEmptyType" />
+      <xsd:element name="nsub" type="docEmptyType" />
+      <xsd:element name="sube" type="docEmptyType" />
+      <xsd:element name="supe" type="docEmptyType" />
+      <xsd:element name="oplus" type="docEmptyType" />
+      <xsd:element name="otimes" type="docEmptyType" />
+      <xsd:element name="perp" type="docEmptyType" />
+      <xsd:element name="sdot" type="docEmptyType" />
+      <xsd:element name="lceil" type="docEmptyType" />
+      <xsd:element name="rceil" type="docEmptyType" />
+      <xsd:element name="lfloor" type="docEmptyType" />
+      <xsd:element name="rfloor" type="docEmptyType" />
+      <xsd:element name="lang" type="docEmptyType" />
+      <xsd:element name="rang" type="docEmptyType" />
+      <xsd:element name="loz" type="docEmptyType" />
+      <xsd:element name="spades" type="docEmptyType" />
+      <xsd:element name="clubs" type="docEmptyType" />
+      <xsd:element name="hearts" type="docEmptyType" />
+      <xsd:element name="diams" type="docEmptyType" />
+      <xsd:element name="OElig" type="docEmptyType" />
+      <xsd:element name="oelig" type="docEmptyType" />
+      <xsd:element name="Scaron" type="docEmptyType" />
+      <xsd:element name="scaron" type="docEmptyType" />
+      <xsd:element name="Yumlaut" type="docEmptyType" />
+      <xsd:element name="circ" type="docEmptyType" />
+      <xsd:element name="tilde" type="docEmptyType" />
+      <xsd:element name="ensp" type="docEmptyType" />
+      <xsd:element name="emsp" type="docEmptyType" />
+      <xsd:element name="thinsp" type="docEmptyType" />
+      <xsd:element name="zwnj" type="docEmptyType" />
+      <xsd:element name="zwj" type="docEmptyType" />
+      <xsd:element name="lrm" type="docEmptyType" />
+      <xsd:element name="rlm" type="docEmptyType" />
+      <xsd:element name="ndash" type="docEmptyType" />
+      <xsd:element name="mdash" type="docEmptyType" />
+      <xsd:element name="lsquo" type="docEmptyType" />
+      <xsd:element name="rsquo" type="docEmptyType" />
+      <xsd:element name="sbquo" type="docEmptyType" />
+      <xsd:element name="ldquo" type="docEmptyType" />
+      <xsd:element name="rdquo" type="docEmptyType" />
+      <xsd:element name="bdquo" type="docEmptyType" />
+      <xsd:element name="dagger" type="docEmptyType" />
+      <xsd:element name="Dagger" type="docEmptyType" />
+      <xsd:element name="permil" type="docEmptyType" />
+      <xsd:element name="lsaquo" type="docEmptyType" />
+      <xsd:element name="rsaquo" type="docEmptyType" />
+      <xsd:element name="euro" type="docEmptyType" />
+      <xsd:element name="trademark" type="docEmptyType" />
+    </xsd:choice>
+  </xsd:group>
+
+  <xsd:complexType name="docTitleType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+  </xsd:complexType>
+
+  <xsd:group name="docCmdGroup">
+    <xsd:choice>
+      <xsd:group ref="docTitleCmdGroup"/>
+      <xsd:element name="linebreak" type="docEmptyType" />
+      <xsd:element name="hruler" type="docEmptyType" />
+      <xsd:element name="preformatted" type="docMarkupType" />
+      <xsd:element name="programlisting" type="listingType" />
+      <xsd:element name="verbatim" type="xsd:string" />
+      <xsd:element name="indexentry" type="docIndexEntryType" />
+      <xsd:element name="orderedlist" type="docListType" />
+      <xsd:element name="itemizedlist" type="docListType" />
+      <xsd:element name="simplesect" type="docSimpleSectType" />
+      <xsd:element name="title" type="docTitleType" />
+      <xsd:element name="variablelist" type="docVariableListType" />
+      <xsd:element name="table" type="docTableType" />
+      <xsd:element name="heading" type="docHeadingType" />
+      <xsd:element name="image" type="docImageType" />
+      <xsd:element name="dotfile" type="docFileType" />
+      <xsd:element name="mscfile" type="docFileType" />
+      <xsd:element name="diafile" type="docFileType" />
+      <xsd:element name="toclist" type="docTocListType" />
+      <xsd:element name="language" type="docLanguageType" />
+      <xsd:element name="parameterlist" type="docParamListType" />
+      <xsd:element name="xrefsect" type="docXRefSectType" />
+      <xsd:element name="copydoc" type="docCopyType" />
+      <xsd:element name="blockquote" type="docBlockQuoteType" />
+      <xsd:element name="parblock" type="docParBlockType" />
+    </xsd:choice>
+  </xsd:group>
+
+  <xsd:complexType name="docParaType" mixed="true">
+    <xsd:group ref="docCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docMarkupType" mixed="true">
+    <xsd:group ref="docCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docURLLink" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="url" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docAnchorType" mixed="true">
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docFormulaType" mixed="true">
+    <xsd:attribute name="id" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docIndexEntryType">
+    <xsd:sequence>
+      <xsd:element name="primaryie" type="xsd:string" />
+      <xsd:element name="secondaryie" type="xsd:string" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docListType">
+    <xsd:sequence>
+      <xsd:element name="listitem" type="docListItemType" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docListItemType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docSimpleSectType">
+    <xsd:sequence>
+      <xsd:element name="title" type="docTitleType" minOccurs="0" />
+      <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+        <xsd:element name="para" type="docParaType" minOccurs="1" maxOccurs="unbounded" />
+      </xsd:sequence>
+    </xsd:sequence>
+    <xsd:attribute name="kind" type="DoxSimpleSectKind" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docVarListEntryType">
+    <xsd:sequence>
+      <xsd:element name="term" type="docTitleType" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:group name="docVariableListGroup">
+    <xsd:sequence>
+      <xsd:element name="varlistentry" type="docVarListEntryType" />
+      <xsd:element name="listitem" type="docListItemType" />
+    </xsd:sequence>
+  </xsd:group>
+
+  <xsd:complexType name="docVariableListType">
+    <xsd:sequence>
+      <xsd:group ref="docVariableListGroup" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docRefTextType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="refid" type="xsd:string" />
+    <xsd:attribute name="kindref" type="DoxRefKind" />
+    <xsd:attribute name="external" type="xsd:string" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docTableType">
+    <xsd:sequence>
+      <xsd:element name="row" type="docRowType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="caption" type="docCaptionType" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="rows" type="xsd:integer" />
+    <xsd:attribute name="cols" type="xsd:integer" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docRowType">
+    <xsd:sequence>
+      <xsd:element name="entry" type="docEntryType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docEntryType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="thead" type="DoxBool" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docCaptionType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docHeadingType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="level" type="xsd:integer" /> <!-- todo: range 1-6 -->
+  </xsd:complexType>
+
+  <xsd:complexType name="docImageType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="type" type="DoxImageKind" /> 
+    <xsd:attribute name="name" type="xsd:string" /> 
+    <xsd:attribute name="width" type="xsd:string" /> 
+    <xsd:attribute name="height" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docFileType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="name" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docTocItemType" mixed="true">
+    <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" />
+    <xsd:attribute name="id" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docTocListType">
+    <xsd:sequence>
+      <xsd:element name="tocitem" type="docTocItemType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docLanguageType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="langid" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docParamListType">
+    <xsd:sequence>
+      <xsd:element name="parameteritem" type="docParamListItem" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+    <xsd:attribute name="kind" type="DoxParamListKind" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docParamListItem">
+    <xsd:sequence>
+      <xsd:element name="parameternamelist" type="docParamNameList" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="parameterdescription" type="descriptionType" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docParamNameList">
+    <xsd:sequence>
+      <xsd:element name="parametertype" type="docParamType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="parametername" type="docParamName" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docParamType" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="ref" type="refTextType" minOccurs="0" maxOccurs="1" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docParamName" mixed="true">
+    <xsd:sequence>
+      <xsd:element name="ref" type="refTextType" minOccurs="0" maxOccurs="1" />
+    </xsd:sequence>
+    <xsd:attribute name="direction" type="DoxParamDir" use="optional" />
+  </xsd:complexType>
+
+  <xsd:complexType name="docXRefSectType">
+    <xsd:sequence>
+      <xsd:element name="xreftitle" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="xrefdescription" type="descriptionType" />
+    </xsd:sequence>
+    <xsd:attribute name="id" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docCopyType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="sect1" type="docSect1Type" minOccurs="0" maxOccurs="unbounded" />
+      <xsd:element name="internal" type="docInternalType" minOccurs="0" />
+    </xsd:sequence>
+    <xsd:attribute name="link" type="xsd:string" /> 
+  </xsd:complexType>
+
+  <xsd:complexType name="docBlockQuoteType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docParBlockType">
+    <xsd:sequence>
+      <xsd:element name="para" type="docParaType" minOccurs="0" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="docEmptyType"/>
+
+  <!-- Simple types -->
+
+  <xsd:simpleType name="DoxBool">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="yes" />
+      <xsd:enumeration value="no" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxGraphRelation">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="include" />
+      <xsd:enumeration value="usage" />
+      <xsd:enumeration value="template-instance" />
+      <xsd:enumeration value="public-inheritance" />
+      <xsd:enumeration value="protected-inheritance" />
+      <xsd:enumeration value="private-inheritance" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxRefKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="compound" />
+      <xsd:enumeration value="member" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxMemberKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="define" />
+      <xsd:enumeration value="property" />
+      <xsd:enumeration value="event" />
+      <xsd:enumeration value="variable" />
+      <xsd:enumeration value="typedef" />
+      <xsd:enumeration value="enum" />
+      <xsd:enumeration value="function" />
+      <xsd:enumeration value="signal" />
+      <xsd:enumeration value="prototype" />
+      <xsd:enumeration value="friend" />
+      <xsd:enumeration value="dcop" />
+      <xsd:enumeration value="slot" />
+      <xsd:enumeration value="interface" />
+      <xsd:enumeration value="service" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxProtectionKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="public" />
+      <xsd:enumeration value="protected" />
+      <xsd:enumeration value="private" />
+      <xsd:enumeration value="package" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxVirtualKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="non-virtual" />
+      <xsd:enumeration value="virtual" />
+      <xsd:enumeration value="pure-virtual" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxCompoundKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="class" />
+      <xsd:enumeration value="struct" />
+      <xsd:enumeration value="union" />
+      <xsd:enumeration value="interface" />
+      <xsd:enumeration value="protocol" />
+      <xsd:enumeration value="category" />
+      <xsd:enumeration value="exception" />
+      <xsd:enumeration value="service" />
+      <xsd:enumeration value="singleton" />
+      <xsd:enumeration value="module" />
+      <xsd:enumeration value="type" />
+      <xsd:enumeration value="file" />
+      <xsd:enumeration value="namespace" />
+      <xsd:enumeration value="group" />
+      <xsd:enumeration value="page" />
+      <xsd:enumeration value="example" />
+      <xsd:enumeration value="dir" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxSectionKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="user-defined" />
+      <xsd:enumeration value="public-type" />
+      <xsd:enumeration value="public-func" />
+      <xsd:enumeration value="public-attrib" />
+      <xsd:enumeration value="public-slot" />
+      <xsd:enumeration value="signal" />
+      <xsd:enumeration value="dcop-func" />
+      <xsd:enumeration value="property" />
+      <xsd:enumeration value="event" />
+      <xsd:enumeration value="public-static-func" />
+      <xsd:enumeration value="public-static-attrib" />
+      <xsd:enumeration value="protected-type" />
+      <xsd:enumeration value="protected-func" />
+      <xsd:enumeration value="protected-attrib" />
+      <xsd:enumeration value="protected-slot" />
+      <xsd:enumeration value="protected-static-func" />
+      <xsd:enumeration value="protected-static-attrib" />
+      <xsd:enumeration value="package-type" />
+      <xsd:enumeration value="package-func" />
+      <xsd:enumeration value="package-attrib" />
+      <xsd:enumeration value="package-static-func" />
+      <xsd:enumeration value="package-static-attrib" />
+      <xsd:enumeration value="private-type" />
+      <xsd:enumeration value="private-func" />
+      <xsd:enumeration value="private-attrib" />
+      <xsd:enumeration value="private-slot" />
+      <xsd:enumeration value="private-static-func" />
+      <xsd:enumeration value="private-static-attrib" />
+      <xsd:enumeration value="friend" />
+      <xsd:enumeration value="related" />
+      <xsd:enumeration value="define" />
+      <xsd:enumeration value="prototype" />
+      <xsd:enumeration value="typedef" />
+      <xsd:enumeration value="enum" />
+      <xsd:enumeration value="func" />
+      <xsd:enumeration value="var" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxHighlightClass">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="comment" />
+      <xsd:enumeration value="normal" />
+      <xsd:enumeration value="preprocessor" />
+      <xsd:enumeration value="keyword" />
+      <xsd:enumeration value="keywordtype" />
+      <xsd:enumeration value="keywordflow" />
+      <xsd:enumeration value="stringliteral" />
+      <xsd:enumeration value="charliteral" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxSimpleSectKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="see" />
+      <xsd:enumeration value="return" />
+      <xsd:enumeration value="author" />
+      <xsd:enumeration value="authors" />
+      <xsd:enumeration value="version" />
+      <xsd:enumeration value="since" />
+      <xsd:enumeration value="date" />
+      <xsd:enumeration value="note" />
+      <xsd:enumeration value="warning" />
+      <xsd:enumeration value="pre" />
+      <xsd:enumeration value="post" />
+      <xsd:enumeration value="copyright" />
+      <xsd:enumeration value="invariant" />
+      <xsd:enumeration value="remark" />
+      <xsd:enumeration value="attention" />
+      <xsd:enumeration value="par" />
+      <xsd:enumeration value="rcs" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxVersionNumber">
+    <xsd:restriction base="xsd:string">
+      <xsd:pattern value="\d+\.\d+.*" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxImageKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="html" />
+      <xsd:enumeration value="latex" />
+      <xsd:enumeration value="rtf" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxParamListKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="param" />
+      <xsd:enumeration value="retval" />
+      <xsd:enumeration value="exception" />
+      <xsd:enumeration value="templateparam" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxCharRange">
+    <xsd:restriction base="xsd:string">
+      <xsd:pattern value="[aeiouncAEIOUNC]" />
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxParamDir">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="in"/>
+      <xsd:enumeration value="out"/>
+      <xsd:enumeration value="inout"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="DoxAccessor">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="retain"/>
+      <xsd:enumeration value="copy"/>
+      <xsd:enumeration value="assign"/>
+      <xsd:enumeration value="weak"/>
+      <xsd:enumeration value="strong"/>
+      <xsd:enumeration value="unretained"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+
+</xsd:schema>
+
diff --git a/contrib/neo_doxygen/tests/java-project/xml/dir_68267d1309a1af8e8297ef4c3efbcdba.xml b/contrib/neo_doxygen/tests/java-project/xml/dir_68267d1309a1af8e8297ef4c3efbcdba.xml
new file mode 100644 (file)
index 0000000..7113035
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="dir_68267d1309a1af8e8297ef4c3efbcdba" kind="dir">
+    <compoundname>src</compoundname>
+    <innerdir refid="dir_b8e0663afee48cb679b74bbd21bdf843">src/org</innerdir>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="%SOURCE_DIRECTORY%/"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/dir_8c35fc67c36f89d827afb23e8c52a418.xml b/contrib/neo_doxygen/tests/java-project/xml/dir_8c35fc67c36f89d827afb23e8c52a418.xml
new file mode 100644 (file)
index 0000000..3d720f8
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="dir_8c35fc67c36f89d827afb23e8c52a418" kind="dir">
+    <compoundname>src/org/example</compoundname>
+    <innerdir refid="dir_ad5d6582648a7bbb3a301939a41e6c0b">src/org/example/foo</innerdir>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="%SOURCE_DIRECTORY%/org/example/"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/dir_ad5d6582648a7bbb3a301939a41e6c0b.xml b/contrib/neo_doxygen/tests/java-project/xml/dir_ad5d6582648a7bbb3a301939a41e6c0b.xml
new file mode 100644 (file)
index 0000000..5280bb0
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="dir_ad5d6582648a7bbb3a301939a41e6c0b" kind="dir">
+    <compoundname>src/org/example/foo</compoundname>
+    <innerfile refid="_a_8java">A.java</innerfile>
+    <innerfile refid="_b_8java">B.java</innerfile>
+    <innerfile refid="_c_8java">C.java</innerfile>
+    <innerfile refid="_empty_class_8java">EmptyClass.java</innerfile>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="%SOURCE_DIRECTORY%/org/example/foo/"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/dir_b8e0663afee48cb679b74bbd21bdf843.xml b/contrib/neo_doxygen/tests/java-project/xml/dir_b8e0663afee48cb679b74bbd21bdf843.xml
new file mode 100644 (file)
index 0000000..193e7cd
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="dir_b8e0663afee48cb679b74bbd21bdf843" kind="dir">
+    <compoundname>src/org</compoundname>
+    <innerdir refid="dir_8c35fc67c36f89d827afb23e8c52a418">src/org/example</innerdir>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="%SOURCE_DIRECTORY%/org/"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/index.xml b/contrib/neo_doxygen/tests/java-project/xml/index.xml
new file mode 100644 (file)
index 0000000..cf3ded8
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygenindex xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="index.xsd" version="1.8.8">
+  <compound refid="classorg_1_1example_1_1foo_1_1_a" kind="class"><name>org::example::foo::A</name>
+    <member refid="classorg_1_1example_1_1foo_1_1_a_1add415ae4129969055d678c7e7e048852" kind="function"><name>bar</name></member>
+  </compound>
+  <compound refid="classorg_1_1example_1_1foo_1_1_b" kind="class"><name>org::example::foo::B</name>
+    <member refid="classorg_1_1example_1_1foo_1_1_b_1ac6b627949b10b9357eefc0cafcae1d87" kind="variable"><name>qux</name></member>
+    <member refid="classorg_1_1example_1_1foo_1_1_b_1a11e157943665cc9e3a9be1502ebeb3b5" kind="function"><name>bar</name></member>
+    <member refid="classorg_1_1example_1_1foo_1_1_b_1a733f4e076f29c7d0c41ed258199ea1d9" kind="function"><name>baz</name></member>
+  </compound>
+  <compound refid="interfaceorg_1_1example_1_1foo_1_1_c" kind="interface"><name>org::example::foo::C</name>
+    <member refid="interfaceorg_1_1example_1_1foo_1_1_c_1a4e97061eb40b045e820de05b33c43d21" kind="variable"><name>THE_ANSWER</name></member>
+    <member refid="interfaceorg_1_1example_1_1foo_1_1_c_1a28ac7ce349ebb3e4a7747a8dd951582b" kind="function"><name>baz</name></member>
+  </compound>
+  <compound refid="classorg_1_1example_1_1foo_1_1_empty_class" kind="class"><name>org::example::foo::EmptyClass</name>
+  </compound>
+  <compound refid="namespaceorg" kind="namespace"><name>org</name>
+  </compound>
+  <compound refid="namespaceorg_1_1example" kind="namespace"><name>org::example</name>
+  </compound>
+  <compound refid="namespaceorg_1_1example_1_1foo" kind="namespace"><name>org::example::foo</name>
+  </compound>
+  <compound refid="_a_8java" kind="file"><name>A.java</name>
+  </compound>
+  <compound refid="_b_8java" kind="file"><name>B.java</name>
+  </compound>
+  <compound refid="_c_8java" kind="file"><name>C.java</name>
+  </compound>
+  <compound refid="_empty_class_8java" kind="file"><name>EmptyClass.java</name>
+  </compound>
+  <compound refid="dir_8c35fc67c36f89d827afb23e8c52a418" kind="dir"><name>src/org/example</name>
+  </compound>
+  <compound refid="dir_ad5d6582648a7bbb3a301939a41e6c0b" kind="dir"><name>src/org/example/foo</name>
+  </compound>
+  <compound refid="dir_b8e0663afee48cb679b74bbd21bdf843" kind="dir"><name>src/org</name>
+  </compound>
+  <compound refid="dir_68267d1309a1af8e8297ef4c3efbcdba" kind="dir"><name>src</name>
+  </compound>
+</doxygenindex>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/index.xsd b/contrib/neo_doxygen/tests/java-project/xml/index.xsd
new file mode 100644 (file)
index 0000000..d7ab2a9
--- /dev/null
@@ -0,0 +1,66 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+  <xsd:element name="doxygenindex" type="DoxygenType"/>
+
+  <xsd:complexType name="DoxygenType">
+    <xsd:sequence>
+      <xsd:element name="compound" type="CompoundType" minOccurs="0" maxOccurs="unbounded"/>
+    </xsd:sequence>
+    <xsd:attribute name="version" type="xsd:string" use="required"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="CompoundType">
+    <xsd:sequence>
+      <xsd:element name="name" type="xsd:string"/>
+      <xsd:element name="member" type="MemberType" minOccurs="0" maxOccurs="unbounded"/>
+    </xsd:sequence>
+    <xsd:attribute name="refid" type="xsd:string" use="required"/>
+    <xsd:attribute name="kind" type="CompoundKind" use="required"/>
+  </xsd:complexType>
+
+  <xsd:complexType name="MemberType">
+    <xsd:sequence>
+      <xsd:element name="name" type="xsd:string"/>
+    </xsd:sequence>
+    <xsd:attribute name="refid" type="xsd:string" use="required"/>
+    <xsd:attribute name="kind" type="MemberKind" use="required"/>
+  </xsd:complexType>
+  
+  <xsd:simpleType name="CompoundKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="class"/>
+      <xsd:enumeration value="struct"/>
+      <xsd:enumeration value="union"/>
+      <xsd:enumeration value="interface"/>
+      <xsd:enumeration value="protocol"/>
+      <xsd:enumeration value="category"/>
+      <xsd:enumeration value="exception"/>
+      <xsd:enumeration value="file"/>
+      <xsd:enumeration value="namespace"/>
+      <xsd:enumeration value="group"/>
+      <xsd:enumeration value="page"/>
+      <xsd:enumeration value="example"/>
+      <xsd:enumeration value="dir"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+
+  <xsd:simpleType name="MemberKind">
+    <xsd:restriction base="xsd:string">
+      <xsd:enumeration value="define"/>
+      <xsd:enumeration value="property"/>
+      <xsd:enumeration value="event"/>
+      <xsd:enumeration value="variable"/>
+      <xsd:enumeration value="typedef"/>
+      <xsd:enumeration value="enum"/>
+      <xsd:enumeration value="enumvalue"/>
+      <xsd:enumeration value="function"/>
+      <xsd:enumeration value="signal"/>
+      <xsd:enumeration value="prototype"/>
+      <xsd:enumeration value="friend"/>
+      <xsd:enumeration value="dcop"/>
+      <xsd:enumeration value="slot"/>
+    </xsd:restriction>
+  </xsd:simpleType>
+
+</xsd:schema>
+
diff --git a/contrib/neo_doxygen/tests/java-project/xml/interfaceorg_1_1example_1_1foo_1_1_c.xml b/contrib/neo_doxygen/tests/java-project/xml/interfaceorg_1_1example_1_1foo_1_1_c.xml
new file mode 100644 (file)
index 0000000..aec6243
--- /dev/null
@@ -0,0 +1,60 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="interfaceorg_1_1example_1_1foo_1_1_c" kind="interface" prot="public">
+    <compoundname>org::example::foo::C</compoundname>
+    <derivedcompoundref refid="classorg_1_1example_1_1foo_1_1_b" prot="public" virt="non-virtual">org.example.foo.B</derivedcompoundref>
+      <sectiondef kind="public-static-attrib">
+      <memberdef kind="variable" id="interfaceorg_1_1example_1_1foo_1_1_c_1a4e97061eb40b045e820de05b33c43d21" prot="public" static="yes" mutable="no">
+        <type>final long</type>
+        <definition>final long org.example.foo.C.THE_ANSWER</definition>
+        <argsstring></argsstring>
+        <name>THE_ANSWER</name>
+        <initializer>= 42L</initializer>
+        <briefdescription>
+        </briefdescription>
+        <detaileddescription>
+<para>“Answer to the Ultimate Question of Life, the Universe, and Everything.“ </para>        </detaileddescription>
+        <inbodydescription>
+        </inbodydescription>
+        <location file="%SOURCE_DIRECTORY%/org/example/foo/C.java" line="25" column="1" bodyfile="%SOURCE_DIRECTORY%/org/example/foo/C.java" bodystart="25" bodyend="-1"/>
+      </memberdef>
+      </sectiondef>
+      <sectiondef kind="public-func">
+      <memberdef kind="function" id="interfaceorg_1_1example_1_1foo_1_1_c_1a28ac7ce349ebb3e4a7747a8dd951582b" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual">
+        <type>void</type>
+        <definition>void org.example.foo.C.baz</definition>
+        <argsstring>()</argsstring>
+        <name>baz</name>
+        <reimplementedby refid="classorg_1_1example_1_1foo_1_1_b_1a733f4e076f29c7d0c41ed258199ea1d9">baz</reimplementedby>
+        <briefdescription>
+        </briefdescription>
+        <detaileddescription>
+<para><ref refid="classorg_1_1example_1_1foo_1_1_a" kindref="compound">A</ref> function with implicit modifiers. </para>        </detaileddescription>
+        <inbodydescription>
+        </inbodydescription>
+        <location file="%SOURCE_DIRECTORY%/org/example/foo/C.java" line="30" column="1"/>
+      </memberdef>
+      </sectiondef>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+<para>An interface </para>    </detaileddescription>
+    <inheritancegraph>
+      <node id="10">
+        <label>org.example.foo.B</label>
+        <link refid="classorg_1_1example_1_1foo_1_1_b"/>
+        <childnode refid="9" relation="public-inheritance">
+        </childnode>
+      </node>
+      <node id="9">
+        <label>org.example.foo.C</label>
+        <link refid="interfaceorg_1_1example_1_1foo_1_1_c"/>
+      </node>
+    </inheritancegraph>
+    <location file="%SOURCE_DIRECTORY%/org/example/foo/C.java" line="21" column="1" bodyfile="%SOURCE_DIRECTORY%/org/example/foo/C.java" bodystart="21" bodyend="31"/>
+    <listofallmembers>
+      <member refid="interfaceorg_1_1example_1_1foo_1_1_c_1a28ac7ce349ebb3e4a7747a8dd951582b" prot="public" virt="non-virtual"><scope>org::example::foo::C</scope><name>baz</name></member>
+      <member refid="interfaceorg_1_1example_1_1foo_1_1_c_1a4e97061eb40b045e820de05b33c43d21" prot="public" virt="non-virtual"><scope>org::example::foo::C</scope><name>THE_ANSWER</name></member>
+    </listofallmembers>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/namespaceorg.xml b/contrib/neo_doxygen/tests/java-project/xml/namespaceorg.xml
new file mode 100644 (file)
index 0000000..43d6207
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="namespaceorg" kind="namespace">
+    <compoundname>org</compoundname>
+    <innernamespace refid="namespaceorg_1_1example">org::example</innernamespace>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="[generated]" line="1" column="1"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/namespaceorg_1_1example.xml b/contrib/neo_doxygen/tests/java-project/xml/namespaceorg_1_1example.xml
new file mode 100644 (file)
index 0000000..ee8d878
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="namespaceorg_1_1example" kind="namespace">
+    <compoundname>org::example</compoundname>
+    <innernamespace refid="namespaceorg_1_1example_1_1foo">org::example::foo</innernamespace>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="[generated]" line="1" column="1"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/neo_doxygen/tests/java-project/xml/namespaceorg_1_1example_1_1foo.xml b/contrib/neo_doxygen/tests/java-project/xml/namespaceorg_1_1example_1_1foo.xml
new file mode 100644 (file)
index 0000000..a307c92
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version='1.0' encoding='UTF-8' standalone='no'?>
+<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="1.8.8">
+  <compounddef id="namespaceorg_1_1example_1_1foo" kind="namespace">
+    <compoundname>org::example::foo</compoundname>
+    <innerclass refid="classorg_1_1example_1_1foo_1_1_a" prot="public">org::example::foo::A</innerclass>
+    <innerclass refid="classorg_1_1example_1_1foo_1_1_b" prot="public">org::example::foo::B</innerclass>
+    <innerclass refid="interfaceorg_1_1example_1_1foo_1_1_c" prot="public">org::example::foo::C</innerclass>
+    <innerclass refid="classorg_1_1example_1_1foo_1_1_empty_class" prot="package">org::example::foo::EmptyClass</innerclass>
+    <briefdescription>
+    </briefdescription>
+    <detaileddescription>
+    </detaileddescription>
+    <location file="%SOURCE_DIRECTORY%/org/example/foo/A.java" line="16" column="1"/>
+  </compounddef>
+</doxygen>
diff --git a/contrib/nitiwiki/.gitignore b/contrib/nitiwiki/.gitignore
new file mode 100644 (file)
index 0000000..89f9ac0
--- /dev/null
@@ -0,0 +1 @@
+out/
diff --git a/contrib/nitiwiki/Makefile b/contrib/nitiwiki/Makefile
new file mode 100644 (file)
index 0000000..8e385f9
--- /dev/null
@@ -0,0 +1,15 @@
+all: nitiwiki
+
+nitiwiki:
+       mkdir -p bin
+       ../../bin/nitc src/nitiwiki.nit -o bin/nitiwiki
+
+tests: nitiwiki
+       cd tests; make
+
+doc:
+       ../../bin/nitdoc -d doc src/nitiwiki.nit
+
+clean:
+       rm -rf bin
+       rm -rf -- .nit_compile 2> /dev/null || true
diff --git a/contrib/nitiwiki/README.md b/contrib/nitiwiki/README.md
new file mode 100644 (file)
index 0000000..abe84ad
--- /dev/null
@@ -0,0 +1,291 @@
+# nitiwiki, a simple wiki manager based on markdown.
+
+Basically, nitiwiki compiles a set of markdown files into an HTML wiki.
+
+The wiki content is structured by `sections` represented by the wiki folders. Sections can contain `articles` represented by markdown files.
+
+Features:
+
+* automatic wiki structure from folders hierarchy
+* automatic site menu
+* automatic sitemap
+* automatic summaries
+* easy and rapid templating
+* customizable section templates and menus
+* rsync synchronization
+* git synchronization
+
+## Wiki structure
+
+Basic wiki structure:
+
+       root
+       |- assets
+       |- out
+       |- pages
+       |- templates
+       |       |- footer.html
+       |       |- header.html
+       |       |- menu.html
+       |       `- template.html
+       `- config.ini
+
+### pages
+
+This is where goes all the content of your wiki.
+Nitiwiki will render an article for each markdown file found in `pages`.
+
+You can categorize your content in sections using sub-folders:
+
+       pages
+       |- section1
+       |       `- index.md
+       |- section2
+       |       `- index.md
+       |- page1.md
+       |- page2.md
+       `- index.md
+
+### assets
+
+This is where you store CSS and JavaScript files used in the design of your site.
+
+You can also use this directory to put some images or other files that will be
+used in all your pages.
+
+       assets
+       |- css
+       |- js
+       `- logo.png
+
+### templates
+
+This folder contains the templates used to generate the HTML pages of your wiki.
+
+The main template is called `template.html`.
+It contains the HTML structure of your pages and some macros that will be replaced
+by the wiki articles.
+
+### out
+
+This is where your wiki will be rendered by nitiwiki.
+Do not put anything in this folder since it will be overwritten at the
+next wiki rendering.
+
+The wiki rendering consists in:
+
+1. copy the `assets` directory to `out`
+2. copy attached article files from `pages` to `out`
+3. translate markdown files from `pages` to html files in `out`
+
+### config.ini
+
+This is the main config file of your wiki. For more details see [Configure the wiki](#Configure_the_wiki).
+
+## Manage the wiki
+
+### Create a new wiki
+
+Just move to the directory where you want to store your source files and type:
+
+       nitiwiki init
+
+This command will import the base structure of your wiki in the current directory.
+At this point nitiwiki has created the main configuration file of your site:
+`config.ini`.
+
+### Configure the wiki
+
+All the nitiwiki configuration is done using
+[ini files](http://en.wikipedia.org/wiki/INI_file).
+
+The wiki configuration is contained in the `config.ini` file located at the root
+directory of your wiki.
+This file can be edited to change nitiwiki settings.
+
+Settings:
+
+* `wiki.name`: Displayed name
+* `wiki.desc`: Long description
+* `wiki.logo`: Logo image url
+* `wiki.root_url`: Base url used to resolve links
+* `wiki.root_dir`: Absolute path of base directory
+* `wiki.source_dir`: Source directory (relative path from `wiki.root_dir`)
+* `wiki.out_dir`: Output directory (relative)
+* `wiki.assets_dir`: Assets directory (relative)
+* `wiki.templates_dir`: Templates directory (relative)
+* `wiki.template`: Wiki main template file
+* `wiki.header`: Wiki main header template file
+* `wiki.footer`: Wiki main footer template file
+* `wiki.menu`: Wiki main menu template file
+* `wiki.rsync_dir`: Directory used to rsync output
+* `wiki.git_origin`: Git origin used to fetch data
+* `wiki.git_branch`: Git branch used to fetch data
+
+For more details on each option see `WikiConfig`.
+
+### Add content
+
+To add content in your wiki simply add markdown files (with `.md` extension) into the `pages/` folder.
+
+Once you have done your changes, use:
+
+       nitiwiki --status
+
+This will show the impacts of your changes on the wiki structure.
+
+Then type:
+
+       nitiwiki --render
+
+This will the generate the html output of your new content.
+The option `--force` can be used to regenerate all the wiki.
+This can be uselful when you perform changes on the template files.
+
+### Configure sections
+
+Section appearance can be customized using config files.
+
+Each section in the `pages/` folder can contain a `config.ini` file.
+Options set on a section will be propagated to all its children unless
+they have their own config file.
+
+Allowed options are:
+
+* `section.title`: Custom title for this section
+* `section.template`: Custom template file
+* `section.header`: Custom header template file
+* `section.footer`: Custom footer template file
+* `section.menu`: Custom menu template file
+* `section.is_hidden`: Set this to `true` will hide the section in all menus and
+  sitemaps.
+
+## Customize templates
+
+Templating your wiki involves modifying 4 template files:
+
+* `template.html`
+* `header.html`
+* `footer.html`
+* `menu.html`
+
+Each of these file contains an HTML skeletton used by nitiwiki to render your files.
+Templates can contains macros marked `%MACRO%` that will be replaced by dynamic content.
+
+Every template can access to:
+
+* `ROOT_URL`: Wiki root url
+* `TITLE`: Wiki name
+* `SUBTITLE`: Wiki description
+* `LOGO`: Wiki logo image path
+
+Additionnal macros can be used in specialized templates.
+
+### Main template
+
+The template file `template.html` represents the overall structure of your wiki pages.
+
+       <!DOCTYPE html>
+       <html>
+               <head>
+                       <title>%TITLE%</title>
+                       <link href="%ROOT_URL%/assets/css/main.css" rel="stylesheet">
+               </head>
+               <body>
+                       %HEADER%
+                       %TOP_MENU%
+                       <div>
+                               %BODY%
+                               %FOOTER%
+                       </div>
+               </body>
+       </html>
+
+Additionnal macros:
+
+* `HEADER`: Wiki header (see [Header template](#Header_template))
+* `FOOTER`: Wiki footer (see [Footer template](#Footer_template))
+* `TOP_MENU`: Wiki top menu (see [Topmenu template](#Topmenu_template))
+* `HEADER`: Wiki header (see [Header template](#Header_template))
+* `BODY`: Wiki body content
+
+### Header template
+
+The template file `header.html` is generated on top of all the wiki pages.
+
+       <header>
+               <a href="#"><img src="%ROOT_URL%/%LOGO%" alt="logo"/></a>
+               <h2>%SUBTITLE%</h2>
+               <h1>%TITLE%</h1>
+       </header>
+
+### Footer template
+
+The template file `footer.html` is generated on the bottom of all the wiki pages.
+
+       <footer>
+               <p>%TITLE% &copy; %YEAR%</p>
+               <p>last modification %GEN_TIME%</p>
+       </footer>
+
+Additionnal macros:
+
+* `YEAR`: Current year
+* `GEN_TIME`: Page generation date
+
+### Topmenu template
+
+The template file `menu.html` contains the menu structure generated on all your pages.
+
+Its content can be static:
+
+       <nav class="menu">
+               <ul class="nav navbar-nav">
+                       <li><a href="#">Home</a></li>
+                       <li><a href="#">Page1</a></li>
+                       <li><a href="#">Page2</a></li>
+               </ul>
+       </nav>
+
+Or dynamic using the macro `MENUS`:
+
+       <nav class="menu">
+               <ul class="nav navbar-nav">
+               %MENUS%
+               </ul>
+       </nav>
+
+## Advanced usages
+
+### Working with git
+
+nitiwiki allows you to store your wiki changes in git.
+Using the option `--fetch` will update the local wiki instance
+according to git informations found in the config file.
+
+Be sure to set `wiki.git_origin` and `wiki.git_branch`
+in order to correctly pull changes.
+
+To automatically update your wiki when changes are pushed on the
+origin repository you can use the following command in a git hook:
+
+       nitiwiki --fetch --render
+
+### Working with a remote server
+
+Sometimes you cannot do what you want on your webserver (like setting crons).
+For this purpose, nitiwiki provide a quick way to update a distant instance
+through `ssh` using `rsync`.
+
+With the option `--rsync`, nitwiki will update a distant location with the
+last rendered output. This way you can manually update your webserver
+after changes or set a cron on a different server that you can control.
+
+Using the following command in your cron will update the web server instance
+from git:
+
+       nitiwiki --fetch --render --rsync
+
+Be sure to set `wiki.rsync_dir` in order to correctly push your changes.
+When using `--rsync`, keep in mind that the rendered output must be configured
+to work on the web server and set `wiki.root_url` accordingly.
diff --git a/contrib/nitiwiki/examples/default/config.ini b/contrib/nitiwiki/examples/default/config.ini
new file mode 100644 (file)
index 0000000..21e85ef
--- /dev/null
@@ -0,0 +1,5 @@
+wiki.name=MyWiki
+wiki.desc=proudly powered by nit
+wiki.logo=assets/logo.png
+wiki.root_url=http://localhost/
+wiki.root_dir=/full/path/to/your/wiki/root/dir
diff --git a/contrib/nitiwiki/examples/default/pages/index.md b/contrib/nitiwiki/examples/default/pages/index.md
new file mode 100644 (file)
index 0000000..b212ceb
--- /dev/null
@@ -0,0 +1 @@
+# Welcome on nitiwiki
diff --git a/contrib/nitiwiki/examples/default/templates/footer.html b/contrib/nitiwiki/examples/default/templates/footer.html
new file mode 100644 (file)
index 0000000..7c8de99
--- /dev/null
@@ -0,0 +1,4 @@
+<footer>
+    <p>%TITLE% &copy; %YEAR%</p>
+    <p>last modification %GEN_TIME%</p>
+</footer>
diff --git a/contrib/nitiwiki/examples/default/templates/header.html b/contrib/nitiwiki/examples/default/templates/header.html
new file mode 100644 (file)
index 0000000..d86aac9
--- /dev/null
@@ -0,0 +1,5 @@
+<header>
+    <a href="#"><img src="%ROOT_URL%/%LOGO%" alt="logo"/></a>
+    <h2>%SUBTITLE%</h2>
+    <h1>%TITLE%</h1>
+</header>
diff --git a/contrib/nitiwiki/examples/default/templates/menu.html b/contrib/nitiwiki/examples/default/templates/menu.html
new file mode 100644 (file)
index 0000000..76a6f95
--- /dev/null
@@ -0,0 +1,5 @@
+<nav class="menu">
+    <ul class="nav navbar-nav">
+    %MENUS%
+    </ul>
+</nav>
diff --git a/contrib/nitiwiki/examples/default/templates/template.html b/contrib/nitiwiki/examples/default/templates/template.html
new file mode 100644 (file)
index 0000000..692a999
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>%TITLE%</title>
+        <link href="%ROOT_URL%/assets/css/main.css" rel="stylesheet">
+    </head>
+    <body>
+        %HEADER%
+        %TOP_MENU%
+        <div>
+            %BODY%
+            %FOOTER%
+        </div>
+    </body>
+</html>
diff --git a/contrib/nitiwiki/examples/nitiwiki/assets/css/main.css b/contrib/nitiwiki/examples/nitiwiki/assets/css/main.css
new file mode 100644 (file)
index 0000000..c00394a
--- /dev/null
@@ -0,0 +1,30 @@
+header { margin: 15px 0; }
+header img {
+       padding: 10px;
+       float: left;
+}
+header h1, header h2 { display: none; }
+
+footer {
+       margin-top: 30px;
+       text-align: center;
+}
+
+.menu {
+       border-top: 6px solid #47CA42;
+       background-color: #0d8921;
+}
+
+.menu .navbar-brand, .menu a { color: #fff; }
+.menu .navbar-nav>.active>a, .menu .navbar-nav>li>a:hover { background-color: #47CA42; }
+
+.sidebar { margin-top: 20px; }
+
+.summary a { color: #333; }
+.summary a:hover { text-decoration: none; }
+.summary a:hover, .summary li:active>a { color: #428bca; }
+.summary li { padding: 2px 0; font-weight: bold }
+.summary li li { font-size: 13px;}
+.summary li li li { font-size: 12px; font-weight: normal }
+
+.breadcrumb { margin-top: 20px; }
diff --git a/contrib/nitiwiki/examples/nitiwiki/assets/logo.png b/contrib/nitiwiki/examples/nitiwiki/assets/logo.png
new file mode 100644 (file)
index 0000000..daccc80
Binary files /dev/null and b/contrib/nitiwiki/examples/nitiwiki/assets/logo.png differ
diff --git a/contrib/nitiwiki/examples/nitiwiki/config.ini b/contrib/nitiwiki/examples/nitiwiki/config.ini
new file mode 100644 (file)
index 0000000..16eaffe
--- /dev/null
@@ -0,0 +1,6 @@
+wiki.name=nitiwiki
+wiki.desc=proudly powered by nit
+wiki.logo=assets/logo.png
+wiki.root_url=http://moz-code.org/nitiwiki/
+wiki.root_dir=.
+wiki.rsync_dir=moz-code.org:nitiwiki/
diff --git a/contrib/nitiwiki/examples/nitiwiki/pages/index.md b/contrib/nitiwiki/examples/nitiwiki/pages/index.md
new file mode 120000 (symlink)
index 0000000..8a33348
--- /dev/null
@@ -0,0 +1 @@
+../../../README.md
\ No newline at end of file
diff --git a/contrib/nitiwiki/examples/nitiwiki/templates/footer.html b/contrib/nitiwiki/examples/nitiwiki/templates/footer.html
new file mode 100644 (file)
index 0000000..94229ea
--- /dev/null
@@ -0,0 +1,10 @@
+<footer class="row">
+       <div class="container-fluid">
+               <div class="well well-sm">
+                       <p><strong>%TITLE% &copy; %YEAR%</strong></p>
+                       <p class="text-muted"><em>last modification %GEN_TIME%</em></p>
+                       <p class="text-muted">Proudly powered by
+                               <a href="http://nitlanguage.org">nit</a>!</p>
+               </div>
+       </div>
+</footer>
diff --git a/contrib/nitiwiki/examples/nitiwiki/templates/header.html b/contrib/nitiwiki/examples/nitiwiki/templates/header.html
new file mode 100644 (file)
index 0000000..8b06ab8
--- /dev/null
@@ -0,0 +1,9 @@
+<div class="container-fluid header">
+       <div class="container">
+               <header>
+                       <a href="http://uqam.ca"><img src="%ROOT_URL%/%LOGO%" alt="logo" /></a>
+                       <h2>%SUBTITLE%</h2>
+                       <h1>%TITLE%</h1>
+               </header>
+       </div>
+</div>
diff --git a/contrib/nitiwiki/examples/nitiwiki/templates/menu.html b/contrib/nitiwiki/examples/nitiwiki/templates/menu.html
new file mode 100644 (file)
index 0000000..1ff832e
--- /dev/null
@@ -0,0 +1,20 @@
+<nav class="menu" role="navigation">
+       <div class="container">
+               <!-- Brand and toggle get grouped for better mobile display -->
+               <div class="navbar-header">
+                       <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
+                               <span class="sr-only">Toggle navigation</span>
+                               <span class="icon-bar"></span>
+                               <span class="icon-bar"></span>
+                               <span class="icon-bar"></span>
+                       </button>
+                       <a class="navbar-brand" href="%ROOT_URL%index.html">%TITLE%</a>
+               </div>
+               <!-- Collect the nav links, forms, and other content for toggling -->
+               <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+                       <ul class="nav navbar-nav">
+                       %MENUS%
+                       </ul>
+               </div><!-- /.navbar-collapse -->
+       </div>
+</nav>
diff --git a/contrib/nitiwiki/examples/nitiwiki/templates/template.html b/contrib/nitiwiki/examples/nitiwiki/templates/template.html
new file mode 100644 (file)
index 0000000..7c43833
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+       <head>
+               <meta charset="utf-8">
+               <meta http-equiv="X-UA-Compatible" content="IE=edge">
+               <meta name="viewport" content="width=device-width, initial-scale=1">
+               <title>%TITLE%</title>
+
+               <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
+               <link href="%ROOT_URL%/assets/css/main.css" rel="stylesheet">
+
+               <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
+               <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+               <!--[if lt IE 9]>
+               <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+               <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+               <![endif]-->
+       </head>
+       <body>
+               %HEADER%
+               %TOP_MENU%
+               <div class="container">
+                       <div class="row">
+                               %BODY%
+                       </div>
+                       %FOOTER%
+               </div>
+
+               <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
+               <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
+       </body>
+</html>
diff --git a/contrib/nitiwiki/src/nitiwiki.nit b/contrib/nitiwiki/src/nitiwiki.nit
new file mode 100644 (file)
index 0000000..200f971
--- /dev/null
@@ -0,0 +1,163 @@
+# 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.
+
+# A wiki engine based on markdown files and git.
+module nitiwiki
+
+import wiki_html
+
+# Locate nit directory
+private fun compute_nit_dir(opt_nit_dir: OptionString): String do
+       # the option has precedence
+       var res = opt_nit_dir.value
+       if res != null then
+               if not check_nit_dir(res) then
+                       print "Fatal Error: --nit-dir does not seem to be a valid base Nit directory: {res}"
+                       exit 1
+               end
+               return res
+       end
+
+       # then the environ variable has precedence
+       res = "NIT_DIR".environ
+       if not res.is_empty then
+               if not check_nit_dir(res) then
+                       print "Fatal Error: NIT_DIR does not seem to be a valid base Nit directory: {res}"
+                       exit 1
+               end
+               return res
+       end
+
+       # find the runpath of the program from argv[0]
+       res = "{sys.program_name.dirname}/.."
+       if check_nit_dir(res) then return res.simplify_path
+
+       # find the runpath of the process from /proc
+       var exe = "/proc/self/exe"
+       if exe.file_exists then
+               res = exe.realpath
+               res = res.dirname.join_path("..")
+               if check_nit_dir(res) then return res.simplify_path
+       end
+
+       # search in the PATH
+       var ps = "PATH".environ.split(":")
+       for p in ps do
+               res = p/".."
+               if check_nit_dir(res) then return res.simplify_path
+       end
+
+       print "Fatal Error: Cannot locate a valid base nit directory. It is quite unexpected. Try to set the environment variable `NIT_DIR` or to use the `--nit-dir` option."
+       exit 1
+       abort
+end
+
+private fun check_nit_dir(res: String): Bool do
+       return res.file_exists and "{res}/src/nit.nit".file_exists
+end
+
+var opt_help = new OptionBool("Display this help message", "-h", "--help")
+var opt_verbose = new OptionCount("Verbose level", "-v")
+var opt_config = new OptionString("Path to config.ini file", "-c", "--config")
+var opt_init = new OptionBool("Initialize a new wiki in the current directory", "--init")
+var opt_status = new OptionBool("Display wiki status", "-s", "--status")
+var opt_render = new OptionBool("Render the out directory from markdown sources", "-r", "--render")
+var opt_force = new OptionBool("Force render even if source files are unchanged", "-f", "--force")
+var opt_clean = new OptionBool("Clean the output directory", "--clean")
+var opt_rsync = new OptionBool("Synchronize outdir with distant wiki using rsync", "-s", "--rsync")
+var opt_fetch = new OptionBool("Render local source from git repo", "--fetch")
+var opt_nit_dir = new OptionString("Nit base directory", "--nit-dir")
+
+var context = new OptionContext
+context.add_option(opt_help, opt_verbose, opt_config)
+context.add_option(opt_init, opt_status, opt_render, opt_force)
+context.add_option(opt_clean, opt_rsync, opt_fetch, opt_nit_dir)
+context.parse(args)
+
+var config_filename = "config.ini"
+
+# --help
+if opt_help.value then
+       context.usage
+       exit 0
+end
+
+# --init
+if opt_init.value then
+       if config_filename.file_exists then
+               print "Already in a nitiwiki directory."
+               exit 0
+       end
+       var nitiwiki_home = "{compute_nit_dir(opt_nit_dir)}/contrib/nitiwiki"
+       var tpl = "{nitiwiki_home}/examples/default/"
+       if not tpl.file_exists then
+               print "Cannot find {tpl} files."
+               print "Maybe your NIT_DIR is not set properly?"
+               print "You can initialize nitiwiki manually by copying the default skeletton here."
+               exit 1
+       end
+       sys.system "cp -R {tpl}/* ."
+       print "Initialized new nitiwiki."
+       print "Set wiki settings by editing {config_filename}."
+       exit 0
+end
+
+# load config files
+
+# --config
+var config_file = opt_config.value
+if config_file == null then
+       config_file = config_filename
+end
+
+if not config_file.file_exists then
+       print "Not in a nitiwiki directory."
+       print "Use --init to initialize one here."
+       exit 0
+end
+
+var config = new WikiConfig(config_file)
+var wiki = new Nitiwiki(config)
+
+# --verbose
+wiki.verbose_level = opt_verbose.value
+
+# --clean
+if opt_clean.value then
+       wiki.clean
+end
+
+# --fetch
+if opt_fetch.value then
+       wiki.fetch
+end
+
+# --render
+if opt_render.value then
+       wiki.parse
+       # --force
+       wiki.force_render = opt_force.value
+       wiki.render
+end
+
+# --rsync
+if opt_rsync.value then
+       wiki.sync
+end
+
+# --status
+if opt_status.value or args.is_empty then
+       wiki.parse
+       wiki.status
+end
diff --git a/contrib/nitiwiki/src/wiki_base.nit b/contrib/nitiwiki/src/wiki_base.nit
new file mode 100644 (file)
index 0000000..2c0276b
--- /dev/null
@@ -0,0 +1,744 @@
+# 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.
+
+# Base entities of a nitiwiki.
+module wiki_base
+
+import template::macro
+import markdown
+import opts
+import ini
+
+# A Nitiwiki instance.
+#
+# Nitiwiki provide all base services used by `WikiSection` and `WikiArticle`.
+# It manages content and renders pages.
+#
+# Each nitiwiki instance is linked to a config file.
+# This file show to `nitiwiki` that a wiki is present in the current directory.
+# Without it, nitiwiki will consider the directory as empty.
+class Nitiwiki
+
+       # Wiki config object.
+       var config: WikiConfig
+
+       # Default config filename.
+       var config_filename = "config.ini"
+
+       # Force render on all file even if the source is unmodified.
+       var force_render = false is writable
+
+       # Verbosity level.
+       var verbose_level = 0 is writable
+
+       # Delete all the output files.
+       fun clean do
+               var out_dir = expand_path(config.root_dir, config.out_dir)
+               if out_dir.file_exists then out_dir.rmdir
+       end
+
+       # Synchronize local output with the distant `WikiConfig::rsync_dir`.
+       fun sync do
+               var root = expand_path(config.root_dir, config.out_dir)
+               sys.system "rsync -vr --delete {root}/ {config.rsync_dir}"
+       end
+
+       fun fetch do
+               sys.system "git pull {config.git_origin} {config.git_branch}"
+       end
+
+       # Analyze wiki files from `dir` to build wiki entries.
+       #
+       # This method build a hierarchical structure of `WikiSection` and `WikiArticle`
+       # based on the markdown source structure.
+       fun parse do
+               var dir = expand_path(config.root_dir, config.source_dir)
+               root_section = new_section(dir)
+               var files = list_md_files(dir)
+               for file in files do
+                       new_article(file)
+               end
+       end
+
+       # Show wiki status.
+       fun status do
+               print "nitiWiki"
+               print "name: {config.wiki_name}"
+               print "config: {config.ini_file}"
+               print "url: {config.root_url}"
+               print ""
+               if root_section.is_dirty then
+                       print "There is modified files:"
+                       var paths = entries.keys.to_a
+                       var s = new DefaultComparator
+                       s.sort(paths)
+                       for path in paths do
+                               var entry = entries[path]
+                               if not entry.is_dirty then continue
+                               var name = entry.name
+                               if entry.has_source then name = entry.src_path.to_s
+                               if entry.is_new then
+                                       print " + {name}"
+                               else
+                                       print " * {name}"
+                               end
+                       end
+                       print ""
+                       print "Use nitiwiki --render to render modified files"
+               else
+                       print "Wiki is up-to-date"
+                       print ""
+                       print "Use nitiwiki --fetch to pull modification from origin"
+                       print "Use nitiwiki --rsync to synchronize distant output"
+               end
+       end
+
+       # Display msg if `level >= verbose_level`
+       fun message(msg: String, level: Int) do
+               if level <= verbose_level then print msg
+       end
+
+       # List markdown source files from a directory.
+       fun list_md_files(dir: String): Array[String] do
+               var files = new Array[String]
+               var pipe = new IProcess("find", dir, "-name", "*.md")
+               while not pipe.eof do
+                       var file = pipe.read_line
+                       if file == "" then break # last line
+                       file = file.substring(0, file.length - 1) # strip last oef
+                       var name = file.basename(".md")
+                       if name == "header" or name == "footer" or name == "menu" then continue
+                       files.add file
+               end
+               pipe.close
+               pipe.wait
+               if pipe.status != 0 then exit 1
+               var s = new DefaultComparator
+               s.sort(files)
+               return files
+       end
+
+       # Does `src` have been modified since `target` creation?
+       #
+       # Always returns `true` if `--force` is on.
+       fun need_render(src, target: String): Bool do
+               if force_render then return true
+               if not target.file_exists then return true
+               return src.file_stat.mtime >= target.file_stat.mtime
+       end
+
+       # Create a new `WikiSection`.
+       #
+       # `path` is used to determine the place in the wiki hierarchy.
+       protected fun new_section(path: String): WikiSection do
+               path = path.simplify_path
+               if entries.has_key(path) then return entries[path].as(WikiSection)
+               var root = expand_path(config.root_dir, config.source_dir)
+               var name = path.basename("")
+               var section = new WikiSection(self, name)
+               entries[path] = section
+               if path == root then return section
+               var ppath = path.dirname
+               if ppath != path  then
+                       var parent = new_section(ppath)
+                       parent.add_child(section)
+               end
+               section.try_load_config
+               return section
+       end
+
+       # Create a new `WikiArticle`.
+       #
+       # `path` is used to determine the ancestor sections.
+       protected fun new_article(path: String): WikiArticle do
+               if entries.has_key(path) then return entries[path].as(WikiArticle)
+               var article = new WikiArticle.from_source(self, path)
+               var section = new_section(path.dirname)
+               section.add_child(article)
+               entries[path] = article
+               return article
+       end
+
+       # Wiki entries found in the last `lookup_hierarchy`.
+       var entries = new HashMap[String, WikiEntry]
+
+       # The root `WikiSection` of the site found in the last `lookup_hierarchy`.
+       var root_section: WikiSection is noinit
+
+       # Does a template named `name` exists for this wiki?
+       fun has_template(name: String): Bool do
+               return expand_path(config.root_dir, config.templates_dir, name).file_exists
+       end
+
+       # Load a template file as a `TemplateString`.
+       #
+       # REQUIRE: `has_template`
+       fun load_template(name: String): TemplateString do
+               assert has_template(name)
+               var file = expand_path(config.root_dir, config.templates_dir, name)
+               var tpl = new TemplateString.from_file(file)
+               if tpl.has_macro("ROOT_URL") then
+                       tpl.replace("ROOT_URL", config.root_url)
+               end
+               if tpl.has_macro("TITLE") then
+                       tpl.replace("TITLE", config.wiki_name)
+               end
+               if tpl.has_macro("SUBTITLE") then
+                       tpl.replace("SUBTITLE", config.wiki_desc)
+               end
+               if tpl.has_macro("LOGO") then
+                       tpl.replace("LOGO", config.wiki_logo)
+               end
+               return tpl
+       end
+
+       # Join `parts` as a path and simplify it
+       fun expand_path(parts: String...): String do
+               var path = ""
+               for part in parts do
+                       path = path.join_path(part)
+               end
+               return path.simplify_path
+       end
+
+       fun pretty_name(name: String): String do
+               name = name.replace("_", " ")
+               name = name.capitalized
+               return name
+       end
+end
+
+# A wiki is composed of hierarchical entries.
+abstract class WikiEntry
+
+       # `Nitiwiki` this entry belongs to.
+       var wiki: Nitiwiki
+
+       # Entry data
+
+       # Entry internal name.
+       #
+       # Mainly used in urls.
+       var name: String
+
+       # Displayed title for `self`.
+       #
+       # If `self` is the root entry then display the wiki `WikiConfig::wiki_name` instead.
+       fun title: String do
+               if is_root then return wiki.config.wiki_name
+               return wiki.pretty_name(name)
+       end
+
+       # Is this section rendered from a source document?
+       #
+       # Source is an abstract concept at this level.
+       # It can represent a directory, a source file,
+       # a part of a file, everything needed to
+       # extend this base framework.
+       fun has_source: Bool do return src_path != null
+
+       # Entry creation time.
+       #
+       # Returns `-1` if not `has_source`.
+       fun create_time: Int do
+               if not has_source then return -1
+               return src_full_path.file_stat.ctime
+       end
+
+       # Entry last modification time.
+       #
+       # Returns `-1` if not `has_source`.
+       fun last_edit_time: Int do
+               if not has_source then return -1
+               return src_full_path.file_stat.mtime
+       end
+
+       # Entry list rendering time.
+       #
+       # Returns `-1` if `is_new`.
+       fun last_render_time: Int do
+               if is_new then return -1
+               return out_full_path.file_stat.mtime
+       end
+
+       # Entries hierarchy
+
+       # Type of the parent entry.
+       type PARENT: WikiEntry
+
+       # Parent entry if any.
+       var parent: nullable PARENT = null
+
+       # Does `self` have a parent?
+       fun is_root: Bool do return parent == null
+
+       # Children labelled by `name`.
+       var children = new HashMap[String, WikiEntry]
+
+       # Does `self` have a child nammed `name`?
+       fun has_child(name: String): Bool do return children.keys.has(name)
+
+       # Retrieve the child called `name`.
+       fun child(name: String): WikiEntry do return children[name]
+
+       # Add a sub-entry to `self`.
+       fun add_child(entry: WikiEntry) do
+               entry.parent = self
+               children[entry.name] = entry
+       end
+
+       # Paths and urls
+
+       # Breadcrumbs from the `Nitiwiki::root_section` to `self`.
+       #
+       # Result is returned as an array containg ordered entries:
+       # `breadcrumbs.first` is the root entry and
+       # `breadcrumbs.last == self`
+       fun breadcrumbs: Array[WikiEntry] is cached do
+               var path = new Array[WikiEntry]
+               var entry: nullable WikiEntry = self
+               while entry != null and not entry.is_root do
+                       path.add entry
+                       entry = entry.parent
+               end
+               return path.reversed
+       end
+
+       # Relative path from `wiki.config.root_dir` to source if any.
+       fun src_path: nullable String is abstract
+
+       # Absolute path to the source if any.
+       fun src_full_path: nullable String do
+               var src = src_path
+               if src == null then return null
+               return wiki.config.root_dir.join_path(src)
+       end
+
+       # Relative path from `wiki.config.root_dir` to rendered output.
+       #
+       # Like `src_path`, this method can represent a
+       # directory or a file.
+       fun out_path: String is abstract
+
+       # Absolute path to the output.
+       fun out_full_path: String do return wiki.config.root_dir.join_path(out_path)
+
+       # Rendering
+
+       # Does `self` have already been rendered?
+       fun is_new: Bool do return not out_full_path.file_exists
+
+       # Does `self` rendered output is outdated?
+       #
+       # Returns `true` if `is_new` then check in children.
+       fun is_dirty: Bool do
+               if is_new then return true
+               if has_source then
+                       if last_edit_time >= last_render_time then return true
+               end
+               for child in children.values do
+                       if child.is_dirty then return true
+               end
+               return false
+       end
+
+       # Render `self` and `children` is needed.
+       fun render do for child in children.values do child.render
+
+       # Templating
+
+       # Template file for `self`.
+       #
+       # Each entity can use a custom template.
+       # By default the template is inherited from the parent.
+       #
+       # If the root does not have a custom template,
+       # then returns the main wiki template file.
+       fun template_file: String do
+               if is_root then return wiki.config.template_file
+               return parent.template_file
+       end
+
+       # Header template file for `self`.
+       #
+       # Behave like `template_file`.
+       fun header_file: String do
+               if is_root then return wiki.config.header_file
+               return parent.header_file
+       end
+
+       # Footer template file for `self`.
+       #
+       # Behave like `template_file`.
+       fun footer_file: String do
+               if is_root then return wiki.config.footer_file
+               return parent.footer_file
+       end
+
+       # Menu template file for `self`.
+       #
+       # Behave like `template_file`.
+       fun menu_file: String do
+               if is_root then return wiki.config.menu_file
+               return parent.menu_file
+       end
+
+       # Display the entry `name`.
+       redef fun to_s do return name
+end
+
+# Each WikiSection is related to a source directory.
+#
+# A section can contain other sub-sections or pages.
+class WikiSection
+       super WikiEntry
+
+       # A section can only have another section as parent.
+       redef type PARENT: WikiSection
+
+       redef fun title do
+               if has_config then
+                       var title = config.title
+                       if title != null then return title
+               end
+               return super
+       end
+
+       # Is this section hidden?
+       #
+       # Hidden section are rendered but not linked in menus.
+       fun is_hidden: Bool do
+               if has_config then return config.is_hidden
+               return false
+       end
+
+       # Source directory.
+       redef fun src_path: String do
+               if parent == null then
+                       return wiki.config.source_dir
+               else
+                       return wiki.expand_path(parent.src_path, name)
+               end
+       end
+
+       # Config
+
+       # Custom configuration file for this section.
+       var config: nullable SectionConfig = null
+
+       # Does this section have its own config file?
+       fun has_config: Bool do return config != null
+
+       # Try to load the config file for this section.
+       private fun try_load_config do
+               var cfile = wiki.expand_path(wiki.config.root_dir, src_path, wiki.config_filename)
+               if not cfile.file_exists then return
+               wiki.message("Custom config for section {name}", 2)
+               config = new SectionConfig(cfile)
+       end
+
+       # Templating
+
+       # Also check custom config.
+       redef fun template_file do
+               if has_config then
+                       var tpl = config.template_file
+                       if tpl != null then return tpl
+               end
+               if is_root then return wiki.config.template_file
+               return parent.template_file
+       end
+
+       # Also check custom config.
+       redef fun header_file do
+               if has_config then
+                       var tpl = config.header_file
+                       if tpl != null then return tpl
+               end
+               if is_root then return wiki.config.header_file
+               return parent.header_file
+       end
+
+       # Also check custom config.
+       redef fun footer_file do
+               if has_config then
+                       var tpl = config.footer_file
+                       if tpl != null then return tpl
+               end
+               if is_root then return wiki.config.footer_file
+               return parent.footer_file
+       end
+
+       # Also check custom config.
+       redef fun menu_file do
+               if has_config then
+                       var tpl = config.menu_file
+                       if tpl != null then return tpl
+               end
+               if is_root then return wiki.config.menu_file
+               return parent.menu_file
+       end
+end
+
+# Each WikiArticle is related to a HTML file.
+#
+# Article can be created from scratch using this API or
+# automatically from a markdown source file (see: `from_source`).
+class WikiArticle
+       super WikiEntry
+
+       # Articles can only have `WikiSection` as parents.
+       redef type PARENT: WikiSection
+
+       redef fun title: String do
+               if name == "index" and parent != null then return parent.title
+               return super
+       end
+
+       # Page content.
+       #
+       # What you want to be displayed in the page.
+       var content: nullable Streamable = null
+
+       # Headlines ids and titles.
+       var headlines = new ArrayMap[String, HeadLine]
+
+       # Create a new articleu sing a markdown source file.
+       init from_source(wiki: Nitiwiki, md_file: String) do
+               src_full_path = md_file
+               init(wiki, md_file.basename(".md"))
+               var md_proc = new MarkdownProcessor
+               content = md_proc.process(md)
+               headlines = md_proc.emitter.decorator.headlines
+       end
+
+       redef var src_full_path: nullable String = null
+
+       redef fun src_path do
+               if src_full_path == null then return null
+               return src_full_path.substring_from(wiki.config.root_dir.length)
+       end
+
+       # The page markdown source content.
+       #
+       # Extract the markdown text from `source_file`.
+       #
+       # REQUIRE: `has_source`.
+       fun md: String is cached do
+               assert has_source
+               var file = new IFStream.open(src_full_path.to_s)
+               var md = file.read_all
+               file.close
+               return md
+       end
+
+       # Returns true if has source and
+       # `last_edit_date` > 'last_render_date'.
+       redef fun is_dirty do
+               if super then return true
+               if has_source then
+                       return wiki.need_render(src_full_path.to_s, out_full_path)
+               end
+               return false
+       end
+
+       redef fun to_s do return "{name} ({parent or else "null"})"
+end
+
+# Wiki configuration class.
+#
+# This class provides services that ensure static typing when accessing the `config.ini` file.
+class WikiConfig
+       super ConfigTree
+
+       # Returns the config value at `key` or return `default` if no key was found.
+       private fun value_or_default(key: String, default: String): String do
+               if not has_key(key) then return default
+               return self[key]
+       end
+
+       # Site name displayed.
+       #
+       # The title is used as home title and in headers.
+       #
+       # * key: `wiki.name`
+       # * default: `MyWiki`
+       fun wiki_name: String is cached do return value_or_default("wiki.name", "MyWiki")
+
+       # Site description.
+       #
+       # Displayed in header.
+       #
+       # * key: `wiki.desc`
+       # * default: ``
+       fun wiki_desc: String is cached do return value_or_default("wiki.desc", "")
+
+       # Site logo url.
+       #
+       # Url of the image to be displayed in header.
+       #
+       # * key: `wiki.logo`
+       # * default: ``
+       fun wiki_logo: String is cached do return value_or_default("wiki.logo", "")
+
+       # Root url of the wiki.
+       #
+       # * key: `wiki.root_url`
+       # * default: `http://localhost/`
+       fun root_url: String is cached do return value_or_default("wiki.root_url", "http://localhost/")
+
+
+       # Root directory of the wiki.
+       #
+       # Directory where the wiki files are stored locally.
+       #
+       # * key: `wiki.root_dir`
+       # * default: `./`
+       fun root_dir: String is cached do return value_or_default("wiki.root_dir", "./").simplify_path
+
+       # Pages directory.
+       #
+       # Directory where markdown source files are stored.
+       #
+       # * key: `wiki.source_dir
+       # * default: `pages/`
+       fun source_dir: String is cached do
+               return value_or_default("wiki.source_dir", "pages/").simplify_path
+       end
+
+       # Output directory.
+       #
+       # Directory where public wiki files are generated.
+       # **This path MUST be relative to `root_dir`.**
+       #
+       # * key: `wiki.out_dir`
+       # * default: `out/`
+       fun out_dir: String is cached do return value_or_default("wiki.out_dir", "out/").simplify_path
+
+       # Asset files directory.
+       #
+       # Directory where public assets like JS scripts or CSS files are stored.
+       # **This path MUST be relative to `root_dir`.**
+       #
+       # * key: `wiki.assets_dir`
+       # * default: `assets/`
+       fun assets_dir: String is cached do
+               return value_or_default("wiki.assets_dir", "assets/").simplify_path
+       end
+
+       # Template files directory.
+       #
+       # Directory where template used in HTML generation are stored.
+       # **This path MUST be relative to `root_dir`.**
+       #
+       # * key: `wiki.templates_dir`
+       # * default: `templates/`
+       fun templates_dir: String is cached do
+               return value_or_default("wiki.templates_dir", "templates/").simplify_path
+       end
+
+       # Main template file.
+       #
+       # The main template is used to specify the overall structure of a page.
+       #
+       # * key: `wiki.template`
+       # * default: `template.html`
+       fun template_file: String is cached do
+               return value_or_default("wiki.template", "template.html")
+       end
+
+       # Main header template file.
+       #
+       # Used to specify the structure of the page header.
+       # This is generally the place where you want to put your logo and wiki title.
+       #
+       # * key: `wiki.header`
+       # * default: `header.html`
+       fun header_file: String is cached do
+               return value_or_default("wiki.header", "header.html")
+       end
+
+       # Main menu template file.
+       #
+       # Used to specify the menu structure.
+       #
+       # * key: `wiki.menu`
+       # * default: `menu.html`
+       fun menu_file: String is cached do
+               return value_or_default("wiki.menu", "menu.html")
+       end
+
+       # Main footer file.
+       #
+       # The main footer is used to specify the structure of the page footer.
+       # This is generally the place where you want to put your copyright.
+       #
+       # * key: `wiki.footer`
+       # * default: `footer.html`
+       fun footer_file: String is cached do
+               return value_or_default("wiki.footer", "footer.html")
+       end
+
+       # Directory used by rsync to upload wiki files.
+       #
+       # This information is used to update your distant wiki files (like the webserver).
+       #
+       # * key: `wiki.rsync_dir`
+       # * default: ``
+       fun rsync_dir: String is cached do return value_or_default("wiki.rsync_dir", "")
+
+       # Remote repository used to pull modifications on sources.
+       #
+       # * key: `wiki.git_origin`
+       # * default: `origin`
+       fun git_origin: String is cached do return value_or_default("wiki.git_origin", "origin")
+
+       # Remote branch used to pull modifications on sources.
+       #
+       # * key: `wiki.git_branch`
+       # * default: `master`
+       fun git_branch: String is cached do return value_or_default("wiki.git_branch", "master")
+end
+
+# WikiSection custom configuration.
+#
+# Each section can provide its own config file to customize
+# appearance or behavior.
+class SectionConfig
+       super ConfigTree
+
+       # Returns the config value at `key` or `null` if no key was found.
+       private fun value_or_null(key: String): nullable String do
+               if not has_key(key) then return null
+               return self[key]
+       end
+
+       # Is this section hidden in sitemap and trees and menus?
+       fun is_hidden: Bool do return value_or_null("section.hidden") == "true"
+
+       # Custom section title if any.
+       fun title: nullable String do return value_or_null("section.title")
+
+       # Custom template file if any.
+       fun template_file: nullable String do return value_or_null("section.template")
+
+       # Custom header file if any.
+       fun header_file: nullable String do return value_or_null("section.header")
+
+       # Custom menu file if any.
+       fun menu_file: nullable String do return value_or_null("section.menu")
+
+       # Custom footer file if any.
+       fun footer_file: nullable String do return value_or_null("section.footer")
+end
diff --git a/contrib/nitiwiki/src/wiki_html.nit b/contrib/nitiwiki/src/wiki_html.nit
new file mode 100644 (file)
index 0000000..c984bc8
--- /dev/null
@@ -0,0 +1,435 @@
+# 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.
+
+# HTML wiki rendering
+module wiki_html
+
+import wiki_base
+
+redef class Nitiwiki
+
+       # Render HTML output looking for changes in the markdown sources.
+       fun render do
+               if not root_section.is_dirty and not force_render then return
+               var out_dir = expand_path(config.root_dir, config.out_dir)
+               out_dir.mkdir
+               copy_assets
+               root_section.add_child make_sitemap
+               root_section.render
+       end
+
+       # Copy the asset directory to the (public) output directory.
+       private fun copy_assets do
+               var src = expand_path(config.root_dir, config.assets_dir)
+               var out = expand_path(config.root_dir, config.out_dir)
+               if need_render(src, expand_path(out, config.assets_dir)) then
+                       if src.file_exists then sys.system "cp -R {src} {out}"
+               end
+       end
+
+       # Build the wiki sitemap page.
+       private fun make_sitemap: WikiSitemap do
+               var sitemap = new WikiSitemap(self, "sitemap")
+               sitemap.is_dirty = true
+               return sitemap
+       end
+end
+
+redef class WikiEntry
+
+       # Url to `self` once generated.
+       fun url: String do return wiki.config.root_url.join_path(breadcrumbs.join("/"))
+
+       # Get a `<a>` template link to `self`
+       fun tpl_link: Streamable do
+               return "<a href=\"{url}\">{title}</a>"
+       end
+end
+
+redef class WikiSection
+
+       # Output directory (where to ouput the HTML pages for this section).
+       redef fun out_path: String do
+               if parent == null then
+                       return wiki.config.out_dir
+               else
+                       return wiki.expand_path(parent.out_path, name)
+               end
+       end
+
+       redef fun render do
+               if not is_dirty and not wiki.force_render then return
+               if is_new then
+                       out_full_path.mkdir
+               else
+                       sys.system "touch {out_full_path}"
+               end
+               if has_source then
+                       wiki.message("Render section {out_path}", 1)
+                       copy_files
+               end
+               var index = self.index
+               if index isa WikiSectionIndex then
+                       index.is_dirty = true
+                       add_child index
+               end
+               super
+       end
+
+       # Copy attached files from `src_path` to `out_path`.
+       private fun copy_files do
+               assert has_source
+               var dir = src_full_path.to_s
+               for name in dir.files do
+                       if name == wiki.config_filename then continue
+                       if name.has_suffix(".md") then continue
+                       if has_child(name) then continue
+                       var src = wiki.expand_path(dir, name)
+                       var out = wiki.expand_path(out_full_path, name)
+                       if not wiki.need_render(src, out) then continue
+                       sys.system "cp -R {src} {out_full_path}"
+               end
+       end
+
+       # The index page for this section.
+       #
+       # If no file `index.md` exists for this section,
+       # a summary is generated using contained articles.
+       fun index: WikiArticle is cached do
+               for child in children.values do
+                       if child isa WikiArticle and child.is_index then return child
+               end
+               return new WikiSectionIndex(wiki, self)
+       end
+
+       redef fun tpl_link do return index.tpl_link
+
+       # Render the section hierarchy as a html tree.
+       #
+       # `limit` is used to specify the max-depth of the tree.
+       #
+       # 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>
+       fun tpl_tree(limit: Int): Template do
+               return tpl_tree_intern(limit, 1)
+       end
+
+       # Build the template tree for this section recursively.
+       protected fun tpl_tree_intern(limit, count: Int): Template do
+               var out = new Template
+               var index = index
+               out.add "<li>"
+               out.add tpl_link
+               if (limit < 0 or count < limit) and
+                  (children.length > 1 or (children.length == 1)) then
+                       out.add " <ul>"
+                       for child in children.values do
+                               if child == index then continue
+                               if child isa WikiArticle then
+                                       out.add "<li>"
+                                       out.add child.tpl_link
+                                       out.add "</li>"
+                               else if child isa WikiSection and not child.is_hidden then
+                                       out.add child.tpl_tree_intern(limit, count + 1)
+                               end
+                       end
+                       out.add " </ul>"
+               end
+               out.add "</li>"
+               return out
+       end
+end
+
+redef class WikiArticle
+
+       redef fun out_path: String do
+               if parent == null then
+                       return wiki.expand_path(wiki.config.out_dir, "{name}.html")
+               else
+                       return wiki.expand_path(parent.out_path, "{name}.html")
+               end
+       end
+
+       redef fun url do
+               if parent == null then
+                       return wiki.config.root_url.join_path("{name}.html")
+               else
+                       return parent.url.join_path("{name}.html")
+               end
+       end
+
+       # Is `self` an index page?
+       #
+       # Checks if `self.name == "index"`.
+       fun is_index: Bool do return name == "index"
+
+       redef fun render do
+               if not is_dirty and not wiki.force_render then return
+               wiki.message("Render article {name}", 2)
+               var file = out_full_path
+               file.dirname.mkdir
+               tpl_page.write_to_file file
+               super
+       end
+
+
+       # Replace macros in the template by wiki data.
+       private fun tpl_page: TemplateString do
+               var tpl = wiki.load_template(template_file)
+               if tpl.has_macro("TOP_MENU") then
+                       tpl.replace("TOP_MENU", tpl_menu)
+               end
+               if tpl.has_macro("HEADER") then
+                       tpl.replace("HEADER", tpl_header)
+               end
+               if tpl.has_macro("BODY") then
+                       tpl.replace("BODY", tpl_article)
+               end
+               if tpl.has_macro("FOOTER") then
+                       tpl.replace("FOOTER", tpl_footer)
+               end
+               return tpl
+       end
+
+       # Generate the HTML header for this article.
+       fun tpl_header: Streamable do
+               var file = header_file
+               if not wiki.has_template(file) then return ""
+               return wiki.load_template(file)
+       end
+
+       # Generate the HTML page for this article.
+       fun tpl_article: TplArticle do
+               var article = new TplArticle
+               article.body = content
+               article.breadcrumbs = new TplBreadcrumbs(self)
+               tpl_sidebar.blocks.add tpl_summary
+               article.sidebar = tpl_sidebar
+               return article
+       end
+
+       # Sidebar for this page.
+       var tpl_sidebar = new TplSidebar
+
+       # Generate the HTML summary for this article.
+       #
+       # Based on `headlines`
+       fun tpl_summary: Streamable do
+               var headlines = self.headlines
+               var tpl = new Template
+               tpl.add "<ul class=\"summary list-unstyled\">"
+               var iter = headlines.iterator
+               while iter.is_ok do
+                       var hl = iter.item
+                       # parse title as markdown
+                       var title = hl.title.md_to_html.to_s
+                       title = title.substring(3, title.length - 8)
+                       tpl.add "<li><a href=\"#{hl.id}\">{title}</a>"
+                       iter.next
+                       if iter.is_ok then
+                               if iter.item.level > hl.level then
+                                       tpl.add "<ul class=\"list-unstyled\">"
+                               else if iter.item.level < hl.level then
+                                       tpl.add "</li>"
+                                       tpl.add "</ul>"
+                               end
+                       else
+                               tpl.add "</li>"
+                       end
+               end
+               tpl.add "</ul>"
+               return tpl
+       end
+
+       # Generate the HTML menu for this article.
+       fun tpl_menu: Streamable do
+               var file = menu_file
+               if not wiki.has_template(file) then return ""
+               var tpl = wiki.load_template(file)
+               if tpl.has_macro("MENUS") then
+                       var items = new Template
+                       for child in wiki.root_section.children.values do
+                               if child isa WikiArticle and child.is_index then continue
+                               if child isa WikiSection and child.is_hidden then continue
+                               items.add "<li"
+                               if self == child or self.breadcrumbs.has(child) then
+                                       items.add " class=\"active\""
+                               end
+                               items.add ">"
+                               items.add child.tpl_link
+                               items.add "</li>"
+                       end
+                       tpl.replace("MENUS", items)
+               end
+               return tpl
+       end
+
+       # Generate the HTML footer for this article.
+       fun tpl_footer: Streamable do
+               var file = footer_file
+               if not wiki.has_template(file) then return ""
+               var tpl = wiki.load_template(file)
+               var time = new Tm.gmtime
+               if tpl.has_macro("YEAR") then
+                       tpl.replace("YEAR", (time.year + 1900).to_s)
+               end
+               if tpl.has_macro("GEN_TIME") then
+                       tpl.replace("GEN_TIME", time.to_s)
+               end
+               return tpl
+       end
+end
+
+# A `WikiArticle` that contains the sitemap tree.
+class WikiSitemap
+       super WikiArticle
+
+       redef fun tpl_article do
+               var article = new TplArticle.with_title("Sitemap")
+               article.body = new TplPageTree(wiki.root_section, -1)
+               return article
+       end
+
+       redef var is_dirty = false
+end
+
+# A `WikiArticle` that contains the section index tree.
+class WikiSectionIndex
+       super WikiArticle
+
+       # The section described by `self`.
+       var section: WikiSection
+
+       init(wiki: Nitiwiki, section: WikiSection) do
+               super(wiki, "index")
+               self.section = section
+       end
+
+       redef var is_dirty = false
+
+       redef fun tpl_article do
+               var article = new TplArticle.with_title(section.title)
+               article.body = new TplPageTree(section, -1)
+               article.breadcrumbs = new TplBreadcrumbs(self)
+               return article
+       end
+end
+
+# Article HTML output.
+class TplArticle
+       super Template
+
+       var title: nullable Streamable = null
+       var body: nullable Streamable = null
+       var sidebar: nullable TplSidebar = null
+       var breadcrumbs: nullable TplBreadcrumbs = null
+
+       init with_title(title: Streamable) do
+               self.title = title
+       end
+
+       redef fun rendering do
+               if sidebar != null then
+                       add "<div class=\"col-sm-3 sidebar\">"
+                       add sidebar.as(not null)
+                       add "</div>"
+                       add "<div class=\"col-sm-9 content\">"
+               else
+                       add "<div class=\"col-sm-12 content\">"
+               end
+               if body != null then
+                       add "<article>"
+                       if breadcrumbs != null then
+                               add breadcrumbs.as(not null)
+                       end
+                       if title != null then
+                               add "<h1>"
+                               add title.as(not null)
+                               add "</h1>"
+                       end
+                       add     body.as(not null)
+                       add " </article>"
+               end
+               add "</div>"
+       end
+end
+
+# A collection of HTML blocks displayed on the side of a page.
+class TplSidebar
+       super Template
+
+       # Blocks are `Stremable` pieces that will be rendered in the sidebar.
+       var blocks = new Array[Streamable]
+
+       redef fun rendering do
+               for block in blocks do
+                       add "<div class=\"sideblock\">"
+                       add block
+                       add "</div>"
+               end
+       end
+end
+
+# An HTML breadcrumbs that show the path from a `WikiArticle` to the `Nitiwiki` root.
+class TplBreadcrumbs
+       super Template
+
+       # Bread crumb article.
+       var article: WikiArticle
+
+       redef fun rendering do
+               var path = article.breadcrumbs
+               if path.is_empty or path.length <= 2 and article.is_index then return
+               add "<ol class=\"breadcrumb\">"
+               for entry in path do
+                       if entry == path.last then
+                               add "<li class=\"active\">"
+                               add entry.title
+                               add "</li>"
+                       else
+                               if article.parent == entry and article.is_index then continue
+                               add "<li>"
+                               add entry.tpl_link
+                               add "</li>"
+                       end
+               end
+               add "</ol>"
+       end
+end
+
+# An HTML tree that show the section pages structure.
+class TplPageTree
+       super Template
+
+       # Builds the page tree from `root`.
+       var root: WikiSection
+
+       # Limits the tree depth to `max_depth` levels.
+       var max_depth: Int
+
+       redef fun rendering do
+               add "<ul>"
+               add root.tpl_tree(-1)
+               add "</ul>"
+       end
+end
diff --git a/contrib/nitiwiki/tests/Makefile b/contrib/nitiwiki/tests/Makefile
new file mode 100644 (file)
index 0000000..0dce637
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright 2013 Alexandre Terrasa <alexandre@moz-code.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.
+
+all: tests
+
+tests: clean
+       ./tests.sh
+
+clean:
+       rm -rf out/
diff --git a/contrib/nitiwiki/tests/nitiwiki.args b/contrib/nitiwiki/tests/nitiwiki.args
new file mode 100644 (file)
index 0000000..b5abeca
--- /dev/null
@@ -0,0 +1 @@
+nitiwiki
diff --git a/contrib/nitiwiki/tests/nitiwiki_render.args b/contrib/nitiwiki/tests/nitiwiki_render.args
new file mode 100644 (file)
index 0000000..6f7050e
--- /dev/null
@@ -0,0 +1 @@
+nitiwiki --config wiki1/config.ini --clean --render -v
diff --git a/contrib/nitiwiki/tests/nitiwiki_status.args b/contrib/nitiwiki/tests/nitiwiki_status.args
new file mode 100644 (file)
index 0000000..aa96d13
--- /dev/null
@@ -0,0 +1 @@
+nitiwiki --config wiki1/config.ini --clean --status
diff --git a/contrib/nitiwiki/tests/res/nitiwiki.res b/contrib/nitiwiki/tests/res/nitiwiki.res
new file mode 100644 (file)
index 0000000..232b5ef
--- /dev/null
@@ -0,0 +1,2 @@
+Not in a nitiwiki directory.
+Use --init to initialize one here.
diff --git a/contrib/nitiwiki/tests/res/nitiwiki_render.res b/contrib/nitiwiki/tests/res/nitiwiki_render.res
new file mode 100644 (file)
index 0000000..adf25a7
--- /dev/null
@@ -0,0 +1 @@
+Render section out
diff --git a/contrib/nitiwiki/tests/res/nitiwiki_status.res b/contrib/nitiwiki/tests/res/nitiwiki_status.res
new file mode 100644 (file)
index 0000000..936a764
--- /dev/null
@@ -0,0 +1,10 @@
+nitiWiki
+name: wiki1
+config: wiki1/config.ini
+url: http://localhost/
+
+There is modified files:
+ + pages
+ + /pages/index.md
+
+Use nitiwiki --render to render modified files
diff --git a/contrib/nitiwiki/tests/tests.sh b/contrib/nitiwiki/tests/tests.sh
new file mode 100755 (executable)
index 0000000..2acbe94
--- /dev/null
@@ -0,0 +1,92 @@
+#!/bin/bash
+
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2014 Alexandre Terrasa <alexandre@moz-code.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.
+
+BIN=../bin
+OUT=./out
+RES=./res
+
+# check args files
+test_args()
+{
+       local test="$1"
+       local args=`cat $test.args`
+       local outdir=$OUT/$test.files
+
+       echo $BIN/$args > $OUT/$test.bin
+       chmod +x $OUT/$test.bin
+       OUTDIR=$outdir $OUT/$test.bin > $OUT/$test.res 2> $OUT/$test.err
+
+       if [ -r $outdir ]; then
+               ls -aR $outdir >> $OUT/$test.res
+       fi
+
+       diff $OUT/$test.res $RES/$test.res > $OUT/$test.diff 2> /dev/null
+}
+
+# return
+#  0 if the sav not exists
+#  1 if the file does match
+#  2 if the file does not match
+check_result() {
+       local test="$1"
+
+       if [ ! -r "$RES/$test.res" ]; then
+               return 0
+       elif [ ! -s $OUT/$test.diff ]; then
+               return 1
+       else
+               return 2
+       fi
+}
+
+echo "Testing..."
+echo ""
+
+rm -rf $OUT 2>/dev/null
+mkdir $OUT 2>/dev/null
+
+all=0
+ok=0
+ko=0
+sk=0
+
+for file in `ls *.args`; do
+       ((all++))
+       test="${file%.*}"
+       echo -n "* $test: "
+
+       test_args $test
+       check_result $test
+
+       case "$?" in
+               0)
+                       echo "skip ($test.res not found)"
+                       ((sk++))
+                       continue;;
+               1)
+                       echo "success"
+                       ((ok++))
+                       ;;
+               2)
+                       echo "error (diff $OUT/$test.res $RES/$test.res)"
+                       ((ko++))
+                       ;;
+       esac
+done
+echo ""
+echo "==> success $ok/$all ($ko tests failed, $sk skipped)"
diff --git a/contrib/nitiwiki/tests/wiki1/assets/css/main.css b/contrib/nitiwiki/tests/wiki1/assets/css/main.css
new file mode 100644 (file)
index 0000000..d58b78d
--- /dev/null
@@ -0,0 +1 @@
+dummy { margin: 0 }
diff --git a/contrib/nitiwiki/tests/wiki1/config.ini b/contrib/nitiwiki/tests/wiki1/config.ini
new file mode 100644 (file)
index 0000000..c24bdd7
--- /dev/null
@@ -0,0 +1,2 @@
+wiki.name=wiki1
+wiki.root_dir=wiki1/
diff --git a/contrib/nitiwiki/tests/wiki1/config2.ini b/contrib/nitiwiki/tests/wiki1/config2.ini
new file mode 100644 (file)
index 0000000..4ebb07b
--- /dev/null
@@ -0,0 +1,3 @@
+wiki.name=wiki2
+wiki.desc=the one used by nit/tests.sh
+wiki.root_dir=../contrib/nitiwiki/tests/wiki1/
diff --git a/contrib/nitiwiki/tests/wiki1/pages/index.md b/contrib/nitiwiki/tests/wiki1/pages/index.md
new file mode 100644 (file)
index 0000000..cc0be1e
--- /dev/null
@@ -0,0 +1 @@
+# Hello World!
diff --git a/contrib/nitiwiki/tests/wiki1/templates/footer.html b/contrib/nitiwiki/tests/wiki1/templates/footer.html
new file mode 100644 (file)
index 0000000..7506b39
--- /dev/null
@@ -0,0 +1,10 @@
+<div class="row footer">
+       <div class="container-fluid">
+               <div class="well well-sm">
+                       <p><strong>%TITLE% &copy; %YEAR%</strong></p>
+                       <p class="text-muted"><em>last modification %GEN_TIME%</em></p>
+                       <p class="text-muted">Proudly powered by
+                               <a href="http://nitlanguage.org">nit</a>!</p>
+               </div>
+       </div>
+</div>
diff --git a/contrib/nitiwiki/tests/wiki1/templates/header.html b/contrib/nitiwiki/tests/wiki1/templates/header.html
new file mode 100644 (file)
index 0000000..1cb06bf
--- /dev/null
@@ -0,0 +1,9 @@
+<div class="container-fluid header">
+       <div class="container">
+               <div class="header">
+                       <a href="http://uqam.ca"><img src="%ROOT_URL%/%LOGO%" alt="logo" /></a>
+                       <h2>%SUBTITLE%</h2>
+                       <h1>%TITLE%</h1>
+               </div>
+       </div>
+</div>
diff --git a/contrib/nitiwiki/tests/wiki1/templates/menu.html b/contrib/nitiwiki/tests/wiki1/templates/menu.html
new file mode 100644 (file)
index 0000000..1ff832e
--- /dev/null
@@ -0,0 +1,20 @@
+<nav class="menu" role="navigation">
+       <div class="container">
+               <!-- Brand and toggle get grouped for better mobile display -->
+               <div class="navbar-header">
+                       <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
+                               <span class="sr-only">Toggle navigation</span>
+                               <span class="icon-bar"></span>
+                               <span class="icon-bar"></span>
+                               <span class="icon-bar"></span>
+                       </button>
+                       <a class="navbar-brand" href="%ROOT_URL%index.html">%TITLE%</a>
+               </div>
+               <!-- Collect the nav links, forms, and other content for toggling -->
+               <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+                       <ul class="nav navbar-nav">
+                       %MENUS%
+                       </ul>
+               </div><!-- /.navbar-collapse -->
+       </div>
+</nav>
diff --git a/contrib/nitiwiki/tests/wiki1/templates/template.html b/contrib/nitiwiki/tests/wiki1/templates/template.html
new file mode 100644 (file)
index 0000000..6b3b126
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+       <head>
+               <meta charset="utf-8">
+               <meta http-equiv="X-UA-Compatible" content="IE=edge">
+               <meta name="viewport" content="width=device-width, initial-scale=1">
+               <title>%TITLE%</title>
+
+               <link href="%ROOT_URL%/assets/vendors/bootstrap/bootstrap-3.2.0-dist/css/bootstrap.min.css" rel="stylesheet">
+               <link href="%ROOT_URL%/assets/css/main.css" rel="stylesheet">
+
+               <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
+               <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+               <!--[if lt IE 9]>
+               <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+               <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+               <![endif]-->
+       </head>
+       <body>
+               %HEADER%
+               %TOP_MENU%
+               <div class="container">
+                       <div class="row">
+                               %BODY%
+                       </div>
+                       %FOOTER%
+               </div>
+
+               <script src="%ROOT_URL%/vendors/jquery/jquery-1.11.1.min.js"></script>
+               <script src="%ROOT_URL%/vendors/bootstrap/bootstrap-3.2.0-dist/js/bootstrap.min.js"></script>
+       </body>
+</html>
index 9470dd8..82ae3d1 100644 (file)
@@ -46,7 +46,6 @@ in "Java" `{
 # This is a low-level class, use `AssetManager` instead
 extern class NativeAssetManager in "Java" `{ android.content.res.AssetManager `}
        super JavaObject
-       redef type SELF: NativeAssetManager
 
        fun close in "Java" `{ recv.close(); `}
 
@@ -172,7 +171,6 @@ end
 # This is a low-level class, use `ResourcesManager` instead
 extern class NativeResources in "Java" `{ android.content.res.Resources `}
        super JavaObject
-       redef type SELF: NativeResources
 
        fun get_assets:NativeAssetManager in "Java" `{ return recv.getAssets(); `}
        fun get_color(id: Int): Int in "Java" `{ return recv.getColor((int)id); `}
@@ -283,7 +281,6 @@ end
 # An android Bitmap, get an instance using the AssetManager or the ResourceManager
 extern class NativeBitmap in "Java" `{ android.graphics.Bitmap `}
        super JavaObject
-       redef type SELF: NativeBitmap
 
        # Create a NativeBitmap from a NativeInputStream retrieved with `open` function of the AssetManager
        # Called by the AssetManager
@@ -299,7 +296,6 @@ end
 # Android AssetFileDescriptor, can be retrieve by AssetManager and used to load a sound in a SoundPool
 extern class NativeAssetFileDescriptor in "Java" `{ android.content.res.AssetFileDescriptor `}
        super JavaObject
-       redef type SELF: NativeAssetFileDescriptor
 
        fun close in "Java" `{
                try {
index e640621..366c7d4 100644 (file)
@@ -38,7 +38,6 @@ in "Java" `{
 # AudioManager of the application, used to manage the audio mode
 extern class NativeAudioManager in "Java" `{ android.media.AudioManager `}
        super JavaObject
-       redef type SELF: NativeAudioManager
 
        fun mode: Int in "Java" `{ return recv.getMode(); `}
        fun mode=(i: Int) in "Java" `{ recv.setMode((int)i); `}
@@ -61,7 +60,6 @@ end
 # This is a low-level class, use `MediaPlater` instead
 extern class NativeMediaPlayer in "Java" `{ android.media.MediaPlayer `}
        super JavaObject
-       redef type SELF: NativeMediaPlayer
 
        new in "Java" `{ return new MediaPlayer(); `}
        fun start in "Java" `{ recv.start(); `}
@@ -108,7 +106,6 @@ end
 # This is a low-level class, use `SoundPool`instead
 extern class NativeSoundPool in "Java" `{ android.media.SoundPool `}
        super JavaObject
-       redef type SELF: NativeSoundPool
 
        new(max_streams, stream_type, src_quality: Int) in "Java" `{
                return new SoundPool((int)max_streams, (int)stream_type, (int)src_quality);
index 9528e05..5a083d2 100644 (file)
@@ -31,7 +31,6 @@ in "Java" `{
 
 extern class NativeBundle in "Java" `{ android.os.Bundle `}
        super JavaObject
-       redef type SELF: NativeBundle
 
        fun clone: JavaObject in "Java" `{ return recv.clone(); `}
        fun size: Int in "Java" `{ return recv.size(); `}
index d07a817..20c85dc 100644 (file)
@@ -33,7 +33,6 @@ in "Java" `{
 
 extern class NativeIntent in "Java" `{ android.content.Intent `}
        super JavaObject
-       redef type SELF: NativeIntent
 
        fun add_category(category: JavaString) in "Java" `{ recv.addCategory(category); `}
        fun add_flags(flags: Int) in "Java" `{ recv.addFlags((int)flags); `}
index dab001d..fca03e0 100644 (file)
@@ -21,6 +21,8 @@ module platform is
        new_annotation max_api_version
        new_annotation target_api_version
        new_annotation android_manifest
+       new_annotation android_manifest_application
+       new_annotation android_manifest_activity
 end
 
 import java
index 8635f86..404aaea 100644 (file)
@@ -33,7 +33,6 @@ in "Java" `{
 
 extern class NativeSharedPreferences in "Java" `{ android.content.SharedPreferences `}
        super JavaObject
-       redef type SELF: NativeSharedPreferences
        
        fun contains(key: JavaString): Bool in "Java" `{ return recv.contains(key); `}
        fun get_all: HashMap[JavaString, JavaObject] import HashMap[JavaString, JavaObject],
@@ -113,7 +112,6 @@ end
 
 extern class NativeSharedPreferencesEditor in "Java" `{ android.content.SharedPreferences$Editor `}
        super JavaObject
-       redef type SELF: NativeSharedPreferencesEditor
 
        fun clear: NativeSharedPreferencesEditor in "Java" `{ return recv.clear(); `}
        fun commit: Bool in "Java" `{ return recv.commit(); `}
index 6226285..f56dbef 100644 (file)
@@ -26,7 +26,6 @@ import native_app_glue
 # Handle to an Android vibrator
 extern class Vibrator in "Java" `{ android.os.Vibrator `}
        super JavaObject
-       redef type SELF: Vibrator
 
        # Vibrate for `n` miliseconds
        fun vibrate(n: Int) in "Java" `{ recv.vibrate(n); `}
index afb6a1d..13891fc 100644 (file)
@@ -34,5 +34,5 @@ interface DataStore
        fun [](key: String): nullable Object is abstract
 
        # Store `value` at `key`
-       fun []=(key: String, value: Serializable) is abstract
+       fun []=(key: String, value: nullable Serializable) is abstract
 end
index fdc7e99..6c843f3 100644 (file)
--- a/lib/c.nit
+++ b/lib/c.nit
@@ -29,7 +29,6 @@ end
 # A native C array, as in a pointer to the first element of the array
 extern class NativeCArray `{ void * `}
        type E: nullable Object
-       type SELF: NativeCArray
 
        fun [](index: E): E is abstract
        fun []=(index: E, val: E) is abstract
@@ -79,7 +78,6 @@ end
 extern class NativeCIntArray `{ int* `}
        super NativeCArray
        redef type E: Int
-       redef type SELF: NativeCIntArray
 
        new(size: Int) `{ return calloc(size, sizeof(int)); `}
        redef fun [](index) `{ return recv[index]; `}
@@ -91,7 +89,6 @@ end
 redef class NativeString
        super NativeCArray
        redef type E: Char
-       redef type SELF: NativeString
 
        redef fun +(offset) `{ return recv + offset; `}
 end
index 04245a5..4ab4eab 100644 (file)
@@ -32,7 +32,6 @@ in "Java" `{
 
 extern class NativeFile in "Java" `{ java.io.File `}
        super JavaObject
-       redef type SELF: NativeFile
 
        fun can_execute: Bool in "Java" `{ return recv.canExecute(); `}
        fun can_read: Bool in "Java" `{ return recv.canRead(); `}
@@ -77,7 +76,6 @@ end
 
 extern class NativeFileInputStream in "Java" `{ java.io.FileInputStream `}
        super JavaObject
-       redef type SELF: NativeFileInputStream
 
        fun available: Int in "Java" `{
                try {
@@ -114,7 +112,6 @@ end
 
 extern class NativeFileOutputStream in "Java" `{ java.io.FileOutputStream `}
        super JavaObject
-       redef type SELF: NativeFileOutputStream
 
        fun close in "Java" `{
                try {
@@ -141,7 +138,7 @@ end
 
 extern class NativeFileDescriptor in "Java" `{ java.io.FileDescriptor `}
        super JavaObject
-       redef type SELF: NativeFileDescriptor
+
        fun sync in "Java" `{
                try{
                        recv.sync();
@@ -154,7 +151,6 @@ end
 
 extern class NativeInputStream in "Java" `{ java.io.InputStream `}
        super JavaObject
-       redef type SELF: NativeInputStream
 
        fun available: Int in "Java" `{
                try {
index 0b6a652..c3db430 100644 (file)
@@ -98,8 +98,6 @@ end
 extern class JavaString in "Java" `{ java.lang.String `}
        super JavaObject
 
-       redef type SELF: JavaString
-
        # Get the string from Java and copy it to Nit memory
        fun to_cstring: NativeString import sys, Sys.jni_env `{
                Sys sys = JavaString_sys(recv);
@@ -140,7 +138,6 @@ redef class Text
 end
 
 redef extern class JavaObject
-       type SELF: JavaObject
 
        # Returns a global reference to the Java object behind this reference
        #
index add43e1..2f675d6 100644 (file)
@@ -33,6 +33,88 @@ class MarkdownProcessor
        # `MarkdownEmitter` used for ouput.
        var emitter: MarkdownEmitter is noinit
 
+       # Work in extended mode (default).
+       #
+       # Behavior changes when using extended mode:
+       #
+       # * Lists and code blocks end a paragraph
+       #
+       #   In normal markdown the following:
+       #
+       #               This is a paragraph
+       #               * and this is not a list
+       #
+       #   Will produce:
+       #
+       #               <p>This is a paragraph
+       #               * and this is not a list</p>
+       #
+       #       When using extended mode this changes to:
+       #
+       #               <p>This is a paragraph</p>
+       #               <ul>
+       #               <li>and this is not a list</li>
+       #               </ul>
+       #
+       # * Fences code blocks
+       #
+       #   If you don't want to indent your all your code with 4 spaces,
+       #   you can wrap your code in ``` ``` ``` or `~~~`.
+       #
+       #       Here's an example:
+       #
+       #               ```
+       #               fun test do
+       #                       print "Hello World!"
+       #               end
+       #               ```
+       #
+       # * Code blocks meta
+       #
+       #   If you want to use syntax highlighting tools, most of them need to know what kind
+       #   of language they are highlighting.
+       #   You can add an optional language identifier after the fence declaration to output
+       #   it in the HTML render.
+       #
+       #               ```nit
+       #               import markdown
+       #
+       #               print "# Hello World!".md_to_html
+       #               ```
+       #
+       #   Becomes
+       #
+       #               <pre class="nit"><code>import markdown
+       #
+       #               print "Hello World!".md_to_html
+       #               </code></pre>
+       #
+       # * Underscores (Emphasis)
+       #
+       #   Underscores in the middle of a word like:
+       #
+       #               Con_cat_this
+       #
+       #       normally produces this:
+       #
+       #               <p>Con<em>cat</em>this</p>
+       #
+       #   With extended mode they don't result in emphasis.
+       #
+       #               <p>Con_cat_this</p>
+       #
+       # * Strikethrough
+       #
+       #   Like in [GFM](https://help.github.com/articles/github-flavored-markdown),
+       #   strikethrought span is marked with `~~`.
+       #
+       #               ~~Mistaken text.~~
+       #
+       #   becomes
+       #
+       #               <del>Mistaken text.</del>
+       var ext_mode = true
+
        init do self.emitter = new MarkdownEmitter(self)
 
        # Process the mardown `input` string and return the processed output.
@@ -219,12 +301,14 @@ class MarkdownProcessor
                if value[leading] == '#' then return new LineHeadline
                if value[leading] == '>' then return new LineBlockquote
 
-               if value.length - leading - trailing > 2 then
-                       if value[leading] == '`' and md.count_chars_start('`') >= 3 then
-                               return new LineFence
-                       end
-                       if value[leading] == '~' and md.count_chars_start('~') >= 3 then
-                               return new LineFence
+               if ext_mode then
+                       if value.length - leading - trailing > 2 then
+                               if value[leading] == '`' and md.count_chars_start('`') >= 3 then
+                                       return new LineFence
+                               end
+                               if value[leading] == '~' and md.count_chars_start('~') >= 3 then
+                                       return new LineFence
+                               end
                        end
                end
 
@@ -307,6 +391,14 @@ class MarkdownProcessor
                                        return new TokenEmUnderscore(pos, c)
                                end
                        end
+                       if ext_mode then
+                               if (c0.is_letter or c0.is_digit) and c0 != '_' and
+                                  (c1.is_letter or c1.is_digit) then
+                                       return new TokenNone(pos, c)
+                               else
+                                       return new TokenEmUnderscore(pos, c)
+                               end
+                       end
                        if c0 != ' ' or c1 != ' ' then
                                return new TokenEmUnderscore(pos, c)
                        else
@@ -335,13 +427,12 @@ class MarkdownProcessor
                        return new TokenHTML(pos, c)
                else if c == '&' then
                        return new TokenEntity(pos, c)
-               else if c == '^' then
-                       if c0 == '^' or c1 == '^' then
-                               return new TokenNone(pos, c)
-                       else
-                               return new TokenSuper(pos, c)
-                       end
                else
+                       if ext_mode then
+                               if c == '~' and c1 == '~' then
+                                       return new TokenStrike(pos, c)
+                               end
+                       end
                        return new TokenNone(pos, c)
                end
        end
@@ -519,8 +610,10 @@ interface Decorator
        # Render a strong text.
        fun add_strong(v: MarkdownEmitter, text: Text) is abstract
 
-       # Render a super text.
-       fun add_super(v: MarkdownEmitter, text: Text) is abstract
+       # Render a strike text.
+       #
+       # Extended mode only (see `MarkdownProcessor::ext_mode`)
+       fun add_strike(v: MarkdownEmitter, text: Text) is abstract
 
        # Render a link.
        fun add_link(v: MarkdownEmitter, link: Text, name: Text, comment: nullable Text) is abstract
@@ -594,7 +687,11 @@ class HTMLDecorator
        end
 
        redef fun add_code(v, block) do
-               v.add "<pre><code>"
+               if block isa BlockFence and block.meta != null then
+                       v.add "<pre class=\"{block.meta.to_s}\"><code>"
+               else
+                       v.add "<pre><code>"
+               end
                v.emit_in block
                v.add "</code></pre>\n"
        end
@@ -635,10 +732,10 @@ class HTMLDecorator
                v.add "</strong>"
        end
 
-       redef fun add_super(v, text) do
-               v.add "<sup>"
+       redef fun add_strike(v, text) do
+               v.add "<del>"
                v.add text
-               v.add "</sup>"
+               v.add "</del>"
        end
 
        redef fun add_image(v, link, name, comment) do
@@ -1032,6 +1129,9 @@ end
 class BlockFence
        super BlockCode
 
+       # Any string found after fence token.
+       var meta: nullable Text
+
        # Fence code lines start at 0 spaces.
        redef var line_start = 0
 end
@@ -1409,10 +1509,10 @@ class LineOther
                var was_empty = line.prev_empty
                while line != null and not line.is_empty do
                        var t = v.line_kind(line)
-                       if v.in_list and t isa LineList then
+                       if (v.in_list or v.ext_mode) and t isa LineList then
                                break
                        end
-                       if t isa LineCode or t isa LineFence then
+                       if v.ext_mode and (t isa LineCode or t isa LineFence) then
                                break
                        end
                        if t isa LineHeadline or t isa LineHeadline1 or t isa LineHeadline2 or
@@ -1551,7 +1651,8 @@ class LineFence
                else
                        block = v.current_block.split(v.current_block.last_line.as(not null))
                end
-               block.kind = new BlockFence(block)
+               var meta = block.first_line.value.meta_from_fence
+               block.kind = new BlockFence(block, meta)
                block.first_line.clear
                var last = block.last_line
                if last != null and v.line_kind(last) isa LineFence then
@@ -2038,17 +2139,19 @@ class TokenEscape
        end
 end
 
-# A markdown super token.
-class TokenSuper
+# A markdown strike token.
+#
+# Extended mode only (see `MarkdownProcessor::ext_mode`)
+class TokenStrike
        super Token
 
        redef fun emit(v) do
                var tmp = v.push_buffer
-               var b = v.emit_text_until(v.current_text.as(not null), pos + 1, self)
+               var b = v.emit_text_until(v.current_text.as(not null), pos + 2, self)
                v.pop_buffer
                if b > 0 then
-                       v.decorator.add_super(v, tmp)
-                       v.current_pos = b
+                       v.decorator.add_strike(v, tmp)
+                       v.current_pos = b + 1
                else
                        v.addc char
                end
@@ -2288,6 +2391,18 @@ redef class Text
                return pos
        end
 
+       # Extract string found at end of fence opening.
+       private fun meta_from_fence: nullable Text do
+               for i in [0..chars.length[ do
+                       var c = chars[i]
+                       print c
+                       if c != ' ' and c != '`' and c != '~' then
+                               return substring_from(i).trim
+                       end
+               end
+               return null
+       end
+
        # Is `self` an unsafe HTML element?
        private fun is_html_unsafe: Bool do return html_unsafe_tags.has(self.write_to_string)
 
index dd7fd58..a8d3b9f 100644 (file)
@@ -407,6 +407,36 @@ sit amet, consectetuer adipiscing elit.</p>
                assert res == exp
        end
 
+       fun test_process_list11 do
+               var test = """
+This is a paragraph
+* and this is not a list
+"""
+               var exp = """
+<p>This is a paragraph
+* and this is not a list</p>
+"""
+               var proc = new MarkdownProcessor
+               proc.ext_mode = false
+               var res = proc.process(test).write_to_string
+               assert res == exp
+       end
+
+       fun test_process_list_ext do
+               var test = """
+This is a paragraph
+* and this is not a list
+"""
+               var exp = """
+<p>This is a paragraph</p>
+<ul>
+<li>and this is not a list</li>
+</ul>
+"""
+               var res = test.md_to_html.write_to_string
+               assert res == exp
+       end
+
        fun test_process_code1 do
                var test = """
 This is a normal paragraph:
@@ -448,7 +478,7 @@ end tell
                assert res == exp
        end
 
-       fun test_process_code3 do
+       fun test_process_code_ext1 do
                var test = """
 Here is an example of AppleScript:
 ~~~
@@ -476,7 +506,7 @@ end tell
                assert res == exp
        end
 
-       fun test_process_code4 do
+       fun test_process_code_ext2 do
                var test = """
 Here is an example of AppleScript:
 ```
@@ -504,6 +534,49 @@ end tell
                assert res == exp
        end
 
+       fun test_process_code_ext3 do
+               var proc = new MarkdownProcessor
+               proc.ext_mode = false
+
+               var test = """
+Here is an example of AppleScript:
+    beep
+"""
+               var exp = """
+<p>Here is an example of AppleScript:
+beep</p>
+"""
+               var res = proc.process(test).write_to_string
+               assert res == exp
+       end
+
+       fun test_process_code_ext4 do
+               var test = """
+Here is an example of AppleScript:
+    beep
+"""
+               var exp = """
+<p>Here is an example of AppleScript:</p>
+<pre><code>beep
+</code></pre>
+"""
+               var res = test.md_to_html.write_to_string
+               assert res == exp
+       end
+
+       fun test_process_code_ext5 do
+               var test = """
+```nit
+print "Hello World!"
+```
+"""
+               var exp = """
+<pre class="nit"><code>print "Hello World!"
+</code></pre>
+"""
+               var res = test.md_to_html.write_to_string
+               assert res == exp
+       end
 
        fun test_process_nesting1 do
                var test = """
@@ -641,6 +714,22 @@ __double underscores__
                assert res == exp
        end
 
+       fun test_process_emph3 do
+               var proc = new MarkdownProcessor
+               proc.ext_mode = false
+               var test = "Con_cat_this"
+               var exp = "<p>Con<em>cat</em>this</p>\n"
+               var res = proc.process(test).write_to_string
+               assert res == exp
+       end
+
+       fun test_process_emph_ext do
+               var test = "Con_cat_this"
+               var exp = "<p>Con_cat_this</p>\n"
+               var res = test.md_to_html.write_to_string
+               assert res == exp
+       end
+
        fun test_process_xml1 do
                var test = """
 This is a regular paragraph.
@@ -908,6 +997,23 @@ break</a> with a line-ending space.</p>
                assert res == exp
        end
 
+       fun test_process_strike do
+               var proc = new MarkdownProcessor
+               proc.ext_mode = false
+               var test = "This is how you ~~strike text~~"
+               var exp = "<p>This is how you ~~strike text~~</p>\n"
+               var res = proc.process(test).write_to_string
+               assert exp == res
+       end
+
+       fun test_process_strike_ext do
+               var test = "This is how you ~~strike text~~"
+               var exp = "<p>This is how you <del>strike text</del></p>\n"
+               var res = test.md_to_html.write_to_string
+               assert exp == res
+       end
+
+
        fun test_daring_encoding do
                var test = """
 AT&T has an ampersand in their name.
@@ -1275,6 +1381,9 @@ Here's how you put `` `backticks` `` in a code span.
        end
 
        fun test_daring_pars do
+               var proc = new MarkdownProcessor
+               proc.ext_mode = false
+
                var test = """
 In Markdown 1.0.0 and earlier. Version
 8. This line turns into a list item.
@@ -1295,7 +1404,7 @@ list item.</p>
 <p>Here's one with a bullet.
 * criminey.</p>
 """
-               var res = test.md_to_html.write_to_string
+               var res = proc.process(test).write_to_string
                assert res == exp
        end
 
@@ -2462,10 +2571,6 @@ class TestLine
                assert v.line_kind(subject) isa LineHeadline
                subject = new MDLine("    code")
                assert v.line_kind(subject) isa LineCode
-               subject = new MDLine("  ~~~")
-               assert v.line_kind(subject) isa LineFence
-               subject = new MDLine("  ```")
-               assert v.line_kind(subject) isa LineFence
                subject = new MDLine("   Title  ")
                subject.next = new MDLine("== ")
                assert v.line_kind(subject) isa LineHeadline1
@@ -2498,6 +2603,14 @@ class TestLine
                assert v.line_kind(subject) isa LineOList
        end
 
+       fun test_line_type_ext do
+               var v = new MarkdownProcessor
+               subject = new MDLine("  ~~~")
+               assert v.line_kind(subject) isa LineFence
+               subject = new MDLine("  ```")
+               assert v.line_kind(subject) isa LineFence
+       end
+
        fun test_count_chars do
                subject = new MDLine("")
                assert subject.count_chars('*') == 0
index 725c612..87afb4a 100644 (file)
 # limitations under the License.
 
 # Impements the services of `mnit:app` using the API from the Android ndk
-module android_app
+module android_app is
+       android_manifest_activity """
+               android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+               android:configChanges="orientation|keyboardHidden"
+               android:screenOrientation="portrait""""
+end
 
 import mnit
 import android
diff --git a/lib/neo4j/jsonable.nit b/lib/neo4j/jsonable.nit
new file mode 100644 (file)
index 0000000..3578d59
--- /dev/null
@@ -0,0 +1,434 @@
+# 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.
+
+# Introduce base classes and services for JSON handling.
+module jsonable
+
+import standard
+private import json::json_parser
+private import json::json_lexer
+
+# Something that can be translated to JSON
+interface Jsonable
+       # Get the JSON representation of `self`
+       fun to_json: String is abstract
+end
+
+redef class String
+       super Jsonable
+
+       redef fun to_json do
+               var res = new FlatBuffer
+               res.add '\"'
+               for i in [0..self.length[ do
+                       var char = self[i]
+                       if char == '\\' then
+                               res.append("\\\\")
+                               continue
+                       else if char == '\"' then
+                               res.append("\\\"")
+                               continue
+                       else if char == '\/' then
+                               res.append("\\/")
+                               continue
+                       else if char == '\n' then
+                               res.append("\\n")
+                               continue
+                       else if char == '\r' then
+                               res.append("\\r")
+                               continue
+                       else if char == '\t' then
+                               res.append("\\t")
+                               continue
+                       end
+                       res.add char
+               end
+               res.add '\"'
+               return res.write_to_string
+       end
+end
+
+redef class Int
+       super Jsonable
+
+       redef fun to_json do return self.to_s
+end
+
+redef class Float
+       super Jsonable
+
+       redef fun to_json do return self.to_s
+end
+
+redef class Bool
+       super Jsonable
+
+       redef fun to_json do return self.to_s
+end
+
+# A JSON Object representation that behaves like a `Map`
+class JsonObject
+       super Jsonable
+       super Map[String, nullable Jsonable]
+
+       private var map = new HashMap[String, nullable Jsonable]
+
+       # Create an empty `JsonObject`
+       #
+       #     var obj = new JsonObject
+       #     assert obj.is_empty
+       init do end
+
+       # Init the JSON Object from a Nit `Map`
+       #
+       #     var map = new HashMap[String, String]
+       #     map["foo"] = "bar"
+       #     map["goo"] = "baz"
+       #     var obj = new JsonObject.from(map)
+       #     assert obj.length == 2
+       #     assert obj["foo"] == "bar"
+       #     assert obj["goo"] == "baz"
+       init from(items: Map[String, nullable Jsonable]) do
+               for k, v in items do map[k] = v
+       end
+
+       redef fun [](key) do return map[key]
+       redef fun []=(key, value) do map[key] = value
+       redef fun clear do map.clear
+       redef fun has_key(key) do return map.has_key(key)
+       redef fun is_empty do return map.is_empty
+       redef fun iterator do return map.iterator
+       redef fun keys do return map.keys
+       redef fun values do return map.values
+       redef fun length do return map.length
+
+       # Advanced query to get a value within `self` or its children.
+       #
+       # A query is composed of the keys to each object seperated by '.'.
+       #
+       # REQUIRE `self.has_key(query)`
+       #
+       #     var obj1 = new JsonObject
+       #     obj1["baz"] = "foobarbaz"
+       #     var obj2 = new JsonObject
+       #     obj2["bar"] = obj1
+       #     var obj3 = new JsonObject
+       #     obj3["foo"] = obj2
+       #     assert obj3.get("foo.bar.baz") == "foobarbaz"
+       fun get(query: String): nullable Jsonable do
+               var keys = query.split(".").reversed
+               var key = keys.pop
+
+               assert has_key(key)
+               var node = self[key]
+
+               while not keys.is_empty do
+                       key = keys.pop
+                       assert node isa JsonObject and node.has_key(key)
+                       node = node[key]
+               end
+               return node
+       end
+
+       # Create an empty `JsonObject`
+       #
+       #     var obj = new JsonObject
+       #     obj["foo"] = "bar"
+       #     assert obj.to_json == "\{\"foo\": \"bar\"\}"
+       redef fun to_json do
+               var tpl = new Array[String]
+               tpl.add "\{"
+               var vals = new Array[String]
+               for k, v in self do
+                       if v == null then
+                               vals.add "{k.to_json}: null"
+                       else
+                               vals.add "{k.to_json}: {v.to_json}"
+                       end
+               end
+               tpl.add vals.join(",")
+               tpl.add "\}"
+               return tpl.join("")
+       end
+
+       redef fun to_s do return to_json
+end
+
+# A JSON Array representation that behaves like a `Sequence`
+class JsonArray
+       super Jsonable
+       super Sequence[nullable Jsonable]
+
+       private var array = new Array[nullable Jsonable]
+
+       init do end
+
+       # init the JSON Array from a Nit `Collection`
+       init from(items: Collection[nullable Jsonable]) do
+               array.add_all(items)
+       end
+
+       redef fun [](key) do return array[key]
+       redef fun []=(key, value) do array[key] = value
+       redef fun clear do array.clear
+       redef fun insert(item, index) do array.insert(item, index)
+       redef fun is_empty do return array.is_empty
+       redef fun iterator do return array.iterator
+       redef fun length do return array.length
+       redef fun pop do return array.pop
+       redef fun push(value) do array.push(value)
+       redef fun remove_at(index) do array.remove_at(index)
+       redef fun shift do return array.shift
+       redef fun unshift(e) do array.unshift(e)
+
+       redef fun to_json do
+               var tpl = new Array[String]
+               tpl.add "["
+               var vals = new Array[String]
+               for v in self do
+                       if v == null then
+                               vals.add "null"
+                       else
+                               vals.add v.to_json
+                       end
+               end
+               tpl.add vals.join(",")
+               tpl.add "]"
+               return tpl.join("")
+       end
+
+       redef fun to_s do return to_json
+end
+
+# An error in JSON format that can be returned by tools using JSON like parsers.
+#
+#     var error = new JsonError("ErrorCode", "ErrorMessage")
+#     assert error.to_s == "ErrorCode: ErrorMessage"
+#     assert error.to_json == "\{\"error\": \"ErrorCode\", \"message\": \"ErrorMessage\"\}"
+class JsonError
+       super Jsonable
+
+       # The error code
+       var error: String
+
+       # The error message
+       var message: String
+
+       redef fun to_json do
+               var tpl = new Array[String]
+               tpl.add "\{"
+               tpl.add "\"error\": {error.to_json}, "
+               tpl.add "\"message\": {message.to_json}"
+               tpl.add "\}"
+               return tpl.join("")
+       end
+
+       redef fun to_s do return "{error}: {message}"
+end
+
+# Redef parser
+
+redef class Nvalue
+       private fun to_nit_object: nullable Jsonable is abstract
+end
+
+redef class Nvalue_number
+       redef fun to_nit_object
+       do
+               var text = n_number.text
+               if text.chars.has('.') or text.chars.has('e') or text.chars.has('E') then return text.to_f
+               return text.to_i
+       end
+end
+
+redef class Nvalue_string
+       redef fun to_nit_object do return n_string.to_nit_string
+end
+
+redef class Nvalue_true
+       redef fun to_nit_object do return true
+end
+
+redef class Nvalue_false
+       redef fun to_nit_object do return false
+end
+
+redef class Nvalue_null
+       redef fun to_nit_object do return null
+end
+
+redef class Nstring
+       # FIXME support \n, etc.
+       fun to_nit_string: String do
+               var res = new FlatBuffer
+               var skip = false
+               for i in [1..text.length-2] do
+                       if skip then
+                               skip = false
+                               continue
+                       end
+                       var char = text[i]
+                       if char == '\\' and i < text.length - 2 then
+                               if text[i + 1] == '\\' then
+                                       res.add('\\')
+                                       skip = true
+                                       continue
+                               end
+                               if text[i + 1] == '\"' then
+                                       res.add('\"')
+                                       skip = true
+                                       continue
+                               end
+                               if text[i + 1] == '/' then
+                                       res.add('\/')
+                                       skip = true
+                                       continue
+                               end
+                               if text[i + 1] == 'n' then
+                                       res.add('\n')
+                                       skip = true
+                                       continue
+                               end
+                               if text[i + 1] == 'r' then
+                                       res.add('\r')
+                                       skip = true
+                                       continue
+                               end
+                               if text[i + 1] == 't' then
+                                       res.add('\t')
+                                       skip = true
+                                       continue
+                               end
+                       end
+                       res.add char
+               end
+               return res.write_to_string
+       end
+end
+
+redef class Nvalue_object
+       redef fun to_nit_object
+       do
+               var obj = new JsonObject
+               var members = n_members
+               if members != null then
+                       var pairs = members.pairs
+                       for pair in pairs do obj[pair.name] = pair.value
+               end
+               return obj
+       end
+end
+
+redef class Nmembers
+       fun pairs: Array[Npair] is abstract
+end
+
+redef class Nmembers_tail
+       redef fun pairs
+       do
+               var arr = n_members.pairs
+               arr.add n_pair
+               return arr
+       end
+end
+
+redef class Nmembers_head
+       redef fun pairs do return [n_pair]
+end
+
+redef class Npair
+       fun name: String do return n_string.to_nit_string
+       fun value: nullable Jsonable do return n_value.to_nit_object
+end
+
+redef class Nvalue_array
+       redef fun to_nit_object
+       do
+               var arr = new JsonArray
+               var elements = n_elements
+               if elements != null then
+                       var items = elements.items
+                       for item in items do arr.add(item.to_nit_object)
+               end
+               return arr
+       end
+end
+
+redef class Nelements
+       fun items: Array[Nvalue] is abstract
+end
+
+redef class Nelements_tail
+       redef fun items
+       do
+               var items = n_elements.items
+               items.add(n_value)
+               return items
+       end
+end
+
+redef class Nelements_head
+       redef fun items do return [n_value]
+end
+
+redef class Text
+       # Parse a JSON String as Jsonable entities
+       #
+       # Example with `JsonObject`"
+       #
+       #     var obj = "\{\"foo\": \{\"bar\": true, \"goo\": [1, 2, 3]\}\}".to_jsonable
+       #     assert obj isa JsonObject
+       #     assert obj["foo"] isa JsonObject
+       #     assert obj["foo"].as(JsonObject)["bar"] == true
+       #
+       # Example with `JsonArray`
+       #
+       #     var arr = "[1, 2, 3]".to_jsonable
+       #     assert arr isa JsonArray
+       #     assert arr.length == 3
+       #     assert arr.first == 1
+       #     assert arr.last == 3
+       #
+       # Example with `String`
+       #
+       #     var str = "\"foo, bar, baz\"".to_jsonable
+       #     assert str isa String
+       #     assert str == "foo, bar, baz"
+       #
+       # Malformed JSON input returns a `JsonError` object
+       #
+       #     var bad = "\{foo: \"bar\"\}".to_jsonable
+       #     assert bad isa JsonError
+       #     assert bad.error == "JsonLexerError"
+       fun to_jsonable: nullable Jsonable
+       do
+               var lexer = new Lexer_json(to_s)
+               var parser = new Parser_json
+               var tokens = lexer.lex
+               parser.tokens.add_all(tokens)
+               var root_node = parser.parse
+               if root_node isa NStart then
+                       return root_node.n_0.to_nit_object
+               else if root_node isa NLexerError then
+                       var pos = root_node.position
+                       var msg =  "{root_node.message} at {pos or else "<unknown>"} for {root_node}"
+                       return new JsonError("JsonLexerError", msg)
+               else if root_node isa NParserError then
+                       var pos = root_node.position
+                       var msg = "{root_node.message} at {pos or else "<unknown>"} for {root_node}"
+                       return new JsonError("JsonParsingError", msg)
+               else abort
+       end
+end
+
diff --git a/lib/pthreads/extra.nit b/lib/pthreads/extra.nit
new file mode 100644 (file)
index 0000000..416b174
--- /dev/null
@@ -0,0 +1,62 @@
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# Offers some POSIX threads services that are not available on all platforms
+module extra is
+       c_compiler_option("-pthread")
+       c_linker_option("-pthread")
+end
+
+intrude import pthreads
+
+in "C" `{
+       // TODO protect with: #ifdef WITH_LIBGC
+       #ifndef ANDROID
+               #define GC_THREADS
+               #include <gc.h>
+       #endif
+`}
+
+redef extern class NativePthread
+       fun cancel: Bool `{
+               return pthread_cancel(*recv);
+       `}
+end
+
+redef class Thread
+       # Cancel the execution of the thread
+       fun cancel
+       do
+               if native == null then return
+               native.cancel
+               native = null
+       end
+end
+
+# Does not return if the running thread is to be cancelled
+fun test_cancel `{ pthread_testcancel(); `}
+
+private extern class NativePthreadBarrier in "C" `{ pthread_barrier_t * `}
+       new(count: Int) `{
+               pthread_barrier_t *barrier = malloc(sizeof(pthread_barrier_t));
+               int res = pthread_barrier_init(barrier, NULL, count);
+               return barrier;
+       `}
+
+       fun destroy `{ pthread_barrier_destroy(recv); `}
+
+       fun wait `{ pthread_barrier_wait(recv); `}
+end
index 1e76e28..94cf078 100644 (file)
@@ -34,9 +34,10 @@ in "C" `{
        // TODO protect with: #ifdef WITH_LIBGC
        // We might have to add the next line to gc_chooser.c too, especially
        // if we get an error like "thread not registered with GC".
+       #ifndef ANDROID
                #define GC_THREADS
                #include <gc.h>
-       //#endif
+       #endif
 `}
 
 redef class Sys
@@ -114,10 +115,6 @@ private extern class NativePthread in "C" `{ pthread_t * `}
                return (nullable_Object)thread_return;
        `}
 
-       fun cancel: Bool `{
-               return pthread_cancel(*recv);
-       `}
-
        fun attr: NativePthreadAttr `{
                pthread_attr_t *pattr = malloc(sizeof(pthread_attr_t));
                pthread_getattr_np(*recv, pattr);
@@ -192,18 +189,6 @@ private extern class NativePthreadMutexAttr in "C" `{ pthread_mutexattr_t * `}
        # pthread_mutexattr_setrobust_np
 end
 
-private extern class NativePthreadBarrier in "C" `{ pthread_barrier_t * `}
-       new(count: Int) `{
-               pthread_barrier_t *barrier = malloc(sizeof(pthread_barrier_t));
-               int res = pthread_barrier_init(barrier, NULL, count);
-               return barrier;
-       `}
-
-       fun destroy `{ pthread_barrier_destroy(recv); `}
-
-       fun wait `{ pthread_barrier_wait(recv); `}
-end
-
 private extern class NativePthreadKey in "C" `{ pthread_key_t * `}
        new `{
                pthread_key_t *key = malloc(sizeof(pthread_key_t));
@@ -222,6 +207,27 @@ private extern class NativePthreadKey in "C" `{ pthread_key_t * `}
        `}
 end
 
+private extern class NativePthreadCond in "C" `{ pthread_cond_t * `}
+       new `{
+               pthread_cond_t cond;
+               int r = pthread_cond_init(&cond, NULL);
+               if (r == 0) {
+                       pthread_cond_t *pcond = malloc(sizeof(pthread_cond_t));
+                       memmove(pcond, &cond, sizeof(pthread_cond_t));
+                       return pcond;
+               }
+               return NULL;
+       `}
+
+       fun destroy `{ pthread_cond_destroy(recv); `}
+
+       fun signal `{ pthread_cond_signal(recv); `}
+
+       fun broadcast `{ pthread_cond_broadcast(recv);  `}
+
+       fun wait(mutex: NativePthreadMutex) `{ pthread_cond_wait(recv, mutex); `}
+end
+
 #
 ## Nity part
 #
@@ -272,14 +278,6 @@ abstract class Thread
                return r
        end
 
-       # Cancel the execution of the thread
-       fun cancel
-       do
-               if native == null then return
-               native.cancel
-               native = null
-       end
-
        redef fun finalize
        do
                if native == null then return
@@ -298,9 +296,6 @@ end
 # Exit current thread and return `value` to caller of `Thread::join`
 fun exit_thread(value: nullable Object) `{ pthread_exit(value); `}
 
-# Does not return if the running thread is to be cancelled
-fun test_cancel `{ pthread_testcancel(); `}
-
 # Returns the handle to the running `Thread`
 fun thread: Thread
 do
@@ -364,24 +359,36 @@ end
 class Barrier
        super Finalizable
 
+       private var mutex = new Mutex
+       private var cond: nullable NativePthreadCond = new NativePthreadCond
+
        # Number of threads that must be waiting for `wait` to unblock
        var count: Int
 
-       private var native: nullable NativePthreadBarrier is noinit
-
-       init do native = new NativePthreadBarrier(count)
+       private var threads_waiting = 0
 
        # Wait at this barrier and block until there are a `count` threads waiting
-       fun wait do native.wait
+       fun wait
+       do
+               mutex.lock
+               threads_waiting += 1
+               if threads_waiting == count then
+                       threads_waiting = 0
+                       cond.broadcast
+               else
+                       cond.wait(mutex.native.as(not null))
+               end
+               mutex.unlock
+       end
 
        redef fun finalize
        do
-               var native = self.native
-               if native != null then
-                       native.destroy
-                       native.free
+               var cond = self.cond
+               if cond != null then
+                       cond.destroy
+                       cond.free
                end
-               self.native = null
+               self.cond = null
        end
 end
 
index b1b1efc..270ed22 100644 (file)
@@ -193,4 +193,22 @@ class TestSaxophonit
                expected.end_document
                assert_equals
        end
+
+       fun test_mixed do
+               var atts = new AttributesImpl
+
+               # TODO For the moment, ignorable white space is not detected.
+               before_test
+               parse_string("<foo>  \r\n\n<bar>  baz  </bar></foo>")
+               expected.document_locator = new SAXLocatorImpl
+               expected.start_document
+               expected.start_element("", "foo", "foo", atts)
+               expected.characters("  \n\n")
+               expected.start_element("", "bar", "bar", atts)
+               expected.characters("  baz  ")
+               expected.end_element("", "bar", "bar")
+               expected.end_element("", "foo", "foo")
+               expected.end_document
+               assert_equals
+       end
 end
index a439ec1..56633ce 100644 (file)
@@ -207,7 +207,7 @@ private class ContainerIterator[E]
 
        redef var is_ok: Bool = true
 
-       private var container: Container[E]
+       var container: Container[E]
 end
 
 # Items can be removed from this collection
@@ -334,6 +334,10 @@ interface Set[E: Object]
                return nhs
        end
 
+       # Returns a new instance of `Set`.
+       #
+       # Depends on the subclass, mainly used for copy services
+       # like `union` or `intersection`.
        protected fun new_set: Set[E] is abstract
 end
 
@@ -944,7 +948,7 @@ private class CoupleMapIterator[K: Object, V]
                _iter.next
        end
 
-       private var iter: Iterator[Couple[K,V]]
+       var iter: Iterator[Couple[K,V]]
 end
 
 # Some tools ###################################################################
index ca6e9fa..331a9d9 100644 (file)
@@ -429,7 +429,7 @@ private class ArrayIterator[E]
 
        redef var index = 0
 
-       private var array: AbstractArrayRead[E]
+       var array: AbstractArrayRead[E]
 end
 
 private class ArrayReverseIterator[E]
@@ -508,7 +508,7 @@ private class ArraySetIterator[E: Object]
 
        redef fun item: E do return _iter.item
 
-       private var iter: ArrayIterator[E]
+       var iter: ArrayIterator[E]
 end
 
 
@@ -778,8 +778,14 @@ universal NativeArray[E]
        fun length: Int is intern
        # Use `self` to initialize a standard Nit Array.
        fun to_a: Array[E] do return new Array[E].with_native(self, length)
+
+       # Get item at `index`.
        fun [](index: Int): E is intern
+
+       # Set `item` at `index`.
        fun []=(index: Int, item: E) is intern
+
+       # Copy `length` items to `dest`.
        fun copy_to(dest: NativeArray[E], length: Int) is intern
        #fun =(o: NativeArray[E]): Bool is intern
        #fun !=(o: NativeArray[E]): Bool is intern
index 9d5e678..0701cc7 100644 (file)
@@ -21,6 +21,8 @@ import hash_collection
 import union_find
 
 redef class Sequence[E]
+
+       # Copy the content of `self` between `start` and `len` to a new Array.
        fun subarray(start, len: Int): Array[E]
        do
                var a = new Array[E].with_capacity(len)
index 92b8d5c..d389c5a 100644 (file)
@@ -19,18 +19,18 @@ import array
 private abstract class HashCollection[K: Object]
        type N: HashNode[K]
 
-       private var array: nullable NativeArray[nullable N] = null # Used to store items
-       private var capacity: Int = 0 # Size of _array
-       private var the_length: Int = 0 # Number of items in the map
+       var array: nullable NativeArray[nullable N] = null # Used to store items
+       var capacity: Int = 0 # Size of _array
+       var the_length: Int = 0 # Number of items in the map
 
-       private var first_item: nullable N = null # First added item (used to visit items in nice order)
-       private var last_item: nullable N = null # Last added item (same)
+       var first_item: nullable N = null # First added item (used to visit items in nice order)
+       var last_item: nullable N = null # Last added item (same)
 
        # The last key accessed (used for cache)
-       private var last_accessed_key: nullable K = null
+       var last_accessed_key: nullable K = null
 
        # The last node accessed (used for cache)
-       private var last_accessed_node: nullable N = null
+       var last_accessed_node: nullable N = null
 
        # Return the index of the key k
        fun index_at(k: K): Int
@@ -191,12 +191,12 @@ private abstract class HashCollection[K: Object]
 end
 
 private abstract class HashNode[K: Object]
-       private var key: K
+       var key: K
        type N: HashNode[K]
-       private var next_item: nullable N = null
-       private var prev_item: nullable N = null
-       private var prev_in_bucklet: nullable N = null
-       private var next_in_bucklet: nullable N = null
+       var next_item: nullable N = null
+       var prev_item: nullable N = null
+       var prev_in_bucklet: nullable N = null
+       var next_in_bucklet: nullable N = null
 end
 
 # A map implemented with a hash table.
@@ -343,9 +343,10 @@ end
 private class HashMapNode[K: Object, V]
        super HashNode[K]
        redef type N: HashMapNode[K, V]
-       private var value: V
+       var value: V
 end
 
+# A `MapIterator` over a `HashMap`.
 class HashMapIterator[K: Object, V]
        super MapIterator[K, V]
        redef fun is_ok do return _node != null
@@ -465,10 +466,10 @@ private class HashSetIterator[E: Object]
        end
 
        # The set to iterate on
-       private var set: HashSet[E]
+       var set: HashSet[E]
 
        # The position in the internal map storage
-       private var node: nullable HashSetNode[E] = null
+       var node: nullable HashSetNode[E] = null
 
        init
        do
index 49fb693..ae1b675 100644 (file)
@@ -278,6 +278,7 @@ class ListIterator[E]
        super IndexedIterator[E]
        redef fun item do return _node.item
 
+       # Set item `e` at self `index`.
        fun item=(e: E) do _node.item = e
 
        redef fun is_ok do return not _node == null
index a79f218..61b5194 100644 (file)
@@ -27,10 +27,17 @@ class Range[E: Discrete]
        # Get the element after the last one.
        var after: E
 
+       #     assert [1..10].has(5)
+       #     assert [1..10].has(10)
+       #     assert not [1..10[.has(10)
        redef fun has(item) do return item >= first and item <= last
 
+       #     assert [1..1].has_only(1)
+       #     assert not [1..10].has_only(1)
        redef fun has_only(item) do return first == item and item == last or is_empty
 
+       #     assert [1..10].count(1)   == 1
+       #     assert [1..10].count(0)   == 0
        redef fun count(item)
        do
                if has(item) then
@@ -42,8 +49,13 @@ class Range[E: Discrete]
 
        redef fun iterator do return new IteratorRange[E](self)
 
+       #     assert [1..10].length             == 10
+       #     assert [1..10[.length             == 9
+       #     assert [1..1].length              == 1
+       #     assert [1..-10].length    == 0
        redef fun length
        do
+               if is_empty then return 0
                var nb = first.distance(after)
                if nb > 0 then
                        return nb
@@ -52,12 +64,19 @@ class Range[E: Discrete]
                end
        end
 
+       #     assert not [1..10[.is_empty
+       #     assert not [1..1].is_empty
+       #     assert [1..-10].is_empty
        redef fun is_empty do return first >= after
 
        # Create a range [`from`, `to`].
-       # The syntax `[from..to[` is equivalent.
-       init(from: E, to: E)
-       do
+       # The syntax `[from..to]` is equivalent.
+       #
+       #     var a = [10..15]
+       #     var b = new Range[Int] (10,15)
+       #     assert a == b
+       #     assert a.to_a == [10, 11, 12, 13, 14, 15]
+       init(from: E, to: E) is old_style_init do
                first = from
                last = to
                after = to.successor(1)
@@ -65,18 +84,46 @@ class Range[E: Discrete]
 
        # Create a range [`from`, `to`[.
        # The syntax `[from..to[` is equivalent.
+       #
+       #     var a = [10..15[
+       #     var b = new Range[Int].without_last(10,15)
+       #     assert a == b
+       #     assert a.to_a == [10, 11, 12, 13, 14]
        init without_last(from: E, to: E)
        do
                first = from
                last = to.predecessor(1)
                after = to
        end
+
+       # Two ranges are equals if they have the same first and last elements.
+       #
+       #     var a = new Range[Int](10, 15)
+       #     var b = new Range[Int].without_last(10, 15)
+       #     assert a == [10..15]
+       #     assert a == [10..16[
+       #     assert not a == [10..15[
+       #     assert b == [10..15[
+       #     assert b == [10..14]
+       #     assert not b == [10..15]
+       redef fun ==(o) do
+               return o isa Range[E] and self.first == o.first and self.last == o.last
+       end
+
+       #     var a = new Range[Int](10, 15)
+       #     assert a.hash == 455
+       #     var b = new Range[Int].without_last(10, 15)
+       #     assert b.hash == 432
+       redef fun hash do
+               # 11 and 23 are magic numbers empirically determined to be not so bad.
+               return first.hash * 11 + last.hash * 23
+       end
 end
 
 private class IteratorRange[E: Discrete]
        # Iterator on ranges.
        super Iterator[E]
-       private var range: Range[E]
+       var range: Range[E]
        redef var item is noinit
 
        redef fun is_ok do return _item < _range.after
index 150ed48..2495800 100644 (file)
@@ -48,8 +48,7 @@ class Process
        var arguments: nullable Array[String]
 
        # Launch a command with some arguments
-       init(command: String, arguments: String...)
-       do
+       init(command: String, arguments: String...) is old_style_init do
                self.command = command
                self.arguments = arguments
                execute
@@ -92,6 +91,8 @@ end
 class IProcess
        super Process
        super IStream
+
+       # File Descriptor used for the input.
        var stream_in: FDIStream is noinit
 
        redef fun close do stream_in.close
@@ -113,6 +114,8 @@ end
 class OProcess
        super Process
        super OStream
+
+       # File Descriptor used for the output.
        var stream_out: OStream is noinit
 
        redef fun close do stream_out.close
@@ -159,6 +162,9 @@ redef class Sys
 end
 
 redef class NativeString
+       # Execute self as a shell command.
+       #
+       # See the posix function system(3).
        fun system: Int is extern "string_NativeString_NativeString_system_0"
 end
 
index fb89882..60f5f69 100644 (file)
@@ -38,6 +38,7 @@ abstract class FStream
        # The FILE *.
        private var file: nullable NativeFile = null
 
+       # The status of a file. see POSIX stat(2).
        fun file_stat: FileStat do return _file.file_stat
 
        # File descriptor of this file
@@ -64,7 +65,7 @@ class IFStream
 
        redef fun close
        do
-               var i = _file.io_close
+               _file.io_close
                _buffer.clear
                end_reached = true
        end
@@ -113,7 +114,7 @@ class OFStream
 
        redef fun close
        do
-               var i = _file.io_close
+               _file.io_close
                _is_writable = false
        end
 
@@ -144,6 +145,7 @@ end
 
 ###############################################################################
 
+# Standard input stream.
 class Stdin
        super IFStream
 
@@ -156,6 +158,7 @@ class Stdin
        redef fun poll_in: Bool is extern "file_stdin_poll_in"
 end
 
+# Standard output stream.
 class Stdout
        super OFStream
        init do
@@ -165,6 +168,7 @@ class Stdout
        end
 end
 
+# Standard error stream.
 class Stderr
        super OFStream
        init do
index 2e9c9ae..d65b135 100644 (file)
@@ -30,6 +30,28 @@ import end # Mark this module is a top level one. (must be only one)
 #
 # Currently, Object is also used to collect all top-level methods.
 interface Object
+       # Type of this instance, automatically specialized in every class
+       #
+       # A common use case of the virtual type `SELF` is to type an attribute and
+       # store another instance of the same type as `self`. It can also be used as as
+       # return type to a method producing a copy of `self` or returning an instance
+       # expected to be the exact same type as self.
+       #
+       # This virtual type must be used with caution as it can hinder specialization.
+       # In fact, it imposes strict restrictions on all sub-classes and their usage.
+       # For example, using `SELF` as a return type of a method `foo`
+       # forces all subclasses to ensure that `foo` returns the correct and updated
+       # type.
+       # A dangerous usage take the form of a method typed by `SELF` which creates
+       # and returns a new instance.
+       # If not correctly specialized, this method would break when invoked on a
+       # sub-class.
+       #
+       # A general rule for safe usage of `SELF` is to ensure that inputs typed
+       # `SELF` are stored in attributes typed `SELF` and returned by methods typed
+       # `SELF`, pretty much the same things as you would do with parameter types.
+       type SELF: Object
+
        # The unique object identifier in the class.
        # Unless specific code, you should not use this method.
        # The identifier is used internally to provide a hash value.
@@ -331,6 +353,21 @@ universal Float
                end
        end
 
+       # Compare float numbers with a given precision.
+       #
+       # Because of the loss of precision in floating numbers,
+       # the `==` method is often not the best way to compare them.
+       #
+       # ~~~
+       # assert 0.01.is_approx(0.02, 0.1)   == true
+       # assert 0.01.is_approx(0.02, 0.001) == false
+       # ~~~
+       fun is_approx(other, precision: Float): Bool
+       do
+               assert precision >= 0.0
+               return self <= other + precision and self >= other - precision
+       end
+
        redef fun max(other)
        do
                if self < other then
@@ -377,6 +414,13 @@ universal Int
        redef fun -(i) is intern
        redef fun *(i) is intern
        redef fun /(i) is intern
+
+       # Modulo of `self` with `i`.
+       #
+       # Finds the remainder of division of `self` by `i`.
+       #
+       #     assert 5 % 2                      == 1
+       #     assert 10 % 2                     == 0
        fun %(i: Int): Int is intern
 
        redef fun zero do return 0
index 2bbb6aa..1d1437b 100644 (file)
@@ -114,17 +114,66 @@ redef class Int
 end
 
 redef class Float
+
+       # Returns the non-negative square root of `self`.
+       #
+       #     assert 9.0.sqrt == 3.0
+       #     #assert 3.0.sqrt == 1.732
+       #     assert 1.0.sqrt == 1.0
+       #     assert 0.0.sqrt == 0.0
        fun sqrt: Float is extern "kernel_Float_Float_sqrt_0"
+
+       # Computes the cosine of `self` (expressed in radians).
+       #
+       #     #assert pi.cos == -1.0
        fun cos: Float is extern "kernel_Float_Float_cos_0"
+
+       # Computes the sine of `self` (expressed in radians).
+       #
+       #     #assert pi.sin == 0.0
        fun sin: Float is extern "kernel_Float_Float_sin_0"
+
+       # Computes the cosine of x (expressed in radians).
+       #
+       #     #assert 0.0.tan == 0.0
        fun tan: Float is extern "kernel_Float_Float_tan_0"
+
+       # Computes the arc cosine of `self`.
+       #
+       #     #assert 0.0.acos == pi / 2.0
        fun acos: Float is extern "kernel_Float_Float_acos_0"
+
+       # Computes the arc sine of `self`.
+       #
+       #     #assert 1.0.asin == pi / 2.0
        fun asin: Float is extern "kernel_Float_Float_asin_0"
+
+       # Computes the arc tangent of `self`.
+       #
+       #     #assert 0.0.tan == 0.0
        fun atan: Float is extern "kernel_Float_Float_atan_0"
+
+       # Returns the absolute value of `self`.
+       #
+       #     assert 12.0.abs == 12.0
+       #     assert (-34.56).abs == 34.56
+       #     assert -34.56.abs == -34.56
        fun abs: Float `{ return fabs(recv); `}
 
+       # Returns `self` raised at `e` power.
+       #
+       #     #assert 2.0.pow(0.0) == 1.0
+       #     #assert 2.0.pow(3.0) == 8.0
+       #     #assert 0.0.pow(9.0) == 0.0
        fun pow(e: Float): Float is extern "kernel_Float_Float_pow_1"
+
+       # Returns the logarithm of `self`.
+       #
+       #     assert 0.0.log.is_inf == -1
+       #     #assert 1.0.log == 0.0
        fun log: Float is extern "kernel_Float_Float_log_0"
+
+       # Returns **e** raised to `self`.
        fun exp: Float is extern "kernel_Float_Float_exp_0"
 
        #     assert 1.1.ceil == 2.0
@@ -138,11 +187,22 @@ redef class Float
        #     assert 2.0.floor == 2.0
        #     assert (-1.5).floor == -2.0
        fun floor: Float `{ return floor(recv); `}
+
+       # Rounds the value of a float to its nearest integer value
+       #
+       #     assert 1.67.round == 2.0
+       #     assert 1.34.round == 1.0
+       #     assert -1.34.round == -1.0
+       #     assert -1.67.round == -2.0
+       fun round: Float is extern "round"
        
        # Returns a random `Float` in `[0.0 .. self[`.
        fun rand: Float is extern "kernel_Float_Float_rand_0"
-       fun hypot_with( b : Float ) : Float is extern "hypotf"
 
+       # Returns the euclidean distance from `b`.
+       fun hypot_with(b : Float): Float is extern "hypotf"
+
+       # Returns true is self is not a number.
        fun is_nan: Bool is extern "isnan"
 
        # Is the float an infinite value
@@ -185,7 +245,13 @@ redef class Sys
        end
 end
 
+# Computes the arc tangent given `x` and `y`.
+#
+#     assert atan2(-0.0, 1.0) == -0.0
+#     assert atan2(0.0, 1.0) == 0.0
 fun atan2(x: Float, y: Float): Float is extern "kernel_Any_Any_atan2_2"
+
+# Approximate value of **pi**.
 fun pi: Float is extern "kernel_Any_Any_pi_0"
 
 # Initialize the pseudo-random generator with the given seed.
index 97cb7cb..98281e9 100644 (file)
@@ -349,7 +349,6 @@ class Regex
                var cstr = text.substring_from(from).to_cstring
                var eflags = gather_eflags
                var match = self.native_match
-               var matches = new Array[Match]
 
                var res = native.regexec(cstr, 1, match, eflags)
 
index c4915fd..ad09beb 100644 (file)
@@ -94,7 +94,7 @@ private class Concat
        # Right child of the node
        var right: String
 
-       init(l: String, r: String) do
+       init(l: String, r: String) is old_style_init do
                left = l
                right = r
                length = l.length + r.length
@@ -145,7 +145,6 @@ private class Concat
 
        redef fun +(o) do
                var s = o.to_s
-               var mlen = length
                var slen = s.length
                if s isa Concat then
                        return new Concat(self, s)
@@ -485,7 +484,7 @@ private class RopeReviter
        # the Rope traversal.
        var subs: IndexedIterator[String]
 
-       init(root: RopeString) do
+       init(root: RopeString) is old_style_init do
                pos = root.length - 1
                subs = new ReverseRopeSubstrings(root)
                ns = subs.item
@@ -532,7 +531,7 @@ private class RopeIter
        # Position (char) in the Rope (0-indexed)
        var pos: Int
 
-       init(root: RopeString) do
+       init(root: RopeString) is old_style_init do
                subs = new RopeSubstrings(root)
                pns = 0
                str = subs.item
@@ -578,7 +577,7 @@ private class ReverseRopeSubstrings
        # Current leaf
        var str: String is noinit
 
-       init(root: RopeString) do
+       init(root: RopeString) is old_style_init do
                var r = new RopeIterPiece(root, false, true, null)
                pos = root.length - 1
                var lnod: String = root
@@ -663,7 +662,7 @@ private class RopeBufSubstringIterator
        # Did we attain the buffered part ?
        var nsstr_done = false
 
-       init(str: RopeBuffer) do
+       init(str: RopeBuffer) is old_style_init do
                iter = str.str.substrings
                nsstr = new FlatString.with_infos(str.ns, str.rpos - str.dumped, str.dumped, str.rpos - 1)
                if str.length == 0 then nsstr_done = true
@@ -700,7 +699,7 @@ private class RopeSubstrings
        # Current leaf
        var str: String is noinit
 
-       init(root: RopeString) do
+       init(root: RopeString) is old_style_init do
                var r = new RopeIterPiece(root, true, false, null)
                pos = 0
                max = root.length - 1
@@ -786,7 +785,7 @@ private class RopeChars
 
        var tgt: RopeString
 
-       init(s: RopeString) do tgt = s
+       init(s: RopeString) is old_style_init do tgt = s
 
        redef fun [](i) do
                return tgt[i]
@@ -798,20 +797,26 @@ private class RopeChars
 
 end
 
+# An Iterator over a RopeBuffer.
 class RopeBufferIter
        super IndexedIterator[Char]
 
+       # Subiterator.
        var sit: IndexedIterator[Char]
 
+       # Native string iterated over.
        var ns: NativeString
 
+       # Current position in `ns`.
        var pns: Int
 
+       # Maximum position iterable.
        var maxpos: Int
 
        redef var index: Int
 
-       init(t: RopeBuffer) do
+       # Init the iterator from a RopeBuffer.
+       init(t: RopeBuffer) is old_style_init do
                ns = t.ns
                maxpos = t.rpos
                sit = t.str.chars.iterator
@@ -819,6 +824,7 @@ class RopeBufferIter
                index = 0
        end
 
+       # Init the iterator from a RopeBuffer starting from `pos`.
        init from(t: RopeBuffer, pos: Int) do
                ns = t.ns
                maxpos = t.length
@@ -844,24 +850,30 @@ class RopeBufferIter
        end
 end
 
+# Reverse iterator over a RopeBuffer.
 class RopeBufferReviter
        super IndexedIterator[Char]
 
+       # Subiterator.
        var sit: IndexedIterator[Char]
 
+       # Native string iterated over.
        var ns: NativeString
 
+       # Current position in `ns`.
        var pns: Int
 
        redef var index: Int
 
-       init(tgt: RopeBuffer) do
+       # Init the iterator from a RopeBuffer.
+       init(tgt: RopeBuffer) is old_style_init do
                sit = tgt.str.chars.reverse_iterator
                pns = tgt.rpos - 1
                index = tgt.length - 1
                ns = tgt.ns
        end
 
+       # Init the iterator from a RopeBuffer starting from `pos`.
        init from(tgt: RopeBuffer, pos: Int) do
                sit = tgt.str.chars.reverse_iterator_from(pos - tgt.rpos - tgt.dumped)
                pns = pos - tgt.str.length
index 84b167a..3026c78 100644 (file)
@@ -244,6 +244,7 @@ abstract class BufferedIStream
        end
 end
 
+# An Input/Output Stream
 interface IOStream
        super IStream
        super OStream
@@ -251,6 +252,7 @@ end
 
 ##############################################################"
 
+# A File Descriptor Stream.
 abstract class FDStream
        super IOS
        # File description
@@ -265,6 +267,7 @@ abstract class FDStream
        private fun native_write_char(i: Int, c: Char): Int is extern "stream_FDStream_FDStream_native_write_char_2"
 end
 
+# An Input File Descriptor Stream.
 class FDIStream
        super FDStream
        super IStream
@@ -278,6 +281,7 @@ class FDIStream
        end
 end
 
+# An Output File Descriptor Stream.
 class FDOStream
        super FDStream
        super OStream
@@ -290,6 +294,7 @@ class FDOStream
        end
 end
 
+# An Input/Output File Descriptor Stream.
 class FDIOStream
        super FDIStream
        super FDOStream
@@ -389,7 +394,9 @@ class StringOStream
                content.add(str.to_s)
        end
 
+       # Is the stream closed?
        protected var closed = false
+
        redef fun close do closed = true
 end
 
index 48cb238..26251ce 100644 (file)
@@ -757,8 +757,6 @@ abstract class FlatText
 
        redef var length: Int = 0
 
-       init do end
-
        redef fun output
        do
                var i = 0
@@ -778,7 +776,7 @@ private abstract class StringCharView
 
        type SELFTYPE: Text
 
-       private var target: SELFTYPE
+       var target: SELFTYPE
 
        redef fun is_empty do return target.is_empty
 
@@ -799,6 +797,11 @@ private abstract class BufferCharView
 
 end
 
+# A `String` holds and manipulates an arbitrary sequence of characters.
+#
+# String objects may be created using literals.
+#
+#     assert "Hello World!" isa String
 abstract class String
        super Text
 
@@ -819,6 +822,9 @@ abstract class String
        #     assert "abc" * 0 == ""
        fun *(i: Int): SELFTYPE is abstract
 
+       # Insert `s` at `pos`.
+       #
+       #     assert "helloworld".insert_at(" ", 5)     == "hello world"
        fun insert_at(s: String, pos: Int): SELFTYPE is abstract
 
        redef fun substrings: Iterator[String] is abstract
@@ -1313,6 +1319,7 @@ private class FlatStringCharView
 
 end
 
+# A mutable sequence of characters.
 abstract class Buffer
        super Text
 
@@ -1529,6 +1536,7 @@ class FlatBuffer
        # Create a new empty string.
        init do end
 
+       # Create a new string copied from `s`.
        init from(s: Text)
        do
                capacity = s.length + 1
@@ -1713,7 +1721,6 @@ private class FlatBufferCharView
 
        redef fun append(s)
        do
-               var my_items = target.items
                var s_length = s.length
                if target.capacity < s.length then enlarge(s_length + target.length)
        end
@@ -2118,8 +2125,14 @@ end
 extern class NativeString `{ char* `}
        # Creates a new NativeString with a capacity of `length`
        new(length: Int) is intern
+
+       # Get char at `index`.
        fun [](index: Int): Char is intern
+
+       # Set char `item` at index.
        fun []=(index: Int, item: Char) is intern
+
+       # Copy `self` to `dest`.
        fun copy_to(dest: NativeString, length: Int, from: Int, to: Int) is intern
 
        # Position of the first nul character.
@@ -2129,7 +2142,11 @@ extern class NativeString `{ char* `}
                while self[l] != '\0' do l += 1
                return l
        end
+
+       # Parse `self` as an Int.
        fun atoi: Int is intern
+
+       # Parse `self` as a Float.
        fun atof: Float is extern "atof"
 
        redef fun to_s
@@ -2137,6 +2154,7 @@ extern class NativeString `{ char* `}
                return to_s_with_length(cstring_length)
        end
 
+       # Returns `self` as a String of `length`.
        fun to_s_with_length(length: Int): FlatString
        do
                assert length >= 0
@@ -2144,6 +2162,7 @@ extern class NativeString `{ char* `}
                return str
        end
 
+       # Returns `self` as a new String.
        fun to_s_with_copy: FlatString
        do
                var length = cstring_length
index 9b1fb8a..9965bb1 100644 (file)
@@ -85,6 +85,7 @@ interface Pattern
                return res
        end
 
+       # Is `self` in `s`?
        protected fun is_in(s: Text): Bool do return search_index_in(s, 0) != -1
 end
 
@@ -204,7 +205,6 @@ class BM_Pattern
 
        private fun compute_gs
        do
-               var x = _motif
                var m = _length
                var suff = suffixes
                var i = 0
index 11ba1fe..07ed861 100644 (file)
@@ -31,11 +31,17 @@ end
 
 # Time since epoch
 extern class TimeT `{time_t`}
+
+       # Returns Time since epoch from now.
        new `{ return time(NULL); `}
+
+       # Returns Time since epoch from `i` (expressed in seconds).
        new from_i(i: Int) `{ return i; `}
 
+       # Update current time.
        fun update `{ time(&recv); `}
 
+       # Convert `self` to a human readable String.
        fun ctime: String import NativeString.to_s_with_copy `{
                return NativeString_to_s_with_copy( ctime(&recv) );
        `}
@@ -44,50 +50,81 @@ extern class TimeT `{time_t`}
        fun difftime(start: TimeT): Float `{ return difftime(recv, start); `}
 
        redef fun to_s do return ctime.replace("\n", "")
+
+       # Convert self to Int (expressed as seconds since epoch).
        fun to_i: Int `{ return (int)recv; `}
 end
 
 # Time structure
 extern class Tm `{struct tm *`}
+
+       # Create a new Time structure expressed in Coordinated Universal Time (UTC).
        new gmtime `{
                struct tm *tm;
                time_t t = time(NULL);
                tm = gmtime(&t);
                return tm;
        `}
+
+       # Create a new Time structure expressed in UTC from `t`.
        new gmtime_from_timet(t: TimeT) `{
                struct tm *tm;
                tm = gmtime(&t);
                return tm;
        `}
 
+       # Create a new Time structure expressed in the local timezone.
        new localtime `{
                struct tm *tm;
                time_t t = time(NULL);
                tm = localtime(&t);
                return tm;
        `}
+
+       # Create a new Time structure expressed in the local timezone from `t`.
        new localtime_from_timet(t: TimeT) `{
                struct tm *tm;
                tm = localtime(&t);
                return tm;
        `}
 
+       # Convert `self` as a TimeT.
        fun to_timet: TimeT `{ return mktime(recv); `}
 
+       # Seconds after the minute.
        fun sec: Int `{ return recv->tm_sec; `}
+
+       # Minutes after the hour.
        fun min: Int `{ return recv->tm_min; `}
+
+       # hours since midnight.
        fun hour: Int `{ return recv->tm_hour; `}
+
+       # Day of the month.
        fun mday: Int `{ return recv->tm_mday; `}
+
+       # Months since January.
        fun mon: Int `{ return recv->tm_mon; `}
+
+       # Years since 1900.
        fun year: Int `{ return recv->tm_year; `}
+
+       # Days since Sunday.
        fun wday: Int `{ return recv->tm_wday; `}
+
+       # Days since January 1st.
        fun yday: Int `{ return recv->tm_yday; `}
+
+       # Is `self` in Daylight Saving Time.
        fun is_dst: Bool `{ return recv->tm_isdst; `}
 
+       # Convert `self` to a human readable String.
        fun asctime: String import NativeString.to_s_with_copy `{
                return NativeString_to_s_with_copy( asctime(recv) );
        `}
+
+       # Convert `self` to a human readable String corresponding to `format`.
+       # TODO document allowed format.
        fun strftime(format: String): String import String.to_cstring, NativeString.to_s `{
                char* buf, *c_format;
                size_t res;
index d05663e..6626036 100644 (file)
@@ -42,7 +42,7 @@ end
 class TreeNode[K: Comparable, E]
 
        # TreeNode type
-       type SELF: TreeNode[K, E]
+       type N: TreeNode[K, E]
 
        # `key` for this node
        var key: K
@@ -51,7 +51,7 @@ class TreeNode[K: Comparable, E]
        var value: E
 
        # Direct parent of this node (null if the node is root)
-       var parent: nullable SELF = null is writable
+       var parent: nullable N = null is writable
 
        redef fun to_s do return "\{{value or else ""}\}"
 
index b689700..4c647b3 100644 (file)
@@ -370,38 +370,38 @@ class BinTreeNode[K: Comparable, E]
        private var prev: nullable BinTreeNode[K, E]
        private var next: nullable BinTreeNode[K, E]
 
-       redef type SELF: BinTreeNode[K, E]
+       redef type N: BinTreeNode[K, E]
 
        init(key: K, item: E) do
                super(key, item)
        end
 
-       private var left_node: nullable SELF = null
+       private var left_node: nullable N = null
 
        # `left` tree node child (null if node has no left child)
-       fun left: nullable SELF do return left_node
+       fun left: nullable N do return left_node
 
        # set `left` child for this node (or null if left no child)
        # ENSURE: node.key < key (only if node != null)
-       fun left=(node: nullable SELF) do
+       fun left=(node: nullable N) do
                #assert node != null implies node.key < key
                left_node = node
        end
 
-       private var right_node: nullable SELF = null
+       private var right_node: nullable N = null
 
        # `right` tree node child (null if node has no right child)
-       fun right: nullable SELF do return right_node
+       fun right: nullable N do return right_node
 
        # set `right` child for this node (or null if right no child)
        # ENSURE: node.key < key (only if node != null)
-       fun right=(node: nullable SELF) do
+       fun right=(node: nullable N) do
                #assert node != null implies node.key > key
                right_node = node
        end
 
        # `parent` of the `parent` of this node (null if root)
-       fun grandparent: nullable SELF do
+       fun grandparent: nullable N do
                if parent == null then
                        return null
                else
@@ -411,7 +411,7 @@ class BinTreeNode[K: Comparable, E]
 
        # Other child of the `grandparent`
        # `left` or `right` depends on the position of the current node against its parent
-       fun uncle: nullable SELF do
+       fun uncle: nullable N do
                var g = grandparent
                if g == null then
                        return null
@@ -426,7 +426,7 @@ class BinTreeNode[K: Comparable, E]
 
        # Other child of the parent
        # `left` or `right` depends on the position of the current node against its parent
-       fun sibling: nullable SELF do
+       fun sibling: nullable N do
                if parent == null then
                        return null
                else if self == parent.left then
index ce17feb..e1fe413 100644 (file)
@@ -130,7 +130,7 @@ end
 class RBTreeNode[K: Comparable, E]
        super BinTreeNode[K, E]
 
-       redef type SELF: RBTreeNode[K, E]
+       redef type N: RBTreeNode[K, E]
 
        # Is the node red?
        private var is_red = true
index cc24d6e..ad34b9a 100644 (file)
@@ -44,6 +44,9 @@ class AndroidProject
        # Custom lines to add to the AndroidManifest.xml in the <application> node
        var manifest_application_lines = new Array[String]
 
+       # Custom lines to add to AndroidManifest.xml as attributes inside the <activity> node
+       var manifest_activity_attributes = new Array[String]
+
        # Minimum API level required for the application to run
        var min_api: nullable Int = null
 
@@ -107,6 +110,9 @@ redef class ModelBuilder
                annots = collect_annotations_on_modules("android_manifest_application", mmodule)
                for an in annots do project.manifest_application_lines.add an.arg_as_string(self) or else ""
 
+               annots = collect_annotations_on_modules("android_manifest_activity", mmodule)
+               for an in annots do project.manifest_activity_attributes.add an.arg_as_string(self) or else ""
+
                # Get the date and time (down to the minute) as string
                var local_time = new Tm.localtime
                var local_time_s = local_time.strftime("%y%m%d%H%M")
index 55468fd..1cf6ba8 100644 (file)
@@ -124,10 +124,12 @@ class AndroidToolchain
 
                # Also copy over the java files
                dir = "{android_project_root}/src/"
-               var extra_java_files = compiler.mainmodule.extra_java_files
-               if extra_java_files != null then for file in extra_java_files do
-                       var path = file.filename
-                       path.file_copy_to("{dir}/{path.basename("")}")
+               for mmodule in compiler.mainmodule.in_importation.greaters do
+                       var extra_java_files = mmodule.extra_java_files
+                       if extra_java_files != null then for file in extra_java_files do
+                               var path = file.filename
+                               path.file_copy_to(dir/path.basename(""))
+                       end
                end
 
                ## Generate delagating makefile
@@ -178,13 +180,11 @@ $(call import-module,android/native_app_glue)
              This will take care of integrating with our NDK code. -->
         <activity android:name="android.app.NativeActivity"
                 android:label="@string/app_name"
-                android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
-                android:configChanges="orientation|keyboardHidden"
-                android:screenOrientation="portrait"
+                {{{project.manifest_activity_attributes.join("\n")}}}
                 {{{icon_declaration}}}>
-            <!-- Tell NativeActivity the name of or .so -->
-            <meta-data android:name=\"{{{app_package}}}\"
-                    android:value=\"{{{app_name}}}\" />
+            <!-- Tell NativeActivity the name of our .so -->
+            <meta-data android:name=\"android.app.lib_name\"
+                    android:value=\"main\" />
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
index 4141f75..0a0e60e 100644 (file)
@@ -16,7 +16,7 @@
 module doc_model
 
 import model_utils
-import markdown
+import docdown
 import doc_templates
 import ordered_tree
 import model_ext
similarity index 99%
rename from src/markdown.nit
rename to src/docdown.nit
index e254480..7df46fe 100644 (file)
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # Transform Nit verbatim documentation into HTML
-module markdown
+module docdown
 
 private import parser
 import html
index 2879ac9..476608c 100644 (file)
@@ -901,6 +901,8 @@ redef class AMethPropdef
                                return v.bool_instance(args[0].to_f.is_nan)
                        else if pname == "is_inf_extern" then
                                return v.bool_instance(args[0].to_f.is_inf != 0)
+                       else if pname == "round" then
+                               return v.float_instance(args[0].to_f.round)
                        end
                else if cname == "NativeString" then
                        if pname == "new" then
index cb56d38..81b3245 100644 (file)
@@ -54,6 +54,7 @@ redef class ModelBuilder
                        build_properties(mclassdef2nclassdef[superclassdef])
                end
 
+               mclassdef.build_self_type(self, nclassdef)
                for nclassdef2 in nclassdef.all_defs do
                        for npropdef in nclassdef2.n_propdefs do
                                npropdef.build_property(self, mclassdef)
@@ -310,6 +311,50 @@ redef class MClassDef
        # What is the `APropdef` associated to a `MProperty`?
        # Used to check multiple definition of a property.
        var mprop2npropdef: Map[MProperty, APropdef] = new HashMap[MProperty, APropdef]
+
+       # Build the virtual type `SELF` only for introduction `MClassDef`
+       fun build_self_type(modelbuilder: ModelBuilder, nclassdef: AClassdef)
+       do
+               if not is_intro then return
+
+               var name = "SELF"
+               var mprop = modelbuilder.try_get_mproperty_by_name(nclassdef, self, name)
+
+               # If SELF type is declared nowherer?
+               if mprop == null then return
+
+               # SELF is not a virtual type? it is weird but we ignore it
+               if not mprop isa MVirtualTypeProp then return
+
+               # Is this the intro of SELF in the library?
+               var intro = mprop.intro
+               var intro_mclassdef = intro.mclassdef
+               if intro_mclassdef == self then
+                       var nintro = modelbuilder.mpropdef2npropdef[intro]
+
+                       # SELF must be declared in Object, otherwise this will create conflicts
+                       if intro_mclassdef.mclass.name != "Object" then
+                               modelbuilder.error(nintro, "Error: the virtual type SELF must be declared in Object.")
+                       end
+
+                       # SELF must be public
+                       if mprop.visibility != public_visibility then
+                               modelbuilder.error(nintro, "Error: the virtual type SELF must be public.")
+                       end
+
+                       # SELF must not be fixed
+                       if intro.is_fixed then
+                               modelbuilder.error(nintro, "Error: the virtual type SELF cannot be fixed.")
+                       end
+
+                       return
+               end
+
+               # This class introduction inherits a SELF
+               # We insert an artificial property to update it
+               var mpropdef = new MVirtualTypeDef(self, mprop, self.location)
+               mpropdef.bound = mclass.mclass_type
+       end
 end
 
 redef class APropdef
index c546c2e..71a8669 100644 (file)
@@ -17,7 +17,7 @@ module test_docdown
 
 import modelize
 import highlight
-import markdown
+import docdown
 
 redef class ModelBuilder
        fun test_markdown(page: HTMLTag, mmodule: MModule)
index 7bb39ca..e612902 100644 (file)
@@ -16,7 +16,7 @@
 module testing_doc
 
 import testing_base
-intrude import markdown
+intrude import docdown
 
 # Extractor, Executor and Reporter for the tests in a module
 class NitUnitExecutor
index 24c0604..cdd5559 100644 (file)
@@ -1,5 +1,5 @@
 
-PROGS=*.nit ../examples/*.nit ../examples/leapfrog/leapfrog.nit ../examples/shoot/shoot_logic.nit ../contrib/pep8analysis/src/pep8analysis ../lib/*.nit ../src/nitdoc.nit ../src/test_parser.nit ../src/nit.nit ../src/nitmetrics.nit ../src/nitg.nit
+PROGS=*.nit ../examples/*.nit ../examples/leapfrog/leapfrog.nit ../examples/shoot/shoot_logic.nit ../contrib/pep8analysis/src/pep8analysis ../contrib/nitiwiki/src/nitiwiki ../lib/*.nit ../src/nitdoc.nit ../src/test_parser.nit ../src/nit.nit ../src/nitmetrics.nit ../src/nitg.nit
 
 all: niti nitg-g nitg-s
 
diff --git a/tests/base_self_type.nit b/tests/base_self_type.nit
new file mode 100644 (file)
index 0000000..7c5d204
--- /dev/null
@@ -0,0 +1,58 @@
+# 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.
+
+import kernel
+
+class X
+       fun foo: SELF do return self
+       fun bar(o: SELF) do o.output_class_name
+end
+
+class Y
+       super X
+
+#alt1# redef fun foo do return new X
+#alt2# redef fun foo do return new Y
+end
+
+class A[E]
+       fun foo: Object do return new G[SELF]
+end
+
+class B[F]
+       super A[F]
+end
+
+class G[E:A[nullable Object]]
+end
+
+var x = new X
+x.output_class_name
+x.foo.output_class_name
+x.bar x
+
+var y = new Y
+y.output_class_name
+y.foo.output_class_name
+x.bar y
+y.bar y
+#alt3# y.bar x
+
+var a = new A[Int]
+a.output_class_name
+a.foo.output_class_name
+
+var b = new B[Bool]
+b.output_class_name
+b.foo.output_class_name
index 778d0d3..6dafd08 100755 (executable)
@@ -13,5 +13,7 @@ printf "%s\n" "$@" \
        ../examples/mpi/src/*.nit \
        ../lib/*/examples/*.nit \
        ../contrib/friendz/src/solver_cmd.nit \
+       ../contrib/neo_doxygen/src/tests/neo_doxygen_*.nit \
        ../contrib/pep8analysis/src/pep8analysis.nit \
+       ../contrib/nitiwiki/src/nitiwiki.nit \
        *.nit
diff --git a/tests/neo_doxygen_dump.args b/tests/neo_doxygen_dump.args
new file mode 100644 (file)
index 0000000..3a355ab
--- /dev/null
@@ -0,0 +1,5 @@
+'empty project with default settings' ../contrib/neo_doxygen/tests/empty-project/xml
+--src-lang any -- empty-project ../contrib/neo_doxygen/tests/empty-project/xml
+--src-lang java empty-project ../contrib/neo_doxygen/tests/empty-project/xml
+--src-lang any -- foo ../contrib/neo_doxygen/tests/java-project/xml
+--src-lang java -- foo ../contrib/neo_doxygen/tests/java-project/xml
index 7175bb7..5668f12 100644 (file)
@@ -1,2 +1,6 @@
 nitg
 nitdoc
+neo_doxygen_dump
+neo_doxygen_file_compound
+neo_doxygen_graph_empty_project
+neo_doxygen_member_resolve_introducer
diff --git a/tests/nitiwiki.args b/tests/nitiwiki.args
new file mode 100644 (file)
index 0000000..ae082af
--- /dev/null
@@ -0,0 +1,2 @@
+nitiwiki --config ../contrib/nitiwiki/tests/wiki1/config2.ini --clean --status
+nitiwiki --config ../contrib/nitiwiki/tests/wiki1/config2.ini --clean --render -v
diff --git a/tests/sav/base_self_type.res b/tests/sav/base_self_type.res
new file mode 100644 (file)
index 0000000..4c75853
--- /dev/null
@@ -0,0 +1,11 @@
+X
+X
+X
+Y
+Y
+Y
+Y
+A[Int]
+G[A[Int]]
+B[Bool]
+G[B[Bool]]
diff --git a/tests/sav/base_self_type_alt1.res b/tests/sav/base_self_type_alt1.res
new file mode 100644 (file)
index 0000000..467d315
--- /dev/null
@@ -0,0 +1 @@
+alt/base_self_type_alt1.nit:25,25--29: Type error: expected SELF, got X
diff --git a/tests/sav/base_self_type_alt2.res b/tests/sav/base_self_type_alt2.res
new file mode 100644 (file)
index 0000000..4c75853
--- /dev/null
@@ -0,0 +1,11 @@
+X
+X
+X
+Y
+Y
+Y
+Y
+A[Int]
+G[A[Int]]
+B[Bool]
+G[B[Bool]]
diff --git a/tests/sav/base_self_type_alt3.res b/tests/sav/base_self_type_alt3.res
new file mode 100644 (file)
index 0000000..78888be
--- /dev/null
@@ -0,0 +1 @@
+alt/base_self_type_alt3.nit:50,7: Type error: expected Y, got X
index 30a32a5..695948f 100644 (file)
@@ -1 +1 @@
-../lib/standard/kernel.nit:79,1--95,3: Fatal error: kernel#Sys does not specialize module_0#Object. Possible duplication of the root class `Object`?
+../lib/standard/kernel.nit:101,1--117,3: Fatal error: kernel#Sys does not specialize module_0#Object. Possible duplication of the root class `Object`?
diff --git a/tests/sav/neo_doxygen_dump.res b/tests/sav/neo_doxygen_dump.res
new file mode 100644 (file)
index 0000000..e043e01
--- /dev/null
@@ -0,0 +1,31 @@
+\e[1mNAME\e[m
+  %PROGRAM_NAME% — Doxygen XML to Neo4j.
+
+\e[1mSYNOPSIS\e[m
+  %PROGRAM_NAME% [--dest <url>] [--src-lang <lang>]
+    [--] <project_name> <doxml_dir>
+  %PROGRAM_NAME% [-h|--help]
+
+\e[1mDESCRIPTION\e[m
+  Convert a Doxygen XML output into a model in Neo4j that is readable by the
+  `nx` tool.
+
+\e[1mARGUMENTS\e[m
+  <project_name>  The internal name of the project. Must the same name as the
+                  one specified to the `nx` tool. Must not begin by an upper
+                  case letter.
+
+  <doxml_dir>     The directory where the XML documents generated by Doxygen are
+                  located.
+
+\e[1mOPTIONS\e[m
+
+  --dest       The URL of the destination graph. `http://localhost:7474` by
+               default.
+
+  -h, --help   Show the help (this page).
+
+  --src-lang   The programming language to assume when processing chunk in the
+               declarations left as-is by Doxygen. Use `any` (the default) to
+               disable any language-specific processing. <any, java>
+
diff --git a/tests/sav/neo_doxygen_dump_args1.res b/tests/sav/neo_doxygen_dump_args1.res
new file mode 100644 (file)
index 0000000..743b9a2
--- /dev/null
@@ -0,0 +1,51 @@
+Reading ../contrib/neo_doxygen/tests/empty-project/xml... Done.
+0 file read.
+Linking nodes...\e[s \e[u\e[J Done.
+Saving 2 nodes...
+---===DONE===---
+Saving 2 edges...
+Edge
+=type=4:ROOT
+=properties=JsonObject(0):
+{}
+----
+=from=Node
+=labels=Array(3):
+35:empty project with default settings
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"empty project with default settings"}
+----
+=to=Entity#0:
+=labels=Array(3):
+35:empty project with default settings
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"empty project with default settings"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+35:empty project with default settings
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"empty project with default settings"}
+----
+=to=Node
+=labels=Array(3):
+35:empty project with default settings
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"empty project with default settings"}
+
+
+---===DONE===---
diff --git a/tests/sav/neo_doxygen_dump_args2.res b/tests/sav/neo_doxygen_dump_args2.res
new file mode 100644 (file)
index 0000000..724e242
--- /dev/null
@@ -0,0 +1,51 @@
+Reading ../contrib/neo_doxygen/tests/empty-project/xml... Done.
+0 file read.
+Linking nodes...\e[s \e[u\e[J Done.
+Saving 2 nodes...
+---===DONE===---
+Saving 2 edges...
+Edge
+=type=4:ROOT
+=properties=JsonObject(0):
+{}
+----
+=from=Node
+=labels=Array(3):
+13:empty-project
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"empty-project"}
+----
+=to=Entity#0:
+=labels=Array(3):
+13:empty-project
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"empty-project"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+13:empty-project
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"empty-project"}
+----
+=to=Node
+=labels=Array(3):
+13:empty-project
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"empty-project"}
+
+
+---===DONE===---
diff --git a/tests/sav/neo_doxygen_dump_args3.res b/tests/sav/neo_doxygen_dump_args3.res
new file mode 100644 (file)
index 0000000..724e242
--- /dev/null
@@ -0,0 +1,51 @@
+Reading ../contrib/neo_doxygen/tests/empty-project/xml... Done.
+0 file read.
+Linking nodes...\e[s \e[u\e[J Done.
+Saving 2 nodes...
+---===DONE===---
+Saving 2 edges...
+Edge
+=type=4:ROOT
+=properties=JsonObject(0):
+{}
+----
+=from=Node
+=labels=Array(3):
+13:empty-project
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"empty-project"}
+----
+=to=Entity#0:
+=labels=Array(3):
+13:empty-project
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"empty-project"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+13:empty-project
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"empty-project"}
+----
+=to=Node
+=labels=Array(3):
+13:empty-project
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"empty-project"}
+
+
+---===DONE===---
diff --git a/tests/sav/neo_doxygen_dump_args4.res b/tests/sav/neo_doxygen_dump_args4.res
new file mode 100644 (file)
index 0000000..6ceb76f
--- /dev/null
@@ -0,0 +1,1951 @@
+Reading ../contrib/neo_doxygen/tests/java-project/xml... Done.
+15 files read.
+Linking nodes...\e[s \e[u\e[J Done.
+Saving 58 nodes...
+---===DONE===---
+Saving 85 edges...
+Edge
+=type=4:ROOT
+=properties=JsonObject(0):
+{}
+----
+=from=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:1,1--1,1","full_name":"org::example::foo::A","name":"A"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:1,1--1,1","full_name":"org::example::foo::A","name":"A"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_a
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"abstract class","visibility":"public","full_name":"org::example::foo::A","name":"A","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1"}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:1,1--1,1","full_name":"org::example::foo::A","name":"A"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:1,1--1,1","full_name":"org::example::foo::B","name":"B"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:1,1--1,1","full_name":"org::example::foo::B","name":"B"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_b
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"class","visibility":"public","full_name":"org::example::foo::B","name":"B","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1"}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:1,1--1,1","full_name":"org::example::foo::B","name":"B"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:1,1--1,1","full_name":"org::example::foo::C","name":"C"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:1,1--1,1","full_name":"org::example::foo::C","name":"C"}
+----
+=to=Entity#36:interfaceorg_1_1example_1_1foo_1_1_c
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"interface","visibility":"public","full_name":"org::example::foo::C","name":"C","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","mdoc":["An interface"]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:1,1--1,1","full_name":"org::example::foo::C","name":"C"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:1,1--1,1","full_name":"org::example::foo::EmptyClass","name":"EmptyClass"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:1,1--1,1","full_name":"org::example::foo::EmptyClass","name":"EmptyClass"}
+----
+=to=Entity#42:classorg_1_1example_1_1foo_1_1_empty_class
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"class","visibility":"package","full_name":"org::example::foo::EmptyClass","name":"EmptyClass","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","mdoc":["This class is empty and is only visible in this package."]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:1,1--1,1","full_name":"org::example::foo::EmptyClass","name":"EmptyClass"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","is_intro":true,"name":"EmptyClass","full_name":"org::example::foo::EmptyClass","mdoc":["This class is empty and is only visible in this package."]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["int"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["EmptyClass"]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_a_1add415ae4129969055d678c7e7e048852
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:22,1--1,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"bar","mdoc":["Does something..."],"is_intro":true,"full_name":"org::example::foo::A::bar"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::A::bar"}
+
+
+Edge
+=type=9:SIGNATURE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_a_1add415ae4129969055d678c7e7e048852
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:22,1--1,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"bar","mdoc":["Does something..."],"is_intro":true,"full_name":"org::example::foo::A::bar"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+
+
+Edge
+=type=9:PARAMETER
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+
+
+Edge
+=type=9:PARAMETER
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+
+
+Edge
+=type=10:RETURNTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["abstract boolean"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["int"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["EmptyClass"]}
+
+
+Edge
+=type=9:CLASSTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#32:classorg_1_1example_1_1foo_1_1_a
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"abstract class","visibility":"public","full_name":"org::example::foo::A","name":"A","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"A","full_name":"org::example::foo::A"}
+
+
+Edge
+=type=5:CLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"A","full_name":"org::example::foo::A"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_a
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"abstract class","visibility":"public","full_name":"org::example::foo::A","name":"A","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1"}
+
+
+Edge
+=type=9:BOUNDTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"A","full_name":"org::example::foo::A"}
+
+
+Edge
+=type=6:MCLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_a
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"abstract class","visibility":"public","full_name":"org::example::foo::A","name":"A","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::A::bar"}
+
+
+Edge
+=type=14:INTRO_CLASSDEF
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::A::bar"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+----
+=to=Entity#67:classorg_1_1example_1_1foo_1_1_a_1add415ae4129969055d678c7e7e048852
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:22,1--1,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"bar","mdoc":["Does something..."],"is_intro":true,"full_name":"org::example::foo::A::bar"}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1ac6b627949b10b9357eefc0cafcae1d87
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:19,1---1,1","visibility":"protected","name":"qux","is_intro":true,"full_name":"org::example::foo::B::qux"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"protected","name":"qux","full_name":"org::example::foo::B::qux"}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1ac6b627949b10b9357eefc0cafcae1d87
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:19,1---1,1","visibility":"protected","name":"qux","is_intro":true,"full_name":"org::example::foo::B::qux"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["String"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["int"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["EmptyClass"]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a11e157943665cc9e3a9be1502ebeb3b5
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(8):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:21,1--23,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"bar","is_intro":true,"full_name":"org::example::foo::B::bar"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::B::bar"}
+
+
+Edge
+=type=9:SIGNATURE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a11e157943665cc9e3a9be1502ebeb3b5
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(8):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:21,1--23,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"bar","is_intro":true,"full_name":"org::example::foo::B::bar"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+
+
+Edge
+=type=9:PARAMETER
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+
+
+Edge
+=type=9:PARAMETER
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+
+
+Edge
+=type=10:RETURNTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["boolean"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["int"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["EmptyClass"]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a733f4e076f29c7d0c41ed258199ea1d9
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:28,1--28,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["Some overriden documentation."],"is_intro":false,"full_name":"org::example::foo::B::baz"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"baz","full_name":"org::example::foo::C::baz"}
+
+
+Edge
+=type=9:SIGNATURE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a733f4e076f29c7d0c41ed258199ea1d9
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:28,1--28,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["Some overriden documentation."],"is_intro":false,"full_name":"org::example::foo::B::baz"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(0):
+{}
+
+
+Edge
+=type=10:RETURNTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(0):
+{}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["void"]}
+
+
+Edge
+=type=9:CLASSTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#32:classorg_1_1example_1_1foo_1_1_b
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"class","visibility":"public","full_name":"org::example::foo::B","name":"B","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"B","full_name":"org::example::foo::B"}
+
+
+Edge
+=type=5:CLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_b
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"class","visibility":"public","full_name":"org::example::foo::B","name":"B","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1"}
+
+
+Edge
+=type=9:BOUNDTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"B","full_name":"org::example::foo::B"}
+
+
+Edge
+=type=6:MCLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_b
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"class","visibility":"public","full_name":"org::example::foo::B","name":"B","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1"}
+
+
+Edge
+=type=8:INHERITS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"A","full_name":"org::example::foo::A"}
+
+
+Edge
+=type=8:INHERITS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"C","full_name":"org::example::foo::C"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"protected","name":"qux","full_name":"org::example::foo::B::qux"}
+
+
+Edge
+=type=14:INTRO_CLASSDEF
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"protected","name":"qux","full_name":"org::example::foo::B::qux"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#67:classorg_1_1example_1_1foo_1_1_b_1ac6b627949b10b9357eefc0cafcae1d87
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:19,1---1,1","visibility":"protected","name":"qux","is_intro":true,"full_name":"org::example::foo::B::qux"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::B::bar"}
+
+
+Edge
+=type=14:INTRO_CLASSDEF
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::B::bar"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a11e157943665cc9e3a9be1502ebeb3b5
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(8):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:21,1--23,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"bar","is_intro":true,"full_name":"org::example::foo::B::bar"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a733f4e076f29c7d0c41ed258199ea1d9
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:28,1--28,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["Some overriden documentation."],"is_intro":false,"full_name":"org::example::foo::B::baz"}
+
+
+Edge
+=type=9:CLASSTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#42:classorg_1_1example_1_1foo_1_1_empty_class
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"class","visibility":"package","full_name":"org::example::foo::EmptyClass","name":"EmptyClass","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","mdoc":["This class is empty and is only visible in this package."]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"EmptyClass","full_name":"org::example::foo::EmptyClass"}
+
+
+Edge
+=type=5:CLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"EmptyClass","full_name":"org::example::foo::EmptyClass"}
+----
+=to=Entity#42:classorg_1_1example_1_1foo_1_1_empty_class
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"class","visibility":"package","full_name":"org::example::foo::EmptyClass","name":"EmptyClass","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","mdoc":["This class is empty and is only visible in this package."]}
+
+
+Edge
+=type=9:BOUNDTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","is_intro":true,"name":"EmptyClass","full_name":"org::example::foo::EmptyClass","mdoc":["This class is empty and is only visible in this package."]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"EmptyClass","full_name":"org::example::foo::EmptyClass"}
+
+
+Edge
+=type=6:MCLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","is_intro":true,"name":"EmptyClass","full_name":"org::example::foo::EmptyClass","mdoc":["This class is empty and is only visible in this package."]}
+----
+=to=Entity#42:classorg_1_1example_1_1foo_1_1_empty_class
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"class","visibility":"package","full_name":"org::example::foo::EmptyClass","name":"EmptyClass","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","mdoc":["This class is empty and is only visible in this package."]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a4e97061eb40b045e820de05b33c43d21
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(6):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.\u000e2\u00080\u0009c"],"is_intro":true,"full_name":"org::example::foo::C::THE_ANSWER"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"public","name":"THE_ANSWER","full_name":"org::example::foo::C::THE_ANSWER"}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a4e97061eb40b045e820de05b33c43d21
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(6):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.\u000e2\u00080\u0009c"],"is_intro":true,"full_name":"org::example::foo::C::THE_ANSWER"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["final long"]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a28ac7ce349ebb3e4a7747a8dd951582b
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:30,1--1,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["A function with implicit modifiers."],"is_intro":true,"full_name":"org::example::foo::C::baz"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"baz","full_name":"org::example::foo::C::baz"}
+
+
+Edge
+=type=9:SIGNATURE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a28ac7ce349ebb3e4a7747a8dd951582b
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:30,1--1,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["A function with implicit modifiers."],"is_intro":true,"full_name":"org::example::foo::C::baz"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(0):
+{}
+
+
+Edge
+=type=10:RETURNTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(0):
+{}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["void"]}
+
+
+Edge
+=type=9:CLASSTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#36:interfaceorg_1_1example_1_1foo_1_1_c
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"interface","visibility":"public","full_name":"org::example::foo::C","name":"C","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","mdoc":["An interface"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"C","full_name":"org::example::foo::C"}
+
+
+Edge
+=type=5:CLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"C","full_name":"org::example::foo::C"}
+----
+=to=Entity#36:interfaceorg_1_1example_1_1foo_1_1_c
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"interface","visibility":"public","full_name":"org::example::foo::C","name":"C","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","mdoc":["An interface"]}
+
+
+Edge
+=type=9:BOUNDTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"C","full_name":"org::example::foo::C"}
+
+
+Edge
+=type=6:MCLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#36:interfaceorg_1_1example_1_1foo_1_1_c
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"interface","visibility":"public","full_name":"org::example::foo::C","name":"C","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","mdoc":["An interface"]}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"public","name":"THE_ANSWER","full_name":"org::example::foo::C::THE_ANSWER"}
+
+
+Edge
+=type=14:INTRO_CLASSDEF
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"public","name":"THE_ANSWER","full_name":"org::example::foo::C::THE_ANSWER"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a4e97061eb40b045e820de05b33c43d21
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(6):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.\u000e2\u00080\u0009c"],"is_intro":true,"full_name":"org::example::foo::C::THE_ANSWER"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"baz","full_name":"org::example::foo::C::baz"}
+
+
+Edge
+=type=14:INTRO_CLASSDEF
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"baz","full_name":"org::example::foo::C::baz"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a28ac7ce349ebb3e4a7747a8dd951582b
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:30,1--1,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["A function with implicit modifiers."],"is_intro":true,"full_name":"org::example::foo::C::baz"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#12:namespaceorg
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org","name":"org","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+
+Edge
+=type=6:PARENT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#12:namespaceorg
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org","name":"org","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+
+
+Edge
+=type=5:NESTS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+----
+=to=Entity#12:namespaceorg
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org","name":"org","location":"\/dev\/null:1,1--1,1"}
+
+
+Edge
+=type=6:PARENT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#23:namespaceorg_1_1example
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example","name":"example","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Entity#12:namespaceorg
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org","name":"org","location":"\/dev\/null:1,1--1,1"}
+
+
+Edge
+=type=5:NESTS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#12:namespaceorg
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org","name":"org","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Entity#23:namespaceorg_1_1example
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example","name":"example","location":"\/dev\/null:1,1--1,1"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#23:namespaceorg_1_1example
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example","name":"example","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+
+Edge
+=type=6:PARENT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Entity#23:namespaceorg_1_1example
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example","name":"example","location":"\/dev\/null:1,1--1,1"}
+
+
+Edge
+=type=5:NESTS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#23:namespaceorg_1_1example
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example","name":"example","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+
+---===DONE===---
diff --git a/tests/sav/neo_doxygen_dump_args5.res b/tests/sav/neo_doxygen_dump_args5.res
new file mode 100644 (file)
index 0000000..a41654d
--- /dev/null
@@ -0,0 +1,1951 @@
+Reading ../contrib/neo_doxygen/tests/java-project/xml... Done.
+15 files read.
+Linking nodes...\e[s \e[u\e[J Done.
+Saving 58 nodes...
+---===DONE===---
+Saving 85 edges...
+Edge
+=type=4:ROOT
+=properties=JsonObject(0):
+{}
+----
+=from=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:1,1--1,1","full_name":"org::example::foo::A","name":"A"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:1,1--1,1","full_name":"org::example::foo::A","name":"A"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_a
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"abstract class","visibility":"public","full_name":"org::example::foo::A","name":"A","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1"}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:1,1--1,1","full_name":"org::example::foo::A","name":"A"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:1,1--1,1","full_name":"org::example::foo::B","name":"B"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:1,1--1,1","full_name":"org::example::foo::B","name":"B"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_b
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"class","visibility":"public","full_name":"org::example::foo::B","name":"B","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1"}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:1,1--1,1","full_name":"org::example::foo::B","name":"B"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:1,1--1,1","full_name":"org::example::foo::C","name":"C"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:1,1--1,1","full_name":"org::example::foo::C","name":"C"}
+----
+=to=Entity#36:interfaceorg_1_1example_1_1foo_1_1_c
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"interface","visibility":"public","full_name":"org::example::foo::C","name":"C","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","mdoc":["An interface"]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:1,1--1,1","full_name":"org::example::foo::C","name":"C"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:1,1--1,1","full_name":"org::example::foo::EmptyClass","name":"EmptyClass"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:1,1--1,1","full_name":"org::example::foo::EmptyClass","name":"EmptyClass"}
+----
+=to=Entity#42:classorg_1_1example_1_1foo_1_1_empty_class
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"class","visibility":"package","full_name":"org::example::foo::EmptyClass","name":"EmptyClass","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","mdoc":["This class is empty and is only visible in this package."]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:1,1--1,1","full_name":"org::example::foo::EmptyClass","name":"EmptyClass"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","is_intro":true,"name":"EmptyClass","full_name":"org::example::foo::EmptyClass","mdoc":["This class is empty and is only visible in this package."]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["int"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["EmptyClass"]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_a_1add415ae4129969055d678c7e7e048852
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:22,1--1,1","is_intern":false,"is_extern":false,"is_abstract":true,"visibility":"public","name":"bar","mdoc":["Does something..."],"is_intro":true,"full_name":"org::example::foo::A::bar"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::A::bar"}
+
+
+Edge
+=type=9:SIGNATURE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_a_1add415ae4129969055d678c7e7e048852
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:22,1--1,1","is_intern":false,"is_extern":false,"is_abstract":true,"visibility":"public","name":"bar","mdoc":["Does something..."],"is_intro":true,"full_name":"org::example::foo::A::bar"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+
+
+Edge
+=type=9:PARAMETER
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+
+
+Edge
+=type=9:PARAMETER
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+
+
+Edge
+=type=10:RETURNTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["boolean"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["int"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["EmptyClass"]}
+
+
+Edge
+=type=9:CLASSTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#32:classorg_1_1example_1_1foo_1_1_a
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"abstract class","visibility":"public","full_name":"org::example::foo::A","name":"A","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"A","full_name":"org::example::foo::A"}
+
+
+Edge
+=type=5:CLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"A","full_name":"org::example::foo::A"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_a
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"abstract class","visibility":"public","full_name":"org::example::foo::A","name":"A","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1"}
+
+
+Edge
+=type=9:BOUNDTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"A","full_name":"org::example::foo::A"}
+
+
+Edge
+=type=6:MCLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_a
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"abstract class","visibility":"public","full_name":"org::example::foo::A","name":"A","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::A::bar"}
+
+
+Edge
+=type=14:INTRO_CLASSDEF
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::A::bar"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:18,1--23,1","is_intro":true,"name":"A","full_name":"org::example::foo::A"}
+----
+=to=Entity#67:classorg_1_1example_1_1foo_1_1_a_1add415ae4129969055d678c7e7e048852
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:22,1--1,1","is_intern":false,"is_extern":false,"is_abstract":true,"visibility":"public","name":"bar","mdoc":["Does something..."],"is_intro":true,"full_name":"org::example::foo::A::bar"}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1ac6b627949b10b9357eefc0cafcae1d87
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:19,1---1,1","visibility":"protected","name":"qux","is_intro":true,"full_name":"org::example::foo::B::qux"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"protected","name":"qux","full_name":"org::example::foo::B::qux"}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1ac6b627949b10b9357eefc0cafcae1d87
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:19,1---1,1","visibility":"protected","name":"qux","is_intro":true,"full_name":"org::example::foo::B::qux"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["String"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["int"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["EmptyClass"]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a11e157943665cc9e3a9be1502ebeb3b5
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(8):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:21,1--23,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"bar","is_intro":true,"full_name":"org::example::foo::B::bar"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::B::bar"}
+
+
+Edge
+=type=9:SIGNATURE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a11e157943665cc9e3a9be1502ebeb3b5
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(8):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:21,1--23,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"bar","is_intro":true,"full_name":"org::example::foo::B::bar"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+
+
+Edge
+=type=9:PARAMETER
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+
+
+Edge
+=type=9:PARAMETER
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+
+
+Edge
+=type=10:RETURNTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(1):
+{"parameter_names":["x","y"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["boolean"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":0,"name":"x"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["int"]}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+10:MParameter
+=properties=JsonObject(3):
+{"is_vararg":false,"rank":1,"name":"y"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["EmptyClass"]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a733f4e076f29c7d0c41ed258199ea1d9
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:28,1--28,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["Some overriden documentation."],"is_intro":false,"full_name":"org::example::foo::B::baz"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"baz","full_name":"org::example::foo::C::baz"}
+
+
+Edge
+=type=9:SIGNATURE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a733f4e076f29c7d0c41ed258199ea1d9
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:28,1--28,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["Some overriden documentation."],"is_intro":false,"full_name":"org::example::foo::B::baz"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(0):
+{}
+
+
+Edge
+=type=10:RETURNTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(0):
+{}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["void"]}
+
+
+Edge
+=type=9:CLASSTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#32:classorg_1_1example_1_1foo_1_1_b
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"class","visibility":"public","full_name":"org::example::foo::B","name":"B","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"B","full_name":"org::example::foo::B"}
+
+
+Edge
+=type=5:CLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_b
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"class","visibility":"public","full_name":"org::example::foo::B","name":"B","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1"}
+
+
+Edge
+=type=9:BOUNDTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"B","full_name":"org::example::foo::B"}
+
+
+Edge
+=type=6:MCLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#32:classorg_1_1example_1_1foo_1_1_b
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(5):
+{"kind":"class","visibility":"public","full_name":"org::example::foo::B","name":"B","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1"}
+
+
+Edge
+=type=8:INHERITS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"A","full_name":"org::example::foo::A"}
+
+
+Edge
+=type=8:INHERITS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"C","full_name":"org::example::foo::C"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"protected","name":"qux","full_name":"org::example::foo::B::qux"}
+
+
+Edge
+=type=14:INTRO_CLASSDEF
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"protected","name":"qux","full_name":"org::example::foo::B::qux"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#67:classorg_1_1example_1_1foo_1_1_b_1ac6b627949b10b9357eefc0cafcae1d87
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:19,1---1,1","visibility":"protected","name":"qux","is_intro":true,"full_name":"org::example::foo::B::qux"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::B::bar"}
+
+
+Edge
+=type=14:INTRO_CLASSDEF
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"bar","full_name":"org::example::foo::B::bar"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a11e157943665cc9e3a9be1502ebeb3b5
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(8):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:21,1--23,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"bar","is_intro":true,"full_name":"org::example::foo::B::bar"}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:18,1--29,1","is_intro":true,"name":"B","full_name":"org::example::foo::B"}
+----
+=to=Entity#67:classorg_1_1example_1_1foo_1_1_b_1a733f4e076f29c7d0c41ed258199ea1d9
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/B.java:28,1--28,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["Some overriden documentation."],"is_intro":false,"full_name":"org::example::foo::B::baz"}
+
+
+Edge
+=type=9:CLASSTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#42:classorg_1_1example_1_1foo_1_1_empty_class
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"class","visibility":"package","full_name":"org::example::foo::EmptyClass","name":"EmptyClass","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","mdoc":["This class is empty and is only visible in this package."]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"EmptyClass","full_name":"org::example::foo::EmptyClass"}
+
+
+Edge
+=type=5:CLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"EmptyClass","full_name":"org::example::foo::EmptyClass"}
+----
+=to=Entity#42:classorg_1_1example_1_1foo_1_1_empty_class
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"class","visibility":"package","full_name":"org::example::foo::EmptyClass","name":"EmptyClass","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","mdoc":["This class is empty and is only visible in this package."]}
+
+
+Edge
+=type=9:BOUNDTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","is_intro":true,"name":"EmptyClass","full_name":"org::example::foo::EmptyClass","mdoc":["This class is empty and is only visible in this package."]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"EmptyClass","full_name":"org::example::foo::EmptyClass"}
+
+
+Edge
+=type=6:MCLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","is_intro":true,"name":"EmptyClass","full_name":"org::example::foo::EmptyClass","mdoc":["This class is empty and is only visible in this package."]}
+----
+=to=Entity#42:classorg_1_1example_1_1foo_1_1_empty_class
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"class","visibility":"package","full_name":"org::example::foo::EmptyClass","name":"EmptyClass","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/EmptyClass.java:21,1--21,1","mdoc":["This class is empty and is only visible in this package."]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a4e97061eb40b045e820de05b33c43d21
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(6):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.\u000e2\u00080\u0009c"],"is_intro":true,"full_name":"org::example::foo::C::THE_ANSWER"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"public","name":"THE_ANSWER","full_name":"org::example::foo::C::THE_ANSWER"}
+
+
+Edge
+=type=4:TYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a4e97061eb40b045e820de05b33c43d21
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(6):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.\u000e2\u00080\u0009c"],"is_intro":true,"full_name":"org::example::foo::C::THE_ANSWER"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["final long"]}
+
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a28ac7ce349ebb3e4a7747a8dd951582b
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:30,1--1,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["A function with implicit modifiers."],"is_intro":true,"full_name":"org::example::foo::C::baz"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"baz","full_name":"org::example::foo::C::baz"}
+
+
+Edge
+=type=9:SIGNATURE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a28ac7ce349ebb3e4a7747a8dd951582b
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:30,1--1,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["A function with implicit modifiers."],"is_intro":true,"full_name":"org::example::foo::C::baz"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(0):
+{}
+
+
+Edge
+=type=10:RETURNTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MSignature
+=properties=JsonObject(0):
+{}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+8:MRawType
+=properties=JsonObject(1):
+{"text":["void"]}
+
+
+Edge
+=type=9:CLASSTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#36:interfaceorg_1_1example_1_1foo_1_1_c
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"interface","visibility":"public","full_name":"org::example::foo::C","name":"C","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","mdoc":["An interface"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"C","full_name":"org::example::foo::C"}
+
+
+Edge
+=type=5:CLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"C","full_name":"org::example::foo::C"}
+----
+=to=Entity#36:interfaceorg_1_1example_1_1foo_1_1_c
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"interface","visibility":"public","full_name":"org::example::foo::C","name":"C","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","mdoc":["An interface"]}
+
+
+Edge
+=type=9:BOUNDTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"C","full_name":"org::example::foo::C"}
+
+
+Edge
+=type=6:MCLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#36:interfaceorg_1_1example_1_1foo_1_1_c
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(6):
+{"kind":"interface","visibility":"public","full_name":"org::example::foo::C","name":"C","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","mdoc":["An interface"]}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"public","name":"THE_ANSWER","full_name":"org::example::foo::C::THE_ANSWER"}
+
+
+Edge
+=type=14:INTRO_CLASSDEF
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+10:MAttribute
+=properties=JsonObject(3):
+{"visibility":"public","name":"THE_ANSWER","full_name":"org::example::foo::C::THE_ANSWER"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a4e97061eb40b045e820de05b33c43d21
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+13:MAttributeDef
+=properties=JsonObject(6):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:25,1---1,1","visibility":"public","name":"THE_ANSWER","mdoc":["\u000e2\u00080\u0009cAnswer to the Ultimate Question of Life, the Universe, and Everything.\u000e2\u00080\u0009c"],"is_intro":true,"full_name":"org::example::foo::C::THE_ANSWER"}
+
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"baz","full_name":"org::example::foo::C::baz"}
+
+
+Edge
+=type=14:INTRO_CLASSDEF
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+9:MProperty
+7:MMethod
+=properties=JsonObject(4):
+{"visibility":"public","is_init":false,"name":"baz","full_name":"org::example::foo::C::baz"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(5):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:21,1--31,1","is_intro":true,"name":"C","full_name":"org::example::foo::C","mdoc":["An interface"]}
+----
+=to=Entity#71:interfaceorg_1_1example_1_1foo_1_1_c_1a28ac7ce349ebb3e4a7747a8dd951582b
+=labels=Array(4):
+3:foo
+7:MEntity
+8:MPropDef
+10:MMethodDef
+=properties=JsonObject(9):
+{"location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/C.java:30,1--1,1","is_intern":false,"is_extern":false,"is_abstract":false,"visibility":"public","name":"baz","mdoc":["A function with implicit modifiers."],"is_intro":true,"full_name":"org::example::foo::C::baz"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#12:namespaceorg
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org","name":"org","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+
+Edge
+=type=6:PARENT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#12:namespaceorg
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org","name":"org","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+
+
+Edge
+=type=5:NESTS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+----
+=to=Entity#12:namespaceorg
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org","name":"org","location":"\/dev\/null:1,1--1,1"}
+
+
+Edge
+=type=6:PARENT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#23:namespaceorg_1_1example
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example","name":"example","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Entity#12:namespaceorg
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org","name":"org","location":"\/dev\/null:1,1--1,1"}
+
+
+Edge
+=type=5:NESTS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#12:namespaceorg
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org","name":"org","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Entity#23:namespaceorg_1_1example
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example","name":"example","location":"\/dev\/null:1,1--1,1"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#23:namespaceorg_1_1example
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example","name":"example","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+
+Edge
+=type=6:PARENT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Entity#23:namespaceorg_1_1example
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example","name":"example","location":"\/dev\/null:1,1--1,1"}
+
+
+Edge
+=type=5:NESTS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#23:namespaceorg_1_1example
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example","name":"example","location":"\/dev\/null:1,1--1,1"}
+----
+=to=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#30:namespaceorg_1_1example_1_1foo
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(5):
+{"kind":"namespace","visibility":"","full_name":"org::example::foo","name":"foo","location":"%SOURCE_DIRECTORY%\/org\/example\/foo\/A.java:16,1--1,1"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+
+---===DONE===---
diff --git a/tests/sav/neo_doxygen_file_compound.res b/tests/sav/neo_doxygen_file_compound.res
new file mode 100644 (file)
index 0000000..e606150
--- /dev/null
@@ -0,0 +1,299 @@
+# Graph
+Edge
+=type=4:ROOT
+=properties=JsonObject(0):
+{}
+----
+=from=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"\/dev\/null:1,1--1,1","full_name":"a::b::Bar","name":"Bar"}
+
+Edge
+=type=10:INTRODUCES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"\/dev\/null:1,1--1,1","full_name":"a::b::Bar","name":"Bar"}
+----
+=to=Entity#12:classa_b_bar
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(4):
+{"kind":"class","visibility":"public","full_name":"a::b::Bar","name":"Bar"}
+
+Edge
+=type=7:DEFINES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"\/dev\/null:1,1--1,1","full_name":"a::b::Bar","name":"Bar"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"\/dev\/null:1,1--1,1","is_intro":true,"name":"Bar","full_name":"a::b::Bar"}
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#10:namespacec
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"c","name":"c"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"\/dev\/null:1,1--1,1","full_name":"c::Bar","name":"Bar"}
+
+Edge
+=type=8:DECLARES
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+7:MModule
+=properties=JsonObject(3):
+{"location":"\/dev\/null:1,1--1,1","full_name":"d::Bar","name":"Bar"}
+
+Edge
+=type=9:CLASSTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#12:classa_b_bar
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(4):
+{"kind":"class","visibility":"public","full_name":"a::b::Bar","name":"Bar"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"Bar","full_name":"a::b::Bar"}
+
+Edge
+=type=5:CLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"Bar","full_name":"a::b::Bar"}
+----
+=to=Entity#12:classa_b_bar
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(4):
+{"kind":"class","visibility":"public","full_name":"a::b::Bar","name":"Bar"}
+
+Edge
+=type=9:BOUNDTYPE
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"\/dev\/null:1,1--1,1","is_intro":true,"name":"Bar","full_name":"a::b::Bar"}
+----
+=to=Entity#0:
+=labels=Array(4):
+3:foo
+7:MEntity
+5:MType
+10:MClassType
+=properties=JsonObject(2):
+{"name":"Bar","full_name":"a::b::Bar"}
+
+Edge
+=type=6:MCLASS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+9:MClassDef
+=properties=JsonObject(4):
+{"location":"\/dev\/null:1,1--1,1","is_intro":true,"name":"Bar","full_name":"a::b::Bar"}
+----
+=to=Entity#12:classa_b_bar
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MClass
+=properties=JsonObject(4):
+{"kind":"class","visibility":"public","full_name":"a::b::Bar","name":"Bar"}
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#10:namespacec
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"c","name":"c"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+Edge
+=type=6:PARENT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#10:namespacec
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"c","name":"c"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+
+Edge
+=type=5:NESTS
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+----
+=to=Entity#10:namespacec
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"c","name":"c"}
+
+
diff --git a/tests/sav/neo_doxygen_graph_empty_project.res b/tests/sav/neo_doxygen_graph_empty_project.res
new file mode 100644 (file)
index 0000000..d57edd6
--- /dev/null
@@ -0,0 +1,44 @@
+# Graph
+Edge
+=type=4:ROOT
+=properties=JsonObject(0):
+{}
+----
+=from=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+----
+=to=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+
+Edge
+=type=7:PROJECT
+=properties=JsonObject(0):
+{}
+----
+=from=Entity#0:
+=labels=Array(3):
+3:foo
+7:MEntity
+6:MGroup
+=properties=JsonObject(2):
+{"full_name":"","name":"foo"}
+----
+=to=Node
+=labels=Array(3):
+3:foo
+7:MEntity
+8:MProject
+=properties=JsonObject(1):
+{"name":"foo"}
+
+
diff --git a/tests/sav/neo_doxygen_member_resolve_introducer.res b/tests/sav/neo_doxygen_member_resolve_introducer.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/nitg-e/base_self_type.res b/tests/sav/nitg-e/base_self_type.res
new file mode 100644 (file)
index 0000000..3c20b42
--- /dev/null
@@ -0,0 +1,11 @@
+X
+X
+X
+Y
+Y
+Y
+Y
+A
+G
+B
+G
diff --git a/tests/sav/nitg-e/base_self_type_alt2.res b/tests/sav/nitg-e/base_self_type_alt2.res
new file mode 100644 (file)
index 0000000..3c20b42
--- /dev/null
@@ -0,0 +1,11 @@
+X
+X
+X
+Y
+Y
+Y
+Y
+A
+G
+B
+G
index 56621b6..980ce17 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:374)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:411)
 11
 21
 31
index 56621b6..980ce17 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:374)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:411)
 11
 21
 31
index 56621b6..980ce17 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:374)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/standard/kernel.nit:411)
 11
 21
 31
diff --git a/tests/sav/nitiwiki.res b/tests/sav/nitiwiki.res
new file mode 100644 (file)
index 0000000..232b5ef
--- /dev/null
@@ -0,0 +1,2 @@
+Not in a nitiwiki directory.
+Use --init to initialize one here.
diff --git a/tests/sav/nitiwiki_args1.res b/tests/sav/nitiwiki_args1.res
new file mode 100644 (file)
index 0000000..3f5641d
--- /dev/null
@@ -0,0 +1,10 @@
+nitiWiki
+name: wiki2
+config: ../contrib/nitiwiki/tests/wiki1/config2.ini
+url: http://localhost/
+
+There is modified files:
+ + pages
+ + /pages/index.md
+
+Use nitiwiki --render to render modified files
diff --git a/tests/sav/nitiwiki_args2.res b/tests/sav/nitiwiki_args2.res
new file mode 100644 (file)
index 0000000..adf25a7
--- /dev/null
@@ -0,0 +1 @@
+Render section out
index af28f14..e248df6 100644 (file)
@@ -41,7 +41,7 @@ Bool [
 Object -> Bool [dir=back arrowtail=open style=dashed];
 
 Float [
- label = "{Float||}"
+ label = "{Float||+ is_approx(other: Float, precision: Float): Bool\l}"
 ]
 Numeric -> Float [dir=back arrowtail=open style=dashed];
 
index 6189897..9a7b30f 100644 (file)
@@ -41,7 +41,7 @@ Bool [
 Object -> Bool [dir=back arrowtail=open style=dashed];
 
 Float [
- label = "{Float||}"
+ label = "{Float||+ is_approx(other: Float, precision: Float): Bool\l}"
 ]
 Numeric -> Float [dir=back arrowtail=open style=dashed];
 
index aa38be4..9533b69 100644 (file)
@@ -1 +1 @@
-Runtime error: Assert failed (../lib/c.nit:64)
+Runtime error: Assert failed (../lib/c.nit:63)
index 95d7a74..17a3dc5 100644 (file)
@@ -1,2 +1,2 @@
-Runtime error: Assert failed (../lib/c.nit:57)
+Runtime error: Assert failed (../lib/c.nit:56)
 0
index 95d7a74..17a3dc5 100644 (file)
@@ -1,2 +1,2 @@
-Runtime error: Assert failed (../lib/c.nit:57)
+Runtime error: Assert failed (../lib/c.nit:56)
 0
index 3bb984c..fdc9a45 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Assert failed (../lib/c.nit:56)
+Runtime error: Assert failed (../lib/c.nit:55)
 0
 0
 1
index ba6c5fe..b05a1b7 100644 (file)
@@ -1,4 +1,4 @@
-Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:782)
+Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:785)
 NativeString
 N
 Nit