Skip to content

Conversation

@efriedma-quic
Copy link
Collaborator

@efriedma-quic efriedma-quic commented Dec 18, 2024

This allows changing the way pretty-printed code is formatted.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:as-a-library libclang and C++ API labels Dec 18, 2024
@llvmbot
Copy link
Member

llvmbot commented Dec 18, 2024

@llvm/pr-subscribers-clang

Author: Eli Friedman (efriedma-quic)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/120494.diff

2 Files Affected:

  • (modified) clang/bindings/python/clang/cindex.py (+78)
  • (modified) clang/bindings/python/tests/cindex/test_cursor.py (+12)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index f8a20a1e224724..df8d9aea81e92c 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1770,6 +1770,14 @@ def spelling(self):
 
         return self._spelling
 
+    def pretty_printed(self, policy):
+        """
+        Pretty print declarations.
+        Parameters:
+        policy -- The policy to control the entities being printed.
+        """
+        return _CXString.from_result(conf.lib.clang_getCursorPrettyPrinted(self, policy))
+
     @property
     def displayname(self):
         """
@@ -3685,6 +3693,69 @@ def write_main_file_to_stdout(self):
         conf.lib.clang_CXRewriter_writeMainFileToStdOut(self)
 
 
+class PrintingPolicyProperty(BaseEnumeration):
+    """
+    A PrintingPolicyProperty identifies a property of a PrintingPolicy.
+    """
+    Indentation = 0
+    SuppressSpecifiers = 1
+    SuppressTagKeyword = 2
+    IncludeTagDefinition = 3
+    SuppressScope = 4
+    SuppressUnwrittenScope = 5
+    SuppressInitializers = 6
+    ConstantArraySizeAsWritten = 7
+    AnonymousTagLocations = 8
+    SuppressStrongLifetime = 9
+    SuppressLifetimeQualifiers = 10
+    SuppressTemplateArgsInCXXConstructors = 11
+    Bool = 12
+    Restrict = 13
+    Alignof = 14
+    UnderscoreAlignof = 15
+    UseVoidForZeroParams = 16
+    TerseOutput = 17
+    PolishForDeclaration = 18
+    Half = 19
+    MSWChar = 20
+    IncludeNewlines = 21
+    MSVCFormatting = 22
+    ConstantsAsWritten = 23
+    SuppressImplicitBase = 24
+    FullyQualifiedName = 25
+
+class PrintingPolicy(ClangObject):
+    """
+    The PrintingPolicy is a wrapper class around clang::PrintingPolicy
+
+    It allows specifying how declarations, expressions, and types should be
+    pretty-printed.
+    """
+
+    @staticmethod
+    def create(cu):
+        """
+        Creates a new PrintingPolicy
+        Parameters:
+        cu -- Any cursor for a translation unit.
+        """
+        return PrintingPolicy(conf.lib.clang_getCursorPrintingPolicy(cu))
+
+    def __init__(self, ptr):
+        ClangObject.__init__(self, ptr)
+
+    def __del__(self):
+        conf.lib.clang_PrintingPolicy_dispose(self)
+
+    def get_property(self, property):
+        """Get a property value for the given printing policy."""
+        return conf.lib.clang_PrintingPolicy_getProperty(self, property.value)
+
+    def set_property(self, property, value):
+        """Set a property value for the given printing policy."""
+        conf.lib.clang_PrintingPolicy_setProperty(self, property.value, value)
+
+
 # Now comes the plumbing to hook up the C library.
 
 # Register callback types
@@ -3787,6 +3858,8 @@ def write_main_file_to_stdout(self):
     ("clang_getCursorExtent", [Cursor], SourceRange),
     ("clang_getCursorLexicalParent", [Cursor], Cursor),
     ("clang_getCursorLocation", [Cursor], SourceLocation),
+    ("clang_getCursorPrettyPrinted", [Cursor, PrintingPolicy], _CXString),
+    ("clang_getCursorPrintingPolicy", [Cursor], c_object_p),
     ("clang_getCursorReferenced", [Cursor], Cursor),
     ("clang_getCursorReferenceNameRange", [Cursor, c_uint, c_uint], SourceRange),
     ("clang_getCursorResultType", [Cursor], Type),
@@ -3909,6 +3982,9 @@ def write_main_file_to_stdout(self):
     ("clang_Cursor_getRawCommentText", [Cursor], _CXString),
     ("clang_Cursor_getOffsetOfField", [Cursor], c_longlong),
     ("clang_Location_isInSystemHeader", [SourceLocation], bool),
+    ("clang_PrintingPolicy_dispose", [PrintingPolicy]),
+    ("clang_PrintingPolicy_getProperty", [PrintingPolicy, c_int], c_uint),
+    ("clang_PrintingPolicy_setProperty", [PrintingPolicy, c_int, c_uint]),
     ("clang_Type_getAlignOf", [Type], c_longlong),
     ("clang_Type_getClassType", [Type], Type),
     ("clang_Type_getNumTemplateArguments", [Type], c_int),
@@ -4089,6 +4165,8 @@ def function_exists(self, name: str) -> bool:
     "FixIt",
     "Index",
     "LinkageKind",
+    "PrintingPolicy",
+    "PrintingPolicyProperty",
     "RefQualifierKind",
     "SourceLocation",
     "SourceRange",
diff --git a/clang/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py
index 4d989a7421e790..06f2d478c97d95 100644
--- a/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/clang/bindings/python/tests/cindex/test_cursor.py
@@ -5,6 +5,8 @@
     BinaryOperator,
     Config,
     CursorKind,
+    PrintingPolicy,
+    PrintingPolicyProperty,
     StorageClass,
     TemplateArgumentKind,
     TranslationUnit,
@@ -981,3 +983,13 @@ def test_from_result_null(self):
     def test_from_cursor_result_null(self):
         tu = get_tu("")
         self.assertEqual(tu.cursor.semantic_parent, None)
+
+    def test_pretty_print(self):
+        tu = get_tu("struct X { int x; }; void f(bool x) { }", lang="cpp")
+        f = get_cursor(tu, "f")
+
+        self.assertEqual(f.displayname, "f(bool)")
+        pp = PrintingPolicy.create(f)
+        self.assertEqual(f.pretty_printed(pp), "void f(bool x) {\n}\n")
+        pp.set_property(PrintingPolicyProperty.Bool, False)
+        self.assertEqual(f.pretty_printed(pp), "void f(_Bool x) {\n}\n")

@github-actions
Copy link

github-actions bot commented Dec 18, 2024

✅ With the latest revision this PR passed the Python code formatter.

Copy link
Contributor

@DeinAlptraum DeinAlptraum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Two minor comments and formatting, otherwise LGTM!

@efriedma-quic efriedma-quic self-assigned this Dec 19, 2024
This allows changing the way pretty-printed code is formatted.
Copy link
Contributor

@DeinAlptraum DeinAlptraum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! @Endilll did you want to take a look at this as well?

@efriedma-quic
Copy link
Collaborator Author

@DeinAlptraum any idea why the Python tests are failing?

@DeinAlptraum
Copy link
Contributor

@efriedma-quic no idea, I would just rebase and hope that's it

@efriedma-quic
Copy link
Collaborator Author

Still failing the same way.

Should I go ahead and merge anyway, or is there someone who can look into this?

@Endilll
Copy link
Contributor

Endilll commented Jan 9, 2025

The failure reminds me of #122063, which was merged just 2 hours ago.
Do you mind merging the main into your PR and try again?

@efriedma-quic
Copy link
Collaborator Author

Oh, looks like that fixed it, thanks.

@efriedma-quic efriedma-quic merged commit e6d061a into llvm:main Jan 9, 2025
8 of 10 checks passed
BaiXilin pushed a commit to BaiXilin/llvm-project that referenced this pull request Jan 12, 2025
This allows changing the way pretty-printed code is formatted.
@epistax
Copy link
Contributor

epistax commented Apr 8, 2025

Should this have enabled getting fully qualified type names? From Python I am using a PrintingPolicy with the FullyQualifiedName property set, but using pretty_printed on a type name with the policy does not provide a fully qualified name.

@efriedma-quic
Copy link
Collaborator Author

The PrintingPolicy constants just reflect the names from clang/include/clang/AST/PrettyPrinter.h. For FullyQualifiedName specifically:

/// When true, print the fully qualified name of function declarations.
/// This is the opposite of SuppressScope and thus overrules it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:as-a-library libclang and C++ API clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants