@@ -2078,6 +2078,79 @@ Parser<ManagedTokenSource>::parse_visibility ()
2078
2078
}
2079
2079
}
2080
2080
2081
+ static std::string
2082
+ extract_module_path (const AST::AttrVec &inner_attrs,
2083
+ const AST::AttrVec &outer_attrs, const std::string &name)
2084
+ {
2085
+ AST::Attribute path_attr = AST::Attribute::create_empty ();
2086
+ for (const auto &attr : inner_attrs)
2087
+ {
2088
+ if (attr.get_path ().as_string () == "path")
2089
+ {
2090
+ path_attr = attr;
2091
+ break;
2092
+ }
2093
+ }
2094
+
2095
+ // Here, we found a path attribute, but it has no associated string. This is
2096
+ // invalid
2097
+ if (!path_attr.is_empty () && !path_attr.has_attr_input ())
2098
+ {
2099
+ rust_error_at (
2100
+ path_attr.get_locus (),
2101
+ // Split the format string so that -Wformat-diag does not complain...
2102
+ "path attributes must contain a filename: '%s'", "#![path = \"file\"]");
2103
+ return name;
2104
+ }
2105
+
2106
+ for (const auto &attr : outer_attrs)
2107
+ {
2108
+ if (attr.get_path ().as_string () == "path")
2109
+ {
2110
+ path_attr = attr;
2111
+ break;
2112
+ }
2113
+ }
2114
+
2115
+ // We didn't find a path attribute. This is not an error, there simply isn't
2116
+ // one present
2117
+ if (path_attr.is_empty ())
2118
+ return name;
2119
+
2120
+ // Here, we found a path attribute, but it has no associated string. This is
2121
+ // invalid
2122
+ if (!path_attr.has_attr_input ())
2123
+ {
2124
+ rust_error_at (
2125
+ path_attr.get_locus (),
2126
+ // Split the format string so that -Wformat-diag does not complain...
2127
+ "path attributes must contain a filename: '%s'", "#[path = \"file\"]");
2128
+ return name;
2129
+ }
2130
+
2131
+ auto path_value = path_attr.get_attr_input ().as_string ();
2132
+
2133
+ // At this point, the 'path' is of the following format: '= "<file.rs>"'
2134
+ // We need to remove the equal sign and only keep the actual filename.
2135
+ // In order to do this, we can simply go through the string until we find
2136
+ // a character that is not an equal sign or whitespace
2137
+ auto filename_begin = path_value.find_first_not_of ("=\t ");
2138
+
2139
+ auto path = path_value.substr (filename_begin);
2140
+
2141
+ // On windows, the path might mix '/' and '\' separators. Replace the
2142
+ // UNIX-like separators by MSDOS separators to make sure the path will resolve
2143
+ // properly.
2144
+ //
2145
+ // Source: rustc compiler
2146
+ // (https://github.com/rust-lang/rust/blob/9863bf51a52b8e61bcad312f81b5193d53099f9f/compiler/rustc_expand/src/module.rs#L174)
2147
+ #if defined(HAVE_DOS_BASED_FILE_SYSTEM)
2148
+ path.replace ('/', '\\');
2149
+ #endif /* HAVE_DOS_BASED_FILE_SYSTEM */
2150
+
2151
+ return path;
2152
+ }
2153
+
2081
2154
// Parses a module - either a bodied module or a module defined in another file.
2082
2155
template <typename ManagedTokenSource>
2083
2156
std::unique_ptr<AST::Module>
@@ -2104,14 +2177,18 @@ Parser<ManagedTokenSource>::parse_module (AST::Visibility vis,
2104
2177
// Construct an external module
2105
2178
return std::unique_ptr<AST::Module> (
2106
2179
new AST::Module (std::move (name), std::move (vis),
2107
- std::move (outer_attrs), locus,
2108
- lexer.get_filename () ));
2180
+ std::move (outer_attrs), locus, lexer.get_filename (),
2181
+ inline_module_stack ));
2109
2182
case LEFT_CURLY: {
2110
2183
lexer.skip_token ();
2111
2184
2112
2185
// parse inner attributes
2113
2186
AST::AttrVec inner_attrs = parse_inner_attributes ();
2114
2187
2188
+ std::string module_path_name
2189
+ = extract_module_path (inner_attrs, outer_attrs, name);
2190
+ InlineModuleStackScope scope (*this, std::move (module_path_name));
2191
+
2115
2192
// parse items
2116
2193
std::vector<std::unique_ptr<AST::Item>> items;
2117
2194
const_TokenPtr tok = lexer.peek_token ();
0 commit comments