Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions include/mrdocs/Metadata/Type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,185 @@ struct TypeInfoCommonBase : TypeInfo
}
};

/** Categorically describes a fundamental type.

@see https://en.cppreference.com/w/cpp/language/types
*/
enum class FundamentalTypeKind
{
// void
Void,
// std::nullptr_t
Nullptr,
// bool
Bool,
// char
Char,
// signed char
SignedChar,
// unsigned char
UnsignedChar,
// char8_t
Char8,
// char16_t
Char16,
// char32_t
Char32,
// wchar_t
WChar,
// short / short int / signed short / signed short int
Short,
// unsigned short / unsigned short int
UnsignedShort,
// int / signed / signed int
Int,
// unsigned / unsigned int
UnsignedInt,
// long / long int / signed long / signed long int
Long,
// unsigned long / unsigned long int
UnsignedLong,
// long long / long long int / signed long long / signed long long int
LongLong,
// unsigned long long / unsigned long long int
UnsignedLongLong,
// float
Float,
// double
Double,
// long double
LongDouble
};

/** Convert a FundamentalTypeKind to a string.

This function converts a FundamentalTypeKind to
the shortest canonical string representing the type.

@return The string representation of the kind
*/
MRDOCS_DECL
std::string_view
toString(FundamentalTypeKind kind) noexcept;

/** Convert a string to a FundamentalTypeKind.

This function converts a string to a FundamentalTypeKind.

All variations of the type specifiers are supported.

However, the "long long" specifier cannot be split
into two separate specifiers.

@return true if the string was successfully converted
*/
MRDOCS_DECL
bool
fromString(std::string_view str, FundamentalTypeKind& kind) noexcept;

/** Apply the "long" specifier to the type

If applying "long" the specifier is a valid operation
the function changes the type and returns true.

For instance, applying "long" to
`FundamentalTypeKind::Int` ("int") results in
`FundamentalTypeKind::Long` ("long int").

@param[in/out] kind The type to modify
@return Whether the operation was successful
*/
MRDOCS_DECL
bool
makeLong(FundamentalTypeKind& kind) noexcept;

/** Apply the "short" specifier to the type

If applying "short" the specifier is a valid operation
the function changes the type and returns true.

For instance, applying "short" to
`FundamentalTypeKind::Int` ("int") results in
`FundamentalTypeKind::Short` ("short int").

@param[in/out] kind The type to modify
@return Whether the operation was successful
*/
MRDOCS_DECL
bool
makeShort(FundamentalTypeKind& kind) noexcept;

/** Apply the "signed" specifier to the type

If applying the "signed" specifier is a valid operation
the function changes the type and returns true.

For instance, applying "signed" to
`FundamentalTypeKind::Char` ("char") results in
`FundamentalTypeKind::SignedChar` ("signed char").

It also returns true if applying the "signed" specifier
is a valid operation but doesn't affect the
type.

For instance, applying "signed" to
`FundamentalTypeKind::Int` ("int") doesn't change the type
but returns `true`, even though `FundamentalTypeKind::Int`
could be declared as "int" or "signed" and multiple
"signed" specifiers are not allowed.

@param[in/out] kind The type to modify
@return Whether the operation was successful
*/
MRDOCS_DECL
bool
makeSigned(FundamentalTypeKind& kind) noexcept;

/** Apply the "unsigned" specifier to the type

If applying the "unsigned" specifier is a valid operation
the function changes the type and returns true.

For instance, applying "unsigned" to
`FundamentalTypeKind::Char` ("char") results in
`FundamentalTypeKind::UnsignedChar` ("unsigned char")
and applying "unsigned" to
`FundamentalTypeKind::Int` ("int") results in
`FundamentalTypeKind::UnsignedInt` ("unsigned int").

@param[in/out] kind The type to modify
@return Whether the operation was successful
*/
MRDOCS_DECL
bool
makeUnsigned(FundamentalTypeKind& kind) noexcept;

