From 43ea2fcc53656eb60c51b644696841050ee61b6d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 29 Dec 2017 12:58:11 -0800 Subject: [PATCH] Clean up type printer --- src/type_printer.cc | 162 +++++++++++++++----------------------------- 1 file changed, 53 insertions(+), 109 deletions(-) diff --git a/src/type_printer.cc b/src/type_printer.cc index b75ec580..66d56d9f 100644 --- a/src/type_printer.cc +++ b/src/type_printer.cc @@ -2,35 +2,22 @@ #include #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(CT.data[1]); -} -#endif - 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, const std::string& return_type) { // 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) - return -1; - // Find a first character where the return_type differs from the + return type_desc.size(); + // Find the first character where the return_type differs from the // function_type. In most cases this is the place where the function name // should be inserted. int ret = 0; @@ -46,7 +33,7 @@ int GetNameInsertingPosition(const std::string& type_desc, } else { // Otherwise return type is just a prefix of the function_type. // Skip any eventual spaces after the return type. - while (ret < int(type_desc.size()) && type_desc[ret] == ' ') + while (type_desc[ret] == ' ') ret++; } return ret; @@ -71,99 +58,56 @@ std::string GetFunctionSignature(IndexFile* db, num_args++; } - std::string type_desc; - int function_name_offset; -#if USE_CLANG_CXX - { - 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()); + std::string type_desc = ClangCursor(decl->cursor).get_type_description(); + int function_name_offset = GetNameInsertingPosition( + type_desc, ::ToString(clang_getTypeSpelling( + clang_getCursorResultType(decl->cursor)))); - T.print(OS, PP, "=^_^="); - type_desc = OS.str(); - function_name_offset = type_desc.find("=^_^="); - if (type_desc[function_name_offset + 5] != ')') - type_desc = type_desc.replace(function_name_offset, 5, ""); - else { - type_desc = type_desc.replace(function_name_offset, 6, ""); - for (int i = function_name_offset; i-- > 0; ) - if (type_desc[i] == '(') { - type_desc.erase(type_desc.begin() + i); - break; - } - 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"; + if (type_desc[function_name_offset] == '(') { + // Find positions to insert argument names. + // Argument name are before ',' or closing ')'. + num_args = 0; + 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; } - 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; - 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); + } else if (type_desc[i] == ',' && balance == 1) + args[num_args++].first = i; } - 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 { // type_desc is either a typedef, or some complicated type we cannot handle. // Append the function_name in this case. - if (type_desc.size() && - (type_desc.back() != ' ' && - type_desc.back() != '*' && - type_desc.back() != '&')) - type_desc.push_back(' '); - type_desc.append(function_name); + AddName(type_desc, function_name); } return type_desc;