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