/** Apply the "char" specifier to the type

If applying the "char" specifier to a type
that might have been declared only with "signed/unsigned"
or "short/long" specifiers, the function changes the type
and returns true.

For instance, applying "char" to
`FundamentalTypeKind::Int` ("int", which could be declared
as "signed") results in
`FundamentalTypeKind::SignedChar` ("signed char").

@param[in/out] kind The type to modify
@return Whether the operation was successful
*/
MRDOCS_DECL
bool
makeChar(FundamentalTypeKind& kind) noexcept;

struct NamedTypeInfo final
: TypeInfoCommonBase<TypeKind::Named>
{
Polymorphic<NameInfo> Name;

std::optional<FundamentalTypeKind> FundamentalType;

std::strong_ordering
operator<=>(NamedTypeInfo const& other) const;
};
Expand Down
60 changes: 55 additions & 5 deletions include/mrdocs/Support/Algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ requires std::equality_comparable_with<El, std::ranges::range_value_t<Range>>
bool
contains(Range const& range, El const& el)
{
return std::find(range.begin(), range.end(), el) != range.end();
return std::find(
std::ranges::begin(range),
std::ranges::end(range), el) != std::ranges::end(range);
}

// A second overload where the range is an initializer list
Expand All @@ -41,7 +43,9 @@ requires std::equality_comparable_with<T, U>
bool
contains(std::initializer_list<T> const& range, U const& el)
{
return std::find(range.begin(), range.end(), el) != range.end();
return std::find(
std::ranges::begin(range),
std::ranges::end(range), el) != std::ranges::end(range);
}

/** Determine if a range contains any of the specified elements.
Expand All @@ -54,15 +58,16 @@ requires std::equality_comparable_with<std::ranges::range_value_t<Els>, std::ran
bool
contains_any(Range const& range, Els const& els)
{
return std::ranges::find_first_of(range, els) != range.end();
return std::ranges::find_first_of(range, els) != std::ranges::end(range);
}

/// @copydoc contains_any(Range const&, Els const&)
template <std::ranges::range Range, class El>
requires std::equality_comparable_with<El, std::ranges::range_value_t<Range>>
bool
contains_any(Range const& range, std::initializer_list<El> const& els)
{
return std::ranges::find_first_of(range, els) != range.end();
return std::ranges::find_first_of(range, els) != std::ranges::end(range);
}

/** Determine if a range contains at least N instances of the specified element.
Expand Down Expand Up @@ -90,10 +95,55 @@ contains_n(Range const& range, El const& el, std::size_t n)
return false;
}

/** Determine if a range contains at least N instances of any of the specified elements.
@param range The range to search.
@param els The elements to search for.
@param n The number of instances to search for.
@return True if the element is found, false otherwise.
*/
template <std::ranges::range Range, std::ranges::range Els>
requires std::equality_comparable_with<std::ranges::range_value_t<Els>, std::ranges::range_value_t<Range>>
bool
contains_n_any(Range const& range, Els const& els, std::size_t n)
{
for (auto const& item : range)
{
if (contains(els, item))
{
--n;
if (n == 0)
{
return true;
}
}
}
return false;
}

/// @copydoc contains_n_any(Range const&, Els const&, std::size_t)
template <std::ranges::range Range, class El>
requires std::equality_comparable_with<El, std::ranges::range_value_t<Range>>
bool
contains_n_any(Range const& range, std::initializer_list<El> const& els, std::size_t n)
{
for (auto const& item : range)
{
if (contains(els, item))
{
--n;
if (n == 0)
{
return true;
}
}
}
return false;
}

