Skip to content

Commit 5d00347

Browse files
Merge branch 'gh-486-fix-pkg-root-detector' into 'main'
Generator: do not warn if out dir is package root. See merge request objectbox/objectbox-dart!25
2 parents 1fcb507 + f9b1e16 commit 5d00347

File tree

8 files changed

+250
-45
lines changed

8 files changed

+250
-45
lines changed

.github/workflows/dart.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- uses: actions/checkout@v3
2222
- name: Install ObjectBox C-API
2323
run: ./install.sh
24-
- name: Test
24+
- name: Integration test
2525
run: ./generator/test.sh
2626

2727
# make sure the init script doesn't stop working - it's not something we usually run during normal development
@@ -54,10 +54,15 @@ jobs:
5454
with:
5555
sdk: ${{ matrix.sdk }}
5656
- uses: actions/checkout@v3
57+
- name: Generator Test
58+
working-directory: generator
59+
run: |
60+
../tool/pub.sh get
61+
../tool/pub.sh run test
5762
- name: Install ObjectBox C-API
5863
working-directory: objectbox
5964
run: ../install.sh
60-
- name: Test
65+
- name: Library Test
6166
working-directory: objectbox
6267
run: |
6368
../tool/pub.sh get

.gitlab-ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ analyze:
3535
- cd ..
3636
- dart format --set-exit-if-changed --fix .
3737

38-
# Runs generator integration tests, e.g. ensures generator works as expected.
38+
# Runs generator unit and integration tests, e.g. ensures generator works as expected.
3939
test-generator:linux:x64:
4040
extends: .cache
4141
stage: test
@@ -44,6 +44,9 @@ test-generator:linux:x64:
4444
script:
4545
- ./install.sh
4646
- ./generator/test.sh
47+
- cd generator
48+
- dart pub get
49+
- dart test
4750

4851
.test:
4952
extends: .cache
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import 'package:build/build.dart';
2+
import 'package:path/path.dart' as path;
3+
4+
import 'config.dart';
5+
6+
class BuilderDirs {
7+
/// The normalized path to the source code root directory.
8+
final String root;
9+
10+
/// The normalized path to the output directory for generated code.
11+
final String out;
12+
13+
BuilderDirs._(this.root, this.out);
14+
15+
factory BuilderDirs(BuildStep buildStep, Config config) {
16+
// Paths from Config are supplied by the user and may contain duplicate
17+
// slashes or be empty: normalize all paths to not return duplicate or
18+
// trailing slashes to ensure they can be compared via strings.
19+
final root = path.normalize(path.dirname(buildStep.inputId.path));
20+
final String out;
21+
if (root.endsWith('test')) {
22+
out = path.normalize('$root/${config.outDirTest}');
23+
} else if (root.endsWith('lib')) {
24+
out = path.normalize('$root/${config.outDirLib}');
25+
} else {
26+
throw ArgumentError('Is not lib or test directory: "$root"');
27+
}
28+
return BuilderDirs._(root, out);
29+
}
30+
}

generator/lib/src/code_builder.dart

Lines changed: 40 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'dart:convert';
44

55
import 'package:build/build.dart';
66
import 'package:glob/glob.dart';
7+
import 'package:objectbox_generator/src/builder_dirs.dart';
78
import 'package:path/path.dart' as path;
89
import 'package:objectbox/internal.dart';
910
import '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
}

generator/lib/src/config.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Config {
2222
final String outDirLib;
2323
final String outDirTest;
2424

25-
Config._(
25+
Config(
2626
{String? jsonFile,
2727
String? codeFile,
2828
String? outDirLib,
@@ -48,9 +48,9 @@ class Config {
4848
outDirLib = outDirTest = outDirYaml as String?;
4949
}
5050

51-
return Config._(outDirLib: outDirLib, outDirTest: outDirTest);
51+
return Config(outDirLib: outDirLib, outDirTest: outDirTest);
5252
}
5353
}
54-
return Config._();
54+
return Config();
5555
}
5656
}

generator/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ dependencies:
2020
yaml: ^3.0.0
2121

2222
dev_dependencies:
23+
test: ^1.16.5
2324
lints: ^2.0.1
2425

2526
# NOTE: remove before publishing

0 commit comments

Comments
 (0)