Merge: Fix qualified imports
authorJean Privat <jean@pryen.org>
Fri, 28 Aug 2015 20:36:18 +0000 (16:36 -0400)
committerJean Privat <jean@pryen.org>
Fri, 28 Aug 2015 20:36:18 +0000 (16:36 -0400)
Solve #1265 and the includes with examples/nitcorn/src/xymus_net.nit

Pull-Request: #1667
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

24 files changed:
examples/nitcorn/Makefile
examples/nitcorn/src/xymus_net.nit
lib/glesv2/examples/opengles2_hello_triangle.nit
src/astbuilder.nit
src/loader.nit
src/parser/parser_nodes.nit
tests/base_import.nit
tests/base_import2.nit [new file with mode: 0644]
tests/project1/module_0.nit [new file with mode: 0644]
tests/project1/module_01.nit [new file with mode: 0644]
tests/project1/module_02.nit [new file with mode: 0644]
tests/project1/subdir/module_0.nit [new file with mode: 0644]
tests/sav/base_import2.res [new file with mode: 0644]
tests/sav/base_import2_alt1.res [new file with mode: 0644]
tests/sav/base_import2_alt2.res [new file with mode: 0644]
tests/sav/base_import2_alt3.res [new file with mode: 0644]
tests/sav/base_import_alt3.res
tests/sav/base_import_alt5.res
tests/sav/base_import_alt6.res [new file with mode: 0644]
tests/sav/nitls_args1.res
tests/sav/nitls_args2.res
tests/sav/nitls_args3.res
tests/sav/nitls_args4.res
tests/sav/xymus_net.res

index 22113aa..e09cde1 100644 (file)
@@ -4,4 +4,4 @@ all:
 
 xymus.net:
        mkdir -p bin/
-       ../../bin/nitc --dir bin/ -I ../../contrib/tnitter/src/ -I ../../contrib/benitlux/src/ -I ../../contrib/opportunity/src/ src/xymus_net.nit
+       ../../bin/nitc --dir bin/ src/xymus_net.nit
index b8a869a..89b9e0b 100644 (file)
@@ -22,8 +22,8 @@ import privileges
 
 # Use actions defined by contribs
 import tnitter
-import benitlux_controller
-import opportunity_controller
+import benitlux::benitlux_controller
+import opportunity::opportunity_controller
 
 # Header for the whole site
 class MasterHeader
index 6389e09..48d49ab 100644 (file)
@@ -22,7 +22,7 @@ module opengles2_hello_triangle
 
 import glesv2
 import egl
-import mnit_linux::sdl
+import sdl
 import x11
 
 if "NIT_TESTING".environ == "true" then exit(0)
index cc7cd88..1e1a235 100644 (file)
@@ -16,8 +16,8 @@
 module astbuilder
 
 intrude import semantize::typing
-intrude import semantize::literal
-intrude import semantize::parser
+intrude import literal
+intrude import parser
 intrude import semantize::scope
 
 # General factory to build semantic nodes in the AST of expressions
index bde4ae2..6d7bbe7 100644 (file)
@@ -287,6 +287,20 @@ redef class ModelBuilder
                return res.first
        end
 
+       # Search groups named `name` from paths `lookpaths`.
+       private fun search_group_in_paths(name: String, lookpaths: Collection[String]): ArraySet[MGroup]
+       do
+               var res = new ArraySet[MGroup]
+               for dirname in lookpaths do
+                       # try a single group directory
+                       var mg = get_mgroup(dirname/name)
+                       if mg != null then
+                               res.add mg
+                       end
+               end
+               return res
+       end
+
        # Cache for `identify_file` by realpath
        private var identified_files_by_path = new HashMap[String, nullable ModulePath]
 
@@ -702,14 +716,77 @@ redef class ModelBuilder
        # This method handles qualified names as used in `AModuleName`.
        fun seach_module_by_amodule_name(n_name: AModuleName, mgroup: nullable MGroup): nullable ModulePath
        do