/** Find the last element in a range that matches an element in the specified range.
@param range The range to search.
@param els The elements to search for.
@return An iterator to the last element found, or range.end() if not found.
@return An iterator to the last element found, or std::ranges::end(range) if not found.
*/
template <std::ranges::range Range, std::ranges::range Els>
requires std::equality_comparable_with<std::ranges::range_value_t<Els>, std::ranges::range_value_t<Range>>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/AST/ClangHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ decayToPrimaryTemplate(Decl const* D)
SmallString<128> symbolName;
llvm::raw_svector_ostream os(symbolName);
D->print(os);
report::debug("symbolName: ", std::string_view(os.str()));
report::trace("symbolName: ", std::string_view(os.str()));
#endif

Decl const* ID = D;
Expand Down
59 changes: 58 additions & 1 deletion src/lib/AST/ClangHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ toFunctionClass(Decl::Kind const kind)
*/
inline
AutoKind
convertToAutoKind(AutoTypeKeyword const kind)
toAutoKind(AutoTypeKeyword const kind)
{
switch(kind)
{
Expand All @@ -514,6 +514,63 @@ convertToAutoKind(AutoTypeKeyword const kind)
}
}

/** Convert a Clang AutoTypeKeyword into a MrDocs AutoKind
*/
inline
std::optional<FundamentalTypeKind>
toFundamentalTypeKind(BuiltinType::Kind const kind)
{
switch(kind)
{
case BuiltinType::Kind::Void:
return FundamentalTypeKind::Void;
case BuiltinType::Kind::NullPtr:
return FundamentalTypeKind::Nullptr;
case BuiltinType::Kind::Bool:
return FundamentalTypeKind::Bool;
case BuiltinType::Kind::Char_U:
case BuiltinType::Kind::Char_S:
return FundamentalTypeKind::Char;
case BuiltinType::Kind::SChar:
return FundamentalTypeKind::SignedChar;
case BuiltinType::Kind::UChar:
return FundamentalTypeKind::UnsignedChar;
case BuiltinType::Kind::Char8:
return FundamentalTypeKind::Char8;
case BuiltinType::Kind::Char16:
return FundamentalTypeKind::Char16;
case BuiltinType::Kind::Char32:
return FundamentalTypeKind::Char32;
case BuiltinType::Kind::WChar_S:
case BuiltinType::Kind::WChar_U:
return FundamentalTypeKind::WChar;
case BuiltinType::Kind::Short:
return FundamentalTypeKind::Short;
case BuiltinType::Kind::UShort:
return FundamentalTypeKind::UnsignedShort;
case BuiltinType::Kind::Int:
return FundamentalTypeKind::Int;
case BuiltinType::Kind::UInt:
return FundamentalTypeKind::UnsignedInt;
case BuiltinType::Kind::Long:
return FundamentalTypeKind::Long;
case BuiltinType::Kind::ULong:
return FundamentalTypeKind::UnsignedLong;
case BuiltinType::Kind::LongLong:
return FundamentalTypeKind::LongLong;
case BuiltinType::Kind::ULongLong:
return FundamentalTypeKind::UnsignedLongLong;
case BuiltinType::Kind::Float:
return FundamentalTypeKind::Float;
case BuiltinType::Kind::Double:
return FundamentalTypeKind::Double;
case BuiltinType::Kind::LongDouble:
return FundamentalTypeKind::LongDouble;
default:
return std::nullopt;
}
}

// ----------------------------------------------------------------

/** Visit a Decl and call the appropriate visitor function.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/AST/ParseJavadoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ namespace detail {
#define MRDOCS_COMMENT_TRACE(D, C) \
SmallString<1024> MRDOCS_COMMENT_TRACE_UNIQUE_NAME; \
::detail::dumpCommentContent(D, C, MRDOCS_COMMENT_TRACE_UNIQUE_NAME); \
report::debug("{}", std::string_view(MRDOCS_COMMENT_TRACE_UNIQUE_NAME.str()))
report::trace("{}", std::string_view(MRDOCS_COMMENT_TRACE_UNIQUE_NAME.str()))
#endif


Expand Down
Loading