llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (TsXor) <details> <summary>Changes</summary> This is part 1 as described in #<!-- -->101784. I moved `LibclangExports`, `LibclangError` and modified `Config` class to a new file: `binder.py`. It can now be used by `cindex.py` with a simple `from .binder import Config`. This PR doesn't modify any existing files, so it is safe to merge. However, @<!-- -->DeinAlptraum will need to manually delete `functionList`, `Config` class and `LibclangError` and add `from .binder import Config` to utilize its typing benefits. Note: compared to #<!-- -->101784, I added a check that prevents `ctyped` from importing `WINFUNCTYPE` when not on windows, which should fix failing linux tests. --- Patch is 63.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/101941.diff 4 Files Affected: - (added) clang/bindings/python/clang/binder.py (+804) - (added) clang/bindings/python/clang/ctyped.py (+433) - (added) clang/bindings/python/tests/ctyped/__init__.py () - (added) clang/bindings/python/tests/ctyped/test_stub_conversion.py (+357) ``````````diff diff --git a/clang/bindings/python/clang/binder.py b/clang/bindings/python/clang/binder.py new file mode 100644 index 0000000000000..8cc661a097cb2 --- /dev/null +++ b/clang/bindings/python/clang/binder.py @@ -0,0 +1,804 @@ +# pyright: reportPrivateUsage=false + +# Enable delayed evaluation of function annotations. +from __future__ import annotations + +import os +from ctypes import cdll +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, Union + +from typing_extensions import Annotated + +from .ctyped import * +from .ctyped import (ANNO_PARAMETER, ANNO_RESULT, ANNO_RESULT_CONVERTER, + generate_metadata) + +if TYPE_CHECKING: + from ctypes import CDLL + from types import EllipsisType + + from .cindex import (CCRStructure, CodeCompletionResults, + CompilationDatabase, CompileCommands, Cursor, + CursorKind, Diagnostic, File, FileInclusion, Index, + Rewriter, SourceLocation, SourceRange, StrPath, + TemplateArgumentKind, Token, TranslationUnit) + from .cindex import Type as ASTType + from .cindex import _CXString, _CXUnsavedFile +else: + EllipsisType = type(Ellipsis) + + +# delayed imports, a list of import name and their alias +# if alias is same as name, use `...` +CINDEX_DELAYED_IMPORTS: List[Tuple[str, Union[str, EllipsisType]]] = [ + ('CCRStructure', ...), + ('CodeCompletionResults', ...), + ('CompilationDatabase', ...), + ('CompileCommands', ...), + ('Cursor', ...), + ('CursorKind', ...), + ('Diagnostic', ...), + ('File', ...), + ('FileInclusion', ...), + ('Index', ...), + ('Rewriter', ...), + ('SourceLocation', ...), + ('SourceRange', ...), + ('TemplateArgumentKind', ...), + ('Token', ...), + ('TranslationUnit', ...), + ('Type', 'ASTType'), + ('_CXString', ...), + ('_CXUnsavedFile', ...), + ('c_interop_string', ...), +] + +def load_cindex_types() -> None: + cindex_imports: Dict[str, Any] = {} + from . import cindex + for name, alias in CINDEX_DELAYED_IMPORTS: + if isinstance(alias, EllipsisType): alias = name + cindex_imports[alias] = getattr(cindex, name) + globals().update(cindex_imports) + + +# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper +# object. This is a problem, because it means that from_parameter will see an +# integer and pass the wrong value on platforms where int != void*. Work around +# this by marshalling object arguments as void**. +CObjectP = CPointer[c_void_p] +c_object_p: Type[CObjectP] = convert_annotation(CObjectP) + + +# Register callback types +TranslationUnitIncludesCallback = Annotated[CFuncPointer, None, c_object_p, CPointer['SourceLocation'], c_uint, py_object] +CursorVisitCallback = Annotated[CFuncPointer, c_int, 'Cursor', 'Cursor', py_object] +FieldsVisitCallback = Annotated[CFuncPointer, c_int, 'Cursor', py_object] + +# TODO: these lines should replace the definition in cindex.py +#translation_unit_includes_callback: Type[CFuncPointer] = convert_annotation(TranslationUnitIncludesCallback, globals()) +#cursor_visit_callback: Type[CFuncPointer] = convert_annotation(CursorVisitCallback, globals()) +#fields_visit_callback: Type[CFuncPointer] = convert_annotation(FieldsVisitCallback, globals()) + + +# Misc object param/result types +# A type may only have param type or result type, this is normal. +ASTTypeResult = Annotated['ASTType', ANNO_RESULT, 'ASTType', 'ASTType.from_result'] + +CInteropStringParam = Annotated[Union[str, bytes, None], ANNO_PARAMETER, 'c_interop_string'] +CInteropStringResult = Annotated[Optional[str], ANNO_RESULT, 'c_interop_string', 'c_interop_string.to_python_string'] + +CXStringResult = Annotated[str, ANNO_RESULT, '_CXString', '_CXString.from_result'] + +CompilationDatabaseParam = Annotated['CompilationDatabase', ANNO_PARAMETER, c_object_p] +CompilationDatabaseResult = Annotated['CompilationDatabase', ANNO_RESULT, c_object_p, 'CompilationDatabase.from_result'] + +CompileCommandsResult = Annotated['CompileCommands', ANNO_RESULT, c_object_p, 'CompileCommands.from_result'] + +CursorResult = Annotated['Cursor', ANNO_RESULT, 'Cursor', 'Cursor.from_cursor_result'] +CursorNullableResult = Annotated[Optional['Cursor'], ANNO_RESULT, 'Cursor', 'Cursor.from_result'] + +DiagnosticParam = Annotated['Diagnostic', ANNO_PARAMETER, c_object_p] + +FileResult = Annotated['File', ANNO_RESULT, c_object_p, 'File.from_result'] + +TemplateArgumentKindResult = Annotated['TemplateArgumentKind', ANNO_RESULT_CONVERTER, 'TemplateArgumentKind.from_id'] + +TranslationUnitParam = Annotated['TranslationUnit', ANNO_PARAMETER, c_object_p] + + +# Functions strictly alphabetical order. +# NOTE: +# - These functions are stubs, they are not implemented, and is replaced by C functions at runtime. +# - If Config.compatibility_check is set to `False`, then a function is allowed to be missing. +# - If a function is missing in C library, it will not be replaced, thus causing NotImplementedError when called. +# - Missing functions are given a `_missing_` attribute, you can check it with `hasattr(conf.lib.xxx, '_missing_')`. +# - These stub functions are generated with a script from old data and manually corrected, so parameter names are missing. +class LibclangExports: + def clang_annotateTokens(self, p1: TranslationUnit, p2: CPointerParam[Token], p3: CUlongParam, p4: CPointerParam[Cursor]) -> CLongResult: + raise NotImplementedError + + def clang_CompilationDatabase_dispose(self, p1: CompilationDatabaseParam) -> CLongResult: + raise NotImplementedError + + def clang_CompilationDatabase_fromDirectory(self, p1: CInteropStringParam, p2: CPointerParam[c_ulong]) -> CompilationDatabaseResult: + raise NotImplementedError + + def clang_CompilationDatabase_getAllCompileCommands(self, p1: CompilationDatabaseParam) -> CompileCommandsResult: + raise NotImplementedError + + def clang_CompilationDatabase_getCompileCommands(self, p1: CompilationDatabaseParam, p2: CInteropStringParam) -> CompileCommandsResult: + raise NotImplementedError + + def clang_CompileCommands_dispose(self, p1: CObjectP) -> CLongResult: + raise NotImplementedError + + def clang_CompileCommands_getCommand(self, p1: CObjectP, p2: CUlongParam) -> CObjectP: + raise NotImplementedError + + def clang_CompileCommands_getSize(self, p1: CObjectP) -> CUlongResult: + raise NotImplementedError + + def clang_CompileCommand_getArg(self, p1: CObjectP, p2: CUlongParam) -> CXStringResult: + raise NotImplementedError + + def clang_CompileCommand_getDirectory(self, p1: CObjectP) -> CXStringResult: + raise NotImplementedError + + def clang_CompileCommand_getFilename(self, p1: CObjectP) -> CXStringResult: + raise NotImplementedError + + def clang_CompileCommand_getNumArgs(self, p1: CObjectP) -> CUlongResult: + raise NotImplementedError + + def clang_codeCompleteAt(self, p1: TranslationUnit, p2: CInteropStringParam, p3: CLongParam, p4: CLongParam, p5: CPointerParam[_CXUnsavedFile], p6: CLongParam, p7: CLongParam) -> CPointer[CCRStructure]: + raise NotImplementedError + + def clang_codeCompleteGetDiagnostic(self, p1: CodeCompletionResults, p2: CLongParam) -> Diagnostic: + raise NotImplementedError + + def clang_codeCompleteGetNumDiagnostics(self, p1: CodeCompletionResults) -> CLongResult: + raise NotImplementedError + + def clang_createIndex(self, p1: CLongParam, p2: CLongParam) -> CObjectP: + raise NotImplementedError + + def clang_createTranslationUnit(self, p1: Index, p2: CInteropStringParam) -> CObjectP: + raise NotImplementedError + + def clang_CXRewriter_create(self, p1: TranslationUnit) -> CObjectP: + raise NotImplementedError + + def clang_CXRewriter_dispose(self, p1: Rewriter) -> CLongResult: + raise NotImplementedError + + def clang_CXRewriter_insertTextBefore(self, p1: Rewriter, p2: SourceLocation, p3: CInteropStringParam) -> CLongResult: + raise NotImplementedError + + def clang_CXRewriter_overwriteChangedFiles(self, p1: Rewriter) -> CLongResult: + raise NotImplementedError + + def clang_CXRewriter_removeText(self, p1: Rewriter, p2: SourceRange) -> CLongResult: + raise NotImplementedError + + def clang_CXRewriter_replaceText(self, p1: Rewriter, p2: SourceRange, p3: CInteropStringParam) -> CLongResult: + raise NotImplementedError + + def clang_CXRewriter_writeMainFileToStdOut(self, p1: Rewriter) -> CLongResult: + raise NotImplementedError + + def clang_CXXConstructor_isConvertingConstructor(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXConstructor_isCopyConstructor(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXConstructor_isDefaultConstructor(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXConstructor_isMoveConstructor(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXField_isMutable(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXMethod_isConst(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXMethod_isDefaulted(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXMethod_isDeleted(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXMethod_isCopyAssignmentOperator(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXMethod_isMoveAssignmentOperator(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXMethod_isExplicit(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXMethod_isPureVirtual(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXMethod_isStatic(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXMethod_isVirtual(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_CXXRecord_isAbstract(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_Cursor_getStorageClass(self, p1: Cursor) -> CIntResult: + raise NotImplementedError + + def clang_EnumDecl_isScoped(self, p1: Cursor) -> bool: + raise NotImplementedError + + def clang_defaultDiagnosticDisplayOptions(self) -> CUlongResult: + raise NotImplementedError + + def clang_defaultSaveOptions(self, p1: TranslationUnit) -> CUlongResult: + raise NotImplementedError + + def clang_disposeCodeCompleteResults(self, p1: CodeCompletionResults) -> CLongResult: + raise NotImplementedError + + def clang_disposeDiagnostic(self, p1: Diagnostic) -> CLongResult: + raise NotImplementedError + + def clang_disposeIndex(self, p1: Index) -> CLongResult: + raise NotImplementedError + + def clang_disposeString(self, p1: _CXString) -> CLongResult: + raise NotImplementedError + + def clang_disposeTokens(self, p1: TranslationUnit, p2: CPointer[Token], p3: CUintParam) -> CLongResult: + raise NotImplementedError + + def clang_disposeTranslationUnit(self, p1: TranslationUnit) -> CLongResult: + raise NotImplementedError + + def clang_equalCursors(self, p1: Cursor, p2: Cursor) -> bool: + raise NotImplementedError + + def clang_equalLocations(self, p1: SourceLocation, p2: SourceLocation) -> bool: + raise NotImplementedError + + def clang_equalRanges(self, p1: SourceRange, p2: SourceRange) -> bool: + raise NotImplementedError + + def clang_equalTypes(self, p1: ASTType, p2: ASTType) -> bool: + raise NotImplementedError + + def clang_formatDiagnostic(self, p1: Diagnostic, p2: CUlongParam) -> CXStringResult: + raise NotImplementedError + + def clang_getAddressSpace(self, p1: ASTType) -> CIntResult: + raise NotImplementedError + + def clang_getArgType(self, p1: ASTType, p2: CUlongParam) -> ASTTypeResult: + raise NotImplementedError + + def clang_getArrayElementType(self, p1: ASTType) -> ASTTypeResult: + raise NotImplementedError + + def clang_getArraySize(self, p1: ASTType) -> CLonglongResult: + raise NotImplementedError + + def clang_getFieldDeclBitWidth(self, p1: Cursor) -> CLongResult: + raise NotImplementedError + + def clang_getCanonicalCursor(self, p1: Cursor) -> CursorResult: + raise NotImplementedError + + def clang_getCanonicalType(self, p1: ASTType) -> ASTTypeResult: + raise NotImplementedError + + def clang_getChildDiagnostics(self, p1: Diagnostic) -> CObjectP: + raise NotImplementedError + + def clang_getCompletionAvailability(self, p1: CObjectP) -> CLongResult: + raise NotImplementedError + + def clang_getCompletionBriefComment(self, p1: CObjectP) -> CXStringResult: + raise NotImplementedError + + def clang_getCompletionChunkCompletionString(self, p1: CObjectP, p2: CLongParam) -> CObjectP: + raise NotImplementedError + + def clang_getCompletionChunkKind(self, p1: CObjectP, p2: CLongParam) -> CLongResult: + raise NotImplementedError + + def clang_getCompletionChunkText(self, p1: CObjectP, p2: CLongParam) -> CXStringResult: + raise NotImplementedError + + def clang_getCompletionPriority(self, p1: CObjectP) -> CLongResult: + raise NotImplementedError + + def clang_getCString(self, p1: _CXString) -> CInteropStringResult: + raise NotImplementedError + + def clang_getCursor(self, p1: TranslationUnit, p2: SourceLocation) -> Cursor: + raise NotImplementedError + + def clang_getCursorAvailability(self, p1: Cursor) -> CLongResult: + raise NotImplementedError + + def clang_getCursorDefinition(self, p1: Cursor) -> CursorNullableResult: + raise NotImplementedError + + def clang_getCursorDisplayName(self, p1: Cursor) -> CXStringResult: + raise NotImplementedError + + def clang_getCursorExceptionSpecificationType(self, p1: Cursor) -> CIntResult: + raise NotImplementedError + + def clang_getCursorExtent(self, p1: Cursor) -> SourceRange: + raise NotImplementedError + + def clang_getCursorLexicalParent(self, p1: Cursor) -> CursorResult: + raise NotImplementedError + + def clang_getCursorLinkage(self, p1: Cursor) -> CIntResult: + raise NotImplementedError + + def clang_getCursorLocation(self, p1: Cursor) -> SourceLocation: + raise NotImplementedError + + def clang_getCursorReferenced(self, p1: Cursor) -> CursorNullableResult: + raise NotImplementedError + + def clang_getCursorReferenceNameRange(self, p1: Cursor, p2: CUlongParam, p3: CUlongParam) -> SourceRange: + raise NotImplementedError + + def clang_getCursorResultType(self, p1: Cursor) -> ASTTypeResult: + raise NotImplementedError + + def clang_getCursorSemanticParent(self, p1: Cursor) -> CursorResult: + raise NotImplementedError + + def clang_getCursorSpelling(self, p1: Cursor) -> CXStringResult: + raise NotImplementedError + + def clang_getCursorTLSKind(self, p1: Cursor) -> CIntResult: + raise NotImplementedError + + def clang_getCursorType(self, p1: Cursor) -> ASTTypeResult: + raise NotImplementedError + + def clang_getCursorUSR(self, p1: Cursor) -> CXStringResult: + raise NotImplementedError + + def clang_Cursor_getMangling(self, p1: Cursor) -> CXStringResult: + raise NotImplementedError + + def clang_getCXXAccessSpecifier(self, p1: Cursor) -> CUlongResult: + raise NotImplementedError + + def clang_getDeclObjCTypeEncoding(self, p1: Cursor) -> CXStringResult: + raise NotImplementedError + + def clang_getDiagnostic(self, p1: TranslationUnitParam, p2: CUlongParam) -> CObjectP: + raise NotImplementedError + + def clang_getDiagnosticCategory(self, p1: Diagnostic) -> CUlongResult: + raise NotImplementedError + + def clang_getDiagnosticCategoryText(self, p1: Diagnostic) -> CXStringResult: + raise NotImplementedError + + def clang_getDiagnosticFixIt(self, p1: Diagnostic, p2: CUlongParam, p3: CPointerParam[SourceRange]) -> CXStringResult: + raise NotImplementedError + + def clang_getDiagnosticInSet(self, p1: CObjectP, p2: CUlongParam) -> CObjectP: + raise NotImplementedError + + def clang_getDiagnosticLocation(self, p1: Diagnostic) -> SourceLocation: + raise NotImplementedError + + def clang_getDiagnosticNumFixIts(self, p1: Diagnostic) -> CUlongResult: + raise NotImplementedError + + def clang_getDiagnosticNumRanges(self, p1: Diagnostic) -> CUlongResult: + raise NotImplementedError + + def clang_getDiagnosticOption(self, p1: Diagnostic, p2: CPointerParam[_CXString]) -> CXStringResult: + raise NotImplementedError + + def clang_getDiagnosticRange(self, p1: Diagnostic, p2: CUlongParam) -> SourceRange: + raise NotImplementedError + + def clang_getDiagnosticSeverity(self, p1: Diagnostic) -> CLongResult: + raise NotImplementedError + + def clang_getDiagnosticSpelling(self, p1: Diagnostic) -> CXStringResult: + raise NotImplementedError + + def clang_getElementType(self, p1: ASTType) -> ASTTypeResult: + raise NotImplementedError + + def clang_getEnumConstantDeclUnsignedValue(self, p1: Cursor) -> CUlonglongResult: + raise NotImplementedError + + def clang_getEnumConstantDeclValue(self, p1: Cursor) -> CLonglongResult: + raise NotImplementedError + + def clang_getEnumDeclIntegerType(self, p1: Cursor) -> ASTTypeResult: + raise NotImplementedError + + def clang_getExceptionSpecificationType(self, p1: ASTType) -> CIntResult: + raise NotImplementedError + + def clang_getFile(self, p1: TranslationUnit, p2: CInteropStringParam) -> CObjectP: + raise NotImplementedError + + def clang_getFileName(self, p1: File) -> CXStringResult: + raise NotImplementedError + + def clang_getFileTime(self, p1: File) -> CUlongResult: + raise NotImplementedError + + def clang_getIBOutletCollectionType(self, p1: Cursor) -> ASTTypeResult: + raise NotImplementedError + + def clang_getIncludedFile(self, p1: Cursor) -> FileResult: + raise NotImplementedError + + def clang_getInclusions(self, p1: TranslationUnit, p2: TranslationUnitIncludesCallback, p3: CPyObject[List[FileInclusion]]) -> CLongResult: + raise NotImplementedError + + def clang_getInstantiationLocation(self, p1: SourceLocation, p2: CPointerParam[CObjectP], p3: CPointerParam[c_ulong], p4: CPointerParam[c_ulong], p5: CPointerParam[c_ulong]) -> CLongResult: + raise NotImplementedError + + def clang_getLocation(self, p1: TranslationUnit, p2: File, p3: CUlongParam, p4: CUlongParam) -> SourceLocation: + raise NotImplementedError + + def clang_getLocationForOffset(self, p1: TranslationUnit, p2: File, p3: CUlongParam) -> SourceLocation: + raise NotImplementedError + + def clang_getNullCursor(self) -> Cursor: + raise NotImplementedError + + def clang_getNumArgTypes(self, p1: ASTType) -> CUlongResult: + raise NotImplementedError + + def clang_getNumCompletionChunks(self, p1: CObjectP) -> CLongResult: + raise NotImplementedError + + def clang_getNumDiagnostics(self, p1: TranslationUnitParam) -> CUlongResult: + raise NotImplementedError + + def clang_getNumDiagnosticsInSet(self, p1: CObjectP) -> CUlongResult: + raise NotImplementedError + + def clang_getNumElements(self, p1: ASTType) -> CLonglongResult: + raise NotImplementedError + + def clang_getNumOverloadedDecls(self, p1: Cursor) -> CUlongResult: + raise NotImplementedError + + def clang_getOverloadedDecl(self, p1: Cursor, p2: CUlongParam) -> CursorResult: + raise NotImplementedError + + def clang_getPointeeType(self, p1: ASTType) -> ASTTypeResult: + raise NotImplementedError + + def clang_getRange(self, p1: SourceLocation, p2: SourceLocation) -> SourceRange: + raise NotImplementedError + + def clang_getRangeEnd(self, p1: SourceRange) -> SourceLocation: + raise NotImplementedError + + def clang_getRangeStart(self, p1: SourceRange) -> SourceLocation: + raise NotImplementedError + + d... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/101941 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits