blob: 52157ee104995e51603e5fca8326846691ee0fbb [file]
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:ffigen/ffigen.dart';
import 'package:ffigen/src/code_generator.dart' as cg;
import 'package:ffigen/src/header_parser.dart' as parser;
import 'package:test/test.dart';
import '../test_utils.dart';
void main() {
group('non_cpp_class', () {
late cg.Library library;
setUpAll(() {
library = parser.parse(
testContext(
// No `cpp:` entry: C++ support is off, so every class must take the
// struct path.
FfiGenerator(
output: Output(dart: DartOutput(path: Uri.file('unused'))),
input: Input(
entryPoints: [
Uri.file(absPath('test/header_parser_tests/non_cpp_class.h')),
],
compilerOptions: [
'-x',
'c++',
'-std=c++17',
if (Platform.isMacOS) ...['-isysroot', macSdkPath],
],
),
visitors: [Visitor(func: (node) => node.isIncluded = true)],
),
),
);
});
test('classes are not bound as C++ classes', () {
expect(library.bindings.whereType<cg.CppClass>(), isEmpty);
});
test('functions using classes through pointers are kept', () {
final funcNames = library.bindings
.whereType<cg.Func>()
.map((f) => f.originalName)
.toSet();
expect(
funcNames,
containsAll([
'widget_create',
'widget_size',
'widget_destroy',
'gadget_create',
]),
);
});
test('a class reached through a pointer is bound as a struct', () {
cg.Type returnTypeOf(String funcName) => library.bindings
.whereType<cg.Func>()
.firstWhere((f) => f.originalName == funcName)
.functionType
.returnType;
for (final (funcName, className) in [
('widget_create', 'Widget'),
('gadget_create', 'Gadget'),
]) {
final returnType = returnTypeOf(funcName);
expect(returnType, isA<cg.PointerType>());
final pointee = (returnType as cg.PointerType).child;
expect(pointee, isA<cg.Struct>());
expect((pointee as cg.Struct).originalName, className);
}
});
});
}