Merge pull request #543 from eefriedman/macro-crash

Fix crash speculatively parsing macro arguments as expressions.
This commit is contained in:
Marcus Klaas de Vries 2015-10-28 08:09:44 +01:00
commit bd0fdbb364
7 changed files with 38 additions and 19 deletions

View File

@ -422,7 +422,7 @@ fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Opt
return Some(user_str); return Some(user_str);
} }
let mut visitor = FmtVisitor::from_codemap(context.codemap, context.config, None); let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None);
visitor.block_indent = context.block_indent; visitor.block_indent = context.block_indent;
let prefix = match self.rules { let prefix = match self.rules {
@ -833,7 +833,9 @@ fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Opt
let attr_str = if !attrs.is_empty() { let attr_str = if !attrs.is_empty() {
// We only use this visitor for the attributes, should we use it for // We only use this visitor for the attributes, should we use it for
// more? // more?
let mut attr_visitor = FmtVisitor::from_codemap(context.codemap, context.config, None); let mut attr_visitor = FmtVisitor::from_codemap(context.parse_session,
context.config,
None);
attr_visitor.block_indent = context.block_indent; attr_visitor.block_indent = context.block_indent;
attr_visitor.last_pos = attrs[0].span.lo; attr_visitor.last_pos = attrs[0].span.lo;
if attr_visitor.visit_attrs(attrs) { if attr_visitor.visit_attrs(attrs) {

View File

@ -26,7 +26,8 @@
extern crate term; extern crate term;
use syntax::ast; use syntax::ast;
use syntax::codemap::{CodeMap, Span}; use syntax::codemap::Span;
use syntax::diagnostic::{EmitterWriter, Handler};
use syntax::parse::{self, ParseSess}; use syntax::parse::{self, ParseSess};
use std::ops::{Add, Sub}; use std::ops::{Add, Sub};
@ -288,11 +289,15 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
} }
// Formatting which depends on the AST. // Formatting which depends on the AST.
fn fmt_ast(krate: &ast::Crate, codemap: &CodeMap, config: &Config, mode: WriteMode) -> FileMap { fn fmt_ast(krate: &ast::Crate,
parse_session: &ParseSess,
config: &Config,
mode: WriteMode)
-> FileMap {
let mut file_map = FileMap::new(); let mut file_map = FileMap::new();
for (path, module) in modules::list_files(krate, codemap) { for (path, module) in modules::list_files(krate, parse_session.codemap()) {
let path = path.to_str().unwrap(); let path = path.to_str().unwrap();
let mut visitor = FmtVisitor::from_codemap(codemap, config, Some(mode)); let mut visitor = FmtVisitor::from_codemap(parse_session, config, Some(mode));
visitor.format_separate_mod(module, path); visitor.format_separate_mod(module, path);
file_map.insert(path.to_owned(), visitor.buffer); file_map.insert(path.to_owned(), visitor.buffer);
} }
@ -382,9 +387,14 @@ pub fn fmt_lines(file_map: &mut FileMap, config: &Config) -> FormatReport {
} }
pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap { pub fn format(file: &Path, config: &Config, mode: WriteMode) -> FileMap {
let parse_session = ParseSess::new(); let mut parse_session = ParseSess::new();
let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session); let krate = parse::parse_crate_from_file(file, Vec::new(), &parse_session);
let mut file_map = fmt_ast(&krate, parse_session.codemap(), config, mode);
// Suppress error output after parsing.
let emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), None));
parse_session.span_diagnostic.handler = Handler::with_emitter(false, emitter);
let mut file_map = fmt_ast(&krate, &parse_session, config, mode);
// For some reason, the codemap does not include terminating // For some reason, the codemap does not include terminating
// newlines so we must add one on for each file. This is sad. // newlines so we must add one on for each file. This is sad.

View File

@ -21,7 +21,7 @@
use syntax::ast; use syntax::ast;
use syntax::parse::token::{Eof, Comma, Token}; use syntax::parse::token::{Eof, Comma, Token};
use syntax::parse::{ParseSess, tts_to_parser}; use syntax::parse::tts_to_parser;
use syntax::codemap::{mk_sp, BytePos}; use syntax::codemap::{mk_sp, BytePos};
use Indent; use Indent;
@ -73,8 +73,7 @@ pub fn rewrite_macro(mac: &ast::Mac,
}; };
} }
let parse_session = ParseSess::new(); let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone(), Vec::new());
let mut parser = tts_to_parser(&parse_session, mac.node.tts.clone(), Vec::new());
let mut expr_vec = Vec::new(); let mut expr_vec = Vec::new();
loop { loop {

View File

@ -11,6 +11,7 @@
// A generic trait to abstract the rewriting of an element (of the AST). // A generic trait to abstract the rewriting of an element (of the AST).
use syntax::codemap::{CodeMap, Span}; use syntax::codemap::{CodeMap, Span};
use syntax::parse::ParseSess;
use Indent; use Indent;
use config::Config; use config::Config;
@ -27,6 +28,7 @@ pub trait Rewrite {
} }
pub struct RewriteContext<'a> { pub struct RewriteContext<'a> {
pub parse_session: &'a ParseSess,
pub codemap: &'a CodeMap, pub codemap: &'a CodeMap,
pub config: &'a Config, pub config: &'a Config,
// Indentation due to nesting of blocks. // Indentation due to nesting of blocks.
@ -36,6 +38,7 @@ pub struct RewriteContext<'a> {
impl<'a> RewriteContext<'a> { impl<'a> RewriteContext<'a> {
pub fn nested_context(&self) -> RewriteContext<'a> { pub fn nested_context(&self) -> RewriteContext<'a> {
RewriteContext { RewriteContext {
parse_session: self.parse_session,
codemap: self.codemap, codemap: self.codemap,
config: self.config, config: self.config,
block_indent: self.block_indent.block_indent(self.config), block_indent: self.block_indent.block_indent(self.config),

View File

@ -10,6 +10,7 @@
use syntax::ast; use syntax::ast;
use syntax::codemap::{self, CodeMap, Span, BytePos}; use syntax::codemap::{self, CodeMap, Span, BytePos};
use syntax::parse::ParseSess;
use syntax::visit; use syntax::visit;
use strings::string_buffer::StringBuffer; use strings::string_buffer::StringBuffer;
@ -23,6 +24,7 @@
use items::rewrite_static; use items::rewrite_static;
pub struct FmtVisitor<'a> { pub struct FmtVisitor<'a> {
pub parse_session: &'a ParseSess,
pub codemap: &'a CodeMap, pub codemap: &'a CodeMap,
pub buffer: StringBuffer, pub buffer: StringBuffer,
pub last_pos: BytePos, pub last_pos: BytePos,
@ -363,12 +365,13 @@ fn push_rewrite(&mut self, span: Span, rewrite: Option<String>) {
} }
} }
pub fn from_codemap(codemap: &'a CodeMap, pub fn from_codemap(parse_session: &'a ParseSess,
config: &'a Config, config: &'a Config,
mode: Option<WriteMode>) mode: Option<WriteMode>)
-> FmtVisitor<'a> { -> FmtVisitor<'a> {
FmtVisitor { FmtVisitor {
codemap: codemap, parse_session: parse_session,
codemap: parse_session.codemap(),
buffer: StringBuffer::new(), buffer: StringBuffer::new(),
last_pos: BytePos(0), last_pos: BytePos(0),
block_indent: Indent { block_indent: Indent {
@ -461,13 +464,10 @@ fn format_import(&mut self, vis: ast::Visibility, vp: &ast::ViewPath, span: Span
let vis = utils::format_visibility(vis); let vis = utils::format_visibility(vis);
let mut offset = self.block_indent; let mut offset = self.block_indent;
offset.alignment += vis.len() + "use ".len(); offset.alignment += vis.len() + "use ".len();
let context = RewriteContext {
codemap: self.codemap,
config: self.config,
block_indent: self.block_indent,
};
// 1 = ";" // 1 = ";"
match vp.rewrite(&context, self.config.max_width - offset.width() - 1, offset) { match vp.rewrite(&self.get_context(),
self.config.max_width - offset.width() - 1,
offset) {
Some(ref s) if s.is_empty() => { Some(ref s) if s.is_empty() => {
// Format up to last newline // Format up to last newline
let prev_span = codemap::mk_sp(self.last_pos, span.lo); let prev_span = codemap::mk_sp(self.last_pos, span.lo);
@ -493,6 +493,7 @@ fn format_import(&mut self, vis: ast::Visibility, vp: &ast::ViewPath, span: Span
pub fn get_context(&self) -> RewriteContext { pub fn get_context(&self) -> RewriteContext {
RewriteContext { RewriteContext {
parse_session: self.parse_session,
codemap: self.codemap, codemap: self.codemap,
config: self.config, config: self.config,
block_indent: self.block_indent, block_indent: self.block_indent,

View File

@ -27,4 +27,6 @@ fn main() {
hamkaas!{ () }; hamkaas!{ () };
macrowithbraces! {dont, format, me} macrowithbraces! {dont, format, me}
x!(fn);
} }

View File

@ -30,4 +30,6 @@ fn main() {
hamkaas!{ () }; hamkaas!{ () };
macrowithbraces! {dont, format, me} macrowithbraces! {dont, format, me}
x!(fn);
} }