Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
90cee4c
wip
liamappelbe Aug 10, 2026
5b86450
Lazy AST node wrappers
liamappelbe Aug 10, 2026
6e419f8
Don't visit children of excluded elements
liamappelbe Aug 10, 2026
b9226e4
wip
liamappelbe Aug 10, 2026
bddcbee
wip
liamappelbe Aug 11, 2026
a2996b4
wip
liamappelbe Aug 11, 2026
8ae873a
fixes
liamappelbe Aug 11, 2026
afd1c2f
bindings
liamappelbe Aug 11, 2026
96a42e0
Merge branch 'main' into ffigen_config_update_4
liamappelbe Aug 11, 2026
8e7fff0
clean up
liamappelbe Aug 11, 2026
a68e55f
clean up
liamappelbe Aug 11, 2026
21c4256
clean up
liamappelbe Aug 12, 2026
886635f
wip
liamappelbe Aug 12, 2026
ed80eb2
manual clean up
liamappelbe Aug 12, 2026
370fb10
regen
liamappelbe Aug 12, 2026
0a19f86
regen
liamappelbe Aug 12, 2026
79643a1
wip
liamappelbe Aug 12, 2026
80e8e1d
restore comment
liamappelbe Aug 12, 2026
7de78e5
revert unnecessary diff
liamappelbe Aug 12, 2026
592673f
revert spurious diff
liamappelbe Aug 12, 2026
243c02b
revert scope
liamappelbe Aug 12, 2026
5c368de
fix tests
liamappelbe Aug 12, 2026
f449200
clean
liamappelbe Aug 12, 2026
5541c18
docs
liamappelbe Aug 12, 2026
7bdf73b
revert junk
liamappelbe Aug 12, 2026
20d6fe8
clean up
liamappelbe Aug 12, 2026
0f0816c
regen
liamappelbe Aug 12, 2026
073fd94
fix
liamappelbe Aug 12, 2026
7076663
clean up
liamappelbe Aug 12, 2026
369f3d3
fix diffs
liamappelbe Aug 12, 2026
b8545e4
dediff
liamappelbe Aug 13, 2026
ed67128
fmt
liamappelbe Aug 13, 2026
bb3f278
fmt
liamappelbe Aug 13, 2026
f2e02e0
Merge branch 'main' into ffigen_config_update_4
liamappelbe Aug 13, 2026
a4bb0b7
wip
liamappelbe Aug 13, 2026
2af5f68
fix
liamappelbe Aug 13, 2026
02e8c3f
fix some tests
liamappelbe Aug 13, 2026
dab4b83
Fix tests
liamappelbe Aug 13, 2026
0bcbfdd
clean up
liamappelbe Aug 13, 2026
eb76e77
clean up
liamappelbe Aug 13, 2026
bb5543d
fix category bug
liamappelbe Aug 13, 2026
195d2b5
fix
liamappelbe Aug 13, 2026
090ddb6
cleaning
liamappelbe Aug 14, 2026
8fa206f
clean up example
liamappelbe Aug 14, 2026
f74dd48
clean up
liamappelbe Aug 14, 2026
01f2959
clean up
liamappelbe Aug 14, 2026
c68cee0
Merge branch 'main' into ffigen_config_update_4
liamappelbe Aug 14, 2026
f224827
migrate monorepo configs
liamappelbe Aug 14, 2026
05bb981
clean up
liamappelbe Aug 14, 2026
dae5b31
changelog
liamappelbe Aug 14, 2026
b02fafc
wip
liamappelbe Aug 14, 2026
00b86d9
wip
liamappelbe Aug 17, 2026
0dda3cf
stableRandomInclude
liamappelbe Aug 17, 2026
7c88237
visitFoo -> foo in inline Visitor
liamappelbe Aug 17, 2026
349653f
Merge branch 'ffigen_config_update_4' into ffigen_global_const
liamappelbe Aug 17, 2026
5f3fd76
Merge branch 'main' into ffigen_global_const
liamappelbe Aug 17, 2026
cd2c6b7
clean up
liamappelbe Aug 17, 2026
8b13691
clean up
liamappelbe Aug 17, 2026
19ee8df
clean up
liamappelbe Aug 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions pkgs/ffigen/lib/src/code_generator/constant.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import 'scope.dart';
import 'utils.dart';
import 'writer.dart';

