Skip to content

Commit

Permalink
feat: MNOTE support
Browse files Browse the repository at this point in the history
  • Loading branch information
slavek-kucera committed Apr 28, 2022
1 parent 3e6daed commit 7ac224c
Show file tree
Hide file tree
Showing 22 changed files with 558 additions and 90 deletions.
1 change: 1 addition & 0 deletions clients/vscode-hlasmplugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- DB2 preprocessor now supports the VERSION option
- Instruction set versioning support
- Basic GOFF, XOBJECT and SYSOPT_XOBJECT support
- MNOTE support

#### Fixed
- Fixed an issue preventing correct N' attribute evaluation of empty subscript arrays
Expand Down
9 changes: 5 additions & 4 deletions language_server/src/lsp/feature_language_features.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,11 @@ void feature_language_features::definition(const json& id, const json& params)


auto definition_position_uri = ws_mngr_.definition(uri_to_path(document_uri).c_str(), pos);
document_uri =
(definition_position_uri.file()[0] == '\0') ? document_uri : path_to_uri(definition_position_uri.file());
json to_ret { { "uri", document_uri },
{ "range", range_to_json({ definition_position_uri.pos(), definition_position_uri.pos() }) } };
document_uri = definition_position_uri.file().empty() ? document_uri : path_to_uri(definition_position_uri.file());
json to_ret {
{ "uri", document_uri },
{ "range", range_to_json({ definition_position_uri.pos(), definition_position_uri.pos() }) },
};
response_->respond(id, "", to_ret);
}

Expand Down
8 changes: 8 additions & 0 deletions language_server/src/lsp/lsp_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,14 @@ void server::consume_diagnostics(parser_library::diagnostic_list diagnostics)
{
one_json["severity"] = (int)d.severity();
}
if (auto t = d.tags(); t != parser_library::diagnostic_tag::none)
{
auto& tags = one_json["tags"] = json::array();
if (static_cast<int>(t) & static_cast<int>(parser_library::diagnostic_tag::unnecessary))
tags.push_back(1);
if (static_cast<int>(t) & static_cast<int>(parser_library::diagnostic_tag::deprecated))
tags.push_back(2);
}
diags_array.push_back(std::move(one_json));
}

Expand Down
28 changes: 28 additions & 0 deletions language_server/test/regress_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,3 +593,31 @@ TEST(regress_test, stability_sync)
for (const auto& message : messages)
s.message_received(message);
}

TEST(regress_test, check_diagnostic_tags)
{
parser_library::workspace_manager ws_mngr;
message_provider_mock mess_p;
lsp::server s(ws_mngr);
s.set_send_message_provider(&mess_p);

auto notf = make_notification("textDocument/didOpen",
R"#({"textDocument":{"uri":"file:///c%3A/test/note_test.hlasm","languageId":"plaintext","version":1,"text":" MNOTE 'test note'"}})#"_json);
s.message_received(notf);

ASSERT_EQ(mess_p.notfs.size(), (size_t)2);
auto publish_notif = std::find_if(mess_p.notfs.begin(), mess_p.notfs.end(), [&](json notif) {
return notif["method"] == "textDocument/publishDiagnostics";
});
ASSERT_NE(publish_notif, mess_p.notfs.end());
ASSERT_EQ((*publish_notif)["method"], "textDocument/publishDiagnostics");
auto diagnostics = (*publish_notif)["params"]["diagnostics"];
ASSERT_EQ(diagnostics.size(), (size_t)1);
EXPECT_EQ(diagnostics[0]["code"].get<std::string>(), "MNOTE");
ASSERT_GT(diagnostics[0].count("tags"), 0);
ASSERT_TRUE(diagnostics[0]["tags"].is_array());
ASSERT_EQ(diagnostics[0]["tags"].size(), (size_t)1);
ASSERT_EQ(diagnostics[0]["tags"][0], 1);

mess_p.notfs.clear();
}
8 changes: 8 additions & 0 deletions parser_library/include/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,13 @@ enum class PARSER_LIBRARY_EXPORT diagnostic_severity
unspecified = 5
};

