diff --git a/Libraries/LibIDL/IDLParser.cpp b/Libraries/LibIDL/IDLParser.cpp index 8c419463825..937b1ed7440 100644 --- a/Libraries/LibIDL/IDLParser.cpp +++ b/Libraries/LibIDL/IDLParser.cpp @@ -160,9 +160,22 @@ HashMap Parser::parse_extended_attributes() static HashTable import_stack; Optional Parser::resolve_import(auto path) { - auto include_path = LexicalPath::join(import_base_path, path).string(); - if (!FileSystem::exists(include_path)) - report_parsing_error(ByteString::formatted("{}: No such file or directory", include_path), filename, input, lexer.tell()); + ByteString include_path; + for (auto import_base_path : import_base_paths) { + auto maybe_include_path = LexicalPath::join(import_base_path, path).string(); + if (!FileSystem::exists(maybe_include_path)) + continue; + + include_path = maybe_include_path; + break; + } + + if (include_path.is_empty()) { + StringBuilder error_message; + error_message.appendff("Failed to find {} in the following directories:\n", path); + error_message.join('\n', import_base_paths); + report_parsing_error(error_message.to_byte_string(), filename, input, lexer.tell()); + } auto real_path_error_or = FileSystem::real_path(include_path); if (real_path_error_or.is_error()) @@ -183,7 +196,7 @@ Optional Parser::resolve_import(auto path) auto data_or_error = file_or_error.value()->read_until_eof(); if (data_or_error.is_error()) report_parsing_error(ByteString::formatted("Failed to read {}: {}", real_path, data_or_error.error()), filename, input, lexer.tell()); - auto& result = Parser(this, real_path, data_or_error.value(), import_base_path).parse(); + auto& result = Parser(this, real_path, data_or_error.value(), import_base_paths).parse(); import_stack.remove(real_path); top_level_resolved_imports().set(real_path, &result); @@ -1229,16 +1242,16 @@ Interface& Parser::parse() return interface; } -Parser::Parser(ByteString filename, StringView contents, ByteString import_base_path) - : import_base_path(move(import_base_path)) +Parser::Parser(ByteString filename, StringView contents, Vector import_base_paths) + : import_base_paths(move(import_base_paths)) , filename(move(filename)) , input(contents) , lexer(input) { } -Parser::Parser(Parser* parent, ByteString filename, StringView contents, ByteString import_base_path) - : import_base_path(move(import_base_path)) +Parser::Parser(Parser* parent, ByteString filename, StringView contents, Vector import_base_paths) + : import_base_paths(move(import_base_paths)) , filename(move(filename)) , input(contents) , lexer(input) diff --git a/Libraries/LibIDL/IDLParser.h b/Libraries/LibIDL/IDLParser.h index 997f735059a..eff941706ab 100644 --- a/Libraries/LibIDL/IDLParser.h +++ b/Libraries/LibIDL/IDLParser.h @@ -17,7 +17,7 @@ namespace IDL { class Parser { public: - Parser(ByteString filename, StringView contents, ByteString import_base_path); + Parser(ByteString filename, StringView contents, Vector import_base_paths); Interface& parse(); Vector imported_files() const; @@ -35,7 +35,7 @@ private: Yes, }; - Parser(Parser* parent, ByteString filename, StringView contents, ByteString import_base_path); + Parser(Parser* parent, ByteString filename, StringView contents, Vector import_base_path); void assert_specific(char ch); void assert_string(StringView expected); @@ -68,7 +68,7 @@ private: ByteString parse_identifier_ending_with_space(); ByteString parse_identifier_ending_with_space_or(auto... possible_terminating_characters); - ByteString import_base_path; + Vector import_base_paths; ByteString filename; StringView input; LineTrackingLexer lexer; diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/main.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/main.cpp index fb9cfd87f67..6fa4f401fcd 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/main.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/main.cpp @@ -21,7 +21,7 @@ ErrorOr serenity_main(Main::Arguments arguments) { Core::ArgsParser args_parser; StringView path; - StringView import_base_path; + Vector import_base_paths; StringView output_path = "-"sv; StringView depfile_path; StringView depfile_prefix; @@ -41,7 +41,7 @@ ErrorOr serenity_main(Main::Arguments arguments) args_parser.add_option(depfile_path, "Path to write dependency file to", "depfile", 'd', "depfile-path"); args_parser.add_option(depfile_prefix, "Prefix to prepend to relative paths in dependency file", "depfile-prefix", 'p', "depfile-prefix"); args_parser.add_positional_argument(path, "IDL file", "idl-file"); - args_parser.add_positional_argument(import_base_path, "Import base path", "import-base-path", Core::ArgsParser::Required::No); + args_parser.add_positional_argument(import_base_paths, "Import base path", "import-base-path", Core::ArgsParser::Required::No); args_parser.parse(arguments); auto idl_file = TRY(Core::File::open(path, Core::File::OpenMode::Read)); @@ -51,10 +51,10 @@ ErrorOr serenity_main(Main::Arguments arguments) auto data = TRY(idl_file->read_until_eof()); - if (import_base_path.is_null()) - import_base_path = lexical_path.dirname(); + if (import_base_paths.is_empty()) + import_base_paths.append(lexical_path.dirname()); - IDL::Parser parser(path, data, import_base_path); + IDL::Parser parser(path, data, move(import_base_paths)); auto& interface = parser.parse(); // If the interface name is the same as its namespace, qualify the name in the generated code. diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp index 08573a62a0a..0f7438acf79 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp @@ -335,18 +335,33 @@ ErrorOr serenity_main(Main::Arguments arguments) Core::ArgsParser args_parser; StringView output_path; - StringView base_path; + Vector base_paths; Vector paths; args_parser.add_option(output_path, "Path to output generated files into", "output-path", 'o', "output-path"); - args_parser.add_option(base_path, "Path to root of IDL file tree", "base-path", 'b', "base-path"); + args_parser.add_option(Core::ArgsParser::Option { + .argument_mode = Core::ArgsParser::OptionArgumentMode::Required, + .help_string = "Path to root of IDL file tree(s)", + .long_name = "base-path", + .short_name = 'b', + .value_name = "base-path", + .accept_value = [&](StringView s) { + base_paths.append(s); + return true; + }, + }); args_parser.add_positional_argument(paths, "Paths of every IDL file that could be Exposed", "paths"); args_parser.parse(arguments); VERIFY(!paths.is_empty()); - VERIFY(!base_path.is_empty()); + VERIFY(!base_paths.is_empty()); - LexicalPath const lexical_base(base_path); + Vector lexical_bases; + for (auto const& base_path : base_paths) { + VERIFY(!base_path.is_empty()); + LexicalPath lexical_path(base_path); + lexical_bases.append(lexical_path.string()); + } // Read in all IDL files, we must own the storage for all of these for the lifetime of the program Vector file_contents; @@ -372,7 +387,7 @@ ErrorOr serenity_main(Main::Arguments arguments) for (size_t i = 0; i < paths.size(); ++i) { auto const& path = paths[i]; - IDL::Parser parser(path, file_contents[i], lexical_base.string()); + IDL::Parser parser(path, file_contents[i], lexical_bases); auto& interface = parser.parse(); if (interface.name.is_empty()) { s_error_string = ByteString::formatted("Interface for file {} missing", path);