/// A simple Constant.
/// Base class for constants.
///
/// Expands to -
/// ```dart
Expand All @@ -22,7 +22,7 @@ import 'writer.dart';
/// ```dart
/// const int name = 10;
/// ```
class Constant extends NoLookUpBinding {
abstract class Constant extends NoLookUpBinding {
/// The rawType is pasted as it is. E.g 'int', 'String', 'double'
final String rawType;

Expand Down Expand Up @@ -62,12 +62,6 @@ class Constant extends NoLookUpBinding {
string: s.toString(),
);
}

@override
public_ast.AstNode? toPublicAstNode() => public_ast.Constant(this);

@override
void visit(Visitation visitation) => visitation.visitConstant(this);
}

/// A [Constant] defined by an unnamed enum.
Expand Down
23 changes: 23 additions & 0 deletions pkgs/ffigen/lib/src/code_generator/global.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ class Global extends LookUpBinding with HasLocalScope {
final Type type;
final bool exposeSymbolAddress;
final bool constant;
final ConstantValue? constantValue;

@override
final bool loadFromNativeAsset;

bool isIncluded = false;

bool get isConst => constantValue != null && !exposeSymbolAddress;

Global({
super.usr,
super.originalName,
Expand All @@ -43,6 +46,7 @@ class Global extends LookUpBinding with HasLocalScope {
super.dartDoc,
this.exposeSymbolAddress = false,
this.constant = false,
this.constantValue,
this.loadFromNativeAsset = false,
}) : super(symbol: Symbol(name, SymbolKind.field));

Expand All @@ -54,6 +58,16 @@ class Global extends LookUpBinding with HasLocalScope {
final s = StringBuffer();
final globalVarName = name;
s.write(makeDartDoc(dartDoc));
if (isConst) {
s.write(
'const ${constantValue!.type} $globalVarName = '
'${constantValue!.value};\n\n',
);
return BindingString(
type: BindingStringType.global,
string: s.toString(),
);
}
final context = w.context;
final dartType = type.getDartType(context);
final ffiDartType = type.getFfiDartType(context);
Expand Down Expand Up @@ -173,6 +187,7 @@ class Global extends LookUpBinding with HasLocalScope {
@override
void visitChildren(Visitor visitor) {
super.visitChildren(visitor);
if (isConst) return;
visitor.visit(type);
visitor.visit(ffiImport);
if (loadFromNativeAsset && exposeSymbolAddress) {
Expand All @@ -183,3 +198,11 @@ class Global extends LookUpBinding with HasLocalScope {
@override
void visit(Visitation visitation) => visitation.visitGlobal(this);
}

/// A constant value for a [Global].
class ConstantValue {
final String type;
final String value;

const ConstantValue({required this.type, required this.value});
}
17 changes: 11 additions & 6 deletions pkgs/ffigen/lib/src/code_generator/library.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,27 @@ class Library {
// Seperate bindings which require lookup.
final lookupBindings = <LookUpBinding>[];
final nativeBindings = <LookUpBinding>[];
final noLookUpBindings = <Binding>[];
String? nativeAssetId;

final outputStyle = context.config.output.style;
final outputStyleAssetId = outputStyle is NativeExternalBindings
? outputStyle.assetId
: null;

for (final binding in bindings.whereType<LookUpBinding>()) {
final loadFromNativeAsset = binding.loadFromNativeAsset;
for (final binding in bindings) {
// All LookUpBindings are look-up bindings, except const Globals.
if (binding is LookUpBinding && !(binding is Global && binding.isConst)) {
final loadFromNativeAsset = binding.loadFromNativeAsset;

// At the moment, all bindings share their native config.
if (loadFromNativeAsset) nativeAssetId = outputStyleAssetId;
// At the moment, all bindings share their native config.
if (loadFromNativeAsset) nativeAssetId = outputStyleAssetId;

(loadFromNativeAsset ? nativeBindings : lookupBindings).add(binding);
(loadFromNativeAsset ? nativeBindings : lookupBindings).add(binding);
} else {
noLookUpBindings.add(binding);
}
}
final noLookUpBindings = bindings.whereType<NoLookUpBinding>().toList();
final hasNoLookupNativeHelper = noLookUpBindings.any(
(b) => b.hasNativeHelperFunctions,
);
Expand Down
5 changes: 2 additions & 3 deletions pkgs/ffigen/lib/src/code_generator/writer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ const _\$objcVersionCheck = $objcPrefix.ObjCVersionCheck(

// Warn for macros.
final hasMacroBindings = bindings.any(
(element) => element is Constant && element.usr.contains('@macro@'),
(element) => element is MacroConstant,
);
if (hasMacroBindings) {
context.logger.info(
Expand All @@ -237,8 +237,7 @@ const _\$objcVersionCheck = $objcPrefix.ObjCVersionCheck(

// Remove internal bindings and macros.
bindings.removeWhere((element) {
return element.isInternal ||
(element is Constant && element.usr.contains('@macro@'));
return element.isInternal || (element is MacroConstant);
});

// Sort bindings alphabetically by USR.
Expand Down
26 changes: 0 additions & 26 deletions pkgs/ffigen/lib/src/config_provider/public_ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -196,32 +196,6 @@ class Global extends DeclNode {
set isIncluded(bool value) => _global.isIncluded = value;
}

/// A C constant declaration.
class Constant extends DeclNode {
final internal.Constant _constant;

Constant(this._constant);

@override
void accept(Visitor visitor) => visitor.visitConstant(this);

@override
String get usr => _constant.usr;

@override
String get originalName => _constant.originalName;

@override
String get name => _constant.symbol.oldName;

@override
set name(String value) => _constant.symbol.oldName = value;

/// Whether this Constant should be included in code generation.
bool get isIncluded => _constant.isIncluded;
set isIncluded(bool value) => _constant.isIncluded = value;
}

/// A C macro constant declaration.
class MacroConstant extends DeclNode {
final internal.MacroConstant _macro;
Expand Down
8 changes: 0 additions & 8 deletions pkgs/ffigen/lib/src/config_provider/public_visitor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ abstract base class Visitor {
void Function(Union) union,
void Function(EnumClass) enumClass,
void Function(Global) global,
void Function(Constant) constant,
void Function(MacroConstant) macroConstant,
void Function(Typealias) typealias,
void Function(ObjCInterface) objCInterface,
Expand All @@ -99,7 +98,6 @@ abstract base class Visitor {
void visitUnion(Union node) {}
void visitEnum(EnumClass node) {}
void visitGlobal(Global node) {}
void visitConstant(Constant node) {}
void visitMacro(MacroConstant node) {}
void visitTypealias(Typealias node) {}
void visitObjCInterface(ObjCInterface node) {}
Expand All @@ -120,7 +118,6 @@ final class _CallbackVisitor extends Visitor {
final void Function(Union) _union;
final void Function(EnumClass) _enumClass;
final void Function(Global) _global;
final void Function(Constant) _constant;
final void Function(MacroConstant) _macroConstant;
final void Function(Typealias) _typealias;
final void Function(ObjCInterface) _objCInterface;
Expand All @@ -140,7 +137,6 @@ final class _CallbackVisitor extends Visitor {
void Function(Union) union = _defaultVisit,
void Function(EnumClass) enumClass = _defaultVisit,
void Function(Global) global = _defaultVisit,
void Function(Constant) constant = _defaultVisit,
void Function(MacroConstant) macroConstant = _defaultVisit,
void Function(Typealias) typealias = _defaultVisit,
void Function(ObjCInterface) objCInterface = _defaultVisit,
Expand All @@ -158,7 +154,6 @@ final class _CallbackVisitor extends Visitor {
_union = union,
_enumClass = enumClass,
_global = global,
_constant = constant,
_macroConstant = macroConstant,
_typealias = typealias,
_objCInterface = objCInterface,
Expand Down Expand Up @@ -190,9 +185,6 @@ final class _CallbackVisitor extends Visitor {
@override
void visitGlobal(Global node) => _global(node);

@override
void visitConstant(Constant node) => _constant(node);

@override
void visitMacro(MacroConstant node) => _macroConstant(node);

Expand Down
8 changes: 0 additions & 8 deletions pkgs/ffigen/lib/src/config_provider/yaml_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1373,14 +1373,6 @@ final class YamlConfigAstVisitor extends public_ast.Visitor {
}
}

@override
void visitConstant(public_ast.Constant node) {
node.isIncluded = config.globals.shouldInclude(_decl(node));
if (config.globals.rename(_decl(node)) case final rename?) {
node.name = rename;
}
}

@override
void visitMacro(public_ast.MacroConstant node) {
node.isIncluded = config.macroDecl.shouldInclude(_decl(node));
Expand Down
2 changes: 1 addition & 1 deletion pkgs/ffigen/lib/src/context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Context {
final CursorIndex cursorIndex;
final bindingsIndex = BindingsIndex();
final savedMacros = <String, Macro>{};
final unnamedEnumConstants = <Constant>[];
final unnamedEnumConstants = <UnnamedEnumConstant>[];
late final ObjCBuiltInFunctions objCBuiltInFunctions;
bool hasSourceErrors = false;
final reportedCommentRanges = <((String, int), (String, int))>{};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import '../utils.dart';
import 'api_availability.dart';

/// Saves unnamed enums.
List<Constant> saveUnNamedEnum(Context context, clang_types.CXCursor cursor) {
List<UnnamedEnumConstant> saveUnNamedEnum(
Context context,
clang_types.CXCursor cursor,
) {
final logger = context.logger;
final addedConstants = <Constant>[];
final addedConstants = <UnnamedEnumConstant>[];
cursor.visitChildren((child) {
try {
logger.finest(
Expand Down Expand Up @@ -40,7 +43,7 @@ List<Constant> saveUnNamedEnum(Context context, clang_types.CXCursor cursor) {
}

/// Adds the parameter to func in functiondecl_parser.dart.
Constant? _addUnNamedEnumConstant(
UnnamedEnumConstant? _addUnNamedEnumConstant(
Context context,
clang_types.CXCursor cursor,
) {
Expand Down
46 changes: 8 additions & 38 deletions pkgs/ffigen/lib/src/header_parser/sub_parsers/var_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,65 +21,34 @@ Binding? parseVarDeclaration(Context context, clang_types.CXCursor cursor) {
if (bindingsIndex.isSeenGlobalVar(usr)) {
return bindingsIndex.getSeenGlobalVar(usr);
}
if (bindingsIndex.isSeenVariableConstant(usr)) {
return bindingsIndex.getSeenVariableConstant(usr);
}

final decl = Declaration(usr: usr, originalName: name);
final cType = cursor.type();

// Try to evaluate as a constant first,
// unless the config asks for the variable's address.
if (cType.isConstQualified && !config.globals.includeSymbolAddress(decl)) {
ConstantValue? constantValue;
if (cType.isConstQualified) {
final evalResult = clang.clang_Cursor_Evaluate(cursor);
final evalKind = clang.clang_EvalResult_getKind(evalResult);
Constant? constant;

switch (evalKind) {
case clang_types.CXEvalResultKind.CXEval_Int:
final value = clang.clang_EvalResult_getAsLongLong(evalResult);
constant = Constant(
usr: usr,
originalName: name,
name: name,
dartDoc: getCursorDocComment(context, cursor),
rawType: 'int',
rawValue: value.toString(),
);
constantValue = ConstantValue(type: 'int', value: value.toString());
break;
case clang_types.CXEvalResultKind.CXEval_Float:
final value = clang.clang_EvalResult_getAsDouble(evalResult);
constant = Constant(
usr: usr,
originalName: name,
name: name,
dartDoc: getCursorDocComment(context, cursor),
rawType: 'double',
rawValue: writeDoubleAsString(value),
constantValue = ConstantValue(
type: 'double',
value: writeDoubleAsString(value),
);
break;
case clang_types.CXEvalResultKind.CXEval_StrLiteral:
final value = clang.clang_EvalResult_getAsStr(evalResult);
final rawValue = getWrittenStringRepresentation(name, value, context);
constant = Constant(
usr: usr,
originalName: name,
name: name,
dartDoc: getCursorDocComment(context, cursor),
rawType: 'String',
rawValue: "'$rawValue'",
);
constantValue = ConstantValue(type: 'String', value: "'$rawValue'");
break;
}
clang.clang_EvalResult_dispose(evalResult);

if (constant != null) {
logger.fine(
'++++ Adding Constant from Global: ${cursor.completeStringRepr()}',
);
bindingsIndex.addVariableConstantToSeen(usr, constant);
return constant;
}
}

logger.fine('++++ Adding Global: ${cursor.completeStringRepr()}');
Expand Down Expand Up @@ -107,6 +76,7 @@ Binding? parseVarDeclaration(Context context, clang_types.CXCursor cursor) {
dartDoc: getCursorDocComment(context, cursor),
exposeSymbolAddress: config.globals.includeSymbolAddress(decl),
constant: cType.isConstQualified,
constantValue: constantValue,
loadFromNativeAsset: nativeOutputStyle,
);
bindingsIndex.addGlobalVarToSeen(usr, global);
Expand Down
16 changes: 6 additions & 10 deletions pkgs/ffigen/lib/src/header_parser/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -516,10 +516,9 @@ class Macro {
class BindingsIndex {
// Tracks if bindings are already seen, Map key is USR obtained from libclang.
final Map<String, Func> _functions = {};
final Map<String, Constant> _unnamedEnumConstants = {};
final Map<String, UnnamedEnumConstant> _unnamedEnumConstants = {};
final Map<String, String> _macros = {};
final Map<String, Global> _globals = {};
final Map<String, Constant> _variableConstants = {};
final Map<String, Typealias> _typealiases = {};
final Map<String, EnumClass> _enums = {};
final Map<String, Compound> _compounds = {};
Expand All @@ -535,18 +534,15 @@ class BindingsIndex {
bool isSeenFunc(String usr) => _functions.containsKey(usr);
void addFuncToSeen(String usr, Func func) => _functions[usr] = func;
Func? getSeenFunc(String usr) => _functions[usr];
void addUnnamedEnumConstantToSeen(String usr, Constant enumConstant) =>
_unnamedEnumConstants[usr] = enumConstant;
Constant? getSeenUnnamedEnumConstant(String usr) =>
void addUnnamedEnumConstantToSeen(
String usr,
UnnamedEnumConstant enumConstant,
) => _unnamedEnumConstants[usr] = enumConstant;
UnnamedEnumConstant? getSeenUnnamedEnumConstant(String usr) =>
_unnamedEnumConstants[usr];
bool isSeenGlobalVar(String usr) => _globals.containsKey(usr);
void addGlobalVarToSeen(String usr, Global global) => _globals[usr] = global;
Global? getSeenGlobalVar(String usr) => _globals[usr];
bool isSeenVariableConstant(String usr) =>
_variableConstants.containsKey(usr);
void addVariableConstantToSeen(String usr, Constant constant) =>
_variableConstants[usr] = constant;
Constant? getSeenVariableConstant(String usr) => _variableConstants[usr];
bool isSeenTypealias(String usr) => _typealiases.containsKey(usr);
void addTypealiasToSeen(String usr, Typealias t) => _typealiases[usr] = t;
Typealias? getSeenTypealias(String usr) => _typealiases[usr];
Expand Down
Loading
Loading