Merge: Correct detection of property name conflicts
authorJean Privat <jean@pryen.org>
Mon, 14 Apr 2014 12:57:55 +0000 (08:57 -0400)
committerJean Privat <jean@pryen.org>
Mon, 14 Apr 2014 12:57:55 +0000 (08:57 -0400)
Fixes #395
Pull-Request: #398

12 files changed:
src/modelbuilder.nit
tests/error_prop_name.nit [new file with mode: 0644]
tests/error_prop_name_m1.nit [new file with mode: 0644]
tests/error_prop_name_m2.nit [new file with mode: 0644]
tests/sav/base_virtual_type_redef.res
tests/sav/error_prop_name.res [new file with mode: 0644]
tests/sav/error_prop_name_alt1.res [new file with mode: 0644]
tests/sav/error_prop_name_alt2.res [new file with mode: 0644]
tests/sav/error_prop_name_alt3.res [new file with mode: 0644]
tests/sav/error_prop_name_alt4.res [new file with mode: 0644]
tests/sav/error_prop_name_m1.res [new file with mode: 0644]
tests/sav/error_prop_name_m2.res [new file with mode: 0644]

index 1db6a04..9492734 100644 (file)
@@ -224,28 +224,55 @@ class ModelBuilder
                        if not mmodule.is_visible(mprop.intro_mclassdef.mmodule, mprop.visibility) then continue
                        if res == null then
                                res = mprop
-                       else
+                               continue
+                       end
+
+                       # Two global properties?
+                       # First, special case for init, keep the most specific ones
+                       if res isa MMethod and mprop isa MMethod and res.is_init and mprop.is_init then
                                var restype = res.intro_mclassdef.bound_mtype
                                var mproptype = mprop.intro_mclassdef.bound_mtype
-                               if restype.is_subtype(mmodule, null, mproptype) then
-                                       # we keep res
-                               else if mproptype.is_subtype(mmodule, null, restype) then
+                               if mproptype.is_subtype(mmodule, null, restype) then
+                                       # found a most specific constructor, so keep it
                                        res = mprop
-                               else
-                                       if ress == null then ress = new Array[MProperty]
-                                       ress.add(mprop)
+                                       continue
                                end
                        end
+
+                       # Ok, just keep all prop in the ress table
+                       if ress == null then
+                               ress = new Array[MProperty]
+                               ress.add(res)
+                       end
+                       ress.add(mprop)
                end
-               if ress != null then
+
+               # There is conflict?
+               if ress != null and res isa MMethod and res.is_init then
+                       # special case forinit again
                        var restype = res.intro_mclassdef.bound_mtype
+                       var ress2 = new Array[MProperty]
                        for mprop in ress do
                                var mproptype = mprop.intro_mclassdef.bound_mtype
                                if not restype.is_subtype(mmodule, null, mproptype) then
-                                       self.error(anode, "Ambigous property name '{name}' for {mtype}; conflict between {mprop.full_name} and {res.full_name}")
-                                       return null
+                                       ress2.add(mprop)
+                               else if not mprop isa MMethod or not mprop.is_init then
+                                       ress2.add(mprop)
                                end
                        end
+                       if ress2.is_empty then
+                               ress = null
+                       else
+                               ress = ress2
+                               ress.add(res)
+                       end
+               end
+
+               if ress != null then
+                       assert ress.length > 1
+                       var s = new Array[String]
+                       for mprop in ress do s.add mprop.full_name
+                       self.error(anode, "Ambigous property name '{name}' for {mtype}; conflict between {s.join(" and ")}")
                end
 
                self.try_get_mproperty_by_name2_cache[mmodule, mtype, name] = res
