Skip to content

Commit 4a6e0b2

Browse files
committed
Merge branch 'main' into modularise-clang-tidy-config
Signed-off-by: Balakrishna Avulapati <ba@bavulapati.com>
2 parents f89c2cc + c5ded55 commit 4a6e0b2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2299
-1258
lines changed

cmake/Sourcemeta.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ endif()
2323

2424
# For debugging purposes
2525
if(PROJECT_IS_TOP_LEVEL)
26+
message(STATUS "CMAKE_VERSION: ${CMAKE_VERSION}")
2627
message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
2728
message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
2829
message(STATUS "CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}")

cmake/common/targets/clang-format.cmake

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,12 @@ function(sourcemeta_target_clang_format_attempt_install)
5454
set(CLANG_FORMAT_BINARY_WHEEL "${CLANG_FORMAT_BINARY_DOWNLOAD_DIR}/clang-format.whl")
5555
message(STATUS "Downloading `clang-format` pre-built binary from ${CLANG_FORMAT_BINARY_URL}")
5656
file(DOWNLOAD "${CLANG_FORMAT_BINARY_URL}" "${CLANG_FORMAT_BINARY_WHEEL}"
57-
STATUS CLANG_FORMAT_BINARY_DOWNLOAD_STATUS SHOW_PROGRESS TLS_VERIFY ON)
57+
STATUS CLANG_FORMAT_BINARY_DOWNLOAD_STATUS SHOW_PROGRESS TLS_VERIFY ON
58+
LOG CLANG_FORMAT_BINARY_DOWNLOAD_LOG)
5859
list(GET CLANG_FORMAT_BINARY_DOWNLOAD_STATUS 0 _code)
5960
if(NOT _code EQUAL 0)
6061
message(WARNING "Failed to download the `clang-format` pre-built binary")
62+
message(WARNING "${CLANG_FORMAT_BINARY_DOWNLOAD_LOG}")
6163
file(REMOVE_RECURSE "${CLANG_FORMAT_BINARY_DOWNLOAD_DIR}")
6264
return()
6365
endif()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
# See https://clang.llvm.org/extra/clang-tidy/index.html
3+
# First disable all default checks (with -*)
4+
Checks: '-*,
5+
bugprone-*,-bugprone-branch-clone,-bugprone-easily-swappable-parameters,-bugprone-empty-catch,
6+
clang-analyzer-*,
7+
clang-diagnostic-*,
8+
modernize-*,
9+
concurrency-*,
10+
cppcoreguidelines-*,-cppcoreguidelines-rvalue-reference-param-not-moved,
11+
performance-*,-performance-enum-size,
12+
portability-*,
13+
objc-*,
14+
misc-*,-misc-no-recursion,-misc-unused-parameters,-misc-const-correctness'
15+
WarningsAsErrors: '*'
16+
HeaderFilterRegex: ''
17+
FormatStyle: none
18+
CheckOptions:
19+
# See https://clang.llvm.org/extra/clang-tidy/checks/misc/include-cleaner.html
20+
# Otherwise ClangTidy wants us to directly include private headers from our modules
21+
- key: misc-include-cleaner.IgnoreHeaders
22+
value: 'src\/core\/.*;uriparser\/.*'

src/core/json/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME json
2-
PRIVATE_HEADERS array.h error.h object.h value.h hash.h
2+
PRIVATE_HEADERS array.h error.h object.h value.h hash.h auto.h
33
SOURCES grammar.h parser.h stringify.h json.cc json_value.cc)
44

55
if(SOURCEMETA_CORE_INSTALL)

src/core/json/include/sourcemeta/core/json.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#endif
77

