From 69c9b5b14ba9c5d23f1a0055ce1559650a634bc3 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Mon, 21 Oct 2019 23:51:57 +0900 Subject: [PATCH 01/12] Add an abstraction layer on top of libsyntax ParseSess --- src/formatting.rs | 147 +++++++++---------------------------- src/ignore_path.rs | 2 + src/lib.rs | 1 + src/syntux.rs | 3 + src/syntux/parser.rs | 39 ++++++++++ src/syntux/session.rs | 165 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 243 insertions(+), 114 deletions(-) create mode 100644 src/syntux.rs create mode 100644 src/syntux/parser.rs create mode 100644 src/syntux/session.rs diff --git a/src/formatting.rs b/src/formatting.rs index 2822a331260..57f2891c488 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -1,23 +1,21 @@ // High level formatting functions. -use std::cell::RefCell; use std::collections::HashMap; use std::io::{self, Write}; use std::panic::{catch_unwind, AssertUnwindSafe}; -use std::rc::Rc; use std::time::{Duration, Instant}; use syntax::ast; -use syntax::errors::emitter::{ColorConfig, Emitter, EmitterWriter}; -use syntax::errors::{Diagnostic, DiagnosticBuilder, Handler}; -use syntax::parse::{self, ParseSess}; -use syntax::source_map::{FilePathMapping, SourceMap, Span, DUMMY_SP}; +use syntax::errors::DiagnosticBuilder; +use syntax::parse; +use syntax::source_map::{SourceMap, Span, DUMMY_SP}; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; use crate::ignore_path::IgnorePathSet; use crate::issues::BadIssueSeeker; +use crate::syntux::session::{ErrorEmission, ParseSess}; use crate::utils::count_newlines; use crate::visitor::{FmtVisitor, SnippetProvider}; use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; @@ -68,7 +66,7 @@ fn format_project( let input_is_stdin = main_file == FileName::Stdin; let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { - Ok(set) => Rc::new(set), + Ok(set) => set, Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), }; if config.skip_children() && ignore_path_set.is_match(&main_file) { @@ -76,14 +74,12 @@ fn format_project( } // Parse the crate. - let can_reset_parser_errors = Rc::new(RefCell::new(false)); - let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); - let mut parse_session = make_parse_sess( - source_map.clone(), - config, - Rc::clone(&ignore_path_set), - can_reset_parser_errors.clone(), - ); + let error_emission = if config.hide_parse_errors() { + ErrorEmission::Silence + } else { + ErrorEmission::Default + }; + let mut parse_session = ParseSess::new(error_emission, ignore_path_set); let mut report = FormatReport::new(); let directory_ownership = input.to_directory_ownership(); let krate = match parse_crate( @@ -92,7 +88,6 @@ fn format_project( config, &mut report, directory_ownership, - can_reset_parser_errors.clone(), ) { Ok(krate) => krate, // Surface parse error via Session (errors are merged there from report) @@ -102,19 +97,19 @@ fn format_project( timer = timer.done_parsing(); // Suppress error output if we have to do any further parsing. - let silent_emitter = silent_emitter(); - parse_session.span_diagnostic = Handler::with_emitter(true, None, silent_emitter); + parse_session.set_silent_emitter(); let mut context = FormatContext::new(&krate, report, parse_session, config, handler); let files = modules::ModResolver::new( - &context.parse_session, + context.parse_session.inner(), directory_ownership.unwrap_or(parse::DirectoryOwnership::UnownedViaMod(true)), !(input_is_stdin || config.skip_children()), ) .visit_crate(&krate) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + for (path, module) in files { - let should_ignore = !input_is_stdin && ignore_path_set.is_match(&path); + let should_ignore = !input_is_stdin && context.ignore_file(&path); if (config.skip_children() && path != main_file) || should_ignore { continue; } @@ -146,6 +141,10 @@ struct FormatContext<'a, T: FormatHandler> { } impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { + fn ignore_file(&self, path: &FileName) -> bool { + self.parse_session.ignore_file(path) + } + // Formats a single file/module. fn format_file( &mut self, @@ -161,7 +160,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { let big_snippet = source_file.src.as_ref().unwrap(); let snippet_provider = SnippetProvider::new(source_file.start_pos, big_snippet); let mut visitor = FmtVisitor::from_source_map( - &self.parse_session, + self.parse_session.inner(), &self.config, &snippet_provider, self.report.clone(), @@ -634,7 +633,6 @@ fn parse_crate( config: &Config, report: &mut FormatReport, directory_ownership: Option, - can_reset_parser_errors: Rc>, ) -> Result { let input_is_stdin = input.is_text(); @@ -642,13 +640,19 @@ fn parse_crate( Input::File(ref file) => { // Use `new_sub_parser_from_file` when we the input is a submodule. Ok(if let Some(dir_own) = directory_ownership { - parse::new_sub_parser_from_file(parse_session, file, dir_own, None, DUMMY_SP) + parse::new_sub_parser_from_file( + parse_session.inner(), + file, + dir_own, + None, + DUMMY_SP, + ) } else { - parse::new_parser_from_file(parse_session, file) + parse::new_parser_from_file(parse_session.inner(), file) }) } Input::Text(text) => parse::maybe_new_parser_from_source_str( - parse_session, + parse_session.inner(), syntax::source_map::FileName::Custom("stdin".to_owned()), text, ) @@ -669,9 +673,7 @@ fn parse_crate( catch_unwind(move || parser.0.parse_crate_mod().map_err(|d| vec![d])) } Err(diagnostics) => { - for diagnostic in diagnostics { - parse_session.span_diagnostic.emit_diagnostic(&diagnostic); - } + parse_session.emit_diagnostics(diagnostics); report.add_parsing_error(); return Err(ErrorKind::ParseError); } @@ -679,7 +681,7 @@ fn parse_crate( match result { Ok(Ok(c)) => { - if !parse_session.span_diagnostic.has_errors() { + if !parse_session.has_errors() { return Ok(c); } // This scenario occurs when the parser encountered errors @@ -687,8 +689,8 @@ fn parse_crate( // occurred in files that are ignored, then reset // the error count and continue. // https://github.com/rust-lang/rustfmt/issues/3779 - if *can_reset_parser_errors.borrow() { - parse_session.span_diagnostic.reset_err_count(); + if parse_session.can_reset_errors() { + parse_session.reset_errors(); return Ok(c); } } @@ -707,89 +709,6 @@ fn parse_crate( Err(ErrorKind::ParseError) } -struct SilentOnIgnoredFilesEmitter { - ignore_path_set: Rc, - source_map: Rc, - emitter: EmitterWriter, - has_non_ignorable_parser_errors: bool, - can_reset: Rc>, -} - -impl Emitter for SilentOnIgnoredFilesEmitter { - fn emit_diagnostic(&mut self, db: &Diagnostic) { - if let Some(primary_span) = &db.span.primary_span() { - let file_name = self.source_map.span_to_filename(*primary_span); - match file_name { - syntax_pos::FileName::Real(ref path) => { - if self - .ignore_path_set - .is_match(&FileName::Real(path.to_path_buf())) - { - if !self.has_non_ignorable_parser_errors { - *self.can_reset.borrow_mut() = true; - } - return; - } - } - _ => (), - }; - } - - self.has_non_ignorable_parser_errors = true; - *self.can_reset.borrow_mut() = false; - self.emitter.emit_diagnostic(db); - } -} - -/// Emitter which discards every error. -struct SilentEmitter; - -impl Emitter for SilentEmitter { - fn emit_diagnostic(&mut self, _db: &Diagnostic) {} -} - -fn silent_emitter() -> Box { - Box::new(SilentEmitter {}) -} - -fn make_parse_sess( - source_map: Rc, - config: &Config, - ignore_path_set: Rc, - can_reset: Rc>, -) -> ParseSess { - let tty_handler = if config.hide_parse_errors() { - let silent_emitter = silent_emitter(); - Handler::with_emitter(true, None, silent_emitter) - } else { - let supports_color = term::stderr().map_or(false, |term| term.supports_color()); - let color_cfg = if supports_color { - ColorConfig::Auto - } else { - ColorConfig::Never - }; - - let emitter_writer = EmitterWriter::stderr( - color_cfg, - Some(source_map.clone()), - false, - false, - None, - false, - ); - let emitter = Box::new(SilentOnIgnoredFilesEmitter { - has_non_ignorable_parser_errors: false, - ignore_path_set: ignore_path_set, - source_map: Rc::clone(&source_map), - emitter: emitter_writer, - can_reset, - }); - Handler::with_emitter(true, None, emitter) - }; - - ParseSess::with_span_handler(tty_handler, source_map) -} - fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) where F: Fn(), diff --git a/src/ignore_path.rs b/src/ignore_path.rs index d8974e12b8f..41afe9cf74b 100644 --- a/src/ignore_path.rs +++ b/src/ignore_path.rs @@ -2,6 +2,8 @@ use ignore::{self, gitignore}; use crate::config::{FileName, IgnoreList}; +unsafe impl Send for IgnorePathSet {} + pub(crate) struct IgnorePathSet { ignore_set: gitignore::Gitignore, } diff --git a/src/lib.rs b/src/lib.rs index 31df6b1c72c..ac97ce42f9b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,6 +74,7 @@ pub(crate) mod source_map; mod spanned; mod stmt; mod string; +mod syntux; #[cfg(test)] mod test; mod types; diff --git a/src/syntux.rs b/src/syntux.rs new file mode 100644 index 00000000000..722224fa8bf --- /dev/null +++ b/src/syntux.rs @@ -0,0 +1,3 @@ +//! This module defines a thin abstract layer on top of the rustc's parser and syntax libraries. + +pub(crate) mod session; diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs new file mode 100644 index 00000000000..4cf64c6fb41 --- /dev/null +++ b/src/syntux/parser.rs @@ -0,0 +1,39 @@ +use syntax::parse::parser::Parser as RawParser; + +use crate::Input; + +/// A parser for Rust source code. +pub struct Parser<'a> { + parser: RawParser<'a>, +} + +/// A builder for the `Parser`. +pub struct ParserBuilder { + silent: bool, + input: Input, +} + +impl ParserBuilder { + pub fn input(&mut self, input: Input) -> &mut ParserBuilder { + self.input = input; + self + } + + pub fn build(self) -> Result { + match self.input { + Input::File(ref file) => { + parse::new_parser_from_file(par) + } + } + Ok(Parser) + } +} + +enum ParserError { + ParserCreationError, +} + +impl<'a> Parser<'a> { + pub fn from_string(text: String) -> Result, ParserError> { + } +} \ No newline at end of file diff --git a/src/syntux/session.rs b/src/syntux/session.rs new file mode 100644 index 00000000000..ef33c86fcbe --- /dev/null +++ b/src/syntux/session.rs @@ -0,0 +1,165 @@ +use std::cell::RefCell; +use std::rc::Rc; + +use syntax::errors::emitter::{ColorConfig, Emitter, EmitterWriter}; +use syntax::errors::{Diagnostic, Handler}; +use syntax::parse::ParseSess as RawParseSess; +use syntax::source_map::{FilePathMapping, SourceMap}; + +use crate::ignore_path::IgnorePathSet; +use crate::FileName; + +/// ParseSess holds structs necessary for constructing a parser. +pub(crate) struct ParseSess { + parse_sess: RawParseSess, + ignore_path_set: Rc, + can_reset_errors: Rc>, +} + +/// Emitter which discards every error. +struct SilentEmitter; + +impl Emitter for SilentEmitter { + fn emit_diagnostic(&mut self, _db: &Diagnostic) {} +} + +fn silent_emitter() -> Box { + Box::new(SilentEmitter {}) +} + +/// Emit errors against every files expect ones specified in the `ignore_path_set`. +struct SilentOnIgnoredFilesEmitter { + ignore_path_set: Rc, + source_map: Rc, + emitter: EmitterWriter, + has_non_ignorable_parser_errors: bool, + can_reset: Rc>, +} + +impl Emitter for SilentOnIgnoredFilesEmitter { + fn emit_diagnostic(&mut self, db: &Diagnostic) { + if let Some(primary_span) = &db.span.primary_span() { + let file_name = self.source_map.span_to_filename(*primary_span); + match file_name { + syntax_pos::FileName::Real(ref path) => { + if self + .ignore_path_set + .is_match(&FileName::Real(path.to_path_buf())) + { + if !self.has_non_ignorable_parser_errors { + *self.can_reset.borrow_mut() = true; + } + return; + } + } + _ => (), + }; + } + + self.has_non_ignorable_parser_errors = true; + *self.can_reset.borrow_mut() = false; + self.emitter.emit_diagnostic(db); + } +} + +pub(crate) enum ErrorEmission { + /// Do not emit errors from the underlying parser. + Silence, + /// Emit every parser error except ones from files specified in the `ignore` config option. + Default, +} + +fn silent_handler() -> Handler { + Handler::with_emitter(true, None, silent_emitter()) +} + +fn default_handler( + source_map: Rc, + ignore_path_set: Rc, + can_reset: Rc>, +) -> Handler { + let supports_color = term::stderr().map_or(false, |term| term.supports_color()); + let color_cfg = if supports_color { + ColorConfig::Auto + } else { + ColorConfig::Never + }; + + let emitter = EmitterWriter::stderr( + color_cfg, + Some(source_map.clone()), + false, + false, + None, + false, + ); + Handler::with_emitter( + true, + None, + Box::new(SilentOnIgnoredFilesEmitter { + has_non_ignorable_parser_errors: false, + source_map, + emitter, + ignore_path_set, + can_reset, + }), + ) +} + +impl ParseSess { + pub(crate) fn new(error_emission: ErrorEmission, ignore_path_set: IgnorePathSet) -> ParseSess { + let ignore_path_set = Rc::new(ignore_path_set); + let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); + let can_reset_errors = Rc::new(RefCell::new(false)); + + let handler = match error_emission { + ErrorEmission::Silence => silent_handler(), + ErrorEmission::Default => default_handler( + Rc::clone(&source_map), + Rc::clone(&ignore_path_set), + Rc::clone(&can_reset_errors), + ), + }; + let parse_sess = RawParseSess::with_span_handler(handler, Rc::clone(&source_map)); + + ParseSess { + parse_sess, + ignore_path_set, + can_reset_errors, + } + } + + pub(crate) fn can_reset_errors(&self) -> bool { + *self.can_reset_errors.borrow() + } + + pub(crate) fn ignore_file(&self, path: &FileName) -> bool { + self.ignore_path_set.as_ref().is_match(&path) + } + + pub(crate) fn set_silent_emitter(&mut self) { + self.parse_sess.span_diagnostic = Handler::with_emitter(true, None, silent_emitter()); + } + + pub(crate) fn inner(&self) -> &RawParseSess { + &self.parse_sess + } + + pub(crate) fn has_errors(&self) -> bool { + self.parse_sess.span_diagnostic.has_errors() + } + + pub(crate) fn reset_errors(&self) { + self.parse_sess.span_diagnostic.reset_err_count(); + } + + pub(crate) fn source_map(&self) -> &SourceMap { + &self.parse_sess.source_map() + } + + pub(crate) fn emit_diagnostics(&self, diagnostics: Vec) { + for diagnostic in diagnostics { + self.parse_sess.span_diagnostic.emit_diagnostic(&diagnostic); + } + } +} From 64c44f4e4a50df3eb9c528366856716bc79fc4d5 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 22 Oct 2019 13:04:12 +0900 Subject: [PATCH 02/12] Add Parser::parse_crate --- src/formatting.rs | 112 +++++---------------------------- src/syntux.rs | 1 + src/syntux/parser.rs | 147 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 147 insertions(+), 113 deletions(-) diff --git a/src/formatting.rs b/src/formatting.rs index 57f2891c488..3a57e8aa2e1 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -2,19 +2,18 @@ use std::collections::HashMap; use std::io::{self, Write}; -use std::panic::{catch_unwind, AssertUnwindSafe}; use std::time::{Duration, Instant}; use syntax::ast; -use syntax::errors::DiagnosticBuilder; use syntax::parse; -use syntax::source_map::{SourceMap, Span, DUMMY_SP}; +use syntax::source_map::{SourceMap, Span}; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; use crate::ignore_path::IgnorePathSet; use crate::issues::BadIssueSeeker; +use crate::syntux::parser::{Parser, ParserError}; use crate::syntux::session::{ErrorEmission, ParseSess}; use crate::utils::count_newlines; use crate::visitor::{FmtVisitor, SnippetProvider}; @@ -74,6 +73,7 @@ fn format_project( } // Parse the crate. + let is_stdin = !input.is_text(); let error_emission = if config.hide_parse_errors() { ErrorEmission::Silence } else { @@ -82,17 +82,17 @@ fn format_project( let mut parse_session = ParseSess::new(error_emission, ignore_path_set); let mut report = FormatReport::new(); let directory_ownership = input.to_directory_ownership(); - let krate = match parse_crate( - input, - &parse_session, - config, - &mut report, - directory_ownership, - ) { + + let krate = match Parser::parse_crate(config, input, directory_ownership, &parse_session) { Ok(krate) => krate, - // Surface parse error via Session (errors are merged there from report) - Err(ErrorKind::ParseError) => return Ok(report), - Err(e) => return Err(e), + Err(e) => { + let forbid_verbose = is_stdin || e != ParserError::ParsePanicError; + should_emit_verbose(forbid_verbose, config, || { + eprintln!("The Rust parser panicked"); + }); + report.add_parsing_error(); + return Ok(report); + } }; timer = timer.done_parsing(); @@ -627,93 +627,11 @@ impl<'a> FormatLines<'a> { } } -fn parse_crate( - input: Input, - parse_session: &ParseSess, - config: &Config, - report: &mut FormatReport, - directory_ownership: Option, -) -> Result { - let input_is_stdin = input.is_text(); - - let parser = match input { - Input::File(ref file) => { - // Use `new_sub_parser_from_file` when we the input is a submodule. - Ok(if let Some(dir_own) = directory_ownership { - parse::new_sub_parser_from_file( - parse_session.inner(), - file, - dir_own, - None, - DUMMY_SP, - ) - } else { - parse::new_parser_from_file(parse_session.inner(), file) - }) - } - Input::Text(text) => parse::maybe_new_parser_from_source_str( - parse_session.inner(), - syntax::source_map::FileName::Custom("stdin".to_owned()), - text, - ) - .map(|mut parser| { - parser.recurse_into_file_modules = false; - parser - }), - }; - - let result = match parser { - Ok(mut parser) => { - parser.cfg_mods = false; - if config.skip_children() { - parser.recurse_into_file_modules = false; - } - - let mut parser = AssertUnwindSafe(parser); - catch_unwind(move || parser.0.parse_crate_mod().map_err(|d| vec![d])) - } - Err(diagnostics) => { - parse_session.emit_diagnostics(diagnostics); - report.add_parsing_error(); - return Err(ErrorKind::ParseError); - } - }; - - match result { - Ok(Ok(c)) => { - if !parse_session.has_errors() { - return Ok(c); - } - // This scenario occurs when the parser encountered errors - // but was still able to recover. If all of the parser errors - // occurred in files that are ignored, then reset - // the error count and continue. - // https://github.com/rust-lang/rustfmt/issues/3779 - if parse_session.can_reset_errors() { - parse_session.reset_errors(); - return Ok(c); - } - } - Ok(Err(mut diagnostics)) => diagnostics.iter_mut().for_each(DiagnosticBuilder::emit), - Err(_) => { - // Note that if you see this message and want more information, - // then run the `parse_crate_mod` function above without - // `catch_unwind` so rustfmt panics and you can get a backtrace. - should_emit_verbose(input_is_stdin, config, || { - println!("The Rust parser panicked") - }); - } - } - - report.add_parsing_error(); - Err(ErrorKind::ParseError) -} - -fn should_emit_verbose(is_stdin: bool, config: &Config, f: F) +fn should_emit_verbose(forbid_verbose_output: bool, config: &Config, f: F) where F: Fn(), { - if config.verbose() == Verbosity::Verbose && !is_stdin { + if config.verbose() == Verbosity::Verbose && !forbid_verbose_output { f(); } } diff --git a/src/syntux.rs b/src/syntux.rs index 722224fa8bf..845576bd8d8 100644 --- a/src/syntux.rs +++ b/src/syntux.rs @@ -1,3 +1,4 @@ //! This module defines a thin abstract layer on top of the rustc's parser and syntax libraries. +pub(crate) mod parser; pub(crate) mod session; diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 4cf64c6fb41..5bd1be28486 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -1,39 +1,154 @@ +use std::panic::{catch_unwind, AssertUnwindSafe}; + +use syntax::ast; +use syntax::errors::Diagnostic; use syntax::parse::parser::Parser as RawParser; +use syntax::parse::DirectoryOwnership; +use syntax::source_map::DUMMY_SP; -use crate::Input; +use crate::syntux::session::ParseSess; +use crate::{Config, Input}; /// A parser for Rust source code. -pub struct Parser<'a> { +pub(crate) struct Parser<'a> { parser: RawParser<'a>, + sess: &'a ParseSess, } /// A builder for the `Parser`. -pub struct ParserBuilder { - silent: bool, - input: Input, +#[derive(Default)] +pub(crate) struct ParserBuilder<'a> { + config: Option<&'a Config>, + sess: Option<&'a ParseSess>, + input: Option, + directory_ownership: Option, } -impl ParserBuilder { - pub fn input(&mut self, input: Input) -> &mut ParserBuilder { - self.input = input; +impl<'a> ParserBuilder<'a> { + pub(crate) fn input(mut self, input: Input) -> ParserBuilder<'a> { + self.input = Some(input); + self + } + + pub(crate) fn sess(mut self, sess: &'a ParseSess) -> ParserBuilder<'a> { + self.sess = Some(sess); + self + } + + pub(crate) fn config(mut self, config: &'a Config) -> ParserBuilder<'a> { + self.config = Some(config); self } - pub fn build(self) -> Result { - match self.input { - Input::File(ref file) => { - parse::new_parser_from_file(par) + pub(crate) fn directory_ownership( + mut self, + directory_ownership: Option, + ) -> ParserBuilder<'a> { + self.directory_ownership = directory_ownership; + self + } + + pub(crate) fn build(self) -> Result, ParserError> { + let config = self.config.ok_or(ParserError::NoConfig)?; + let sess = self.sess.ok_or(ParserError::NoParseSess)?; + let input = self.input.ok_or(ParserError::NoInput)?; + + let mut parser = match Self::parser(sess.inner(), input, self.directory_ownership) { + Ok(p) => p, + Err(db) => { + sess.emit_diagnostics(db); + // report.add_parsing_error(); + return Err(ParserError::ParserCreationError); } + }; + + parser.cfg_mods = false; + + if config.skip_children() { + parser.recurse_into_file_modules = false; + } + + Ok(Parser { parser, sess }) + } + + fn parser( + sess: &'a syntax::parse::ParseSess, + input: Input, + directory_ownership: Option, + ) -> Result, Vec> { + match input { + Input::File(ref file) => Ok(if let Some(directory_ownership) = directory_ownership { + syntax::parse::new_sub_parser_from_file( + sess, + file, + directory_ownership, + None, + DUMMY_SP, + ) + } else { + syntax::parse::new_parser_from_file(sess, file) + }), + Input::Text(text) => syntax::parse::maybe_new_parser_from_source_str( + sess, + syntax::source_map::FileName::Custom("stdin".to_owned()), + text, + ) + .map(|mut parser| { + parser.recurse_into_file_modules = false; + parser + }), } - Ok(Parser) } } -enum ParserError { +#[derive(Debug, PartialEq)] +pub(crate) enum ParserError { + NoConfig, + NoParseSess, + NoInput, ParserCreationError, + ParseError, + ParsePanicError, } impl<'a> Parser<'a> { - pub fn from_string(text: String) -> Result, ParserError> { + pub(crate) fn parse_crate( + config: &'a Config, + input: Input, + directory_ownership: Option, + sess: &'a ParseSess, + ) -> Result { + let mut parser = ParserBuilder::default() + .config(config) + .input(input) + .directory_ownership(directory_ownership) + .sess(sess) + .build()?; + + parser.parse_crate_inner() } -} \ No newline at end of file + + fn parse_crate_inner(&mut self) -> Result { + let mut parser = AssertUnwindSafe(&mut self.parser); + + match catch_unwind(move || parser.parse_crate_mod()) { + Ok(Ok(krate)) => { + if !self.sess.has_errors() { + return Ok(krate); + } + + if self.sess.can_reset_errors() { + self.sess.reset_errors(); + return Ok(krate); + } + + Err(ParserError::ParseError) + } + Ok(Err(mut db)) => { + db.emit(); + Err(ParserError::ParseError) + } + Err(_) => Err(ParserError::ParsePanicError), + } + } +} From 20e3b5f72dce8c96d0584b13bdbdb556a9c540a0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 22 Oct 2019 13:07:19 +0900 Subject: [PATCH 03/12] Remove unused Send impl --- src/ignore_path.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ignore_path.rs b/src/ignore_path.rs index 41afe9cf74b..d8974e12b8f 100644 --- a/src/ignore_path.rs +++ b/src/ignore_path.rs @@ -2,8 +2,6 @@ use ignore::{self, gitignore}; use crate::config::{FileName, IgnoreList}; -unsafe impl Send for IgnorePathSet {} - pub(crate) struct IgnorePathSet { ignore_set: gitignore::Gitignore, } From 7c1dfa3053e34d9d328a8f2fee047f558c2d983f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 22 Oct 2019 13:51:05 +0900 Subject: [PATCH 04/12] Simplify interface --- src/formatting.rs | 16 +++------------- src/syntux/session.rs | 31 ++++++++++++++----------------- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/formatting.rs b/src/formatting.rs index 3a57e8aa2e1..8b8c6d9f5f6 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -11,10 +11,9 @@ use syntax::source_map::{SourceMap, Span}; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; -use crate::ignore_path::IgnorePathSet; use crate::issues::BadIssueSeeker; use crate::syntux::parser::{Parser, ParserError}; -use crate::syntux::session::{ErrorEmission, ParseSess}; +use crate::syntux::session::ParseSess; use crate::utils::count_newlines; use crate::visitor::{FmtVisitor, SnippetProvider}; use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; @@ -64,22 +63,13 @@ fn format_project( let main_file = input.file_name(); let input_is_stdin = main_file == FileName::Stdin; - let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { - Ok(set) => set, - Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), - }; - if config.skip_children() && ignore_path_set.is_match(&main_file) { + let mut parse_session = ParseSess::new(config)?; + if config.skip_children() && parse_session.ignore_file(&main_file) { return Ok(FormatReport::new()); } // Parse the crate. let is_stdin = !input.is_text(); - let error_emission = if config.hide_parse_errors() { - ErrorEmission::Silence - } else { - ErrorEmission::Default - }; - let mut parse_session = ParseSess::new(error_emission, ignore_path_set); let mut report = FormatReport::new(); let directory_ownership = input.to_directory_ownership(); diff --git a/src/syntux/session.rs b/src/syntux/session.rs index ef33c86fcbe..c3cbe22c2a4 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -7,7 +7,7 @@ use syntax::parse::ParseSess as RawParseSess; use syntax::source_map::{FilePathMapping, SourceMap}; use crate::ignore_path::IgnorePathSet; -use crate::FileName; +use crate::{Config, ErrorKind, FileName}; /// ParseSess holds structs necessary for constructing a parser. pub(crate) struct ParseSess { @@ -62,13 +62,6 @@ impl Emitter for SilentOnIgnoredFilesEmitter { } } -pub(crate) enum ErrorEmission { - /// Do not emit errors from the underlying parser. - Silence, - /// Emit every parser error except ones from files specified in the `ignore` config option. - Default, -} - fn silent_handler() -> Handler { Handler::with_emitter(true, None, silent_emitter()) } @@ -107,26 +100,30 @@ fn default_handler( } impl ParseSess { - pub(crate) fn new(error_emission: ErrorEmission, ignore_path_set: IgnorePathSet) -> ParseSess { - let ignore_path_set = Rc::new(ignore_path_set); + pub(crate) fn new(config: &Config) -> Result { + let ignore_path_set = match IgnorePathSet::from_ignore_list(&config.ignore()) { + Ok(ignore_path_set) => Rc::new(ignore_path_set), + Err(e) => return Err(ErrorKind::InvalidGlobPattern(e)), + }; let source_map = Rc::new(SourceMap::new(FilePathMapping::empty())); let can_reset_errors = Rc::new(RefCell::new(false)); - let handler = match error_emission { - ErrorEmission::Silence => silent_handler(), - ErrorEmission::Default => default_handler( + let handler = if config.hide_parse_errors() { + silent_handler() + } else { + default_handler( Rc::clone(&source_map), Rc::clone(&ignore_path_set), Rc::clone(&can_reset_errors), - ), + ) }; - let parse_sess = RawParseSess::with_span_handler(handler, Rc::clone(&source_map)); + let parse_sess = RawParseSess::with_span_handler(handler, source_map); - ParseSess { + Ok(ParseSess { parse_sess, ignore_path_set, can_reset_errors, - } + }) } pub(crate) fn can_reset_errors(&self) -> bool { From b0855d7367a2249496c23abb1346289610118b85 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 22 Oct 2019 16:07:41 +0900 Subject: [PATCH 05/12] Move parser under syntux module --- src/formatting.rs | 9 +- src/lib.rs | 3 +- src/macros.rs | 6 +- src/modules.rs | 157 +++++--------------------------- src/modules/visitor.rs | 64 ++----------- src/rewrite.rs | 2 +- src/syntux/parser.rs | 198 ++++++++++++++++++++++++++++++++++++++++- src/syntux/session.rs | 24 ++++- src/visitor.rs | 2 +- 9 files changed, 261 insertions(+), 204 deletions(-) diff --git a/src/formatting.rs b/src/formatting.rs index 8b8c6d9f5f6..82e68e9ecea 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -5,14 +5,13 @@ use std::io::{self, Write}; use std::time::{Duration, Instant}; use syntax::ast; -use syntax::parse; use syntax::source_map::{SourceMap, Span}; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; use crate::config::{Config, FileName, Verbosity}; use crate::issues::BadIssueSeeker; -use crate::syntux::parser::{Parser, ParserError}; +use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError}; use crate::syntux::session::ParseSess; use crate::utils::count_newlines; use crate::visitor::{FmtVisitor, SnippetProvider}; @@ -91,8 +90,8 @@ fn format_project( let mut context = FormatContext::new(&krate, report, parse_session, config, handler); let files = modules::ModResolver::new( - context.parse_session.inner(), - directory_ownership.unwrap_or(parse::DirectoryOwnership::UnownedViaMod(true)), + &context.parse_session, + directory_ownership.unwrap_or(DirectoryOwnership::UnownedViaMod(true)), !(input_is_stdin || config.skip_children()), ) .visit_crate(&krate) @@ -150,7 +149,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { let big_snippet = source_file.src.as_ref().unwrap(); let snippet_provider = SnippetProvider::new(source_file.start_pos, big_snippet); let mut visitor = FmtVisitor::from_source_map( - self.parse_session.inner(), + &self.parse_session, &self.config, &snippet_provider, self.report.clone(), diff --git a/src/lib.rs b/src/lib.rs index ac97ce42f9b..9828b023ce0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,13 +20,14 @@ use std::rc::Rc; use failure::Fail; use ignore; -use syntax::{ast, parse::DirectoryOwnership}; +use syntax::ast; use crate::comment::LineClasses; use crate::emitter::Emitter; use crate::formatting::{FormatErrorMap, FormattingError, ReportedErrors, SourceFile}; use crate::issues::Issue; use crate::shape::Indent; +use crate::syntux::parser::DirectoryOwnership; use crate::utils::indent_next_line; pub use crate::config::{ diff --git a/src/macros.rs b/src/macros.rs index 8f509dd12c8..b5fd838feb4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -290,7 +290,7 @@ fn rewrite_macro_inner( } } - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + let mut parser = new_parser_from_tts(context.parse_session.inner(), ts.trees().collect()); let mut arg_vec = Vec::new(); let mut vec_with_semi = false; let mut trailing_comma = false; @@ -1192,7 +1192,7 @@ fn next_space(tok: &TokenKind) -> SpaceState { pub(crate) fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option { if &mac.path.to_string() == "try" { let ts: TokenStream = mac.tts.clone(); - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + let mut parser = new_parser_from_tts(context.parse_session.inner(), ts.trees().collect()); Some(ast::Expr { id: ast::NodeId::root(), // dummy value @@ -1424,7 +1424,7 @@ fn format_lazy_static( ts: &TokenStream, ) -> Option { let mut result = String::with_capacity(1024); - let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); + let mut parser = new_parser_from_tts(context.parse_session.inner(), ts.trees().collect()); let nested_shape = shape .block_indent(context.config.tab_spaces()) .with_max_width(context.config); diff --git a/src/modules.rs b/src/modules.rs index 568faa7194b..d8a7fc16645 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -3,18 +3,16 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::attr; -use syntax::parse::{ - new_sub_parser_from_file, parser, token::TokenKind, DirectoryOwnership, PResult, ParseSess, -}; -use syntax::source_map::{self, Span}; +use syntax::source_map; use syntax::symbol::sym; use syntax::visit::Visitor; -use syntax_pos::{self, symbol::Symbol, DUMMY_SP}; +use syntax_pos::{self, symbol::Symbol}; use crate::attr::MetaVisitor; use crate::config::FileName; use crate::items::is_mod_decl; +use crate::syntux::parser::{Directory, DirectoryOwnership, ModulePathSuccess, Parser}; +use crate::syntux::session::ParseSess; use crate::utils::contains_skip; mod visitor; @@ -29,21 +27,6 @@ pub(crate) struct ModResolver<'ast, 'sess> { recursive: bool, } -#[derive(Clone)] -struct Directory { - path: PathBuf, - ownership: DirectoryOwnership, -} - -impl<'a> Directory { - fn to_syntax_directory(&'a self) -> syntax::parse::Directory<'a> { - syntax::parse::Directory { - path: Cow::Borrowed(&self.path), - ownership: self.ownership.clone(), - } - } -} - #[derive(Clone)] enum SubModKind<'a, 'ast> { /// `mod foo;` @@ -100,8 +83,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { /// Visit `cfg_if` macro and look for module declarations. fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), String> { - let mut visitor = - visitor::CfgIfVisitor::new(self.parse_sess, self.directory.to_syntax_directory()); + let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess, &self.directory); visitor.visit_item(&item); for module_item in visitor.mods() { if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.kind { @@ -259,7 +241,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { attrs: &[ast::Attribute], sub_mod: &Cow<'ast, ast::Mod>, ) -> Result, String> { - if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &self.directory.path) { + if let Some(path) = Parser::submod_path_from_attr(attrs, &self.directory.path) { return Ok(SubModKind::External( path, DirectoryOwnership::Owned { relative: None }, @@ -267,23 +249,18 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } // Look for nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`. - let mut mods_outside_ast = self - .find_mods_ouside_of_ast(attrs, sub_mod) - .unwrap_or(vec![]); + let mut mods_outside_ast = self.find_mods_outside_of_ast(attrs, sub_mod); let relative = match self.directory.ownership { DirectoryOwnership::Owned { relative } => relative, DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod(_) => None, }; - match parser::Parser::default_submod_path( - mod_name, - relative, - &self.directory.path, - self.parse_sess.source_map(), - ) - .result + match self + .parse_sess + .default_submod_path(mod_name, relative, &self.directory.path) + .result { - Ok(parser::ModulePathSuccess { + Ok(ModulePathSuccess { path, directory_ownership, .. @@ -324,21 +301,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } } - fn find_mods_ouside_of_ast( - &self, - attrs: &[ast::Attribute], - sub_mod: &Cow<'ast, ast::Mod>, - ) -> Option)>> { - use std::panic::{catch_unwind, AssertUnwindSafe}; - Some( - catch_unwind(AssertUnwindSafe(|| { - self.find_mods_ouside_of_ast_inner(attrs, sub_mod) - })) - .ok()?, - ) - } - - fn find_mods_ouside_of_ast_inner( + fn find_mods_outside_of_ast( &self, attrs: &[ast::Attribute], sub_mod: &Cow<'ast, ast::Mod>, @@ -350,6 +313,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { path_visitor.visit_meta_item(&meta) } } + let mut result = vec![]; for path in path_visitor.paths() { let mut actual_path = self.directory.path.clone(); @@ -357,14 +321,9 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if !actual_path.exists() { continue; } - let file_name = syntax_pos::FileName::Real(actual_path.clone()); - if self - .parse_sess - .source_map() - .get_source_file(&file_name) - .is_some() - { - // If the specfied file is already parsed, then we just use that. + + if self.parse_sess.is_file_parsed(&actual_path) { + // If the specified file is already parsed, then we just use that. result.push(( actual_path, DirectoryOwnership::Owned { relative: None }, @@ -372,32 +331,16 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { )); continue; } - let mut parser = new_sub_parser_from_file( + + let m = match Parser::parse_file_as_module( + self.directory.ownership, self.parse_sess, &actual_path, - self.directory.ownership, - None, - DUMMY_SP, - ); - parser.cfg_mods = false; - let lo = parser.token.span; - // FIXME(topecongiro) Format inner attributes (#3606). - let _mod_attrs = match parse_inner_attributes(&mut parser) { - Ok(attrs) => attrs, - Err(mut e) => { - e.cancel(); - parser.sess.span_diagnostic.reset_err_count(); - continue; - } - }; - let m = match parse_mod_items(&mut parser, lo) { - Ok(m) => m, - Err(mut e) => { - e.cancel(); - parser.sess.span_diagnostic.reset_err_count(); - continue; - } + ) { + Some(m) => m, + None => continue, }; + result.push(( actual_path, DirectoryOwnership::Owned { relative: None }, @@ -423,58 +366,6 @@ fn find_path_value(attrs: &[ast::Attribute]) -> Option { attrs.iter().flat_map(path_value).next() } -// FIXME(topecongiro) Use the method from libsyntax[1] once it become public. -// -// [1] https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/attr.rs -fn parse_inner_attributes<'a>(parser: &mut parser::Parser<'a>) -> PResult<'a, Vec> { - let mut attrs: Vec = vec![]; - loop { - match parser.token.kind { - TokenKind::Pound => { - // Don't even try to parse if it's not an inner attribute. - if !parser.look_ahead(1, |t| t == &TokenKind::Not) { - break; - } - - let attr = parser.parse_attribute(true)?; - assert_eq!(attr.style, ast::AttrStyle::Inner); - attrs.push(attr); - } - TokenKind::DocComment(s) => { - // we need to get the position of this token before we bump. - let attr = attr::mk_sugared_doc_attr(s, parser.token.span); - if attr.style == ast::AttrStyle::Inner { - attrs.push(attr); - parser.bump(); - } else { - break; - } - } - _ => break, - } - } - Ok(attrs) -} - -fn parse_mod_items<'a>(parser: &mut parser::Parser<'a>, inner_lo: Span) -> PResult<'a, ast::Mod> { - let mut items = vec![]; - while let Some(item) = parser.parse_item()? { - items.push(item); - } - - let hi = if parser.token.span.is_dummy() { - inner_lo - } else { - parser.prev_span - }; - - Ok(ast::Mod { - inner: inner_lo.to(hi), - items, - inline: false, - }) -} - fn is_cfg_if(item: &ast::Item) -> bool { match item.kind { ast::ItemKind::Mac(ref mac) => { diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index e9223ce9644..80338b89b13 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -1,11 +1,10 @@ use syntax::ast; -use syntax::parse::token::{DelimToken, TokenKind}; -use syntax::parse::{stream_to_parser_with_base_dir, Directory, ParseSess}; -use syntax::symbol::kw; use syntax::visit::Visitor; use syntax_pos::Symbol; use crate::attr::MetaVisitor; +use crate::syntux::parser::{Directory, Parser}; +use crate::syntux::session::ParseSess; pub(crate) struct ModItem { pub(crate) item: ast::Item, @@ -15,11 +14,11 @@ pub(crate) struct ModItem { pub(crate) struct CfgIfVisitor<'a> { parse_sess: &'a ParseSess, mods: Vec, - base_dir: Directory<'a>, + base_dir: &'a Directory, } impl<'a> CfgIfVisitor<'a> { - pub(crate) fn new(parse_sess: &'a ParseSess, base_dir: Directory<'a>) -> CfgIfVisitor<'a> { + pub(crate) fn new(parse_sess: &'a ParseSess, base_dir: &'a Directory) -> CfgIfVisitor<'a> { CfgIfVisitor { mods: vec![], parse_sess, @@ -65,58 +64,9 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { } }; - let mut parser = - stream_to_parser_with_base_dir(self.parse_sess, mac.tts.clone(), self.base_dir.clone()); - parser.cfg_mods = false; - let mut process_if_cfg = true; - - while parser.token.kind != TokenKind::Eof { - if process_if_cfg { - if !parser.eat_keyword(kw::If) { - return Err("Expected `if`"); - } - parser - .parse_attribute(false) - .map_err(|_| "Failed to parse attributes")?; - } - - if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) { - return Err("Expected an opening brace"); - } - - while parser.token != TokenKind::CloseDelim(DelimToken::Brace) - && parser.token.kind != TokenKind::Eof - { - let item = match parser.parse_item() { - Ok(Some(item_ptr)) => item_ptr.into_inner(), - Ok(None) => continue, - Err(mut err) => { - err.cancel(); - parser.sess.span_diagnostic.reset_err_count(); - return Err( - "Expected item inside cfg_if block, but failed to parse it as an item", - ); - } - }; - if let ast::ItemKind::Mod(..) = item.kind { - self.mods.push(ModItem { item }); - } - } - - if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) { - return Err("Expected a closing brace"); - } - - if parser.eat(&TokenKind::Eof) { - break; - } - - if !parser.eat_keyword(kw::Else) { - return Err("Expected `else`"); - } - - process_if_cfg = parser.token.is_keyword(kw::If); - } + let items = Parser::parse_cfg_if(self.parse_sess, mac, &self.base_dir)?; + self.mods + .append(&mut items.into_iter().map(|item| ModItem { item }).collect()); Ok(()) } diff --git a/src/rewrite.rs b/src/rewrite.rs index 602512e87ce..6660187619f 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -3,13 +3,13 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use syntax::parse::ParseSess; use syntax::ptr; use syntax::source_map::{SourceMap, Span}; use crate::config::{Config, IndentStyle}; use crate::shape::Shape; use crate::skip::SkipContext; +use crate::syntux::session::ParseSess; use crate::visitor::SnippetProvider; use crate::FormatReport; diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 5bd1be28486..240c5dac0fb 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -1,14 +1,36 @@ +use std::borrow::Cow; use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::path::{Path, PathBuf}; use syntax::ast; use syntax::errors::Diagnostic; use syntax::parse::parser::Parser as RawParser; -use syntax::parse::DirectoryOwnership; -use syntax::source_map::DUMMY_SP; +use syntax::parse::token::{DelimToken, TokenKind}; +use syntax::parse::{new_sub_parser_from_file, PResult}; +use syntax::source_map::{Span, DUMMY_SP}; +use syntax::symbol::kw; use crate::syntux::session::ParseSess; use crate::{Config, Input}; +pub(crate) type DirectoryOwnership = syntax::parse::DirectoryOwnership; +pub(crate) type ModulePathSuccess = syntax::parse::parser::ModulePathSuccess; + +#[derive(Clone)] +pub(crate) struct Directory { + pub(crate) path: PathBuf, + pub(crate) ownership: DirectoryOwnership, +} + +impl<'a> Directory { + pub(crate) fn to_syntax_directory(&'a self) -> syntax::parse::Directory<'a> { + syntax::parse::Directory { + path: Cow::Borrowed(&self.path), + ownership: self.ownership.clone(), + } + } +} + /// A parser for Rust source code. pub(crate) struct Parser<'a> { parser: RawParser<'a>, @@ -112,6 +134,98 @@ pub(crate) enum ParserError { } impl<'a> Parser<'a> { + pub(crate) fn submod_path_from_attr(attrs: &[ast::Attribute], path: &Path) -> Option { + syntax::parse::parser::Parser::submod_path_from_attr(attrs, path) + } + + // FIXME(topecongiro) Use the method from libsyntax[1] once it become public. + // + // [1] https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/attr.rs + fn parse_inner_attrs(parser: &mut RawParser<'a>) -> PResult<'a, Vec> { + let mut attrs: Vec = vec![]; + loop { + match parser.token.kind { + TokenKind::Pound => { + // Don't even try to parse if it's not an inner attribute. + if !parser.look_ahead(1, |t| t == &TokenKind::Not) { + break; + } + + let attr = parser.parse_attribute(true)?; + assert_eq!(attr.style, ast::AttrStyle::Inner); + attrs.push(attr); + } + TokenKind::DocComment(s) => { + // we need to get the position of this token before we bump. + let attr = syntax::attr::mk_sugared_doc_attr(s, parser.token.span); + if attr.style == ast::AttrStyle::Inner { + attrs.push(attr); + parser.bump(); + } else { + break; + } + } + _ => break, + } + } + Ok(attrs) + } + + fn parse_mod_items(parser: &mut RawParser<'a>, span: Span) -> PResult<'a, ast::Mod> { + let mut items = vec![]; + while let Some(item) = parser.parse_item()? { + items.push(item); + } + + let hi = if parser.token.span.is_dummy() { + span + } else { + parser.prev_span + }; + + Ok(ast::Mod { + inner: span.to(hi), + items, + inline: false, + }) + } + + pub(crate) fn parse_file_as_module( + directory_ownership: DirectoryOwnership, + sess: &'a ParseSess, + path: &Path, + ) -> Option { + let result = catch_unwind(AssertUnwindSafe(|| { + let mut parser = + new_sub_parser_from_file(sess.inner(), &path, directory_ownership, None, DUMMY_SP); + + parser.cfg_mods = false; + let lo = parser.token.span; + // FIXME(topecongiro) Format inner attributes (#3606). + match Parser::parse_inner_attrs(&mut parser) { + Ok(_attrs) => (), + Err(mut e) => { + e.cancel(); + sess.reset_errors(); + return None; + } + } + + match Parser::parse_mod_items(&mut parser, lo) { + Ok(m) => Some(m.clone()), + Err(mut db) => { + db.cancel(); + sess.reset_errors(); + None + } + } + })); + match result { + Ok(Some(m)) => Some(m), + _ => None, + } + } + pub(crate) fn parse_crate( config: &'a Config, input: Input, @@ -151,4 +265,84 @@ impl<'a> Parser<'a> { Err(_) => Err(ParserError::ParsePanicError), } } + + pub(crate) fn parse_cfg_if( + sess: &'a ParseSess, + mac: &'a ast::Mac, + base_dir: &Directory, + ) -> Result, &'static str> { + match catch_unwind(AssertUnwindSafe(|| { + Parser::parse_cfg_if_inner(sess, mac, base_dir) + })) { + Ok(Ok(items)) => Ok(items), + Ok(err @ Err(_)) => err, + Err(..) => Err("failed to parse cfg_if!"), + } + } + + fn parse_cfg_if_inner( + sess: &'a ParseSess, + mac: &'a ast::Mac, + base_dir: &Directory, + ) -> Result, &'static str> { + let mut parser = syntax::parse::stream_to_parser_with_base_dir( + sess.inner(), + mac.tts.clone(), + base_dir.to_syntax_directory(), + ); + + parser.cfg_mods = false; + let mut items = vec![]; + let mut process_if_cfg = true; + + while parser.token.kind != TokenKind::Eof { + if process_if_cfg { + if !parser.eat_keyword(kw::If) { + return Err("Expected `if`"); + } + parser + .parse_attribute(false) + .map_err(|_| "Failed to parse attributes")?; + } + + if !parser.eat(&TokenKind::OpenDelim(DelimToken::Brace)) { + return Err("Expected an opening brace"); + } + + while parser.token != TokenKind::CloseDelim(DelimToken::Brace) + && parser.token.kind != TokenKind::Eof + { + let item = match parser.parse_item() { + Ok(Some(item_ptr)) => item_ptr.into_inner(), + Ok(None) => continue, + Err(mut err) => { + err.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + return Err( + "Expected item inside cfg_if block, but failed to parse it as an item", + ); + } + }; + if let ast::ItemKind::Mod(..) = item.kind { + items.push(item); + } + } + + if !parser.eat(&TokenKind::CloseDelim(DelimToken::Brace)) { + return Err("Expected a closing brace"); + } + + if parser.eat(&TokenKind::Eof) { + break; + } + + if !parser.eat_keyword(kw::Else) { + return Err("Expected `else`"); + } + + process_if_cfg = parser.token.is_keyword(kw::If); + } + + Ok(items) + } } diff --git a/src/syntux/session.rs b/src/syntux/session.rs index c3cbe22c2a4..ab3b0e62ce5 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -1,6 +1,8 @@ use std::cell::RefCell; +use std::path::Path; use std::rc::Rc; +use syntax::ast; use syntax::errors::emitter::{ColorConfig, Emitter, EmitterWriter}; use syntax::errors::{Diagnostic, Handler}; use syntax::parse::ParseSess as RawParseSess; @@ -126,7 +128,27 @@ impl ParseSess { }) } - pub(crate) fn can_reset_errors(&self) -> bool { + pub(crate) fn default_submod_path( + &self, + id: ast::Ident, + relative: Option, + dir_path: &Path, + ) -> syntax::parse::parser::ModulePath { + syntax::parse::parser::Parser::default_submod_path( + id, + relative, + dir_path, + self.source_map(), + ) + } + + pub(crate) fn is_file_parsed(&self, path: &Path) -> bool { + self.source_map() + .get_source_file(&syntax_pos::FileName::Real(path.to_path_buf())) + .is_some() + } + + pub(super) fn can_reset_errors(&self) -> bool { *self.can_reset_errors.borrow() } diff --git a/src/visitor.rs b/src/visitor.rs index 15490798a6e..2da8304cfa4 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,7 +1,6 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use syntax::parse::ParseSess; use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; use syntax::{ast, visit}; @@ -23,6 +22,7 @@ use crate::skip::{is_skip_attr, SkipContext}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; use crate::stmt::Stmt; +use crate::syntux::session::ParseSess; use crate::utils::{ self, contains_skip, count_newlines, depr_skip_annotation, inner_attributes, last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, From 0508c70ab947297d6f61254b2799292952c2f066 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 22 Oct 2019 16:22:43 +0900 Subject: [PATCH 06/12] temp --- Cargo.toml | 3 +-- src/lib.rs | 1 - src/modules.rs | 8 ++++++-- src/syntux/session.rs | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 547ab70d7a2..ec72692de94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ ignore = "0.4.6" annotate-snippets = { version = "0.6", features = ["ansi_term"] } structopt = "0.3" rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } +lazy_static = "1.0.0" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` @@ -74,5 +75,3 @@ version = "610.0.0" package = "rustc-ap-syntax_pos" version = "610.0.0" -[dev-dependencies] -lazy_static = "1.0.0" diff --git a/src/lib.rs b/src/lib.rs index 9828b023ce0..0763ab2e75f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,6 @@ #[macro_use] extern crate derive_new; -#[cfg(test)] #[macro_use] extern crate lazy_static; #[macro_use] diff --git a/src/modules.rs b/src/modules.rs index d8a7fc16645..e0dceb3266b 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -6,7 +6,7 @@ use syntax::ast; use syntax::source_map; use syntax::symbol::sym; use syntax::visit::Visitor; -use syntax_pos::{self, symbol::Symbol}; +use syntax_pos::symbol::Symbol; use crate::attr::MetaVisitor; use crate::config::FileName; @@ -19,6 +19,10 @@ mod visitor; type FileModMap<'ast> = BTreeMap>; +lazy_static! { + static ref CFG_IF: Symbol = Symbol::intern("cfg_if"); +} + /// Maps each module to the corresponding file. pub(crate) struct ModResolver<'ast, 'sess> { parse_sess: &'sess ParseSess, @@ -370,7 +374,7 @@ fn is_cfg_if(item: &ast::Item) -> bool { match item.kind { ast::ItemKind::Mac(ref mac) => { if let Some(first_segment) = mac.path.segments.first() { - if first_segment.ident.name == Symbol::intern("cfg_if") { + if first_segment.ident.name == *CFG_IF { return true; } } diff --git a/src/syntux/session.rs b/src/syntux/session.rs index ab3b0e62ce5..04edd941e22 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -172,7 +172,7 @@ impl ParseSess { self.parse_sess.span_diagnostic.reset_err_count(); } - pub(crate) fn source_map(&self) -> &SourceMap { + fn source_map(&self) -> &SourceMap { &self.parse_sess.source_map() } From 96a4c88dc7daf01c2efcc271d0736452fac83f5c Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 22 Oct 2019 22:57:13 +0900 Subject: [PATCH 07/12] Hide SourceMap --- src/closures.rs | 6 ++-- src/comment.rs | 4 +-- src/expr.rs | 27 +++++++-------- src/formatting.rs | 46 +++++++++---------------- src/items.rs | 6 ++-- src/lists.rs | 4 +-- src/macros.rs | 10 +++--- src/matches.rs | 7 ++-- src/missed_spans.rs | 25 ++++++-------- src/modules.rs | 10 ++---- src/reorder.rs | 4 +-- src/rewrite.rs | 7 ++-- src/source_file.rs | 17 ++++----- src/source_map.rs | 29 ++-------------- src/syntux/session.rs | 80 ++++++++++++++++++++++++++++++++++++++++--- src/utils.rs | 2 +- src/visitor.rs | 70 +++++++++++++++++++------------------ 17 files changed, 187 insertions(+), 167 deletions(-) diff --git a/src/closures.rs b/src/closures.rs index eaa42b991f2..69ffd888957 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -43,7 +43,7 @@ pub(crate) fn rewrite_closure( if let ast::ExprKind::Block(ref block, _) = body.kind { // The body of the closure is an empty block. - if block.stmts.is_empty() && !block_contains_comment(block, context.source_map) { + if block.stmts.is_empty() && !block_contains_comment(context, block) { return body .rewrite(context, shape) .map(|s| format!("{} {}", prefix, s)); @@ -112,7 +112,7 @@ fn needs_block(block: &ast::Block, prefix: &str, context: &RewriteContext<'_>) - is_unsafe_block(block) || block.stmts.len() > 1 || has_attributes - || block_contains_comment(block, context.source_map) + || block_contains_comment(context, block) || prefix.contains('\n') } @@ -304,7 +304,7 @@ pub(crate) fn rewrite_last_closure( ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) && !context.inside_macro() - && is_simple_block(block, Some(&body.attrs), context.source_map) => + && is_simple_block(context, block, Some(&body.attrs)) => { stmt_expr(&block.stmts[0]).unwrap_or(body) } diff --git a/src/comment.rs b/src/comment.rs index e725adea6ba..6350e1d3f99 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1556,10 +1556,10 @@ pub(crate) fn recover_comment_removed( // We missed some comments. Warn and keep the original text. if context.config.error_on_unformatted() { context.report.append( - context.source_map.span_to_filename(span).into(), + context.parse_sess.span_to_filename(span), vec![FormattingError::from_span( span, - &context.source_map, + &context.parse_sess, ErrorKind::LostComment, )], ); diff --git a/src/expr.rs b/src/expr.rs index 8665f2a7248..76c187a7e61 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -3,7 +3,7 @@ use std::cmp::min; use itertools::Itertools; use syntax::parse::token::{DelimToken, LitKind}; -use syntax::source_map::{BytePos, SourceMap, Span}; +use syntax::source_map::{BytePos, Span}; use syntax::{ast, ptr}; use crate::chains::rewrite_chain; @@ -430,7 +430,7 @@ fn rewrite_empty_block( return None; } - if !block_contains_comment(block, context.source_map) && shape.width >= 2 { + if !block_contains_comment(context, block) && shape.width >= 2 { return Some(format!("{}{}{{}}", prefix, label_str)); } @@ -487,7 +487,7 @@ fn rewrite_single_line_block( label: Option, shape: Shape, ) -> Option { - if is_simple_block(block, attrs, context.source_map) { + if is_simple_block(context, block, attrs) { let expr_shape = shape.offset_left(last_line_width(prefix))?; let expr_str = block.stmts[0].rewrite(context, expr_shape)?; let label_str = rewrite_label(label); @@ -750,8 +750,8 @@ impl<'a> ControlFlow<'a> { let fixed_cost = self.keyword.len() + " { } else { }".len(); if let ast::ExprKind::Block(ref else_node, _) = else_block.kind { - if !is_simple_block(self.block, None, context.source_map) - || !is_simple_block(else_node, None, context.source_map) + if !is_simple_block(context, self.block, None) + || !is_simple_block(context, else_node, None) || pat_expr_str.contains('\n') { return None; @@ -1105,9 +1105,8 @@ fn extract_comment(span: Span, context: &RewriteContext<'_>, shape: Shape) -> Op } } -pub(crate) fn block_contains_comment(block: &ast::Block, source_map: &SourceMap) -> bool { - let snippet = source_map.span_to_snippet(block.span).unwrap(); - contains_comment(&snippet) +pub(crate) fn block_contains_comment(context: &RewriteContext<'_>, block: &ast::Block) -> bool { + contains_comment(context.snippet(block.span)) } // Checks that a block contains no statements, an expression and no comments or @@ -1115,37 +1114,37 @@ pub(crate) fn block_contains_comment(block: &ast::Block, source_map: &SourceMap) // FIXME: incorrectly returns false when comment is contained completely within // the expression. pub(crate) fn is_simple_block( + context: &RewriteContext<'_>, block: &ast::Block, attrs: Option<&[ast::Attribute]>, - source_map: &SourceMap, ) -> bool { (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) - && !block_contains_comment(block, source_map) + && !block_contains_comment(context, block) && attrs.map_or(true, |a| a.is_empty())) } /// Checks whether a block contains at most one statement or expression, and no /// comments or attributes. pub(crate) fn is_simple_block_stmt( + context: &RewriteContext<'_>, block: &ast::Block, attrs: Option<&[ast::Attribute]>, - source_map: &SourceMap, ) -> bool { block.stmts.len() <= 1 - && !block_contains_comment(block, source_map) + && !block_contains_comment(context, block) && attrs.map_or(true, |a| a.is_empty()) } /// Checks whether a block contains no statements, expressions, comments, or /// inner attributes. pub(crate) fn is_empty_block( + context: &RewriteContext<'_>, block: &ast::Block, attrs: Option<&[ast::Attribute]>, - source_map: &SourceMap, ) -> bool { block.stmts.is_empty() - && !block_contains_comment(block, source_map) + && !block_contains_comment(context, block) && attrs.map_or(true, |a| inner_attributes(a).is_empty()) } diff --git a/src/formatting.rs b/src/formatting.rs index 82e68e9ecea..0c01a3c4c7a 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -5,7 +5,7 @@ use std::io::{self, Write}; use std::time::{Duration, Instant}; use syntax::ast; -use syntax::source_map::{SourceMap, Span}; +use syntax::source_map::Span; use self::newline_style::apply_newline_style; use crate::comment::{CharClasses, FullCodeCharKind}; @@ -14,7 +14,7 @@ use crate::issues::BadIssueSeeker; use crate::syntux::parser::{DirectoryOwnership, Parser, ParserError}; use crate::syntux::session::ParseSess; use crate::utils::count_newlines; -use crate::visitor::{FmtVisitor, SnippetProvider}; +use crate::visitor::FmtVisitor; use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session}; mod newline_style; @@ -141,13 +141,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { module: &ast::Mod, is_root: bool, ) -> Result<(), ErrorKind> { - let source_file = self - .parse_session - .source_map() - .lookup_char_pos(module.inner.lo()) - .file; - let big_snippet = source_file.src.as_ref().unwrap(); - let snippet_provider = SnippetProvider::new(source_file.start_pos, big_snippet); + let snippet_provider = self.parse_session.snippet_provider(module.inner); let mut visitor = FmtVisitor::from_source_map( &self.parse_session, &self.config, @@ -158,16 +152,16 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { // Format inner attributes if available. if !self.krate.attrs.is_empty() && is_root { - visitor.skip_empty_lines(source_file.end_pos); + visitor.skip_empty_lines(snippet_provider.end_pos()); if visitor.visit_attrs(&self.krate.attrs, ast::AttrStyle::Inner) { visitor.push_rewrite(module.inner, None); } else { - visitor.format_separate_mod(module, &*source_file); + visitor.format_separate_mod(module, snippet_provider.end_pos()); } } else { - visitor.last_pos = source_file.start_pos; - visitor.skip_empty_lines(source_file.end_pos); - visitor.format_separate_mod(module, &*source_file); + visitor.last_pos = snippet_provider.start_pos(); + visitor.skip_empty_lines(snippet_provider.end_pos()); + visitor.format_separate_mod(module, snippet_provider.end_pos()); }; debug_assert_eq!( @@ -192,7 +186,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { apply_newline_style( self.config.newline_style(), &mut visitor.buffer, - &big_snippet, + snippet_provider.entire_snippet(), ); if visitor.macro_rewrite_failure { @@ -202,7 +196,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { .add_non_formatted_ranges(visitor.skipped_range.borrow().clone()); self.handler.handle_formatted_file( - self.parse_session.source_map(), + &self.parse_session, path, visitor.buffer.to_owned(), &mut self.report, @@ -214,7 +208,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { trait FormatHandler { fn handle_formatted_file( &mut self, - source_map: &SourceMap, + parse_session: &ParseSess, path: FileName, result: String, report: &mut FormatReport, @@ -225,14 +219,14 @@ impl<'b, T: Write + 'b> FormatHandler for Session<'b, T> { // Called for each formatted file. fn handle_formatted_file( &mut self, - source_map: &SourceMap, + parse_session: &ParseSess, path: FileName, result: String, report: &mut FormatReport, ) -> Result<(), ErrorKind> { if let Some(ref mut out) = self.out { match source_file::write_file( - Some(source_map), + Some(parse_session), &path, &result, out, @@ -265,23 +259,15 @@ pub(crate) struct FormattingError { impl FormattingError { pub(crate) fn from_span( span: Span, - source_map: &SourceMap, + parse_sess: &ParseSess, kind: ErrorKind, ) -> FormattingError { FormattingError { - line: source_map.lookup_char_pos(span.lo()).line, + line: parse_sess.line_of_byte_pos(span.lo()), is_comment: kind.is_comment(), kind, is_string: false, - line_buffer: source_map - .span_to_lines(span) - .ok() - .and_then(|fl| { - fl.file - .get_line(fl.lines[0].line_index) - .map(std::borrow::Cow::into_owned) - }) - .unwrap_or_else(String::new), + line_buffer: parse_sess.span_to_first_line_string(span), } } diff --git a/src/items.rs b/src/items.rs index 401cf78d721..6532bf5669f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -360,17 +360,17 @@ impl<'a> FmtVisitor<'a> { return None; } - let source_map = self.get_context().source_map; + let context = self.get_context(); if self.config.empty_item_single_line() - && is_empty_block(block, None, source_map) + && is_empty_block(&context, block, None) && self.block_indent.width() + fn_str.len() + 3 <= self.config.max_width() && !last_line_contains_single_line_comment(fn_str) { return Some(format!("{} {{}}", fn_str)); } - if !self.config.fn_single_line() || !is_simple_block_stmt(block, None, source_map) { + if !self.config.fn_single_line() || !is_simple_block_stmt(&context, block, None) { return None; } diff --git a/src/lists.rs b/src/lists.rs index 077d08cb4e4..77c076540f1 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -560,7 +560,7 @@ pub(crate) struct ListItems<'a, I, F1, F2, F3> where I: Iterator, { - snippet_provider: &'a SnippetProvider<'a>, + snippet_provider: &'a SnippetProvider, inner: Peekable, get_lo: F1, get_hi: F2, @@ -777,7 +777,7 @@ where #[allow(clippy::too_many_arguments)] // Creates an iterator over a list's items with associated comments. pub(crate) fn itemize_list<'a, T, I, F1, F2, F3>( - snippet_provider: &'a SnippetProvider<'_>, + snippet_provider: &'a SnippetProvider, inner: I, terminator: &'a str, separator: &'a str, diff --git a/src/macros.rs b/src/macros.rs index b5fd838feb4..710e53e2304 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -182,8 +182,8 @@ fn return_macro_parse_failure_fallback( } context.skipped_range.borrow_mut().push(( - context.source_map.lookup_line(span.lo()).unwrap().line, - context.source_map.lookup_line(span.hi()).unwrap().line, + context.parse_sess.line_of_byte_pos(span.lo()), + context.parse_sess.line_of_byte_pos(span.hi()), )); // Return the snippet unmodified if the macro is not block-like @@ -290,7 +290,7 @@ fn rewrite_macro_inner( } } - let mut parser = new_parser_from_tts(context.parse_session.inner(), ts.trees().collect()); + let mut parser = new_parser_from_tts(context.parse_sess.inner(), ts.trees().collect()); let mut arg_vec = Vec::new(); let mut vec_with_semi = false; let mut trailing_comma = false; @@ -1192,7 +1192,7 @@ fn next_space(tok: &TokenKind) -> SpaceState { pub(crate) fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext<'_>) -> Option { if &mac.path.to_string() == "try" { let ts: TokenStream = mac.tts.clone(); - let mut parser = new_parser_from_tts(context.parse_session.inner(), ts.trees().collect()); + let mut parser = new_parser_from_tts(context.parse_sess.inner(), ts.trees().collect()); Some(ast::Expr { id: ast::NodeId::root(), // dummy value @@ -1424,7 +1424,7 @@ fn format_lazy_static( ts: &TokenStream, ) -> Option { let mut result = String::with_capacity(1024); - let mut parser = new_parser_from_tts(context.parse_session.inner(), ts.trees().collect()); + let mut parser = new_parser_from_tts(context.parse_sess.inner(), ts.trees().collect()); let nested_shape = shape .block_indent(context.config.tab_spaces()) .with_max_width(context.config); diff --git a/src/matches.rs b/src/matches.rs index fcfb8055f01..1f84d8bc54f 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -276,7 +276,7 @@ fn block_can_be_flattened<'a>( ast::ExprKind::Block(ref block, _) if !is_unsafe_block(block) && !context.inside_macro() - && is_simple_block(block, Some(&expr.attrs), context.source_map) => + && is_simple_block(context, block, Some(&expr.attrs)) => { Some(&*block) } @@ -332,10 +332,7 @@ fn rewrite_match_body( shape.offset_left(extra_offset(pats_str, shape) + 4), ); let (is_block, is_empty_block) = if let ast::ExprKind::Block(ref block, _) = body.kind { - ( - true, - is_empty_block(block, Some(&body.attrs), context.source_map), - ) + (true, is_empty_block(context, block, Some(&body.attrs))) } else { (false, false) }; diff --git a/src/missed_spans.rs b/src/missed_spans.rs index a957d3b3e30..47a449aec3f 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -86,9 +86,8 @@ impl<'a> FmtVisitor<'a> { assert!( start < end, - "Request to format inverted span: {:?} to {:?}", - self.source_map.lookup_char_pos(start), - self.source_map.lookup_char_pos(end) + "Request to format inverted span: {}", + self.parse_sess.span_to_debug_info(mk_sp(start, end)), ); self.last_pos = end; @@ -139,26 +138,22 @@ impl<'a> FmtVisitor<'a> { // Get a snippet from the file start to the span's hi without allocating. // We need it to determine what precedes the current comment. If the comment // follows code on the same line, we won't touch it. - let big_span_lo = self.source_map.lookup_char_pos(span.lo()).file.start_pos; - let local_begin = self.source_map.lookup_byte_offset(big_span_lo); - let local_end = self.source_map.lookup_byte_offset(span.hi()); - let start_index = local_begin.pos.to_usize(); - let end_index = local_end.pos.to_usize(); - let big_snippet = &local_begin.sf.src.as_ref().unwrap()[start_index..end_index]; - + let big_span_lo = self.snippet_provider.start_pos(); + let big_snippet = self.snippet_provider.entire_snippet(); let big_diff = (span.lo() - big_span_lo).to_usize(); + let snippet = self.snippet(span); debug!("write_snippet `{}`", snippet); - self.write_snippet_inner(big_snippet, big_diff, snippet, span, process_last_snippet); + self.write_snippet_inner(big_snippet, snippet, big_diff, span, process_last_snippet); } fn write_snippet_inner( &mut self, big_snippet: &str, - big_diff: usize, old_snippet: &str, + big_diff: usize, span: Span, process_last_snippet: F, ) where @@ -167,9 +162,9 @@ impl<'a> FmtVisitor<'a> { // Trim whitespace from the right hand side of each line. // Annoyingly, the library functions for splitting by lines etc. are not // quite right, so we must do it ourselves. - let char_pos = self.source_map.lookup_char_pos(span.lo()); - let file_name = &char_pos.file.name.clone().into(); - let mut status = SnippetStatus::new(char_pos.line); + let line = self.parse_sess.line_of_byte_pos(span.lo()); + let file_name = &self.parse_sess.span_to_filename(span); + let mut status = SnippetStatus::new(line); let snippet = &*transform_missing_snippet(self.config, old_snippet); diff --git a/src/modules.rs b/src/modules.rs index e0dceb3266b..0c35cc2d073 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -3,7 +3,6 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::source_map; use syntax::symbol::sym; use syntax::visit::Visitor; use syntax_pos::symbol::Symbol; @@ -66,12 +65,9 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { mut self, krate: &'ast ast::Crate, ) -> Result, String> { - let root_filename = self.parse_sess.source_map().span_to_filename(krate.span); + let root_filename = self.parse_sess.span_to_filename(krate.span); self.directory.path = match root_filename { - source_map::FileName::Real(ref path) => path - .parent() - .expect("Parent directory should exists") - .to_path_buf(), + FileName::Real(ref p) => p.parent().unwrap_or(Path::new("")).to_path_buf(), _ => PathBuf::new(), }; @@ -81,7 +77,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } self.file_map - .insert(root_filename.into(), Cow::Borrowed(&krate.module)); + .insert(root_filename, Cow::Borrowed(&krate.module)); Ok(self.file_map) } diff --git a/src/reorder.rs b/src/reorder.rs index 5a6a45118b9..653e69b5ef8 100644 --- a/src/reorder.rs +++ b/src/reorder.rs @@ -208,13 +208,13 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { item_kind: ReorderableItemKind, in_group: bool, ) -> usize { - let mut last = self.source_map.lookup_line_range(items[0].span()); + let mut last = self.parse_sess.lookup_line_range(items[0].span()); let item_length = items .iter() .take_while(|ppi| { item_kind.is_same_item_kind(&***ppi) && (!in_group || { - let current = self.source_map.lookup_line_range(ppi.span()); + let current = self.parse_sess.lookup_line_range(ppi.span()); let in_same_group = current.lo < last.hi + 2; last = current; in_same_group diff --git a/src/rewrite.rs b/src/rewrite.rs index 6660187619f..cd868bdf8f6 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -4,7 +4,7 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; use syntax::ptr; -use syntax::source_map::{SourceMap, Span}; +use syntax::source_map::Span; use crate::config::{Config, IndentStyle}; use crate::shape::Shape; @@ -26,8 +26,7 @@ impl Rewrite for ptr::P { #[derive(Clone)] pub(crate) struct RewriteContext<'a> { - pub(crate) parse_session: &'a ParseSess, - pub(crate) source_map: &'a SourceMap, + pub(crate) parse_sess: &'a ParseSess, pub(crate) config: &'a Config, pub(crate) inside_macro: Rc>, // Force block indent style even if we are using visual indent style. @@ -37,7 +36,7 @@ pub(crate) struct RewriteContext<'a> { pub(crate) is_if_else_block: Cell, // When rewriting chain, veto going multi line except the last element pub(crate) force_one_line_chain: Cell, - pub(crate) snippet_provider: &'a SnippetProvider<'a>, + pub(crate) snippet_provider: &'a SnippetProvider, // Used for `format_snippet` pub(crate) macro_rewrite_failure: Cell, pub(crate) report: FormatReport, diff --git a/src/source_file.rs b/src/source_file.rs index b6764ee7464..683e0bfbcab 100644 --- a/src/source_file.rs +++ b/src/source_file.rs @@ -2,10 +2,9 @@ use std::fs; use std::io::{self, Write}; use std::path::Path; -use syntax::source_map::SourceMap; - use crate::config::FileName; use crate::emitter::{self, Emitter}; +use crate::syntux::session::ParseSess; use crate::NewlineStyle; #[cfg(test)] @@ -14,6 +13,7 @@ use crate::config::Config; use crate::create_emitter; #[cfg(test)] use crate::formatting::FileRecord; +use std::rc::Rc; // Append a newline to the end of each file. pub(crate) fn append_newline(s: &mut String) { @@ -48,7 +48,7 @@ where } pub(crate) fn write_file( - source_map: Option<&SourceMap>, + parse_sess: Option<&ParseSess>, filename: &FileName, formatted_text: &str, out: &mut T, @@ -84,20 +84,17 @@ where // source map instead of hitting the file system. This also supports getting // original text for `FileName::Stdin`. let original_text = if newline_style != NewlineStyle::Auto && *filename != FileName::Stdin { - fs::read_to_string(ensure_real_path(filename))? + Rc::new(fs::read_to_string(ensure_real_path(filename))?) } else { - match source_map - .and_then(|x| x.get_source_file(&filename.into())) - .and_then(|x| x.src.as_ref().map(ToString::to_string)) - { + match parse_sess.and_then(|sess| sess.get_original_snippet(filename)) { Some(ori) => ori, - None => fs::read_to_string(ensure_real_path(filename))?, + None => Rc::new(fs::read_to_string(ensure_real_path(filename))?), } }; let formatted_file = emitter::FormattedFile { filename, - original_text: &original_text, + original_text: original_text.as_str(), formatted_text, }; diff --git a/src/source_map.rs b/src/source_map.rs index b1ab83e7aba..c1562f36a5a 100644 --- a/src/source_map.rs +++ b/src/source_map.rs @@ -1,11 +1,10 @@ //! This module contains utilities that work with the `SourceMap` from `libsyntax`/`syntex_syntax`. //! This includes extension traits and methods for looking up spans and line ranges for AST nodes. -use syntax::source_map::{BytePos, SourceMap, Span}; +use syntax::source_map::{BytePos, Span}; use crate::comment::FindUncommented; use crate::config::file_lines::LineRange; -use crate::utils::starts_with_newline; use crate::visitor::SnippetProvider; pub(crate) trait SpanUtils { @@ -26,7 +25,7 @@ pub(crate) trait LineRangeUtils { fn lookup_line_range(&self, span: Span) -> LineRange; } -impl<'a> SpanUtils for SnippetProvider<'a> { +impl SpanUtils for SnippetProvider { fn span_after(&self, original: Span, needle: &str) -> BytePos { self.opt_span_after(original, needle).unwrap_or_else(|| { panic!( @@ -81,27 +80,3 @@ impl<'a> SpanUtils for SnippetProvider<'a> { Some(original.lo() + BytePos(offset as u32)) } } - -impl LineRangeUtils for SourceMap { - fn lookup_line_range(&self, span: Span) -> LineRange { - let snippet = self.span_to_snippet(span).unwrap_or_default(); - let lo = self.lookup_line(span.lo()).unwrap(); - let hi = self.lookup_line(span.hi()).unwrap(); - - debug_assert_eq!( - lo.sf.name, hi.sf.name, - "span crossed file boundary: lo: {:?}, hi: {:?}", - lo, hi - ); - - // in case the span starts with a newline, the line range is off by 1 without the - // adjustment below - let offset = 1 + if starts_with_newline(&snippet) { 1 } else { 0 }; - // Line numbers start at 1 - LineRange { - file: lo.sf.clone(), - lo: lo.line + offset, - hi: hi.line + offset, - } - } -} diff --git a/src/syntux/session.rs b/src/syntux/session.rs index 04edd941e22..deb8ebbcfa6 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -7,8 +7,13 @@ use syntax::errors::emitter::{ColorConfig, Emitter, EmitterWriter}; use syntax::errors::{Diagnostic, Handler}; use syntax::parse::ParseSess as RawParseSess; use syntax::source_map::{FilePathMapping, SourceMap}; +use syntax_pos::{BytePos, Span}; +use crate::config::file_lines::LineRange; use crate::ignore_path::IgnorePathSet; +use crate::source_map::LineRangeUtils; +use crate::utils::starts_with_newline; +use crate::visitor::SnippetProvider; use crate::{Config, ErrorKind, FileName}; /// ParseSess holds structs necessary for constructing a parser. @@ -138,12 +143,13 @@ impl ParseSess { id, relative, dir_path, - self.source_map(), + self.parse_sess.source_map(), ) } pub(crate) fn is_file_parsed(&self, path: &Path) -> bool { - self.source_map() + self.parse_sess + .source_map() .get_source_file(&syntax_pos::FileName::Real(path.to_path_buf())) .is_some() } @@ -160,6 +166,32 @@ impl ParseSess { self.parse_sess.span_diagnostic = Handler::with_emitter(true, None, silent_emitter()); } + pub(crate) fn span_to_filename(&self, span: Span) -> FileName { + self.parse_sess.source_map().span_to_filename(span).into() + } + + pub(crate) fn span_to_first_line_string(&self, span: Span) -> String { + let file_lines = self.parse_sess.source_map().span_to_lines(span).ok(); + + let first_line_str = match file_lines { + Some(fl) => fl + .file + .get_line(fl.lines[0].line_index) + .map(|s| s.into_owned()), + None => return String::new(), + }; + + first_line_str.unwrap_or(String::new()) + } + + pub(crate) fn line_of_byte_pos(&self, pos: BytePos) -> usize { + self.parse_sess.source_map().lookup_char_pos(pos).line + } + + pub(crate) fn span_to_debug_info(&self, span: Span) -> String { + self.parse_sess.source_map().span_to_string(span) + } + pub(crate) fn inner(&self) -> &RawParseSess { &self.parse_sess } @@ -172,8 +204,20 @@ impl ParseSess { self.parse_sess.span_diagnostic.reset_err_count(); } - fn source_map(&self) -> &SourceMap { - &self.parse_sess.source_map() + pub(crate) fn snippet_provider(&self, span: Span) -> SnippetProvider { + let source_file = self.parse_sess.source_map().lookup_char_pos(span.lo()).file; + SnippetProvider::new( + source_file.start_pos, + source_file.end_pos, + Rc::clone(source_file.src.as_ref().unwrap()), + ) + } + + pub(crate) fn get_original_snippet(&self, file_name: &FileName) -> Option> { + self.parse_sess + .source_map() + .get_source_file(&file_name.into()) + .and_then(|source_file| source_file.src.clone()) } pub(crate) fn emit_diagnostics(&self, diagnostics: Vec) { @@ -182,3 +226,31 @@ impl ParseSess { } } } + +impl LineRangeUtils for ParseSess { + fn lookup_line_range(&self, span: Span) -> LineRange { + let snippet = self + .parse_sess + .source_map() + .span_to_snippet(span) + .unwrap_or_default(); + let lo = self.parse_sess.source_map().lookup_line(span.lo()).unwrap(); + let hi = self.parse_sess.source_map().lookup_line(span.hi()).unwrap(); + + debug_assert_eq!( + lo.sf.name, hi.sf.name, + "span crossed file boundary: lo: {:?}, hi: {:?}", + lo, hi + ); + + // in case the span starts with a newline, the line range is off by 1 without the + // adjustment below + let offset = 1 + if starts_with_newline(&snippet) { 1 } else { 0 }; + // Line numbers start at 1 + LineRange { + file: lo.sf.clone(), + lo: lo.line + offset, + hi: hi.line + offset, + } + } +} diff --git a/src/utils.rs b/src/utils.rs index d01a0ff73ba..6f68f205a93 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -343,7 +343,7 @@ macro_rules! out_of_file_lines_range { && !$self .config .file_lines() - .intersects(&$self.source_map.lookup_line_range($span)) + .intersects(&$self.parse_sess.lookup_line_range($span)) }; } diff --git a/src/visitor.rs b/src/visitor.rs index 2da8304cfa4..9646e9cf9d6 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,7 +1,7 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use syntax::source_map::{self, BytePos, Pos, SourceMap, Span}; +use syntax::source_map::{BytePos, Pos, Span}; use syntax::{ast, visit}; use crate::attr::*; @@ -30,40 +30,53 @@ use crate::utils::{ use crate::{ErrorKind, FormatReport, FormattingError}; /// Creates a string slice corresponding to the specified span. -pub(crate) struct SnippetProvider<'a> { +pub(crate) struct SnippetProvider { /// A pointer to the content of the file we are formatting. - big_snippet: &'a str, + big_snippet: Rc, /// A position of the start of `big_snippet`, used as an offset. start_pos: usize, + /// A end position of the file that this snippet lives. + end_pos: usize, } -impl<'a> SnippetProvider<'a> { +impl SnippetProvider { pub(crate) fn span_to_snippet(&self, span: Span) -> Option<&str> { let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; Some(&self.big_snippet[start_index..end_index]) } - pub(crate) fn new(start_pos: BytePos, big_snippet: &'a str) -> Self { + pub(crate) fn new(start_pos: BytePos, end_pos: BytePos, big_snippet: Rc) -> Self { let start_pos = start_pos.to_usize(); + let end_pos = end_pos.to_usize(); SnippetProvider { big_snippet, start_pos, + end_pos, } } + + pub(crate) fn entire_snippet(&self) -> &str { + self.big_snippet.as_str() + } + pub(crate) fn start_pos(&self) -> BytePos { + BytePos::from_usize(self.start_pos) + } + pub(crate) fn end_pos(&self) -> BytePos { + BytePos::from_usize(self.end_pos) + } } pub(crate) struct FmtVisitor<'a> { parent_context: Option<&'a RewriteContext<'a>>, - pub(crate) parse_session: &'a ParseSess, - pub(crate) source_map: &'a SourceMap, + pub(crate) parse_sess: &'a ParseSess, pub(crate) buffer: String, pub(crate) last_pos: BytePos, // FIXME: use an RAII util or closure for indenting pub(crate) block_indent: Indent, pub(crate) config: &'a Config, pub(crate) is_if_else_block: bool, - pub(crate) snippet_provider: &'a SnippetProvider<'a>, + pub(crate) snippet_provider: &'a SnippetProvider, pub(crate) line_number: usize, /// List of 1-based line ranges which were annotated with skip /// Both bounds are inclusifs. @@ -98,10 +111,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { fn visit_stmt(&mut self, stmt: &Stmt<'_>) { debug!( - "visit_stmt: {:?} {:?} `{}`", - self.source_map.lookup_char_pos(stmt.span().lo()), - self.source_map.lookup_char_pos(stmt.span().hi()), - self.snippet(stmt.span()), + "visit_stmt: {}", + self.parse_sess.span_to_debug_info(stmt.span()) ); // https://github.com/rust-lang/rust/issues/63679. @@ -183,9 +194,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { has_braces: bool, ) { debug!( - "visit_block: {:?} {:?}", - self.source_map.lookup_char_pos(b.span.lo()), - self.source_map.lookup_char_pos(b.span.hi()) + "visit_block: {}", + self.parse_sess.span_to_debug_info(b.span), ); // Check if this block has braces. @@ -681,10 +691,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { // do not take into account the lines with attributes as part of the skipped range let attrs_end = attrs .iter() - .map(|attr| self.source_map.lookup_char_pos(attr.span.hi()).line) + .map(|attr| self.parse_sess.line_of_byte_pos(attr.span.hi())) .max() .unwrap_or(1); - let first_line = self.source_map.lookup_char_pos(main_span.lo()).line; + let first_line = self.parse_sess.line_of_byte_pos(main_span.lo()); // Statement can start after some newlines and/or spaces // or it can be on the same line as the last attribute. // So here we need to take a minimum between the two. @@ -696,7 +706,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> { let mut visitor = FmtVisitor::from_source_map( - ctx.parse_session, + ctx.parse_sess, ctx.config, ctx.snippet_provider, ctx.report.clone(), @@ -709,13 +719,12 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn from_source_map( parse_session: &'a ParseSess, config: &'a Config, - snippet_provider: &'a SnippetProvider<'_>, + snippet_provider: &'a SnippetProvider, report: FormatReport, ) -> FmtVisitor<'a> { FmtVisitor { parent_context: None, - parse_session, - source_map: parse_session.source_map(), + parse_sess: parse_session, buffer: String::with_capacity(snippet_provider.big_snippet.len() * 2), last_pos: BytePos(0), block_indent: Indent::empty(), @@ -742,22 +751,22 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { for attr in attrs { if attr.check_name(depr_skip_annotation()) { - let file_name = self.source_map.span_to_filename(attr.span).into(); + let file_name = self.parse_sess.span_to_filename(attr.span); self.report.append( file_name, vec![FormattingError::from_span( attr.span, - &self.source_map, + self.parse_sess, ErrorKind::DeprecatedAttr, )], ); } else if self.is_unknown_rustfmt_attr(&attr.path.segments) { - let file_name = self.source_map.span_to_filename(attr.span).into(); + let file_name = self.parse_sess.span_to_filename(attr.span); self.report.append( file_name, vec![FormattingError::from_span( attr.span, - &self.source_map, + self.parse_sess, ErrorKind::BadAttr, )], ); @@ -862,14 +871,10 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } } - pub(crate) fn format_separate_mod( - &mut self, - m: &ast::Mod, - source_file: &source_map::SourceFile, - ) { + pub(crate) fn format_separate_mod(&mut self, m: &ast::Mod, end_pos: BytePos) { self.block_indent = Indent::empty(); self.walk_mod_items(m); - self.format_missing_with_indent(source_file.end_pos); + self.format_missing_with_indent(end_pos); } pub(crate) fn skip_empty_lines(&mut self, end_pos: BytePos) { @@ -900,8 +905,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { pub(crate) fn get_context(&self) -> RewriteContext<'_> { RewriteContext { - parse_session: self.parse_session, - source_map: self.source_map, + parse_sess: self.parse_sess, config: self.config, inside_macro: Rc::new(Cell::new(false)), use_block: Cell::new(false), From 6626ee35f0800384b4cff3f6e310d69c34cda138 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 22 Oct 2019 23:00:54 +0900 Subject: [PATCH 08/12] Tiny refactorings --- src/formatting.rs | 2 +- src/types.rs | 4 ++-- src/visitor.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/formatting.rs b/src/formatting.rs index 0c01a3c4c7a..b5bb08750ab 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -142,7 +142,7 @@ impl<'a, T: FormatHandler + 'a> FormatContext<'a, T> { is_root: bool, ) -> Result<(), ErrorKind> { let snippet_provider = self.parse_session.snippet_provider(module.inner); - let mut visitor = FmtVisitor::from_source_map( + let mut visitor = FmtVisitor::from_parse_sess( &self.parse_session, &self.config, &snippet_provider, diff --git a/src/types.rs b/src/types.rs index 3efe80fdb81..fa3d56aa0a9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -2,7 +2,7 @@ use std::iter::ExactSizeIterator; use std::ops::Deref; use syntax::ast::{self, FunctionRetTy, Mutability}; -use syntax::source_map::{self, BytePos, Span}; +use syntax::source_map::{BytePos, Span, DUMMY_SP}; use syntax::symbol::kw; use crate::config::lists::*; @@ -277,7 +277,7 @@ fn rewrite_segment( ast::GenericArgs::Parenthesized(ref data) => { let output = match data.output { Some(ref ty) => FunctionRetTy::Ty(ty.clone()), - None => FunctionRetTy::Default(source_map::DUMMY_SP), + None => FunctionRetTy::Default(DUMMY_SP), }; result.push_str(&format_function_type( data.inputs.iter().map(|x| &**x), diff --git a/src/visitor.rs b/src/visitor.rs index 9646e9cf9d6..cbf083e9298 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -705,7 +705,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } pub(crate) fn from_context(ctx: &'a RewriteContext<'_>) -> FmtVisitor<'a> { - let mut visitor = FmtVisitor::from_source_map( + let mut visitor = FmtVisitor::from_parse_sess( ctx.parse_sess, ctx.config, ctx.snippet_provider, @@ -716,7 +716,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { visitor } - pub(crate) fn from_source_map( + pub(crate) fn from_parse_sess( parse_session: &'a ParseSess, config: &'a Config, snippet_provider: &'a SnippetProvider, From 05de168ffd5ac44b3a36dd0648cacc2b879ef130 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 22 Oct 2019 23:11:10 +0900 Subject: [PATCH 09/12] Restrict visibility --- src/syntux/parser.rs | 2 +- src/syntux/session.rs | 29 ++++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 240c5dac0fb..d537bd65c7b 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -23,7 +23,7 @@ pub(crate) struct Directory { } impl<'a> Directory { - pub(crate) fn to_syntax_directory(&'a self) -> syntax::parse::Directory<'a> { + fn to_syntax_directory(&'a self) -> syntax::parse::Directory<'a> { syntax::parse::Directory { path: Cow::Borrowed(&self.path), ownership: self.ownership.clone(), diff --git a/src/syntux/session.rs b/src/syntux/session.rs index deb8ebbcfa6..c9fa3b795eb 100644 --- a/src/syntux/session.rs +++ b/src/syntux/session.rs @@ -154,10 +154,6 @@ impl ParseSess { .is_some() } - pub(super) fn can_reset_errors(&self) -> bool { - *self.can_reset_errors.borrow() - } - pub(crate) fn ignore_file(&self, path: &FileName) -> bool { self.ignore_path_set.as_ref().is_match(&path) } @@ -196,14 +192,6 @@ impl ParseSess { &self.parse_sess } - pub(crate) fn has_errors(&self) -> bool { - self.parse_sess.span_diagnostic.has_errors() - } - - pub(crate) fn reset_errors(&self) { - self.parse_sess.span_diagnostic.reset_err_count(); - } - pub(crate) fn snippet_provider(&self, span: Span) -> SnippetProvider { let source_file = self.parse_sess.source_map().lookup_char_pos(span.lo()).file; SnippetProvider::new( @@ -219,12 +207,27 @@ impl ParseSess { .get_source_file(&file_name.into()) .and_then(|source_file| source_file.src.clone()) } +} - pub(crate) fn emit_diagnostics(&self, diagnostics: Vec) { +// Methods that should be restricted within the syntux module. +impl ParseSess { + pub(super) fn emit_diagnostics(&self, diagnostics: Vec) { for diagnostic in diagnostics { self.parse_sess.span_diagnostic.emit_diagnostic(&diagnostic); } } + + pub(super) fn can_reset_errors(&self) -> bool { + *self.can_reset_errors.borrow() + } + + pub(super) fn has_errors(&self) -> bool { + self.parse_sess.span_diagnostic.has_errors() + } + + pub(super) fn reset_errors(&self) { + self.parse_sess.span_diagnostic.reset_err_count(); + } } impl LineRangeUtils for ParseSess { From 1218799b809dc478f8efec570e233dc3916130b2 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 23 Oct 2019 23:01:29 +0900 Subject: [PATCH 10/12] Remove obsolete comment --- src/syntux/parser.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index d537bd65c7b..3cfed10a459 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -79,7 +79,6 @@ impl<'a> ParserBuilder<'a> { Ok(p) => p, Err(db) => { sess.emit_diagnostics(db); - // report.add_parsing_error(); return Err(ParserError::ParserCreationError); } }; From d539e3c93f15a7617ac1151f8e5ed61a1d735827 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 23 Oct 2019 23:02:16 +0900 Subject: [PATCH 11/12] Use input_is_stdin --- src/formatting.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/formatting.rs b/src/formatting.rs index b5bb08750ab..e3001559840 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -68,14 +68,13 @@ fn format_project( } // Parse the crate. - let is_stdin = !input.is_text(); let mut report = FormatReport::new(); let directory_ownership = input.to_directory_ownership(); let krate = match Parser::parse_crate(config, input, directory_ownership, &parse_session) { Ok(krate) => krate, Err(e) => { - let forbid_verbose = is_stdin || e != ParserError::ParsePanicError; + let forbid_verbose = input_is_stdin || e != ParserError::ParsePanicError; should_emit_verbose(forbid_verbose, config, || { eprintln!("The Rust parser panicked"); }); From 9770c541e9b9079c514f0a873867349ac8443c83 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 23 Oct 2019 23:03:17 +0900 Subject: [PATCH 12/12] Remove is_text --- src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0763ab2e75f..dbd9469908e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -509,13 +509,6 @@ pub enum Input { } impl Input { - fn is_text(&self) -> bool { - match *self { - Input::File(_) => false, - Input::Text(_) => true, - } - } - fn file_name(&self) -> FileName { match *self { Input::File(ref file) => FileName::Real(file.clone()),