diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml index c4f98d23..bb8526d2 100644 --- a/.github/workflows/test-package.yml +++ b/.github/workflows/test-package.yml @@ -14,13 +14,13 @@ env: jobs: # Check code formatting and static analysis on a single OS (linux) - # against Dart stable. + # against Dart master. analyze: runs-on: ubuntu-latest strategy: fail-fast: false matrix: - sdk: [stable] + sdk: [master] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v0.1 @@ -44,7 +44,7 @@ jobs: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v0.1 with: - channel: stable + channel: master - name: Install dependencies run: dart pub get - name: Install libclang-10-dev diff --git a/example/libclang-example/generated_bindings.dart b/example/libclang-example/generated_bindings.dart index 3b2fc267..df0e7f9e 100644 --- a/example/libclang-example/generated_bindings.dart +++ b/example/libclang-example/generated_bindings.dart @@ -2851,7 +2851,32 @@ class ArrayHelper_CXCursor_data_level0 { /// Describes the availability of a given entity on a particular platform, e.g., /// a particular class might only be available on Mac OS 10.7 or newer. -class CXPlatformAvailability extends ffi.Struct {} +class CXPlatformAvailability extends ffi.Struct { + /// A string that describes the platform for which this structure + /// provides availability information. + /// + /// Possible values are "ios" or "macos". + CXString Platform; + + /// The version number in which this entity was introduced. + CXVersion Introduced; + + /// The version number in which this entity was deprecated (but is + /// still available). + CXVersion Deprecated; + + /// The version number in which this entity was obsoleted, and therefore + /// is no longer available. + CXVersion Obsoleted; + + /// Whether the entity is unconditionally unavailable on this platform. + @ffi.Int32() + int Unavailable; + + /// An optional message to provide to a user of this API, e.g., to + /// suggest replacement APIs. + CXString Message; +} class CXCursorSetImpl extends ffi.Struct {} @@ -3202,20 +3227,127 @@ class ArrayHelper_CXIdxLoc_ptr_data_level0 { } /// Data for ppIncludedFile callback. -class CXIdxIncludedFileInfo extends ffi.Struct {} +class CXIdxIncludedFileInfo extends ffi.Struct { + /// Location of '#' in the \#include/\#import directive. + CXIdxLoc hashLoc; + + /// Filename as written in the \#include/\#import directive. + ffi.Pointer filename; + + /// The actual file that the \#include/\#import directive resolved to. + ffi.Pointer file; + + @ffi.Int32() + int isImport; + + @ffi.Int32() + int isAngled; + + /// Non-zero if the directive was automatically turned into a module + /// import. + @ffi.Int32() + int isModuleImport; +} /// Data for IndexerCallbacks#importedASTFile. -class CXIdxImportedASTFileInfo extends ffi.Struct {} +class CXIdxImportedASTFileInfo extends ffi.Struct { + /// Top level AST file containing the imported PCH, module or submodule. + ffi.Pointer file; + + /// The imported module or NULL if the AST file is a PCH. + ffi.Pointer module; + + /// Location where the file is imported. Applicable only for modules. + CXIdxLoc loc; + + /// Non-zero if an inclusion directive was automatically turned into + /// a module import. Applicable only for modules. + @ffi.Int32() + int isImplicit; +} + +class CXIdxAttrInfo extends ffi.Struct { + @ffi.Int32() + int kind; + + CXCursor cursor; + + CXIdxLoc loc; +} + +class CXIdxEntityInfo extends ffi.Struct { + @ffi.Int32() + int kind; + + @ffi.Int32() + int templateKind; + + @ffi.Int32() + int lang; -class CXIdxAttrInfo extends ffi.Struct {} + ffi.Pointer name; -class CXIdxEntityInfo extends ffi.Struct {} + ffi.Pointer USR; -class CXIdxContainerInfo extends ffi.Struct {} + CXCursor cursor; + + ffi.Pointer> attributes; + + @ffi.Uint32() + int numAttributes; +} + +class CXIdxContainerInfo extends ffi.Struct { + CXCursor cursor; +} + +class CXIdxIBOutletCollectionAttrInfo extends ffi.Struct { + ffi.Pointer attrInfo; + + ffi.Pointer objcClass; + + CXCursor classCursor; + + CXIdxLoc classLoc; +} -class CXIdxIBOutletCollectionAttrInfo extends ffi.Struct {} +class CXIdxDeclInfo extends ffi.Struct { + ffi.Pointer entityInfo; -class CXIdxDeclInfo extends ffi.Struct {} + CXCursor cursor; + + CXIdxLoc loc; + + ffi.Pointer semanticContainer; + + /// Generally same as #semanticContainer but can be different in + /// cases like out-of-line C++ member functions. + ffi.Pointer lexicalContainer; + + @ffi.Int32() + int isRedeclaration; + + @ffi.Int32() + int isDefinition; + + @ffi.Int32() + int isContainer; + + ffi.Pointer declAsContainer; + + /// Whether the declaration exists in code or was created implicitly + /// by the compiler, e.g. implicit Objective-C methods for properties. + @ffi.Int32() + int isImplicit; + + ffi.Pointer> attributes; + + @ffi.Uint32() + int numAttributes; + + @ffi.Uint32() + int flags; +} class CXIdxObjCContainerDeclInfo extends ffi.Struct { ffi.Pointer declInfo; @@ -3224,9 +3356,21 @@ class CXIdxObjCContainerDeclInfo extends ffi.Struct { int kind; } -class CXIdxBaseClassInfo extends ffi.Struct {} +class CXIdxBaseClassInfo extends ffi.Struct { + ffi.Pointer base; -class CXIdxObjCProtocolRefInfo extends ffi.Struct {} + CXCursor cursor; + + CXIdxLoc loc; +} + +class CXIdxObjCProtocolRefInfo extends ffi.Struct { + ffi.Pointer protocol; + + CXCursor cursor; + + CXIdxLoc loc; +} class CXIdxObjCProtocolRefListInfo extends ffi.Struct { ffi.Pointer> protocols; @@ -3243,7 +3387,17 @@ class CXIdxObjCInterfaceDeclInfo extends ffi.Struct { ffi.Pointer protocols; } -class CXIdxObjCCategoryDeclInfo extends ffi.Struct {} +class CXIdxObjCCategoryDeclInfo extends ffi.Struct { + ffi.Pointer containerInfo; + + ffi.Pointer objcClass; + + CXCursor classCursor; + + CXIdxLoc classLoc; + + ffi.Pointer protocols; +} class CXIdxObjCPropertyDeclInfo extends ffi.Struct { ffi.Pointer declInfo; @@ -3263,7 +3417,36 @@ class CXIdxCXXClassDeclInfo extends ffi.Struct { } /// Data for IndexerCallbacks#indexEntityReference. -class CXIdxEntityRefInfo extends ffi.Struct {} +class CXIdxEntityRefInfo extends ffi.Struct { + @ffi.Int32() + int kind; + + /// Reference cursor. + CXCursor cursor; + + CXIdxLoc loc; + + /// The entity that gets referenced. + ffi.Pointer referencedEntity; + + /// Immediate "parent" of the reference. For example: + /// + /// \code + /// Foo *var; + /// \endcode + /// + /// The parent of reference of type 'Foo' is the variable 'var'. + /// For references inside statement bodies of functions/methods, + /// the parentEntity will be the function/method. + ffi.Pointer parentEntity; + + /// Lexical container context of the reference. + ffi.Pointer container; + + /// Sets of symbol roles of the reference. + @ffi.Int32() + int role; +} /// A group of callbacks used by #clang_indexSourceFile and /// #clang_indexTranslationUnit. diff --git a/lib/src/header_parser/sub_parsers/structdecl_parser.dart b/lib/src/header_parser/sub_parsers/structdecl_parser.dart index 334349c8..c20e8d93 100644 --- a/lib/src/header_parser/sub_parsers/structdecl_parser.dart +++ b/lib/src/header_parser/sub_parsers/structdecl_parser.dart @@ -17,7 +17,6 @@ final _logger = Logger('ffigen.header_parser.structdecl_parser'); /// Holds temporary information regarding [struc] while parsing. class _ParsedStruc { Struc struc; - bool nestedStructMember = false; bool unimplementedMemberType = false; bool flexibleArrayMember = false; bool arrayMember = false; @@ -73,7 +72,6 @@ Struc parseStructDeclaration( void _setStructMembers(Pointer cursor) { _stack.top.arrayMember = false; - _stack.top.nestedStructMember = false; _stack.top.unimplementedMemberType = false; final resultCode = clang.clang_visitChildren_wrap( @@ -92,12 +90,6 @@ void _setStructMembers(Pointer cursor) { _logger.warning( 'Removed All Struct Members from: ${_stack.top.struc.name}(${_stack.top.struc.originalName}), Array members not supported'); return _stack.top.struc.members.clear(); - } else if (_stack.top.nestedStructMember) { - _logger.fine( - '---- Removed Struct members, reason: struct has struct members ${cursor.completeStringRepr()}'); - _logger.warning( - 'Removed All Struct Members from ${_stack.top.struc.name}(${_stack.top.struc.originalName}), Nested Structures not supported.'); - return _stack.top.struc.members.clear(); } else if (_stack.top.unimplementedMemberType) { _logger.fine( '---- Removed Struct members, reason: member with unimplementedtype ${cursor.completeStringRepr()}'); @@ -135,19 +127,7 @@ int _structMembersVisitor(Pointer cursor, _logger.finer('===== member: ${cursor.completeStringRepr()}'); final mt = cursor.type().toCodeGenTypeAndDispose(); - //TODO(4): Remove these when support for Structs by value arrives. - if (mt.broadType == BroadType.Struct) { - // Setting this flag will exclude adding members for this struct's - // bindings. - _stack.top.nestedStructMember = true; - } else if (mt.broadType == BroadType.ConstantArray) { - _stack.top.arrayMember = true; - if (mt.child.broadType == BroadType.Struct) { - // Setting this flag will exclude adding members for this struct's - // bindings. - _stack.top.nestedStructMember = true; - } - } else if (mt.broadType == BroadType.IncompleteArray) { + if (mt.broadType == BroadType.IncompleteArray) { // TODO(68): Structs with flexible Array Members are not supported. _stack.top.flexibleArrayMember = true; } else if (clang.clang_getFieldDeclBitWidth_wrap(cursor) != -1) { diff --git a/test/header_parser_tests/function_n_struct_test.dart b/test/header_parser_tests/function_n_struct_test.dart index 909c13a5..5e3be116 100644 --- a/test/header_parser_tests/function_n_struct_test.dart +++ b/test/header_parser_tests/function_n_struct_test.dart @@ -10,6 +10,7 @@ import 'package:test/test.dart'; import 'package:yaml/yaml.dart' as yaml; import 'package:ffigen/src/strings.dart' as strings; +import '../native_test/native_test_bindings.dart'; import '../test_utils.dart'; Library actual, expected; @@ -41,7 +42,8 @@ ${strings.headers}: expected.getBindingAsString('func2')); }); test('Struct2 nested struct member', () { - expect((actual.getBinding('Struct2') as Struc).members.isEmpty, true); + expect(actual.getBindingAsString('Struct2'), + expected.getBindingAsString('Struct2')); }); test('Struct3 flexible array member', () { expect((actual.getBinding('Struct3') as Struc).members.isEmpty, true); @@ -53,7 +55,13 @@ ${strings.headers}: } Library expectedLibrary() { - final struc2 = Struc(name: 'Struct2', members: []); + final struc1 = Struc(name: 'Struct1', members: []); + final struc2 = Struc(name: 'Struct2', members: [ + Member( + name: 'a', + type: Type.struct(struc1), + ), + ]); final struc3 = Struc(name: 'Struct3', members: []); return Library( name: 'Bindings', @@ -84,7 +92,12 @@ Library expectedLibrary() { SupportedNativeType.Void, ), ), - Struc(name: 'Struct4'), + Struc(name: 'Struct4', members: [ + Member( + name: 'a', + type: Type.struct(struc1), + ), + ]), ], ); } diff --git a/test/large_integration_tests/_expected_libclang_bindings.dart b/test/large_integration_tests/_expected_libclang_bindings.dart index 4b6325bd..2ec39ab5 100644 --- a/test/large_integration_tests/_expected_libclang_bindings.dart +++ b/test/large_integration_tests/_expected_libclang_bindings.dart @@ -3428,7 +3428,30 @@ abstract class CXVisibilityKind { /// Describes the availability of a given entity on a particular platform, e.g., /// a particular class might only be available on Mac OS 10.7 or newer. -class CXPlatformAvailability extends ffi.Struct {} +class CXPlatformAvailability extends ffi.Struct { + /// A string that describes the platform for which this structure provides + /// availability information. + CXString Platform; + + /// The version number in which this entity was introduced. + CXVersion Introduced; + + /// The version number in which this entity was deprecated (but is still + /// available). + CXVersion Deprecated; + + /// The version number in which this entity was obsoleted, and therefore is no + /// longer available. + CXVersion Obsoleted; + + /// Whether the entity is unconditionally unavailable on this platform. + @ffi.Int32() + int Unavailable; + + /// An optional message to provide to a user of this API, e.g., to suggest + /// replacement APIs. + CXString Message; +} /// Describe the "language" of the entity referred to by a cursor. abstract class CXLanguageKind { @@ -4212,10 +4235,43 @@ class ArrayHelper_CXIdxLoc_ptr_data_level0 { } /// Data for ppIncludedFile callback. -class CXIdxIncludedFileInfo extends ffi.Struct {} +class CXIdxIncludedFileInfo extends ffi.Struct { + /// Location of '#' in the #include/#import directive. + CXIdxLoc hashLoc; + + /// Filename as written in the #include/#import directive. + ffi.Pointer filename; + + /// The actual file that the #include/#import directive resolved to. + ffi.Pointer file; + + @ffi.Int32() + int isImport; + + @ffi.Int32() + int isAngled; + + /// Non-zero if the directive was automatically turned into a module import. + @ffi.Int32() + int isModuleImport; +} /// Data for IndexerCallbacks#importedASTFile. -class CXIdxImportedASTFileInfo extends ffi.Struct {} +class CXIdxImportedASTFileInfo extends ffi.Struct { + /// Top level AST file containing the imported PCH, module or submodule. + ffi.Pointer file; + + /// The imported module or NULL if the AST file is a PCH. + ffi.Pointer module; + + /// Location where the file is imported. Applicable only for modules. + CXIdxLoc loc; + + /// Non-zero if an inclusion directive was automatically turned into a module + /// import. Applicable only for modules. + @ffi.Int32() + int isImplicit; +} abstract class CXIdxEntityKind { static const int CXIdxEntity_Unexposed = 0; @@ -4273,19 +4329,92 @@ abstract class CXIdxAttrKind { static const int CXIdxAttr_IBOutletCollection = 3; } -class CXIdxAttrInfo extends ffi.Struct {} +class CXIdxAttrInfo extends ffi.Struct { + @ffi.Int32() + int kind; + + CXCursor cursor; + + CXIdxLoc loc; +} + +class CXIdxEntityInfo extends ffi.Struct { + @ffi.Int32() + int kind; + + @ffi.Int32() + int templateKind; + + @ffi.Int32() + int lang; + + ffi.Pointer name; + + ffi.Pointer USR; + + CXCursor cursor; + + ffi.Pointer> attributes; + + @ffi.Uint32() + int numAttributes; +} + +class CXIdxContainerInfo extends ffi.Struct { + CXCursor cursor; +} + +class CXIdxIBOutletCollectionAttrInfo extends ffi.Struct { + ffi.Pointer attrInfo; -class CXIdxEntityInfo extends ffi.Struct {} + ffi.Pointer objcClass; -class CXIdxContainerInfo extends ffi.Struct {} + CXCursor classCursor; -class CXIdxIBOutletCollectionAttrInfo extends ffi.Struct {} + CXIdxLoc classLoc; +} abstract class CXIdxDeclInfoFlags { static const int CXIdxDeclFlag_Skipped = 1; } -class CXIdxDeclInfo extends ffi.Struct {} +class CXIdxDeclInfo extends ffi.Struct { + ffi.Pointer entityInfo; + + CXCursor cursor; + + CXIdxLoc loc; + + ffi.Pointer semanticContainer; + + /// Generally same as #semanticContainer but can be different in cases like + /// out-of-line C++ member functions. + ffi.Pointer lexicalContainer; + + @ffi.Int32() + int isRedeclaration; + + @ffi.Int32() + int isDefinition; + + @ffi.Int32() + int isContainer; + + ffi.Pointer declAsContainer; + + /// Whether the declaration exists in code or was created implicitly by the + /// compiler, e.g. implicit Objective-C methods for properties. + @ffi.Int32() + int isImplicit; + + ffi.Pointer> attributes; + + @ffi.Uint32() + int numAttributes; + + @ffi.Uint32() + int flags; +} abstract class CXIdxObjCContainerKind { static const int CXIdxObjCContainer_ForwardRef = 0; @@ -4300,9 +4429,21 @@ class CXIdxObjCContainerDeclInfo extends ffi.Struct { int kind; } -class CXIdxBaseClassInfo extends ffi.Struct {} +class CXIdxBaseClassInfo extends ffi.Struct { + ffi.Pointer base; -class CXIdxObjCProtocolRefInfo extends ffi.Struct {} + CXCursor cursor; + + CXIdxLoc loc; +} + +class CXIdxObjCProtocolRefInfo extends ffi.Struct { + ffi.Pointer protocol; + + CXCursor cursor; + + CXIdxLoc loc; +} class CXIdxObjCProtocolRefListInfo extends ffi.Struct { ffi.Pointer> protocols; @@ -4319,7 +4460,17 @@ class CXIdxObjCInterfaceDeclInfo extends ffi.Struct { ffi.Pointer protocols; } -class CXIdxObjCCategoryDeclInfo extends ffi.Struct {} +class CXIdxObjCCategoryDeclInfo extends ffi.Struct { + ffi.Pointer containerInfo; + + ffi.Pointer objcClass; + + CXCursor classCursor; + + CXIdxLoc classLoc; + + ffi.Pointer protocols; +} class CXIdxObjCPropertyDeclInfo extends ffi.Struct { ffi.Pointer declInfo; @@ -4363,7 +4514,28 @@ abstract class CXSymbolRole { } /// Data for IndexerCallbacks#indexEntityReference. -class CXIdxEntityRefInfo extends ffi.Struct {} +class CXIdxEntityRefInfo extends ffi.Struct { + @ffi.Int32() + int kind; + + /// Reference cursor. + CXCursor cursor; + + CXIdxLoc loc; + + /// The entity that gets referenced. + ffi.Pointer referencedEntity; + + /// Immediate "parent" of the reference. For example: + ffi.Pointer parentEntity; + + /// Lexical container context of the reference. + ffi.Pointer container; + + /// Sets of symbol roles of the reference. + @ffi.Int32() + int role; +} /// A group of callbacks used by #clang_indexSourceFile and /// #clang_indexTranslationUnit.