From: Douglas Gregor Date: Sat, 2 Oct 2010 22:49:11 +0000 (+0000) Subject: Introduce a new libclang function, clang_getCursorDisplayName(), which X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=358559d8d7b458c5f64941842383a16e61f0828d;p=clang Introduce a new libclang function, clang_getCursorDisplayName(), which produces a simple "display" name that captures the arguments/parameters for a function, function template, class template, or class template specialization. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@115428 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index f78df52d83..707c0df201 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -1884,6 +1884,15 @@ CINDEX_LINKAGE CXString clang_constructUSR_ObjCProperty(const char *property, */ CINDEX_LINKAGE CXString clang_getCursorSpelling(CXCursor); +/** + * \brief Retrieve the display name for the entity referenced by this cursor. + * + * The display name contains extra information that helps identify the cursor, + * such as the parameters of a function or template or the arguments of a + * class template specialization. + */ +CINDEX_LINKAGE CXString clang_getCursorDisplayName(CXCursor); + /** \brief For a cursor that is a reference, retrieve a cursor representing the * entity that it references. * diff --git a/test/Index/print-display-names.cpp b/test/Index/print-display-names.cpp new file mode 100644 index 0000000000..94fe4665e6 --- /dev/null +++ b/test/Index/print-display-names.cpp @@ -0,0 +1,20 @@ +template +class ClassTmpl { }; + +typedef int Integer; + +template class ClassTmpl; + +void f(ClassTmpl p); + +template +void g(ClassTmpl); + +template<> void g(ClassTmpl); + +// RUN: c-index-test -test-load-source all-display %s | FileCheck %s +// CHECK: print-display-names.cpp:2:7: ClassTemplate=ClassTmpl:2:7 +// CHECK: print-display-names.cpp:6:16: ClassDecl=ClassTmpl:6:16 (Definition) +// CHECK: print-display-names.cpp:8:6: FunctionDecl=f(ClassTmpl):8:6 +// CHECK: print-display-names.cpp:11:6: FunctionTemplate=g(ClassTmpl):11:6 +// CHECK: print-display-names.cpp:13:17: FunctionDecl=g<>(ClassTmpl):13:17 [Specialization of g:11:6] diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index f83162295d..9c5a67d304 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -156,6 +156,8 @@ int parse_remapped_files(int argc, const char **argv, int start_arg, /* Pretty-printing. */ /******************************************************************************/ +int want_display_name = 0; + static void PrintCursor(CXCursor Cursor) { if (clang_isInvalid(Cursor.kind)) { CXString ks = clang_getCursorKindSpelling(Cursor.kind); @@ -171,7 +173,8 @@ static void PrintCursor(CXCursor Cursor) { unsigned num_overridden; ks = clang_getCursorKindSpelling(Cursor.kind); - string = clang_getCursorSpelling(Cursor); + string = want_display_name? clang_getCursorDisplayName(Cursor) + : clang_getCursorSpelling(Cursor); printf("%s=%s", clang_getCString(ks), clang_getCString(string)); clang_disposeString(ks); @@ -604,6 +607,11 @@ static int perform_test_load(CXIndex Idx, CXTranslationUnit TU, /* Perform some simple filtering. */ if (!strcmp(filter, "all") || !strcmp(filter, "local")) ck = NULL; + else if (!strcmp(filter, "all-display") || + !strcmp(filter, "local-display")) { + ck = NULL; + want_display_name = 1; + } else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0; else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl; else if (!strcmp(filter, "interface")) K = CXCursor_ObjCInterfaceDecl; @@ -661,7 +669,8 @@ int perform_test_load_source(int argc, const char **argv, int result; Idx = clang_createIndex(/* excludeDeclsFromPCH */ - !strcmp(filter, "local") ? 1 : 0, + (!strcmp(filter, "local") || + !strcmp(filter, "local-display"))? 1 : 0, /* displayDiagnosics=*/1); if (UseExternalASTs && strlen(UseExternalASTs)) diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 4f551b4190..57367dd159 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -33,6 +33,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Timer.h" #include "llvm/System/Mutex.h" #include "llvm/System/Program.h" @@ -2705,6 +2706,90 @@ CXString clang_getCursorSpelling(CXCursor C) { return createCXString(""); } +CXString clang_getCursorDisplayName(CXCursor C) { + if (!clang_isDeclaration(C.kind)) + return clang_getCursorSpelling(C); + + Decl *D = getCursorDecl(C); + if (!D) + return createCXString(""); + + PrintingPolicy &Policy = getCursorContext(C).PrintingPolicy; + if (FunctionTemplateDecl *FunTmpl = dyn_cast(D)) + D = FunTmpl->getTemplatedDecl(); + + if (FunctionDecl *Function = dyn_cast(D)) { + llvm::SmallString<64> Str; + llvm::raw_svector_ostream OS(Str); + OS << Function->getNameAsString(); + if (Function->getPrimaryTemplate()) + OS << "<>"; + OS << "("; + for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) { + if (I) + OS << ", "; + OS << Function->getParamDecl(I)->getType().getAsString(Policy); + } + + if (Function->isVariadic()) { + if (Function->getNumParams()) + OS << ", "; + OS << "..."; + } + OS << ")"; + return createCXString(OS.str()); + } + + if (ClassTemplateDecl *ClassTemplate = dyn_cast(D)) { + llvm::SmallString<64> Str; + llvm::raw_svector_ostream OS(Str); + OS << ClassTemplate->getNameAsString(); + OS << "<"; + TemplateParameterList *Params = ClassTemplate->getTemplateParameters(); + for (unsigned I = 0, N = Params->size(); I != N; ++I) { + if (I) + OS << ", "; + + NamedDecl *Param = Params->getParam(I); + if (Param->getIdentifier()) { + OS << Param->getIdentifier()->getName(); + continue; + } + + // There is no parameter name, which makes this tricky. Try to come up + // with something useful that isn't too long. + if (TemplateTypeParmDecl *TTP = dyn_cast(Param)) + OS << (TTP->wasDeclaredWithTypename()? "typename" : "class"); + else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast(Param)) + OS << NTTP->getType().getAsString(Policy); + else + OS << "template<...> class"; + } + + OS << ">"; + return createCXString(OS.str()); + } + + if (ClassTemplateSpecializationDecl *ClassSpec + = dyn_cast(D)) { + // If the type was explicitly written, use that. + if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten()) + return createCXString(TSInfo->getType().getAsString(Policy)); + + llvm::SmallString<64> Str; + llvm::raw_svector_ostream OS(Str); + OS << ClassSpec->getNameAsString(); + OS << TemplateSpecializationType::PrintTemplateArgumentList( + ClassSpec->getTemplateArgs().getFlatArgumentList(), + ClassSpec->getTemplateArgs().flat_size(), + Policy); + return createCXString(OS.str()); + } + + return clang_getCursorSpelling(C); +} + CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { switch (Kind) { case CXCursor_FunctionDecl: diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports index d2e246e7e8..0682a58e6b 100644 --- a/tools/libclang/libclang.darwin.exports +++ b/tools/libclang/libclang.darwin.exports @@ -42,6 +42,7 @@ _clang_getCompletionPriority _clang_getCursor _clang_getCursorAvailability _clang_getCursorDefinition +_clang_getCursorDisplayName _clang_getCursorExtent _clang_getCursorKind _clang_getCursorKindSpelling diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index d8ae1e47b3..e7e4f8be14 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -42,6 +42,7 @@ clang_getCompletionPriority clang_getCursor clang_getCursorAvailability clang_getCursorDefinition +clang_getCursorDisplayName clang_getCursorExtent clang_getCursorKind clang_getCursorKindSpelling