@@ -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 ,
@@ -4859,82 +4877,104 @@ impl<'a> Parser<'a> {
4859
4877
self . mod_path_stack . pop ( ) . unwrap ( ) ;
4860
4878
}
4861
4879
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 > {
4868
4926
let mut prefix = PathBuf :: from ( & self . sess . codemap ( ) . span_to_filename ( self . span ) ) ;
4869
4927
prefix. pop ( ) ;
4870
4928
let mut dir_path = prefix;
4871
4929
for part in & self . mod_path_stack {
4872
4930
dir_path. push ( & * * part) ;
4873
4931
}
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
- }
4908
4932
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) ) ;
4933
4954
}
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
+ }
4935
4963
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)
4938
4978
}
4939
4979
4940
4980
fn eval_src_mod_from_path ( & mut self ,
0 commit comments