Skip to content

Commit c23a9d4

Browse files
committed
Auto merge of #25387 - eddyb:syn-file-loader, r=nikomatsakis
This allows compiling entire crates from memory or preprocessing source files before they are tokenized. Minor API refactoring included, which is a [breaking-change] for libsyntax users: * `ParseSess::{next_node_id, reserve_node_ids}` moved to rustc's `Session` * `new_parse_sess` -> `ParseSess::new` * `new_parse_sess_special_handler` -> `ParseSess::with_span_handler` * `mk_span_handler` -> `SpanHandler::new` * `default_handler` -> `Handler::new` * `mk_handler` -> `Handler::with_emitter` * `string_to_filemap(sess source, path)` -> `sess.codemap().new_filemap(path, source)`
2 parents 2da9efe + 8cc9878 commit c23a9d4

File tree

23 files changed

+149
-142
lines changed

23 files changed

+149
-142
lines changed

src/grammar/verify.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,9 @@ fn main() {
287287
let options = config::basic_options();
288288
let session = session::build_session(options, None,
289289
syntax::diagnostics::registry::Registry::new(&[]));
290-
let filemap = parse::string_to_filemap(&session.parse_sess,
291-
code,
292-
String::from_str("<n/a>"));
290+
let filemap = session.parse_sess.codemap().new_filemap(String::from_str("<n/a>"), code);
293291
let mut lexer = lexer::StringReader::new(session.diagnostic(), filemap);
294-
let ref cm = lexer.span_diagnostic.cm;
292+
let cm = session.codemap();
295293

296294
// ANTLR
297295
let mut token_file = File::open(&Path::new(&args.next().unwrap())).unwrap();

src/librustc/middle/astencode.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1866,7 +1866,7 @@ impl FakeExtCtxt for parse::ParseSess {
18661866

18671867
#[cfg(test)]
18681868
fn mk_ctxt() -> parse::ParseSess {
1869-
parse::new_parse_sess()
1869+
parse::ParseSess::new()
18701870
}
18711871

18721872
#[cfg(test)]

src/librustc/session/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
852852
parse::parse_meta_from_source_str("cfgspec".to_string(),
853853
s.to_string(),
854854
Vec::new(),
855-
&parse::new_parse_sess())
855+
&parse::ParseSess::new())
856856
}).collect::<ast::CrateConfig>()
857857
}
858858

src/librustc/session/mod.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ pub struct Session {
6464
/// operations such as auto-dereference and monomorphization.
6565
pub recursion_limit: Cell<usize>,
6666

67-
pub can_print_warnings: bool
67+
pub can_print_warnings: bool,
68+
69+
next_node_id: Cell<ast::NodeId>
6870
}
6971

