@@ -4,6 +4,7 @@ import 'package:analyzer/dart/ast/ast.dart';
44import 'package:analyzer/dart/element/element2.dart' ;
55import 'package:analyzer/file_system/physical_file_system.dart' ;
66import 'package:collection/collection.dart' ;
7+ import 'package:dart_eval/dart_eval_bridge.dart' ;
78import 'package:dart_eval/src/eval/bindgen/bridge.dart' ;
89import 'package:dart_eval/src/eval/bindgen/bridge_declaration.dart' ;
910import 'package:dart_eval/src/eval/bindgen/configure.dart' ;
@@ -19,10 +20,14 @@ import 'package:package_config/package_config.dart';
1920import 'package:path/path.dart' ;
2021
2122/// Adapted from code by Alex Wallen (@a-wallen)
22- class Bindgen {
23+ class Bindgen implements BridgeDeclarationRegistry {
2324 static final resourceProvider = PhysicalResourceProvider .INSTANCE ;
2425 final includedPaths = [resourceProvider.pathContext.current];
2526
27+ final _bridgeDeclarations = < String , List <BridgeDeclaration >> {};
28+ final _exportedLibMappings = < String , String > {};
29+ final List <({String file, String uri, String name})> registerClasses = [];
30+
2631 AnalysisContextCollection ? _contextCollection;
2732
2833 void inject ({required Package package}) {
@@ -35,6 +40,73 @@ class Bindgen {
3540 includedPaths.add (normalize (filepath));
3641 }
3742
43+ // Manually define a (unresolved) bridge class
44+ @override
45+ void defineBridgeClass (BridgeClassDef classDef) {
46+ if (! classDef.bridge && ! classDef.wrap) {
47+ throw CompileError (
48+ 'Cannot define a bridge class that\' s not either bridge or wrap' );
49+ }
50+ final type = classDef.type;
51+ final spec = type.type.spec;
52+
53+ if (spec == null ) {
54+ throw CompileError (
55+ 'Cannot define a bridge class that\' s already resolved, a ref, or a generic function type' );
56+ }
57+
58+ final libraryDeclarations = _bridgeDeclarations[spec.library];
59+ if (libraryDeclarations == null ) {
60+ _bridgeDeclarations[spec.library] = [classDef];
61+ } else {
62+ libraryDeclarations.add (classDef);
63+ }
64+ }
65+
66+ /// Define a bridged enum definition to be used when binding.
67+ @override
68+ void defineBridgeEnum (BridgeEnumDef enumDef) {
69+ final spec = enumDef.type.spec;
70+ if (spec == null ) {
71+ throw CompileError (
72+ 'Cannot define a bridge enum that\' s already resolved, a ref, or a generic function type' );
73+ }
74+
75+ final libraryDeclarations = _bridgeDeclarations[spec.library];
76+ if (libraryDeclarations == null ) {
77+ _bridgeDeclarations[spec.library] = [enumDef];
78+ } else {
79+ libraryDeclarations.add (enumDef);
80+ }
81+ }
82+
83+ @override
84+ void addSource (DartSource source) {
85+ // Has no effect in binding generator
86+ }
87+
88+ /// Define a bridged top-level function declaration.
89+ @override
90+ void defineBridgeTopLevelFunction (BridgeFunctionDeclaration function) {
91+ final libraryDeclarations = _bridgeDeclarations[function.library];
92+ if (libraryDeclarations == null ) {
93+ _bridgeDeclarations[function.library] = [function];
94+ } else {
95+ libraryDeclarations.add (function);
96+ }
97+ }
98+
99+ /// Define a set of unresolved bridge classes
100+ void defineBridgeClasses (List <BridgeClassDef > classDefs) {
101+ for (final classDef in classDefs) {
102+ defineBridgeClass (classDef);
103+ }
104+ }
105+
106+ void addExportedLibraryMapping (String libraryUri, String exportUri) {
107+ _exportedLibMappings[libraryUri] = exportUri;
108+ }
109+
38110 Future <String ?> parse (
39111 io.File src, String filename, String uri, bool all) async {
40112 final resourceProvider = PhysicalResourceProvider .INSTANCE ;
@@ -50,7 +122,12 @@ class Bindgen {
50122 final analysisContext = _contextCollection! .contextFor (filePath);
51123 final session = analysisContext.currentSession;
52124 final analysisResult = await session.getResolvedUnit (filePath);
53- final ctx = BindgenContext (uri, all: all);
125+ final ctx = BindgenContext (
126+ filename,
127+ uri,
128+ all: all,
129+ bridgeDeclarations: _bridgeDeclarations,
130+ exportedLibMappings: _exportedLibMappings);
54131
55132 if (analysisResult is ResolvedUnitResult ) {
56133 // Access the resolved unit and analyze it
@@ -82,6 +159,7 @@ class Bindgen {
82159 .where ((declaration) => declaration.declaredFragment != null )
83160 .map ((declaration) =>
84161 _$instance (ctx, declaration.declaredFragment! .element))
162+ .toList ()
85163 .nonNulls;
86164
87165 if (resolved.isEmpty) {
@@ -123,16 +201,24 @@ class Bindgen {
123201
124202 final isBridge = bindAnnoValue? .getField ('bridge' )? .toBoolValue () ?? false ;
125203
204+ if (element.isSealed) {
205+ throw CompileError (
206+ 'Cannot bind sealed class ${element .name3 } as a bridge type. '
207+ 'Please remove the @Bind annotation, use a wrapper, or make the class non-sealed.' );
208+ }
209+
210+ registerClasses.add ((
211+ file: ctx.filename,
212+ uri: ctx.libOverrides[element.name3! ] ?? ctx.uri,
213+ name: '${element .name3 !}${isBridge ? '\$ bridge' : '' }' ,
214+ ));
215+
126216 if (isBridge) {
127- if (element.isSealed) {
128- throw CompileError (
129- 'Cannot bind sealed class ${element .name3 } as a bridge type. '
130- 'Please remove the @Bind annotation, use a wrapper, or make the class non-sealed.' );
131- }
132217
133218 return '''
134219/// dart_eval bridge binding for [${element .name3 }]
135220class \$ ${element .name3 }\$ bridge extends ${element .name3 } with \$ Bridge<${element .name3 }> {
221+ ${bindForwardedConstructors (ctx , element )}
136222/// Configure this class for use in a [Runtime]
137223${bindConfigureForRuntime (ctx , element , isBridge : true )}
138224/// Compile-time type specification of [\$ ${element .name3 }\$ bridge]
0 commit comments