enum class PARSER_LIBRARY_EXPORT diagnostic_tag
{
none = 0,
unnecessary = 1 << 0,
deprecated = 1 << 1,
};

struct PARSER_LIBRARY_EXPORT diagnostic_related_info
{
diagnostic_related_info(diagnostic_related_info_s&);
Expand All @@ -236,6 +243,7 @@ struct PARSER_LIBRARY_EXPORT diagnostic
const char* message() const;
const diagnostic_related_info related_info(size_t index) const;
size_t related_info_size() const;
diagnostic_tag tags() const;

private:
diagnostic_s& impl_;
Expand Down
42 changes: 31 additions & 11 deletions parser_library/src/diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>

namespace hlasm_plugin::parser_library {

Expand All @@ -32,7 +33,7 @@ struct concat_helper

size_t len(std::string_view t) const { return t.size(); }
template<typename T>
std::enable_if_t<!std::is_convertible_v<T&&, std::string_view>, size_t> len(T&&) const
std::enable_if_t<!std::is_convertible_v<T&&, std::string_view>, size_t> len(const T&) const
{
return 8; // arbitrary estimate for the length of the stringified argument (typically small numbers)
}
Expand All @@ -45,7 +46,7 @@ std::string concat(Args&&... args)

concat_helper h;

result.reserve((... + h.len(std::forward<Args>(args))));
result.reserve((... + h.len(std::as_const(args))));

(h(result, std::forward<Args>(args)), ...);

Expand Down Expand Up @@ -2411,14 +2412,25 @@ diagnostic_op diagnostic_op::error_U006_duplicate_base_specified(const range& ra
return diagnostic_op(diagnostic_severity::error, "U006", "Base registers must be distinct.", range);
}

diagnostic_op diagnostic_op::mnote_diagnostic(unsigned level, std::string_view message, const range& range)
{
const auto lvl = level >= 8 ? diagnostic_severity::error
: level >= 4 ? diagnostic_severity::warning
: level >= 2 ? diagnostic_severity::info
: diagnostic_severity::hint;
const auto tag = level >= 2 ? diagnostic_tag::none : diagnostic_tag::unnecessary;
return diagnostic_op(lvl, "MNOTE", std::string(message), range, tag);
}

diagnostic_s diagnostic_s::error_W0002(std::string_view ws_uri, std::string_view ws_name)
{
return diagnostic_s(std::string(ws_uri),
{},
diagnostic_severity::error,
"W0002",
concat("The configuration file proc_grps for workspace ", ws_name, " is malformed."),
{});
{},
diagnostic_tag::none);
}

diagnostic_s diagnostic_s::error_W0003(std::string_view file_name, std::string_view ws_name)
Expand All @@ -2428,7 +2440,8 @@ diagnostic_s diagnostic_s::error_W0003(std::string_view file_name, std::string_v
diagnostic_severity::error,
"W0003",
concat("The configuration file pgm_conf for workspace ", ws_name, " is malformed."),
{});
{},
diagnostic_tag::none);
}

diagnostic_s diagnostic_s::error_W0004(std::string_view file_name, std::string_view ws_name)
Expand All @@ -2440,7 +2453,8 @@ diagnostic_s diagnostic_s::error_W0004(std::string_view file_name, std::string_v
concat("The configuration file pgm_conf for workspace ",
ws_name,
" refers to a processor group, that is not defined in proc_grps"),
{});
{},
diagnostic_tag::none);
}

diagnostic_s diagnostic_s::error_W0005(std::string_view file_name, std::string_view proc_group)
Expand All @@ -2450,7 +2464,8 @@ diagnostic_s diagnostic_s::error_W0005(std::string_view file_name, std::string_v
diagnostic_severity::warning,
"W0005",
concat("The processor group '", proc_group, "' from '", file_name, "' defines invalid assembler options."),
{});
{},
diagnostic_tag::none);
}

