summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@qt.io>2018-04-17 10:03:06 +0200
committerNikolai Kosjar <nikolai.kosjar@qt.io>2018-04-19 12:43:29 +0000
commit2408485cceff289e018df684683a22f301b04c71 (patch)
tree16fb21dc34baf454c10264661a533cd016f9f687
parentae67eb7103b782deb5dda308e19d6f8e68e31ae2 (diff)
[backported/clang-7][libclang] Add PrintingPolicy for pretty printing declarations
------------------------------------------------------------------------- * Improves pretty printing for Qt Creator's tooltips. ------------------------------------------------------------------------- Summary: Introduce clang_getCursorPrettyPrinted() for pretty printing declarations. Expose also PrintingPolicy, so the user gets more fine-grained control of the entities being printed. The already existing clang_getCursorDisplayName() is pretty limited - for example, it does not handle return types, parameter names or default arguments for function declarations. Addressing these issues in clang_getCursorDisplayName() would mean to duplicate existing code (e.g. clang::DeclPrinter), so rather expose new API to access the existing functionality. Reviewed By: jbcoe Subscribers: cfe-commits Tags: #clang Patch by nik (Nikolai Kosjar) Differential Revision: https://reviews.llvm.org/D39903 Change-Id: I509a01bb5a1e4e1d899c2725f50ed78e482c075f Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
-rw-r--r--include/clang-c/Index.h85
-rw-r--r--test/Index/print-display-names.cpp23
-rw-r--r--tools/c-index-test/c-index-test.c104
-rw-r--r--tools/libclang/CIndex.cpp191
-rw-r--r--tools/libclang/libclang.exports5
-rw-r--r--unittests/libclang/LibclangTest.cpp32
6 files changed, 428 insertions, 12 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index ee522f43f7..0179058944 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -34,6 +34,7 @@
#define CINDEX_VERSION_MAJOR 0
#define CINDEX_VERSION_MINOR 45
#define CINDEX_VERSION_HAS_ISINVALIDECL_BACKPORTED
+#define CINDEX_VERSION_HAS_PRETTYDECL_BACKPORTED
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -4093,6 +4094,90 @@ CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
unsigned options);
/**
+ * \brief Opaque pointer representing a policy that controls pretty printing
+ * for \c clang_getCursorPrettyPrinted.
+ */
+typedef void *CXPrintingPolicy;
+
+/**
+ * \brief Properties for the printing policy.
+ *
+ * See \c clang::PrintingPolicy for more information.
+ */
+enum CXPrintingPolicyProperty {
+ CXPrintingPolicy_Indentation,
+ CXPrintingPolicy_SuppressSpecifiers,
+ CXPrintingPolicy_SuppressTagKeyword,
+ CXPrintingPolicy_IncludeTagDefinition,
+ CXPrintingPolicy_SuppressScope,
+ CXPrintingPolicy_SuppressUnwrittenScope,
+ CXPrintingPolicy_SuppressInitializers,
+ CXPrintingPolicy_ConstantArraySizeAsWritten,
+ CXPrintingPolicy_AnonymousTagLocations,
+ CXPrintingPolicy_SuppressStrongLifetime,
+ CXPrintingPolicy_SuppressLifetimeQualifiers,
+ CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors,
+ CXPrintingPolicy_Bool,
+ CXPrintingPolicy_Restrict,
+ CXPrintingPolicy_Alignof,
+ CXPrintingPolicy_UnderscoreAlignof,
+ CXPrintingPolicy_UseVoidForZeroParams,
+ CXPrintingPolicy_TerseOutput,
+ CXPrintingPolicy_PolishForDeclaration,
+ CXPrintingPolicy_Half,
+ CXPrintingPolicy_MSWChar,
+ CXPrintingPolicy_IncludeNewlines,
+ CXPrintingPolicy_MSVCFormatting,
+ CXPrintingPolicy_ConstantsAsWritten, /* Ops, not yet there in clang 5.0 and we do not need it. */
+ CXPrintingPolicy_SuppressImplicitBase, /* Ops, not yet there in clang 5.0 and we do not need it. */
+ CXPrintingPolicy_FullyQualifiedName,
+
+ CXPrintingPolicy_LastProperty = CXPrintingPolicy_FullyQualifiedName
+};
+
+/**
+ * \brief Get a property value for the given printing policy.
+ */
+CINDEX_LINKAGE unsigned
+clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
+ enum CXPrintingPolicyProperty Property);
+
+/**
+ * \brief Set a property value for the given printing policy.
+ */
+CINDEX_LINKAGE void
+clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
+ enum CXPrintingPolicyProperty Property,
+ unsigned Value);
+
+/**
+ * \brief Retrieve the default policy for the cursor.
+ *
+ * The policy should be released after use with \c
+ * clang_PrintingPolicy_dispose.
+ */
+CINDEX_LINKAGE CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor);
+
+/**
+ * \brief Release a printing policy.
+ */
+CINDEX_LINKAGE void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy);
+
+/**
+ * \brief Pretty print declarations.
+ *
+ * \param Cursor The cursor representing a declaration.
+ *
+ * \param Policy The policy to control the entities being printed. If
+ * NULL, a default policy is used.
+ *
+ * \returns The pretty printed declaration or the empty string for
+ * other cursors.
+ */
+CINDEX_LINKAGE CXString clang_getCursorPrettyPrinted(CXCursor Cursor,
+ CXPrintingPolicy Policy);
+
+/**
* \brief Retrieve the display name for the entity referenced by this cursor.
*
* The display name contains extra information that helps identify the cursor,
diff --git a/test/Index/print-display-names.cpp b/test/Index/print-display-names.cpp
index 94fe4665e6..5ba10e43bc 100644
--- a/test/Index/print-display-names.cpp
+++ b/test/Index/print-display-names.cpp
@@ -12,9 +12,20 @@ void g(ClassTmpl<T, T>);
template<> void g<int>(ClassTmpl<int, int>);
-// RUN: c-index-test -test-load-source all-display %s | FileCheck %s
-// CHECK: print-display-names.cpp:2:7: ClassTemplate=ClassTmpl<T, typename>:2:7
-// CHECK: print-display-names.cpp:6:16: ClassDecl=ClassTmpl<Integer, Integer>:6:16 (Definition)
-// CHECK: print-display-names.cpp:8:6: FunctionDecl=f(ClassTmpl<float, Integer>):8:6
-// CHECK: print-display-names.cpp:11:6: FunctionTemplate=g(ClassTmpl<T, T>):11:6
-// CHECK: print-display-names.cpp:13:17: FunctionDecl=g<>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6]
+// RUN: c-index-test -test-load-source all-display %s | FileCheck %s --check-prefix=DISPLAY_NAME
+// DISPLAY_NAME: print-display-names.cpp:2:7: ClassTemplate=ClassTmpl<T, typename>:2:7
+// DISPLAY_NAME: print-display-names.cpp:6:16: ClassDecl=ClassTmpl<Integer, Integer>:6:16 (Definition)
+// DISPLAY_NAME: print-display-names.cpp:8:6: FunctionDecl=f(ClassTmpl<float, Integer>):8:6
+// DISPLAY_NAME: print-display-names.cpp:11:6: FunctionTemplate=g(ClassTmpl<T, T>):11:6
+// DISPLAY_NAME: print-display-names.cpp:13:17: FunctionDecl=g<>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6]
+
+// RUN: env CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT=1 c-index-test -test-load-source all-pretty %s | FileCheck %s --check-prefix=PRETTY
+// PRETTY: print-display-names.cpp:2:7: ClassTemplate=template <typename T, typename > class ClassTmpl {}:2:7 (Definition) Extent=[1:1 - 2:20]
+// PRETTY: print-display-names.cpp:4:13: TypedefDecl=typedef int Integer:4:13 (Definition) Extent=[4:1 - 4:20]
+// PRETTY: print-display-names.cpp:6:16: ClassDecl=template<> class ClassTmpl<int, int> {}:6:16 (Definition) [Specialization of ClassTmpl:2:7] Extent=[6:1 - 6:43]
+// PRETTY: print-display-names.cpp:8:6: FunctionDecl=void f(ClassTmpl<float, Integer> p):8:6 Extent=[8:1 - 8:36]
+// PRETTY: print-display-names.cpp:8:34: ParmDecl=ClassTmpl<float, Integer> p:8:34 (Definition) Extent=[8:8 - 8:35]
+// PRETTY: print-display-names.cpp:11:6: FunctionTemplate=template <typename T> void g(ClassTmpl<T, T>):11:6 Extent=[10:1 - 11:24]
+// PRETTY: print-display-names.cpp:11:23: ParmDecl=ClassTmpl<T, T>:11:23 (Definition) Extent=[11:8 - 11:23]
+// PRETTY: print-display-names.cpp:13:17: FunctionDecl=template<> void g<int>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6] [Template arg 0: kind: 1, type: int] Extent=[13:1 - 13:44]
+// PRETTY: print-display-names.cpp:13:43: ParmDecl=ClassTmpl<int, int>:13:43 (Definition) Extent=[13:24 - 13:43]
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index c5e345ef6a..e9902efffb 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -86,6 +86,69 @@ static unsigned getDefaultParsingOptions() {
return options;
}
+static void ModifyPrintingPolicyAccordingToEnv(CXPrintingPolicy Policy) {
+ struct Mapping {
+ const char *name;
+ enum CXPrintingPolicyProperty property;
+ };
+ struct Mapping mappings[] = {
+ {"CINDEXTEST_PRINTINGPOLICY_INDENTATION", CXPrintingPolicy_Indentation},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSPECIFIERS",
+ CXPrintingPolicy_SuppressSpecifiers},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTAGKEYWORD",
+ CXPrintingPolicy_SuppressTagKeyword},
+ {"CINDEXTEST_PRINTINGPOLICY_INCLUDETAGDEFINITION",
+ CXPrintingPolicy_IncludeTagDefinition},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSCOPE",
+ CXPrintingPolicy_SuppressScope},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSUNWRITTENSCOPE",
+ CXPrintingPolicy_SuppressUnwrittenScope},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSINITIALIZERS",
+ CXPrintingPolicy_SuppressInitializers},
+ {"CINDEXTEST_PRINTINGPOLICY_CONSTANTARRAYSIZEASWRITTEN",
+ CXPrintingPolicy_ConstantArraySizeAsWritten},
+ {"CINDEXTEST_PRINTINGPOLICY_ANONYMOUSTAGLOCATIONS",
+ CXPrintingPolicy_AnonymousTagLocations},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSTRONGLIFETIME",
+ CXPrintingPolicy_SuppressStrongLifetime},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSLIFETIMEQUALIFIERS",
+ CXPrintingPolicy_SuppressLifetimeQualifiers},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTEMPLATEARGSINCXXCONSTRUCTORS",
+ CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors},
+ {"CINDEXTEST_PRINTINGPOLICY_BOOL", CXPrintingPolicy_Bool},
+ {"CINDEXTEST_PRINTINGPOLICY_RESTRICT", CXPrintingPolicy_Restrict},
+ {"CINDEXTEST_PRINTINGPOLICY_ALIGNOF", CXPrintingPolicy_Alignof},
+ {"CINDEXTEST_PRINTINGPOLICY_UNDERSCOREALIGNOF",
+ CXPrintingPolicy_UnderscoreAlignof},
+ {"CINDEXTEST_PRINTINGPOLICY_USEVOIDFORZEROPARAMS",
+ CXPrintingPolicy_UseVoidForZeroParams},
+ {"CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT", CXPrintingPolicy_TerseOutput},
+ {"CINDEXTEST_PRINTINGPOLICY_POLISHFORDECLARATION",
+ CXPrintingPolicy_PolishForDeclaration},
+ {"CINDEXTEST_PRINTINGPOLICY_HALF", CXPrintingPolicy_Half},
+ {"CINDEXTEST_PRINTINGPOLICY_MSWCHAR", CXPrintingPolicy_MSWChar},
+ {"CINDEXTEST_PRINTINGPOLICY_INCLUDENEWLINES",
+ CXPrintingPolicy_IncludeNewlines},
+ {"CINDEXTEST_PRINTINGPOLICY_MSVCFORMATTING",
+ CXPrintingPolicy_MSVCFormatting},
+ {"CINDEXTEST_PRINTINGPOLICY_CONSTANTSASWRITTEN",
+ CXPrintingPolicy_ConstantsAsWritten},
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSIMPLICITBASE",
+ CXPrintingPolicy_SuppressImplicitBase},
+ {"CINDEXTEST_PRINTINGPOLICY_FULLYQUALIFIEDNAME",
+ CXPrintingPolicy_FullyQualifiedName},
+ };
+
+ unsigned i;
+ for (i = 0; i < sizeof(mappings) / sizeof(struct Mapping); i++) {
+ char *value = getenv(mappings[i].name);
+ if (value) {
+ clang_PrintingPolicy_setProperty(Policy, mappings[i].property,
+ (unsigned)strtoul(value, 0L, 10));
+ }
+ }
+}
+
/** \brief Returns 0 in case of success, non-zero in case of a failure. */
static int checkForErrors(CXTranslationUnit TU);
@@ -356,7 +419,11 @@ static void PrintRange(CXSourceRange R, const char *str) {
PrintExtent(stdout, begin_line, begin_column, end_line, end_column);
}
-int want_display_name = 0;
+static enum DisplayType {
+ DisplayType_Spelling,
+ DisplayType_DisplayName,
+ DisplayType_Pretty
+} wanted_display_type = DisplayType_Spelling;
static void printVersion(const char *Prefix, CXVersion Version) {
if (Version.Major < 0)
@@ -656,6 +723,24 @@ static int lineCol_cmp(const void *p1, const void *p2) {
return (int)lhs->col - (int)rhs->col;
}
+static CXString CursorToText(CXCursor Cursor) {
+ switch (wanted_display_type) {
+ case DisplayType_Spelling:
+ return clang_getCursorSpelling(Cursor);
+ case DisplayType_DisplayName:
+ return clang_getCursorDisplayName(Cursor);
+ case DisplayType_Pretty:
+ default: {
+ CXString text;
+ CXPrintingPolicy Policy = clang_getCursorPrintingPolicy(Cursor);
+ ModifyPrintingPolicyAccordingToEnv(Policy);
+ text = clang_getCursorPrettyPrinted(Cursor, Policy);
+ clang_PrintingPolicy_dispose(Policy);
+ return text;
+ }
+ }
+}
+
static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
if (clang_isInvalid(Cursor.kind)) {
@@ -682,8 +767,7 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
int I;
ks = clang_getCursorKindSpelling(Cursor.kind);
- string = want_display_name? clang_getCursorDisplayName(Cursor)
- : clang_getCursorSpelling(Cursor);
+ string = CursorToText(Cursor);
printf("%s=%s", clang_getCString(ks),
clang_getCString(string));
clang_disposeString(ks);
@@ -1686,7 +1770,12 @@ static int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
else if (!strcmp(filter, "all-display") ||
!strcmp(filter, "local-display")) {
ck = NULL;
- want_display_name = 1;
+ wanted_display_type = DisplayType_DisplayName;
+ }
+ else if (!strcmp(filter, "all-pretty") ||
+ !strcmp(filter, "local-pretty")) {
+ ck = NULL;
+ wanted_display_type = DisplayType_Pretty;
}
else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0;
else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
@@ -1754,8 +1843,11 @@ int perform_test_load_source(int argc, const char **argv,
const char *InvocationPath;
Idx = clang_createIndex(/* excludeDeclsFromPCH */
- (!strcmp(filter, "local") ||
- !strcmp(filter, "local-display"))? 1 : 0,
+ (!strcmp(filter, "local") ||
+ !strcmp(filter, "local-display") ||
+ !strcmp(filter, "local-pretty"))
+ ? 1
+ : 0,
/* displayDiagnostics=*/1);
InvocationPath = getenv("CINDEXTEST_INVOCATION_EMISSION_PATH");
if (InvocationPath)
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 429fca3474..bd2e4bc8d2 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -4706,6 +4706,197 @@ CXStringSet *clang_Cursor_getObjCManglings(CXCursor C) {
return cxstring::createSet(Manglings);
}
+CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor C) {
+ if (clang_Cursor_isNull(C))
+ return 0;
+ return new PrintingPolicy(getCursorContext(C).getPrintingPolicy());
+}
+
+void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy) {
+ if (Policy)
+ delete static_cast<PrintingPolicy *>(Policy);
+}
+
+unsigned
+clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
+ enum CXPrintingPolicyProperty Property) {
+ if (!Policy)
+ return 0;
+
+ PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
+ switch (Property) {
+ case CXPrintingPolicy_Indentation:
+ return P->Indentation;
+ case CXPrintingPolicy_SuppressSpecifiers:
+ return P->SuppressSpecifiers;
+ case CXPrintingPolicy_SuppressTagKeyword:
+ return P->SuppressTagKeyword;
+ case CXPrintingPolicy_IncludeTagDefinition:
+ return P->IncludeTagDefinition;
+ case CXPrintingPolicy_SuppressScope:
+ return P->SuppressScope;
+ case CXPrintingPolicy_SuppressUnwrittenScope:
+ return P->SuppressUnwrittenScope;
+ case CXPrintingPolicy_SuppressInitializers:
+ return P->SuppressInitializers;
+ case CXPrintingPolicy_ConstantArraySizeAsWritten:
+ return P->ConstantArraySizeAsWritten;
+ case CXPrintingPolicy_AnonymousTagLocations:
+ return P->AnonymousTagLocations;
+ case CXPrintingPolicy_SuppressStrongLifetime:
+ return P->SuppressStrongLifetime;
+ case CXPrintingPolicy_SuppressLifetimeQualifiers:
+ return P->SuppressLifetimeQualifiers;
+ case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
+ return P->SuppressTemplateArgsInCXXConstructors;
+ case CXPrintingPolicy_Bool:
+ return P->Bool;
+ case CXPrintingPolicy_Restrict:
+ return P->Restrict;
+ case CXPrintingPolicy_Alignof:
+ return P->Alignof;
+ case CXPrintingPolicy_UnderscoreAlignof:
+ return P->UnderscoreAlignof;
+ case CXPrintingPolicy_UseVoidForZeroParams:
+ return P->UseVoidForZeroParams;
+ case CXPrintingPolicy_TerseOutput:
+ return P->TerseOutput;
+ case CXPrintingPolicy_PolishForDeclaration:
+ return P->PolishForDeclaration;
+ case CXPrintingPolicy_Half:
+ return P->Half;
+ case CXPrintingPolicy_MSWChar:
+ return P->MSWChar;
+ case CXPrintingPolicy_IncludeNewlines:
+ return P->IncludeNewlines;
+ case CXPrintingPolicy_MSVCFormatting:
+ return P->MSVCFormatting;
+ case CXPrintingPolicy_ConstantsAsWritten:
+ // Ops, not yet there in clang 5.0 and we do not need it.
+ return 0;
+ case CXPrintingPolicy_SuppressImplicitBase:
+ // Ops, not yet there in clang 5.0 and we do not need it.
+ return 0;
+ case CXPrintingPolicy_FullyQualifiedName:
+ return P->FullyQualifiedName;
+ }
+
+ assert(false && "Invalid CXPrintingPolicyProperty");
+ return 0;
+}
+
+void clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
+ enum CXPrintingPolicyProperty Property,
+ unsigned Value) {
+ if (!Policy)
+ return;
+
+ PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
+ switch (Property) {
+ case CXPrintingPolicy_Indentation:
+ P->Indentation = Value;
+ return;
+ case CXPrintingPolicy_SuppressSpecifiers:
+ P->SuppressSpecifiers = Value;
+ return;
+ case CXPrintingPolicy_SuppressTagKeyword:
+ P->SuppressTagKeyword = Value;
+ return;
+ case CXPrintingPolicy_IncludeTagDefinition:
+ P->IncludeTagDefinition = Value;
+ return;
+ case CXPrintingPolicy_SuppressScope:
+ P->SuppressScope = Value;
+ return;
+ case CXPrintingPolicy_SuppressUnwrittenScope:
+ P->SuppressUnwrittenScope = Value;
+ return;
+ case CXPrintingPolicy_SuppressInitializers:
+ P->SuppressInitializers = Value;
+ return;
+ case CXPrintingPolicy_ConstantArraySizeAsWritten:
+ P->ConstantArraySizeAsWritten = Value;
+ return;
+ case CXPrintingPolicy_AnonymousTagLocations:
+ P->AnonymousTagLocations = Value;
+ return;
+ case CXPrintingPolicy_SuppressStrongLifetime:
+ P->SuppressStrongLifetime = Value;
+ return;
+ case CXPrintingPolicy_SuppressLifetimeQualifiers:
+ P->SuppressLifetimeQualifiers = Value;
+ return;
+ case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
+ P->SuppressTemplateArgsInCXXConstructors = Value;
+ return;
+ case CXPrintingPolicy_Bool:
+ P->Bool = Value;
+ return;
+ case CXPrintingPolicy_Restrict:
+ P->Restrict = Value;
+ return;
+ case CXPrintingPolicy_Alignof:
+ P->Alignof = Value;
+ return;
+ case CXPrintingPolicy_UnderscoreAlignof:
+ P->UnderscoreAlignof = Value;
+ return;
+ case CXPrintingPolicy_UseVoidForZeroParams:
+ P->UseVoidForZeroParams = Value;
+ return;
+ case CXPrintingPolicy_TerseOutput:
+ P->TerseOutput = Value;
+ return;
+ case CXPrintingPolicy_PolishForDeclaration:
+ P->PolishForDeclaration = Value;
+ return;
+ case CXPrintingPolicy_Half:
+ P->Half = Value;
+ return;
+ case CXPrintingPolicy_MSWChar:
+ P->MSWChar = Value;
+ return;
+ case CXPrintingPolicy_IncludeNewlines:
+ P->IncludeNewlines = Value;
+ return;
+ case CXPrintingPolicy_MSVCFormatting:
+ P->MSVCFormatting = Value;
+ return;
+ case CXPrintingPolicy_ConstantsAsWritten:
+ // Ops, not yet there in clang 5.0 and we do not need it.
+ return;
+ case CXPrintingPolicy_SuppressImplicitBase:
+ // Ops, not yet there in clang 5.0 and we do not need it.
+ return;
+ case CXPrintingPolicy_FullyQualifiedName:
+ P->FullyQualifiedName = Value;
+ return;
+ }
+
+ assert(false && "Invalid CXPrintingPolicyProperty");
+}
+
+CXString clang_getCursorPrettyPrinted(CXCursor C, CXPrintingPolicy cxPolicy) {
+ if (clang_Cursor_isNull(C))
+ return cxstring::createEmpty();
+
+ if (clang_isDeclaration(C.kind)) {
+ const Decl *D = getCursorDecl(C);
+ if (!D)
+ return cxstring::createEmpty();
+
+ SmallString<128> Str;
+ llvm::raw_svector_ostream OS(Str);
+ PrintingPolicy *UserPolicy = static_cast<PrintingPolicy *>(cxPolicy);
+ D->print(OS, UserPolicy ? *UserPolicy
+ : getCursorContext(C).getPrintingPolicy());
+
+ return cxstring::createDup(OS.str());
+ }
+
+ return cxstring::createEmpty();
+}
+
CXString clang_getCursorDisplayName(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return clang_getCursorSpelling(C);
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 5d1b0224ef..67e4b4334b 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -178,6 +178,8 @@ clang_getCursorAvailability
clang_getCursorCompletionString
clang_getCursorDefinition
clang_getCursorDisplayName
+clang_getCursorPrintingPolicy
+clang_getCursorPrettyPrinted
clang_getCursorExtent
clang_getCursorExceptionSpecificationType
clang_getCursorKind
@@ -359,3 +361,6 @@ clang_EvalResult_isUnsignedInt
clang_EvalResult_getAsDouble
clang_EvalResult_getAsStr
clang_EvalResult_dispose
+clang_PrintingPolicy_getProperty
+clang_PrintingPolicy_setProperty
+clang_PrintingPolicy_dispose
diff --git a/unittests/libclang/LibclangTest.cpp b/unittests/libclang/LibclangTest.cpp
index f2a96d6be6..342fbd5279 100644
--- a/unittests/libclang/LibclangTest.cpp
+++ b/unittests/libclang/LibclangTest.cpp
@@ -572,3 +572,35 @@ TEST_F(LibclangReparseTest, clang_parseTranslationUnit2FullArgv) {
EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
DisplayDiagnostics();
}
+
+class LibclangPrintingPolicyTest : public LibclangParseTest {
+public:
+ CXPrintingPolicy Policy = nullptr;
+
+ void SetUp() override {
+ LibclangParseTest::SetUp();
+ std::string File = "file.cpp";
+ WriteFile(File, "int i;\n");
+ ClangTU = clang_parseTranslationUnit(Index, File.c_str(), nullptr, 0,
+ nullptr, 0, TUFlags);
+ CXCursor TUCursor = clang_getTranslationUnitCursor(ClangTU);
+ Policy = clang_getCursorPrintingPolicy(TUCursor);
+ }
+ void TearDown() override {
+ clang_PrintingPolicy_dispose(Policy);
+ LibclangParseTest::TearDown();
+ }
+};
+
+TEST_F(LibclangPrintingPolicyTest, SetAndGetProperties) {
+ for (unsigned Value = 0; Value < 2; ++Value) {
+ for (int I = 0; I < CXPrintingPolicy_LastProperty; ++I) {
+ auto Property = static_cast<enum CXPrintingPolicyProperty>(I);
+ if (Property == CXPrintingPolicy_ConstantsAsWritten || Property == CXPrintingPolicy_SuppressImplicitBase)
+ continue; // These are not yet in clang 5.0.
+
+ clang_PrintingPolicy_setProperty(Policy, Property, Value);
+ EXPECT_EQ(Value, clang_PrintingPolicy_getProperty(Policy, Property));
+ }
+ }
+}