Commit 8ca67085 authored by Jürg Billeter's avatar Jürg Billeter

Support using directives inside namespaces

parent 08f7f39b
......@@ -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);
......
......@@ -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 {
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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,44 +102,16 @@ 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.
*
......@@ -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);
}
......
/* 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;
}
/**
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment