diff --git a/clients/vscode-hlasmplugin/CHANGELOG.md b/clients/vscode-hlasmplugin/CHANGELOG.md index 7ed285994..1c4868769 100644 --- a/clients/vscode-hlasmplugin/CHANGELOG.md +++ b/clients/vscode-hlasmplugin/CHANGELOG.md @@ -10,6 +10,7 @@ #### Fixed - Program to processor group mapping precedence - The language server may crash while accessing content of virtual files +- "Diagnostics suppressed" informational message may be incorrectly generated ## [1.9.0](https://github.com/eclipse-che4z/che-che4z-lsp-for-hlasm/compare/1.8.0...1.9.0) (2023-08-03) diff --git a/parser_library/src/workspaces/macro_cache.cpp b/parser_library/src/workspaces/macro_cache.cpp index 05ae75987..bcb540749 100644 --- a/parser_library/src/workspaces/macro_cache.cpp +++ b/parser_library/src/workspaces/macro_cache.cpp @@ -85,36 +85,37 @@ const macro_cache_data* macro_cache::find_cached_data(const macro_cache_key& key return &cached_data; } -bool macro_cache::load_from_cache(const macro_cache_key& key, const analyzing_context& ctx) const +std::optional>> macro_cache::load_from_cache( + const macro_cache_key& key, const analyzing_context& ctx) const { + std::optional>> result; if (auto cached_data = find_cached_data(key)) { + auto& locs = result.emplace(); if (key.data.proc_kind == processing::processing_kind::MACRO) { lsp::macro_info_ptr info = std::get(cached_data->cached_member); if (!info) - return true; // The file for which the analyzer is cached does not contain definition of macro + return result; // The file for which the analyzer is cached does not contain definition of macro ctx.hlasm_ctx->add_macro(info->macro_definition, info->external); ctx.lsp_ctx->add_macro(info, lsp::text_data_view(macro_file_->get_text())); // Add all copy members on which this macro is dependant for (const auto& copy_ptr : info->macro_definition->used_copy_members) { - auto file = file_mngr_->find(copy_ptr->definition_location.resource_loc); + const auto& file = locs.emplace_back(file_mngr_->find(copy_ptr->definition_location.resource_loc)); ctx.hlasm_ctx->add_copy_member(copy_ptr); ctx.lsp_ctx->add_copy(copy_ptr, lsp::text_data_view(file->get_text())); } } else if (key.data.proc_kind == processing::processing_kind::COPY) { - auto copy_member = std::get(cached_data->cached_member); + const auto& copy_member = std::get(cached_data->cached_member); ctx.hlasm_ctx->add_copy_member(copy_member); ctx.lsp_ctx->add_copy(copy_member, lsp::text_data_view(macro_file_->get_text())); } - - return true; } - return false; + return result; } version_stamp macro_cache::get_copy_member_versions(context::macro_def_ptr macro) const diff --git a/parser_library/src/workspaces/macro_cache.h b/parser_library/src/workspaces/macro_cache.h index 559ca83c0..78a97cc4a 100644 --- a/parser_library/src/workspaces/macro_cache.h +++ b/parser_library/src/workspaces/macro_cache.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -96,7 +97,8 @@ class macro_cache final macro_cache(const file_manager& file_mngr, std::shared_ptr macro_file); // Checks whether any dependencies with specified macro cache key (macro context) have changed. If not, loads the // cached macro to the specified context. Returns true, if the macro was loaded. - bool load_from_cache(const macro_cache_key& key, const analyzing_context& ctx) const; + std::optional>> load_from_cache( + const macro_cache_key& key, const analyzing_context& ctx) const; void save_macro(const macro_cache_key& key, const analyzer& analyzer); private: diff --git a/parser_library/src/workspaces/workspace.cpp b/parser_library/src/workspaces/workspace.cpp index 803a54c31..8d90dfc19 100644 --- a/parser_library/src/workspaces/workspace.cpp +++ b/parser_library/src/workspaces/workspace.cpp @@ -190,8 +190,17 @@ struct workspace_parse_lib_provider final : public parse_lib_provider auto& mc = get_cache(url, file); - if (mc.load_from_cache(cache_key, ctx)) + if (auto files = mc.load_from_cache(cache_key, ctx); files.has_value()) + { + for (const auto& f : files.value()) + { + // carry-over nested copy dependencies + current_file_map.try_emplace(f->get_location(), f); + (void)get_cache(f->get_location(), f); + } + co_return true; + } const bool collect_hl = file->get_lsp_editing() || macro_pfc.m_last_opencode_analyzer_with_lsp || macro_pfc.m_last_macro_analyzer_with_lsp || ctx.hlasm_ctx->processing_stack().parent().empty(); diff --git a/parser_library/test/workspace/macro_cache_test.cpp b/parser_library/test/workspace/macro_cache_test.cpp index 2d3549a3e..238e63879 100644 --- a/parser_library/test/workspace/macro_cache_test.cpp +++ b/parser_library/test/workspace/macro_cache_test.cpp @@ -124,7 +124,7 @@ TEST(macro_cache_test, copy_from_macro) // try recalling the cached results analyzing_context new_ctx = create_analyzing_context(opencode_file_name, ids); - EXPECT_TRUE(macro_c.load_from_cache(macro_key, new_ctx)); + EXPECT_EQ(macro_c.load_from_cache(macro_key, new_ctx), std::vector { copy_file }); EXPECT_NE(new_ctx.hlasm_ctx->get_macro_definition(macro_id), nullptr); EXPECT_NE(new_ctx.lsp_ctx->get_macro_info(macro_id), nullptr); EXPECT_NE(new_ctx.hlasm_ctx->get_copy_member(copy_id), nullptr); diff --git a/parser_library/test/workspace/workspace_test.cpp b/parser_library/test/workspace/workspace_test.cpp index b2f50b027..5f20c296c 100644 --- a/parser_library/test/workspace/workspace_test.cpp +++ b/parser_library/test/workspace/workspace_test.cpp @@ -187,6 +187,10 @@ std::string pgmconf_file = R"({ { "program": "source3", "pgroup": "P1" + }, + { + "program": "source4", + "pgroup": "P1" } ] })"; @@ -226,12 +230,24 @@ std::string correct_macro_file = R"( MACRO MEND )"; +std::string cordep_macro_file = R"( MACRO + CORDEP + COPY DEP + MEND +)"; + +std::string dep_macro_file = R"( + MNOTE 'DEP' +)"; + std::string source_using_macro_file = R"( ERROR label )"; std::string source_using_macro_file_no_error = R"( CORRECT)"; +std::string source_using_macro_with_dep = R"( CORDEP)"; + const std::string hlasmplugin_folder = ".hlasmplugin"; const resource_location empty_loc = resource_location(""); @@ -241,8 +257,11 @@ const resource_location pgm_conf_loc(hlasmplugin_folder + "/pgm_conf.json"); const resource_location source1_loc("source1"); const resource_location source2_loc("source2"); const resource_location source3_loc("source3"); +const resource_location source4_loc("source4"); const resource_location faulty_macro_loc("lib/ERROR"); const resource_location correct_macro_loc("lib/CORRECT"); +const resource_location cordep_macro_loc("lib/CORDEP"); +const resource_location dep_macro_loc("lib/DEP"); } // namespace class file_manager_extended : public file_manager_impl, public external_file_reader @@ -253,8 +272,11 @@ class file_manager_extended : public file_manager_impl, public external_file_rea { source1_loc, source_using_macro_file }, { source2_loc, source_using_macro_file }, { source3_loc, source_using_macro_file_no_error }, + { source4_loc, source_using_macro_with_dep }, { faulty_macro_loc, faulty_macro_file }, { correct_macro_loc, correct_macro_file }, + { cordep_macro_loc, cordep_macro_file }, + { dep_macro_loc, dep_macro_file }, }; public: @@ -273,12 +295,16 @@ class file_manager_extended : public file_manager_impl, public external_file_rea { { "ERROR", faulty_macro_loc }, { "CORRECT", correct_macro_loc }, + { "CORDEP", cordep_macro_loc }, + { "DEP", dep_macro_loc }, }, hlasm_plugin::utils::path::list_directory_rc::done, }); return hlasm_plugin::utils::value_task::from_value({ { { "ERROR", faulty_macro_loc }, + { "CORDEP", cordep_macro_loc }, + { "DEP", dep_macro_loc }, }, hlasm_plugin::utils::path::list_directory_rc::done, }); @@ -649,3 +675,26 @@ TEST_F(workspace_test, use_external_library) parse_all_files(ws); EXPECT_EQ(collect_and_get_diags_size(ws), 0); } + +TEST_F(workspace_test, track_nested_dependencies) +{ + file_manager_extended file_manager; + config.diag_supress_limit = 0; + workspace ws(empty_loc, "workspace_name", file_manager, config, global_settings); + + ws.open().run(); + run_if_valid(ws.did_open_file(source4_loc)); + parse_all_files(ws); + EXPECT_EQ(collect_and_get_diags_size(ws), (size_t)1); + EXPECT_TRUE(matches_message_codes(diags(), { "MNOTE" })); + + run_if_valid(ws.did_open_file(dep_macro_loc, file_content_state::changed_lsp)); + parse_all_files(ws); + EXPECT_EQ(collect_and_get_diags_size(ws), (size_t)1); + EXPECT_TRUE(matches_message_codes(diags(), { "MNOTE" })); + + run_if_valid(ws.did_change_file(source4_loc, file_content_state::changed_content)); + parse_all_files(ws); + EXPECT_EQ(collect_and_get_diags_size(ws), (size_t)1); + EXPECT_TRUE(matches_message_codes(diags(), { "MNOTE" })); // SUP should not appear +}