Merge: nitdoc: full rewrite
authorJean Privat <jean@pryen.org>
Wed, 20 Jun 2018 18:59:16 +0000 (14:59 -0400)
committerJean Privat <jean@pryen.org>
Wed, 20 Jun 2018 18:59:16 +0000 (14:59 -0400)
This PR introduces a new version of Nitdoc based on DocCommands.
The main objective is to unify the display with `nitweb`.
Beside a cleaner implementation and the removal of a lot of code here a quick presentation of the new tool.

### Replace Overview page by Nit Catalog

Avoiding the clutter of the old overview page.

![home](https://user-images.githubusercontent.com/583144/40859182-df1db392-65ae-11e8-82d6-8abd1708722e.png)

This closes #1516

### New packages pages

Package READMEs are now rendered with support of `[[doc commands]]`

![screenshot from 2018-06-01 15 19 10](https://user-images.githubusercontent.com/583144/40859246-263b4a14-65af-11e8-9fe8-4806fedc4a2a.png)

### Simplified modules pages

The modules pages offer a simplified view of its content with introduced and redefined classes:

![screenshot from 2018-06-01 15 23 28](https://user-images.githubusercontent.com/583144/40859466-ed481434-65af-11e8-8c06-88d8b50b17e2.png)

### Module code view

The source code of a module can be viewed directly in the documentation:

![screenshot from 2018-06-01 15 25 12](https://user-images.githubusercontent.com/583144/40860212-9bca9192-65b2-11e8-9115-a623a3d9f026.png)

Entities in the source code can be clicked to access the related documentation page.
This closes #953.

### Class & property linearization

In the new nitdoc, I totally removed the concept of definition pages. Thus no more page for a MClassDef or a MPropDef.

Instead we present the linearization of a MClass or MProperty like in nitweb.

![screenshot from 2018-06-01 15 27 53](https://user-images.githubusercontent.com/583144/40859654-89aa4cca-65b0-11e8-9e2a-0f710a9186ea.png)

There is now a simple rule for where a click on a class or property will land:
* If the user clicks on an introduction, the target page is the documentation of the class or property (the intro def)
* If the user clicks on a redefinition, the target is the definition card in the linearization list.

Beside in the linearization lists, there is only two places where you can find a link to a redefinition:
* in the **Redefined classes** of a module page (tab #doc)
* in the **Redefined properties** of a class page (tab #doc)

Here also, the code is linked to the documentation.

I applied heuristics that disable the linearization lists for:
* `Sys`
* `Object::SELF`
* `Object::init`
* `Object::to_s`

This closes #1563.

### Better quicksearch results

In order to close #361, I added an heuristic to place the packages and modules on top of the list depending on the query.

If the query has a better matches with properties, they will be presented in top, here an example for the query `pop`:

![screenshot from 2018-06-01 15 36 44](https://user-images.githubusercontent.com/583144/40859970-9a7a4ce8-65b1-11e8-9a84-c6fc83886e96.png)

The `pop` first matches `pop` and `popup` then we presents the packages and modules `popcorn`.

For the query `popc`:

![screenshot from 2018-06-01 15 37 57](https://user-images.githubusercontent.com/583144/40860045-e0eea2dc-65b1-11e8-90d1-5f233ce7d204.png)

We directly show the matches for the packages and modules (same behavior than before).

### Redesign

The new design (imported from nitweb) add a lot of free spaces for future PR like example suggestions, doc generation, call graphs etc.

We can benefit from the tabbed view to add new content (like in nitweb with the license et contrib rules for examples).
We can also use the space under the documentation to introduce examples and other things.

### Regressions

The only regression is the disappearance of concerns sections. I'm working on it with new doc commands.

Final note, it also closes #962.

Pull-Request: #2707

18 files changed:
.gitignore
lib/core/core.nit
lib/core/file.nit
lib/posix/README.md [new file with mode: 0644]
lib/posix/ext.nit [moved from lib/posix_ext/posix_ext.nit with 91% similarity]
lib/posix/package.ini [moved from lib/posix_ext/package.ini with 55% similarity]
lib/posix/posix.nit [moved from lib/core/posix.nit with 94% similarity]
lib/privileges/privileges.nit
lib/trees/bktree.nit [new file with mode: 0644]
lib/vsm/vsm.nit
share/nitweb/directives/entity/card.html
share/nitweb/directives/ui/search-field.html
share/nitweb/views/catalog/person.html
share/nitweb/views/search.html
src/indexing/code_index.nit [new file with mode: 0644]
src/indexing/tests/test_code_index.nit [new file with mode: 0644]
tests/MINGW64_NT.skip
tests/testall.sh

index c4cb96e..1463ddf 100644 (file)
@@ -31,10 +31,12 @@ src/*.dat
 src/*.gnu
 src/*.bin
 src/nitc_0
+src/nitc_0.exe
 
 c_src/*.o
 c_src/*.cksum
 c_src/nitc
+c_src/nitc.exe
 
 csrc2/
 
index 54f2550..5261077 100644 (file)
@@ -15,7 +15,6 @@
 # This module is implicitly imported by every module.
 module core
 
-import posix
 import environ
 import time
 import file
index fa50549..ed4c6c8 100644 (file)
@@ -306,6 +306,9 @@ redef class Int
        private fun fd_to_stream(mode: CString): NativeFile `{
                return fdopen((int)self, mode);
        `}
+
+       # Does the file descriptor `self` refer to a terminal?
+       fun isatty: Bool `{ return isatty(self); `}
 end
 
 # Constant for read-only file streams
diff --git a/lib/posix/README.md b/lib/posix/README.md
new file mode 100644 (file)
index 0000000..3b73f9c
--- /dev/null
@@ -0,0 +1,5 @@
+Services conforming to POSIX
+
+The core module `posix` includes POSIX services available on all POSIX compliant systems.
+For services provided by some implementations of POSIX but absent from any POSIX version,
+import `posix::ext`.
similarity index 91%
rename from lib/posix_ext/posix_ext.nit
rename to lib/posix/ext.nit
index 8dd83c3..85da40a 100644 (file)
@@ -1,7 +1,5 @@
 # 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
@@ -15,7 +13,9 @@
 # limitations under the License.
 
 # Services not defined in POSIX but provided by most implementations
-module posix_ext
+module ext
+
+import posix
 
 redef extern class Passwd
        # User information
similarity index 55%
rename from lib/posix_ext/package.ini
rename to lib/posix/package.ini
index 6b78527..79c6ca1 100644 (file)
@@ -1,12 +1,12 @@
 [package]
-name=posix_ext
+name=posix
 tags=wrapper,lib
 maintainer=Alexis Laferrière <alexis.laf@xymus.net>
 license=Apache-2.0
-desc=Services not defined in POSIX but provided by most implementations
+desc=Services conforming to POSIX
 [upstream]
-browse=https://github.com/nitlang/nit/tree/master/lib/posix_ext/
+browse=https://github.com/nitlang/nit/tree/master/lib/posix/
 git=https://github.com/nitlang/nit.git
-git.directory=lib/posix_ext/
+git.directory=lib/posix/
 homepage=http://nitlanguage.org
 issues=https://github.com/nitlang/nit/issues
similarity index 94%
rename from lib/core/posix.nit
rename to lib/posix/posix.nit
index 587e606..03a8a2e 100644 (file)
@@ -1,7 +1,5 @@
 # This file is part of NIT ( http://www.nitlanguage.org ).
 #
-# Copyright 2013 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
@@ -17,8 +15,6 @@
 # Services conforming to POSIX
 module posix
 
-import text
-
 in "C Header" `{
 #include <sys/types.h>
 #include <unistd.h>
@@ -111,8 +107,3 @@ extern class Group `{struct group*`}
                return ret;
        `}
 end
-
-redef class Int
-       # Does the file descriptor `self` refer to a terminal?
-       fun isatty: Bool `{ return isatty(self); `}
-end
index f17a28e..c3a9466 100644 (file)
@@ -21,6 +21,7 @@
 module privileges
 
 import opts
+import posix
 
 redef class Text
        # Does the operating system know the user named `self`?
diff --git a/lib/trees/bktree.nit b/lib/trees/bktree.nit
new file mode 100644 (file)
index 0000000..b7d0d48
--- /dev/null
@@ -0,0 +1,149 @@
+# 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.
+
+# Implementation of BKTree
+#
+# As proposed by W. A. Burkhard and R. M. Keller in
+# "Some approaches to best-match file searching" the BKTree data structure
+# is usefull to speed-up spell checking based on the Levenshtein distance between
+# words.
+#
+# With a BKTree, the complexity to find mispelled words in a dictionnary is *O(log n)*
+# instead of *O(n)* with a dummy list.
+#
+# Example:
+#
+# ~~~
+# # Create a new BKTree
+# var tree = new BKTree
+#
+# # Index some words in the dictionnary for spell checking
+# tree.add("book")
+# tree.add("books")
+# tree.add("cake")
+# tree.add("boo")
+# tree.add("cape")
+# tree.add("boon")
+# tree.add("cook")
+# tree.add("cart")
+#
+# # Search suggestions in the BKTree
+# assert tree.search("caqe").join(", ") == "\{1: cake\}, \{1: cape\}"
+# ~~~
+#
+# See <https://dl.acm.org/citation.cfm?id=362003.362025>.
+module bktree
+
+import abstract_tree
+
+# A BKTree implementation
+#
+# See `add` to insert a new word.
+# See `search` to find matches from a `key`.
+class BKTree
+
+       # Default tolerance used to find matches
+       #
+       # Default is `2`.
+       var default_tolerance = 2 is writable
+
+       # Tree root
+       private var root: nullable BKNode = null
+
+       # Add a `key` in the tree
+       fun add(key: String) do
+               var root = self.root
+               if root == null then
+                       self.root = new BKNode(key)
+                       return
+               end
+
+               var node = root
+               var dist = node.key.levenshtein_distance(key)
+
+               while node.has_key(dist) do
+                       if dist == 0 then return
+                       node = node[dist]
+                       dist = node.key.levenshtein_distance(key)
+               end
+               node[dist] = new BKNode(key)
+       end
+
+       # Search `key` with a distance of `tolerance` in `self`.
+       #
+       # If `tolerance` is null, the use `default_tolerance` instead.
+       fun search(key: String, tolerance: nullable Int): Array[BKMatch] do
+               var res = new Array[BKMatch]
+               var root = self.root
+               if root != null then
+                       if tolerance == null then tolerance = self.default_tolerance
+                       search_recursive(root, res, key, tolerance)
+               end
+               default_comparator.sort(res)
+               return res
+       end
+
+       private fun search_recursive(node: BKNode, res: Array[BKMatch], key: String, tolerance: Int) do
+               var dist = node.key.levenshtein_distance(key)
+               var min = dist - tolerance
+               var max = dist + tolerance
+
+               if dist < tolerance then
+                       res.add new BKMatch(dist, node.key)
+               end
+
+               for odist, child in node do
+                       if odist < min or odist > max then continue
+                       search_recursive(child, res, key, tolerance)
+               end
+       end
+end
+
+# A node that goes in a BKTree
+#
+# Each child is mapped from `self` by its distance as an Int.
+private class BKNode
+       super HashMap[Int, BKNode]
+
+       # Key stored in `self`
+       var key: String
+
+       redef fun to_s do return "\{{key}\}"
+end
+
+# A match in a BKTree
+#
+# Used to order results returned by `BKTree::search`.
+class BKMatch
+       super Comparable
+
+       redef type OTHER: BKMatch
+
+       # Distance of `key` from the search query
+       var distance: Int
+
+       # Matched `key`
+       var key: String
+
+       redef fun ==(o) do return o isa BKMatch and distance == o.distance and key == o.key
+
+       redef fun <=>(o) do
+               if distance == o.distance then
+                       return key <=> o.key
+               end
+               return distance <=> o.distance
+       end
+
+       redef fun to_s do return "\{{distance}: {key}\}"
+end
index 4a64f99..ad3d928 100644 (file)
@@ -77,6 +77,17 @@ class Vector
                return super
        end
 
+       # Increment value for `obj` term
+       #
+       # If the term isn't already in the vector, the new value is 1.0.
+       fun inc(obj: nullable Object) do
+               if has_key(obj) then
+                       self[obj] += 1.0
+               else
+                       self[obj] = 1.0
+               end
+       end
+
        # The norm of the vector.
        #
        # `||x|| = (x1 ** 2 ... + xn ** 2).sqrt`
@@ -112,10 +123,18 @@ end
 # Documents can then be matched to query vectors.
 class VSMIndex
 
+       # Kind of documents stored in this index
+       #
+       # Clients can redefine this type to specialize the index.
+       type DOC: Document
+
        # Documents index
+       var documents = new HashSet[DOC]
+
+       # Inversed index
        #
-       # TODO use a more efficient representation.
-       var documents = new HashSet[Document]
+       # Link documents to existing terms.
+       var inversed_index = new HashMap[nullable Object, Array[DOC]]
 
        # Count for all terms in all indexed documents
        #
@@ -137,12 +156,18 @@ class VSMIndex
        #
        # Returns an `IndexMatch` for each indexed document.
        # Results are ordered by descending similarity.
-       fun match_vector(query: Vector): Array[IndexMatch] do
-               var matches = new Array[IndexMatch]
+       fun match_vector(query: Vector): Array[IndexMatch[DOC]] do
+               var documents = new HashSet[DOC]
+               for term, count in query do
+                       if inversed_index.has_key(term) then
+                               documents.add_all inversed_index[term]
+                       end
+               end
+               var matches = new Array[IndexMatch[DOC]]
                for doc in documents do
                        var sim = query.cosine_similarity(doc.tfidf)
                        if sim == 0.0 then continue
-                       matches.add new IndexMatch(doc, sim)
+                       matches.add new IndexMatch[DOC](doc, sim)
                end
                sorter.sort(matches)
                return matches
@@ -156,13 +181,13 @@ class VSMIndex
        #
        # When processing batch documents, use `auto_update = false` to disable
        # the auto update of the index.
-       fun index_document(doc: Document, auto_update: nullable Bool) do
+       fun index_document(doc: DOC, auto_update: nullable Bool) do
                for term, count in doc.terms_count do
-                       if not terms_doc_count.has_key(term) then
-                               terms_doc_count[term] = 1.0
-                       else
-                               terms_doc_count[term] += 1.0
+                       terms_doc_count.inc(term)
+                       if not inversed_index.has_key(term) then
+                               inversed_index[term] = new Array[DOC]
                        end
+                       inversed_index[term].add doc
                end
                documents.add doc
                if auto_update == null or auto_update then update_index
@@ -196,7 +221,7 @@ class StringIndex
        # Return the Document created.
        #
        # See `index_document`.
-       fun index_string(title, uri, string: String, auto_update: nullable Bool): Document do
+       fun index_string(title, uri, string: String, auto_update: nullable Bool): DOC do
                var vector = parse_string(string)
                var doc = new Document(title, uri, vector)
                index_document(doc, auto_update)
@@ -206,7 +231,7 @@ class StringIndex
        # Match the `query` string against all indexed documents
        #
        # See `match_vector`.
-       fun match_string(query: String): Array[IndexMatch] do
+       fun match_string(query: String): Array[IndexMatch[DOC]] do
                var vector = parse_string(query)
                var doc = new Document("", "", vector)
                return match_vector(doc.terms_frequency)
@@ -221,12 +246,7 @@ class StringIndex
                loop
                        var token = reader.read_word
                        if token == "" then break
-
-                       if not vector.has_key(token) then
-                               vector[token] = 1.0
-                       else
-                               vector[token] += 1.0
-                       end
+                       vector.inc(token)
                end
                return vector
        end
@@ -241,7 +261,7 @@ class FileIndex
        # Return the created document or null if `path` is not accepted by `accept_file`.
        #
        # See `index_document`.
-       fun index_file(path: String, auto_update: nullable Bool): nullable Document do
+       fun index_file(path: String, auto_update: nullable Bool): nullable DOC do
                if not accept_file(path) then return null
                var vector = parse_file(path)
                var doc = new Document(path, path, vector)
@@ -347,17 +367,17 @@ class Document
        # A high weight in tf–idf is reached by a high term frequency
        # (in the given document) and a low document frequency of the term in the
        # whole collection of documents
-       var tfidf = new Vector
+       var tfidf: Vector = terms_count is lazy
 
        redef fun to_s do return "{title}"
 end
 
 # A match to a `request` in an `Index`
-class IndexMatch
+class IndexMatch[DOC: Document]
        super Comparable
 
        # Document matching the `request_vector`
-       var document: Document
+       var document: DOC
 
        # Similarity between the `request` and the `doc`.
        #
@@ -372,7 +392,7 @@ end
 class IndexMatchSorter
        super DefaultComparator
 
-       redef type COMPARED: IndexMatch
+       redef type COMPARED: IndexMatch[Document]
 
        redef fun compare(a, b) do
                return b.similarity <=> a.similarity
index 9b295be..34ec170 100644 (file)
@@ -17,6 +17,7 @@
        <div class='card-body' ng-if='mentity.class_name != "MPackage"'>
                <h5 class='card-heading'>
                        <entity-signature mentity='mentity' />
+                       <small><br/><entity-namespace namespace='mentity.namespace' /></small>
                </h5>
                <span class='synopsis' ng-bind-html='mentity.html_synopsis' />
        </div>
index a4d06a6..949a6e3 100644 (file)
@@ -9,7 +9,7 @@
                <entity-card ng-click='vm.selectEnter()' ng-class='{active: vm.activeItem == $index}' ng-mouseover='vm.setActive($index)' mentity='mentity' ng-repeat='mentity in vm.results.results' />
                <div class='card' ng-click='vm.selectEnter()' ng-mouseover='vm.setActive(vm.results.results.length)' ng-class='{active: vm.activeItem == vm.results.results.length}'>
                        <div class='card-body'>
-                               Show all {{vm.results.total}} results for <a>"{{vm.query}}"</a>
+                               Show all {{vm.results.count}} results for <a>"{{vm.query}}"</a>
                        </div>
                </div>
        </div>
index 433b73d..54d9471 100644 (file)
@@ -13,7 +13,7 @@
 <br><br>
 <div class='container'>
        <div ng-if='vm.maintaining.results.length > 0'>
-               <h3 id='maintaining'>{{vm.maintaining.total}} maintained projects</h3>
+               <h3 id='maintaining'>{{vm.maintaining.count}} maintained projects</h3>
                <div class='card-list'>
                        <entity-card mentity='package' ng-repeat='package in vm.maintaining.results' />
                </div>
@@ -22,7 +22,7 @@
                </div>
        </div>
        <div ng-if='vm.contributing.results.length > 0'>
-               <h3 id='contributing'>{{vm.contributing.total}} contributed projects</h3>
+               <h3 id='contributing'>{{vm.contributing.count}} contributed projects</h3>
                <div class='card-list'>
                        <entity-card mentity='package' ng-repeat='package in vm.contributing.results' />
                </div>
index 6614e9c..ddf9f4c 100644 (file)
@@ -1,6 +1,6 @@
 <div class='container'>
        <h2>
-               {{vm.entities.total}} matches for
+               {{vm.entities.count}} matches for
                <a ui-sref='search({q: vm.query})'>{{vm.query}}</a>
        </h2>
        <div class='card-list'>
diff --git a/src/indexing/code_index.nit b/src/indexing/code_index.nit
new file mode 100644 (file)
index 0000000..765fad0
--- /dev/null
@@ -0,0 +1,204 @@
+# 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.
+
+# An index that contains Nit code
+#
+# Model entities are indexed by their ANode.
+#
+# Vectorization is based on model usage such as:
+# * modules importation
+# * classes spcialization and refinement
+# * methods calls and refinements
+#
+# Example:
+# ~~~nitish
+# # Create the index
+# var index = new CodeIndex(toolcontext)
+# for mentity in mentities do
+#      index.index_mentity(mentity)
+# end
+#
+# # Match a piece of code
+# var matches = index.match_code("print \"Hello, World!\"")
+# for match in matches do
+#      print match
+# end
+# ~~~
+module code_index
+
+import vsm
+import semantize
+import parser_util
+
+# Index for Nit doc
+class CodeIndex
+       super VSMIndex
+
+       redef type DOC: CodeDocument
+
+       # ToolContext used to parse pieces of code
+       var toolcontext: ToolContext
+
+       # Index `mentity`
+       fun index_mentity(mentity: MEntity) do
+               var terms = vectorize_mentity(mentity)
+               var doc = new CodeDocument(mentity, terms)
+               index_document(doc, false)
+       end
+
+       # Match `code` with the index
+       fun match_code(code: String): Array[IndexMatch[DOC]] do
+               var node = parse_code(code)
+               if node == null then return new Array[IndexMatch[DOC]]
+               return match_node(node)
+       end
+
+       # Match `node` with the index
+       fun match_node(node: ANode): Array[IndexMatch[DOC]] do
+               var vector = vectorize_node(node)
+               return match_vector(vector)
+       end
+
+       # Parse a piece of code
+       private fun parse_code(code: String): nullable AModule do
+               # Try to parse code
+               var node = toolcontext.parse_something(code)
+               if not node isa AModule then return null
+
+               # Load code into model
+               var mbuilder = toolcontext.modelbuilder
+               mbuilder.load_rt_module(null, node, "tmp")
+               mbuilder.run_phases
+               return node
+       end
+
+       # Transform `node` in a Vector
+       private fun vectorize_node(node: ANode): Vector do
+               var visitor = new CodeIndexVisitor
+               visitor.enter_visit(node)
+               return visitor.vector
+       end
+
+       # Transform `mentity` in a Vector
+       private fun vectorize_mentity(mentity: MEntity): Vector do
+               var node = toolcontext.modelbuilder.mentity2node(mentity)
+               if node == null then return new Vector
+               return vectorize_node(node)
+       end
+end
+
+# A specific document for mentities code
+class CodeDocument
+       super Document
+       autoinit(mentity, terms_count)
+
+       # MEntity related to this document
+       var mentity: MEntity
+
+       redef var title = mentity.full_name is lazy
+
+       redef var uri = mentity.location.to_s is lazy
+end
+
+# Code index visitor
+#
+# Used to build a VSM Vector from a Nit ANode.
+private class CodeIndexVisitor
+       super Visitor
+
+       var vector = new Vector
+
+       redef fun visit(node) do
+               node.accept_code_index_visitor(self)
+       end
+end
+
+redef class ANode
+       private fun accept_code_index_visitor(v: CodeIndexVisitor) do
+               visit_all(v)
+       end
+end
+
+redef class AStdImport
+       redef fun accept_code_index_visitor(v) do
+               var mmodule = self.mmodule
+               if mmodule != null then
+                       v.vector.inc "import#{mmodule.full_name}"
+               end
+       end
+end
+
+redef class AStdClassdef
+       redef fun accept_code_index_visitor(v) do
+               var mclassdef = self.mclassdef
+               if mclassdef != null then
+                       if not mclassdef.is_intro then
+                               v.vector.inc "redef#{mclassdef.full_name}"
+                               v.vector.inc "redef#{mclassdef.mclass.full_name}"
+                       end
+               end
+               visit_all(v)
+       end
+end
+
+redef class ASuperPropdef
+       redef fun accept_code_index_visitor(v) do
+               var mtype = self.n_type.mtype
+               if mtype isa MClassType then
+                       v.vector.inc "super#{mtype.mclass.intro.full_name}"
+                       v.vector.inc "super#{mtype.mclass.full_name}"
+               end
+       end
+end
+
+redef class APropdef
+       redef fun accept_code_index_visitor(v) do
+               var mpropdef = self.mpropdef
+               if mpropdef != null then
+                       if not mpropdef.is_intro then
+                               v.vector.inc "redef#{mpropdef.mproperty.intro.full_name}"
+                               v.vector.inc "redef#{mpropdef.mproperty.full_name}"
+                       end
+               end
+               visit_all(v)
+       end
+end
+
+redef class ASendExpr
+       redef fun accept_code_index_visitor(v) do
+               var callsite = self.callsite
+               if callsite != null then
+                       var args = callsite.signaturemap.as(not null).map.length
+                       v.vector.inc "call#{callsite.mpropdef.full_name}({args})"
+                       v.vector.inc "call#{callsite.mpropdef.mproperty.full_name}({args})"
+                       v.vector.inc "call#{callsite.mpropdef.mclassdef.full_name}({args})"
+                       v.vector.inc "call#{callsite.mpropdef.mclassdef.mclass.full_name}({args})"
+               end
+               visit_all(v)
+       end
+end
+
+redef class ANewExpr
+       redef fun accept_code_index_visitor(v) do
+               var callsite = self.callsite
+               if callsite != null then
+                       var args = callsite.signaturemap.as(not null).map.length
+                       v.vector.inc "call#{callsite.mpropdef.full_name}({args})"
+                       v.vector.inc "call#{callsite.mpropdef.mproperty.full_name}({args})"
+                       v.vector.inc "new#{callsite.mpropdef.mclassdef.full_name}({args})"
+                       v.vector.inc "new#{callsite.mpropdef.mclassdef.mclass.full_name}({args})"
+               end
+               visit_all(v)
+       end
+end
diff --git a/src/indexing/tests/test_code_index.nit b/src/indexing/tests/test_code_index.nit
new file mode 100644 (file)
index 0000000..b2a8f2e
--- /dev/null
@@ -0,0 +1,74 @@
+# 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.
+
+module test_code_index is test
+
+import code_index
+import frontend
+
+class TestCodeIndex
+       test
+
+       # CodeIndex used in tests
+       var test_index: CodeIndex is noinit
+
+       # Initialize test variables
+       #
+       # Must be called before test execution.
+       # FIXME should be before_all
+       fun build_test_env is before do
+               var test_path = "NIT_TESTING_PATH".environ.dirname
+               var test_src = test_path / "../../../tests/test_prog"
+
+               # build model
+               var toolcontext = new ToolContext
+               var model = new Model
+               var modelbuilder = new ModelBuilder(model, toolcontext)
+               var mmodules = modelbuilder.parse_full([test_src])
+               modelbuilder.run_phases
+               toolcontext.run_global_phases(mmodules)
+
+               # create index
+               var index = new CodeIndex(toolcontext)
+               for mmodule in mmodules do
+                       index.index_mentity(mmodule)
+               end
+               test_index = index
+               modelbuilder.paths.add test_src
+       end
+
+       fun test_find1 is test do
+               var query = "import game\n"
+               var matches = test_index.match_code(query)
+               assert matches.first.document.mentity.full_name == "test_prog::test_prog"
+       end
+
+       fun test_find2 is test do
+               var query = "import game\nimport rpg\n"
+               var matches = test_index.match_code(query)
+               assert matches.first.document.mentity.full_name == "test_prog::game"
+       end
+
+       fun test_find3 is test do
+               var query = "import game\nclass MyGame\nsuper Game\nredef fun start_game do end\nend\n"
+               var matches = test_index.match_code(query)
+               assert matches.first.document.mentity.full_name == "test_prog::game_examples"
+       end
+
+       fun test_find_error is test do
+               var query = "error"
+               var matches = test_index.match_code(query)
+               assert matches.is_empty
+       end
+end
index e08c0ad..7b99224 100644 (file)
@@ -3,6 +3,7 @@ cocoa_message_box
 hello_cocoa
 hello_ios
 test_platform_ios
+test_platform_android
 mpi
 emscripten
 neo_doxygen
@@ -10,3 +11,69 @@ neo4j
 mongo
 pernicious_numbers
 frankuchredux
+base_autocast
+base_covar_int_alt5
+base_div_by_zero
+shootout_mandelbrot_args1
+test_binary
+test_curl
+test_ffi_java
+test_ffi_objc_types_and_callbacks
+test_fix_int
+test_glsl_validation
+test_json_static
+test_jvm
+test_kill_process
+test_msgpack_deserialization
+test_nitcorn
+test_path_args1
+test_postgres
+test_read_all_args1
+test_regex_check
+test_signals
+test_stream_poll
+nitc
+nitls_args3
+nitmetrics_args3
+nitpm_args
+nitsmells_args
+nitunit_args
+nitvm
+nitweb
+test_highlight_args1
+test_neo
+test_loader_args2
+test_loader_args5
+montecarlo
+catalan_numbers
+count_the_coins
+fibonacci_word
+first_letter_last_letter
+curl_http
+nlp_index
+drop_privileges
+concurrent_array_and_barrier
+jointask_example
+socket_client
+socket_server
+socket_simple_server
+fannkuchredux
+mandelbrot
+thread_ring
+htcpcp_server
+simple_file_server
+test_restful_annot
+nitin
+nitiwiki_args1
+nitiwiki_args2
+test_annot_pkgconfig_alt
+test_gtk
+nitlight_as_a_service
+curl_rest
+lang_annot
+opengles2_hello_triangle
+nlp_server
+ui_test
+restful_annot
+langannot
+simple_simulation
index 61b00e9..7740b5f 100755 (executable)
 # limitations under the License.
 
 # Run some tests on each engine
-for x in nitcg nitcs nitcsg nitce niti nitvm; do
+
+engine=(nitcg nitcg nitcs nitcsg nitce niti nitvm)
+if uname | grep MINGW64 1>/dev/null 2>&1; then
+       engine=(nitcg nitcg nitcs nitcsg nitce)
+fi
+
+for x in "${engine[@]}"; do
        echo "--engine $x"
        ./tests.sh --engine $x "$@"
 done