Skip to content

Commit 05e72d5

Browse files
committed
Generate errors outside AST tree
1 parent f2915a0 commit 05e72d5

16 files changed

+365
-175
lines changed

CMakeLists.txt

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ add_library(hk_objects OBJECT
4242
"${CMAKE_CURRENT_SOURCE_DIR}/src/ast/import_declaration_node.hpp"
4343
"${CMAKE_CURRENT_SOURCE_DIR}/src/ast/import_library_declaration_node.hpp"
4444
"${CMAKE_CURRENT_SOURCE_DIR}/src/ast/import_module_declaration_node.hpp"
45+
"${CMAKE_CURRENT_SOURCE_DIR}/src/ast/import_repository_declaration_node.cpp"
4546
"${CMAKE_CURRENT_SOURCE_DIR}/src/ast/import_repository_declaration_node.hpp"
4647
"${CMAKE_CURRENT_SOURCE_DIR}/src/ast/module_declaration_node.hpp"
4748
"${CMAKE_CURRENT_SOURCE_DIR}/src/ast/module_node.cpp"
@@ -51,6 +52,7 @@ add_library(hk_objects OBJECT
5152
"${CMAKE_CURRENT_SOURCE_DIR}/src/error/error_code.hpp"
5253
"${CMAKE_CURRENT_SOURCE_DIR}/src/error/error_item.hpp"
5354
"${CMAKE_CURRENT_SOURCE_DIR}/src/error/error_list.hpp"
55+
"${CMAKE_CURRENT_SOURCE_DIR}/src/error/error_location.hpp"
5456
"${CMAKE_CURRENT_SOURCE_DIR}/src/error/errors.hpp"
5557
"${CMAKE_CURRENT_SOURCE_DIR}/src/error/make_error.hpp"
5658
"${CMAKE_CURRENT_SOURCE_DIR}/src/parser/consume.hpp"
@@ -100,6 +102,8 @@ add_library(hk_objects OBJECT
100102
"${CMAKE_CURRENT_SOURCE_DIR}/src/utility/fixed_fifo.hpp"
101103
"${CMAKE_CURRENT_SOURCE_DIR}/src/utility/fqname.hpp"
102104
"${CMAKE_CURRENT_SOURCE_DIR}/src/utility/generator.hpp"
105+
"${CMAKE_CURRENT_SOURCE_DIR}/src/utility/git_error.cpp"
106+
"${CMAKE_CURRENT_SOURCE_DIR}/src/utility/git_error.hpp"
103107
"${CMAKE_CURRENT_SOURCE_DIR}/src/utility/git.cpp"
104108
"${CMAKE_CURRENT_SOURCE_DIR}/src/utility/git.hpp"
105109
"${CMAKE_CURRENT_SOURCE_DIR}/src/utility/log.cpp"
@@ -193,19 +197,11 @@ if(BUILD_TESTING)
193197
endif()
194198

195199
add_custom_command(
196-
OUTPUT ${CMAKE_BINARY_DIR}/test_data/.copied
200+
TARGET hktests POST_BUILD
197201
COMMAND ${CMAKE_COMMAND} -E copy_directory
198202
${CMAKE_SOURCE_DIR}/test_data
199203
${CMAKE_BINARY_DIR}/test_data
200-
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_BINARY_DIR}/test_data/.copied
201-
DEPENDS ${CMAKE_SOURCE_DIR}/test_data # optional, see note
202-
COMMENT "Copying test_data directory"
203204
)
204205

205-
add_custom_target(copy_test_data ALL
206-
DEPENDS ${CMAKE_BINARY_DIR}/test_data/.copied
207-
)
208-
209-
add_dependencies(hktests copy_test_data)
210206
add_test(NAME hktests COMMAND hktests)
211207
endif()

src/ast/import_declaration_node.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@
44
#include "node.hpp"
55
#include "utility/fqname.hpp"
66
#include "utility/generator.hpp"
7-
7+
#include "utility/repository_url.hpp"
8+
#include "error/error_location.hpp"
89

910
namespace hk::ast {
1011

1112
class import_declaration_node : public node {
1213
public:
1314
using node::node;
1415

16+
[[nodiscard]] virtual generator<std::pair<repository_url, error_location>> remote_repositories(error_list &errors) const
17+
{
18+
co_return;
19+
}
1520
};
1621

1722
using import_declaration_node_ptr = std::unique_ptr<import_declaration_node>;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
#include "import_repository_declaration_node.hpp"
3+
4+
namespace hk::ast {
5+
6+
[[nodiscard]] generator<std::pair<repository_url, error_location>>
7+
import_repository_declaration_node::remote_repositories(error_list& errors) const
8+
{
9+
co_yield {url, error_location{errors, first, last}};
10+
}
11+
12+
} // namespace hk::ast

src/ast/import_repository_declaration_node.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@ namespace hk::ast {
66

77
class import_repository_declaration_node : public import_declaration_node {
88
public:
9+
repository_url url;
10+
911
using import_declaration_node::import_declaration_node;
1012

1113
import_repository_declaration_node(file_location first, file_location last, repository_url url) :
1214
import_declaration_node(first, last), url(url)
1315
{
1416
}
1517

16-
repository_url url;
18+
[[nodiscard]] generator<std::pair<repository_url, error_location>> remote_repositories(error_list &errors) const override;
19+
1720
};
1821

1922
} // namespace hk::ast

src/ast/module_node.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
namespace hk::ast {
66

7-
[[nodiscard]] generator<module_node::remote_repository_result> module_node::remote_repositories() const
7+
[[nodiscard]] generator<std::pair<repository_url, error_location>> module_node::remote_repositories() const
88
{
99
for (auto const& import : imports) {
10-
if (auto repository_import_ptr = dynamic_cast<import_repository_declaration_node const*>(import.get())) {
11-
co_yield remote_repository_result{repository_import_ptr->url, fxxxxxxxst, this};
10+
for (auto result : import->remote_repositories(errors)) {
11+
co_yield std::move(result);
1212
}
1313
}
1414
}

src/ast/module_node.hpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "module_declaration_node.hpp"
66
#include "import_declaration_node.hpp"
77
#include "error/error_list.hpp"
8+
#include "error/error_location.hpp"
89
#include "utility/repository_url.hpp"
910
#include <memory>
1011
#include <vector>
@@ -24,7 +25,7 @@ class module_node : public node {
2425

2526
/** List of errors found.
2627
*/
27-
error_list errors;
28+
mutable error_list errors;
2829

2930
/** The path to the module file.
3031
*/
@@ -49,13 +50,7 @@ class module_node : public node {
4950
std::vector<import_declaration_node_ptr> imports;
5051
std::vector<node_ptr> body;
5152

52-
struct remote_repository_result {
53-
repository_url url;
54-
file_location first;
55-
file_location last;
56-
module_node *node;
57-
};
58-
[[nodiscard]] generator<remote_repository_result> remote_repositories() const;
53+
[[nodiscard]] generator<std::pair<repository_url, error_location>> remote_repositories() const;
5954

6055
};
6156

src/error/error_location.hpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
2+
#pragma once
3+
4+
#include "utility/file_location.hpp"
5+
#include "error_list.hpp"
6+
7+
namespace hk {
8+
9+
/** This class holds an error-location in module.
10+
*
11+
* If a error occurs outside of the AST tree, this class can be used to report
12+
* an error inside that module.
13+
*/
14+
class error_location {
15+
public:
16+
constexpr error_location() noexcept = default;
17+
constexpr error_location(error_location const&) noexcept = default;
18+
constexpr error_location(error_location&&) noexcept = default;
19+
constexpr error_location &operator=(error_location const&) noexcept = default;
20+
constexpr error_location &operator=(error_location&&) noexcept = default;
21+
22+
/** Create an error location.
23+
*
24+
* @param errors The error list of the module.
25+
* @param first The location of the first character of the module where an
26+
* optional error can appear.
27+
* @param last One beyond the last character.
28+
*/
29+
constexpr error_location(error_list &errors, file_location first, file_location last = file_location{})
30+
: _errors_ptr(&errors), _first(first), _last(last) {}
31+
32+
/** Add an error to the list.
33+
*
34+
* @tparam ErrorCode The error being raised, including the format string.
35+
* @param args The arguments to format the error message.
36+
* @return A unexpected error containing the error code.
37+
*/
38+
template<typename ErrorType, typename... Args>
39+
std::unexpected<error_code> add(Args&&... args)
40+
{
41+
assert(_errors_ptr != nullptr);
42+
43+
auto e = error_item{_first, _last, ErrorType::code, ErrorType::fmt, std::forward<Args>(args)...};
44+
_errors_ptr->push_back(std::move(e));
45+
return std::unexpected{ErrorType::code};
46+
}
47+
48+
private:
49+
error_list *_errors_ptr = nullptr;
50+
file_location _first = {};
51+
file_location _last = {};
52+
};
53+
54+
}

src/error/errors.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ E(missing_import_mod_declaration_name, "E0012: Expected fully qualified name aft
2222
E(missing_import_declaration_semicolon, "E0013: Expected ';' after a import-declaration.");
2323
E(missing_fqname_identifier_after_dot, "E0014: Expected identifier after '.' in fully qualified name.");
2424

25+
E(could_not_clone_repository, "W0001: Could not clone repository '{}' rev '{}': {}.");
2526

2627
#undef E
2728

src/repository/repository.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
#include "utility/vector_set.hpp"
55
#include "utility/file_cursor.hpp"
66
#include "utility/git.hpp"
7+
#include "error/errors.hpp"
78
#include "parser/parse_module.hpp"
89
#include <cassert>
910
#include <algorithm>
11+
#include <map>
1012

1113
namespace hk {
1214

@@ -71,12 +73,12 @@ void repository::scan_prologues(repository_flags flags)
7173

7274
void repository::recursive_scan_prologues(repository_flags flags)
7375
{
74-
auto todo = std::set<repository_url>{};
75-
auto done = std::set<repository_url>{};
76+
auto todo = std::map<repository_url, error_location>{};
77+
auto done = std::map<repository_url, error_location>{};
7678

7779
scan_prologues(flags);
78-
for (auto child_repo_url : remote_repositories()) {
79-
todo.insert(std::move(child_repo_url));
80+
for (auto item : remote_repositories()) {
81+
todo.insert(std::move(item));
8082
}
8183

8284
auto hkdeps = _path / "_hkdeps";
@@ -88,11 +90,11 @@ void repository::recursive_scan_prologues(repository_flags flags)
8890
}
8991

9092
assert(it != done.end());
91-
auto child_repo_path = hkdeps / it->directory();
92-
auto &child_repo = get_child_repository(*it);
93+
auto child_repo_path = hkdeps / it->first.directory();
94+
auto &child_repo = get_child_repository(it->first);
9395
if (not child_repo.repository) {
94-
if (auto r = git_checkout_or_clone(*it, child_repo_path, flags); r != git_error::ok) {
95-
96+
if (auto r = git_checkout_or_clone(it->first, child_repo_path, flags); r != git_error::ok) {
97+
it->second.add<error::could_not_clone_repository>(it->first.url(), it->first.rev(), r);
9698
}
9799

98100
child_repo.repository = std::make_unique<repository>(child_repo_path);
@@ -115,11 +117,11 @@ void repository::untouch(bool remove)
115117
}
116118
}
117119

118-
[[nodiscard]] generator<repository_url> repository::remote_repositories() const
120+
[[nodiscard]] generator<std::pair<repository_url, error_location>> repository::remote_repositories() const
119121
{
120122
for (auto const& m : _modules) {
121-
for (auto u : m.ast->remote_repositories()) {
122-
co_yield std::move(u);
123+
for (auto repo : m.ast->remote_repositories()) {
124+
co_yield std::move(repo);
123125
}
124126
}
125127
}

src/repository/repository.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class repository {
2929
*/
3030
void recursive_scan_prologues(repository_flags flags);
3131

32-
[[nodiscard]] generator<repository_url> remote_repositories() const;
32+
[[nodiscard]] generator<std::pair<repository_url, error_location>> remote_repositories() const;
3333

3434
private:
3535
struct module_type {

0 commit comments

Comments
 (0)