rustfmt_nightly/parse/
parser.rs1use std::panic::{AssertUnwindSafe, catch_unwind};
2use std::path::{Path, PathBuf};
3
4use rustc_ast::{ast, attr};
5use rustc_errors::Diag;
6use rustc_parse::lexer::StripTokens;
7use rustc_parse::parser::Parser as RawParser;
8use rustc_parse::{exp, new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
9use rustc_span::{Span, sym};
10use thin_vec::ThinVec;
11
12use crate::Input;
13use crate::parse::session::ParseSess;
14
15pub(crate) type DirectoryOwnership = rustc_expand::module::DirOwnership;
16pub(crate) type ModulePathSuccess = rustc_expand::module::ModulePathSuccess;
17pub(crate) type ModError<'a> = rustc_expand::module::ModError<'a>;
18
19#[derive(Clone)]
20pub(crate) struct Directory {
21 pub(crate) path: PathBuf,
22 pub(crate) ownership: DirectoryOwnership,
23}
24
25pub(crate) struct Parser<'a> {
27 parser: RawParser<'a>,
28}
29
30#[derive(Default)]
32pub(crate) struct ParserBuilder<'a> {
33 psess: Option<&'a ParseSess>,
34 input: Option<Input>,
35}
36
37impl<'a> ParserBuilder<'a> {
38 pub(crate) fn input(mut self, input: Input) -> ParserBuilder<'a> {
39 self.input = Some(input);
40 self
41 }
42
43 pub(crate) fn psess(mut self, psess: &'a ParseSess) -> ParserBuilder<'a> {
44 self.psess = Some(psess);
45 self
46 }
47
48 pub(crate) fn build(self) -> Result<Parser<'a>, ParserError> {
49 let psess = self.psess.ok_or(ParserError::NoParseSess)?;
50 let input = self.input.ok_or(ParserError::NoInput)?;
51
52 let parser = match Self::parser(psess.inner(), input) {
53 Ok(p) => p,
54 Err(diagnostics) => {
55 psess.emit_diagnostics(diagnostics);
56 return Err(ParserError::ParserCreationError);
57 }
58 };
59
60 Ok(Parser { parser })
61 }
62
63 fn parser(
64 psess: &'a rustc_session::parse::ParseSess,
65 input: Input,
66 ) -> Result<RawParser<'a>, Vec<Diag<'a>>> {
67 match input {
68 Input::File(ref file) => {
69 new_parser_from_file(psess, file, StripTokens::ShebangAndFrontmatter, None)
70 }
71 Input::Text(text) => new_parser_from_source_str(
72 psess,
73 rustc_span::FileName::Custom("stdin".to_owned()),
74 text,
75 StripTokens::ShebangAndFrontmatter,
76 ),
77 }
78 }
79}
80
81#[derive(Debug, PartialEq)]
82pub(crate) enum ParserError {
83 NoParseSess,
84 NoInput,
85 ParserCreationError,
86 ParseError,
87 ParsePanicError,
88}
89
90impl<'a> Parser<'a> {
91 pub(crate) fn submod_path_from_attr(attrs: &[ast::Attribute], path: &Path) -> Option<PathBuf> {
92 let path_sym = attr::first_attr_value_str_by_name(attrs, sym::path)?;
93 let path_str = path_sym.as_str();
94
95 #[cfg(windows)]
100 let path_str = path_str.replace("/", "\\");
101
102 Some(path.join(path_str))
103 }
104
105 pub(crate) fn parse_file_as_module(
106 psess: &'a ParseSess,
107 path: &Path,
108 span: Span,
109 ) -> Result<(ast::AttrVec, ThinVec<Box<ast::Item>>, Span), ParserError> {
110 let result = catch_unwind(AssertUnwindSafe(|| {
111 let mut parser = unwrap_or_emit_fatal(new_parser_from_file(
112 psess.inner(),
113 path,
114 StripTokens::ShebangAndFrontmatter,
115 Some(span),
116 ));
117 match parser.parse_mod(exp!(Eof)) {
118 Ok((a, i, spans)) => Some((a, i, spans.inner_span)),
119 Err(e) => {
120 e.emit();
121 if psess.can_reset_errors() {
122 psess.reset_errors();
123 }
124 None
125 }
126 }
127 }));
128 match result {
129 Ok(Some(m)) if !psess.has_errors() => Ok(m),
130 Ok(Some(m)) if psess.can_reset_errors() => {
131 psess.reset_errors();
132 Ok(m)
133 }
134 Ok(_) => Err(ParserError::ParseError),
135 Err(..) if path.exists() => Err(ParserError::ParseError),
136 Err(_) => Err(ParserError::ParsePanicError),
137 }
138 }
139
140 pub(crate) fn parse_crate(
141 input: Input,
142 psess: &'a ParseSess,
143 ) -> Result<ast::Crate, ParserError> {
144 let krate = Parser::parse_crate_inner(input, psess)?;
145 if !psess.has_errors() {
146 return Ok(krate);
147 }
148
149 if psess.can_reset_errors() {
150 psess.reset_errors();
151 return Ok(krate);
152 }
153
154 Err(ParserError::ParseError)
155 }
156
157 fn parse_crate_inner(input: Input, psess: &'a ParseSess) -> Result<ast::Crate, ParserError> {
158 ParserBuilder::default()
159 .input(input)
160 .psess(psess)
161 .build()?
162 .parse_crate_mod()
163 }
164
165 fn parse_crate_mod(&mut self) -> Result<ast::Crate, ParserError> {
166 let mut parser = AssertUnwindSafe(&mut self.parser);
167 let err = Err(ParserError::ParsePanicError);
168 match catch_unwind(move || parser.parse_crate_mod()) {
169 Ok(Ok(k)) => Ok(k),
170 Ok(Err(db)) => {
171 db.emit();
172 err
173 }
174 Err(_) => err,
175 }
176 }
177}