]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Use inheritted scopes of base-types/prerequisites to resolve symbols
authorRico Tzschichholz <ricotz@ubuntu.com>
Wed, 15 Jul 2020 15:46:58 +0000 (17:46 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 15 Jul 2020 16:58:43 +0000 (18:58 +0200)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/54

tests/Makefile.am
tests/resolver/peek-inner-types-ambiguous.test [new file with mode: 0644]
tests/resolver/peek-inner-types.vala [new file with mode: 0644]
vala/valasymbolresolver.vala

index 42cad8968910882f5c661d1533656e4c84f72607..6d9e32ebe4878bd16487509415a4614394ec8c9e 100644 (file)
@@ -765,6 +765,8 @@ TESTS = \
        parser/bug749576.vala \
        resolver/class-base-cycle.test \
        resolver/interface-prerequisite-cycle.test \
+       resolver/peek-inner-types-ambiguous.test \
+       resolver/peek-inner-types.vala \
        resolver/struct-base-cycle.test \
        ordering/delegate-class.vala \
        ordering/delegate-enum.vala \
diff --git a/tests/resolver/peek-inner-types-ambiguous.test b/tests/resolver/peek-inner-types-ambiguous.test
new file mode 100644 (file)
index 0000000..1a6108c
--- /dev/null
@@ -0,0 +1,34 @@
+Invalid Code
+
+namespace Baz {
+       public class Foo {
+               public class Bar {
+               }
+
+               public interface IBar : Bar {
+               }
+       }
+       public interface IFoo : Foo {
+               public class Bar {
+               }
+
+               public interface IBar : Bar {
+               }
+       }
+}
+
+class Manam : Baz.Foo, Baz.IFoo {
+       public Bar? foo () {
+               return null;
+       }
+
+       public IBar? ifoo () {
+               return null;
+       }
+}
+
+void main () {
+       var manam = new Manam ();
+       manam.foo ();
+       manam.ifoo ();
+}
diff --git a/tests/resolver/peek-inner-types.vala b/tests/resolver/peek-inner-types.vala
new file mode 100644 (file)
index 0000000..1c9ef86
--- /dev/null
@@ -0,0 +1,42 @@
+namespace Baz {
+       public class Foo {
+               public class Bar1 {
+               }
+
+               public interface IBar1 : Bar1 {
+               }
+       }
+       public interface IFoo : Foo {
+               public class Bar2 {
+               }
+
+               public interface IBar2 : Bar2 {
+               }
+       }
+}
+
+class Manam : Baz.Foo, Baz.IFoo {
+       public Bar1? foo1 () {
+               return null;
+       }
+
+       public IBar1? ifoo1 () {
+               return null;
+       }
+
+       public Bar2? foo2 () {
+               return null;
+       }
+
+       public IBar2? ifoo2 () {
+               return null;
+       }
+}
+
+void main () {
+       var manam = new Manam ();
+       manam.foo1 ();
+       manam.ifoo1 ();
+       manam.foo2 ();
+       manam.ifoo2 ();
+}
index 28365127a89161875f1947d9756572b1c1ad275b..3f9bc6de00a370928b8cfd9c54294d4f2e5d9a94 100644 (file)
@@ -286,6 +286,49 @@ public class Vala.SymbolResolver : CodeVisitor {
 
                                scope = scope.parent_scope;
                        }
+                       // Look for matches in inner types of base-types/prerequisites
+                       ObjectTypeSymbol? current_symbol = null;
+                       if (sym == null) {
+                               scope = current_scope;
+                               while (scope != null) {
+                                       if (scope.owner is ObjectTypeSymbol) {
+                                               current_symbol = (ObjectTypeSymbol) scope.owner;
+                                               break;
+                                       }
+                                       scope = scope.parent_scope;
+                               }
+                       }
+                       if (current_symbol != null) {
+                               unowned List<DataType> types;
+                               if (current_symbol is Class) {
+                                       types = ((Class) current_symbol).get_base_types ();
+                               } else if (current_symbol is Interface) {
+                                       types = ((Interface) current_symbol).get_prerequisites ();
+                               } else {
+                                       assert_not_reached ();
+                               }
+                               foreach (DataType type in types) {
+                                       if (type.type_symbol == null) {
+                                               continue;
+                                       }
+
+                                       var local_sym = SemanticAnalyzer.symbol_lookup_inherited (type.type_symbol, unresolved_symbol.name);
+
+                                       // only look for types and type containers
+                                       if (!(local_sym is Namespace || local_sym is TypeSymbol)) {
+                                               local_sym = null;
+                                       }
+
+                                       if (local_sym != null && local_sym.access == SymbolAccessibility.PUBLIC) {
+                                               if (sym != null && sym != local_sym) {
+                                                       unresolved_symbol.error = true;
+                                                       Report.error (unresolved_symbol.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (unresolved_symbol.name, sym.get_full_name (), local_sym.get_full_name ()));
+                                                       return null;
+                                               }
+                                               sym = local_sym;
+                                       }
+                               }
+                       }
                        if (sym == null && unresolved_symbol.source_reference != null) {
                                foreach (UsingDirective ns in unresolved_symbol.source_reference.using_directives) {
                                        if (ns.error || ns.namespace_symbol is UnresolvedSymbol) {