[clang] Use existing AvailabilityKind enum for code completion availability (PR #160296)
Jannick Kremer via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 17 02:46:04 PST 2026
https://github.com/DeinAlptraum updated https://github.com/llvm/llvm-project/pull/160296
>From 930402a752c87d84b961bb2192d6efa732bf7ad9 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Tue, 23 Sep 2025 22:26:44 +0900
Subject: [PATCH 01/16] Use existing AvailabilityKind enum for code completion
availability
---
clang/bindings/python/clang/cindex.py | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 2b6ab00c88219..8bee77424d1f4 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3051,6 +3051,16 @@ class _CXUnsavedFile(Structure):
}
+# Converting the new enum names (full upper-case, underscore separated)
+# to the old ones (separated by capitalization), e.g. RESULT_TYPE -> ResultType
+def _kind_to_old_name(kind: BaseEnumeration):
+ # Remove underscores
+ components = kind.name.split("_")
+ # Upper-camel case each split component
+ components = [component.lower().capitalize() for component in components]
+ return "".join(components)
+
+
class CompletionChunk:
class Kind:
def __init__(self, name: str):
@@ -3177,9 +3187,9 @@ def priority(self) -> int:
return conf.lib.clang_getCompletionPriority(self.obj) # type: ignore [no-any-return]
@property
- def availability(self) -> CompletionChunk.Kind:
+ def availability(self) -> AvailabilityKind:
res = conf.lib.clang_getCompletionAvailability(self.obj)
- return availabilityKinds[res]
+ return AvailabilityKind.from_id(res)
@property
def briefComment(self) -> str:
@@ -3191,20 +3201,12 @@ def __repr__(self) -> str:
+ " || Priority: "
+ str(self.priority)
+ " || Availability: "
- + str(self.availability)
+ + _kind_to_old_name(self.availability)
+ " || Brief comment: "
+ str(self.briefComment)
)
-availabilityKinds = {
- 0: CompletionChunk.Kind("Available"),
- 1: CompletionChunk.Kind("Deprecated"),
- 2: CompletionChunk.Kind("NotAvailable"),
- 3: CompletionChunk.Kind("NotAccessible"),
-}
-
-
class CodeCompletionResult(Structure):
_fields_ = [("cursorKind", c_int), ("completionString", c_object_p)]
>From d6649a3f0f5c3b135db65a30d676c6dd47ce5bef Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Wed, 24 Sep 2025 22:18:25 +0900
Subject: [PATCH 02/16] Turn comment into docstring
---
clang/bindings/python/clang/cindex.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 8bee77424d1f4..989ba5ada2f0a 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3051,9 +3051,11 @@ class _CXUnsavedFile(Structure):
}
-# Converting the new enum names (full upper-case, underscore separated)
-# to the old ones (separated by capitalization), e.g. RESULT_TYPE -> ResultType
def _kind_to_old_name(kind: BaseEnumeration):
+ """
+ Converting the new enum names (full upper-case, underscore separated)
+ to the old ones (separated by capitalization), e.g. RESULT_TYPE -> ResultType
+ """
# Remove underscores
components = kind.name.split("_")
# Upper-camel case each split component
>From 802224da0c86a8bca476e8fdf0e37ae3dc243ccf Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Wed, 24 Sep 2025 17:02:44 +0200
Subject: [PATCH 03/16] Update clang/bindings/python/clang/cindex.py
Co-authored-by: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
---
clang/bindings/python/clang/cindex.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 989ba5ada2f0a..fddddfa570a8e 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3051,7 +3051,7 @@ class _CXUnsavedFile(Structure):
}
-def _kind_to_old_name(kind: BaseEnumeration):
+def _convert_screaming_caps_to_pascal_case(kind: BaseEnumeration):
"""
Converting the new enum names (full upper-case, underscore separated)
to the old ones (separated by capitalization), e.g. RESULT_TYPE -> ResultType
>From a8cc996a3dfa24a2c3a66868324bfd58557f0d06 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Sun, 4 Jan 2026 17:24:03 +0900
Subject: [PATCH 04/16] Remove unused CompletionString.Availability
---
clang/bindings/python/clang/cindex.py | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index fddddfa570a8e..b376465c8738b 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3155,16 +3155,6 @@ def isKindResultType(self) -> bool:
class CompletionString(ClangObject):
- class Availability:
- def __init__(self, name):
- self.name = name
-
- def __str__(self):
- return self.name
-
- def __repr__(self):
- return "<Availability: %s>" % self
-
def __len__(self) -> int:
return self.num_chunks
>From b01d045f216489b8b9ce475cb50daa2b21d6e3dc Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Sun, 4 Jan 2026 17:27:23 +0900
Subject: [PATCH 05/16] Pass string instead of enum variant to converter
---
clang/bindings/python/clang/cindex.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index b376465c8738b..6a2e54aed5c53 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3051,13 +3051,13 @@ class _CXUnsavedFile(Structure):
}
-def _convert_screaming_caps_to_pascal_case(kind: BaseEnumeration):
+def _convert_screaming_caps_to_pascal_case(kind: str):
"""
Converting the new enum names (full upper-case, underscore separated)
to the old ones (separated by capitalization), e.g. RESULT_TYPE -> ResultType
"""
# Remove underscores
- components = kind.name.split("_")
+ components = kind.split("_")
# Upper-camel case each split component
components = [component.lower().capitalize() for component in components]
return "".join(components)
@@ -3193,7 +3193,7 @@ def __repr__(self) -> str:
+ " || Priority: "
+ str(self.priority)
+ " || Availability: "
- + _kind_to_old_name(self.availability)
+ + _convert_screaming_caps_to_pascal_case(self.availability.name)
+ " || Brief comment: "
+ str(self.briefComment)
)
>From 49507d2f96c43e2d877f97a20fd4b99d6b7ec314 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Mon, 5 Jan 2026 01:17:33 +0900
Subject: [PATCH 06/16] Add AvailabilityKindCompat
---
clang/bindings/python/clang/cindex.py | 52 +++++++++++++------
.../tests/cindex/test_code_completion.py | 37 ++++++++++++-
2 files changed, 72 insertions(+), 17 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 6a2e54aed5c53..a51023c2d9c5d 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3051,18 +3051,6 @@ class _CXUnsavedFile(Structure):
}
-def _convert_screaming_caps_to_pascal_case(kind: str):
- """
- Converting the new enum names (full upper-case, underscore separated)
- to the old ones (separated by capitalization), e.g. RESULT_TYPE -> ResultType
- """
- # Remove underscores
- components = kind.split("_")
- # Upper-camel case each split component
- components = [component.lower().capitalize() for component in components]
- return "".join(components)
-
-
class CompletionChunk:
class Kind:
def __init__(self, name: str):
@@ -3179,9 +3167,9 @@ def priority(self) -> int:
return conf.lib.clang_getCompletionPriority(self.obj) # type: ignore [no-any-return]
@property
- def availability(self) -> AvailabilityKind:
+ def availability(self) -> AvailabilityKindCompat:
res = conf.lib.clang_getCompletionAvailability(self.obj)
- return AvailabilityKind.from_id(res)
+ return AvailabilityKindCompat.from_id(res)
@property
def briefComment(self) -> str:
@@ -3193,11 +3181,45 @@ def __repr__(self) -> str:
+ " || Priority: "
+ str(self.priority)
+ " || Availability: "
- + _convert_screaming_caps_to_pascal_case(self.availability.name)
+ + str(self.availability)
+ " || Brief comment: "
+ str(self.briefComment)
)
+# AvailabilityKindCompat is an exact copy of AvailabilityKind, except for __str__
+# This is a temporary measure to keep the string representation the same
+# until we unify the return of CompletionString.availability to be AvailabilityKind
+# Note that deriving from AvailabilityKind directly is not possible
+class AvailabilityKindCompat(BaseEnumeration):
+ """
+ Describes the availability of an entity.
+ """
+
+ # Ensure AvailabilityKindCompat is comparable with AvailabilityKind
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, AvailabilityKind):
+ return self.value == other.value
+ else:
+ return NotImplemented
+
+ def __str__(self) -> str:
+ """
+ Returns the common enum names (full upper-case, underscore separated)
+ to the old format (separated by capitalization), e.g. NOT_ACCESSIBLE -> NotAccessible
+ This is a temporary measure and will be changed in a future release
+ to return the same format (full upper-case, underscore separated) like other Kinds
+ """
+ # Remove underscores
+ components = self.name.split("_")
+ # Upper-camel case each split component
+ components = [component.lower().capitalize() for component in components]
+ return "".join(components)
+
+ AVAILABLE = 0
+ DEPRECATED = 1
+ NOT_AVAILABLE = 2
+ NOT_ACCESSIBLE = 3
+
class CodeCompletionResult(Structure):
_fields_ = [("cursorKind", c_int), ("completionString", c_object_p)]
diff --git a/clang/bindings/python/tests/cindex/test_code_completion.py b/clang/bindings/python/tests/cindex/test_code_completion.py
index 32b75eb1ae029..f2ebc7ab73fcd 100644
--- a/clang/bindings/python/tests/cindex/test_code_completion.py
+++ b/clang/bindings/python/tests/cindex/test_code_completion.py
@@ -1,5 +1,4 @@
-from clang.cindex import TranslationUnit
-
+from clang.cindex import TranslationUnit, AvailabilityKind, AvailabilityKindCompat
import unittest
from pathlib import Path
@@ -137,3 +136,37 @@ class Q : public P {
"{'void', ResultType} | {'~P', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 79 || Availability: Available || Brief comment: ",
]
self.check_completion_results(cr, expected)
+
+ def test_availability_kind_compat_(self):
+ numKinds = len(AvailabilityKindCompat)
+
+ # Compare with regular kind
+ for compatKind in AvailabilityKindCompat:
+ commonKind = AvailabilityKind.from_id(compatKind.value)
+ nextKindId = (compatKind.value+1) % numKinds
+ commonKindUnequal= AvailabilityKind.from_id(nextKindId)
+ self.assertEqual(commonKind, compatKind)
+ self.assertEqual(compatKind, commonKind)
+ self.assertNotEqual(commonKindUnequal, compatKind)
+ self.assertNotEqual(compatKind, commonKindUnequal)
+
+ # Compare two compat kinds
+ for compatKind in AvailabilityKindCompat:
+ compatKind2 = AvailabilityKindCompat.from_id(compatKind.value)
+ nextKindId = (compatKind.value+1) % numKinds
+ compatKind2Unequal = AvailabilityKind.from_id(nextKindId)
+ self.assertEqual(compatKind, compatKind2)
+ self.assertEqual(compatKind2, compatKind)
+ self.assertNotEqual(compatKind2Unequal, compatKind)
+ self.assertNotEqual(compatKind, compatKind2Unequal)
+
+ def test_compat_str(self):
+ kindStringMap = {
+ 0: "Available",
+ 1: "Deprecated",
+ 2: "NotAvailable",
+ 3: "NotAccessible",
+ }
+ for id, string in kindStringMap.items():
+ kind = AvailabilityKindCompat.from_id(id)
+ self.assertEqual(str(kind), string)
>From 8fb54316b75a350268a4306bdcebc80ae630f6c9 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Mon, 5 Jan 2026 01:36:47 +0900
Subject: [PATCH 07/16] Add deprecation warning
---
clang/bindings/python/clang/cindex.py | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index a51023c2d9c5d..ebb3a4f538c5c 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -84,6 +84,7 @@
import os
import sys
from enum import Enum
+import warnings
from typing import (
Any,
@@ -3186,6 +3187,7 @@ def __repr__(self) -> str:
+ str(self.briefComment)
)
+
# AvailabilityKindCompat is an exact copy of AvailabilityKind, except for __str__
# This is a temporary measure to keep the string representation the same
# until we unify the return of CompletionString.availability to be AvailabilityKind
@@ -3209,6 +3211,14 @@ def __str__(self) -> str:
This is a temporary measure and will be changed in a future release
to return the same format (full upper-case, underscore separated) like other Kinds
"""
+
+ warnings.warn(
+ "The CompletionString.availability's return value will be changed in "
+ "a future release to be unified with other kinds. As a result, its string "
+ "representations will change to full upper-case, prefixed with the class name "
+ "(e.g. NotAvailable -> AvailabilityKind.NOT_AVAILABLE).",
+ DeprecationWarning,
+ )
# Remove underscores
components = self.name.split("_")
# Upper-camel case each split component
>From bc84caf3cb6b2bdb3e09ee34dbdaad91b010c3ac Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Mon, 5 Jan 2026 01:48:29 +0900
Subject: [PATCH 08/16] Fix enums test
---
clang/bindings/python/tests/cindex/test_enums.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/clang/bindings/python/tests/cindex/test_enums.py b/clang/bindings/python/tests/cindex/test_enums.py
index 0d3453e602edf..d290686b5ee71 100644
--- a/clang/bindings/python/tests/cindex/test_enums.py
+++ b/clang/bindings/python/tests/cindex/test_enums.py
@@ -4,6 +4,7 @@
from clang.cindex import (
AccessSpecifier,
AvailabilityKind,
+ AvailabilityKindCompat,
BinaryOperator,
CursorKind,
ExceptionSpecificationKind,
@@ -22,7 +23,10 @@
class TestEnums(unittest.TestCase):
+ # Test all enum classes, except for AvailabilityKindCompat since it is
+ # just a copy of AvailabilityKind and has no corresponding C-class
enums = BaseEnumeration.__subclasses__()
+ enums.remove(AvailabilityKindCompat)
def test_from_id(self):
"""Check that kinds can be constructed from valid IDs"""
>From 2d5878292557faff241bbb8fc616717773fd6bfa Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Mon, 5 Jan 2026 01:52:13 +0900
Subject: [PATCH 09/16] Fix formatting
---
clang/bindings/python/tests/cindex/test_code_completion.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/bindings/python/tests/cindex/test_code_completion.py b/clang/bindings/python/tests/cindex/test_code_completion.py
index f2ebc7ab73fcd..6e12077a35bde 100644
--- a/clang/bindings/python/tests/cindex/test_code_completion.py
+++ b/clang/bindings/python/tests/cindex/test_code_completion.py
@@ -143,8 +143,8 @@ def test_availability_kind_compat_(self):
# Compare with regular kind
for compatKind in AvailabilityKindCompat:
commonKind = AvailabilityKind.from_id(compatKind.value)
- nextKindId = (compatKind.value+1) % numKinds
- commonKindUnequal= AvailabilityKind.from_id(nextKindId)
+ nextKindId = (compatKind.value + 1) % numKinds
+ commonKindUnequal = AvailabilityKind.from_id(nextKindId)
self.assertEqual(commonKind, compatKind)
self.assertEqual(compatKind, commonKind)
self.assertNotEqual(commonKindUnequal, compatKind)
@@ -153,7 +153,7 @@ def test_availability_kind_compat_(self):
# Compare two compat kinds
for compatKind in AvailabilityKindCompat:
compatKind2 = AvailabilityKindCompat.from_id(compatKind.value)
- nextKindId = (compatKind.value+1) % numKinds
+ nextKindId = (compatKind.value + 1) % numKinds
compatKind2Unequal = AvailabilityKind.from_id(nextKindId)
self.assertEqual(compatKind, compatKind2)
self.assertEqual(compatKind2, compatKind)
>From 19bd1be33f035b093276ba6ad32a1f92ae23723f Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Sat, 17 Jan 2026 18:57:05 +0900
Subject: [PATCH 10/16] Improve documentation according to review comments
---
clang/bindings/python/clang/cindex.py | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index ebb3a4f538c5c..760657acafae4 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3187,14 +3187,15 @@ def __repr__(self) -> str:
+ str(self.briefComment)
)
-
-# AvailabilityKindCompat is an exact copy of AvailabilityKind, except for __str__
+# AvailabilityKindCompat is an exact copy of AvailabilityKind, except for __str__.
# This is a temporary measure to keep the string representation the same
-# until we unify the return of CompletionString.availability to be AvailabilityKind
-# Note that deriving from AvailabilityKind directly is not possible
+# until we change CompletionString.availability to return AvailabilityKind,
+# like Cursor.availability does.
+# Note that deriving from AvailabilityKind directly is not possible.
class AvailabilityKindCompat(BaseEnumeration):
"""
Describes the availability of an entity.
+ It is deprecated in favor of AvailabilityKind.
"""
# Ensure AvailabilityKindCompat is comparable with AvailabilityKind
@@ -3206,17 +3207,17 @@ def __eq__(self, other: object) -> bool:
def __str__(self) -> str:
"""
- Returns the common enum names (full upper-case, underscore separated)
- to the old format (separated by capitalization), e.g. NOT_ACCESSIBLE -> NotAccessible
- This is a temporary measure and will be changed in a future release
- to return the same format (full upper-case, underscore separated) like other Kinds
+ Converts enum value to string in the old camelCase format.
+ This is a temporary measure that will be changed in the future release
+ to return string in ALL_CAPS format, like for other enums.
"""
warnings.warn(
- "The CompletionString.availability's return value will be changed in "
- "a future release to be unified with other kinds. As a result, its string "
- "representations will change to full upper-case, prefixed with the class name "
- "(e.g. NotAvailable -> AvailabilityKind.NOT_AVAILABLE).",
+ "String representation of 'CompletionString.availability' will be "
+ "changed in a future release from 'camelCase' to 'ALL_CAPS' to "
+ "match other enums. 'CompletionString.availability' can be "
+ "compared to 'AvailabilityKind' directly, "
+ "without conversion to string.",
DeprecationWarning,
)
# Remove underscores
>From 1a1bfb416f83b882dac5d23e51b337f9f4ea8b8b Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Sat, 17 Jan 2026 18:57:57 +0900
Subject: [PATCH 11/16] Reformat test imports
---
clang/bindings/python/tests/cindex/test_code_completion.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/bindings/python/tests/cindex/test_code_completion.py b/clang/bindings/python/tests/cindex/test_code_completion.py
index 6e12077a35bde..02a9aa6597c15 100644
--- a/clang/bindings/python/tests/cindex/test_code_completion.py
+++ b/clang/bindings/python/tests/cindex/test_code_completion.py
@@ -1,4 +1,4 @@
-from clang.cindex import TranslationUnit, AvailabilityKind, AvailabilityKindCompat
+from clang.cindex import AvailabilityKind, AvailabilityKindCompat, TranslationUnit
import unittest
from pathlib import Path
>From f30a3e311ac494a67772eafd639f64d378d42f37 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Sat, 17 Jan 2026 19:07:57 +0900
Subject: [PATCH 12/16] Fix test
---
clang/bindings/python/tests/cindex/test_code_completion.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/bindings/python/tests/cindex/test_code_completion.py b/clang/bindings/python/tests/cindex/test_code_completion.py
index 02a9aa6597c15..d438115c1d054 100644
--- a/clang/bindings/python/tests/cindex/test_code_completion.py
+++ b/clang/bindings/python/tests/cindex/test_code_completion.py
@@ -154,7 +154,7 @@ def test_availability_kind_compat_(self):
for compatKind in AvailabilityKindCompat:
compatKind2 = AvailabilityKindCompat.from_id(compatKind.value)
nextKindId = (compatKind.value + 1) % numKinds
- compatKind2Unequal = AvailabilityKind.from_id(nextKindId)
+ compatKind2Unequal = AvailabilityKindCompat.from_id(nextKindId)
self.assertEqual(compatKind, compatKind2)
self.assertEqual(compatKind2, compatKind)
self.assertNotEqual(compatKind2Unequal, compatKind)
>From c716885f201f40d06277faf8c3a0d6c81a7cd898 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Sat, 17 Jan 2026 19:09:01 +0900
Subject: [PATCH 13/16] Fix isinstance check
---
clang/bindings/python/clang/cindex.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 760657acafae4..6936d3130078e 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3200,7 +3200,7 @@ class AvailabilityKindCompat(BaseEnumeration):
# Ensure AvailabilityKindCompat is comparable with AvailabilityKind
def __eq__(self, other: object) -> bool:
- if isinstance(other, AvailabilityKind):
+ if isinstance(other, (AvailabilityKind, AvailabilityKindCompat)):
return self.value == other.value
else:
return NotImplemented
>From 51cceb35ae906cdd93e9338f80d076fc212dc8f5 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Sat, 17 Jan 2026 19:15:25 +0900
Subject: [PATCH 14/16] Move AvailabilityKindCompat into CompletionString
---
clang/bindings/python/clang/cindex.py | 91 ++++++++++---------
.../tests/cindex/test_code_completion.py | 14 +--
.../python/tests/cindex/test_enums.py | 4 +-
3 files changed, 55 insertions(+), 54 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 6936d3130078e..b1a0b159f5262 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3144,6 +3144,51 @@ def isKindResultType(self) -> bool:
class CompletionString(ClangObject):
+ # AvailabilityKindCompat is an exact copy of AvailabilityKind, except for __str__.
+ # This is a temporary measure to keep the string representation the same
+ # until we change CompletionString.availability to return AvailabilityKind,
+ # like Cursor.availability does.
+ # Note that deriving from AvailabilityKind directly is not possible.
+ class AvailabilityKindCompat(BaseEnumeration):
+ """
+ Describes the availability of an entity.
+ It is deprecated in favor of AvailabilityKind.
+ """
+
+ # Ensure AvailabilityKindCompat is comparable with AvailabilityKind
+ def __eq__(self, other: object) -> bool:
+ if isinstance(other, (AvailabilityKind, CompletionString.AvailabilityKindCompat)):
+ return self.value == other.value
+ else:
+ return NotImplemented
+
+ def __str__(self) -> str:
+ """
+ Converts enum value to string in the old camelCase format.
+ This is a temporary measure that will be changed in the future release
+ to return string in ALL_CAPS format, like for other enums.
+ """
+
+ warnings.warn(
+ "String representation of 'CompletionString.availability' will be "
+ "changed in a future release from 'camelCase' to 'ALL_CAPS' to "
+ "match other enums. 'CompletionString.availability' can be "
+ "compared to 'AvailabilityKind' directly, "
+ "without conversion to string.",
+ DeprecationWarning,
+ )
+ # Remove underscores
+ components = self.name.split("_")
+ # Upper-camel case each split component
+ components = [component.lower().capitalize() for component in components]
+ return "".join(components)
+
+ AVAILABLE = 0
+ DEPRECATED = 1
+ NOT_AVAILABLE = 2
+ NOT_ACCESSIBLE = 3
+
+
def __len__(self) -> int:
return self.num_chunks
@@ -3170,7 +3215,7 @@ def priority(self) -> int:
@property
def availability(self) -> AvailabilityKindCompat:
res = conf.lib.clang_getCompletionAvailability(self.obj)
- return AvailabilityKindCompat.from_id(res)
+ return CompletionString.AvailabilityKindCompat.from_id(res)
@property
def briefComment(self) -> str:
@@ -3187,50 +3232,6 @@ def __repr__(self) -> str:
+ str(self.briefComment)
)
-# AvailabilityKindCompat is an exact copy of AvailabilityKind, except for __str__.
-# This is a temporary measure to keep the string representation the same
-# until we change CompletionString.availability to return AvailabilityKind,
-# like Cursor.availability does.
-# Note that deriving from AvailabilityKind directly is not possible.
-class AvailabilityKindCompat(BaseEnumeration):
- """
- Describes the availability of an entity.
- It is deprecated in favor of AvailabilityKind.
- """
-
- # Ensure AvailabilityKindCompat is comparable with AvailabilityKind
- def __eq__(self, other: object) -> bool:
- if isinstance(other, (AvailabilityKind, AvailabilityKindCompat)):
- return self.value == other.value
- else:
- return NotImplemented
-
- def __str__(self) -> str:
- """
- Converts enum value to string in the old camelCase format.
- This is a temporary measure that will be changed in the future release
- to return string in ALL_CAPS format, like for other enums.
- """
-
- warnings.warn(
- "String representation of 'CompletionString.availability' will be "
- "changed in a future release from 'camelCase' to 'ALL_CAPS' to "
- "match other enums. 'CompletionString.availability' can be "
- "compared to 'AvailabilityKind' directly, "
- "without conversion to string.",
- DeprecationWarning,
- )
- # Remove underscores
- components = self.name.split("_")
- # Upper-camel case each split component
- components = [component.lower().capitalize() for component in components]
- return "".join(components)
-
- AVAILABLE = 0
- DEPRECATED = 1
- NOT_AVAILABLE = 2
- NOT_ACCESSIBLE = 3
-
class CodeCompletionResult(Structure):
_fields_ = [("cursorKind", c_int), ("completionString", c_object_p)]
diff --git a/clang/bindings/python/tests/cindex/test_code_completion.py b/clang/bindings/python/tests/cindex/test_code_completion.py
index d438115c1d054..c082a004df766 100644
--- a/clang/bindings/python/tests/cindex/test_code_completion.py
+++ b/clang/bindings/python/tests/cindex/test_code_completion.py
@@ -1,4 +1,4 @@
-from clang.cindex import AvailabilityKind, AvailabilityKindCompat, TranslationUnit
+from clang.cindex import AvailabilityKind, CompletionString, TranslationUnit
import unittest
from pathlib import Path
@@ -138,10 +138,10 @@ class Q : public P {
self.check_completion_results(cr, expected)
def test_availability_kind_compat_(self):
- numKinds = len(AvailabilityKindCompat)
+ numKinds = len(CompletionString.AvailabilityKindCompat)
# Compare with regular kind
- for compatKind in AvailabilityKindCompat:
+ for compatKind in CompletionString.AvailabilityKindCompat:
commonKind = AvailabilityKind.from_id(compatKind.value)
nextKindId = (compatKind.value + 1) % numKinds
commonKindUnequal = AvailabilityKind.from_id(nextKindId)
@@ -151,10 +151,10 @@ def test_availability_kind_compat_(self):
self.assertNotEqual(compatKind, commonKindUnequal)
# Compare two compat kinds
- for compatKind in AvailabilityKindCompat:
- compatKind2 = AvailabilityKindCompat.from_id(compatKind.value)
+ for compatKind in CompletionString.AvailabilityKindCompat:
+ compatKind2 = CompletionString.AvailabilityKindCompat.from_id(compatKind.value)
nextKindId = (compatKind.value + 1) % numKinds
- compatKind2Unequal = AvailabilityKindCompat.from_id(nextKindId)
+ compatKind2Unequal = CompletionString.AvailabilityKindCompat.from_id(nextKindId)
self.assertEqual(compatKind, compatKind2)
self.assertEqual(compatKind2, compatKind)
self.assertNotEqual(compatKind2Unequal, compatKind)
@@ -168,5 +168,5 @@ def test_compat_str(self):
3: "NotAccessible",
}
for id, string in kindStringMap.items():
- kind = AvailabilityKindCompat.from_id(id)
+ kind = CompletionString.AvailabilityKindCompat.from_id(id)
self.assertEqual(str(kind), string)
diff --git a/clang/bindings/python/tests/cindex/test_enums.py b/clang/bindings/python/tests/cindex/test_enums.py
index d290686b5ee71..f50bd219cee77 100644
--- a/clang/bindings/python/tests/cindex/test_enums.py
+++ b/clang/bindings/python/tests/cindex/test_enums.py
@@ -4,8 +4,8 @@
from clang.cindex import (
AccessSpecifier,
AvailabilityKind,
- AvailabilityKindCompat,
BinaryOperator,
+ CompletionString,
CursorKind,
ExceptionSpecificationKind,
LanguageKind,
@@ -26,7 +26,7 @@ class TestEnums(unittest.TestCase):
# Test all enum classes, except for AvailabilityKindCompat since it is
# just a copy of AvailabilityKind and has no corresponding C-class
enums = BaseEnumeration.__subclasses__()
- enums.remove(AvailabilityKindCompat)
+ enums.remove(CompletionString.AvailabilityKindCompat)
def test_from_id(self):
"""Check that kinds can be constructed from valid IDs"""
>From 82def13cc64f71a06b9dccd8de0ae0bca5c93bf4 Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Sat, 17 Jan 2026 19:30:44 +0900
Subject: [PATCH 15/16] Add release note
---
clang/docs/ReleaseNotes.rst | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4d886c3d55e7c..3c3afb8077957 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -54,6 +54,19 @@ Clang Frontend Potentially Breaking Changes
Clang Python Bindings Potentially Breaking Changes
--------------------------------------------------
+- Remove ``CompletionString.Availability``. No libclang interfaces returned instances of it.
+- Remove ``CompletionString.Kind`` and its container, ``availabilityKinds``.
+ ``CompletionString.availability`` now returns instances of ``CompletionString.AvailabilityKindCompat``.
+
+ Instances of ``AvailabilityKindCompat`` have the same ``__str__`` representation
+ as the previous ``CompletionString.Kind``s and are equality-compatible with
+ the existing ``AvailabilityKind`` enum. It will be replaced by ``AvailabilityKind``
+ in a future release. When this happens, the return type of ``CompletionString.availability``
+ will change to ``AvailabilityKind``, so it is recommended to use ``AvailabilityKind``
+ to compare with the return values of ``CompletionString.availability``.
+
+ In this release, uses of ``availabilityKinds`` need to be replaced by
+ ``CompletionString.AvailabilityKindCompat``.
What's New in Clang |release|?
==============================
>From f7b635d885e157c4dc020511927000a0c45d36ff Mon Sep 17 00:00:00 2001
From: Jannick Kremer <jannick.kremer at mailbox.org>
Date: Sat, 17 Jan 2026 19:45:37 +0900
Subject: [PATCH 16/16] Fix formatting
---
clang/bindings/python/clang/cindex.py | 5 +++--
.../bindings/python/tests/cindex/test_code_completion.py | 8 ++++++--
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index b1a0b159f5262..29c35628cf60c 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -3157,7 +3157,9 @@ class AvailabilityKindCompat(BaseEnumeration):
# Ensure AvailabilityKindCompat is comparable with AvailabilityKind
def __eq__(self, other: object) -> bool:
- if isinstance(other, (AvailabilityKind, CompletionString.AvailabilityKindCompat)):
+ if isinstance(
+ other, (AvailabilityKind, CompletionString.AvailabilityKindCompat)
+ ):
return self.value == other.value
else:
return NotImplemented
@@ -3188,7 +3190,6 @@ def __str__(self) -> str:
NOT_AVAILABLE = 2
NOT_ACCESSIBLE = 3
-
def __len__(self) -> int:
return self.num_chunks
diff --git a/clang/bindings/python/tests/cindex/test_code_completion.py b/clang/bindings/python/tests/cindex/test_code_completion.py
index c082a004df766..4c0ecca85e4f4 100644
--- a/clang/bindings/python/tests/cindex/test_code_completion.py
+++ b/clang/bindings/python/tests/cindex/test_code_completion.py
@@ -152,9 +152,13 @@ def test_availability_kind_compat_(self):
# Compare two compat kinds
for compatKind in CompletionString.AvailabilityKindCompat:
- compatKind2 = CompletionString.AvailabilityKindCompat.from_id(compatKind.value)
+ compatKind2 = CompletionString.AvailabilityKindCompat.from_id(
+ compatKind.value
+ )
nextKindId = (compatKind.value + 1) % numKinds
- compatKind2Unequal = CompletionString.AvailabilityKindCompat.from_id(nextKindId)
+ compatKind2Unequal = CompletionString.AvailabilityKindCompat.from_id(
+ nextKindId
+ )
self.assertEqual(compatKind, compatKind2)
self.assertEqual(compatKind2, compatKind)
self.assertNotEqual(compatKind2Unequal, compatKind)
More information about the cfe-commits
mailing list