7072
impl Session {
@@ -213,16 +215,23 @@ impl Session {
213215
lints.insert(id, vec!((lint_id, sp, msg)));
214216
}
215217
pub fn next_node_id(&self) -> ast::NodeId {
216-
self.parse_sess.next_node_id()
218+
self.reserve_node_ids(1)
217219
}
218220
pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId {
219-
self.parse_sess.reserve_node_ids(count)
221+
let id = self.next_node_id.get();
222+
223+
match id.checked_add(count) {
224+
Some(next) => self.next_node_id.set(next),
225+
None => self.bug("Input too large, ran out of node ids!")
226+
}
227+
228+
id
220229
}
221230
pub fn diagnostic<'a>(&'a self) -> &'a diagnostic::SpanHandler {
222231
&self.parse_sess.span_diagnostic
223232
}
224233
pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
225-
&self.parse_sess.span_diagnostic.cm
234+
self.parse_sess.codemap()
226235
}
227236
// This exists to help with refactoring to eliminate impossible
228237
// cases later on
@@ -359,9 +368,9 @@ pub fn build_session(sopts: config::Options,
359368

360369
let codemap = codemap::CodeMap::new();
361370
let diagnostic_handler =
362-
diagnostic::default_handler(sopts.color, Some(registry), can_print_warnings);
371+
diagnostic::Handler::new(sopts.color, Some(registry), can_print_warnings);
363372
let span_diagnostic_handler =
364-
diagnostic::mk_span_handler(diagnostic_handler, codemap);
373+
diagnostic::SpanHandler::new(diagnostic_handler, codemap);
365374

366375
build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
367376
}
@@ -378,7 +387,7 @@ pub fn build_session_(sopts: config::Options,
378387
}
379388
};
380389
let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
381-
let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
390+
let p_s = parse::ParseSess::with_span_handler(span_diagnostic);
382391
let default_sysroot = match sopts.maybe_sysroot {
383392
Some(_) => None,
384393
None => Some(filesearch::get_or_default_sysroot())
@@ -421,7 +430,8 @@ pub fn build_session_(sopts: config::Options,
421430
delayed_span_bug: RefCell::new(None),
422431
features: RefCell::new(feature_gate::Features::new()),
423432
recursion_limit: Cell::new(64),
424-
can_print_warnings: can_print_warnings
433+
can_print_warnings: can_print_warnings,
434+
next_node_id: Cell::new(1)
425435
};
426436

427437
sess

src/librustc_back/target/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ impl Target {
218218
// this is 1. ugly, 2. error prone.
219219

220220

221-
let handler = diagnostic::default_handler(diagnostic::Auto, None, true);
221+
let handler = diagnostic::Handler::new(diagnostic::Auto, None, true);
222222

223223
let get_req_field = |name: &str| {
224224
match obj.find(name)

src/librustc_driver/test.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ fn test_env<F>(source_string: &str,
105105
let codemap =
106106
CodeMap::new();
107107
let diagnostic_handler =
108-
diagnostic::mk_handler(true, emitter);
108+
diagnostic::Handler::with_emitter(true, emitter);
109109
let span_diagnostic_handler =
110-
diagnostic::mk_span_handler(diagnostic_handler, codemap);
110+
diagnostic::SpanHandler::new(diagnostic_handler, codemap);
111111

112112
let sess = session::build_session_(options, None, span_diagnostic_handler);
113113
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));

src/librustc_trans/back/write.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use util::common::time;
2121
use util::common::path2cstr;
2222
use syntax::codemap;
2323
use syntax::diagnostic;
24-
use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
24+
use syntax::diagnostic::{Emitter, Handler, Level};
2525

2626
use std::ffi::{CStr, CString};
2727
use std::fs;
@@ -928,7 +928,7 @@ fn run_work_multithreaded(sess: &Session,
928928
futures.push(rx);
929929

930930
thread::Builder::new().name(format!("codegen-{}", i)).spawn(move || {
931-
let diag_handler = mk_handler(true, box diag_emitter);
931+
let diag_handler = Handler::with_emitter(true, box diag_emitter);
932932

933933
// Must construct cgcx inside the proc because it has non-Send
934934
// fields.

src/librustdoc/core.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
110110
};
111111

112112
let codemap = codemap::CodeMap::new();
113-
let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None, true);
113+
let diagnostic_handler = diagnostic::Handler::new(diagnostic::Auto, None, true);
114114
let span_diagnostic_handler =
115-
diagnostic::mk_span_handler(diagnostic_handler, codemap);
115+
diagnostic::SpanHandler::new(diagnostic_handler, codemap);
116116

117117
let sess = session::build_session_(sessopts, cpath,
118118
span_diagnostic_handler);

src/librustdoc/html/highlight.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@ use syntax::parse;
2424
/// Highlights some source code, returning the HTML output.
2525
pub fn highlight(src: &str, class: Option<&str>, id: Option<&str>) -> String {
2626
debug!("highlighting: ================\n{}\n==============", src);
27-
let sess = parse::new_parse_sess();
28-
let fm = parse::string_to_filemap(&sess,
29-
src.to_string(),
30-
"<stdin>".to_string());
27+
let sess = parse::ParseSess::new();
28+
let fm = sess.codemap().new_filemap("<stdin>".to_string(), src.to_string());
3129

3230
let mut out = Vec::new();
3331
doit(&sess,
@@ -62,7 +60,7 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader,
6260
loop {
6361
let next = lexer.next_token();
6462

65-
let snip = |sp| sess.span_diagnostic.cm.span_to_snippet(sp).unwrap();
63+
let snip = |sp| sess.codemap().span_to_snippet(sp).unwrap();
6664

6765
if next.tok == token::Eof { break }
6866

@@ -178,7 +176,7 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader,
178176

179177
// as mentioned above, use the original source code instead of
180178
// stringifying this token
181-
let snip = sess.span_diagnostic.cm.span_to_snippet(next.sp).unwrap();
179+
let snip = sess.codemap().span_to_snippet(next.sp).unwrap();
182180
if klass == "" {
183181
try!(write!(out, "{}", Escape(&snip)));
184182
} else {

src/librustdoc/test.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ pub fn run(input: &str,
6565
};
6666

6767
let codemap = CodeMap::new();
68-
let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None, true);
68+
let diagnostic_handler = diagnostic::Handler::new(diagnostic::Auto, None, true);
6969
let span_diagnostic_handler =
70-
diagnostic::mk_span_handler(diagnostic_handler, codemap);
70+
diagnostic::SpanHandler::new(diagnostic_handler, codemap);
7171

7272
let sess = session::build_session_(sessopts,
7373
Some(input_path.clone()),
@@ -184,7 +184,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
184184
// it with a sink that is also passed to rustc itself. When this function
185185
// returns the output of the sink is copied onto the output of our own thread.
186186
//
187-
// The basic idea is to not use a default_handler() for rustc, and then also
187+
// The basic idea is to not use a default Handler for rustc, and then also
188188
// not print things by default to the actual stderr.
189189
struct Sink(Arc<Mutex<Vec<u8>>>);
190190
impl Write for Sink {
@@ -206,9 +206,9 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
206206

207207
// Compile the code
208208
let codemap = CodeMap::new();
209-
let diagnostic_handler = diagnostic::mk_handler(true, box emitter);
209+
let diagnostic_handler = diagnostic::Handler::with_emitter(true, box emitter);
210210
let span_diagnostic_handler =
211-
diagnostic::mk_span_handler(diagnostic_handler, codemap);
211+
diagnostic::SpanHandler::new(diagnostic_handler, codemap);
212212

213213
let sess = session::build_session_(sessopts,
214214
None,

src/libsyntax/codemap.rs

+46-2
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ pub use self::MacroFormat::*;
2121

2222
use std::cell::RefCell;
2323
use std::ops::{Add, Sub};
24+
use std::path::Path;
2425
use std::rc::Rc;
2526

26-
use std::fmt;
27+
use std::{fmt, fs};
28+
use std::io::{self, Read};
2729

2830
use serialize::{Encodable, Decodable, Encoder, Decoder};
2931

@@ -527,24 +529,66 @@ impl FileMap {
527529
}
528530
}
529531

532+
/// An abstraction over the fs operations used by the Parser.
533+
pub trait FileLoader {
534+
/// Query the existence of a file.
535+
fn file_exists(&self, path: &Path) -> bool;
536+
537+
/// Read the contents of an UTF-8 file into memory.
538+
fn read_file(&self, path: &Path) -> io::Result<String>;
539+
}
540+
541+
/// A FileLoader that uses std::fs to load real files.
542+
pub struct RealFileLoader;
543+
544+
impl FileLoader for RealFileLoader {
545+
fn file_exists(&self, path: &Path) -> bool {
546+
fs::metadata(path).is_ok()
547+
}
548+
549+
fn read_file(&self, path: &Path) -> io::Result<String> {
550+
let mut src = String::new();
551+
try!(try!(fs::File::open(path)).read_to_string(&mut src));
552+
Ok(src)
553+
}
554+
}
530555

531556
// _____________________________________________________________________________
532557
// CodeMap
533558
//
534559

535560
pub struct CodeMap {
536561
pub files: RefCell<Vec<Rc<FileMap>>>,
537-
expansions: RefCell<Vec<ExpnInfo>>
562+
expansions: RefCell<Vec<ExpnInfo>>,
563+
file_loader: Box<FileLoader>
538564
}
539565

540566
impl CodeMap {
541567
pub fn new() -> CodeMap {
542568
CodeMap {
543569
files: RefCell::new(Vec::new()),
544570
expansions: RefCell::new(Vec::new()),
571+
file_loader: Box::new(RealFileLoader)
572+
}
573+
}
574+
575+
pub fn with_file_loader(file_loader: Box<FileLoader>) -> CodeMap {
576+
CodeMap {
577+
files: RefCell::new(Vec::new()),
578+
expansions: RefCell::new(Vec::new()),
579+
file_loader: file_loader
545580
}
546581
}
547582

583+
pub fn file_exists(&self, path: &Path) -> bool {
584+
self.file_loader.file_exists(path)
585+
}
586+
587+
pub fn load_file(&self, path: &Path) -> io::Result<Rc<FileMap>> {
588+
let src = try!(self.file_loader.read_file(path));
589+
Ok(self.new_filemap(path.to_str().unwrap().to_string(), src))
590+
}
591+
548592
pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> {
549593
let mut files = self.files.borrow_mut();
550594
let start_pos = match files.last() {

src/libsyntax/diagnostic.rs

+19-21
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ pub struct SpanHandler {
122122
}
123123

124124
impl SpanHandler {
125+
pub fn new(handler: Handler, cm: codemap::CodeMap) -> SpanHandler {
126+
SpanHandler {
127+
handler: handler,
128+
cm: cm,
129+
}
130+
}
125131
pub fn span_fatal(&self, sp: Span, msg: &str) -> FatalError {
126132
self.handler.emit(Some((&self.cm, sp)), msg, Fatal);
127133
return FatalError;
@@ -187,6 +193,19 @@ pub struct Handler {
187193
}
188194

189195
impl Handler {
196+
pub fn new(color_config: ColorConfig,
197+
registry: Option<diagnostics::registry::Registry>,
198+
can_emit_warnings: bool) -> Handler {
199+
let emitter = Box::new(EmitterWriter::stderr(color_config, registry));
200+
Handler::with_emitter(can_emit_warnings, emitter)
201+
}
202+
pub fn with_emitter(can_emit_warnings: bool, e: Box<Emitter + Send>) -> Handler {
203+
Handler {
204+
err_count: Cell::new(0),
205+
emit: RefCell::new(e),
206+
can_emit_warnings: can_emit_warnings
207+
}
208+
}
190209
pub fn fatal(&self, msg: &str) -> ! {
191210
self.emit.borrow_mut().emit(None, msg, None, Fatal);
192211
panic!(FatalError);
@@ -254,27 +273,6 @@ impl Handler {
254273
}
255274
}
256275

257-
pub fn mk_span_handler(handler: Handler, cm: codemap::CodeMap) -> SpanHandler {
258-
SpanHandler {
259-
handler: handler,
260-
cm: cm,
261-
}
262-
}
263-
264-
pub fn default_handler(color_config: ColorConfig,
265-
registry: Option<diagnostics::registry::Registry>,
266-
can_emit_warnings: bool) -> Handler {
267-
mk_handler(can_emit_warnings, Box::new(EmitterWriter::stderr(color_config, registry)))
268-
}
269-
270-
pub fn mk_handler(can_emit_warnings: bool, e: Box<Emitter + Send>) -> Handler {
271-
Handler {
272-
err_count: Cell::new(0),
273-
emit: RefCell::new(e),
274-
can_emit_warnings: can_emit_warnings
275-
}
276-
}
277-
278276
#[derive(Copy, PartialEq, Clone, Debug)]
279277
pub enum Level {
280278
Bug,

src/libsyntax/ext/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ impl<'a> ExtCtxt<'a> {
648648
parse::tts_to_parser(self.parse_sess, tts.to_vec(), self.cfg())
649649
}
650650

651-
pub fn codemap(&self) -> &'a CodeMap { &self.parse_sess.span_diagnostic.cm }
651+
pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() }
652652
pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
653653
pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() }
654654
pub fn call_site(&self) -> Span {

0 commit comments

Comments
 (0)