Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
40 changes: 17 additions & 23 deletions pkgs/ffigen/lib/src/header_parser/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -175,39 +175,33 @@ List<Binding> transformBindings(List<Binding> bindings, Context context) {
applyConfigFiltersVisitation.indirectlyIncluded,
);

final findByValueCompoundsVisitation = FindByValueCompoundsVisitation();
visit(
final byValueCompounds = visit(
context,
findByValueCompoundsVisitation,
FindByValueCompoundsVisitation(),
FindByValueCompoundsVisitation.rootNodes(included),
);
final byValueCompounds = findByValueCompoundsVisitation.byValueCompounds;
).byValueCompounds;
visit(
context,
ClearOpaqueCompoundMembersVisitation(config, byValueCompounds, included),
bindings,
);

final findTransitiveDepsVisitation = FindTransitiveDepsVisitation();
visit(context, findTransitiveDepsVisitation, included);
final transitives = findTransitiveDepsVisitation.transitives;
final findDirectTransitiveDepsVisitation = FindDirectTransitiveDepsVisitation(
config,
final transitives = visit(
context,
FindTransitiveDepsVisitation(),
included,
directlyIncluded,
);
visit(context, findDirectTransitiveDepsVisitation, included);
final directTransitives =
findDirectTransitiveDepsVisitation.directTransitives;

final listBindingsVisitation = ListBindingsVisitation(
config,
).transitives;
final directTransitives = visit(
context,
FindDirectTransitiveDepsVisitation(config, included, directlyIncluded),
included,
transitives,
directTransitives,
);
visit(context, listBindingsVisitation, bindings);
final finalBindings = listBindingsVisitation.bindings;
).directTransitives;

final finalBindings = visit(
context,
ListBindingsVisitation(config, included, transitives, directTransitives),
bindings,
).bindings;
visit(context, MarkBindingsVisitation(finalBindings), bindings);

final finalBindingsList = finalBindings.toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class ClassDeclaration extends AstNode
/// If this class is a wrapper for another entity (class, struct, etc)
bool isWrapper;

// Whether this is a stub wrapper.
bool isStub;

/// An instance of the original entity that this class is wraping
PropertyDeclaration? wrappedInstance;

Expand Down Expand Up @@ -77,6 +80,7 @@ class ClassDeclaration extends AstNode
this.hasObjCAnnotation = false,
this.superClass,
this.isWrapper = false,
this.isStub = false,
this.wrappedInstance,
this.wrapperInitializer,
this.initializers = const [],
Expand Down
8 changes: 8 additions & 0 deletions pkgs/swift2objc/lib/src/ast/declarations/globals/globals.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ class GlobalFunctionDeclaration extends AstNode implements FunctionDeclaration {
this.async = false,
});

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

@override
void visitChildren(Visitor visitor) {
super.visitChildren(visitor);
Expand Down Expand Up @@ -104,6 +108,10 @@ class GlobalVariableDeclaration extends AstNode implements VariableDeclaration {
required this.async,
}) : assert(!(throws && !isConstant));

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

