Skip to content

Commit 6832f75

Browse files
committed
Support attaching attributes to modules via the crate file. Issue #487
1 parent 74f8eb5 commit 6832f75

File tree

8 files changed

+66
-42
lines changed

8 files changed

+66
-42
lines changed

src/comp/front/ast.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ tag crate_directive_ {
8989
// and redirected to the use of const stmt_decls inside
9090
// crate directive blocks.
9191
cdir_let(ident, @expr, vec[@crate_directive]);
92-
cdir_src_mod(ident, option::t[filename]);
93-
cdir_dir_mod(ident, option::t[filename], vec[@crate_directive]);
92+
cdir_src_mod(ident, option::t[filename], vec[attribute]);
93+
cdir_dir_mod(ident, option::t[filename],
94+
vec[@crate_directive], vec[attribute]);
9495
cdir_view_item(@view_item);
9596
cdir_syntax(path);
9697
cdir_auth(path, _auth);

src/comp/front/eval.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ fn eval_crate_directive(ctx cx, env e, @ast::crate_directive cdir, str prefix,
279279
case (ast::cdir_expr(?x)) {
280280
eval_crate_directive_expr(cx, e, x, prefix, view_items, items);
281281
}
282-
case (ast::cdir_src_mod(?id, ?file_opt)) {
282+
case (ast::cdir_src_mod(?id, ?file_opt, ?attrs)) {
283283
auto file_path = id + ".rs";
284284
alt (file_opt) {
285285
case (some(?f)) { file_path = f; }
@@ -291,23 +291,25 @@ fn eval_crate_directive(ctx cx, env e, @ast::crate_directive cdir, str prefix,
291291
new_parser(cx.sess, e, full_path, cx.chpos,
292292
cx.next_id);
293293
auto inner_attrs = parse_inner_attrs_and_next(p0);
294+
auto mod_attrs = attrs + inner_attrs._0;
294295
auto first_item_outer_attrs = inner_attrs._1;
295296
auto m0 = parse_mod_items(p0, token::EOF, first_item_outer_attrs);
296297

297298
auto i = front::parser::mk_item(p0, cdir.span.lo, cdir.span.hi,
298-
id, ast::item_mod(m0), []);
299+
id, ast::item_mod(m0),
300+
mod_attrs);
299301
// Thread defids and chpos through the parsers
300302
cx.chpos = p0.get_chpos();
301303
cx.next_id = p0.next_id();
302304
vec::push[@ast::item](items, i);
303305
}
304-
case (ast::cdir_dir_mod(?id, ?dir_opt, ?cdirs)) {
306+
case (ast::cdir_dir_mod(?id, ?dir_opt, ?cdirs, ?attrs)) {
305307
auto path = id;
306308
alt (dir_opt) { case (some(?d)) { path = d; } case (none) { } }
307309
auto full_path = prefix + std::fs::path_sep() + path;
308310
auto m0 = eval_crate_directives_to_mod(cx, e, cdirs, full_path);
309311
auto i = @rec(ident=id,
310-
attrs=[],
312+
attrs=attrs,
311313
id=cx.next_id,
312314
node=ast::item_mod(m0),
313315
span=cdir.span);

src/comp/front/fold.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,12 @@ fn noop_fold_crate_directive(&crate_directive_ cd, ast_fold fld)
143143
cdir_let(fld.fold_ident(id), fld.fold_expr(e),
144144
map(fld.fold_crate_directive, cds))
145145
}
146-
case(cdir_src_mod(?id,?fname)) {
147-
cdir_src_mod(fld.fold_ident(id), fname)
146+
case(cdir_src_mod(?id,?fname,?attrs)) {
147+
cdir_src_mod(fld.fold_ident(id), fname, attrs)
148148
}
149-
case(cdir_dir_mod(?id,?fname,?cds)) {
149+
case(cdir_dir_mod(?id,?fname,?cds,?attrs)) {
150150
cdir_dir_mod(fld.fold_ident(id),fname,
151-
map(fld.fold_crate_directive, cds))
151+
map(fld.fold_crate_directive, cds), attrs)
152152
}
153153
case(cdir_view_item(?vi)) {
154154
cdir_view_item(fld.fold_view_item(vi))

src/comp/front/parser.rs

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,7 +1488,7 @@ fn parse_stmt(&parser p) -> @ast::stmt {
14881488
}
14891489

14901490
fn parse_crate_stmt(&parser p) -> @ast::stmt {
1491-
auto cdir = parse_crate_directive(p);
1491+
auto cdir = parse_crate_directive(p, []);
14921492
ret @spanned(cdir.span.lo, cdir.span.hi,
14931493
ast::stmt_crate_directive(@cdir));
14941494
}
@@ -2141,15 +2141,6 @@ fn parse_inner_attrs_and_next(&parser p) -> tup(vec[ast::attribute],
21412141
ret tup(inner_attrs, next_outer_attrs);
21422142
}
21432143

2144-
fn parse_inner_attrs(&parser p) -> vec[ast::attribute] {
2145-
auto attrs_and_next = parse_inner_attrs_and_next(p);
2146-
if (vec::len(attrs_and_next._1) > 0u) {
2147-
ret p.fatal("expected crate directive but found " +
2148-
token::to_str(p.get_reader(), p.peek()));
2149-
}
2150-
ret attrs_and_next._0;
2151-
}
2152-
21532144
fn parse_meta_item(&parser p) -> @ast::meta_item {
21542145
auto lo = p.get_lo_pos();
21552146
auto ident = parse_ident(p);
@@ -2350,16 +2341,18 @@ fn parse_str(&parser p) -> ast::ident {
23502341
// Each crate file is a sequence of directives.
23512342
//
23522343
// Each directive imperatively extends its environment with 0 or more items.
2353-
fn parse_crate_directive(&parser p) -> ast::crate_directive {
2344+
fn parse_crate_directive(&parser p, vec[ast::attribute] first_outer_attr)
2345+
-> ast::crate_directive {
2346+
2347+
// Collect the next attributes
2348+
auto outer_attrs = first_outer_attr
2349+
+ parse_outer_attributes(p);
2350+
// In a crate file outer attributes are only going to apply to mods
2351+
auto expect_mod = vec::len(outer_attrs) > 0u;
2352+
23542353
auto lo = p.get_lo_pos();
2355-
if (eat_word(p, "auth")) {
2356-
auto n = parse_path(p);
2357-
expect(p, token::EQ);
2358-
auto a = parse_auth(p);
2359-
auto hi = p.get_hi_pos();
2360-
expect(p, token::SEMI);
2361-
ret spanned(lo, hi, ast::cdir_auth(n, a));
2362-
} else if (eat_word(p, "mod")) {
2354+
if (expect_mod || is_word(p, "mod")) {
2355+
expect_word(p, "mod");
23632356
auto id = parse_ident(p);
23642357
auto file_opt =
23652358
alt (p.peek()) {
@@ -2375,27 +2368,40 @@ fn parse_crate_directive(&parser p) -> ast::crate_directive {
23752368
token::SEMI) {
23762369
auto hi = p.get_hi_pos();
23772370
p.bump();
2378-
ret spanned(lo, hi, ast::cdir_src_mod(id, file_opt));
2371+
ret spanned(lo, hi, ast::cdir_src_mod(id, file_opt,
2372+
outer_attrs));
23792373
}
23802374
case (
23812375
// mod x = "foo_dir" { ...directives... }
23822376
token::LBRACE) {
23832377
p.bump();
2384-
auto cdirs = parse_crate_directives(p, token::RBRACE);
2378+
auto inner_attrs = parse_inner_attrs_and_next(p);
2379+
auto mod_attrs = outer_attrs + inner_attrs._0;
2380+
auto next_outer_attr = inner_attrs._1;
2381+
auto cdirs = parse_crate_directives(p, token::RBRACE,
2382+
next_outer_attr);
23852383
auto hi = p.get_hi_pos();
23862384
expect(p, token::RBRACE);
2387-
ret spanned(lo, hi, ast::cdir_dir_mod(id, file_opt, cdirs));
2385+
ret spanned(lo, hi, ast::cdir_dir_mod(id, file_opt, cdirs,
2386+
mod_attrs));
23882387
}
23892388
case (?t) { unexpected(p, t); }
23902389
}
2390+
} else if (eat_word(p, "auth")) {
2391+
auto n = parse_path(p);
2392+
expect(p, token::EQ);
2393+
auto a = parse_auth(p);
2394+
auto hi = p.get_hi_pos();
2395+
expect(p, token::SEMI);
2396+
ret spanned(lo, hi, ast::cdir_auth(n, a));
23912397
} else if (eat_word(p, "let")) {
23922398
expect(p, token::LPAREN);
23932399
auto id = parse_value_ident(p);
23942400
expect(p, token::EQ);
23952401
auto x = parse_expr(p);
23962402
expect(p, token::RPAREN);
23972403
expect(p, token::LBRACE);
2398-
auto v = parse_crate_directives(p, token::RBRACE);
2404+
auto v = parse_crate_directives(p, token::RBRACE, []);
23992405
auto hi = p.get_hi_pos();
24002406
expect(p, token::RBRACE);
24012407
ret spanned(lo, hi, ast::cdir_let(id, x, v));
@@ -2409,11 +2415,20 @@ fn parse_crate_directive(&parser p) -> ast::crate_directive {
24092415
fail;
24102416
}
24112417

2412-
fn parse_crate_directives(&parser p, token::token term) ->
2418+
fn parse_crate_directives(&parser p, token::token term,
2419+
vec[ast::attribute] first_outer_attr) ->
24132420
vec[@ast::crate_directive] {
2421+
2422+
// This is pretty ugly. If we have an outer attribute then we can't accept
2423+
// seeing the terminator next, so if we do see it then fail the same way
2424+
// parse_crate_directive would
2425+
if (vec::len(first_outer_attr) > 0u && p.peek() == term) {
2426+
expect_word(p, "mod");
2427+
}
2428+
24142429
let vec[@ast::crate_directive] cdirs = [];
24152430
while (p.peek() != term) {
2416-
auto cdir = @parse_crate_directive(p);
2431+
auto cdir = @parse_crate_directive(p, first_outer_attr);
24172432
vec::push(cdirs, cdir);
24182433
}
24192434
ret cdirs;
@@ -2422,8 +2437,10 @@ fn parse_crate_directives(&parser p, token::token term) ->
24222437
fn parse_crate_from_crate_file(&parser p) -> @ast::crate {
24232438
auto lo = p.get_lo_pos();
24242439
auto prefix = std::fs::dirname(p.get_filemap().name);
2425-
auto crate_attrs = parse_inner_attrs(p);
2426-
auto cdirs = parse_crate_directives(p, token::EOF);
2440+
auto leading_attrs = parse_inner_attrs_and_next(p);
2441+
auto crate_attrs = leading_attrs._0;
2442+
auto first_cdir_attr = leading_attrs._1;
2443+
auto cdirs = parse_crate_directives(p, token::EOF, first_cdir_attr);
24272444
let vec[str] deps = [];
24282445
auto cx =
24292446
@rec(p=p,

src/comp/middle/visit.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ fn visit_crate_directive[E](&@crate_directive cd, &E e, &vt[E] v) {
6666
visit_crate_directive(cdir, e, v);
6767
}
6868
}
69-
case (cdir_src_mod(_, _)) { }
70-
case (cdir_dir_mod(_, _, ?cdirs)) {
69+
case (cdir_src_mod(_, _, _)) { }
70+
case (cdir_dir_mod(_, _, ?cdirs, _)) {
7171
for (@crate_directive cdir in cdirs) {
7272
visit_crate_directive(cdir, e, v);
7373
}

src/comp/middle/walk.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ fn walk_crate_directive(&ast_visitor v, @ast::crate_directive cd) {
5959
walk_crate_directive(v, cdir);
6060
}
6161
}
62-
case (ast::cdir_src_mod(_, _)) { }
63-
case (ast::cdir_dir_mod(_, _, ?cdirs)) {
62+
case (ast::cdir_src_mod(_, _, _)) { }
63+
case (ast::cdir_dir_mod(_, _, ?cdirs, _)) {
6464
for (@ast::crate_directive cdir in cdirs) {
6565
walk_crate_directive(v, cdir);
6666
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// xfail-stage0
2-
// error-pattern: expected crate directive
2+
// error-pattern: expecting mod
33

44
#[attr = "val"];
55
#[attr = "val"] // Unterminated

src/test/run-pass/crate-attributes.rc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#[name = "crate-attributes"];
22
#[vers = "1.0"];
33

4+
#[attr1]
45
mod m = "crate-attributes-src" {
6+
#[attr_inner];
7+
8+
#[attr2]
59
mod foo;
610
}

0 commit comments

Comments
 (0)