diagnostic_s diagnostic_s::error_W0006(std::string_view file_name, std::string_view proc_group)
Expand All @@ -2460,7 +2475,8 @@ diagnostic_s diagnostic_s::error_W0006(std::string_view file_name, std::string_v
diagnostic_severity::warning,
"W0006",
concat("The processor group '", proc_group, "' from '", file_name, "' defines invalid preprocessor options."),
{});
{},
diagnostic_tag::none);
}

diagnostic_s diagnostic_s::error_W0007(std::string_view file_name, std::string_view proc_group)
Expand All @@ -2474,7 +2490,8 @@ diagnostic_s diagnostic_s::error_W0007(std::string_view file_name, std::string_v
"' 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)
Expand All @@ -2497,7 +2514,8 @@ diagnostic_s diagnostic_s::warning_L0003(std::string_view path)
concat("Macros from library '",
path,
"' were selected by a deprecated mechanism to specify file extensions (alwaysRecognize in pgm_conf.json)."),
{});
{},
diagnostic_tag::none);
}

diagnostic_s diagnostic_s::warning_L0004(std::string_view path, std::string_view macro_name)
Expand All @@ -2507,7 +2525,8 @@ diagnostic_s diagnostic_s::warning_L0004(std::string_view path, std::string_view
diagnostic_severity::warning,
"L0004",
concat("Library '", path, "' contains multiple definitions of the macro '", macro_name, "'."),
{});
{},
diagnostic_tag::none);
}

diagnostic_s diagnostic_s::warning_L0005(std::string_view pattern, size_t limit)
Expand All @@ -2517,7 +2536,8 @@ diagnostic_s diagnostic_s::warning_L0005(std::string_view pattern, size_t limit)
diagnostic_severity::warning,
"L0005",
concat("Limit of ", limit, " directories was reached while evaluating library pattern '", pattern, "'."),
{});
{},
diagnostic_tag::none);
}

diagnostic_op diagnostic_op::error_S100(std::string_view message, const range& range)
Expand Down
20 changes: 17 additions & 3 deletions parser_library/src/diagnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,20 @@ struct diagnostic_op
std::string code;
std::string message;
range diag_range;
diagnostic_tag tag;

diagnostic_op() = default;

diagnostic_op(diagnostic_severity severity, std::string code, std::string message, range diag_range = {})
diagnostic_op(diagnostic_severity severity,
std::string code,
std::string message,
range diag_range = {},
diagnostic_tag tag = diagnostic_tag::none)
: severity(severity)
, code(std::move(code))
, message(std::move(message))
, diag_range(std::move(diag_range)) {};
, diag_range(std::move(diag_range))
, tag(tag) {};

static diagnostic_op error_I999(std::string_view instr_name, const range& range);

Expand Down Expand Up @@ -708,6 +715,8 @@ struct diagnostic_op
int e_off);

static diagnostic_op error_U006_duplicate_base_specified(const range& range);

static diagnostic_op mnote_diagnostic(unsigned level, std::string_view message, const range& range);
};

struct range_uri_s
Expand Down Expand Up @@ -754,14 +763,16 @@ class diagnostic_s
diagnostic_severity severity,
std::string code,
std::string message,
std::vector<diagnostic_related_info_s> related)
std::vector<diagnostic_related_info_s> related,
diagnostic_tag tag)
: file_name(std::move(file_name))
, diag_range(range)
, severity(severity)
, code(std::move(code))
, source("HLASM Plugin")
, message(std::move(message))
, related(std::move(related))
, tag(tag)
{}
diagnostic_s(std::string file_name, diagnostic_op diag_op)
: file_name(std::move(file_name))
Expand All @@ -770,13 +781,15 @@ class diagnostic_s
, code(std::move(diag_op.code))
, source("HLASM Plugin")
, message(std::move(diag_op.message))
, tag(diag_op.tag)
{}
diagnostic_s(diagnostic_op diag_op)
: diag_range(std::move(diag_op.diag_range))
, severity(diag_op.severity)
, code(std::move(diag_op.code))
, source("HLASM Plugin")
, message(std::move(diag_op.message))
, tag(diag_op.tag)
{}


