@@ -4,6 +4,7 @@ import 'dart:convert';
44
55import 'package:build/build.dart' ;
66import 'package:glob/glob.dart' ;
7+ import 'package:objectbox_generator/src/builder_dirs.dart' ;
78import 'package:path/path.dart' as path;
89import 'package:objectbox/internal.dart' ;
910import 'package:dart_style/dart_style.dart' ;
@@ -27,25 +28,14 @@ class CodeBuilder extends Builder {
2728 r'$test$' : [path.join (_config.outDirTest, _config.codeFile)]
2829 };
2930
30- String _dir (BuildStep buildStep) => path.dirname (buildStep.inputId.path);
31-
32- String _outDir (BuildStep buildStep) {
33- var dir = _dir (buildStep);
34- if (dir.endsWith ('test' )) {
35- return dir + '/' + _config.outDirTest;
36- } else if (dir.endsWith ('lib' )) {
37- return dir + '/' + _config.outDirLib;
38- } else {
39- throw Exception ('Unrecognized path being generated: $dir ' );
40- }
41- }
42-
4331 @override
4432 FutureOr <void > build (BuildStep buildStep) async {
33+ final builderDirs = BuilderDirs (buildStep, _config);
34+
4535 // build() will be called only twice, once for the `lib` directory and once for the `test` directory
4636 // map from file name to a 'json' representation of entities
4737 final files = < String , List <dynamic >> {};
48- final glob = Glob (_dir (buildStep) + ' /**' + EntityResolver .suffix);
38+ final glob = Glob ('${ builderDirs . root } /**${ EntityResolver .suffix }' );
4939 await for (final input in buildStep.findAssets (glob)) {
5040 files[input.path] = json.decode (await buildStep.readAsString (input))! ;
5141 }
@@ -64,26 +54,27 @@ class CodeBuilder extends Builder {
6454 log.info ('Found ${entities .length } entities in: ${files .keys }' );
6555
6656 // update the model JSON with the read entities
67- final model = await updateModel (entities, buildStep);
57+ final model = await updateModel (entities, buildStep, builderDirs );
6858
6959 Pubspec ? pubspec;
7060 try {
71- final pubspecFile = File (path.join (_dir (buildStep) , '../pubspec.yaml' ));
61+ final pubspecFile = File (path.join (builderDirs.root , '../pubspec.yaml' ));
7262 pubspec = Pubspec .parse (pubspecFile.readAsStringSync ());
7363 } catch (e) {
7464 log.info ("Couldn't load pubspec.yaml: $e " );
7565 }
7666
7767 // generate binding code
78- updateCode (model, files.keys.toList (growable: false ), buildStep, pubspec);
68+ updateCode (model, files.keys.toList (growable: false ), buildStep,
69+ builderDirs, pubspec);
7970 }
8071
81- Future <ModelInfo > updateModel (
82- List < ModelEntity > entities, BuildStep buildStep ) async {
72+ Future <ModelInfo > updateModel (List < ModelEntity > entities, BuildStep buildStep,
73+ BuilderDirs builderDirs ) async {
8374 // load an existing model or initialize a new one
8475 ModelInfo model;
8576 final jsonId = AssetId (
86- buildStep.inputId.package, _outDir (buildStep) + '/' + _config.jsonFile);
77+ buildStep.inputId.package, '${ builderDirs . out }/${ _config .jsonFile }' );
8778 if (await buildStep.canRead (jsonId)) {
8879 log.info ('Using model: ${jsonId .path }' );
8980 model =
@@ -106,44 +97,54 @@ class CodeBuilder extends Builder {
10697 return model;
10798 }
10899
109- void updateCode (ModelInfo model, List <String > infoFiles, BuildStep buildStep,
110- Pubspec ? pubspec) async {
111- // If output directory is not package root directory,
112- // need to prefix imports with as many '../' to be relative from root.
113- final rootPath = _dir (buildStep);
114- final outPath = _outDir (buildStep);
115- final rootDir = Directory (rootPath).absolute;
116- var outDir = Directory (outPath).absolute;
117- var prefix = '' ;
100+ /// Returns a prefix for imports if the output directory is not the
101+ /// package root directory.
102+ ///
103+ /// Returns the empty string if the output directory is the root directory,
104+ /// otherwise adds as many '../' as necessary to be relative from root.
105+ ///
106+ /// Returns null if the root directory was not found by walking up from the
107+ /// output directory.
108+ static String ? getPrefixFor (BuilderDirs builderDirs) {
109+ // Note: comparing path strings below so paths should be normalized (they
110+ // are by BuilderDirs).
111+ final rootDir = Directory (builderDirs.root).absolute;
112+ var outDir = Directory (builderDirs.out).absolute;
118113
119114 if (! outDir.path.startsWith (rootDir.path)) {
120115 throw InvalidGenerationSourceError (
121116 'configured output_dir ${outDir .path } is not a '
122117 'subdirectory of the source directory ${rootDir .path }' );
123118 }
124119
120+ var prefix = '' ;
125121 while (outDir.path != rootDir.path) {
126122 final parent = outDir.parent;
127123 if (parent.path == outDir.path) {
128- log.warning (
129- 'Failed to find package root from output directory, generated imports might be incorrect.' );
130- prefix = '' ;
131- break ; // Reached top-most directory, stop searching.
124+ return null ; // Reached top-most directory, stop searching.
132125 }
133126 outDir = parent;
134127 prefix += '../' ;
135128 }
136- if (prefix.isNotEmpty) {
129+ return prefix;
130+ }
131+
132+ void updateCode (ModelInfo model, List <String > infoFiles, BuildStep buildStep,
133+ BuilderDirs builderDirs, Pubspec ? pubspec) async {
134+ var prefix = getPrefixFor (builderDirs);
135+ if (prefix == null ) {
136+ log.warning (
137+ 'Failed to find package root from output directory, generated imports might be incorrect (rootDir="${builderDirs .root }", outDir="${builderDirs .out }")' );
138+ } else if (prefix.isNotEmpty) {
137139 log.info (
138- 'Output directory not in package root, adding prefix to imports: ' +
139- prefix);
140+ 'Output directory not in package root, adding prefix to imports: $prefix ' );
140141 }
141142
142143 // transform '/lib/path/entity.objectbox.info' to 'path/entity.dart'
143144 final imports = infoFiles
144145 .map ((file) => file
145146 .replaceFirst (EntityResolver .suffix, '.dart' )
146- .replaceFirst (rootPath + ' /' , prefix))
147+ .replaceFirst ('${ builderDirs . root } /' , prefix ?? '' ))
147148 .toList ();
148149
149150 var code = CodeChunks .objectboxDart (model, imports, pubspec);
@@ -152,8 +153,8 @@ class CodeBuilder extends Builder {
152153 code = DartFormatter ().format (code);
153154 } finally {
154155 // Write the code even after a formatter error so it's easier to debug.
155- final codeId =
156- AssetId ( buildStep.inputId.package, outPath + '/' + _config.codeFile);
156+ final codeId = AssetId (
157+ buildStep.inputId.package, '${ builderDirs . out }/${ _config .codeFile }' );
157158 log.info ('Generating code: ${codeId .path }' );
158159 await buildStep.writeAsString (codeId, code);
159160 }
0 commit comments