diff --git a/clients/vscode-hlasmplugin/CHANGELOG.md b/clients/vscode-hlasmplugin/CHANGELOG.md index c25bdef37..ff51573ce 100644 --- a/clients/vscode-hlasmplugin/CHANGELOG.md +++ b/clients/vscode-hlasmplugin/CHANGELOG.md @@ -9,6 +9,7 @@ - Instruction set versioning support - Basic GOFF, XOBJECT and SYSOPT_XOBJECT support - MNOTE support +- Assembler options can be specified in pgm_conf.json to override values from proc_grps.json #### Fixed - Fixed an issue preventing correct N' attribute evaluation of empty subscript arrays diff --git a/clients/vscode-hlasmplugin/README.md b/clients/vscode-hlasmplugin/README.md index a661edd92..a46e1082a 100644 --- a/clients/vscode-hlasmplugin/README.md +++ b/clients/vscode-hlasmplugin/README.md @@ -171,6 +171,22 @@ The program name in `pgm_conf.json` can be wildcarded, as in the following examp ``` In this example, GROUP1 is used for all open code programs. +Assmebler options defined by the processor group can be overriden in the `pgm_conf.json` file as shown in the following example: +``` +{ + "pgms": [ + { + "program": "source_code", + "pgroup": "GROUP1", + "asm_options": + { + "SYSPARM": "SYSPARM override value" + } + } + ] +} +``` + ### File Extensions The `alwaysRecognize` option in `pgm_conf.json` has been deprecated in favour of the standard VSCode user and workspace level setting `file.associations`. diff --git a/clients/vscode-hlasmplugin/package.json b/clients/vscode-hlasmplugin/package.json index dac5c4278..ede7925fd 100644 --- a/clients/vscode-hlasmplugin/package.json +++ b/clients/vscode-hlasmplugin/package.json @@ -76,11 +76,11 @@ "jsonValidation": [ { "fileMatch": "pgm_conf.json", - "url": "./pgm_conf_schema" + "url": "./schema/pgm_conf.json" }, { "fileMatch": "proc_grps.json", - "url": "./proc_grps_schema" + "url": "./schema/proc_grps.json" } ], "breakpoints": [ diff --git a/clients/vscode-hlasmplugin/schema/asm_options.json b/clients/vscode-hlasmplugin/schema/asm_options.json new file mode 100644 index 000000000..79c8e735b --- /dev/null +++ b/clients/vscode-hlasmplugin/schema/asm_options.json @@ -0,0 +1,56 @@ +{ + "type": "object", + "description": "List of assembler options", + "properties": { + "GOFF": { + "type": "boolean", + "description": "Produces Generalized Object File format dataset." + }, + "OPTABLE": { + "type": "string", + "description": "Specifies the instruction set to use.", + "enum": [ + "UNI", + "DOS", + "370", + "XA", + "ESA", + "ZOP", + "ZS1", + "YOP", + "ZS2", + "Z9", + "ZS3", + "Z10", + "ZS4", + "Z11", + "ZS5", + "Z12", + "ZS6", + "Z13", + "ZS7", + "Z14", + "ZS8", + "Z15", + "ZS9" + ] + }, + "SYSPARM": { + "type": "string", + "description": "Specifies the character string the assembler assigns to the &SYSPARM system variable symbol.", + "maxLength": 255 + }, + "PROFILE": { + "type": "string", + "description": "Profile Member to be copied into the source program." + }, + "SYSTEM_ID": { + "type": "string", + "description": "Provides the value for the SYSTEM_ID system variable. Defaults to 'z/OS 02.04.00' when omitted." + }, + "XOBJECT": { + "type": "boolean", + "description": "Synonym for the GOFF option." + } + } +} diff --git a/clients/vscode-hlasmplugin/pgm_conf_schema b/clients/vscode-hlasmplugin/schema/pgm_conf.json similarity index 95% rename from clients/vscode-hlasmplugin/pgm_conf_schema rename to clients/vscode-hlasmplugin/schema/pgm_conf.json index 2d5225d12..31e00e8d9 100644 --- a/clients/vscode-hlasmplugin/pgm_conf_schema +++ b/clients/vscode-hlasmplugin/schema/pgm_conf.json @@ -14,6 +14,9 @@ "pgroup": { "type": "string", "description": "Name of processor group as defined in proc_grps.json" + }, + "asm_options": { + "$ref": "asm_options.json" } }, "required": [ diff --git a/clients/vscode-hlasmplugin/proc_grps_schema b/clients/vscode-hlasmplugin/schema/proc_grps.json similarity index 68% rename from clients/vscode-hlasmplugin/proc_grps_schema rename to clients/vscode-hlasmplugin/schema/proc_grps.json index 353c2f773..424990404 100644 --- a/clients/vscode-hlasmplugin/proc_grps_schema +++ b/clients/vscode-hlasmplugin/schema/proc_grps.json @@ -46,60 +46,7 @@ } }, "asm_options": { - "type": "object", - "description": "List of assembler options", - "properties": { - "GOFF": { - "type": "boolean", - "description": "Produces Generalized Object File format dataset." - }, - "OPTABLE": { - "type": "string", - "description": "Specifies the instruction set to use.", - "enum": [ - "UNI", - "DOS", - "370", - "XA", - "ESA", - "ZOP", - "ZS1", - "YOP", - "ZS2", - "Z9", - "ZS3", - "Z10", - "ZS4", - "Z11", - "ZS5", - "Z12", - "ZS6", - "Z13", - "ZS7", - "Z14", - "ZS8", - "Z15", - "ZS9" - ] - }, - "SYSPARM": { - "type": "string", - "description": "Specifies the character string the assembler assigns to the &SYSPARM system variable symbol.", - "maxLength": 255 - }, - "PROFILE": { - "type": "string", - "description": "Profile Member to be copied into the source program." - }, - "SYSTEM_ID": { - "type": "string", - "description": "Provides the value for the SYSTEM_ID system variable. Defaults to 'z/OS 02.04.00' when omitted." - }, - "XOBJECT": { - "type": "boolean", - "description": "Synonym for the GOFF option." - } - } + "$ref": "asm_options.json" }, "preprocessor": { "description": "Defines optional preprocessor pass for open code.", diff --git a/parser_library/src/compiler_options.h b/parser_library/src/compiler_options.h index 9ac3677a7..155f1fc4b 100644 --- a/parser_library/src/compiler_options.h +++ b/parser_library/src/compiler_options.h @@ -40,6 +40,8 @@ struct asm_option bool sysopt_xobject = sysopt_xobject_default; long long statement_count_limit = 10'000'000; + + bool operator==(const asm_option&) const = default; }; } // namespace hlasm_plugin::parser_library #endif diff --git a/parser_library/src/config/CMakeLists.txt b/parser_library/src/config/CMakeLists.txt index 36ecf6ef6..ac1edf16d 100644 --- a/parser_library/src/config/CMakeLists.txt +++ b/parser_library/src/config/CMakeLists.txt @@ -11,6 +11,8 @@ # Broadcom, Inc. - initial API and implementation target_sources(parser_library PRIVATE + assembler_options.cpp + assembler_options.h pgm_conf.cpp pgm_conf.h proc_grps.cpp diff --git a/parser_library/src/config/assembler_options.cpp b/parser_library/src/config/assembler_options.cpp new file mode 100644 index 000000000..b9e7f404f --- /dev/null +++ b/parser_library/src/config/assembler_options.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2022 Broadcom. + * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + */ + +#include "assembler_options.h" + +#include "compiler_options.h" +#include "nlohmann/json.hpp" + +namespace hlasm_plugin::parser_library::config { + + +namespace { +bool optable_valid(std::string_view optable) noexcept +{ +#ifdef __cpp_lib_ranges + return optable.size() == 0 + || std::ranges::any_of(instr_set_version_equivalents, [optable](auto item) { return optable == item.first; }); +#else + return optable.size() == 0 + || std::any_of(std::begin(instr_set_version_equivalents), + std::end(instr_set_version_equivalents), + [optable](auto item) { return optable == item.first; }); +#endif +} +} // namespace + +bool assembler_options::valid() const noexcept +{ + if (sysparm.has_value() && sysparm.value().size() >= 256) + return false; + if (optable.has_value() && !optable_valid(optable.value())) + return false; + return true; +} + +namespace { +std::optional find_instruction_set(std::string_view optable) +{ +#ifdef __cpp_lib_ranges + auto it = std::ranges::lower_bound( + instr_set_version_equivalents, optable, {}, [](const auto& instr) { return instr.first; }); +#else + auto it = std::lower_bound(std::begin(instr_set_version_equivalents), + std::end(instr_set_version_equivalents), + optable, + [](const auto& l, const auto& r) { return l.first < r; }); +#endif + + if (it == std::end(instr_set_version_equivalents) || it->first != optable) + return std::nullopt; + + return it->second; +} +} // namespace + +void assembler_options::apply(asm_option& opts) const +{ + if (sysparm.has_value()) + opts.sysparm = sysparm.value(); + if (profile.has_value()) + opts.profile = profile.value(); + if (optable.has_value()) + { + if (auto translated = find_instruction_set(optable.value()); translated.has_value()) + { + opts.instr_set = translated.value(); + } + } + if (system_id.has_value()) + opts.system_id = system_id.value(); + if (goff.has_value()) + opts.sysopt_xobject = goff.value(); +} + +bool assembler_options::has_value() const noexcept +{ + return sysparm.has_value() || profile.has_value() || optable.has_value() || system_id.has_value() + || goff.has_value(); +} + +template +void optional_to_json(nlohmann::json& j, std::string name, const std::optional& o) +{ + if (o.has_value()) + j[name] = o.value(); +} + +template +void optional_from_json(const nlohmann::json& j, std::string_view name, std::optional& o) +{ + if (auto it = j.find(name); it != j.end()) + o = it->get(); + else + o.reset(); +} + +void to_json(nlohmann::json& j, const assembler_options& p) +{ + j = nlohmann::json::object(); + optional_to_json(j, "GOFF", p.goff); // GOFF and XOBJECTS are synonyms + optional_to_json(j, "OPTABLE", p.optable); + optional_to_json(j, "PROFILE", p.profile); + optional_to_json(j, "SYSPARM", p.sysparm); + optional_to_json(j, "SYSTEM_ID", p.system_id); +} + +namespace { +std::optional get_goff_from_json(const nlohmann::json& j) +{ + bool present = false; + bool goff = false; + bool xobject = false; + + if (auto it = j.find("GOFF"); it != j.end()) + { + it->get_to(goff); + present = true; + } + + if (auto it = j.find("XOBJECT"); it != j.end()) + { + it->get_to(xobject); + present = true; + } + if (present) + return goff || xobject; // GOFF and XOBJECTS are synonyms + else + return std::nullopt; +} +} // namespace + +void from_json(const nlohmann::json& j, assembler_options& p) +{ + if (!j.is_object()) + throw nlohmann::json::other_error::create(501, "asm_options must be an object."); + + p.goff = get_goff_from_json(j); + optional_from_json(j, "OPTABLE", p.optable); + optional_from_json(j, "PROFILE", p.profile); + optional_from_json(j, "SYSPARM", p.sysparm); + optional_from_json(j, "SYSTEM_ID", p.system_id); +} +} // namespace hlasm_plugin::parser_library::config diff --git a/parser_library/src/config/assembler_options.h b/parser_library/src/config/assembler_options.h new file mode 100644 index 000000000..e653b9209 --- /dev/null +++ b/parser_library/src/config/assembler_options.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022 Broadcom. + * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + */ + +#ifndef HLASMPARSER_PARSERLIBRARY_CONFIG_ASSEMBLER_OPTIONS_H +#define HLASMPARSER_PARSERLIBRARY_CONFIG_ASSEMBLER_OPTIONS_H + +#include +#include + +#include "nlohmann/json_fwd.hpp" + +namespace hlasm_plugin::parser_library { +struct asm_option; +} // namespace hlasm_plugin::parser_library + +namespace hlasm_plugin::parser_library::config { + +struct assembler_options +{ + std::optional sysparm; + std::optional profile; + std::optional optable; + std::optional system_id; + std::optional goff; + + bool operator==(const assembler_options&) const = default; + bool valid() const noexcept; + void apply(asm_option& opts) const; + bool has_value() const noexcept; +}; +void to_json(nlohmann::json& j, const assembler_options& p); +void from_json(const nlohmann::json& j, assembler_options& p); +} // namespace hlasm_plugin::parser_library::config +#endif diff --git a/parser_library/src/config/pgm_conf.cpp b/parser_library/src/config/pgm_conf.cpp index bf5faec12..7632d6f16 100644 --- a/parser_library/src/config/pgm_conf.cpp +++ b/parser_library/src/config/pgm_conf.cpp @@ -21,12 +21,16 @@ namespace hlasm_plugin::parser_library::config { void to_json(nlohmann::json& j, const program_mapping& p) { j = nlohmann::json { { "program", p.program }, { "pgroup", p.pgroup } }; + if (p.opts.has_value()) + j["asm_options"] = p.opts; } void from_json(const nlohmann::json& j, program_mapping& p) { j.at("program").get_to(p.program); j.at("pgroup").get_to(p.pgroup); + if (auto it = j.find("asm_options"); it != j.end()) + it->get_to(p.opts); } void to_json(nlohmann::json& j, const pgm_conf& p) diff --git a/parser_library/src/config/pgm_conf.h b/parser_library/src/config/pgm_conf.h index d9ab7006c..393caaf5d 100644 --- a/parser_library/src/config/pgm_conf.h +++ b/parser_library/src/config/pgm_conf.h @@ -19,6 +19,7 @@ #include #include +#include "assembler_options.h" #include "nlohmann/json_fwd.hpp" namespace hlasm_plugin::parser_library::config { @@ -27,6 +28,7 @@ struct program_mapping { std::string program; std::string pgroup; + assembler_options opts; }; void to_json(nlohmann::json& j, const program_mapping& p); void from_json(const nlohmann::json& j, program_mapping& p); diff --git a/parser_library/src/config/proc_grps.cpp b/parser_library/src/config/proc_grps.cpp index ec8d877c8..c43fb39bc 100644 --- a/parser_library/src/config/proc_grps.cpp +++ b/parser_library/src/config/proc_grps.cpp @@ -14,6 +14,7 @@ #include "proc_grps.h" +#include "assembler_options.h" #include "instruction_set_version.h" #include "nlohmann/json.hpp" @@ -41,57 +42,6 @@ void from_json(const nlohmann::json& j, library& p) throw nlohmann::json::other_error::create(501, "Unexpected JSON type."); } -void to_json(nlohmann::json& j, const assembler_options& p) -{ - j = nlohmann::json::object(); - if (p.goff) - { - j["GOFF"] = p.goff; // GOFF and XOBJECTS are synonyms - } - if (p.optable.size()) - j["OPTABLE"] = p.optable; - if (p.profile.size()) - j["PROFILE"] = p.profile; - if (p.sysparm.size()) - j["SYSPARM"] = p.sysparm; - if (p.system_id.size()) - j["SYSTEM_ID"] = p.system_id; -} - -namespace { -bool get_goff_from_json(const nlohmann::json& j) -{ - bool goff = false; - bool xobject = false; - - if (auto it = j.find("GOFF"); it != j.end()) - it->get_to(goff); - - if (auto it = j.find("XOBJECT"); it != j.end()) - { - it->get_to(xobject); - } - - return goff || xobject; // GOFF and XOBJECTS are synonyms -} -} // namespace - -void from_json(const nlohmann::json& j, assembler_options& p) -{ - if (!j.is_object()) - throw nlohmann::json::other_error::create(501, "asm_options must be an object."); - - p.goff = get_goff_from_json(j); - if (auto it = j.find("OPTABLE"); it != j.end()) - it->get_to(p.optable); - if (auto it = j.find("PROFILE"); it != j.end()) - it->get_to(p.profile); - if (auto it = j.find("SYSPARM"); it != j.end()) - it->get_to(p.sysparm); - if (auto it = j.find("SYSTEM_ID"); it != j.end()) - it->get_to(p.system_id); -} - void to_json(nlohmann::json& j, const db2_preprocessor& v) { static const db2_preprocessor default_config; @@ -244,23 +194,6 @@ void from_json(const nlohmann::json& j, proc_grps& p) it->get_to(p.macro_extensions); } -namespace { -bool optable_valid(std::string_view optable) noexcept -{ -#ifdef __cpp_lib_ranges - return optable.size() == 0 - || std::ranges::any_of(instr_set_version_equivalents, [optable](auto item) { return optable == item.first; }); -#else - return optable.size() == 0 - || std::any_of(std::begin(instr_set_version_equivalents), - std::end(instr_set_version_equivalents), - [optable](auto item) { return optable == item.first; }); -#endif -} -} // namespace - -bool assembler_options::valid() const noexcept { return sysparm.size() < 256 && optable_valid(optable); } - namespace { struct preprocessor_validator { diff --git a/parser_library/src/config/proc_grps.h b/parser_library/src/config/proc_grps.h index 7458a5211..4cad807db 100644 --- a/parser_library/src/config/proc_grps.h +++ b/parser_library/src/config/proc_grps.h @@ -20,6 +20,7 @@ #include #include +#include "assembler_options.h" #include "nlohmann/json_fwd.hpp" namespace hlasm_plugin::parser_library::config { @@ -33,19 +34,6 @@ struct library void to_json(nlohmann::json& j, const library& p); void from_json(const nlohmann::json& j, library& p); -struct assembler_options -{ - std::string sysparm; - std::string profile; - std::string optable; - std::string system_id; - bool goff = false; - - bool valid() const noexcept; -}; -void to_json(nlohmann::json& j, const assembler_options& p); -void from_json(const nlohmann::json& j, assembler_options& p); - struct db2_preprocessor { std::string version; diff --git a/parser_library/src/diagnostic.cpp b/parser_library/src/diagnostic.cpp index bbe946269..8817a6617 100644 --- a/parser_library/src/diagnostic.cpp +++ b/parser_library/src/diagnostic.cpp @@ -2457,13 +2457,13 @@ diagnostic_s diagnostic_s::error_W0004(std::string_view file_name, std::string_v diagnostic_tag::none); } -diagnostic_s diagnostic_s::error_W0005(std::string_view file_name, std::string_view proc_group) +diagnostic_s diagnostic_s::error_W0005(std::string_view file_name, std::string_view name, std::string_view type) { return diagnostic_s(std::string(file_name), {}, diagnostic_severity::warning, "W0005", - concat("The processor group '", proc_group, "' from '", file_name, "' defines invalid assembler options."), + concat("The ", type, " '", name, "' from '", file_name, "' defines invalid assembler options."), {}, diagnostic_tag::none); } @@ -2479,21 +2479,6 @@ diagnostic_s diagnostic_s::error_W0006(std::string_view file_name, std::string_v diagnostic_tag::none); } -diagnostic_s diagnostic_s::error_W0007(std::string_view file_name, std::string_view proc_group) -{ - return diagnostic_s(std::string(file_name), - {}, - diagnostic_severity::warning, - "W0007", - concat("The processor group '", - proc_group, - "' from '", - file_name, - "' refers to invalid OPTABLE value. Using value UNI as default."), - {}, - diagnostic_tag::none); -} - diagnostic_s diagnostic_s::error_L0001(std::string_view path) { return diagnostic_s(std::string(path), {}, "L0001", concat("Unable to load library: ", path, ".")); diff --git a/parser_library/src/diagnostic.h b/parser_library/src/diagnostic.h index 7504066fe..60ffb6d8f 100644 --- a/parser_library/src/diagnostic.h +++ b/parser_library/src/diagnostic.h @@ -825,12 +825,10 @@ class diagnostic_s static diagnostic_s error_W0004(std::string_view file_name, std::string_view ws_name); - static diagnostic_s error_W0005(std::string_view file_name, std::string_view proc_group); + static diagnostic_s error_W0005(std::string_view file_name, std::string_view name, std::string_view type); static diagnostic_s error_W0006(std::string_view file_name, std::string_view proc_group); - static diagnostic_s error_W0007(std::string_view file_name, std::string_view proc_group); - /* E01x - wrong format - E010 - unknown name diff --git a/parser_library/src/workspaces/processor_group.cpp b/parser_library/src/workspaces/processor_group.cpp index 5f2be7f9f..1a98bb416 100644 --- a/parser_library/src/workspaces/processor_group.cpp +++ b/parser_library/src/workspaces/processor_group.cpp @@ -14,8 +14,6 @@ #include "processor_group.h" -#include "config/proc_grps.h" - namespace hlasm_plugin::parser_library::workspaces { namespace { @@ -33,47 +31,14 @@ struct translate_pp_options }; } // namespace -processor_group::processor_group(const std::string& pg_name, - std::string_view pg_file_name, - const config::assembler_options& asm_options, - const config::preprocessor_options& pp) +processor_group::processor_group( + const std::string& pg_name, const config::assembler_options& asm_options, const config::preprocessor_options& pp) : m_pg_name(pg_name) - , m_asm_opts(translate_assembler_options(asm_options, pg_file_name)) + , m_asm_opts(asm_options) , m_prep_opts(std::visit(translate_pp_options {}, pp.options)) {} -instruction_set_version processor_group::find_instruction_set( - std::string_view optable, std::string_view pg_file_name) const -{ -#ifdef __cpp_lib_ranges - auto it = std::ranges::lower_bound( - instr_set_version_equivalents, optable, {}, [](const auto& instr) { return instr.first; }); -#else - auto it = std::lower_bound(std::begin(instr_set_version_equivalents), - std::end(instr_set_version_equivalents), - optable, - [](const auto& l, const auto& r) { return l.first < r; }); -#endif - - if (it == std::end(instr_set_version_equivalents) || it->first != optable) - { - add_diagnostic(diagnostic_s::error_W0007(pg_file_name, m_pg_name)); - return asm_option::instr_set_default; - } - - return it->second; -} - -asm_option processor_group::translate_assembler_options( - const config::assembler_options& asm_options, std::string_view pg_file_name) const -{ - return asm_option { .sysparm = asm_options.sysparm, - .profile = asm_options.profile, - .instr_set = asm_options.optable.empty() ? asm_option::instr_set_default - : find_instruction_set(asm_options.optable, pg_file_name), - .system_id = asm_options.system_id.empty() ? asm_option::system_id_default : asm_options.system_id, - .sysopt_xobject = asm_options.goff }; -} +void processor_group::update_asm_options(asm_option& opts) const { m_asm_opts.apply(opts); } void processor_group::collect_diags() const { diff --git a/parser_library/src/workspaces/processor_group.h b/parser_library/src/workspaces/processor_group.h index e961252be..5e232d153 100644 --- a/parser_library/src/workspaces/processor_group.h +++ b/parser_library/src/workspaces/processor_group.h @@ -15,7 +15,7 @@ #ifndef HLASMPLUGIN_PARSERLIBRARY_PROCESSOR_GROUP_H #define HLASMPLUGIN_PARSERLIBRARY_PROCESSOR_GROUP_H -#include "compiler_options.h" +#include "config/proc_grps.h" #include "diagnosable_impl.h" #include "file_manager.h" #include "library.h" @@ -33,7 +33,6 @@ class processor_group : public diagnosable_impl { public: processor_group(const std::string& pg_name, - std::string_view pg_file_name, const config::assembler_options& asm_options, const config::preprocessor_options& pp); @@ -45,19 +44,15 @@ class processor_group : public diagnosable_impl const std::vector>& libraries() const { return m_libs; } - const asm_option& asm_options() const { return m_asm_opts; } + void update_asm_options(asm_option& opts) const; const preprocessor_options& preprocessor() const { return m_prep_opts; } private: std::vector> m_libs; std::string m_pg_name; - asm_option m_asm_opts; + config::assembler_options m_asm_opts; preprocessor_options m_prep_opts; - - instruction_set_version find_instruction_set(std::string_view optable, std::string_view pg_file_name) const; - asm_option translate_assembler_options( - const config::assembler_options& asm_options, std::string_view pg_file_name) const; }; } // namespace hlasm_plugin::parser_library::workspaces #endif // !HLASMPLUGIN_PARSERLIBRARY_PROCESSOR_GROUP_H diff --git a/parser_library/src/workspaces/workspace.cpp b/parser_library/src/workspaces/workspace.cpp index 03db9c9ca..05821eb01 100644 --- a/parser_library/src/workspaces/workspace.cpp +++ b/parser_library/src/workspaces/workspace.cpp @@ -44,7 +44,7 @@ workspace::workspace(const ws_uri& uri, , uri_(uri) , file_manager_(file_manager) , fm_vfm_(file_manager_) - , implicit_proc_grp("pg_implicit", "", {}, {}) + , implicit_proc_grp("pg_implicit", {}, {}) , ws_path_(uri) , global_config_(global_config) { @@ -130,6 +130,18 @@ void workspace::show_message(const std::string& message) lib_config workspace::get_config() { return local_config_.fill_missing_settings(global_config_); } const processor_group& workspace::get_proc_grp_by_program(const std::string& filename) const +{ + const auto* pgm = get_program(filename); + if (pgm) + return proc_grps_.at(pgm->pgroup); + return implicit_proc_grp; +} +const processor_group& workspace::get_proc_grp_by_program(const program& pgm) const +{ + return proc_grps_.at(pgm.pgroup); +} + +const program* workspace::get_program(const std::string& filename) const { assert(opened_); @@ -138,14 +150,14 @@ const processor_group& workspace::get_proc_grp_by_program(const std::string& fil // direct match auto program = exact_pgm_conf_.find(file); if (program != exact_pgm_conf_.cend()) - return proc_grps_.at(program->second.pgroup); + return &program->second; for (const auto& pgm : regex_pgm_conf_) { if (std::regex_match(file, pgm.second)) - return proc_grps_.at(pgm.first.pgroup); + return &pgm.first; } - return implicit_proc_grp; + return nullptr; } const ws_uri& workspace::uri() { return uri_; } @@ -553,7 +565,7 @@ bool workspace::load_and_process_config() // process processor groups for (auto& pg : proc_groups.pgroups) { - processor_group prc_grp(pg.name, proc_grps_file->get_file_name(), pg.asm_options, pg.preprocessor); + processor_group prc_grp(pg.name, pg.asm_options, pg.preprocessor); for (const auto& lib : pg.libs) { @@ -599,9 +611,9 @@ bool workspace::load_and_process_config() std::replace(pgm_name.begin(), pgm_name.end(), '/', '\\'); if (!is_wildcard(pgm_name)) - exact_pgm_conf_.emplace(pgm_name, program { pgm_name, pgm.pgroup }); + exact_pgm_conf_.emplace(pgm_name, program { pgm_name, pgm.pgroup, pgm.opts }); else - regex_pgm_conf_.push_back({ program { pgm_name, pgm.pgroup }, wildcard2regex(pgm_name) }); + regex_pgm_conf_.push_back({ program { pgm_name, pgm.pgroup, pgm.opts }, wildcard2regex(pgm_name) }); } else { @@ -629,7 +641,8 @@ bool workspace::load_config( for (const auto& pg : proc_groups.pgroups) { if (!pg.asm_options.valid()) - config_diags_.push_back(diagnostic_s::error_W0005(proc_grps_file->get_file_name(), pg.name)); + config_diags_.push_back( + diagnostic_s::error_W0005(proc_grps_file->get_file_name(), pg.name, "processor group")); if (!pg.preprocessor.valid()) config_diags_.push_back(diagnostic_s::error_W0006(proc_grps_file->get_file_name(), pg.name)); } @@ -650,6 +663,12 @@ bool workspace::load_config( try { nlohmann::json::parse(pgm_conf_file->get_text()).get_to(pgm_config); + for (const auto& pgm : pgm_config.pgms) + { + if (!pgm.opts.valid()) + config_diags_.push_back( + diagnostic_s::error_W0005(pgm_conf_file->get_file_name(), pgm.program, "program")); + } exact_pgm_conf_.clear(); regex_pgm_conf_.clear(); } @@ -764,9 +783,20 @@ std::optional workspace::get_library( asm_option workspace::get_asm_options(const std::string& file_name) const { - auto& proc_grp = get_proc_grp_by_program(file_name); + asm_option result; + + auto pgm = get_program(file_name); + if (pgm) + { + get_proc_grp_by_program(*pgm).update_asm_options(result); + pgm->asm_opts.apply(result); + } + else + { + implicit_proc_grp.update_asm_options(result); + } - return proc_grp.asm_options(); + return result; } preprocessor_options workspace::get_preprocessor_options(const std::string& file_name) const diff --git a/parser_library/src/workspaces/workspace.h b/parser_library/src/workspaces/workspace.h index 1966839fc..d8357b1b7 100644 --- a/parser_library/src/workspaces/workspace.h +++ b/parser_library/src/workspaces/workspace.h @@ -35,7 +35,6 @@ #include "processor.h" #include "processor_group.h" - namespace hlasm_plugin::parser_library::workspaces { using ws_uri = std::string; @@ -48,13 +47,15 @@ struct library_local_options; // information that a program uses certain processor group struct program { - program(program_id prog_id, proc_grp_id pgroup) - : prog_id(prog_id) - , pgroup(pgroup) + program(program_id prog_id, proc_grp_id pgroup, config::assembler_options asm_opts) + : prog_id(std::move(prog_id)) + , pgroup(std::move(pgroup)) + , asm_opts(std::move(asm_opts)) {} program_id prog_id; proc_grp_id pgroup; + config::assembler_options asm_opts; }; @@ -88,6 +89,8 @@ class workspace : public diagnosable_impl, public parse_lib_provider, public lsp void add_proc_grp(processor_group pg); const processor_group& get_proc_grp(const proc_grp_id& proc_grp) const; const processor_group& get_proc_grp_by_program(const std::string& program) const; + const processor_group& get_proc_grp_by_program(const program& program) const; + const program* get_program(const std::string& filename) const; workspace_file_info parse_file(const std::string& file_uri); void refresh_libraries(); diff --git a/parser_library/test/config/CMakeLists.txt b/parser_library/test/config/CMakeLists.txt index 8784c3197..80c11dd46 100644 --- a/parser_library/test/config/CMakeLists.txt +++ b/parser_library/test/config/CMakeLists.txt @@ -11,6 +11,7 @@ # Broadcom, Inc. - initial API and implementation target_sources(library_test PRIVATE + assembler_options_test.cpp pgm_conf_test.cpp proc_grps_test.cpp system_id_test.cpp diff --git a/parser_library/test/config/assembler_options_test.cpp b/parser_library/test/config/assembler_options_test.cpp new file mode 100644 index 000000000..f965fc5b1 --- /dev/null +++ b/parser_library/test/config/assembler_options_test.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2022 Broadcom. + * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Broadcom, Inc. - initial API and implementation + */ + +#include + +#include "gtest/gtest.h" + +#include "compiler_options.h" +#include "config/assembler_options.h" +#include "nlohmann/json.hpp" + +using namespace hlasm_plugin::parser_library; +using namespace hlasm_plugin::parser_library::config; + +TEST(assembler_options, read) +{ + const auto cases = { + std::make_pair(R"({})"_json, assembler_options {}), + std::make_pair(R"({"PROFILE":"MAC"})"_json, assembler_options { .profile = "MAC" }), + std::make_pair(R"({"SYSPARM":"TESTPARM"})"_json, assembler_options { .sysparm = "TESTPARM" }), + std::make_pair(R"({"OPTABLE":"ZS9"})"_json, assembler_options { .optable = "ZS9" }), + std::make_pair(R"({"SYSTEM_ID":"VSE"})"_json, assembler_options { .system_id = "VSE" }), + std::make_pair(R"({"GOFF":true})"_json, assembler_options { .goff = true }), + std::make_pair(R"({"XOBJECT":true})"_json, assembler_options { .goff = true }), + std::make_pair( + R"({"GOFF":true,"PROFILE":"MAC","SYSPARM":"TESTPARM","OPTABLE":"ZS9","SYSTEM_ID":"VSE","XOBJECT":false})"_json, + assembler_options { + .sysparm = "TESTPARM", .profile = "MAC", .optable = "ZS9", .system_id = "VSE", .goff = true }), + }; + + for (const auto& [input, expected] : cases) + { + EXPECT_EQ(input.get(), expected); + } +} + +TEST(assembler_options, write) +{ + const auto cases = { + std::make_pair(R"({})"_json, assembler_options {}), + std::make_pair(R"({"PROFILE":"MAC"})"_json, assembler_options { .profile = "MAC" }), + std::make_pair(R"({"SYSPARM":"TESTPARM"})"_json, assembler_options { .sysparm = "TESTPARM" }), + std::make_pair(R"({"OPTABLE":"ZS9"})"_json, assembler_options { .optable = "ZS9" }), + std::make_pair(R"({"SYSTEM_ID":"VSE"})"_json, assembler_options { .system_id = "VSE" }), + std::make_pair(R"({"GOFF":true})"_json, assembler_options { .goff = true }), + std::make_pair(R"({"GOFF":true,"PROFILE":"MAC","SYSPARM":"TESTPARM","OPTABLE":"ZS9","SYSTEM_ID":"VSE"})"_json, + assembler_options { + .sysparm = "TESTPARM", .profile = "MAC", .optable = "ZS9", .system_id = "VSE", .goff = true }), + }; + + for (const auto& [expected, input] : cases) + EXPECT_EQ(nlohmann::json(input), expected); +} + +TEST(assembler_options, validate) +{ + const auto cases = { + std::make_pair(assembler_options {}, true), + std::make_pair(assembler_options { "A" }, true), + std::make_pair(assembler_options { "SYSPARM" }, true), + std::make_pair(assembler_options { std::string(255, 'A') }, true), + std::make_pair(assembler_options { std::string(256, 'A') }, false), + std::make_pair(assembler_options { "", "", "" }, true), + std::make_pair(assembler_options { "", "", "UNI" }, true), + std::make_pair(assembler_options { "", "", "A" }, false), + std::make_pair(assembler_options { "", "", "", "", false }, true), + std::make_pair(assembler_options { "", "", "", "", true }, true), + }; + + for (const auto& [input, expected] : cases) + EXPECT_EQ(input.valid(), expected); +} + +TEST(assembler_options, has_value) +{ + const auto cases = { + std::make_pair(assembler_options {}, false), + std::make_pair(assembler_options { "A" }, true), + std::make_pair(assembler_options { "SYSPARM" }, true), + std::make_pair(assembler_options { std::string(255, 'A') }, true), + std::make_pair(assembler_options { std::string(256, 'A') }, true), + std::make_pair(assembler_options { "", "", "" }, true), + std::make_pair(assembler_options { "", "", "UNI" }, true), + std::make_pair(assembler_options { "", "", "A" }, true), + std::make_pair(assembler_options { "", "", "", "", false }, true), + std::make_pair(assembler_options { "", "", "", "", true }, true), + std::make_pair(assembler_options { .goff = true }, true), + }; + + for (const auto& [input, expected] : cases) + EXPECT_EQ(input.has_value(), expected); +} + +TEST(assembler_options, apply) +{ + const auto cases = { + std::make_pair(std::vector {}, asm_option {}), + std::make_pair( + std::vector { + { .sysparm = "PARM" }, + }, + asm_option { .sysparm = "PARM" }), + std::make_pair( + std::vector { + { .profile = "PARM" }, + }, + asm_option { .profile = "PARM" }), + std::make_pair( + std::vector { + { .system_id = "PARM" }, + }, + asm_option { .system_id = "PARM" }), + std::make_pair( + std::vector { + { .optable = "Z10" }, + }, + asm_option { .instr_set = instruction_set_version::Z10 }), + std::make_pair( + std::vector { + { .optable = "Z10" }, + { .optable = "Z11" }, + }, + asm_option { .instr_set = instruction_set_version::Z11 }), + std::make_pair( + std::vector { + { .optable = "Z10" }, + { .optable = "invalid" }, + }, + asm_option { .instr_set = instruction_set_version::Z10 }), + std::make_pair(std::vector { { .goff = true } }, asm_option { .sysopt_xobject = true }), + std::make_pair( + std::vector { + { .goff = true }, + { .goff = true }, + }, + asm_option { .sysopt_xobject = true }), + std::make_pair( + std::vector { + { .goff = true }, + { .goff = false }, + }, + asm_option { .sysopt_xobject = false }), + std::make_pair( + std::vector { + { .goff = true }, + {}, + }, + asm_option { .sysopt_xobject = true }), + std::make_pair( + std::vector { + { .system_id = "PARM" }, + { .goff = true }, + }, + asm_option { .system_id = "PARM", .sysopt_xobject = true }), + }; + + for (const auto& [input, expected] : cases) + { + asm_option result; + for (const auto& opt : input) + opt.apply(result); + EXPECT_EQ(result, expected) << nlohmann::json(input).dump(2); + } +} \ No newline at end of file diff --git a/parser_library/test/config/pgm_conf_test.cpp b/parser_library/test/config/pgm_conf_test.cpp index 04da21531..5d3518070 100644 --- a/parser_library/test/config/pgm_conf_test.cpp +++ b/parser_library/test/config/pgm_conf_test.cpp @@ -25,7 +25,11 @@ TEST(pgm_conf, full_content_read) "pgms":[ { "program": "P1", - "pgroup": "G1" + "pgroup": "G1", + "asm_options": + { + "SYSPARM":"PARM" + } }, { "program": "P2", @@ -43,8 +47,10 @@ TEST(pgm_conf, full_content_read) ASSERT_EQ(config.pgms.size(), 2); EXPECT_EQ(config.pgms[0].pgroup, "G1"); EXPECT_EQ(config.pgms[0].program, "P1"); + EXPECT_EQ(config.pgms[0].opts, assembler_options { .sysparm = "PARM" }); EXPECT_EQ(config.pgms[1].pgroup, "G2"); EXPECT_EQ(config.pgms[1].program, "P2"); + EXPECT_EQ(config.pgms[1].opts, assembler_options {}); ASSERT_EQ(config.always_recognize.size(), 3); EXPECT_EQ(config.always_recognize[0], "*.mac"); @@ -56,9 +62,16 @@ TEST(pgm_conf, full_content_read) TEST(pgm_conf, full_content_write) { - const pgm_conf config = { { { "P1", "G1" }, { "P2", "G2" } }, { "*.mac1", "*.mac2", "*.mac3" }, 321 }; + const pgm_conf config = { + { + { "P1", "G1", { .sysparm = "PARM" } }, + { "P2", "G2" }, + }, + { "*.mac1", "*.mac2", "*.mac3" }, + 321, + }; const auto expected = - R"({"pgms":[{"program":"P1","pgroup":"G1"},{"program":"P2","pgroup":"G2"}],"alwaysRecognize":["*.mac1","*.mac2","*.mac3"],"diagnosticsSuppressLimit":321})"_json; + R"({"pgms":[{"program":"P1","pgroup":"G1","asm_options":{"SYSPARM":"PARM"}},{"program":"P2","pgroup":"G2"}],"alwaysRecognize":["*.mac1","*.mac2","*.mac3"],"diagnosticsSuppressLimit":321})"_json; EXPECT_EQ(nlohmann::json(config), expected); } diff --git a/parser_library/test/config/proc_grps_test.cpp b/parser_library/test/config/proc_grps_test.cpp index 279147a89..a81e35ccc 100644 --- a/parser_library/test/config/proc_grps_test.cpp +++ b/parser_library/test/config/proc_grps_test.cpp @@ -47,49 +47,6 @@ TEST(proc_grps, library_write) EXPECT_EQ(nlohmann::json(l), expected); } -TEST(proc_grps, assembler_options_read) -{ - const auto cases = { - std::make_pair(R"({})"_json, assembler_options {}), - std::make_pair(R"({"PROFILE":"MAC"})"_json, assembler_options { "", "MAC" }), - std::make_pair(R"({"SYSPARM":"TESTPARM"})"_json, assembler_options { "TESTPARM", "" }), - std::make_pair(R"({"OPTABLE":"ZS9"})"_json, assembler_options { "", "", "ZS9" }), - std::make_pair(R"({"SYSTEM_ID":"VSE"})"_json, assembler_options { "", "", "", "VSE" }), - std::make_pair(R"({"GOFF":true})"_json, assembler_options { "", "", "", "", true }), - std::make_pair(R"({"XOBJECT":true})"_json, assembler_options { "", "", "", "", true }), - std::make_pair( - R"({"GOFF":true,"PROFILE":"MAC","SYSPARM":"TESTPARM","OPTABLE":"ZS9","SYSTEM_ID":"VSE","XOBJECT":false})"_json, - assembler_options { "TESTPARM", "MAC", "ZS9", "VSE", true }), - }; - - for (const auto& [input, expected] : cases) - { - const auto ao = input.get(); - EXPECT_EQ(ao.profile, expected.profile); - EXPECT_EQ(ao.sysparm, expected.sysparm); - EXPECT_EQ(ao.optable, expected.optable); - EXPECT_EQ(ao.system_id, expected.system_id); - EXPECT_EQ(ao.goff, expected.goff); - } -} - -TEST(proc_grps, assembler_options_write) -{ - const auto cases = { - std::make_pair(R"({})"_json, assembler_options {}), - std::make_pair(R"({"PROFILE":"MAC"})"_json, assembler_options { "", "MAC" }), - std::make_pair(R"({"SYSPARM":"TESTPARM"})"_json, assembler_options { "TESTPARM", "" }), - std::make_pair(R"({"OPTABLE":"ZS9"})"_json, assembler_options { "", "", "ZS9" }), - std::make_pair(R"({"SYSTEM_ID":"VSE"})"_json, assembler_options { "", "", "", "VSE" }), - std::make_pair(R"({"GOFF":true})"_json, assembler_options { "", "", "", "", true }), - std::make_pair(R"({"GOFF":true,"PROFILE":"MAC","SYSPARM":"TESTPARM","OPTABLE":"ZS9","SYSTEM_ID":"VSE"})"_json, - assembler_options { "TESTPARM", "MAC", "ZS9", "VSE", true }), - }; - - for (const auto& [expected, input] : cases) - EXPECT_EQ(nlohmann::json(input), expected); -} - static void compare_proc_grps(const proc_grps& pg, const proc_grps& expected) { ASSERT_EQ(pg.pgroups.size(), expected.pgroups.size()); @@ -213,25 +170,6 @@ TEST(proc_grps, invalid) EXPECT_THROW(input.get(), nlohmann::json::exception); } -TEST(proc_grps, assembler_options_validate) -{ - const auto cases = { - std::make_pair(assembler_options {}, true), - std::make_pair(assembler_options { "A" }, true), - std::make_pair(assembler_options { "SYSPARM" }, true), - std::make_pair(assembler_options { std::string(255, 'A') }, true), - std::make_pair(assembler_options { std::string(256, 'A') }, false), - std::make_pair(assembler_options { "", "", "" }, true), - std::make_pair(assembler_options { "", "", "UNI" }, true), - std::make_pair(assembler_options { "", "", "A" }, false), - std::make_pair(assembler_options { "", "", "", "", false }, true), - std::make_pair(assembler_options { "", "", "", "", true }, true), - }; - - for (const auto& [input, expected] : cases) - EXPECT_EQ(input.valid(), expected); -} - TEST(proc_grps, preprocessor_options_validate) { const auto cases = { diff --git a/parser_library/test/workspace/load_config_test.cpp b/parser_library/test/workspace/load_config_test.cpp index b11ac432b..d3a08034f 100644 --- a/parser_library/test/workspace/load_config_test.cpp +++ b/parser_library/test/workspace/load_config_test.cpp @@ -122,6 +122,14 @@ class file_pgm_conf : public file_impl "program": "pgm1", "pgroup": "P1" }, + { + "program": "pgm_override", + "pgroup": "P1", + "asm_options": + { + "PROFILE": "PROFILE OVERRIDE" + } + }, { "program": "pgms\\*", "pgroup": "P2" @@ -134,6 +142,14 @@ class file_pgm_conf : public file_impl "program": "pgm1", "pgroup": "P1" }, + { + "program": "pgm_override", + "pgroup": "P1", + "asm_options": + { + "PROFILE": "PROFILE OVERRIDE" + } + }, { "program": "pgms/*", "pgroup": "P2" @@ -247,6 +263,13 @@ TEST(workspace, load_config_synthetic) ws.get_preprocessor_options(is_windows() ? "test_proc_grps_uri\\pgm1" : "test_proc_grps_uri/pgm1"); EXPECT_TRUE(std::holds_alternative(pp_options)); + + // test of asm_options override + const auto& asm_options_override = + ws.get_asm_options(is_windows() ? "test_proc_grps_uri\\pgm_override" : "test_proc_grps_uri/pgm_override"); + + EXPECT_EQ("SEVEN", asm_options_override.sysparm); + EXPECT_EQ("PROFILE OVERRIDE", asm_options_override.profile); } diff --git a/parser_library/test/workspace/processor_group_test.cpp b/parser_library/test/workspace/processor_group_test.cpp index 886fdc883..0af82f1d6 100644 --- a/parser_library/test/workspace/processor_group_test.cpp +++ b/parser_library/test/workspace/processor_group_test.cpp @@ -21,10 +21,15 @@ using namespace hlasm_plugin::parser_library; using namespace hlasm_plugin::parser_library::workspaces; -auto asm_options(config::assembler_options o) { return processor_group("", "", std::move(o), {}).asm_options(); } +auto asm_options(config::assembler_options o) +{ + asm_option result; + processor_group("", std::move(o), {}).update_asm_options(result); + return result; +} auto pp_options(decltype(config::preprocessor_options::options) o) { - return processor_group("", "", {}, config::preprocessor_options { .options = std::move(o) }).preprocessor(); + return processor_group("", {}, config::preprocessor_options { .options = std::move(o) }).preprocessor(); } TEST(processor_group, assembler_options) @@ -58,17 +63,8 @@ TEST(processor_group, preprocessor_options) EXPECT_EQ(pp_options(config::cics_preprocessor { .prolog = false, .leasm = true }), cics(false, true, true)); } -class processor_group_test : public diagnosable_impl, public testing::Test -{ -public: - void collect_diags() const override {} -}; - -TEST_F(processor_group_test, asm_options_optable_valid) +TEST(processor_group, asm_options_optable_valid) { - std::string grp_name = "Group"; - config::assembler_options asm_opts; - const auto cases = { std::make_pair("ZOP", instruction_set_version::ZOP), std::make_pair("ZS1", instruction_set_version::ZOP), @@ -98,25 +94,12 @@ TEST_F(processor_group_test, asm_options_optable_valid) for (const auto& [input, expected] : cases) { - diags().clear(); - - asm_opts.optable = input; - workspaces::processor_group proc_group("Group", "", asm_opts, {}); - - auto instr_set = proc_group.asm_options().instr_set; - - collect_diags_from_child(proc_group); - EXPECT_EQ(diags().size(), (size_t)0); - - EXPECT_EQ(instr_set, expected); + EXPECT_EQ(asm_options({ .optable = input }).instr_set, expected); } } -TEST_F(processor_group_test, asm_options_optable_invalid) +TEST(processor_group, asm_options_optable_invalid) { - std::string grp_name = "Group"; - config::assembler_options asm_opts; - const auto cases = { std::make_pair("klgadh", instruction_set_version::UNI), std::make_pair("ZS5ZS6", instruction_set_version::UNI), @@ -126,17 +109,6 @@ TEST_F(processor_group_test, asm_options_optable_invalid) for (const auto& [input, expected] : cases) { - diags().clear(); - - asm_opts.optable = input; - workspaces::processor_group proc_group("Group", "", asm_opts, {}); - - auto instr_set = proc_group.asm_options().instr_set; - - collect_diags_from_child(proc_group); - EXPECT_EQ(diags().size(), (size_t)1); - EXPECT_TRUE(matches_message_codes(diags(), { "W0007" })); - - EXPECT_EQ(instr_set, expected); + EXPECT_EQ(asm_options({ .optable = input }).instr_set, expected); } } diff --git a/parser_library/test/workspace/workspace_test.cpp b/parser_library/test/workspace/workspace_test.cpp index 0c8a5825a..89f7222f6 100644 --- a/parser_library/test/workspace/workspace_test.cpp +++ b/parser_library/test/workspace/workspace_test.cpp @@ -234,6 +234,30 @@ std::string pgmconf_file = R"({ ] })"; +std::string pgmconf_file_invalid_assembler_options = R"({ + "pgms": [ + { + "program": "source1", + "pgroup": "P1" + }, + { + "program": "source2", + "pgroup": "P1" + }, + { + "program": "source3", + "pgroup": "P1" + }, + { + "program": "invalid", + "pgroup": "P1", + "asm_options": { + "SYSPARM": "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFFFGGGGGGGGGGHHHHHHHHHHIIIIIIIIIIJJJJJJJJJJAAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFFFGGGGGGGGGGHHHHHHHHHHIIIIIIIIIIJJJJJJJJJJAAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFFFGGGGGGGGGGHHHHHHHHHHIIIIIIIIIIJJJJJJJJJJ" + } + } + ] +})"; + std::string faulty_macro_file = R"( MACRO ERROR label @@ -292,6 +316,7 @@ enum class file_manager_opt_variant optional, invalid_assembler_options, invalid_preprocessor_options, + invalid_assembler_options_in_pgm_conf, }; class file_manager_opt : public file_manager_impl @@ -301,6 +326,7 @@ class file_manager_opt : public file_manager_impl switch (variant) { case file_manager_opt_variant::old_school: + case file_manager_opt_variant::invalid_assembler_options_in_pgm_conf: return std::make_unique("proc_grps.json", pgroups_file_old_school, *this); case file_manager_opt_variant::default_to_required: return std::make_unique("proc_grps.json", pgroups_file_default, *this); @@ -318,12 +344,22 @@ class file_manager_opt : public file_manager_impl throw std::logic_error("Not implemented"); } + std::unique_ptr generate_pgm_conf_file(file_manager_opt_variant variant) + { + switch (variant) + { + case file_manager_opt_variant::invalid_assembler_options_in_pgm_conf: + return std::make_unique("pgm_conf.json", pgmconf_file_invalid_assembler_options, *this); + default: + return std::make_unique("pgm_conf.json", pgmconf_file, *this); + } + } + public: file_manager_opt(file_manager_opt_variant variant) { files_.emplace(hlasmplugin_folder + "proc_grps.json", generate_proc_grps_file(variant)); - files_.emplace(hlasmplugin_folder + "pgm_conf.json", - std::make_unique("pgm_conf.json", pgmconf_file, *this)); + files_.emplace(hlasmplugin_folder + "pgm_conf.json", generate_pgm_conf_file(variant)); files_.emplace("source1", std::make_unique("source1", source_using_macro_file_no_error, *this)); files_.emplace( correct_macro_path, std::make_unique(correct_macro_path, correct_macro_file, *this)); @@ -446,6 +482,17 @@ TEST_F(workspace_test, invalid_assembler_options) EXPECT_TRUE(std::any_of(diags().begin(), diags().end(), [](const auto& d) { return d.code == "W0005"; })); } +TEST_F(workspace_test, invalid_assembler_options_in_pgm_conf) +{ + file_manager_opt file_manager(file_manager_opt_variant::invalid_assembler_options_in_pgm_conf); + lib_config config; + workspace ws("", "workspace_name", file_manager, config); + ws.open(); + + EXPECT_GE(collect_and_get_diags_size(ws, file_manager), (size_t)1); + EXPECT_TRUE(std::any_of(diags().begin(), diags().end(), [](const auto& d) { return d.code == "W0005"; })); +} + TEST_F(workspace_test, invalid_preprocessor_options) { file_manager_opt file_manager(file_manager_opt_variant::invalid_preprocessor_options);