Expand All @@ -787,6 +800,7 @@ class diagnostic_s
std::string source;
std::string message;
std::vector<diagnostic_related_info_s> related;
diagnostic_tag tag = diagnostic_tag::none;

/*
Lxxxx - local library messages
Expand Down
5 changes: 3 additions & 2 deletions parser_library/src/lexing/input_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <exception>

#include "logical_line.h"
#include "utils/utf8text.h"

namespace hlasm_plugin::parser_library::lexing {

Expand All @@ -37,7 +38,7 @@ void append_utf8_to_utf32(UTF32String& t, std::string_view s)
s.remove_prefix(1);
continue;
}
const auto cs = utf8_prefix_sizes[c];
const auto cs = utils::utf8_prefix_sizes[c];
if (cs.utf8 && cs.utf8 <= s.size())
{
uint32_t v = c & 0b0111'1111u >> cs.utf8;
Expand All @@ -48,7 +49,7 @@ void append_utf8_to_utf32(UTF32String& t, std::string_view s)
}
else
{
t.append(1, substitute_character);
t.append(1, utils::substitute_character);
s.remove_prefix(1);
}
}
Expand Down
8 changes: 5 additions & 3 deletions parser_library/src/lexing/logical_line.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#include "logical_line.h"

#include "utils/utf8text.h"

namespace hlasm_plugin::parser_library::lexing {
std::pair<std::string_view, logical_line_segment_eol> extract_line(std::string_view& input)
{
Expand Down Expand Up @@ -64,12 +66,12 @@ std::pair<size_t, size_t> substr_step(std::string_view& s, size_t& chars)
continue;
}

const auto cs = utf8_prefix_sizes[c];
const auto cs = utils::utf8_prefix_sizes[c];
if constexpr (validate)
{
if (!cs.utf8 || s.size() < cs.utf8)
if (cs.utf8 < 2 || s.size() < cs.utf8 || !utils::utf8_valid_multibyte_prefix(s[0], s[1]))
throw hlasm_plugin::parser_library::lexing::utf8_error();
for (const auto* p = s.data() + 1; p != s.data() + cs.utf8; ++p)
for (const auto* p = s.data() + 2; p != s.data() + cs.utf8; ++p)
if ((*p & 0xc0) != 0x80)
throw hlasm_plugin::parser_library::lexing::utf8_error();
}
Expand Down
25 changes: 0 additions & 25 deletions parser_library/src/lexing/logical_line.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#ifndef HLASMPLUGIN_HLASMPARSERLIBRARY_LOGICAL_LINE_H
#define HLASMPLUGIN_HLASMPARSERLIBRARY_LOGICAL_LINE_H

#include <array>
#include <cassert>
#include <limits>
#include <stdexcept>
Expand All @@ -24,30 +23,6 @@

namespace hlasm_plugin::parser_library::lexing {

// Length of Unicode character in 8/16-bit chunks
struct char_size
{
uint8_t utf8 : 4;
uint8_t utf16 : 4;
};

// Map first byte of UTF-8 encoded Unicode character to char_size
constexpr const auto utf8_prefix_sizes = []() {
std::array<char_size, 256> sizes = {};
static_assert(std::numeric_limits<unsigned char>::max() < sizes.size());
for (int i = 0b0000'0000; i <= 0b0111'1111; ++i)
sizes[i] = { 1, 1 };
for (int i = 0b1100'0000; i <= 0b1101'1111; ++i)
sizes[i] = { 2, 1 };
for (int i = 0b1110'0000; i <= 0b1110'1111; ++i)
sizes[i] = { 3, 1 };
for (int i = 0b1111'0000; i <= 0b1111'0111; ++i)
sizes[i] = { 4, 2 };
return sizes;
}();

constexpr const char substitute_character = 0x1a;

class utf8_error : public std::runtime_error
{
public:
Expand Down
Loading

0 comments on commit 7ac224c

Please sign in to comment.