From 4026053e99b6554bd7d996839e04dfeb9d40aa4d Mon Sep 17 00:00:00 2001 From: Kevin Atkinson Date: Fri, 10 Feb 2012 11:28:43 -0700 Subject: [PATCH] Do a better job of reporting source location for files (i.e. filemap) that are really a substr of another file. --- src/comp/driver/diagnostic.rs | 1 + src/comp/syntax/codemap.rs | 46 +++++++++++++++++++++++++++-- src/test/compile-fail/qquote.rs | 51 +++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/qquote.rs diff --git a/src/comp/driver/diagnostic.rs b/src/comp/driver/diagnostic.rs index ebda3956bfd41..6bc5f91a16a09 100644 --- a/src/comp/driver/diagnostic.rs +++ b/src/comp/driver/diagnostic.rs @@ -175,6 +175,7 @@ fn emit(cmsp: option<(codemap::codemap, span)>, msg: str, lvl: level) { alt cmsp { some((cm, sp)) { + let sp = codemap::adjust_span(cm,sp); let ss = codemap::span_to_str(sp, cm); let lines = codemap::span_to_lines(sp, cm); print_diagnostic(ss, lvl, msg); diff --git a/src/comp/syntax/codemap.rs b/src/comp/syntax/codemap.rs index 963f3d02573dc..3f848cc893ce7 100644 --- a/src/comp/syntax/codemap.rs +++ b/src/comp/syntax/codemap.rs @@ -46,6 +46,8 @@ fn get_substr_info(cm: codemap, sp: span) let pos = lookup_char_pos(cm, sp.lo); let name = #fmt("<%s:%u:%u>", pos.file.name, pos.line, pos.col); ret (name, fss_internal(sp)); + //ret (name, fss_external({filename: pos.file.name, + // line: pos.line, col: pos.col})); } fn next_line(file: filemap, chpos: uint, byte_pos: uint) { @@ -92,6 +94,40 @@ fn lookup_byte_pos(map: codemap, pos: uint) -> loc { ret lookup_pos(map, pos, lookup); } +fn lookup_char_pos_adj(map: codemap, pos: uint) + -> {filename: str, line: uint, col: uint, file: option} +{ + let loc = lookup_char_pos(map, pos); + alt (loc.file.substr) { + fss_none { + {filename: loc.file.name, line: loc.line, col: loc.col, + file: some(loc.file)} + } + fss_internal(sp) { + lookup_char_pos_adj(map, sp.lo + (pos - loc.file.start_pos.ch)) + } + fss_external(eloc) { + {filename: eloc.filename, + line: eloc.line + loc.line - 1u, + col: if loc.line == 1u {eloc.col + loc.col} else {loc.col}, + file: none} + } + } +} + +fn adjust_span(map: codemap, sp: span) -> span { + fn lookup(pos: file_pos) -> uint { ret pos.ch; } + let line = lookup_line(map, sp.lo, lookup); + alt (line.fm.substr) { + fss_none {sp} + fss_internal(s) { + adjust_span(map, {lo: s.lo + (sp.lo - line.fm.start_pos.ch), + hi: s.lo + (sp.hi - line.fm.start_pos.ch), + expn_info: sp.expn_info})} + fss_external(_) {sp} + } +} + enum expn_info_ { expanded_from({call_site: span, callie: {name: str, span: option}}) @@ -99,19 +135,25 @@ enum expn_info_ { type expn_info = option<@expn_info_>; type span = {lo: uint, hi: uint, expn_info: expn_info}; -fn span_to_str(sp: span, cm: codemap) -> str { +fn span_to_str_no_adj(sp: span, cm: codemap) -> str { let lo = lookup_char_pos(cm, sp.lo); let hi = lookup_char_pos(cm, sp.hi); ret #fmt("%s:%u:%u: %u:%u", lo.file.name, lo.line, lo.col, hi.line, hi.col) } +fn span_to_str(sp: span, cm: codemap) -> str { + let lo = lookup_char_pos_adj(cm, sp.lo); + let hi = lookup_char_pos_adj(cm, sp.hi); + ret #fmt("%s:%u:%u: %u:%u", lo.filename, + lo.line, lo.col, hi.line, hi.col) +} + type file_lines = {file: filemap, lines: [uint]}; fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines { let lo = lookup_char_pos(cm, sp.lo); let hi = lookup_char_pos(cm, sp.hi); - // FIXME: Check for filemap? let lines = []; uint::range(lo.line - 1u, hi.line as uint) {|i| lines += [i]; }; ret @{file: lo.file, lines: lines}; diff --git a/src/test/compile-fail/qquote.rs b/src/test/compile-fail/qquote.rs new file mode 100644 index 0000000000000..243e90c35df3e --- /dev/null +++ b/src/test/compile-fail/qquote.rs @@ -0,0 +1,51 @@ +// xfail-pretty + +use std; +use rustc; + +import rustc::*; +import std::io::*; + +import rustc::driver::diagnostic; +import rustc::syntax::ast; +import rustc::syntax::codemap; +import rustc::syntax::parse::parser; +import rustc::syntax::print::*; + +fn new_parse_sess() -> parser::parse_sess { + fail; +} + +iface fake_ext_ctxt { + fn session() -> fake_session; +} + +type fake_options = {cfg: ast::crate_cfg}; + +type fake_session = {opts: @fake_options, + parse_sess: parser::parse_sess}; + +impl of fake_ext_ctxt for fake_session { + fn session() -> fake_session {self} +} + +fn mk_ctxt() -> fake_ext_ctxt { + let opts : fake_options = {cfg: []}; + {opts: @opts, parse_sess: new_parse_sess()} as fake_ext_ctxt +} + + +fn main() { + let ext_cx = mk_ctxt(); + + let abc = #ast{23}; + check_pp(abc, pprust::print_expr, "23"); + + let expr3 = #ast{2 - $(abcd) + 7}; //! ERROR unresolved name: abcd + check_pp(expr3, pprust::print_expr, "2 - 23 + 7"); +} + +fn check_pp(expr: T, f: fn(pprust::ps, T), expect: str) { + fail; +} +