88
// NOLINTBEGIN(misc-include-cleaner)
9+
#include <sourcemeta/core/json_auto.h>
910
#include <sourcemeta/core/json_error.h>
1011
#include <sourcemeta/core/json_value.h>
1112
// NOLINTEND(misc-include-cleaner)
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
#ifndef SOURCEMETA_CORE_JSON_AUTO_H_
2+
#define SOURCEMETA_CORE_JSON_AUTO_H_
3+
4+
#include <sourcemeta/core/json_value.h>
5+
6+
#include <concepts> // std::same_as, std::constructible_from
7+
#include <functional> // std::function
8+
#include <optional> // std::optional
9+
#include <tuple> // std::tuple, std::apply, std::tuple_element_t, std::tuple_size, std::tuple_size_v
10+
#include <type_traits> // std::false_type, std::true_type, std::void_t, std::is_enum_v, std::underlying_type_t, std::is_same_v, std::is_base_of_v, std::remove_cvref_t
11+
#include <utility> // std::pair
12+
13+
// Forward declarations (added as needed)
14+
#ifndef DOXYGEN
15+
namespace sourcemeta::core {
16+
template <typename L, typename R>
17+
auto to_json(const std::pair<L, R> &value) -> JSON;
18+
}
19+
#endif
20+
21+
namespace sourcemeta::core {
22+
23+
/// @ingroup json
24+
template <typename, typename = void>
25+
struct to_json_has_mapped_type : std::false_type {};
26+
template <typename T>
27+
struct to_json_has_mapped_type<T, std::void_t<typename T::mapped_type>>
28+
: std::true_type {};
29+
30+
/// @ingroup json
31+
template <typename T> struct to_json_is_basic_string : std::false_type {};
32+
template <typename CharT, typename Traits, typename Alloc>
33+
struct to_json_is_basic_string<std::basic_string<CharT, Traits, Alloc>>
34+
: std::true_type {};
35+
36+
/// @ingroup json
37+
template <typename T>
38+
concept to_json_has_method = requires(const T value) {
39+
{ value.to_json() } -> std::same_as<JSON>;
40+
};
41+
42+
/// @ingroup json
43+
/// Container-like classes can opt-out from automatic JSON
44+
/// serialisation by setting `using json_auto = std::false_type;`
45+
template <typename, typename = void>
46+
struct to_json_supports_auto_impl : std::true_type {};
47+
template <typename T>
48+
struct to_json_supports_auto_impl<T, std::void_t<typename T::json_auto>>
49+
: std::bool_constant<
50+
!std::is_same_v<typename T::json_auto, std::false_type>> {};
51+
template <typename T>
52+
concept to_json_supports_auto = to_json_supports_auto_impl<T>::value;
53+
54+
/// @ingroup json
55+
template <typename T>
56+
concept to_json_list_like =
57+
requires(T type) {
58+
typename T::value_type;
59+
typename T::const_iterator;
60+
{ type.cbegin() } -> std::same_as<typename T::const_iterator>;
61+
{ type.cend() } -> std::same_as<typename T::const_iterator>;
62+
} && to_json_supports_auto<T> && !to_json_has_mapped_type<T>::value &&
63+
!to_json_has_method<T> && !to_json_is_basic_string<T>::value;
64+
65+
/// @ingroup json
66+
template <typename T>
67+
concept to_json_map_like =
68+
requires(T type) {
69+
typename T::value_type;
70+
typename T::const_iterator;
71+
typename T::key_type;
72+
{ type.cbegin() } -> std::same_as<typename T::const_iterator>;
73+
{ type.cend() } -> std::same_as<typename T::const_iterator>;
74+
} && to_json_supports_auto<T> && to_json_has_mapped_type<T>::value &&
75+
!to_json_has_method<T> &&
76+
std::is_same_v<typename T::key_type, JSON::String>;
77+
78+
/// @ingroup json
79+
/// If the value has a `.to_json()` method, always prefer that
80+
template <typename T>
81+
requires(to_json_has_method<T>)
82+
auto to_json(const T &value) -> JSON {
83+
return value.to_json();
84+
}
85+
86+
// TODO: How can we keep this in the hash header that does not yet know about
87+
// JSON?
88+
/// @ingroup json
89+
template <typename T>
90+
requires std::is_same_v<T, JSON::Object::Container::hash_type>
91+
auto to_json(const T &hash) -> JSON {
92+
auto result{JSON::make_array()};
93+
#if defined(__SIZEOF_INT128__)
94+
result.push_back(JSON{static_cast<std::size_t>(hash.a >> 64)});
95+
result.push_back(JSON{static_cast<std::size_t>(hash.a)});
96+
result.push_back(JSON{static_cast<std::size_t>(hash.b >> 64)});
97+
result.push_back(JSON{static_cast<std::size_t>(hash.b)});
98+
#else
99+
result.push_back(JSON{static_cast<std::size_t>(hash.a)});
100+
result.push_back(JSON{static_cast<std::size_t>(hash.b)});
101+
result.push_back(JSON{static_cast<std::size_t>(hash.c)});
102+
result.push_back(JSON{static_cast<std::size_t>(hash.d)});
103+
#endif
104+
return result;
105+
}
106+
107+
/// @ingroup json
108+
template <typename T>
109+
requires std::constructible_from<JSON, T>
110+
auto to_json(const T &value) -> JSON {
111+
return JSON{value};
112+
}
113+
114+
/// @ingroup json
115+
template <typename T>
116+
requires std::is_enum_v<T>
117+
auto to_json(const T value) -> JSON {
118+
return to_json(static_cast<std::underlying_type_t<T>>(value));
119+
}
120+
121+
/// @ingroup json
122+
template <typename T> auto to_json(const std::optional<T> &value) -> JSON {
123+
return value.has_value() ? to_json(value.value()) : JSON{nullptr};
124+
}
125+
126+
/// @ingroup json
127+
template <to_json_list_like T>
128+
auto to_json(typename T::const_iterator begin, typename T::const_iterator end)
129+
-> JSON {
130+
// TODO: Extend `make_array` to optionally take iterators, etc
131+
auto result{JSON::make_array()};
132+
for (auto iterator = begin; iterator != end; ++iterator) {
133+
result.push_back(to_json(*iterator));
134+
}
135+
136+
return result;
137+
}
138+
139+
/// @ingroup json
140+
template <to_json_list_like T>
141+
auto to_json(
142+
typename T::const_iterator begin, typename T::const_iterator end,
143+
const std::function<JSON(const typename T::value_type &)> &callback)
144+
-> JSON {
145+
// TODO: Extend `make_array` to optionally take iterators, etc
146+
auto result{JSON::make_array()};
147+
for (auto iterator = begin; iterator != end; ++iterator) {
148+
result.push_back(callback(*iterator));
149+
}
150+
151+
return result;
152+
}
153+
154+
/// @ingroup json
155+
template <to_json_list_like T> auto to_json(const T &value) -> JSON {
156+
return to_json<T>(value.cbegin(), value.cend());
157+
}
158+
159+
/// @ingroup json
160+
template <to_json_list_like T>
161+
auto to_json(
162+
const T &value,
163+
const std::function<JSON(const typename T::value_type &)> &callback)
164+
-> JSON {
165+
return to_json<T>(value.cbegin(), value.cend(), callback);
166+
}
167+
168+
/// @ingroup json
169+
template <to_json_map_like T>
170+
auto to_json(typename T::const_iterator begin, typename T::const_iterator end)
171+
-> JSON {
172+
auto result{JSON::make_object()};
173+
for (auto iterator = begin; iterator != end; ++iterator) {
174+
result.assign(iterator->first, to_json(iterator->second));
175+
}
176+
177+
return result;
178+
}
179+
180+
/// @ingroup json
181+
template <to_json_map_like T> auto to_json(const T &value) -> JSON {
182+
return to_json<T>(value.cbegin(), value.cend());
183+
}
184+
185+
/// @ingroup json
186+
template <to_json_map_like T>
187+
auto to_json(
188+
typename T::const_iterator begin, typename T::const_iterator end,
189+
const std::function<JSON(const typename T::mapped_type &)> &callback)
190+
-> JSON {
191+
auto result{JSON::make_object()};
192+
for (auto iterator = begin; iterator != end; ++iterator) {
193+
result.assign(iterator->first, callback(iterator->second));
194+
}
195+
196+
return result;
197+
}
198+
199+
/// @ingroup json
200+
template <to_json_map_like T>
201+
auto to_json(
202+
const T &value,
203+
const std::function<JSON(const typename T::mapped_type &)> &callback)
204+
-> JSON {
205+
return to_json<T>(value.cbegin(), value.cend(), callback);
206+
}
207+
208+
/// @ingroup json
209+
template <typename L, typename R>
210+
auto to_json(const std::pair<L, R> &value) -> JSON {
211+
auto tuple{JSON::make_array()};
212+
tuple.push_back(to_json(value.first));
213+
tuple.push_back(to_json(value.second));
214+
return tuple;
215+
}
216+
217+
// Handle 1-element tuples
218+
/// @ingroup json
219+
template <typename T>
220+
requires(std::tuple_size_v<std::remove_cvref_t<std::tuple<T>>> == 1)
221+
auto to_json(const std::tuple<T> &value) -> JSON {
222+
auto tuple = JSON::make_array();
223+
std::apply([&](const T &element) { tuple.push_back(to_json(element)); },
224+
value);
225+
return tuple;
226+
}
227+
228+
// We have to do this mess because MSVC seems confuses `std::pair`
229+
// of 2 elements with this overload
230+
/// @ingroup json
231+
template <typename TupleT>
232+
requires(requires {
233+
typename std::tuple_size<std::remove_cvref_t<TupleT>>::type;
234+
} && (std::tuple_size_v<std::remove_cvref_t<TupleT>> >= 2) &&
235+
(!std::is_base_of_v<
236+
std::pair<std::tuple_element_t<0, std::remove_cvref_t<TupleT>>,
237+
std::tuple_element_t<1, std::remove_cvref_t<TupleT>>>,
238+
std::remove_cvref_t<TupleT>>))
239+
auto to_json(const TupleT &value) -> JSON {
240+
auto tuple = JSON::make_array();
241+
std::apply(
242+
[&tuple](const auto &...elements) {
243+
(tuple.push_back(to_json(elements)), ...);
244+
},
245+
value);
246+
return tuple;
247+
}
248+
249+
} // namespace sourcemeta::core
250+
251+
#endif

