Skip to content

Commit 7ea2674

Browse files
committed
Auto merge of #26750 - nrc:refactor-submod, r=sfackler
This makes the functionality usable from outside the parser
2 parents e1ac57d + f3ba950 commit 7ea2674

File tree

1 file changed

+108
-68
lines changed

1 file changed

+108
-68
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 108 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
6060
use ast::{Visibility, WhereClause};
6161
use ast;
6262
use ast_util::{self, AS_PREC, ident_to_path, operator_prec};
63-
use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp};
63+
use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp, CodeMap};
6464
use diagnostic;
6565
use ext::tt::macro_parser;
6666
use parse;
@@ -297,6 +297,24 @@ fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
297297
t.is_plain_ident() || *t == token::Underscore
298298
}
299299

300+
/// Information about the path to a module.
301+
pub struct ModulePath {
302+
pub name: String,
303+
pub path_exists: bool,
304+
pub result: Result<ModulePathSuccess, ModulePathError>,
305+
}
306+
307+
pub struct ModulePathSuccess {
308+
pub path: ::std::path::PathBuf,
309+
pub owns_directory: bool,
310+
}
311+
312+
pub struct ModulePathError {
313+
pub err_msg: String,
314+
pub help_msg: String,
315+
}
316+
317+
300318
impl<'a> Parser<'a> {
301319
pub fn new(sess: &'a ParseSess,
302320
cfg: ast::CrateConfig,
@@ -4859,82 +4877,104 @@ impl<'a> Parser<'a> {
48594877
self.mod_path_stack.pop().unwrap();
48604878
}
48614879

4862-
/// Read a module from a source file.
4863-
fn eval_src_mod(&mut self,
4864-
id: ast::Ident,
4865-
outer_attrs: &[ast::Attribute],
4866-
id_sp: Span)
4867-
-> PResult<(ast::Item_, Vec<ast::Attribute> )> {
4880+
pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option<PathBuf> {
4881+
::attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&*d))
4882+
}
4883+
4884+
/// Returns either a path to a module, or .
4885+
pub fn default_submod_path(id: ast::Ident, dir_path: &Path, codemap: &CodeMap) -> ModulePath
4886+
{
4887+
let mod_string = token::get_ident(id);
4888+
let mod_name = mod_string.to_string();
4889+
let default_path_str = format!("{}.rs", mod_name);
4890+
let secondary_path_str = format!("{}/mod.rs", mod_name);
4891+
let default_path = dir_path.join(&default_path_str);
4892+
let secondary_path = dir_path.join(&secondary_path_str);
4893+
let default_exists = codemap.file_exists(&default_path);
4894+
let secondary_exists = codemap.file_exists(&secondary_path);
4895+
4896+
let result = match (default_exists, secondary_exists) {
4897+
(true, false) => Ok(ModulePathSuccess { path: default_path, owns_directory: false }),
4898+
(false, true) => Ok(ModulePathSuccess { path: secondary_path, owns_directory: true }),
4899+
(false, false) => Err(ModulePathError {
4900+
err_msg: format!("file not found for module `{}`", mod_name),
4901+
help_msg: format!("name the file either {} or {} inside the directory {:?}",
4902+
default_path_str,
4903+
secondary_path_str,
4904+
dir_path.display()),
4905+
}),
4906+
(true, true) => Err(ModulePathError {
4907+
err_msg: format!("file for module `{}` found at both {} and {}",
4908+
mod_name,
4909+
default_path_str,
4910+
secondary_path_str),
4911+
help_msg: "delete or rename one of them to remove the ambiguity".to_owned(),
4912+
}),
4913+
};
4914+
4915+
ModulePath {
4916+
name: mod_name,
4917+
path_exists: default_exists || secondary_exists,
4918+
result: result,
4919+
}
4920+
}
4921+
4922+
fn submod_path(&mut self,
4923+
id: ast::Ident,
4924+
outer_attrs: &[ast::Attribute],
4925+
id_sp: Span) -> PResult<ModulePathSuccess> {
48684926
let mut prefix = PathBuf::from(&self.sess.codemap().span_to_filename(self.span));
48694927
prefix.pop();
48704928
let mut dir_path = prefix;
48714929
for part in &self.mod_path_stack {
48724930
dir_path.push(&**part);
48734931
}
4874-
let mod_string = token::get_ident(id);
4875-
let (file_path, owns_directory) = match ::attr::first_attr_value_str_by_name(
4876-
outer_attrs, "path") {
4877-
Some(d) => (dir_path.join(&*d), true),
4878-
None => {
4879-
let mod_name = mod_string.to_string();
4880-
let default_path_str = format!("{}.rs", mod_name);
4881-
let secondary_path_str = format!("{}/mod.rs", mod_name);
4882-
let default_path = dir_path.join(&default_path_str[..]);
4883-
let secondary_path = dir_path.join(&secondary_path_str[..]);
4884-
let default_exists = self.sess.codemap().file_exists(&default_path);
4885-
let secondary_exists = self.sess.codemap().file_exists(&secondary_path);
4886-
4887-
if !self.owns_directory {
4888-
self.span_err(id_sp,
4889-
"cannot declare a new module at this location");
4890-
let this_module = match self.mod_path_stack.last() {
4891-
Some(name) => name.to_string(),
4892-
None => self.root_module_name.as_ref().unwrap().clone(),
4893-
};
4894-
self.span_note(id_sp,
4895-
&format!("maybe move this module `{0}` \
4896-
to its own directory via \
4897-
`{0}/mod.rs`",
4898-
this_module));
4899-
if default_exists || secondary_exists {
4900-
self.span_note(id_sp,
4901-
&format!("... or maybe `use` the module \
4902-
`{}` instead of possibly \
4903-
redeclaring it",
4904-
mod_name));
4905-
}
4906-
self.abort_if_errors();
4907-
}
49084932

4909-
match (default_exists, secondary_exists) {
4910-
(true, false) => (default_path, false),
4911-
(false, true) => (secondary_path, true),
4912-
(false, false) => {
4913-
return Err(self.span_fatal_help(id_sp,
4914-
&format!("file not found for module `{}`",
4915-
mod_name),
4916-
&format!("name the file either {} or {} inside \
4917-
the directory {:?}",
4918-
default_path_str,
4919-
secondary_path_str,
4920-
dir_path.display())));
4921-
}
4922-
(true, true) => {
4923-
return Err(self.span_fatal_help(
4924-
id_sp,
4925-
&format!("file for module `{}` found at both {} \
4926-
and {}",
4927-
mod_name,
4928-
default_path_str,
4929-
secondary_path_str),
4930-
"delete or rename one of them to remove the ambiguity"));
4931-
}
4932-
}
4933+
if let Some(p) = Parser::submod_path_from_attr(outer_attrs, &dir_path) {
4934+
return Ok(ModulePathSuccess { path: p, owns_directory: true });
4935+
}
4936+
4937+
let paths = Parser::default_submod_path(id, &dir_path, self.sess.codemap());
4938+
4939+
if !self.owns_directory {
4940+
self.span_err(id_sp, "cannot declare a new module at this location");
4941+
let this_module = match self.mod_path_stack.last() {
4942+
Some(name) => name.to_string(),
4943+
None => self.root_module_name.as_ref().unwrap().clone(),
4944+
};
4945+
self.span_note(id_sp,
4946+
&format!("maybe move this module `{0}` to its own directory \
4947+
via `{0}/mod.rs`",
4948+
this_module));
4949+
if paths.path_exists {
4950+
self.span_note(id_sp,
4951+
&format!("... or maybe `use` the module `{}` instead \
4952+
of possibly redeclaring it",
4953+
paths.name));
49334954
}
4934-
};
4955+
self.abort_if_errors();
4956+
}
4957+
4958+
match paths.result {
4959+
Ok(succ) => Ok(succ),
4960+
Err(err) => Err(self.span_fatal_help(id_sp, &err.err_msg, &err.help_msg)),
4961+
}
4962+
}
49354963

4936-
self.eval_src_mod_from_path(file_path, owns_directory,
4937-
mod_string.to_string(), id_sp)
4964+
/// Read a module from a source file.
4965+
fn eval_src_mod(&mut self,
4966+
id: ast::Ident,
4967+
outer_attrs: &[ast::Attribute],
4968+
id_sp: Span)
4969+
-> PResult<(ast::Item_, Vec<ast::Attribute> )> {
4970+
let ModulePathSuccess { path, owns_directory } = try!(self.submod_path(id,
4971+
outer_attrs,
4972+
id_sp));
4973+
4974+
self.eval_src_mod_from_path(path,
4975+
owns_directory,
4976+
token::get_ident(id).to_string(),
4977+
id_sp)
49384978
}
49394979

49404980
fn eval_src_mod_from_path(&mut self,

0 commit comments

Comments
 (0)