-               if n_name.n_quad != null then mgroup = null # Start from top level
-               for grp in n_name.n_path do
-                       var path = search_mmodule_by_name(grp, mgroup, grp.text)
-                       if path == null then return null # Forward error
-                       mgroup = path.mgroup
-               end
                var mod_name = n_name.n_id.text
-               return search_mmodule_by_name(n_name, mgroup, mod_name)
+
+               # If a quad is given, we ignore the starting group (go from path)
+               if n_name.n_quad != null then mgroup = null
+
+               # If name not qualified, just search the name
+               if n_name.n_path.is_empty then
+                       # Fast search if no n_path
+                       return search_mmodule_by_name(n_name, mgroup, mod_name)
+               end
+
+               # If qualified and in a group
+               if mgroup != null then
+                       # First search in the project
+                       var r = mgroup.mproject.root
+                       assert r != null
+                       scan_group(r)
+                       # Get all modules with the final name
+                       var res = r.mmodule_paths_by_name(mod_name)
+                       # Filter out the name that does not match the qualifiers
+                       res = [for x in res do if match_amodulename(n_name, x) then x]
+                       if res.not_empty then
+                               if res.length > 1 then
+                                       error(n_name, "Error: conflicting module files for `{mod_name}`: `{res.join(",")}`")
+                               end
+                               return res.first
+                       end
+               end
+
+               # If no module yet, then assume that the first element of the path
+               # Is to be searched in the path.
+               var root_name = n_name.n_path.first.text
+               var roots = search_group_in_paths(root_name, paths)
+               if roots.is_empty then
+                       error(n_name, "Error: cannot find `{root_name}`. Tried: {paths.join(", ")}.")
+                       return null
+               end
+
+               var res = new ArraySet[ModulePath]
+               for r in roots do
+                       # Then, for each root, collect modules that matches the qualifiers
+                       scan_group(r)
+                       var root_res = r.mmodule_paths_by_name(mod_name)
+                       for x in root_res do if match_amodulename(n_name, x) then res.add x
+               end
+               if res.not_empty then
+                       if res.length > 1 then
+                               error(n_name, "Error: conflicting module files for `{mod_name}`: `{res.join(",")}`")
+                       end
+                       return res.first
+               end
+               # If still nothing, just call a basic search that will fail and will produce an error message
+               error(n_name, "Error: cannot find module `{mod_name}` from `{root_name}`. Tried: {paths.join(", ")}.")
+               return null
+       end
+
+       # Is elements of `n_name` correspond to the group nesting of `m`?
+       #
+       # Basically it check that `bar::foo` matches `bar/foo.nit` and `bar/baz/foo.nit`
+       # but not `baz/foo.nit` nor `foo/bar.nit`
+       #
+       # Is used by `seach_module_by_amodule_name` to validate qualified names.
+       private fun match_amodulename(n_name: AModuleName, m: ModulePath): Bool
+       do
+               var g: nullable MGroup = m.mgroup
+               for grp in n_name.n_path.reverse_iterator do
+                       while g != null and grp.text != g.name do
+                               g = g.parent
+                       end
+               end
+               return g != null
        end
 
        # Analyze the module importation and fill the module_importation_hierarchy
index 9550339..0990d6a 100644 (file)
@@ -203,6 +203,7 @@ class ANodes[E: ANode]
        private var parent: ANode
        private var items = new Array[E]
        redef fun iterator do return items.iterator
+       redef fun reverse_iterator do return items.reverse_iterator
        redef fun length do return items.length
        redef fun is_empty do return items.is_empty
        redef fun push(e)
index 8fb3e6c..8f972aa 100644 (file)
@@ -1,3 +1,23 @@
-import project1 #alt1# import project1::module1 #alt2# import project1::module2 #alt3# import project1::fail #alt4# import project1::module4 #alt5# import project1::project2
+# 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 project1 #alt1-6#
+#alt1#import project1::module1
+#alt2#import project1::module2
+#alt3#import project1::fail
+#alt4#import project1::module4
+#alt5#import project1::project2
+#alt6#import fail::module1
 
 foo