src/core/json/include/sourcemeta/core/json_value.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,9 @@ class SOURCEMETA_CORE_JSON_EXPORT JSON {
216216

217217
/// Misc constructors
218218
JSON(const JSON &);
219-
JSON(JSON &&);
219+
JSON(JSON &&) noexcept;
220220
auto operator=(const JSON &) -> JSON &;
221-
auto operator=(JSON &&) -> JSON &;
221+
auto operator=(JSON &&) noexcept -> JSON &;
222222

223223
/// Destructor
224224
~JSON();

src/core/json/json.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
namespace sourcemeta::core {
1717

18+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
1819
auto parse_json(std::basic_istream<JSON::Char, JSON::CharTraits> &stream,
1920
std::uint64_t &line, std::uint64_t &column,
2021
const JSON::ParseCallback &callback) -> JSON {
@@ -27,6 +28,7 @@ auto parse_json(const std::basic_string<JSON::Char, JSON::CharTraits> &input,
2728
return internal_parse_json(input, line, column, callback);
2829
}
2930

31+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
3032
auto parse_json(std::basic_istream<JSON::Char, JSON::CharTraits> &stream,
3133
const JSON::ParseCallback &callback) -> JSON {
3234
std::uint64_t line{1};

src/core/json/json_value.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ JSON::JSON(const JSON &other) : current_type{other.current_type} {
117117
}
118118
}
119119

120-
JSON::JSON(JSON &&other) : current_type{other.current_type} {
120+
JSON::JSON(JSON &&other) noexcept : current_type{other.current_type} {
121121
switch (other.current_type) {
122122
case Type::Boolean:
123123
this->data_boolean = other.data_boolean;
@@ -174,7 +174,7 @@ auto JSON::operator=(const JSON &other) -> JSON & {
174174
return *this;
175175
}
176176

177-
auto JSON::operator=(JSON &&other) -> JSON & {
177+
auto JSON::operator=(JSON &&other) noexcept -> JSON & {
178178
this->maybe_destruct_union();
179179
this->current_type = other.current_type;
180180
switch (other.current_type) {

src/core/jsonl/include/sourcemeta/core/jsonl_iterator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class SOURCEMETA_CORE_JSONL_EXPORT ConstJSONLIterator {
3939
std::uint64_t line{1};
4040
std::uint64_t column{0};
4141
auto parse_next() -> JSON;
42-
std::basic_istream<JSON::Char, JSON::CharTraits> *data;
42+
std::basic_istream<JSON::Char, JSON::CharTraits> *data{};
4343

4444
// Exporting symbols that depends on the standard C++ library is considered
4545
// safe.
@@ -50,7 +50,7 @@ class SOURCEMETA_CORE_JSONL_EXPORT ConstJSONLIterator {
5050
// Use PIMPL idiom to hide internal details, mainly
5151
// templated members, which are tricky to DLL-export.
5252
struct Internal;
53-
std::unique_ptr<Internal> internal;
53+
std::unique_ptr<Internal> internal{};
5454
#if defined(_MSC_VER)
5555
#pragma warning(default : 4251)
5656
#endif

0 commit comments

Comments
 (0)