mirror of
https://github.com/MaskRay/ccls.git
synced 2025-04-14 12:52:14 +00:00
Clean up type printer
This commit is contained in:
parent
daaf3a701b
commit
43ea2fcc53
@ -2,35 +2,22 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "loguru.hpp"
|
#include "loguru.hpp"
|
||||||
|
|
||||||
#if USE_CLANG_CXX
|
|
||||||
# include "CXTranslationUnit.h"
|
|
||||||
# include "clang/AST/Type.h"
|
|
||||||
# include "clang/AST/PrettyPrinter.h"
|
|
||||||
# include "clang/Frontend/ASTUnit.h"
|
|
||||||
# include "llvm/ADT/SmallString.h"
|
|
||||||
# include "llvm/Support/raw_ostream.h"
|
|
||||||
|
|
||||||
using namespace clang;
|
|
||||||
|
|
||||||
// Extracted from clang/tools/libclang/CXType.cpp
|
|
||||||
static inline QualType GetQualType(CXType CT) {
|
|
||||||
return QualType::getFromOpaquePtr(CT.data[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline CXTranslationUnit GetTU(CXType CT) {
|
|
||||||
return static_cast<CXTranslationUnit>(CT.data[1]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
void AddName(std::string& before, const std::string& name) {
|
||||||
|
if (before.size() &&
|
||||||
|
(before.back() != ' ' && before.back() != '*' && before.back() != '&'))
|
||||||
|
before.push_back(' ');
|
||||||
|
before.append(name);
|
||||||
|
}
|
||||||
|
|
||||||
int GetNameInsertingPosition(const std::string& type_desc,
|
int GetNameInsertingPosition(const std::string& type_desc,
|
||||||
const std::string& return_type) {
|
const std::string& return_type) {
|
||||||
// Check if type_desc contains an (.
|
// Check if type_desc contains an (.
|
||||||
if (type_desc.empty() || type_desc.size() <= return_type.size() ||
|
if (type_desc.size() <= return_type.size() ||
|
||||||
type_desc.find("(", 0) == std::string::npos)
|
type_desc.find("(", 0) == std::string::npos)
|
||||||
return -1;
|
return type_desc.size();
|
||||||
// Find a first character where the return_type differs from the
|
// Find the first character where the return_type differs from the
|
||||||
// function_type. In most cases this is the place where the function name
|
// function_type. In most cases this is the place where the function name
|
||||||
// should be inserted.
|
// should be inserted.
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -46,7 +33,7 @@ int GetNameInsertingPosition(const std::string& type_desc,
|
|||||||
} else {
|
} else {
|
||||||
// Otherwise return type is just a prefix of the function_type.
|
// Otherwise return type is just a prefix of the function_type.
|
||||||
// Skip any eventual spaces after the return type.
|
// Skip any eventual spaces after the return type.
|
||||||
while (ret < int(type_desc.size()) && type_desc[ret] == ' ')
|
while (type_desc[ret] == ' ')
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -71,99 +58,56 @@ std::string GetFunctionSignature(IndexFile* db,
|
|||||||
num_args++;
|
num_args++;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string type_desc;
|
std::string type_desc = ClangCursor(decl->cursor).get_type_description();
|
||||||
int function_name_offset;
|
int function_name_offset = GetNameInsertingPosition(
|
||||||
#if USE_CLANG_CXX
|
type_desc, ::ToString(clang_getTypeSpelling(
|
||||||
{
|
clang_getCursorResultType(decl->cursor))));
|
||||||
CXType CT = clang_getCursorType(decl->cursor);
|
|
||||||
QualType T = GetQualType(CT);
|
|
||||||
if (!T.isNull()) {
|
|
||||||
CXTranslationUnit TU = GetTU(CT);
|
|
||||||
SmallString<64> Str;
|
|
||||||
llvm::raw_svector_ostream OS(Str);
|
|
||||||
PrintingPolicy PP(cxtu::getASTUnit(TU)->getASTContext().getLangOpts());
|
|
||||||
|
|
||||||
T.print(OS, PP, "=^_^=");
|
if (type_desc[function_name_offset] == '(') {
|
||||||
type_desc = OS.str();
|
// Find positions to insert argument names.
|
||||||
function_name_offset = type_desc.find("=^_^=");
|
// Argument name are before ',' or closing ')'.
|
||||||
if (type_desc[function_name_offset + 5] != ')')
|
num_args = 0;
|
||||||
type_desc = type_desc.replace(function_name_offset, 5, "");
|
for (int balance = 0, i = function_name_offset;
|
||||||
else {
|
i < int(type_desc.size()) && num_args < int(args.size()); i++) {
|
||||||
type_desc = type_desc.replace(function_name_offset, 6, "");
|
if (type_desc[i] == '(' || type_desc[i] == '[')
|
||||||
for (int i = function_name_offset; i-- > 0; )
|
balance++;
|
||||||
if (type_desc[i] == '(') {
|
else if (type_desc[i] == ')' || type_desc[i] == ']') {
|
||||||
type_desc.erase(type_desc.begin() + i);
|
if (--balance <= 0) {
|
||||||
break;
|
args[num_args].first = i;
|
||||||
}
|
|
||||||
function_name_offset--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
type_desc = ClangCursor(decl->cursor).get_type_description();
|
|
||||||
std::string return_type = ::ToString(
|
|
||||||
clang_getTypeSpelling(clang_getCursorResultType(decl->cursor)));
|
|
||||||
function_name_offset = GetNameInsertingPosition(type_desc, return_type);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (function_name_offset >= 0 && type_desc[function_name_offset] == '(') {
|
|
||||||
if (num_args > 0) {
|
|
||||||
// Find positions to insert argument names.
|
|
||||||
// Last argument name is before ')'
|
|
||||||
num_args = 0;
|
|
||||||
// Other argument names come before ','
|
|
||||||
for (int balance = 0, i = function_name_offset;
|
|
||||||
i < int(type_desc.size()) && num_args < int(args.size()); i++) {
|
|
||||||
if (type_desc[i] == '(' || type_desc[i] == '[')
|
|
||||||
balance++;
|
|
||||||
else if (type_desc[i] == ')' || type_desc[i] == ']') {
|
|
||||||
if (--balance <= 0) {
|
|
||||||
args[num_args].first = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (type_desc[i] == ',' && balance == 1)
|
|
||||||
args[num_args++].first = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second pass: Insert argument names before each comma.
|
|
||||||
int i = 0;
|
|
||||||
std::string type_desc_with_names;
|
|
||||||
for (auto& arg : args) {
|
|
||||||
if (arg.first < 0) {
|
|
||||||
LOG_S(ERROR)
|
|
||||||
<< "When adding argument names to '" << type_desc
|
|
||||||
<< "', failed to detect positions to insert argument names";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (arg.second.empty())
|
} else if (type_desc[i] == ',' && balance == 1)
|
||||||
continue;
|
args[num_args++].first = i;
|
||||||
// TODO Use inside-out syntax. Note, clang/lib/AST/TypePrinter.cpp does
|
|
||||||
// not print arg names.
|
|
||||||
type_desc_with_names.insert(type_desc_with_names.end(), &type_desc[i],
|
|
||||||
&type_desc[arg.first]);
|
|
||||||
i = arg.first;
|
|
||||||
if (type_desc_with_names.size() &&
|
|
||||||
(type_desc_with_names.back() != ' ' &&
|
|
||||||
type_desc_with_names.back() != '*' &&
|
|
||||||
type_desc_with_names.back() != '&'))
|
|
||||||
type_desc_with_names.push_back(' ');
|
|
||||||
type_desc_with_names.append(arg.second);
|
|
||||||
}
|
|
||||||
type_desc_with_names.insert(type_desc_with_names.end(),
|
|
||||||
type_desc.begin() + i, type_desc.end());
|
|
||||||
type_desc = std::move(type_desc_with_names);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type_desc.insert(function_name_offset, function_name);
|
// Second pass: insert argument names before each comma and closing paren.
|
||||||
|
int i = function_name_offset;
|
||||||
|
std::string type_desc_with_names(type_desc.begin(),
|
||||||
|
type_desc.begin() + i);
|
||||||
|
type_desc_with_names.append(function_name);
|
||||||
|
for (auto& arg : args) {
|
||||||
|
if (arg.first < 0) {
|
||||||
|
LOG_S(ERROR)
|
||||||
|
<< "When adding argument names to '" << type_desc
|
||||||
|
<< "', failed to detect positions to insert argument names";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (arg.second.empty())
|
||||||
|
continue;
|
||||||
|
// TODO Use inside-out syntax. Note, clang/lib/AST/TypePrinter.cpp does
|
||||||
|
// not print arg names.
|
||||||
|
type_desc_with_names.insert(type_desc_with_names.end(), &type_desc[i],
|
||||||
|
&type_desc[arg.first]);
|
||||||
|
i = arg.first;
|
||||||
|
AddName(type_desc_with_names, arg.second);
|
||||||
|
}
|
||||||
|
type_desc_with_names.insert(type_desc_with_names.end(),
|
||||||
|
type_desc.begin() + i, type_desc.end());
|
||||||
|
type_desc = std::move(type_desc_with_names);
|
||||||
} else {
|
} else {
|
||||||
// type_desc is either a typedef, or some complicated type we cannot handle.
|
// type_desc is either a typedef, or some complicated type we cannot handle.
|
||||||
// Append the function_name in this case.
|
// Append the function_name in this case.
|
||||||
if (type_desc.size() &&
|
AddName(type_desc, function_name);
|
||||||
(type_desc.back() != ' ' &&
|
|
||||||
type_desc.back() != '*' &&
|
|
||||||
type_desc.back() != '&'))
|
|
||||||
type_desc.push_back(' ');
|
|
||||||
type_desc.append(function_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return type_desc;
|
return type_desc;
|
||||||
|
Loading…
Reference in New Issue
Block a user