[vala/staging: 2/2] vala: Use inheritted scopes of base-types/prerequisites to resolve symbols



commit 244b69cc5386b6707d603ea5a437ae3f02952c58
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Wed Jul 15 17:46:58 2020 +0200

    vala: Use inheritted scopes of base-types/prerequisites to resolve symbols
    
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/54

 tests/Makefile.am                              |  2 ++
 tests/resolver/peek-inner-types-ambiguous.test | 34 ++++++++++++++++++++
 tests/resolver/peek-inner-types.vala           | 42 +++++++++++++++++++++++++
 vala/valasymbolresolver.vala                   | 43 ++++++++++++++++++++++++++
 4 files changed, 121 insertions(+)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 42cad8968..6d9e32ebe 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 000000000..1a6108cc9
--- /dev/null
+++ b/tests/resolver/peek-inner-types-ambiguous.test
@@ -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
index 000000000..1c9ef8639
--- /dev/null
+++ b/tests/resolver/peek-inner-types.vala
@@ -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 ();
+}
diff --git a/vala/valasymbolresolver.vala b/vala/valasymbolresolver.vala
index 28365127a..3f9bc6de0 100644
--- a/vala/valasymbolresolver.vala
+++ b/vala/valasymbolresolver.vala
@@ -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) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]