Files
clang-uml/src/cx/type.h
2021-03-03 23:24:25 +01:00

229 lines
5.6 KiB
C++

/**
* src/cx/type.h
*
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <clang-c/CXCompilationDatabase.h>
#include <clang-c/Index.h>
#include <spdlog/spdlog.h>
#include "uml/class_diagram_model.h"
#include "util/util.h"
namespace clanguml {
namespace cx {
namespace detail {
std::string to_string(CXString &&cxs)
{
std::string r{clang_getCString(cxs)};
clang_disposeString(cxs);
return r;
}
}
using detail::to_string;
class type {
public:
type(CXType &&t)
: m_type{std::move(t)}
{
}
~type() = default;
std::string spelling() const
{
return to_string(clang_getTypeSpelling(m_type));
}
bool operator==(const type &b) const
{
return clang_equalTypes(m_type, b.get());
}
type canonical() const { return {clang_getCanonicalType(m_type)}; }
bool is_const_qualified() const
{
return clang_isConstQualifiedType(m_type);
}
bool is_volatile_qualified() const
{
return clang_isVolatileQualifiedType(m_type);
}
bool is_restricted_qualified() const
{
return clang_isRestrictQualifiedType(m_type);
}
std::string typedef_name() const
{
return to_string(clang_getTypedefName(m_type));
}
type pointee_type() const { return {clang_getPointeeType(m_type)}; }
/*
*cursor type_declaration() const
*{
* return {clang_getTypeDeclaration(m_type)};
*}
*/
/*
*std::string type_kind_spelling() const
*{
* return clang_getTypeKindSpelling(kind());
*}
*/
CXTypeKind kind() const { return m_type.kind; }
std::string kind_spelling()
{
return to_string(clang_getTypeKindSpelling(m_type.kind));
}
CXCallingConv calling_convention() const
{
return clang_getFunctionTypeCallingConv(m_type);
}
type result_type() const { return clang_getResultType(m_type); }
int exception_specification_type() const
{
return clang_getExceptionSpecificationType(m_type);
}
int argument_type_count() const { return clang_getNumArgTypes(m_type); }
type argument_type(int i) const { return {clang_getArgType(m_type, i)}; }
bool is_function_variadic() const
{
return clang_isFunctionTypeVariadic(m_type);
}
bool is_pod() const { return clang_isPODType(m_type); }
bool is_pointer() const { return kind() == CXType_Pointer; }
bool is_record() const { return kind() == CXType_Record; }
/**
* @brief Return final referenced type.
*
* This method allows to extract a final type in case a type consists of a
* single or multiple pointers or references.
*
* @return Referenced type.
*/
type referenced() const
{
auto t = *this;
while (t.is_pointer() || t.is_reference()) {
t = t.pointee_type();
}
return t;
}
bool is_reference() const
{
return (kind() == CXType_LValueReference) ||
(kind() == CXType_RValueReference);
}
bool is_array() const { return clang_getArraySize(m_type) > -1; }
type array_type() const { return {clang_getArrayElementType(m_type)}; }
bool is_relationship() const
{
return is_pointer() || is_record() || is_reference() || !is_pod() ||
is_array() || (spelling().find("std::array") == 0);
}
type element_type() const { return clang_getElementType(m_type); }
long long element_count() const { return clang_getNumElements(m_type); }
type array_element_type() const
{
return clang_getArrayElementType(m_type);
}
type named_type() const { return clang_Type_getNamedType(m_type); }
CXTypeNullabilityKind nullability() const
{
return clang_Type_getNullability(m_type);
}
type class_type() const { return clang_Type_getClassType(m_type); }
long long size_of() const { return clang_Type_getSizeOf(m_type); }
type modified_type() const { return clang_Type_getModifiedType(m_type); }
type value_type() const { return clang_Type_getValueType(m_type); }
bool is_template() const { return template_arguments_count() > 0; }
int template_arguments_count() const
{
return clang_Type_getNumTemplateArguments(m_type);
}
type template_argument_type(int i) const
{
return clang_Type_getTemplateArgumentAsType(m_type, i);
}
const CXType &get() const { return m_type; }
CXRefQualifierKind cxxref_qualifier() const
{
return clang_Type_getCXXRefQualifier(m_type);
}
std::string unqualified() const
{
auto toks = clanguml::util::split(spelling(), " ");
const std::vector<std::string> qualifiers = {
"static", "const", "volatile", "register", "mutable"};
toks.erase(toks.begin(),
std::find_if(
toks.begin(), toks.end(), [&qualifiers](const auto &t) {
return std::count(
qualifiers.begin(), qualifiers.end(), t) == 0;
}));
return fmt::format("{}", fmt::join(toks, " "));
}
private:
CXType m_type;
};
}
}