@@ -60,7 +60,7 @@ use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
60
60
use ast:: { Visibility , WhereClause } ;
61
61
use ast;
62
62
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 } ;
64
64
use diagnostic;
65
65
use ext:: tt:: macro_parser;
66
66
use parse;
@@ -297,6 +297,24 @@ fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
297
297
t. is_plain_ident ( ) || * t == token:: Underscore
298
298
}
299
299
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
+
300
318
impl < ' a > Parser < ' a > {
301
319
pub fn new ( sess : & ' a ParseSess ,
302
320
cfg : ast:: CrateConfig ,
@@ -4861,82 +4879,104 @@ impl<'a> Parser<'a> {
4861
4879
self . mod_path_stack . pop ( ) . unwrap ( ) ;
4862
4880
}
4863
4881
4864
- /// Read a module from a source file.
4865
- fn eval_src_mod ( & mut self ,
4866
- id : ast:: Ident ,
4867
- outer_attrs : & [ ast:: Attribute ] ,
4868
- id_sp : Span )
4869
- -> PResult < ( ast:: Item_ , Vec < ast:: Attribute > ) > {
4882
+ pub fn submod_path_from_attr ( attrs : & [ ast:: Attribute ] , dir_path : & Path ) -> Option < PathBuf > {
4883
+ :: attr:: first_attr_value_str_by_name ( attrs, "path" ) . map ( |d| dir_path. join ( & * d) )
4884
+ }
4885
+
4886
+ /// Returns either a path to a module, or .
4887
+ pub fn default_submod_path ( id : ast:: Ident , dir_path : & Path , codemap : & CodeMap ) -> ModulePath
4888
+ {
4889
+ let mod_string = token:: get_ident ( id) ;
4890
+ let mod_name = mod_string. to_string ( ) ;
4891
+ let default_path_str = format ! ( "{}.rs" , mod_name) ;
4892
+ let secondary_path_str = format ! ( "{}/mod.rs" , mod_name) ;
4893
+ let default_path = dir_path. join ( & default_path_str) ;
4894
+ let secondary_path = dir_path. join ( & secondary_path_str) ;
4895
+ let default_exists = codemap. file_exists ( & default_path) ;
4896
+ let secondary_exists = codemap. file_exists ( & secondary_path) ;
4897
+
4898
+ let result = match ( default_exists, secondary_exists) {
4899
+ ( true , false ) => Ok ( ModulePathSuccess { path : default_path, owns_directory : false } ) ,
4900
+ ( false , true ) => Ok ( ModulePathSuccess { path : secondary_path, owns_directory : true } ) ,
4901
+ ( false , false ) => Err ( ModulePathError {
4902
+ err_msg : format ! ( "file not found for module `{}`" , mod_name) ,
4903
+ help_msg : format ! ( "name the file either {} or {} inside the directory {:?}" ,
4904
+ default_path_str,
4905
+ secondary_path_str,
4906
+ dir_path. display( ) ) ,
4907
+ } ) ,
4908
+ ( true , true ) => Err ( ModulePathError {
4909
+ err_msg : format ! ( "file for module `{}` found at both {} and {}" ,
4910
+ mod_name,
4911
+ default_path_str,
4912
+ secondary_path_str) ,
4913
+ help_msg : "delete or rename one of them to remove the ambiguity" . to_owned ( ) ,
4914
+ } ) ,
4915
+ } ;
4916
+
4917
+ ModulePath {
4918
+ name : mod_name,
4919
+ path_exists : default_exists || secondary_exists,
4920
+ result : result,
4921
+ }
4922
+ }
4923
+
4924
+ fn submod_path ( & mut self ,
4925
+ id : ast:: Ident ,
4926
+ outer_attrs : & [ ast:: Attribute ] ,
4927
+ id_sp : Span ) -> PResult < ModulePathSuccess > {
4870
4928
let mut prefix = PathBuf :: from ( & self . sess . codemap ( ) . span_to_filename ( self . span ) ) ;
4871
4929
prefix. pop ( ) ;
4872
4930
let mut dir_path = prefix;
4873
4931
for part in & self . mod_path_stack {
4874
4932
dir_path. push ( & * * part) ;
4875
4933
}
4876
- let mod_string = token:: get_ident ( id) ;
4877
- let ( file_path, owns_directory) = match :: attr:: first_attr_value_str_by_name (
4878
- outer_attrs, "path" ) {
4879
- Some ( d) => ( dir_path. join ( & * d) , true ) ,
4880
- None => {
4881
- let mod_name = mod_string. to_string ( ) ;
4882
- let default_path_str = format ! ( "{}.rs" , mod_name) ;
4883
- let secondary_path_str = format ! ( "{}/mod.rs" , mod_name) ;
4884
- let default_path = dir_path. join ( & default_path_str[ ..] ) ;
4885
- let secondary_path = dir_path. join ( & secondary_path_str[ ..] ) ;
4886
- let default_exists = self . sess . codemap ( ) . file_exists ( & default_path) ;
4887
- let secondary_exists = self . sess . codemap ( ) . file_exists ( & secondary_path) ;
4888
-
4889
- if !self . owns_directory {
4890
- self . span_err ( id_sp,
4891
- "cannot declare a new module at this location" ) ;
4892
- let this_module = match self . mod_path_stack . last ( ) {
4893
- Some ( name) => name. to_string ( ) ,
4894
- None => self . root_module_name . as_ref ( ) . unwrap ( ) . clone ( ) ,
4895
- } ;
4896
- self . span_note ( id_sp,
4897
- & format ! ( "maybe move this module `{0}` \
4898
- to its own directory via \
4899
- `{0}/mod.rs`",
4900
- this_module) ) ;
4901
- if default_exists || secondary_exists {
4902
- self . span_note ( id_sp,
4903
- & format ! ( "... or maybe `use` the module \
4904
- `{}` instead of possibly \
4905
- redeclaring it",
4906
- mod_name) ) ;
4907
- }
4908
- self . abort_if_errors ( ) ;
4909
- }
4910
4934
4911
- match ( default_exists, secondary_exists) {
4912
- ( true , false ) => ( default_path, false ) ,
4913
- ( false , true ) => ( secondary_path, true ) ,
4914
- ( false , false ) => {
4915
- return Err ( self . span_fatal_help ( id_sp,
4916
- & format ! ( "file not found for module `{}`" ,
4917
- mod_name) ,
4918
- & format ! ( "name the file either {} or {} inside \
4919
- the directory {:?}",
4920
- default_path_str,
4921
- secondary_path_str,
4922
- dir_path. display( ) ) ) ) ;
4923
- }
4924
- ( true , true ) => {
4925
- return Err ( self . span_fatal_help (
4926
- id_sp,
4927
- & format ! ( "file for module `{}` found at both {} \
4928
- and {}",
4929
- mod_name,
4930
- default_path_str,
4931
- secondary_path_str) ,
4932
- "delete or rename one of them to remove the ambiguity" ) ) ;
4933
- }
4934
- }
4935
+ if let Some ( p) = Parser :: submod_path_from_attr ( outer_attrs, & dir_path) {
4936
+ return Ok ( ModulePathSuccess { path : p, owns_directory : true } ) ;
4937
+ }
4938
+
4939
+ let paths = Parser :: default_submod_path ( id, & dir_path, self . sess . codemap ( ) ) ;
4940
+
4941
+ if !self . owns_directory {
4942
+ self . span_err ( id_sp, "cannot declare a new module at this location" ) ;
4943
+ let this_module = match self . mod_path_stack . last ( ) {
4944
+ Some ( name) => name. to_string ( ) ,
4945
+ None => self . root_module_name . as_ref ( ) . unwrap ( ) . clone ( ) ,
4946
+ } ;
4947
+ self . span_note ( id_sp,
4948
+ & format ! ( "maybe move this module `{0}` to its own directory \
4949
+ via `{0}/mod.rs`",
4950
+ this_module) ) ;
4951
+ if paths. path_exists {
4952
+ self . span_note ( id_sp,
4953
+ & format ! ( "... or maybe `use` the module `{}` instead \
4954
+ of possibly redeclaring it",
4955
+ paths. name) ) ;
4935
4956
}
4936
- } ;
4957
+ self . abort_if_errors ( ) ;
4958
+ }
4959
+
4960
+ match paths. result {
4961
+ Ok ( succ) => Ok ( succ) ,
4962
+ Err ( err) => Err ( self . span_fatal_help ( id_sp, & err. err_msg , & err. help_msg ) ) ,
4963
+ }
4964
+ }
4937
4965
4938
- self . eval_src_mod_from_path ( file_path, owns_directory,
4939
- mod_string. to_string ( ) , id_sp)
4966
+ /// Read a module from a source file.
4967
+ fn eval_src_mod ( & mut self ,
4968
+ id : ast:: Ident ,
4969
+ outer_attrs : & [ ast:: Attribute ] ,
4970
+ id_sp : Span )
4971
+ -> PResult < ( ast:: Item_ , Vec < ast:: Attribute > ) > {
4972
+ let ModulePathSuccess { path, owns_directory } = try!( self . submod_path ( id,
4973
+ outer_attrs,
4974
+ id_sp) ) ;
4975
+
4976
+ self . eval_src_mod_from_path ( path,
4977
+ owns_directory,
4978
+ token:: get_ident ( id) . to_string ( ) ,
4979
+ id_sp)
4940
4980
}
4941
4981
4942
4982
fn eval_src_mod_from_path ( & mut self ,
0 commit comments