diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 42bc254..486a690 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,12 @@ name: Dart CI -on: push +on: + push: + branches: + - main + pull_request: + branches: + - main jobs: format: @@ -57,6 +63,17 @@ jobs: flutter test -j 1 working-directory: packages/isar_test + test_generator: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: subosito/flutter-action@v2 + - name: Run Generator Unit tests + run: | + dart pub get + dart test + working-directory: packages/isar_generator + drive_ios: strategy: matrix: diff --git a/packages/isar_generator/lib/src/isar_analyzer.dart b/packages/isar_generator/lib/src/isar_analyzer.dart index 6050e44..e75848c 100644 --- a/packages/isar_generator/lib/src/isar_analyzer.dart +++ b/packages/isar_generator/lib/src/isar_analyzer.dart @@ -10,7 +10,9 @@ import 'package:isar_generator/src/object_info.dart'; class IsarAnalyzer { ObjectInfo analyze(Element modelClass) { - if (modelClass is! ClassElement) { + if (modelClass is! ClassElement || + modelClass.isEnum || + modelClass.isMixin) { err('Only classes may be annotated with @Collection.', modelClass); } diff --git a/packages/isar_generator/pubspec.yaml b/packages/isar_generator/pubspec.yaml index f3e6101..1472e7e 100644 --- a/packages/isar_generator/pubspec.yaml +++ b/packages/isar_generator/pubspec.yaml @@ -18,4 +18,7 @@ dependencies: source_gen: ^1.2.2 dev_dependencies: + build_test: ^2.1.5 + matcher: ^0.12.12 + test: ^1.21.0 very_good_analysis: ^3.0.1 diff --git a/packages/isar_generator/test/error_test.dart b/packages/isar_generator/test/error_test.dart new file mode 100644 index 0000000..3b90980 --- /dev/null +++ b/packages/isar_generator/test/error_test.dart @@ -0,0 +1,33 @@ +import 'dart:io'; + +import 'package:build/build.dart'; +import 'package:build_test/build_test.dart'; +import 'package:isar_generator/isar_generator.dart'; +import 'package:test/test.dart'; + +void main() { + group('Error case', () { + for (final file in Directory('test/errors').listSync(recursive: true)) { + if (file is! File || !file.path.endsWith('.dart')) continue; + + test(file.path, () async { + final content = await file.readAsLines(); + + final errorMessage = content.first.split('//').last.trim(); + + var error = ''; + try { + await testBuilder( + getIsarGenerator(BuilderOptions.empty), + {'a|${file.path}': content.join('\n')}, + reader: await PackageAssetReader.currentIsolate(), + ); + } catch (e) { + error = e.toString(); + } + + expect(error.toLowerCase(), contains(errorMessage.toLowerCase())); + }); + } + }); +} diff --git a/packages/isar_generator/test/errors/class/abstract.dart b/packages/isar_generator/test/errors/class/abstract.dart new file mode 100644 index 0000000..670331f --- /dev/null +++ b/packages/isar_generator/test/errors/class/abstract.dart @@ -0,0 +1,8 @@ +// must not be abstract + +import 'package:isar/isar.dart'; + +@Collection() +abstract class Model { + int? id; +} diff --git a/packages/isar_generator/test/errors/class/constructor_named.dart b/packages/isar_generator/test/errors/class/constructor_named.dart new file mode 100644 index 0000000..02a8ecb --- /dev/null +++ b/packages/isar_generator/test/errors/class/constructor_named.dart @@ -0,0 +1,10 @@ +// unnamed constructor + +import 'package:isar/isar.dart'; + +@Collection() +class Model { + Model.create(); + + int? id; +} diff --git a/packages/isar_generator/test/errors/class/constructor_unknown_parameter.dart b/packages/isar_generator/test/errors/class/constructor_unknown_parameter.dart new file mode 100644 index 0000000..e41e620 --- /dev/null +++ b/packages/isar_generator/test/errors/class/constructor_unknown_parameter.dart @@ -0,0 +1,13 @@ +// constructor parameter does not match a property + +import 'package:isar/isar.dart'; + +@Collection() +class Model { + // ignore: avoid_unused_constructor_parameters + Model(this.prop1, String somethingElse); + + int? id; + + final String prop1; +} diff --git a/packages/isar_generator/test/errors/class/constructor_wrong_parameter.dart b/packages/isar_generator/test/errors/class/constructor_wrong_parameter.dart new file mode 100644 index 0000000..a574512 --- /dev/null +++ b/packages/isar_generator/test/errors/class/constructor_wrong_parameter.dart @@ -0,0 +1,13 @@ +// constructor parameter type does not match property type + +import 'package:isar/isar.dart'; + +@Collection() +class Model { + // ignore: avoid_unused_constructor_parameters + Model(int prop1); + + int? id; + + String prop1 = '5'; +} diff --git a/packages/isar_generator/test/errors/class/enum.dart b/packages/isar_generator/test/errors/class/enum.dart new file mode 100644 index 0000000..b563c8b --- /dev/null +++ b/packages/isar_generator/test/errors/class/enum.dart @@ -0,0 +1,7 @@ +// only classes + +import 'package:isar/isar.dart'; + +// ignore: invalid_annotation_target +@Collection() +enum Test { a, b, c } diff --git a/packages/isar_generator/test/errors/class/invalid_name.dart b/packages/isar_generator/test/errors/class/invalid_name.dart new file mode 100644 index 0000000..670331f --- /dev/null +++ b/packages/isar_generator/test/errors/class/invalid_name.dart @@ -0,0 +1,8 @@ +// must not be abstract + +import 'package:isar/isar.dart'; + +@Collection() +abstract class Model { + int? id; +} diff --git a/packages/isar_generator/test/errors/class/mixin.dart b/packages/isar_generator/test/errors/class/mixin.dart new file mode 100644 index 0000000..fe8debf --- /dev/null +++ b/packages/isar_generator/test/errors/class/mixin.dart @@ -0,0 +1,7 @@ +// only classes + +import 'package:isar/isar.dart'; + +// ignore: invalid_annotation_target +@Collection() +mixin Test {} diff --git a/packages/isar_generator/test/errors/class/private.dart b/packages/isar_generator/test/errors/class/private.dart new file mode 100644 index 0000000..e042467 --- /dev/null +++ b/packages/isar_generator/test/errors/class/private.dart @@ -0,0 +1,9 @@ +// must be public + +import 'package:isar/isar.dart'; + +@Collection() +// ignore: unused_element +class _Model { + int? id; +} diff --git a/packages/isar_generator/test/errors/class/variable.dart b/packages/isar_generator/test/errors/class/variable.dart new file mode 100644 index 0000000..11270c1 --- /dev/null +++ b/packages/isar_generator/test/errors/class/variable.dart @@ -0,0 +1,7 @@ +// only classes + +import 'package:isar/isar.dart'; + +// ignore: invalid_annotation_target +@Collection() +const t = 'hello'; diff --git a/packages/isar_generator/test/errors/id/converter.dart b/packages/isar_generator/test/errors/id/converter.dart new file mode 100644 index 0000000..4e4137c --- /dev/null +++ b/packages/isar_generator/test/errors/id/converter.dart @@ -0,0 +1,24 @@ +// Converters are not allowed for ids + +import 'package:isar/isar.dart'; + +@Collection() +class Test { + @Id() + @Converter() + late String id; +} + +class Converter extends TypeConverter { + const Converter(); + + @override + String fromIsar(int object) { + return object.toString(); + } + + @override + int toIsar(String object) { + return int.parse(object); + } +} diff --git a/packages/isar_generator/test/errors/id/duplicate.dart b/packages/isar_generator/test/errors/id/duplicate.dart new file mode 100644 index 0000000..c2dd52f --- /dev/null +++ b/packages/isar_generator/test/errors/id/duplicate.dart @@ -0,0 +1,12 @@ +// Two or more properties annotated with @Id() + +import 'package:isar/isar.dart'; + +@Collection() +class Test { + @Id() + int? id1; + + @Id() + int? id2; +} diff --git a/packages/isar_generator/test/errors/id/missing.dart b/packages/isar_generator/test/errors/id/missing.dart new file mode 100644 index 0000000..2164141 --- /dev/null +++ b/packages/isar_generator/test/errors/id/missing.dart @@ -0,0 +1,8 @@ +// no int property named "id" + +import 'package:isar/isar.dart'; + +@Collection() +class Test { + late String name; +} diff --git a/packages/isar_generator/test/errors/id/not_long.dart b/packages/isar_generator/test/errors/id/not_long.dart new file mode 100644 index 0000000..567a501 --- /dev/null +++ b/packages/isar_generator/test/errors/id/not_long.dart @@ -0,0 +1,9 @@ +// Only int ids are allowed + +import 'package:isar/isar.dart'; + +@Collection() +class Test { + @Id() + String? id; +} diff --git a/packages/isar_generator/test/errors/id/not_long2.dart b/packages/isar_generator/test/errors/id/not_long2.dart new file mode 100644 index 0000000..a18612d --- /dev/null +++ b/packages/isar_generator/test/errors/id/not_long2.dart @@ -0,0 +1,10 @@ +// Only int ids are allowed + +import 'package:isar/isar.dart'; + +@Collection() +class Test { + @Id() + @Size32() + int? id; +} diff --git a/packages/isar_generator/test/errors/index/bytes_not_hashed.dart b/packages/isar_generator/test/errors/index/bytes_not_hashed.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/composite_double_not_last.dart b/packages/isar_generator/test/errors/index/composite_double_not_last.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/composite_non_hashed_list.dart b/packages/isar_generator/test/errors/index/composite_non_hashed_list.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/composite_string_value_not_last.dart b/packages/isar_generator/test/errors/index/composite_string_value_not_last.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/contains_id.dart b/packages/isar_generator/test/errors/index/contains_id.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/double_list_hashed.dart b/packages/isar_generator/test/errors/index/double_list_hashed.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/duplicate_name.dart b/packages/isar_generator/test/errors/index/duplicate_name.dart new file mode 100644 index 0000000..b6ac213 --- /dev/null +++ b/packages/isar_generator/test/errors/index/duplicate_name.dart @@ -0,0 +1,14 @@ +// same name + +import 'package:isar/isar.dart'; + +@Collection() +class Model { + int? id; + + @Index(name: 'myindex') + String? prop1; + + @Index(name: 'myindex') + String? prop2; +} diff --git a/packages/isar_generator/test/errors/index/duplicate_property.dart b/packages/isar_generator/test/errors/index/duplicate_property.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/invalid_name.dart b/packages/isar_generator/test/errors/index/invalid_name.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/non_string_hashed.dart b/packages/isar_generator/test/errors/index/non_string_hashed.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/non_string_list_hashed_elements.dart b/packages/isar_generator/test/errors/index/non_string_list_hashed_elements.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/non_unique_replace.dart b/packages/isar_generator/test/errors/index/non_unique_replace.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/property_does_not_exist.dart b/packages/isar_generator/test/errors/index/property_does_not_exist.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/index/unique_contains_double.dart b/packages/isar_generator/test/errors/index/unique_contains_double.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/link/backlink_target_does_no_exist.dart b/packages/isar_generator/test/errors/link/backlink_target_does_no_exist.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/link/backlink_target_is_backlink.dart b/packages/isar_generator/test/errors/link/backlink_target_is_backlink.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/link/backlink_target_not_a_link.dart b/packages/isar_generator/test/errors/link/backlink_target_not_a_link.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/link/duplicate_name.dart b/packages/isar_generator/test/errors/link/duplicate_name.dart new file mode 100644 index 0000000..b958b92 --- /dev/null +++ b/packages/isar_generator/test/errors/link/duplicate_name.dart @@ -0,0 +1,18 @@ +// same name + +import 'package:isar/isar.dart'; + +@Collection() +class Model { + int? id; + + final IsarLink prop1 = IsarLink(); + + @Name('prop1') + final IsarLinks prop2 = IsarLinks(); +} + +@Collection() +class Model2 { + int? id; +} diff --git a/packages/isar_generator/test/errors/link/invalid_name.dart b/packages/isar_generator/test/errors/link/invalid_name.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/link/invalid_type.dart b/packages/isar_generator/test/errors/link/invalid_type.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/link/late.dart b/packages/isar_generator/test/errors/link/late.dart new file mode 100644 index 0000000..0a989e0 --- /dev/null +++ b/packages/isar_generator/test/errors/link/late.dart @@ -0,0 +1,15 @@ +// must not be late + +import 'package:isar/isar.dart'; + +@Collection() +class Model { + int? id; + + late IsarLink link; +} + +@Collection() +class Model2 { + int? id; +} diff --git a/packages/isar_generator/test/errors/link/nullable.dart b/packages/isar_generator/test/errors/link/nullable.dart new file mode 100644 index 0000000..d69d99a --- /dev/null +++ b/packages/isar_generator/test/errors/link/nullable.dart @@ -0,0 +1,15 @@ +// must not be nullable + +import 'package:isar/isar.dart'; + +@Collection() +class Model { + int? id; + + IsarLink? link; +} + +@Collection() +class Model2 { + int? id; +} diff --git a/packages/isar_generator/test/errors/link/target_not_a_collection.dart b/packages/isar_generator/test/errors/link/target_not_a_collection.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/link/type_nullable.dart b/packages/isar_generator/test/errors/link/type_nullable.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/property/converter_constructor_arguments.dart b/packages/isar_generator/test/errors/property/converter_constructor_arguments.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/property/converter_nullability.dart b/packages/isar_generator/test/errors/property/converter_nullability.dart new file mode 100644 index 0000000..e69de29 diff --git a/packages/isar_generator/test/errors/property/duplicate_name.dart b/packages/isar_generator/test/errors/property/duplicate_name.dart new file mode 100644 index 0000000..a7e14ca --- /dev/null +++ b/packages/isar_generator/test/errors/property/duplicate_name.dart @@ -0,0 +1,13 @@ +// same name + +import 'package:isar/isar.dart'; + +@Collection() +class Model { + int? id; + + String? prop1; + + @Name('prop1') + String? prop2; +} diff --git a/packages/isar_generator/test/errors/property/invalid_name.dart b/packages/isar_generator/test/errors/property/invalid_name.dart new file mode 100644 index 0000000..e69de29