[vala] Support using directives inside namespaces



commit 8ca6708517e07c3d9a25c9352b0b26792ed49e6c
Author: Jürg Billeter <j bitron ch>
Date:   Sat Sep 26 00:38:08 2009 +0200

    Support using directives inside namespaces

 compiler/valacompiler.vala    |    8 +++++-
 vala/valagenieparser.vala     |    1 +
 vala/valamemberaccess.vala    |    6 ++--
 vala/valanamespace.vala       |   20 ++++++++++++++++-
 vala/valaparser.vala          |   22 ++++++++++++++++--
 vala/valasourcefile.vala      |   48 ++++++----------------------------------
 vala/valasourcereference.vala |    7 ++++-
 vala/valasymbolresolver.vala  |   20 +++++++---------
 8 files changed, 70 insertions(+), 62 deletions(-)
---
diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala
index e1cf96b..4f8e31f 100644
--- a/compiler/valacompiler.vala
+++ b/compiler/valacompiler.vala
@@ -273,10 +273,14 @@ class Vala.Compiler {
 
 					if (context.profile == Profile.POSIX) {
 						// import the Posix namespace by default (namespace of backend-specific standard library)
-						source_file.add_using_directive (new UsingDirective (new UnresolvedSymbol (null, "Posix", null)));
+						var ns_ref = new UsingDirective (new UnresolvedSymbol (null, "Posix", null));
+						source_file.add_using_directive (ns_ref);
+						context.root.add_using_directive (ns_ref);
 					} else if (context.profile == Profile.GOBJECT) {
 						// import the GLib namespace by default (namespace of backend-specific standard library)
-						source_file.add_using_directive (new UsingDirective (new UnresolvedSymbol (null, "GLib", null)));
+						var ns_ref = new UsingDirective (new UnresolvedSymbol (null, "GLib", null));
+						source_file.add_using_directive (ns_ref);
+						context.root.add_using_directive (ns_ref);
 					}
 
 					context.add_source_file (source_file);
diff --git a/vala/valagenieparser.vala b/vala/valagenieparser.vala
index 32edf6b..9aa9652 100644
--- a/vala/valagenieparser.vala
+++ b/vala/valagenieparser.vala
@@ -2402,6 +2402,7 @@ public class Vala.Genie.Parser : CodeVisitor {
 		var ns_ref = new UsingDirective (sym, get_src (begin));
 
 		scanner.source_file.add_using_directive (ns_ref);
+		context.root.add_using_directive (ns_ref);
 	}
 
 	void parse_using_directives () throws ParseError {
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 8833d80..af6ca6b 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -254,11 +254,11 @@ public class Vala.MemberAccess : Expression {
 				sym = sym.parent_symbol;
 			}
 
-			if (symbol_reference == null) {
-				foreach (UsingDirective ns in analyzer.current_source_file.get_using_directives ()) {
+			if (symbol_reference == null && source_reference != null) {
+				foreach (UsingDirective ns in source_reference.using_directives) {
 					var local_sym = ns.namespace_symbol.scope.lookup (member_name);
 					if (local_sym != null) {
-						if (symbol_reference != null) {
+						if (symbol_reference != null && symbol_reference != local_sym) {
 							error = true;
 							Report.error (source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (member_name, symbol_reference.get_full_name (), local_sym.get_full_name ()));
 							return false;
diff --git a/vala/valanamespace.vala b/vala/valanamespace.vala
index b7e16aa..aebac89 100644
--- a/vala/valanamespace.vala
+++ b/vala/valanamespace.vala
@@ -46,6 +46,8 @@ public class Vala.Namespace : Symbol {
 
 	private Gee.List<Namespace> namespaces = new ArrayList<Namespace> ();
 
+	private Gee.List<UsingDirective> using_directives = new ArrayList<UsingDirective> ();
+
 	/**
 	 * Creates a new namespace.
 	 *
@@ -57,7 +59,16 @@ public class Vala.Namespace : Symbol {
 		base (name, source_reference);
 		access = SymbolAccessibility.PUBLIC;
 	}
-	
+
+	/**
+	 * Adds a new using directive with the specified namespace.
+	 *
+	 * @param ns reference to namespace
+	 */
+	public void add_using_directive (UsingDirective ns) {
+		using_directives.add (ns);
+	}
+
 	public void add_comment (Comment comment) {
 		comments.add (comment);
 	}
@@ -84,6 +95,9 @@ public class Vala.Namespace : Symbol {
 				old_ns.source_reference = ns.source_reference;
 			}
 
+			foreach (var using_directive in ns.using_directives) {
+				old_ns.add_using_directive (using_directive);
+			}
 			foreach (Namespace sub_ns in ns.get_namespaces ()) {
 				old_ns.add_namespace (sub_ns);
 			}
@@ -392,6 +406,10 @@ public class Vala.Namespace : Symbol {
 	}
 
 	public override void accept_children (CodeVisitor visitor) {
+		foreach (UsingDirective ns_ref in using_directives) {
+			ns_ref.accept (visitor);
+		}
+
 		foreach (Namespace ns in namespaces) {
 			ns.accept (visitor);
 		}
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 962ff4c..e9add95 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -310,7 +310,7 @@ public class Vala.Parser : CodeVisitor {
 
 
 		try {
-			parse_using_directives ();
+			parse_using_directives (context.root);
 			parse_declarations (context.root, true);
 		} catch (ParseError e) {
 			// already reported
@@ -1964,7 +1964,22 @@ public class Vala.Parser : CodeVisitor {
 		}
 
 		set_attributes (ns, attrs);
-		parse_declarations (ns);
+
+		expect (TokenType.OPEN_BRACE);
+
+		var old_using_directives = scanner.source_file.current_using_directives;
+		parse_using_directives (ns);
+
+		parse_declarations (ns, true);
+
+		scanner.source_file.current_using_directives = old_using_directives;
+
+		if (!accept (TokenType.CLOSE_BRACE)) {
+			// only report error if it's not a secondary error
+			if (context.report.get_errors () == 0) {
+				Report.error (get_current_src (), "expected `}'");
+			}
+		}
 
 		Namespace result = ns;
 		while (sym.inner != null) {
@@ -2015,13 +2030,14 @@ public class Vala.Parser : CodeVisitor {
 		scanner.source_file.add_node (sym);
 	}
 
-	void parse_using_directives () throws ParseError {
+	void parse_using_directives (Namespace ns) throws ParseError {
 		while (accept (TokenType.USING)) {
 			do {
 				var begin = get_location ();
 				var sym = parse_symbol_name ();
 				var ns_ref = new UsingDirective (sym, get_src (begin));
 				scanner.source_file.add_using_directive (ns_ref);
+				ns.add_using_directive (ns_ref);
 			} while (accept (TokenType.COMMA));
 			expect (TokenType.SEMICOLON);
 		}
diff --git a/vala/valasourcefile.vala b/vala/valasourcefile.vala
index ee3d281..ab6d570 100644
--- a/vala/valasourcefile.vala
+++ b/vala/valasourcefile.vala
@@ -53,7 +53,7 @@ public class Vala.SourceFile {
 
 	private ArrayList<Comment> comments = new ArrayList<Comment> ();
 
-	private Gee.List<UsingDirective> using_directives = new ArrayList<UsingDirective> ();
+	public Gee.List<UsingDirective> current_using_directives { get; set; default = new ArrayList<UsingDirective> (); }
 
 	private Gee.List<CodeNode> nodes = new ArrayList<CodeNode> ();
 	
@@ -102,45 +102,17 @@ public class Vala.SourceFile {
 	 * @param ns reference to namespace
 	 */
 	public void add_using_directive (UsingDirective ns) {
-		foreach (UsingDirective using_directive in using_directives) {
-			if (same_symbol (using_directive.namespace_symbol, ns.namespace_symbol)) {
-				// ignore duplicates
-				return;
-			}
-		}
-		using_directives.add (ns);
-	}
-
-	public void clear_using_directives () {
-		using_directives.clear ();
-	}
-
-	bool same_symbol (Symbol? sym1, Symbol? sym2) {
-		if (sym1 == sym2) {
-			return true;
-		}
-
-		var unresolved_symbol1 = sym1 as UnresolvedSymbol;
-		var unresolved_symbol2 = sym2 as UnresolvedSymbol;
-		if (unresolved_symbol1 != null && unresolved_symbol2 != null) {
-			if (same_symbol (unresolved_symbol1.inner, unresolved_symbol2.inner)) {
-				return (unresolved_symbol1.name == unresolved_symbol2.name);
-			}
+		// do not modify current_using_directives, it should be considered immutable
+		// for correct symbol resolving
+		var old_using_directives = current_using_directives;
+		current_using_directives = new ArrayList<UsingDirective> ();
+		foreach (var using_directive in old_using_directives) {
+			current_using_directives.add (using_directive);
 		}
-
-		return false;
+		current_using_directives.add (ns);
 	}
 
 	/**
-	 * Returns a copy of the list of using directives.
-	 *
-	 * @return using directive list
-	 */
-	public Gee.List<UsingDirective> get_using_directives () {
-		return new ReadOnlyList<UsingDirective> (using_directives);
-	}
-	
-	/**
 	 * Adds the specified code node to this source file.
 	 *
 	 * @param node a code node
@@ -167,10 +139,6 @@ public class Vala.SourceFile {
 	}
 
 	public void accept_children (CodeVisitor visitor) {
-		foreach (UsingDirective ns_ref in using_directives) {
-			ns_ref.accept (visitor);
-		}
-		
 		foreach (CodeNode node in nodes) {
 			node.accept (visitor);
 		}
diff --git a/vala/valasourcereference.vala b/vala/valasourcereference.vala
index 4afe4d8..7675977 100644
--- a/vala/valasourcereference.vala
+++ b/vala/valasourcereference.vala
@@ -1,6 +1,6 @@
 /* valasourcereference.vala
  *
- * Copyright (C) 2006-2008  Jürg Billeter
+ * Copyright (C) 2006-2009  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -50,7 +50,9 @@ public class Vala.SourceReference {
 	 * The last column number of the referenced source code.
 	 */
 	public int last_column { get; set; }
-	
+
+	public Gee.List<UsingDirective> using_directives { get; private set; }
+
 	/**
 	 * Creates a new source reference.
 	 *
@@ -67,6 +69,7 @@ public class Vala.SourceReference {
 		first_column = _first_column;
 		last_line = _last_line;
 		last_column = _last_column;
+		using_directives = file.current_using_directives;
 	}
 	
 	/**
diff --git a/vala/valasymbolresolver.vala b/vala/valasymbolresolver.vala
index 24612f1..213bd53 100644
--- a/vala/valasymbolresolver.vala
+++ b/vala/valasymbolresolver.vala
@@ -31,7 +31,6 @@ using Gee;
 public class Vala.SymbolResolver : CodeVisitor {
 	Symbol root_symbol;
 	Scope current_scope;
-	Gee.List<UsingDirective> current_using_directives;
 	
 	/**
 	 * Resolve symbol names in the specified code context.
@@ -40,18 +39,17 @@ public class Vala.SymbolResolver : CodeVisitor {
 	 */
 	public void resolve (CodeContext context) {
 		root_symbol = context.root;
-		current_scope = root_symbol.scope;
 
-		context.accept (this);
+		context.root.accept (this);
 	}
 	
-	public override void visit_source_file (SourceFile file) {
-		current_using_directives = file.get_using_directives ();
-		current_scope = root_symbol.scope;
+	public override void visit_namespace (Namespace ns) {
+		var old_scope = current_scope;
+		current_scope = ns.scope;
 
-		file.accept_children (this);
+		ns.accept_children (this);
 
-		current_using_directives = null;
+		current_scope = old_scope;
 	}
 	
 	public override void visit_class (Class cl) {
@@ -220,8 +218,8 @@ public class Vala.SymbolResolver : CodeVisitor {
 
 				scope = scope.parent_scope;
 			}
-			if (sym == null) {
-				foreach (UsingDirective ns in current_using_directives) {
+			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) {
 						continue;
 					}
@@ -234,7 +232,7 @@ public class Vala.SymbolResolver : CodeVisitor {
 					}
 
 					if (local_sym != null) {
-						if (sym != null) {
+						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;



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