diff --git a/tests/error_prop_name.nit b/tests/error_prop_name.nit
new file mode 100644 (file)
index 0000000..0af0a77
--- /dev/null
@@ -0,0 +1,37 @@
+# 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 error_prop_name_m1
+import error_prop_name_m2
+
+class C
+       fun bar do 4.output
+       fun bar_c do bar
+end
+
+redef class A
+       super B
+       super C
+
+       #alt3#redef fun foo do 5.output
+       #alt4#redef fun bar do 6.output
+end
+
+var a = new A
+a.foo_a
+a.foo_b
+#alt1#a.foo
+a.bar_a
+a.bar_c
+#alt2#a.bar
diff --git a/tests/error_prop_name_m1.nit b/tests/error_prop_name_m1.nit
new file mode 100644 (file)
index 0000000..d1f1fa0
--- /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.
+
+import kernel
+
+class A
+       fun foo do 1.output
+       fun foo_a do foo
+
+       fun bar do 2.output
+       fun bar_a do bar
+end
diff --git a/tests/error_prop_name_m2.nit b/tests/error_prop_name_m2.nit
new file mode 100644 (file)
index 0000000..a29202c
--- /dev/null
@@ -0,0 +1,20 @@
+# 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 B
+       fun foo do 3.output
+       fun foo_b do foo
+end
index 0a956f4..a5ebee7 100644 (file)
@@ -1,2 +1 @@
-base_virtual_type_redef.nit:24,13--17: Ambigous property name 'OTHER' for Int; conflict between base_virtual_type_redef::Number::OTHER and standard::kernel::Comparable::OTHER
-base_virtual_type_redef.nit:24,2--22: Error: No property Int::OTHER is inherited. Remove the redef keyword to define a new property.
+base_virtual_type_redef.nit:24,13--17: Ambigous property name 'OTHER' for Int; conflict between standard::kernel::Comparable::OTHER and base_virtual_type_redef::Number::OTHER
diff --git a/tests/sav/error_prop_name.res b/tests/sav/error_prop_name.res
new file mode 100644 (file)
index 0000000..6a1a6aa
--- /dev/null
@@ -0,0 +1,4 @@
+1
+3
+2
+4
diff --git a/tests/sav/error_prop_name_alt1.res b/tests/sav/error_prop_name_alt1.res
new file mode 100644 (file)
index 0000000..f7f0ccf
--- /dev/null
@@ -0,0 +1 @@
+alt/error_prop_name_alt1.nit:34,1--5: Ambigous property name 'foo' for A; conflict between error_prop_name_m1::A::foo and error_prop_name_m2::B::foo
diff --git a/tests/sav/error_prop_name_alt2.res b/tests/sav/error_prop_name_alt2.res
new file mode 100644 (file)
index 0000000..80410f3
--- /dev/null
@@ -0,0 +1 @@
+alt/error_prop_name_alt2.nit:37,1--5: Ambigous property name 'bar' for A; conflict between error_prop_name_m1::A::bar and error_prop_name_alt2::C::bar
diff --git a/tests/sav/error_prop_name_alt3.res b/tests/sav/error_prop_name_alt3.res
new file mode 100644 (file)
index 0000000..b21c3cb
--- /dev/null
@@ -0,0 +1 @@
+alt/error_prop_name_alt3.nit:27,12--14: Ambigous property name 'foo' for A; conflict between error_prop_name_m1::A::foo and error_prop_name_m2::B::foo
diff --git a/tests/sav/error_prop_name_alt4.res b/tests/sav/error_prop_name_alt4.res
new file mode 100644 (file)
index 0000000..1f9c04f
--- /dev/null
@@ -0,0 +1 @@
+alt/error_prop_name_alt4.nit:28,12--14: Ambigous property name 'bar' for A; conflict between error_prop_name_m1::A::bar and error_prop_name_alt4::C::bar
diff --git a/tests/sav/error_prop_name_m1.res b/tests/sav/error_prop_name_m1.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/error_prop_name_m2.res b/tests/sav/error_prop_name_m2.res
new file mode 100644 (file)
index 0000000..e69de29