@override
void visitChildren(Visitor visitor) {
super.visitChildren(visitor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import '../generator.dart';

List<String> generateClass(ClassDeclaration declaration) {
return [
if (declaration.isStub) ..._generateStubComment(declaration),
...generateAvailability(declaration),
'${_generateClassHeader(declaration)} {',
...[
Expand All @@ -26,6 +27,14 @@ List<String> generateClass(ClassDeclaration declaration) {
];
}

List<String> _generateStubComment(ClassDeclaration declaration) {
final wrappedType = declaration.wrappedInstance!.type.swiftType;
return [
'// This wrapper is a stub. To generate the full wrapper, add $wrappedType',
"// to your config's include function.",
];
}

String _generateClassHeader(ClassDeclaration declaration) {
final header = StringBuffer();

Expand Down
85 changes: 80 additions & 5 deletions pkgs/swift2objc/lib/src/transformer/_core/dependencies.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,104 @@

import '../../ast/_core/interfaces/compound_declaration.dart';
import '../../ast/_core/interfaces/declaration.dart';
import '../../ast/declarations/compounds/class_declaration.dart';
import '../../ast/declarations/compounds/protocol_declaration.dart';
import '../../ast/declarations/compounds/struct_declaration.dart';
import '../../ast/declarations/globals/globals.dart';
import '../../ast/visitor.dart';

class DependencyVisitation extends Visitation {
Set<Declaration> topLevelDeclarations = {};
class FindIncludesVisitation extends Visitation {
final bool Function(Declaration) filter;
final includes = <Declaration>{};

FindIncludesVisitation(this.filter);

@override
void visitDeclaration(Declaration node) {
if (filter(node)) {
includes.add(node);
node.visitChildren(visitor);
}
}
}

class ListDeclsVisitation extends Visitation {
final Set<Declaration> includes;
final Set<Declaration> directTransitives;
final topLevelDecls = <Declaration>{};
final stubDecls = <Declaration>{};

ListDeclsVisitation(this.includes, this.directTransitives);

@override
void visitGlobalFunctionDeclaration(GlobalFunctionDeclaration node) {
node.visitChildren(visitor);
topLevelDeclarations.add(node);
topLevelDecls.add(node);
}

@override
void visitGlobalVariableDeclaration(GlobalVariableDeclaration node) {
node.visitChildren(visitor);
topLevelDeclarations.add(node);
topLevelDecls.add(node);
}

@override
void visitCompoundDeclaration(CompoundDeclaration node) {
node.visitChildren(visitor);

// Don't add nested classes etc to the top level declarations.
if (node.nestingParent == null) topLevelDeclarations.add(node);
if (node.nestingParent == null) topLevelDecls.add(node);

if (!includes.contains(node) && directTransitives.contains(node)) {
stubDecls.add(node);
}
}
}

class FindDirectTransitiveDepsVisitation extends Visitation {
final Set<Declaration> includes;
final directTransitives = <Declaration>{};

FindDirectTransitiveDepsVisitation(this.includes);

void _visitImpl(Declaration node, bool forceVisitChildren) {
directTransitives.add(node);
if (forceVisitChildren || includes.contains(node)) {
node.visitChildren(visitor);
}
}

@override
void visitDeclaration(Declaration node) => _visitImpl(node, true);

@override
void visitClassDeclaration(ClassDeclaration node) {
_visitImpl(node, false);

// Always visit the super type, protocols, and nesting parent, regardless of
// whether the node is directly included. This ensures that super types etc
// of stubs are also stubs, rather than being omitted like the rest of the
// stub's children.
visitor.visit(node.superClass);
visitor.visitAll(node.conformedProtocols);
visitor.visit(node.nestingParent);
}

@override
void visitProtocolDeclaration(ProtocolDeclaration node) {
_visitImpl(node, false);

// See visitClassDeclaration.
visitor.visitAll(node.conformedProtocols);
visitor.visit(node.nestingParent);
}

@override
void visitStructDeclaration(StructDeclaration node) {
_visitImpl(node, false);

// See visitClassDeclaration.
visitor.visitAll(node.conformedProtocols);
visitor.visit(node.nestingParent);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ ReferredType _createWrapperClass(DeclaredType primitiveType) {
(ReferredType, bool) maybeGetPrimitiveWrapper(
ReferredType type,
bool shouldWrapPrimitives,
TransformationMap transformationMap,
TransformationState state,
) {
if (type is! DeclaredType || !shouldWrapPrimitives) {
return (type, false);
Expand All @@ -57,7 +57,7 @@ ReferredType _createWrapperClass(DeclaredType primitiveType) {
return (type, false);
}

transformationMap[type.declaration] = (wrapper as DeclaredType).declaration;
state.map[type.declaration] = (wrapper as DeclaredType).declaration;
return (wrapper, true);
}

Expand Down
11 changes: 5 additions & 6 deletions pkgs/swift2objc/lib/src/transformer/_core/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import 'unique_namer.dart';
// that weird. Refactor this as part of the transformer refactor.

(String value, ReferredType type) maybeWrapValue(ReferredType type,
String value, UniqueNamer globalNamer, TransformationMap transformationMap,
String value, UniqueNamer globalNamer, TransformationState state,
{bool shouldWrapPrimitives = false}) {
final (wrappedPrimitiveType, returnsWrappedPrimitive) =
maybeGetPrimitiveWrapper(type, shouldWrapPrimitives, transformationMap);
maybeGetPrimitiveWrapper(type, shouldWrapPrimitives, state);
if (returnsWrappedPrimitive) {
return (
'${(wrappedPrimitiveType as DeclaredType).name}($value)',
Expand All @@ -38,15 +38,14 @@ import 'unique_namer.dart';
} else if (type is DeclaredType) {
final declaration = type.declaration;
if (declaration is TypealiasDeclaration) {
return maybeWrapValue(
declaration.target, value, globalNamer, transformationMap,
return maybeWrapValue(declaration.target, value, globalNamer, state,
shouldWrapPrimitives: shouldWrapPrimitives);
}

final transformedTypeDeclaration = transformDeclaration(
declaration,
globalNamer,
transformationMap,
state,
);

return (
Expand All @@ -55,7 +54,7 @@ import 'unique_namer.dart';
);
} else if (type is OptionalType) {
final (newValue, newType) =
maybeWrapValue(type.child, '$value!', globalNamer, transformationMap);
maybeWrapValue(type.child, '$value!', globalNamer, state);
return (
'$value == nil ? nil : $newValue',
OptionalType(newType),
Expand Down
Loading
Loading