diff --git a/tests/base_import2.nit b/tests/base_import2.nit
new file mode 100644 (file)
index 0000000..1b2955e
--- /dev/null
@@ -0,0 +1,18 @@
+# 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 module_0 #alt1-3#
+#alt1#import project1::module_0
+#alt2#import project1::module_01
+#alt3#import project1::module_02
diff --git a/tests/project1/module_0.nit b/tests/project1/module_0.nit
new file mode 100644 (file)
index 0000000..5604c67
--- /dev/null
@@ -0,0 +1,18 @@
+# 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
+
+1.output
+0.output
diff --git a/tests/project1/module_01.nit b/tests/project1/module_01.nit
new file mode 100644 (file)
index 0000000..8499bb9
--- /dev/null
@@ -0,0 +1,15 @@
+# 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 module_0
diff --git a/tests/project1/module_02.nit b/tests/project1/module_02.nit
new file mode 100644 (file)
index 0000000..58207a5
--- /dev/null
@@ -0,0 +1,15 @@
+# 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 ::module_0
diff --git a/tests/project1/subdir/module_0.nit b/tests/project1/subdir/module_0.nit
new file mode 100644 (file)
index 0000000..9c6ed48
--- /dev/null
@@ -0,0 +1,19 @@
+# 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
+
+1.output
+'s'.output
+0.output
diff --git a/tests/sav/base_import2.res b/tests/sav/base_import2.res
new file mode 100644 (file)
index 0000000..573541a
--- /dev/null
@@ -0,0 +1 @@
+0
diff --git a/tests/sav/base_import2_alt1.res b/tests/sav/base_import2_alt1.res
new file mode 100644 (file)
index 0000000..2bac1c7
--- /dev/null
@@ -0,0 +1 @@
+alt/base_import2_alt1.nit:16,8--25: Error: conflicting module files for `module_0`: `./project1/module_0.nit,./project1/subdir/module_0.nit`
diff --git a/tests/sav/base_import2_alt2.res b/tests/sav/base_import2_alt2.res
new file mode 100644 (file)
index 0000000..b261da1
--- /dev/null
@@ -0,0 +1,2 @@
+1
+0
diff --git a/tests/sav/base_import2_alt3.res b/tests/sav/base_import2_alt3.res
new file mode 100644 (file)
index 0000000..573541a
--- /dev/null
@@ -0,0 +1 @@
+0
index f9cc83e..28413fe 100644 (file)
@@ -1 +1 @@
-alt/base_import_alt3.nit:1,8--21: Error: cannot find module `fail` from `project1`. Tried: ., ../lib/core, ../lib/core/collection, alt, ../lib, ../contrib.
+alt/base_import_alt3.nit:18,8--21: Error: cannot find module `fail` from `project1`. Tried: ., ../lib/core, ../lib/core/collection, alt, ../lib, ../contrib.
index d93c6ce..335fcd3 100644 (file)
@@ -1 +1 @@
-alt/base_import_alt5.nit:1,8--25: Error: cannot find module `project2` from `project1`. Tried: ., ../lib/core, ../lib/core/collection, alt, ../lib, ../contrib.
+alt/base_import_alt5.nit:20,8--25: Error: cannot find module `project2` from `project1`. Tried: ., ../lib/core, ../lib/core/collection, alt, ../lib, ../contrib.
diff --git a/tests/sav/base_import_alt6.res b/tests/sav/base_import_alt6.res
new file mode 100644 (file)
index 0000000..9cdbe5b
--- /dev/null
@@ -0,0 +1 @@
+alt/base_import_alt6.nit:21,8--20: Error: cannot find `fail`. Tried: ., ../lib/core, ../lib/core/collection, alt, ../lib, ../contrib.
index b497cd5..19b7801 100644 (file)
@@ -3,7 +3,11 @@ project1 (\e[33mproject1\e[m)
 |--\e[1mmodule1\e[m (\e[33mproject1/module1.nit\e[m)
 |--\e[1mmodule2\e[m (\e[33mproject1/module2.nit\e[m)
 |--\e[1mmodule3\e[m (\e[33mproject1/module3.nit\e[m)
+|--\e[1mmodule_0\e[m (\e[33mproject1/module_0.nit\e[m)
+|--\e[1mmodule_01\e[m (\e[33mproject1/module_01.nit\e[m)
+|--\e[1mmodule_02\e[m (\e[33mproject1/module_02.nit\e[m)
 |--\e[1mproject1\e[m (\e[33mproject1/project1.nit\e[m)
 `--subdir (\e[33mproject1/subdir\e[m)
-   `--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
+   |--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
+   `--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
 \e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
index b497cd5..19b7801 100644 (file)
@@ -3,7 +3,11 @@ project1 (\e[33mproject1\e[m)
 |--\e[1mmodule1\e[m (\e[33mproject1/module1.nit\e[m)
 |--\e[1mmodule2\e[m (\e[33mproject1/module2.nit\e[m)
 |--\e[1mmodule3\e[m (\e[33mproject1/module3.nit\e[m)
+|--\e[1mmodule_0\e[m (\e[33mproject1/module_0.nit\e[m)
+|--\e[1mmodule_01\e[m (\e[33mproject1/module_01.nit\e[m)
+|--\e[1mmodule_02\e[m (\e[33mproject1/module_02.nit\e[m)
 |--\e[1mproject1\e[m (\e[33mproject1/project1.nit\e[m)
 `--subdir (\e[33mproject1/subdir\e[m)
-   `--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
+   |--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
+   `--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
 \e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
index 52b93a0..c5ec486 100644 (file)
@@ -3,9 +3,13 @@ project1 (\e[33mproject1\e[m)
 |--\e[1mmodule1\e[m (\e[33mproject1/module1.nit\e[m)
 |--\e[1mmodule2\e[m (\e[33mproject1/module2.nit\e[m)
 |--\e[1mmodule3\e[m (\e[33mproject1/module3.nit\e[m)
+|--\e[1mmodule_0\e[m (\e[33mproject1/module_0.nit\e[m)
+|--\e[1mmodule_01\e[m (\e[33mproject1/module_01.nit\e[m)
+|--\e[1mmodule_02\e[m (\e[33mproject1/module_02.nit\e[m)
 |--\e[1mproject1\e[m (\e[33mproject1/project1.nit\e[m)
 `--subdir (\e[33mproject1/subdir\e[m)
-   `--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
+   |--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
+   `--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
 project2 (\e[33mproject1/project2\e[m)
 |--\e[1mfoo\e[m (\e[33mproject1/project2/foo.nit\e[m)
 `--\e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
index eeed2c7..a8b51a5 100644 (file)
@@ -3,5 +3,9 @@ project1/\e[1mmodule1\e[m (\e[33mproject1/module1.nit\e[m)
 project1/\e[1mmodule2\e[m (\e[33mproject1/module2.nit\e[m)
 project1/\e[1mmodule3\e[m (\e[33mproject1/module3.nit\e[m)
 project1/subdir/\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
+project1/\e[1mmodule_0\e[m (\e[33mproject1/module_0.nit\e[m)
+project1/subdir/\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
+project1/\e[1mmodule_01\e[m (\e[33mproject1/module_01.nit\e[m)
+project1/\e[1mmodule_02\e[m (\e[33mproject1/module_02.nit\e[m)
 project1/\e[1mproject1\e[m (\e[33mproject1/project1.nit\e[m)
 project2/\e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
index cb5a73d..e69de29 100644 (file)
@@ -1,2 +0,0 @@
-../examples/nitcorn/src/xymus_net.nit:25,8--26: Error: cannot find module `benitlux_controller` from `src`. Tried: alt, ../lib, ../contrib, ../examples.
-../examples/nitcorn/src/xymus_net.nit:26,8--29: Error: cannot find module `opportunity_controller` from `src`. Tried: alt, ../lib, ../contrib, ../examples.