From 1b175c677d758252af957a6c0cbba675cdda9b46 Mon Sep 17 00:00:00 2001 From: "Christopher D. Leary" Date: Sun, 20 Oct 2024 00:32:57 -0700 Subject: [PATCH 1/2] [DSLX:LS] Diagnostics updates for dependent modules. Previously if you made a change to `leaf.x` that unbroke a module that depended on `leaf.x`, you wouldn't naturally get an update to the "problems" pane in VSCode that indicated the problem had been resolved. Introduces a very lightweight virtualized filesystem layer so we can see updated text in the editor (language server) workspace reflected in the language server results. Update before review. --- xls/codegen/vast/dslx_builder.cc | 13 +-- xls/dslx/BUILD | 1 + .../cpp_transpiler/cpp_transpiler_main.cc | 6 +- xls/dslx/create_import_data.cc | 11 ++- xls/dslx/create_import_data.h | 2 +- xls/dslx/dslx_fmt.cc | 3 +- xls/dslx/import_data.cc | 18 +++++ xls/dslx/import_data.h | 63 +++++++++++++-- xls/dslx/import_routines.cc | 23 +++--- xls/dslx/import_routines.h | 15 ++-- xls/dslx/interp_value_from_string.cc | 2 +- xls/dslx/ir_convert/ir_converter.cc | 5 +- xls/dslx/lsp/BUILD | 26 ++++++ xls/dslx/lsp/dslx_ls.cc | 25 ++++-- xls/dslx/lsp/import_sensitivity.cc | 74 +++++++++++++++++ xls/dslx/lsp/import_sensitivity.h | 44 ++++++++++ xls/dslx/lsp/import_sensitivity_test.cc | 63 +++++++++++++++ xls/dslx/lsp/language_server_adapter.cc | 80 +++++++++++++++++-- xls/dslx/lsp/language_server_adapter.h | 31 ++++++- xls/dslx/lsp/language_server_adapter_test.cc | 57 +++++++++++++ xls/dslx/run_routines/run_routines.cc | 10 ++- xls/dslx/type_system/typecheck_main.cc | 3 +- xls/dslx/type_system/typecheck_module.cc | 2 +- xls/flows/ir_wrapper.h | 9 ++- xls/fuzzer/sample_generator.cc | 3 +- xls/fuzzer/sample_runner.cc | 6 +- xls/passes/channel_legalization_pass.cc | 13 --- xls/public/c_api_dslx.cc | 3 +- xls/public/runtime_build_actions.cc | 2 +- xls/tools/eval_dslx_main.cc | 6 +- xls/tools/eval_ir_main.cc | 3 +- 31 files changed, 537 insertions(+), 85 deletions(-) create mode 100644 xls/dslx/lsp/import_sensitivity.cc create mode 100644 xls/dslx/lsp/import_sensitivity.h create mode 100644 xls/dslx/lsp/import_sensitivity_test.cc diff --git a/xls/codegen/vast/dslx_builder.cc b/xls/codegen/vast/dslx_builder.cc index 2401194548..fd3db70d99 100644 --- a/xls/codegen/vast/dslx_builder.cc +++ b/xls/codegen/vast/dslx_builder.cc @@ -292,9 +292,10 @@ DslxBuilder::DslxBuilder( : additional_search_paths_( WrapOptionalPathInVector(additional_search_path)), dslx_stdlib_path_(dslx_stdlib_path), - import_data_(dslx::CreateImportData( - dslx_stdlib_path_, additional_search_paths_, - /*enabled_warnings=*/dslx::kDefaultWarningsSet)), + import_data_( + dslx::CreateImportData(dslx_stdlib_path_, additional_search_paths_, + /*enabled_warnings=*/dslx::kDefaultWarningsSet, + std::make_unique())), module_(std::string(main_module_name), /*fs_path=*/std::nullopt, import_data_.file_table()), resolver_(resolver), @@ -527,7 +528,8 @@ absl::StatusOr DslxBuilder::GetOrImportModule( return dslx::TypecheckModule( module, &import_data_, &warnings_); }, - import_tokens, &import_data_, dslx::Span::Fake())); + import_tokens, &import_data_, dslx::Span::Fake(), + import_data_.vfs())); auto* name_def = resolver_->MakeNameDef(*this, dslx::Span::Fake(), tail); VLOG(2) << "Creating import node via name definition `" @@ -734,7 +736,8 @@ absl::StatusOr DslxBuilder::FormatModule() { const std::string file_name = module_.name() + ".x"; auto import_data = dslx::CreateImportData(dslx_stdlib_path_, additional_search_paths_, - /*enabled_warnings=*/dslx::kDefaultWarningsSet); + /*enabled_warnings=*/dslx::kDefaultWarningsSet, + std::make_unique()); dslx::Fileno fileno = import_data.file_table().GetOrCreate(file_name); dslx::Scanner scanner(import_data.file_table(), fileno, text); dslx::Parser parser(module_.name(), &scanner); diff --git a/xls/dslx/BUILD b/xls/dslx/BUILD index f9d566e67d..f0f4383e89 100644 --- a/xls/dslx/BUILD +++ b/xls/dslx/BUILD @@ -318,6 +318,7 @@ cc_library( ":import_record", ":interp_bindings", ":warning_kind", + "//xls/common/file:filesystem", "//xls/common/status:ret_check", "//xls/common/status:status_macros", "//xls/dslx/bytecode:bytecode_cache_interface", diff --git a/xls/dslx/cpp_transpiler/cpp_transpiler_main.cc b/xls/dslx/cpp_transpiler/cpp_transpiler_main.cc index 0da87d8c06..2066beb340 100644 --- a/xls/dslx/cpp_transpiler/cpp_transpiler_main.cc +++ b/xls/dslx/cpp_transpiler/cpp_transpiler_main.cc @@ -70,9 +70,9 @@ absl::Status RealMain(const std::filesystem::path& module_path, std::string_view namespaces) { XLS_ASSIGN_OR_RETURN(std::string module_text, GetFileContents(module_path)); - ImportData import_data( - CreateImportData(dslx_stdlib_path, /*additional_search_paths=*/dslx_paths, - kDefaultWarningsSet)); + ImportData import_data(CreateImportData( + dslx_stdlib_path, /*additional_search_paths=*/dslx_paths, + kDefaultWarningsSet, std::make_unique())); XLS_ASSIGN_OR_RETURN(TypecheckedModule module, ParseAndTypecheck(module_text, std::string(module_path), "source", &import_data)); diff --git a/xls/dslx/create_import_data.cc b/xls/dslx/create_import_data.cc index 02acecd64f..458b5876b0 100644 --- a/xls/dslx/create_import_data.cc +++ b/xls/dslx/create_import_data.cc @@ -29,15 +29,17 @@ namespace xls::dslx { ImportData CreateImportData( const std::filesystem::path& stdlib_path, absl::Span additional_search_paths, - WarningKindSet warnings) { - ImportData import_data(stdlib_path, additional_search_paths, warnings); + WarningKindSet warnings, std::unique_ptr vfs) { + ImportData import_data(stdlib_path, additional_search_paths, warnings, + std::move(vfs)); import_data.SetBytecodeCache(std::make_unique(&import_data)); return import_data; } ImportData CreateImportDataForTest() { ImportData import_data(xls::kDefaultDslxStdlibPath, - /*additional_search_paths=*/{}, kDefaultWarningsSet); + /*additional_search_paths=*/{}, kDefaultWarningsSet, + std::make_unique()); import_data.SetBytecodeCache(std::make_unique(&import_data)); return import_data; } @@ -45,7 +47,8 @@ ImportData CreateImportDataForTest() { std::unique_ptr CreateImportDataPtrForTest() { auto import_data = absl::WrapUnique( new ImportData(xls::kDefaultDslxStdlibPath, - /*additional_search_paths=*/{}, kDefaultWarningsSet)); + /*additional_search_paths=*/{}, kDefaultWarningsSet, + std::make_unique())); import_data->SetBytecodeCache( std::make_unique(import_data.get())); return import_data; diff --git a/xls/dslx/create_import_data.h b/xls/dslx/create_import_data.h index 6e834e8a56..b6c26c9fca 100644 --- a/xls/dslx/create_import_data.h +++ b/xls/dslx/create_import_data.h @@ -32,7 +32,7 @@ namespace xls::dslx { ImportData CreateImportData( const std::filesystem::path& stdlib_path, absl::Span additional_search_paths, - WarningKindSet warnings); + WarningKindSet warnings, std::unique_ptr vfs); // Creates an ImportData with reasonable defaults (standard path to the stdlib // and no additional search paths). diff --git a/xls/dslx/dslx_fmt.cc b/xls/dslx/dslx_fmt.cc index ba44b31fb3..172cc9e976 100644 --- a/xls/dslx/dslx_fmt.cc +++ b/xls/dslx/dslx_fmt.cc @@ -78,7 +78,8 @@ absl::Status RealMain(std::string_view input_path, ImportData import_data = CreateImportData(xls::kDefaultDslxStdlibPath, - /*additional_search_paths=*/{}, kNoWarningsSet); + /*additional_search_paths=*/{}, kNoWarningsSet, + std::make_unique()); std::string formatted; if (mode == "autofmt") { std::vector comments; diff --git a/xls/dslx/import_data.cc b/xls/dslx/import_data.cc index 424e9af54a..dc4b915e05 100644 --- a/xls/dslx/import_data.cc +++ b/xls/dslx/import_data.cc @@ -32,6 +32,7 @@ #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" +#include "xls/common/file/filesystem.h" #include "xls/common/status/ret_check.h" #include "xls/common/status/status_macros.h" #include "xls/dslx/bytecode/bytecode_cache_interface.h" @@ -46,6 +47,19 @@ namespace xls::dslx { +absl::Status RealFilesystem::FileExists(const std::filesystem::path& path) { + return xls::FileExists(path); +} + +absl::StatusOr RealFilesystem::GetFileContents( + const std::filesystem::path& path) { + return xls::GetFileContents(path); +} + +absl::StatusOr RealFilesystem::GetCurrentDirectory() { + return xls::GetCurrentDirectory(); +} + /* static */ absl::StatusOr ImportTokens::FromString( std::string_view module_name) { return ImportTokens(absl::StrSplit(module_name, '.')); @@ -185,6 +199,10 @@ absl::Status ImportData::AddToImporterStack( } } + if (importer_stack_observer_ != nullptr) { + importer_stack_observer_(importer_span, imported); + } + VLOG(3) << "Adding import span to stack: " << importer_span.ToString(file_table()); importer_stack_.push_back(new_import_record); diff --git a/xls/dslx/import_data.h b/xls/dslx/import_data.h index c1347e9db9..9a793f71c5 100644 --- a/xls/dslx/import_data.h +++ b/xls/dslx/import_data.h @@ -40,6 +40,33 @@ namespace xls::dslx { +// A virtualizable filesystem seam so that we can perform imports using either +// the real filesystem or a virtual filesystem. +// +// This is useful for use-cases like language servers where a mix of real +// filesystem and virtualized filesystem contents (i.e. with temporary edits in +// working buffers) are used. +class VirtualizableFilesystem { + public: + virtual ~VirtualizableFilesystem() = default; + + virtual absl::Status FileExists(const std::filesystem::path& path) = 0; + + virtual absl::StatusOr GetFileContents( + const std::filesystem::path& path) = 0; + + virtual absl::StatusOr GetCurrentDirectory() = 0; +}; + +class RealFilesystem : public VirtualizableFilesystem { + public: + ~RealFilesystem() override = default; + absl::Status FileExists(const std::filesystem::path& path) override; + absl::StatusOr GetFileContents( + const std::filesystem::path& path) override; + absl::StatusOr GetCurrentDirectory() override; +}; + // An entry that goes into the ImportData. class ModuleInfo { public: @@ -104,12 +131,11 @@ class ImportTokens { std::vector pieces_; }; -// Wrapper around a {subject: module_info} mapping that modules can be imported -// into. -// Use the routines in create_import_data.h to instantiate an object. +// Wrapper around a `{subject: module_info}` mapping that modules can be +// imported into. class ImportData { public: - // All instantiations of ImportData should pass a stdlib_path as below. + // Use the routines in `create_import_data.h` to instantiate an object. ImportData() = delete; bool Contains(const ImportTokens& target) const { @@ -124,6 +150,17 @@ class ImportData { absl::Status AddToImporterStack(const Span& importer_span, const std::filesystem::path& imported); + // Registers a callback to be notified when we see that an importing span is + // beginning to import a filesystem path. This is useful for tracking the DAG + // of dependencies. + // + // Recursion checks are performed before this callback is invoked, so the + // callback results should all be validated to be DAG compliant. + void SetImporterStackObserver( + std::function f) { + importer_stack_observer_ = std::move(f); + } + // This pops the entry from the import stack and verifies it's the latest // entry, returning an error iff it is not. absl::Status PopFromImporterStack(const Span& import_span); @@ -205,22 +242,29 @@ class ImportData { FileTable& file_table() { return file_table_; } const FileTable& file_table() const { return file_table_; } + VirtualizableFilesystem& vfs() const { return *vfs_; } + private: friend ImportData CreateImportData(const std::filesystem::path&, absl::Span, - WarningKindSet); + WarningKindSet, + std::unique_ptr); + friend std::unique_ptr CreateImportDataPtr( const std::filesystem::path&, absl::Span, WarningKindSet); + friend ImportData CreateImportDataForTest(); friend std::unique_ptr CreateImportDataPtrForTest(); ImportData(std::filesystem::path stdlib_path, absl::Span additional_search_paths, - WarningKindSet enabled_warnings) + WarningKindSet enabled_warnings, + std::unique_ptr vfs) : stdlib_path_(std::move(stdlib_path)), additional_search_paths_(additional_search_paths), - enabled_warnings_(enabled_warnings) {} + enabled_warnings_(enabled_warnings), + vfs_(std::move(vfs)) {} // Attempts to find a module owned by this ImportData according to the // filename present in "span". Returns a NotFound error if a corresponding @@ -240,8 +284,13 @@ class ImportData { WarningKindSet enabled_warnings_; std::unique_ptr bytecode_cache_; + std::function + importer_stack_observer_; + // See comment on AddToImporterStack() above. std::vector importer_stack_; + + std::unique_ptr vfs_; }; } // namespace xls::dslx diff --git a/xls/dslx/import_routines.cc b/xls/dslx/import_routines.cc index 4b073b9748..05179d9c33 100644 --- a/xls/dslx/import_routines.cc +++ b/xls/dslx/import_routines.cc @@ -32,7 +32,6 @@ #include "absl/strings/str_join.h" #include "absl/types/span.h" #include "xls/common/config/xls_config.h" -#include "xls/common/file/filesystem.h" #include "xls/common/file/get_runfile_path.h" #include "xls/common/status/ret_check.h" #include "xls/common/status/status_macros.h" @@ -48,7 +47,8 @@ namespace xls::dslx { static absl::StatusOr FindExistingPath( const ImportTokens& subject, const std::filesystem::path& stdlib_path, absl::Span additional_search_paths, - const Span& import_span, const FileTable& file_table) { + const Span& import_span, const FileTable& file_table, + VirtualizableFilesystem& vfs) { absl::Span pieces = subject.pieces(); std::optional subject_parent_path; const absl::flat_hash_set builtins = { @@ -66,13 +66,13 @@ static absl::StatusOr FindExistingPath( std::vector attempted; // Helper that tries to see if "path" is present relative to "base". - auto try_path = [&attempted](const std::filesystem::path& base, - const std::filesystem::path& path) + auto try_path = [&attempted, &vfs](const std::filesystem::path& base, + const std::filesystem::path& path) -> std::optional { auto full_path = std::filesystem::path(base) / path; VLOG(3) << "Trying path: " << full_path; attempted.push_back(std::string{full_path}); - if (FileExists(full_path).ok()) { + if (vfs.FileExists(full_path).ok()) { VLOG(3) << "Found existing file for import path: " << full_path; return full_path; } @@ -104,7 +104,7 @@ static absl::StatusOr FindExistingPath( VLOG(3) << "Attempting runfile-based import path via " << subject_path; if (absl::StatusOr runfile_path = GetXlsRunfilePath(GetXLSRootDir() / subject_path); - runfile_path.ok() && FileExists(*runfile_path).ok()) { + runfile_path.ok() && vfs.FileExists(*runfile_path).ok()) { return *runfile_path; } @@ -121,7 +121,7 @@ static absl::StatusOr FindExistingPath( << *subject_parent_path; if (absl::StatusOr runfile_path = GetXlsRunfilePath( absl::StrCat(GetXLSRootDir(), *subject_parent_path)); - runfile_path.ok() && FileExists(*runfile_path).ok()) { + runfile_path.ok() && vfs.FileExists(*runfile_path).ok()) { return *runfile_path; } } @@ -138,13 +138,14 @@ static absl::StatusOr FindExistingPath( "attempted: [ %s ]; working " "directory: \"%s\"; stdlib directory: \"%s\"", import_span.ToString(file_table), absl::StrJoin(attempted, " :: "), - GetCurrentDirectory().value(), stdlib_path)); + vfs.GetCurrentDirectory().value(), stdlib_path)); } absl::StatusOr DoImport(const TypecheckModuleFn& ftypecheck, const ImportTokens& subject, ImportData* import_data, - const Span& import_span) { + const Span& import_span, + VirtualizableFilesystem& vfs) { XLS_RET_CHECK(import_data != nullptr); if (import_data->Contains(subject)) { VLOG(3) << "DoImport (cached) subject: " << subject.ToString(); @@ -157,13 +158,13 @@ absl::StatusOr DoImport(const TypecheckModuleFn& ftypecheck, XLS_ASSIGN_OR_RETURN(std::filesystem::path found_path, FindExistingPath(subject, import_data->stdlib_path(), import_data->additional_search_paths(), - import_span, file_table)); + import_span, file_table, vfs)); XLS_RETURN_IF_ERROR(import_data->AddToImporterStack(import_span, found_path)); absl::Cleanup cleanup = absl::MakeCleanup( [&] { CHECK_OK(import_data->PopFromImporterStack(import_span)); }); - XLS_ASSIGN_OR_RETURN(std::string contents, GetFileContents(found_path)); + XLS_ASSIGN_OR_RETURN(std::string contents, vfs.GetFileContents(found_path)); absl::Span pieces = subject.pieces(); std::string fully_qualified_name = absl::StrJoin(pieces, "."); diff --git a/xls/dslx/import_routines.h b/xls/dslx/import_routines.h index 4ca0d259a5..d2320ba15e 100644 --- a/xls/dslx/import_routines.h +++ b/xls/dslx/import_routines.h @@ -28,27 +28,30 @@ namespace xls::dslx { // Type-checking callback lambda. using TypecheckModuleFn = std::function(Module*)>; -// Imports the module identified (globally) by 'subject'. +// Imports the module identified (globally) by `subject`. // // Importing means: locating, parsing, typechecking, and caching in the import // cache. // -// Resolves against an existing import in 'cache' if it is present. +// Resolves against an existing import in `import_data` if it is present. // // Args: // ftypecheck: Function that can be used to get type information for a module. // subject: Tokens that globally uniquely identify the module to import; e.g. -// something built-in like ('std',) for the standard library or something -// fully qualified like ('xls', 'lib', 'math'). -// cache: Cache that we resolve against so we don't waste resources +// something built-in like `{"std"}` for the standard library or something +// fully qualified like `{"xls", "lib", "math"}`. +// import_data: Cache that we resolve against so we don't waste resources // re-importing things in the import DAG. +// import_span: Indicates the "importer" (i.e. the AST node, lexically) that +// caused this attempt to import. // // Returns: // The imported module information. absl::StatusOr DoImport(const TypecheckModuleFn& ftypecheck, const ImportTokens& subject, ImportData* import_data, - const Span& import_span); + const Span& import_span, + VirtualizableFilesystem& vfs); } // namespace xls::dslx diff --git a/xls/dslx/interp_value_from_string.cc b/xls/dslx/interp_value_from_string.cc index 1e328bde71..135612d2d7 100644 --- a/xls/dslx/interp_value_from_string.cc +++ b/xls/dslx/interp_value_from_string.cc @@ -37,7 +37,7 @@ absl::StatusOr InterpValueFromString( ImportData import_data = CreateImportData( dslx_stdlib_path, /*additional_search_paths=*/absl::Span{}, - kDefaultWarningsSet); + kDefaultWarningsSet, std::make_unique()); XLS_ASSIGN_OR_RETURN(TypecheckedModule tm, ParseAndTypecheck(program, "cmdline_constant.x", "cmdline_constant", &import_data)); diff --git a/xls/dslx/ir_convert/ir_converter.cc b/xls/dslx/ir_convert/ir_converter.cc index dd1f482726..4b77d230a1 100644 --- a/xls/dslx/ir_convert/ir_converter.cc +++ b/xls/dslx/ir_convert/ir_converter.cc @@ -550,8 +550,9 @@ absl::StatusOr ConvertFilesToPackage( "path to know where to resolve the entry function"); } for (std::string_view path : paths) { - ImportData import_data(CreateImportData(stdlib_path, dslx_paths, - convert_options.enabled_warnings)); + ImportData import_data(CreateImportData( + stdlib_path, dslx_paths, convert_options.enabled_warnings, + std::make_unique())); XLS_ASSIGN_OR_RETURN(std::string text, GetFileContents(path)); XLS_ASSIGN_OR_RETURN(std::string module_name, PathToName(path)); XLS_RETURN_IF_ERROR(AddContentsToPackage( diff --git a/xls/dslx/lsp/BUILD b/xls/dslx/lsp/BUILD index 921f39befc..f762198df6 100644 --- a/xls/dslx/lsp/BUILD +++ b/xls/dslx/lsp/BUILD @@ -54,6 +54,9 @@ cc_library( srcs = ["language_server_adapter.cc"], hdrs = ["language_server_adapter.h"], deps = [ + "//xls/common/file:filesystem", + "//xls/common/status:ret_check", + ":import_sensitivity", ":document_symbols", ":find_definition", ":lsp_type_utils", @@ -147,3 +150,26 @@ cc_library( "@verible//common/lsp:lsp-protocol-enums", ], ) + +cc_library( + name = "import_sensitivity", + srcs = ["import_sensitivity.cc"], + hdrs = ["import_sensitivity.h"], + deps = [ + "@com_google_absl//absl/log", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/container:flat_hash_set", + "@com_google_absl//absl/container:btree", + "@com_google_absl//absl/strings", + ], +) + +cc_test( + name = "import_sensitivity_test", + srcs = ["import_sensitivity_test.cc"], + deps = [ + ":import_sensitivity", + "@com_google_googletest//:gtest", + "//xls/common:xls_gunit_main", + ], +) diff --git a/xls/dslx/lsp/dslx_ls.cc b/xls/dslx/lsp/dslx_ls.cc index b470581bfc..34497a3228 100644 --- a/xls/dslx/lsp/dslx_ls.cc +++ b/xls/dslx/lsp/dslx_ls.cc @@ -106,11 +106,26 @@ void TextChangeHandler(const std::string& file_uri, // Note: this returns a status, but we don't need to surface it from here. adapter.Update(file_uri, file_content).IgnoreError(); }); - verible::lsp::PublishDiagnosticsParams params{ - .uri = file_uri, - .diagnostics = adapter.GenerateParseDiagnostics(file_uri), - }; - dispatcher.SendNotification("textDocument/publishDiagnostics", params); + + // For now we brute force evaluate all the files in the DAG that may be + // sensitive to the update. We'll need to be smarter as we observe scaling + // issues (e.g. only evaluate sensitive files if the original file went from + // being an import-time error to having no import-time error). + std::vector sensitive_uris = + adapter.import_sensitivity().GatherAllSensitiveToChangeIn(file_uri); + for (std::string sensitive_uri : sensitive_uris) { + // Note to all dependent files that an update has occurred. + // We don't need to do this for the file that we updated directly. + if (sensitive_uri != file_uri) { + adapter.Update(sensitive_uri, std::nullopt).IgnoreError(); + } + + verible::lsp::PublishDiagnosticsParams params{ + .uri = sensitive_uri, + .diagnostics = adapter.GenerateParseDiagnostics(sensitive_uri), + }; + dispatcher.SendNotification("textDocument/publishDiagnostics", params); + } } absl::Status RealMain() { diff --git a/xls/dslx/lsp/import_sensitivity.cc b/xls/dslx/lsp/import_sensitivity.cc new file mode 100644 index 0000000000..8b3e3d1ce4 --- /dev/null +++ b/xls/dslx/lsp/import_sensitivity.cc @@ -0,0 +1,74 @@ +// Copyright 2024 The XLS Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "xls/dslx/lsp/import_sensitivity.h" + +#include "absl/log/log.h" +#include "absl/strings/str_join.h" + +namespace xls::dslx { + +void ImportSensitivity::NoteImportAttempt(std::string_view importer_uri, + std::string_view imported_uri) { + imported_to_importers_[imported_uri].insert(std::string{importer_uri}); +} + +std::vector ImportSensitivity::GatherAllSensitiveToChangeIn( + std::string_view uri) { + // We maintain a set for O(1) checking of whether a file has already been + // placed in the result, but we keep a vector for stable dependency ordering + // and avoiding non-deterministic behavior. + absl::flat_hash_set result_set = {std::string{uri}}; + std::vector result = {std::string{uri}}; + + auto add_result = [&](std::string_view to_add) { + auto [it, inserted] = result_set.insert(std::string{to_add}); + if (inserted) { + result.push_back(std::string{to_add}); + } + }; + + // We note which ones we've already checked and we keep a worklist of things + // we need to check, seeded with the ones we know import `uri`. + absl::flat_hash_set checked; + std::vector to_check(imported_to_importers_[uri].begin(), + imported_to_importers_[uri].end()); + + for (const std::string& s : to_check) { + add_result(s); + } + + while (!to_check.empty()) { + // Pluck off the `to_check` worklist. + std::string uri = to_check.back(); + to_check.pop_back(); + + auto [it, inserted] = checked.insert(uri); + if (!inserted) { + continue; + } + + const absl::btree_set& importers = imported_to_importers_[uri]; + for (const std::string& s : importers) { + add_result(s); + } + to_check.insert(to_check.end(), importers.begin(), importers.end()); + } + + VLOG(5) << "GatherAllSensitiveToChangeIn; uri: " << uri + << " result: " << absl::StrJoin(result, ", "); + return result; +} + +} // namespace xls::dslx diff --git a/xls/dslx/lsp/import_sensitivity.h b/xls/dslx/lsp/import_sensitivity.h new file mode 100644 index 0000000000..2f442c0c6f --- /dev/null +++ b/xls/dslx/lsp/import_sensitivity.h @@ -0,0 +1,44 @@ +// Copyright 2024 The XLS Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef XLS_DSLX_LSP_IMPORT_SENSITIVITY_H_ +#define XLS_DSLX_LSP_IMPORT_SENSITIVITY_H_ + +#include +#include + +#include "absl/container/btree_set.h" +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" + +namespace xls::dslx { + +// Tracks import attempts that are made by DSLX file URIs in order to determine +// which we should try to re-evaluate when there's a change. +class ImportSensitivity { + public: + void NoteImportAttempt(std::string_view importer_uri, + std::string_view imported_uri); + + std::vector GatherAllSensitiveToChangeIn(std::string_view uri); + + private: + // Note: we use a btree set for the values for stable ordering of results. + absl::flat_hash_map> + imported_to_importers_; +}; + +} // namespace xls::dslx + +#endif // XLS_DSLX_LSP_IMPORT_SENSITIVITY_H_ diff --git a/xls/dslx/lsp/import_sensitivity_test.cc b/xls/dslx/lsp/import_sensitivity_test.cc new file mode 100644 index 0000000000..901423f78d --- /dev/null +++ b/xls/dslx/lsp/import_sensitivity_test.cc @@ -0,0 +1,63 @@ +// Copyright 2024 The XLS Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "xls/dslx/lsp/import_sensitivity.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace xls::dslx { +namespace { + +TEST(ImportSensitivityTest, SingleImport) { + ImportSensitivity s; + s.NoteImportAttempt("outer.x", "inner.x"); + + auto sensitive_to_outer = s.GatherAllSensitiveToChangeIn("outer.x"); + ASSERT_EQ(sensitive_to_outer.size(), 1); + EXPECT_THAT(sensitive_to_outer, testing::UnorderedElementsAre("outer.x")); + + auto sensitive_to_inner = s.GatherAllSensitiveToChangeIn("inner.x"); + EXPECT_EQ(sensitive_to_inner.size(), 2); + EXPECT_THAT(sensitive_to_inner, + testing::UnorderedElementsAre("outer.x", "inner.x")); +} + +TEST(ImportSensitivityTest, TwoLevelLinear) { + ImportSensitivity s; + s.NoteImportAttempt("middle.x", "inner.x"); + s.NoteImportAttempt("outer.x", "middle.x"); + + auto sensitive_to_inner = s.GatherAllSensitiveToChangeIn("inner.x"); + EXPECT_EQ(sensitive_to_inner.size(), 3); + EXPECT_THAT(sensitive_to_inner, + testing::UnorderedElementsAre("outer.x", "middle.x", "inner.x")); +} + +TEST(ImportSensitivityTest, Diamond) { + ImportSensitivity s; + s.NoteImportAttempt("middle0.x", "leaf.x"); + s.NoteImportAttempt("middle1.x", "leaf.x"); + s.NoteImportAttempt("outer.x", "middle0.x"); + s.NoteImportAttempt("outer.x", "middle1.x"); + + auto sensitive_to_inner = s.GatherAllSensitiveToChangeIn("leaf.x"); + EXPECT_EQ(sensitive_to_inner.size(), 4); + EXPECT_THAT(sensitive_to_inner, + testing::UnorderedElementsAre("outer.x", "middle0.x", "middle1.x", + "leaf.x")); +} + +} // namespace +} // namespace xls::dslx diff --git a/xls/dslx/lsp/language_server_adapter.cc b/xls/dslx/lsp/language_server_adapter.cc index 7cdf340bb8..b1c4b52a0b 100644 --- a/xls/dslx/lsp/language_server_adapter.cc +++ b/xls/dslx/lsp/language_server_adapter.cc @@ -32,11 +32,13 @@ #include "absl/time/clock.h" #include "absl/time/time.h" #include "absl/types/span.h" -#include "nlohmann/json.hpp" #include "external/verible/common/lsp/lsp-file-utils.h" #include "external/verible/common/lsp/lsp-protocol-enums.h" #include "external/verible/common/lsp/lsp-protocol.h" +#include "nlohmann/json.hpp" #include "xls/common/casts.h" +#include "xls/common/file/filesystem.h" +#include "xls/common/status/ret_check.h" #include "xls/common/status/status_macros.h" #include "xls/dslx/create_import_data.h" #include "xls/dslx/extract_module_name.h" @@ -137,6 +139,47 @@ absl::StatusOr MaybeRelpathToUri( } // namespace +// Implements an overlay on top of the underlying filesystem that prefers the +// language server's versions when they are present. +// +// TODO(cdleary): 2024-10-20 Note that this is not currently hooked into +// workspace file creation/deletion events explicitly, so everything comes via +// textual updates. +class LanguageServerFilesystem : public VirtualizableFilesystem { + public: + explicit LanguageServerFilesystem(LanguageServerAdapter& parent) + : parent_(parent) {} + + absl::Status FileExists(const std::filesystem::path& path) override { + std::string uri = verible::lsp::PathToLSPUri(path.c_str()); + auto it = parent_.vfs_contents().find(uri); + if (it == parent_.vfs_contents().end()) { + return xls::FileExists(path); + } + + return absl::OkStatus(); + } + + absl::StatusOr GetFileContents( + const std::filesystem::path& path) override { + // First we check if it exists in the virtual layer. + std::string uri = verible::lsp::PathToLSPUri(path.c_str()); + auto it = parent_.vfs_contents().find(uri); + if (it == parent_.vfs_contents().end()) { + return xls::GetFileContents(path); + } + + return it->second; + } + + absl::StatusOr GetCurrentDirectory() override { + return xls::GetCurrentDirectory(); + } + + private: + LanguageServerAdapter& parent_; +}; + LanguageServerAdapter::LanguageServerAdapter( std::string_view stdlib, const std::vector& dslx_paths) @@ -150,8 +193,21 @@ LanguageServerAdapter::ParseData* LanguageServerAdapter::FindParsedForUri( return nullptr; } -absl::Status LanguageServerAdapter::Update(std::string_view file_uri, - std::string_view dslx_code) { +absl::Status LanguageServerAdapter::Update( + std::string_view file_uri, std::optional dslx_code) { + // Either update or get the last contents from the virtual filesystem map. + if (dslx_code.has_value()) { + vfs_contents_[file_uri] = std::string{dslx_code.value()}; + } else { + auto it = vfs_contents_.find(file_uri); + if (it == vfs_contents_.end()) { + return absl::NotFoundError(absl::StrCat( + "Could not find previous contents for file URI: ", file_uri)); + } + dslx_code = it->second; + } + XLS_RET_CHECK(dslx_code.has_value()); + const absl::Time start = absl::Now(); absl::StatusOr module_name_or = ExtractModuleName(file_uri); if (!module_name_or.ok()) { @@ -164,12 +220,26 @@ absl::Status LanguageServerAdapter::Update(std::string_view file_uri, std::unique_ptr& insert_value = inserted.first->second; ImportData import_data = - CreateImportData(stdlib_, dslx_paths_, kAllWarningsSet); + CreateImportData(stdlib_, dslx_paths_, kAllWarningsSet, + std::make_unique(*this)); + + import_data.SetImporterStackObserver( + [&](const Span& importer_span, const std::filesystem::path& imported) { + std::string_view importer_filename = + importer_span.GetFilename(import_data.file_table()); + CHECK(absl::StartsWith(importer_filename, "file://") || + absl::StartsWith(importer_filename, "memfile://")) + << "importer_filename: " << importer_filename + << " imported: " << imported; + std::string imported_uri = verible::lsp::PathToLSPUri(imported.c_str()); + import_sensitivity_.NoteImportAttempt(importer_filename, imported_uri); + }); + const std::string& module_name = module_name_or.value(); std::vector comments; absl::StatusOr typechecked_module = - ParseAndTypecheck(dslx_code, /*path=*/file_uri, + ParseAndTypecheck(dslx_code.value(), /*path=*/file_uri, /*module_name=*/module_name, &import_data, &comments); if (typechecked_module.ok()) { diff --git a/xls/dslx/lsp/language_server_adapter.h b/xls/dslx/lsp/language_server_adapter.h index b05b1909f9..0df6376122 100644 --- a/xls/dslx/lsp/language_server_adapter.h +++ b/xls/dslx/lsp/language_server_adapter.h @@ -34,6 +34,7 @@ #include "xls/dslx/frontend/module.h" #include "xls/dslx/frontend/pos.h" #include "xls/dslx/import_data.h" +#include "xls/dslx/lsp/import_sensitivity.h" #include "xls/dslx/parse_and_typecheck.h" #include "xls/dslx/type_system/type_info.h" @@ -52,15 +53,27 @@ class LanguageServerAdapter { LanguageServerAdapter(std::string_view stdlib, const std::vector& dslx_paths); + // Takes note that `dslx_code` is the current file contents for `file_uri` + // and performs a parse-and-typecheck using that file/contents as the entry + // point. + // + // `dslx_code` can be nullopt when we're re-evaluating the previous contents + // again; i.e. because we think a dependency may have been corrected. + // // Note: this is parsing is triggered for every keystroke. Fine for now. // Successful and unsuccessful parses are memoized so that their status // and can be queried. + // // Implementation note: since we currently do not react to buffer closed // events in the buffer change listener, we keep track of every file ever // opened and never delete. - absl::Status Update(std::string_view file_uri, std::string_view dslx_code); + absl::Status Update(std::string_view file_uri, + std::optional dslx_code); - // Generate LSP diagnostics for the file with given uri + // Generate LSP diagnostics for the file with given `uri`. + // + // Note that this only finds the existing parse-and-typecheck result, it does + // not trigger any new parsing activity, for that we need to `Update`. std::vector GenerateParseDiagnostics( std::string_view uri) const; @@ -100,6 +113,12 @@ class LanguageServerAdapter { DocumentHighlight(std::string_view uri, const verible::lsp::Position& position) const; + ImportSensitivity& import_sensitivity() { return import_sensitivity_; } + + const absl::flat_hash_map& vfs_contents() const { + return vfs_contents_; + } + private: class ParseData; @@ -150,6 +169,14 @@ class LanguageServerAdapter { const std::string stdlib_; const std::vector dslx_paths_; absl::flat_hash_map> uri_parse_data_; + + // The language server, in effect, needs to maintain a virtual filesystem + // layer, that's interwoven with the true filesystem; i.e. if a file is + // present on disk but not opened in the LSP workspace, we resolve it on + // disk. + absl::flat_hash_map vfs_contents_; + + ImportSensitivity import_sensitivity_; }; } // namespace xls::dslx diff --git a/xls/dslx/lsp/language_server_adapter_test.cc b/xls/dslx/lsp/language_server_adapter_test.cc index dbf471b5d5..1750a08315 100644 --- a/xls/dslx/lsp/language_server_adapter_test.cc +++ b/xls/dslx/lsp/language_server_adapter_test.cc @@ -37,6 +37,7 @@ namespace xls::dslx { namespace { using ::absl_testing::StatusIs; +using ::testing::HasSubstr; std::string DebugString(const verible::lsp::Position& pos) { return absl::StrFormat("Position{.line=%d, .character=%d}", pos.line, @@ -381,5 +382,61 @@ fn f() -> u32 { FOO })")); EXPECT_EQ(highlights[3].range.start.line, 4); } +// This models a scenario where we observe a problem in `outer.x`, but that +// problem actually stems from the import of `inner.x`. +// +// Even though `outer.x` does not successfully import `inner.x` we test that +// the module DAG information contains "outer tried to import inner" -- we use +// this DAG information to walk upwards and check whether `outer.x` is ok once +// `inner.x` is fixed. +TEST(LanguageServerAdapterTest, DagShowsUnsuccessfulImports) { + XLS_ASSERT_OK_AND_ASSIGN(TempDirectory tempdir, TempDirectory::Create()); + LanguageServerAdapter adapter(kDefaultDslxStdlibPath, + /*dslx_paths=*/{tempdir.path()}); + + std::string inner_uri = absl::StrFormat("file://%s/inner.x", tempdir.path()); + const std::string bad_inner_contents = R"(const FOO = u32:42;)"; + const std::string good_inner_contents = R"(pub const FOO = u32:42;)"; + XLS_ASSERT_OK( + SetFileContents(tempdir.path() / "inner.x", bad_inner_contents)); + XLS_ASSERT_OK(adapter.Update(inner_uri, bad_inner_contents)); + + std::string outer_uri = absl::StrFormat("file://%s/outer.x", tempdir.path()); + std::string outer_contents = R"(import inner; + +const OUTER_FOO = inner::FOO; // this is not public, at first +)"; + EXPECT_THAT( + adapter.Update(outer_uri, outer_contents), + StatusIs(absl::StatusCode::kInvalidArgument, + HasSubstr("Attempted to refer to module member const FOO"))); + std::vector diags = + adapter.GenerateParseDiagnostics(outer_uri); + ASSERT_EQ(diags.size(), 1); + + // Now we make our correction to inner in our text buffer. + // + // This should cause outer to be re-evaluated, and we should no longer see + // error diagnostics for it. + XLS_ASSERT_OK(adapter.Update(inner_uri, good_inner_contents)); + auto sensitive_set = + adapter.import_sensitivity().GatherAllSensitiveToChangeIn(inner_uri); + ASSERT_EQ(sensitive_set.size(), 2); + EXPECT_THAT(sensitive_set, + testing::UnorderedElementsAre(inner_uri, outer_uri)); + + for (const std::string& sensitive : sensitive_set) { + if (sensitive == inner_uri) { + continue; + } + + XLS_ASSERT_OK(adapter.Update(sensitive, std::nullopt)) + << "due to update of: " << sensitive; + } + + diags = adapter.GenerateParseDiagnostics(outer_uri); + ASSERT_TRUE(diags.empty()); +} + } // namespace } // namespace xls::dslx diff --git a/xls/dslx/run_routines/run_routines.cc b/xls/dslx/run_routines/run_routines.cc index e5a2b91c9d..0144b3d8bc 100644 --- a/xls/dslx/run_routines/run_routines.cc +++ b/xls/dslx/run_routines/run_routines.cc @@ -483,8 +483,9 @@ absl::StatusOr ParseAndProve( const absl::Time start = absl::Now(); TestResultData result(start, /*test_cases=*/{}); - auto import_data = CreateImportData(options.dslx_stdlib_path, - options.dslx_paths, options.warnings); + auto import_data = + CreateImportData(options.dslx_stdlib_path, options.dslx_paths, + options.warnings, std::make_unique()); FileTable& file_table = import_data.file_table(); absl::StatusOr tm_or = ParseAndTypecheck(program, filename, module_name, &import_data); @@ -657,8 +658,9 @@ absl::StatusOr AbstractTestRunner::ParseAndTest( const absl::Time start = absl::Now(); TestResultData result(start, /*test_cases=*/{}); - auto import_data = CreateImportData(options.dslx_stdlib_path, - options.dslx_paths, options.warnings); + auto import_data = + CreateImportData(options.dslx_stdlib_path, options.dslx_paths, + options.warnings, std::make_unique()); FileTable& file_table = import_data.file_table(); absl::StatusOr tm_or = diff --git a/xls/dslx/type_system/typecheck_main.cc b/xls/dslx/type_system/typecheck_main.cc index 11457e3538..196d18efa8 100644 --- a/xls/dslx/type_system/typecheck_main.cc +++ b/xls/dslx/type_system/typecheck_main.cc @@ -63,7 +63,8 @@ absl::Status RealMain(absl::Span dslx_paths, std::optional output_path) { ImportData import_data(CreateImportData( dslx_stdlib_path, - /*additional_search_paths=*/dslx_paths, kDefaultWarningsSet)); + /*additional_search_paths=*/dslx_paths, kDefaultWarningsSet, + std::make_unique())); XLS_ASSIGN_OR_RETURN(std::string input_contents, GetFileContents(input_path)); XLS_ASSIGN_OR_RETURN(std::string module_name, PathToName(input_path.c_str())); absl::StatusOr tm_or = ParseAndTypecheck( diff --git a/xls/dslx/type_system/typecheck_module.cc b/xls/dslx/type_system/typecheck_module.cc index 04ecde0bfc..31c0d78587 100644 --- a/xls/dslx/type_system/typecheck_module.cc +++ b/xls/dslx/type_system/typecheck_module.cc @@ -220,7 +220,7 @@ absl::Status TypecheckModuleMember(const ModuleMember& member, Module* module, XLS_ASSIGN_OR_RETURN( ModuleInfo * imported, DoImport(ctx->typecheck_module(), ImportTokens(import->subject()), - import_data, import->span())); + import_data, import->span(), import_data->vfs())); ctx->type_info()->AddImport(import, &imported->module(), imported->type_info()); } else if (std::holds_alternative(member) || diff --git a/xls/flows/ir_wrapper.h b/xls/flows/ir_wrapper.h index 648c55b9ea..b054c3fa43 100644 --- a/xls/flows/ir_wrapper.h +++ b/xls/flows/ir_wrapper.h @@ -196,10 +196,11 @@ class IrWrapper { private: // Construct this object with a default ImportData. explicit IrWrapper() - : import_data_(dslx::CreateImportData( - xls::kDefaultDslxStdlibPath, - /*additional_search_paths=*/{}, - /*enabled_warnings=*/dslx::kAllWarningsSet)) {} + : import_data_( + dslx::CreateImportData(xls::kDefaultDslxStdlibPath, + /*additional_search_paths=*/{}, + /*enabled_warnings=*/dslx::kAllWarningsSet, + std::make_unique())) {} // Pointers to the each of the DSLX modules explicitly given to this wrapper. // diff --git a/xls/fuzzer/sample_generator.cc b/xls/fuzzer/sample_generator.cc index 3433d70174..d23de18dbd 100644 --- a/xls/fuzzer/sample_generator.cc +++ b/xls/fuzzer/sample_generator.cc @@ -402,7 +402,8 @@ absl::StatusOr GenerateSample( ImportData import_data( dslx::CreateImportData(/*stdlib_path=*/"", /*additional_search_paths=*/{}, - /*enabled_warnings=*/dslx::kAllWarningsSet)); + /*enabled_warnings=*/dslx::kAllWarningsSet, + std::make_unique())); absl::StatusOr tm = ParseAndTypecheck(dslx_text, "sample.x", "sample", &import_data); if (!tm.ok()) { diff --git a/xls/fuzzer/sample_runner.cc b/xls/fuzzer/sample_runner.cc index 6aa3950341..d8e4ba0bd2 100644 --- a/xls/fuzzer/sample_runner.cc +++ b/xls/fuzzer/sample_runner.cc @@ -138,7 +138,8 @@ absl::StatusOr> InterpretDslxFunction( const ArgsBatch& args_batch, const std::filesystem::path& run_dir) { dslx::ImportData import_data = dslx::CreateImportData( GetDefaultDslxStdlibPath(), - /*additional_search_paths=*/{}, dslx::kDefaultWarningsSet); + /*additional_search_paths=*/{}, dslx::kDefaultWarningsSet, + std::make_unique()); XLS_ASSIGN_OR_RETURN( dslx::TypecheckedModule tm, dslx::ParseAndTypecheck(text, "sample.x", "sample", &import_data)); @@ -647,7 +648,8 @@ InterpretDslxProc(std::string_view text, std::string_view top_name, const std::filesystem::path& run_dir) { dslx::ImportData import_data = dslx::CreateImportData( GetDefaultDslxStdlibPath(), - /*additional_search_paths=*/{}, dslx::kDefaultWarningsSet); + /*additional_search_paths=*/{}, dslx::kDefaultWarningsSet, + std::make_unique()); XLS_ASSIGN_OR_RETURN( dslx::TypecheckedModule tm, dslx::ParseAndTypecheck(text, "sample.x", "sample", &import_data)); diff --git a/xls/passes/channel_legalization_pass.cc b/xls/passes/channel_legalization_pass.cc index a294b1b1c3..e49c7fcafc 100644 --- a/xls/passes/channel_legalization_pass.cc +++ b/xls/passes/channel_legalization_pass.cc @@ -284,19 +284,6 @@ class AdapterBuilder { std::vector adapter_instantiation_args_; }; -// Get the token operand number for a given channel op. -absl::StatusOr TokenOperandNumberForChannelOp(Node* node) { - switch (node->op()) { - case Op::kSend: - return Send::kTokenOperand; - case Op::kReceive: - return Receive::kTokenOperand; - default: - return absl::InvalidArgumentError( - absl::StrFormat("Expected channel op, got %s.", node->ToString())); - } -} - struct ChannelSends { Channel* channel; std::vector sends; diff --git a/xls/public/c_api_dslx.cc b/xls/public/c_api_dslx.cc index 4a0e6c7d3c..920102ff46 100644 --- a/xls/public/c_api_dslx.cc +++ b/xls/public/c_api_dslx.cc @@ -68,7 +68,8 @@ struct xls_dslx_import_data* xls_dslx_import_data_create( std::vector cpp_additional_search_paths = xls::ToCpp(additional_search_paths, additional_search_paths_count); xls::dslx::ImportData import_data = CreateImportData( - cpp_stdlib_path, cpp_additional_search_paths, xls::dslx::kAllWarningsSet); + cpp_stdlib_path, cpp_additional_search_paths, xls::dslx::kAllWarningsSet, + std::make_unique()); return reinterpret_cast( new xls::dslx::ImportData{std::move(import_data)}); } diff --git a/xls/public/runtime_build_actions.cc b/xls/public/runtime_build_actions.cc index 6eb10c3ce9..0fec867d45 100644 --- a/xls/public/runtime_build_actions.cc +++ b/xls/public/runtime_build_actions.cc @@ -55,7 +55,7 @@ absl::StatusOr ConvertDslxToIr( << " stdlib_path: " << dslx_stdlib_path; dslx::ImportData import_data(dslx::CreateImportData( std::string(dslx_stdlib_path), additional_search_paths, - dslx::kDefaultWarningsSet)); + dslx::kDefaultWarningsSet, std::make_unique())); XLS_ASSIGN_OR_RETURN( dslx::TypecheckedModule typechecked, dslx::ParseAndTypecheck(dslx, path, module_name, &import_data)); diff --git a/xls/tools/eval_dslx_main.cc b/xls/tools/eval_dslx_main.cc index bf9116a4fb..112a9107f2 100644 --- a/xls/tools/eval_dslx_main.cc +++ b/xls/tools/eval_dslx_main.cc @@ -65,9 +65,9 @@ static absl::Status RealMain( const std::filesystem::path& dslx_path, const std::vector& additional_search_paths, std::string_view entry_fn_name, std::string_view args_text) { - dslx::ImportData import_data( - dslx::CreateImportData(kDefaultDslxStdlibPath, additional_search_paths, - dslx::kDefaultWarningsSet)); + dslx::ImportData import_data(dslx::CreateImportData( + kDefaultDslxStdlibPath, additional_search_paths, + dslx::kDefaultWarningsSet, std::make_unique())); XLS_ASSIGN_OR_RETURN(std::vector args, dslx::ParseArgs(args_text)); diff --git a/xls/tools/eval_ir_main.cc b/xls/tools/eval_ir_main.cc index 108f083eaf..0d52ae6604 100644 --- a/xls/tools/eval_ir_main.cc +++ b/xls/tools/eval_ir_main.cc @@ -550,7 +550,8 @@ absl::StatusOr> ConvertValidator( absl::Span dslx_paths, std::string_view validator_dslx) { dslx::ImportData import_data(dslx::CreateImportData( - std::string(dslx_stdlib_path), dslx_paths, dslx::kDefaultWarningsSet)); + std::string(dslx_stdlib_path), dslx_paths, dslx::kDefaultWarningsSet, + std::make_unique())); XLS_ASSIGN_OR_RETURN(dslx::TypecheckedModule module, dslx::ParseAndTypecheck(validator_dslx, "fake_path", kPackageName, &import_data)); From d7a8513b09515c4d980293235ac66824ae02564c Mon Sep 17 00:00:00 2001 From: "Christopher D. Leary" Date: Sun, 20 Oct 2024 18:34:15 -0700 Subject: [PATCH 2/2] Unbreak repl in contrib. --- xls/dev_tools/repl.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xls/dev_tools/repl.cc b/xls/dev_tools/repl.cc index 373cc9be69..6033a9cffc 100644 --- a/xls/dev_tools/repl.cc +++ b/xls/dev_tools/repl.cc @@ -312,7 +312,8 @@ absl::Status CommandReload() { dslx::ImportData import_data(dslx::CreateImportData( /*dslx_stdlib_path=*/"", /*additional_search_paths=*/{}, - /*enabled_warnings=*/dslx::kDefaultWarningsSet)); + /*enabled_warnings=*/dslx::kDefaultWarningsSet, + std::make_unique())); dslx::FileTable& file_table = import_data.file_table();