Add ISSUE_TEMPLATE

This commit is contained in:
kodjomoustapha 2023-11-06 15:31:20 +01:00
parent 13a693a54c
commit b0df26f3dd
80 changed files with 160 additions and 4441 deletions

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: ⚠️ Extension Issue
url: https://github.com/kodjodevf/mangayomi-extensions/issues/new
about: Issues and requests for extensions and sources should be opened in the mangayomi-extensions repository instead
- name: 🧑‍💻 Mangayomi help discord
url: https://discord.com/invite/EjfBuYahsP
about: Common questions are answered here

80
.github/ISSUE_TEMPLATE/report_issue.yml vendored Normal file
View file

@ -0,0 +1,80 @@
name: 🐞 Issue report
description: Report an issue in Mangayomi
labels: [Bug]
body:
- type: textarea
id: reproduce-steps
attributes:
label: Steps to reproduce
description: Provide an example of the issue.
placeholder: |
Example:
1. First step
2. Second step
3. Issue here
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: Expected behavior
description: Explain what you should expect to happen.
placeholder: |
Example:
"This should happen..."
validations:
required: true
- type: textarea
id: actual-behavior
attributes:
label: Actual behavior
description: Explain what actually happens.
placeholder: |
Example:
"This happened instead..."
validations:
required: true
- type: input
id: mangayomi-version
attributes:
label: Mangayomi version
description: You can find your Mangayomi version in **More → About**.
placeholder: |
Example: "0.0.67"
validations:
required: true
- type: input
id: device
attributes:
label: Device
description: List your device, model and the OS version.
placeholder: |
Example: "Google Pixel 5 android 11"
validations:
required: true
- type: textarea
id: other-details
attributes:
label: Other details
placeholder: |
Additional details and attachments.
- type: checkboxes
id: acknowledgements
attributes:
label: Acknowledgements
description: Read this carefully, we will close and ignore your issue if you skimmed through this.
options:
- label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open or closed issue.
required: true
- label: I have written a short but informative title.
required: true
- label: If this is an issue with an extension, I should be opening an issue in the [extensions repository](https://github.com/kodjodevf/mangayomi-extensions/issues/new).
required: true
- label: I have updated all installed extensions.
required: true

View file

@ -0,0 +1,32 @@
name: ⭐ Feature request
description: Suggest a feature to improve Mangayomi
labels: [Feature request]
body:
- type: textarea
id: feature-description
attributes:
label: Describe your suggested feature
description: How can Mangayomi be improved?
placeholder: |
Example:
"It should work like this..."
validations:
required: true
- type: textarea
id: other-details
attributes:
label: Other details
placeholder: |
Additional details and attachments.
- type: checkboxes
id: acknowledgements
attributes:
label: Acknowledgements
description: Read this carefully, we will close and ignore your issue if you skimmed through this.
options:
- label: I have searched the existing issues and this is a new ticket, **NOT** a duplicate or related to another open or closed issue.
required: true
- label: I have written a short but informative title.
required: true

View file

@ -1,30 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
version:
revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
- platform: macos
create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

View file

@ -99,58 +99,39 @@ class MainScreen extends ConsumerWidget {
useIndicator: true,
destinations: [
NavigationRailDestination(
selectedIcon: const Icon(
Icons.collections_bookmark,
),
selectedIcon:
const Icon(Icons.collections_bookmark),
icon: const Icon(
Icons.collections_bookmark_outlined,
),
Icons.collections_bookmark_outlined),
label: Padding(
padding: const EdgeInsets.only(top: 5),
child: Text(l10n.manga))),
NavigationRailDestination(
selectedIcon: const Icon(
Icons.video_collection,
),
selectedIcon:
const Icon(Icons.video_collection),
icon: const Icon(
Icons.video_collection_outlined,
),
Icons.video_collection_outlined),
label: Padding(
padding: const EdgeInsets.only(top: 5),
child: Text(l10n.anime),
)),
padding: const EdgeInsets.only(top: 5),
child: Text(l10n.anime))),
NavigationRailDestination(
selectedIcon: const Icon(
Icons.new_releases,
),
icon: const Icon(
Icons.new_releases_outlined,
),
selectedIcon: const Icon(Icons.history),
icon: const Icon(Icons.history_outlined),
label: Padding(
padding: const EdgeInsets.only(top: 5),
child: Text(l10n.history))),
NavigationRailDestination(
selectedIcon: const Icon(
Icons.history,
),
icon: const Icon(
Icons.history_outlined,
),
selectedIcon: const Icon(Icons.explore),
icon: const Icon(Icons.explore_outlined),
label: Padding(
padding: const EdgeInsets.only(top: 5),
child: Text(l10n.browse),
)),
padding: const EdgeInsets.only(top: 5),
child: Text(l10n.browse))),
NavigationRailDestination(
selectedIcon: const Icon(
Icons.more_horiz,
),
icon: const Icon(
Icons.more_horiz_outlined,
),
selectedIcon: const Icon(Icons.more_horiz),
icon: const Icon(Icons.more_horiz_outlined),
label: Padding(
padding: const EdgeInsets.only(top: 5),
child: Text(l10n.more),
)),
padding: const EdgeInsets.only(top: 5),
child: Text(l10n.more))),
],
selectedIndex: currentIndex,
onDestinationSelected: (newIndex) {
@ -201,44 +182,28 @@ class MainScreen extends ConsumerWidget {
selectedIndex: currentIndex,
destinations: [
NavigationDestination(
selectedIcon: const Icon(
Icons.collections_bookmark,
),
selectedIcon:
const Icon(Icons.collections_bookmark),
icon: const Icon(
Icons.collections_bookmark_outlined,
),
Icons.collections_bookmark_outlined),
label: l10n.manga),
NavigationDestination(
selectedIcon: const Icon(
Icons.video_collection,
),
icon: const Icon(
Icons.video_collection_outlined,
),
selectedIcon:
const Icon(Icons.video_collection),
icon:
const Icon(Icons.video_collection_outlined),
label: l10n.anime),
NavigationDestination(
selectedIcon: const Icon(
Icons.new_releases,
),
icon: const Icon(
Icons.new_releases_outlined,
),
selectedIcon: const Icon(Icons.history),
icon: const Icon(Icons.history_outlined),
label: l10n.history),
NavigationDestination(
selectedIcon: const Icon(
Icons.history,
),
icon: const Icon(
Icons.history_outlined,
),
selectedIcon: const Icon(Icons.explore),
icon: const Icon(Icons.explore_outlined),
label: l10n.browse),
NavigationDestination(
selectedIcon: const Icon(
Icons.more_horiz,
),
icon: const Icon(
Icons.more_horiz_outlined,
),
selectedIcon: const Icon(Icons.more_horiz),
icon: const Icon(Icons.more_horiz_outlined),
label: l10n.more),
],
onDestinationSelected: (newIndex) {

View file

@ -1 +0,0 @@
See [Isar Changelog](https://pub.dev/packages/isar/changelog)

View file

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -1 +0,0 @@
### Code generator for the [Isar Database](https://github.com/isar/isar) please go there for documentation.

View file

@ -1,9 +0,0 @@
include: package:very_good_analysis/analysis_options.yaml
analyzer:
errors:
cascade_invocations: ignore
avoid_positional_boolean_parameters: ignore
parameter_assignments: ignore
public_member_api_docs: ignore
use_string_buffers: ignore

View file

@ -1,8 +0,0 @@
builders:
isar_generator:
import: "package:isar_generator/isar_generator.dart"
builder_factories: ["getIsarGenerator"]
build_extensions: { ".dart": ["isar_generator.g.part"] }
auto_apply: dependents
build_to: cache
applies_builders: ["source_gen|combining_builder"]

View file

@ -1,11 +0,0 @@
import 'package:build/build.dart';
import 'package:isar_generator/src/collection_generator.dart';
import 'package:source_gen/source_gen.dart';
Builder getIsarGenerator(BuilderOptions options) => SharedPartBuilder(
[
IsarCollectionGenerator(),
IsarEmbeddedGenerator(),
],
'isar_generator',
);

View file

@ -1,119 +0,0 @@
import 'package:dartx/dartx.dart';
import 'package:isar_generator/src/object_info.dart';
String generateByIndexExtension(ObjectInfo oi) {
final uniqueIndexes = oi.indexes.where((e) => e.unique).toList();
if (uniqueIndexes.isEmpty) {
return '';
}
var code =
'extension ${oi.dartName}ByIndex on IsarCollection<${oi.dartName}> {';
for (final index in uniqueIndexes) {
code += generateSingleByIndex(oi, index);
code += generateAllByIndex(oi, index);
if (!index.properties.first.isMultiEntry) {
code += generatePutByIndex(oi, index);
}
}
return '''
$code
}''';
}
extension on ObjectIndex {
String get dartName {
return properties.map((e) => e.property.dartName.capitalize()).join();
}
}
String generateSingleByIndex(ObjectInfo oi, ObjectIndex index) {
final params = index.properties
.map((i) => '${i.property.dartType} ${i.property.dartName}')
.join(',');
final paramsList = index.properties.map((i) => i.property.dartName).join(',');
return '''
Future<${oi.dartName}?> getBy${index.dartName}($params) {
return getByIndex(r'${index.name}', [$paramsList]);
}
${oi.dartName}? getBy${index.dartName}Sync($params) {
return getByIndexSync(r'${index.name}', [$paramsList]);
}
Future<bool> deleteBy${index.dartName}($params) {
return deleteByIndex(r'${index.name}', [$paramsList]);
}
bool deleteBy${index.dartName}Sync($params) {
return deleteByIndexSync(r'${index.name}', [$paramsList]);
}
''';
}
String generateAllByIndex(ObjectInfo oi, ObjectIndex index) {
String valsName(ObjectProperty p) => '${p.dartName}Values';
final props = index.properties;
final params = props
.map((ip) => 'List<${ip.property.dartType}> ${valsName(ip.property)}')
.join(',');
String createValues;
if (props.length == 1) {
final p = props.first.property;
createValues = 'final values = ${valsName(p)}.map((e) => [e]).toList();';
} else {
final lenAssert = props
.sublist(1)
.map((i) => '${valsName(i.property)}.length == len')
.join('&&');
createValues = '''
final len = ${valsName(props.first.property)}.length;
assert($lenAssert, 'All index values must have the same length');
final values = <List<dynamic>>[];
for (var i = 0; i < len; i++) {
values.add([${props.map((ip) => '${valsName(ip.property)}[i]').join(',')}]);
}
''';
}
return '''
Future<List<${oi.dartName}?>> getAllBy${index.dartName}($params) {
$createValues
return getAllByIndex(r'${index.name}', values);
}
List<${oi.dartName}?> getAllBy${index.dartName}Sync($params) {
$createValues
return getAllByIndexSync(r'${index.name}', values);
}
Future<int> deleteAllBy${index.dartName}($params) {
$createValues
return deleteAllByIndex(r'${index.name}', values);
}
int deleteAllBy${index.dartName}Sync($params) {
$createValues
return deleteAllByIndexSync(r'${index.name}', values);
}
''';
}
String generatePutByIndex(ObjectInfo oi, ObjectIndex index) {
return '''
Future<Id> putBy${index.dartName}(${oi.dartName} object) {
return putByIndex(r'${index.name}', object);
}
Id putBy${index.dartName}Sync(${oi.dartName} object, {bool saveLinks = true}) {
return putByIndexSync(r'${index.name}', object, saveLinks: saveLinks);
}
Future<List<Id>> putAllBy${index.dartName}(List<${oi.dartName}> objects) {
return putAllByIndex(r'${index.name}', objects);
}
List<Id> putAllBy${index.dartName}Sync(List<${oi.dartName}> objects, {bool saveLinks = true}) {
return putAllByIndexSync(r'${index.name}', objects, saveLinks: saveLinks);
}
''';
}

View file

@ -1,112 +0,0 @@
import 'package:dartx/dartx.dart';
import 'package:isar/isar.dart';
import 'package:isar_generator/src/isar_type.dart';
import 'package:isar_generator/src/object_info.dart';
String generateSchema(ObjectInfo object) {
var code = 'const ${object.dartName.capitalize()}Schema = ';
if (!object.isEmbedded) {
code += 'CollectionSchema(';
} else {
code += 'Schema(';
}
final properties = object.objectProperties
.mapIndexed(
(i, e) => "r'${e.isarName}': ${_generatePropertySchema(object, i)}",
)
.join(',');
code += '''
name: r'${object.isarName}',
id: ${object.id},
properties: {$properties},
estimateSize: ${object.estimateSizeName},
serialize: ${object.serializeName},
deserialize: ${object.deserializeName},
deserializeProp: ${object.deserializePropName},''';
if (!object.isEmbedded) {
final indexes = object.indexes
.map((e) => "r'${e.name}': ${_generateIndexSchema(e)}")
.join(',');
final links = object.links
.map((e) => "r'${e.isarName}': ${_generateLinkSchema(object, e)}")
.join(',');
final embeddedSchemas = object.embeddedDartNames.entries
.map((e) => "r'${e.key}': ${e.value.capitalize()}Schema")
.join(',');
code += '''
idName: r'${object.idProperty.isarName}',
indexes: {$indexes},
links: {$links},
embeddedSchemas: {$embeddedSchemas},
getId: ${object.getIdName},
getLinks: ${object.getLinksName},
attach: ${object.attachName},
version: '${Isar.version}',
''';
}
return '$code);';
}
String _generatePropertySchema(ObjectInfo object, int index) {
final property = object.objectProperties[index];
var enumMap = '';
if (property.isEnum) {
enumMap = 'enumMap: ${property.enumValueMapName(object)},';
}
var target = '';
if (property.targetIsarName != null) {
target = "target: r'${property.targetIsarName}',";
}
return '''
PropertySchema(
id: $index,
name: r'${property.isarName}',
type: IsarType.${property.isarType.name},
$enumMap
$target
)
''';
}
String _generateIndexSchema(ObjectIndex index) {
final properties = index.properties.map((e) {
return '''
IndexPropertySchema(
name: r'${e.property.isarName}',
type: IndexType.${e.type.name},
caseSensitive: ${e.caseSensitive},
)''';
}).join(',');
return '''
IndexSchema(
id: ${index.id},
name: r'${index.name}',
unique: ${index.unique},
replace: ${index.replace},
properties: [$properties],
)''';
}
String _generateLinkSchema(ObjectInfo object, ObjectLink link) {
var linkName = '';
if (link.isBacklink) {
linkName = "linkName: r'${link.targetLinkIsarName}',";
}
return '''
LinkSchema(
id: ${link.id(object.isarName)},
name: r'${link.isarName}',
target: r'${link.targetCollectionIsarName}',
single: ${link.isSingle},
$linkName
)''';
}

View file

@ -1,27 +0,0 @@
import 'package:dartx/dartx.dart';
import 'package:isar/isar.dart';
import 'package:isar_generator/src/isar_type.dart';
import 'package:isar_generator/src/object_info.dart';
String generateDistinctBy(ObjectInfo oi) {
var code = '''
extension ${oi.dartName}QueryWhereDistinct on QueryBuilder<${oi.dartName}, ${oi.dartName}, QDistinct> {''';
for (final property in oi.objectProperties) {
if (property.isarType == IsarType.string) {
code += '''
QueryBuilder<${oi.dartName}, ${oi.dartName}, QDistinct>distinctBy${property.dartName.capitalize()}({bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'${property.isarName}', caseSensitive: caseSensitive);
});
}''';
} else if (!property.isarType.containsObject) {
code += '''
QueryBuilder<${oi.dartName}, ${oi.dartName}, QDistinct>distinctBy${property.dartName.capitalize()}() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'${property.isarName}');
});
}''';
}
}
return '$code}';
}

View file

@ -1,278 +0,0 @@
import 'package:dartx/dartx.dart';
import 'package:isar/isar.dart';
import 'package:isar_generator/src/code_gen/query_filter_length.dart';
import 'package:isar_generator/src/isar_type.dart';
import 'package:isar_generator/src/object_info.dart';
class FilterGenerator {
FilterGenerator(this.object) : objName = object.dartName;
final ObjectInfo object;
final String objName;
String generate() {
var code =
'extension ${objName}QueryFilter on QueryBuilder<$objName, $objName, '
'QFilterCondition> {';
for (final property in object.properties) {
if (property.nullable) {
code += generateIsNull(property);
code += generateIsNotNull(property);
}
if (property.elementNullable) {
code += generateElementIsNull(property);
code += generateElementIsNotNull(property);
}
if (!property.isarType.containsObject) {
code += generateEqualTo(property);
if (!property.isarType.containsBool) {
code += generateGreaterThan(property);
code += generateLessThan(property);
code += generateBetween(property);
}
}
if (property.isarType.containsString) {
code += generateStringStartsWith(property);
code += generateStringEndsWith(property);
code += generateStringContains(property);
code += generateStringMatches(property);
code += generateStringIsEmpty(property);
code += generateStringIsNotEmpty(property);
}
if (property.isarType.isList) {
code += generateListLength(property);
}
}
return '''
$code
}''';
}
String mPrefix(ObjectProperty p, [bool listElement = true]) {
final any = listElement && p.isarType.isList ? 'Element' : '';
return 'QueryBuilder<$objName, $objName, QAfterFilterCondition> '
'${p.dartName.decapitalize()}$any';
}
String generateEqualTo(ObjectProperty p) {
final optional = [
if (p.isarType.containsString) 'bool caseSensitive = true',
if (p.isarType.containsFloat) 'double epsilon = Query.epsilon',
].join(',');
return '''
${mPrefix(p)}EqualTo(${p.nScalarDartType} value ${optional.isNotBlank ? ', {$optional,}' : ''}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'${p.isarName}',
value: value,
${p.isarType.containsString ? 'caseSensitive: caseSensitive,' : ''}
${p.isarType.containsFloat ? 'epsilon: epsilon,' : ''}
));
});
}''';
}
String generateGreaterThan(ObjectProperty p) {
final optional = [
'bool include = false',
if (p.isarType.containsString) 'bool caseSensitive = true',
if (p.isarType.containsFloat) 'double epsilon = Query.epsilon',
].join(',');
return '''
${mPrefix(p)}GreaterThan(${p.nScalarDartType} value, {$optional,}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
include: include,
property: r'${p.isarName}',
value: value,
${p.isarType.containsString ? 'caseSensitive: caseSensitive,' : ''}
${p.isarType.containsFloat ? 'epsilon: epsilon,' : ''}
));
});
}''';
}
String generateLessThan(ObjectProperty p) {
final optional = [
'bool include = false',
if (p.isarType.containsString) 'bool caseSensitive = true',
if (p.isarType.containsFloat) 'double epsilon = Query.epsilon',
].join(',');
return '''
${mPrefix(p)}LessThan(${p.nScalarDartType} value, {$optional,}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.lessThan(
include: include,
property: r'${p.isarName}',
value: value,
${p.isarType.containsString ? 'caseSensitive: caseSensitive,' : ''}
${p.isarType.containsFloat ? 'epsilon: epsilon,' : ''}
));
});
}''';
}
String generateBetween(ObjectProperty p) {
final optional = [
'bool includeLower = true',
'bool includeUpper = true',
if (p.isarType.containsString) 'bool caseSensitive = true',
if (p.isarType.containsFloat) 'double epsilon = Query.epsilon',
].join(',');
return '''
${mPrefix(p)}Between(${p.nScalarDartType} lower, ${p.nScalarDartType} upper, {$optional,}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.between(
property: r'${p.isarName}',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
${p.isarType.containsString ? 'caseSensitive: caseSensitive,' : ''}
${p.isarType.containsFloat ? 'epsilon: epsilon,' : ''}
));
});
}''';
}
String generateIsNull(ObjectProperty p) {
return '''
${mPrefix(p, false)}IsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNull(
property: r'${p.isarName}',
));
});
}''';
}
String generateElementIsNull(ObjectProperty p) {
return '''
${mPrefix(p)}IsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.elementIsNull(
property: r'${p.isarName}',
));
});
}''';
}
String generateIsNotNull(ObjectProperty p) {
return '''
${mPrefix(p, false)}IsNotNull() {
return QueryBuilder.apply(this, (query) {
return query
.addFilterCondition(const FilterCondition.isNotNull(
property: r'${p.isarName}',
));
});
}''';
}
String generateElementIsNotNull(ObjectProperty p) {
return '''
${mPrefix(p)}IsNotNull() {
return QueryBuilder.apply(this, (query) {
return query
.addFilterCondition(const FilterCondition.elementIsNotNull(
property: r'${p.isarName}',
));
});
}''';
}
String generateStringStartsWith(ObjectProperty p) {
return '''
${mPrefix(p)}StartsWith(String value, {bool caseSensitive = true,}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.startsWith(
property: r'${p.isarName}',
value: value,
caseSensitive: caseSensitive,
));
});
}''';
}
String generateStringEndsWith(ObjectProperty p) {
return '''
${mPrefix(p)}EndsWith(String value, {bool caseSensitive = true,}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.endsWith(
property: r'${p.isarName}',
value: value,
caseSensitive: caseSensitive,
));
});
}''';
}
String generateStringContains(ObjectProperty p) {
return '''
${mPrefix(p)}Contains(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.contains(
property: r'${p.isarName}',
value: value,
caseSensitive: caseSensitive,
));
});
}''';
}
String generateStringMatches(ObjectProperty p) {
return '''
${mPrefix(p)}Matches(String pattern, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.matches(
property: r'${p.isarName}',
wildcard: pattern,
caseSensitive: caseSensitive,
));
});
}''';
}
String generateStringIsEmpty(ObjectProperty p) {
return '''
${mPrefix(p)}IsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'${p.isarName}',
value: '',
));
});
}''';
}
String generateStringIsNotEmpty(ObjectProperty p) {
return '''
${mPrefix(p)}IsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
property: r'${p.isarName}',
value: '',
));
});
}''';
}
String generateListLength(ObjectProperty p) {
return generateLength(objName, p.dartName,
(lower, includeLower, upper, includeUpper) {
return '''
QueryBuilder.apply(this, (query) {
return query.listLength(
r'${p.isarName}',
$lower,
$includeLower,
$upper,
$includeUpper,
);
})''';
});
}
}

View file

@ -1,50 +0,0 @@
import 'package:dartx/dartx.dart';
String generateLength(
String objectName,
String propertyName,
String Function(
String lower,
String includeLower,
String upper,
String includeUpper,
)
codeGen,
) {
return '''
QueryBuilder<$objectName, $objectName, QAfterFilterCondition> ${propertyName.decapitalize()}LengthEqualTo(int length) {
return ${codeGen('length', 'true', 'length', 'true')};
}
QueryBuilder<$objectName, $objectName, QAfterFilterCondition> ${propertyName.decapitalize()}IsEmpty() {
return ${codeGen('0', 'true', '0', 'true')};
}
QueryBuilder<$objectName, $objectName, QAfterFilterCondition> ${propertyName.decapitalize()}IsNotEmpty() {
return ${codeGen('0', 'false', '999999', 'true')};
}
QueryBuilder<$objectName, $objectName, QAfterFilterCondition> ${propertyName.decapitalize()}LengthLessThan(
int length, {
bool include = false,
}) {
return ${codeGen('0', 'true', 'length', 'include')};
}
QueryBuilder<$objectName, $objectName, QAfterFilterCondition> ${propertyName.decapitalize()}LengthGreaterThan(
int length, {
bool include = false,
}) {
return ${codeGen('length', 'include', '999999', 'true')};
}
QueryBuilder<$objectName, $objectName, QAfterFilterCondition> ${propertyName.decapitalize()}LengthBetween(
int lower,
int upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return ${codeGen('lower', 'includeLower', 'upper', 'includeUpper')};
}
''';
}

View file

@ -1,38 +0,0 @@
import 'package:dartx/dartx.dart';
import 'package:isar_generator/src/code_gen/query_filter_length.dart';
import 'package:isar_generator/src/object_info.dart';
String generateQueryLinks(ObjectInfo oi) {
var code =
'extension ${oi.dartName}QueryLinks on QueryBuilder<${oi.dartName}, '
'${oi.dartName}, QFilterCondition> {';
for (final link in oi.links) {
code += '''
QueryBuilder<${oi.dartName}, ${oi.dartName}, QAfterFilterCondition> ${link.dartName.decapitalize()}(FilterQuery<${link.targetCollectionDartName}> q) {
return QueryBuilder.apply(this, (query) {
return query.link(q, r'${link.isarName}');
});
}''';
if (link.isSingle) {
code += '''
QueryBuilder<${oi.dartName}, ${oi.dartName}, QAfterFilterCondition> ${link.dartName.decapitalize()}IsNull() {
return QueryBuilder.apply(this, (query) {
return query.linkLength(r'${link.isarName}', 0, true, 0, true);
});
}''';
} else {
code += generateLength(oi.dartName, link.dartName,
(lower, includeLower, upper, includeUpper) {
return '''
QueryBuilder.apply(this, (query) {
return query.linkLength(r'${link.isarName}', $lower, $includeLower, $upper, $includeUpper);
})''';
});
}
}
return '''
$code
}''';
}

View file

@ -1,29 +0,0 @@
import 'package:dartx/dartx.dart';
import 'package:isar/isar.dart';
import 'package:isar_generator/src/isar_type.dart';
import 'package:isar_generator/src/object_info.dart';
String generateQueryObjects(ObjectInfo oi) {
var code =
'extension ${oi.dartName}QueryObject on QueryBuilder<${oi.dartName}, '
'${oi.dartName}, QFilterCondition> {';
for (final property in oi.objectProperties) {
if (!property.isarType.containsObject) {
continue;
}
var name = property.dartName.decapitalize();
if (property.isarType.isList) {
name += 'Element';
}
code += '''
QueryBuilder<${oi.dartName}, ${oi.dartName}, QAfterFilterCondition> $name(FilterQuery<${property.typeClassName}> q) {
return QueryBuilder.apply(this, (query) {
return query.object(q, r'${property.isarName}');
});
}''';
}
return '''
$code
}''';
}

View file

@ -1,25 +0,0 @@
import 'package:isar_generator/src/object_info.dart';
String generatePropertyQuery(ObjectInfo oi) {
var code = '''
extension ${oi.dartName}QueryProperty on QueryBuilder<${oi.dartName}, ${oi.dartName}, QQueryProperty> {''';
// Ids are always non-nullable regardless of their specified nullability
code += '''
QueryBuilder<${oi.dartName}, int, QQueryOperations>${oi.idProperty.dartName}Property() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'${oi.idProperty.isarName}');
});
}''';
for (final property in oi.objectProperties) {
code += '''
QueryBuilder<${oi.dartName}, ${property.dartType}, QQueryOperations>${property.dartName}Property() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'${property.isarName}');
});
}''';
}
return '$code}';
}

View file

@ -1,55 +0,0 @@
import 'package:dartx/dartx.dart';
import 'package:isar/isar.dart';
import 'package:isar_generator/src/isar_type.dart';
import 'package:isar_generator/src/object_info.dart';
String generateSortBy(ObjectInfo oi) {
var code = '''
extension ${oi.dartName}QuerySortBy on QueryBuilder<${oi.dartName}, ${oi.dartName}, QSortBy> {''';
for (final property in oi.objectProperties) {
if (property.isarType.isList || property.isarType.containsObject) {
continue;
}
code += '''
QueryBuilder<${oi.dartName}, ${oi.dartName}, QAfterSortBy>sortBy${property.dartName.capitalize()}() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'${property.isarName}', Sort.asc);
});
}
QueryBuilder<${oi.dartName}, ${oi.dartName}, QAfterSortBy>sortBy${property.dartName.capitalize()}Desc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'${property.isarName}', Sort.desc);
});
}''';
}
code += '''
}
extension ${oi.dartName}QuerySortThenBy on QueryBuilder<${oi.dartName}, ${oi.dartName}, QSortThenBy> {''';
for (final property in oi.properties) {
if (property.isarType.isList || property.isarType.containsObject) {
continue;
}
code += '''
QueryBuilder<${oi.dartName}, ${oi.dartName}, QAfterSortBy>thenBy${property.dartName.capitalize()}() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'${property.isarName}', Sort.asc);
});
}
QueryBuilder<${oi.dartName}, ${oi.dartName}, QAfterSortBy>thenBy${property.dartName.capitalize()}Desc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'${property.isarName}', Sort.desc);
});
}''';
}
return '$code}';
}

View file

@ -1,568 +0,0 @@
import 'package:dartx/dartx.dart';
import 'package:isar/isar.dart';
import 'package:isar_generator/src/object_info.dart';
class WhereGenerator {
WhereGenerator(this.object)
: objName = object.dartName,
id = object.idProperty;
final ObjectInfo object;
final String objName;
final ObjectProperty id;
final existing = <String>{};
String generate() {
var code = 'extension ${objName}QueryWhereSort on QueryBuilder<$objName, '
'$objName, QWhere> {';
code += generateAnyId();
for (final index in object.indexes) {
if (index.properties.all((element) => element.type == IndexType.value)) {
code += generateAny(index);
}
}
code += '''
}
extension ${objName}QueryWhere on QueryBuilder<$objName, $objName, QWhereClause> {
''';
code += generateWhereIdEqualTo();
code += generateWhereIdNotEqualTo();
code += generateWhereIdGreaterThan();
code += generateWhereIdLessThan();
code += generateWhereIdBetween();
for (final index in object.indexes) {
for (var n = 0; n < index.properties.length; n++) {
final indexProperty = index.properties[n];
final property = indexProperty.property;
if ((property.nullable && !indexProperty.isMultiEntry) ||
(property.elementNullable && indexProperty.isMultiEntry)) {
code += generateWhereIsNull(index, n + 1);
code += generateWhereIsNotNull(index, n + 1);
}
code += generateWhereEqualTo(index, n + 1);
code += generateWhereNotEqualTo(index, n + 1);
if (indexProperty.type == IndexType.value) {
if (property.isarType != IsarType.bool &&
property.isarType != IsarType.boolList) {
code += generateWhereGreaterThan(index, n + 1);
code += generateWhereLessThan(index, n + 1);
code += generateWhereBetween(index, n + 1);
}
if (property.isarType == IsarType.string ||
property.isarType == IsarType.stringList) {
code += generateWhereStartsWith(index, n + 1);
code += generateStringIsEmpty(index, n + 1);
code += generateStringIsNotEmpty(index, n + 1);
}
}
}
}
return '$code}';
}
String getMethodName(ObjectIndex index, int propertyCount, [String? method]) {
String propertyName(ObjectIndexProperty p) {
var name = p.property.dartName.capitalize();
if (p.isMultiEntry) {
name += 'Element';
}
return name;
}
var name = '';
final eqProperties =
index.properties.sublist(0, propertyCount - (method != null ? 1 : 0));
if (eqProperties.isNotEmpty) {
name += eqProperties.map(propertyName).join();
name += 'EqualTo';
}
if (method != null) {
name += propertyName(index.properties[propertyCount - 1]);
name += method;
}
final remainingProperties = propertyCount < index.properties.length
? index.properties.sublist(propertyCount)
: null;
if (remainingProperties != null) {
name += 'Any';
name += remainingProperties.map(propertyName).join();
}
return name.decapitalize();
}
String paramType(ObjectIndexProperty p) {
if (p.property.isarType.isList && p.type == IndexType.hash) {
return p.property.dartType;
} else {
return p.property.nScalarDartType;
}
}
String paramName(ObjectIndexProperty p) {
if (p.property.isarType.isList && p.type != IndexType.hash) {
return '${p.property.dartName}Element';
} else {
return p.property.dartName;
}
}
String joinToParams(List<ObjectIndexProperty> properties) {
return properties
.map((it) => '${paramType(it)} ${paramName(it)}')
.join(',');
}
String joinToValues(List<ObjectIndexProperty> properties) {
return properties.map((it) {
if (it.property.isarType.isList && it.type != IndexType.hash) {
return '${it.property.dartName}Element';
} else {
return paramName(it);
}
}).join(', ');
}
String generateAnyId() {
return '''
QueryBuilder<$objName, $objName, QAfterWhere> any${id.dartName.capitalize()}() {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(const IdWhereClause.any());
});
}
''';
}
String generateAny(ObjectIndex index) {
final name = getMethodName(index, 0);
if (!existing.add(name)) {
return '';
}
return '''
QueryBuilder<$objName, $objName, QAfterWhere> $name() {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
const IndexWhereClause.any(indexName: r'${index.name}'),
);
});
}
''';
}
String get mPrefix => 'QueryBuilder<$objName, $objName, QAfterWhereClause>';
String generateWhereIdEqualTo() {
final idName = id.dartName.decapitalize();
return '''
$mPrefix ${idName}EqualTo(Id $idName) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(
lower: $idName,
upper: $idName,
));
});
}
''';
}
String generateWhereEqualTo(ObjectIndex index, int propertyCount) {
final name = getMethodName(index, propertyCount);
if (!existing.add(name)) {
return '';
}
final properties = index.properties.takeFirst(propertyCount);
final values = joinToValues(properties);
final params = joinToParams(properties);
return '''
$mPrefix $name($params ${properties.containsFloat ? ', {double epsilon = Query.epsilon,}' : ''}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IndexWhereClause.equalTo(
indexName: r'${index.name}',
value: [$values],
${properties.containsFloat ? 'epsilon: epsilon,' : ''}
));
});
}
''';
}
String generateWhereIdNotEqualTo() {
final idName = id.dartName.decapitalize();
return '''
$mPrefix ${idName}NotEqualTo(Id $idName) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query.addWhereClause(
IdWhereClause.lessThan(upper: $idName, includeUpper: false),
).addWhereClause(
IdWhereClause.greaterThan(lower: $idName, includeLower: false),
);
} else {
return query.addWhereClause(
IdWhereClause.greaterThan(lower: $idName, includeLower: false),
).addWhereClause(
IdWhereClause.lessThan(upper: $idName, includeUpper: false),
);
}
});
}
''';
}
String generateWhereNotEqualTo(ObjectIndex index, int propertyCount) {
final name = getMethodName(index, propertyCount, 'NotEqualTo');
if (!existing.add(name)) {
return '';
}
final properties = index.properties.takeFirst(propertyCount);
final params = joinToParams(properties);
final equalProperties = properties.dropLast(1);
final notEqualProperty = properties.last;
final equalValues = joinToValues(equalProperties);
var notEqualValue = joinToValues([notEqualProperty]);
if (equalValues.isNotEmpty) {
notEqualValue = ',$notEqualValue';
}
return '''
$mPrefix $name($params ${properties.containsFloat ? ', {double epsilon = Query.epsilon,}' : ''}) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query.addWhereClause(IndexWhereClause.between(
indexName: r'${index.name}',
lower: [$equalValues],
upper: [$equalValues $notEqualValue],
includeUpper: false,
${properties.containsFloat ? 'epsilon: epsilon,' : ''}
)).addWhereClause(IndexWhereClause.between(
indexName: r'${index.name}',
lower: [$equalValues $notEqualValue],
includeLower: false,
upper: [$equalValues],
${properties.containsFloat ? 'epsilon: epsilon,' : ''}
));
} else {
return query.addWhereClause(IndexWhereClause.between(
indexName: r'${index.name}',
lower: [$equalValues $notEqualValue],
includeLower: false,
upper: [$equalValues],
${properties.containsFloat ? 'epsilon: epsilon,' : ''}
)).addWhereClause(IndexWhereClause.between(
indexName: r'${index.name}',
lower: [$equalValues],
upper: [$equalValues $notEqualValue],
includeUpper: false,
${properties.containsFloat ? 'epsilon: epsilon,' : ''}
));
}
});
}
''';
}
String generateWhereIdGreaterThan() {
final idName = id.dartName.decapitalize();
return '''
$mPrefix ${idName}GreaterThan(Id $idName, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.greaterThan(lower: $idName, includeLower: include),
);
});
}
''';
}
String generateWhereGreaterThan(ObjectIndex index, int propertyCount) {
final name = getMethodName(index, propertyCount, 'GreaterThan');
if (!existing.add(name)) {
return '';
}
final properties = index.properties.takeFirst(propertyCount);
final optional = [
'bool include = false',
if (properties.containsFloat) 'double epsilon = Query.epsilon',
].join(',');
return '''
$mPrefix $name(${joinToParams(properties)}, {$optional,}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IndexWhereClause.between(
indexName: r'${index.name}',
lower: [${joinToValues(properties)}],
includeLower: include,
upper: [${joinToValues(properties.dropLast(1))}],
${properties.containsFloat ? 'epsilon: epsilon,' : ''}
));
});
}
''';
}
String generateWhereIdLessThan() {
final idName = id.dartName.decapitalize();
return '''
$mPrefix ${idName}LessThan(Id $idName, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.lessThan(upper: $idName, includeUpper: include),
);
});
}
''';
}
String generateWhereLessThan(ObjectIndex index, int propertyCount) {
final name = getMethodName(index, propertyCount, 'LessThan');
if (!existing.add(name)) {
return '';
}
final properties = index.properties.takeFirst(propertyCount);
final optional = [
'bool include = false',
if (properties.containsFloat) 'double epsilon = Query.epsilon',
].join(',');
return '''
$mPrefix $name(${joinToParams(properties)}, {$optional,}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IndexWhereClause.between(
indexName: r'${index.name}',
lower: [${joinToValues(properties.dropLast(1))}],
upper: [${joinToValues(properties)}],
includeUpper: include,
${properties.containsFloat ? 'epsilon: epsilon,' : ''}
));
});
}
''';
}
String generateWhereIdBetween() {
final idName = id.dartName.decapitalize();
final lowerName = 'lower${id.dartName.capitalize()}';
final upperName = 'upper${id.dartName.capitalize()}';
return '''
$mPrefix ${idName}Between(Id $lowerName, Id $upperName, {bool includeLower = true, bool includeUpper = true,}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(
lower: $lowerName,
includeLower: includeLower,
upper: $upperName,
includeUpper: includeUpper,
));
});
}
''';
}
String generateWhereBetween(ObjectIndex index, int propertyCount) {
final name = getMethodName(index, propertyCount, 'Between');
if (!existing.add(name)) {
return '';
}
final properties = index.properties.takeFirst(propertyCount);
final equalProperties = properties.dropLast(1);
final betweenProperty = properties.last;
var params = joinToParams(equalProperties);
if (params.isNotEmpty) {
params += ',';
}
final betweenType = paramType(betweenProperty);
final lowerName = 'lower${paramName(betweenProperty).capitalize()}';
final upperName = 'upper${paramName(betweenProperty).capitalize()}';
params += '$betweenType $lowerName, $betweenType $upperName';
var values = joinToValues(equalProperties);
if (values.isNotEmpty) {
values += ',';
}
final optional = [
'bool includeLower = true',
'bool includeUpper = true',
if (properties.containsFloat) 'double epsilon = Query.epsilon',
].join(',');
return '''
$mPrefix $name($params, {$optional,}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IndexWhereClause.between(
indexName: r'${index.name}',
lower: [$values $lowerName],
includeLower: includeLower,
upper: [$values $upperName],
includeUpper: includeUpper,
${properties.containsFloat ? 'epsilon: epsilon,' : ''}
));
});
}
''';
}
String generateWhereIsNull(ObjectIndex index, int propertyCount) {
final name = getMethodName(index, propertyCount, 'IsNull');
if (!existing.add(name)) {
return '';
}
final properties = index.properties.takeFirst(propertyCount - 1);
var values = joinToValues(properties);
if (values.isNotEmpty) {
values += ',';
}
final params = joinToParams(properties);
return '''
$mPrefix $name($params) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IndexWhereClause.equalTo(
indexName: r'${index.name}',
value: [$values null],
));
});
}
''';
}
String generateWhereIsNotNull(ObjectIndex index, int propertyCount) {
final name = getMethodName(index, propertyCount, 'IsNotNull');
if (!existing.add(name)) {
return '';
}
final properties = index.properties.takeFirst(propertyCount - 1);
var values = joinToValues(properties);
if (values.isNotEmpty) {
values += ',';
}
final params = joinToParams(properties);
return '''
$mPrefix $name($params) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IndexWhereClause.between(
indexName: r'${index.name}',
lower: [$values null],
includeLower: false,
upper: [$values],
));
});
}
''';
}
String generateWhereStartsWith(ObjectIndex index, int propertyCount) {
final name = getMethodName(index, propertyCount, 'StartsWith');
if (!existing.add(name)) {
return '';
}
final equalProperties = index.properties.dropLast(1);
var params = joinToParams(equalProperties);
if (params.isNotEmpty) {
params += ',';
}
final prefixProperty = index.properties.last;
final prefixName = '${paramName(prefixProperty).capitalize()}Prefix';
params += 'String $prefixName';
var values = joinToValues(equalProperties);
if (values.isNotEmpty) {
values += ',';
}
return '''
$mPrefix $name($params) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IndexWhereClause.between(
indexName: r'${index.name}',
lower: [$values $prefixName],
upper: [$values '\$$prefixName\\u{FFFFF}'],
));
});
}
''';
}
String generateStringIsEmpty(ObjectIndex index, int propertyCount) {
final name = getMethodName(index, propertyCount, 'IsEmpty');
if (!existing.add(name)) {
return '';
}
final properties = index.properties.dropLast(1);
var values = joinToValues(properties);
if (values.isNotEmpty) {
values += ',';
}
final params = joinToParams(properties);
return '''
$mPrefix $name($params) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IndexWhereClause.equalTo(
indexName: r'${index.name}',
value: [$values ''],
));
});
}''';
}
String generateStringIsNotEmpty(ObjectIndex index, int propertyCount) {
final name = getMethodName(index, propertyCount, 'IsNotEmpty');
if (!existing.add(name)) {
return '';
}
final properties = index.properties.dropLast(1);
var values = joinToValues(properties);
if (values.isNotEmpty) {
values += ',';
}
final params = joinToParams(properties);
return '''
$mPrefix $name($params) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query.addWhereClause(IndexWhereClause.lessThan(
indexName: r'${index.name}',
upper: [''],
)).addWhereClause(IndexWhereClause.greaterThan(
indexName: r'${index.name}',
lower: [''],
));
} else {
return query.addWhereClause(IndexWhereClause.greaterThan(
indexName: r'${index.name}',
lower: [''],
)).addWhereClause(IndexWhereClause.lessThan(
indexName: r'${index.name}',
upper: [''],
));
}
});
}''';
}
}
extension on List<ObjectIndexProperty> {
bool get containsFloat =>
last.isarType == IsarType.float || last.isarType == IsarType.floatList;
}

View file

@ -1,476 +0,0 @@
import 'package:dartx/dartx.dart';
import 'package:isar/isar.dart';
import 'package:isar_generator/src/object_info.dart';
String _prepareSerialize(
bool nullable,
String value,
String Function(String) size,
) {
var code = '';
if (nullable) {
code += '''
{
final value = $value;
if (value != null) {''';
value = 'value';
}
code += 'bytesCount += ${size(value)};';
if (nullable) {
code += '}}';
}
return code;
}
String _prepareSerializeList(
bool nullable,
bool elementNullable,
String value,
String size, [
String? prepare,
]) {
var code = '';
if (nullable) {
code += '''
{
final list = $value;
if (list != null) {''';
value = 'list';
}
code += '''
bytesCount += 3 + $value.length * 3;
{
${prepare ?? ''}
for (var i = 0; i < $value.length; i++) {
final value = $value[i];''';
if (elementNullable) {
code += 'if (value != null) {';
}
code += 'bytesCount += $size;';
if (elementNullable) {
code += '}';
}
code += '}}';
if (nullable) {
code += '}}';
}
return code;
}
String generateEstimateSerialize(ObjectInfo object) {
var code = '''
int ${object.estimateSizeName}(
${object.dartName} object,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
var bytesCount = offsets.last;''';
for (final property in object.properties) {
final value = 'object.${property.dartName}';
switch (property.isarType) {
case IsarType.string:
final enumValue = property.isEnum ? '.${property.enumProperty}' : '';
code += _prepareSerialize(
property.nullable,
value,
(value) => '3 + $value$enumValue.length * 3',
);
break;
case IsarType.stringList:
final enumValue = property.isEnum ? '.${property.enumProperty}' : '';
code += _prepareSerializeList(
property.nullable,
property.elementNullable,
value,
'value$enumValue.length * 3',
);
break;
case IsarType.object:
code += _prepareSerialize(
property.nullable,
value,
(value) {
return '3 + ${property.targetSchema}.estimateSize($value, '
'allOffsets[${property.scalarDartType}]!, allOffsets)';
},
);
break;
case IsarType.objectList:
code += _prepareSerializeList(
property.nullable,
property.elementNullable,
value,
'${property.targetSchema}.estimateSize(value, offsets, allOffsets)',
'final offsets = allOffsets[${property.scalarDartType}]!;',
);
break;
case IsarType.byteList:
case IsarType.boolList:
code += _prepareSerialize(
property.nullable,
value,
(value) => '3 + $value.length',
);
break;
case IsarType.intList:
case IsarType.floatList:
code += _prepareSerialize(
property.nullable,
value,
(value) => '3 + $value.length * 4',
);
break;
case IsarType.longList:
case IsarType.doubleList:
case IsarType.dateTimeList:
code += _prepareSerialize(
property.nullable,
value,
(value) => '3 + $value.length * 8',
);
break;
// ignore: no_default_cases
default:
break;
}
}
return '''
$code
return bytesCount;
}''';
}
String generateSerialize(ObjectInfo object) {
var code = '''
void ${object.serializeName}(
${object.dartName} object,
IsarWriter writer,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {''';
for (var i = 0; i < object.objectProperties.length; i++) {
final property = object.objectProperties[i];
var value = 'object.${property.dartName}';
if (property.isEnum) {
final nOp = property.nullable ? '?' : '';
final elNOp = property.elementNullable ? '?' : '';
value = property.isarType.isList
? '$value$nOp.map((e) => e$elNOp.${property.enumProperty}).toList()'
: '$value$nOp.${property.enumProperty}';
}
switch (property.isarType) {
case IsarType.bool:
code += 'writer.writeBool(offsets[$i], $value);';
break;
case IsarType.byte:
code += 'writer.writeByte(offsets[$i], $value);';
break;
case IsarType.int:
code += 'writer.writeInt(offsets[$i], $value);';
break;
case IsarType.float:
code += 'writer.writeFloat(offsets[$i], $value);';
break;
case IsarType.long:
code += 'writer.writeLong(offsets[$i], $value);';
break;
case IsarType.double:
code += 'writer.writeDouble(offsets[$i], $value);';
break;
case IsarType.dateTime:
code += 'writer.writeDateTime(offsets[$i], $value);';
break;
case IsarType.string:
code += 'writer.writeString(offsets[$i], $value);';
break;
case IsarType.object:
code += '''
writer.writeObject<${property.typeClassName}>(
offsets[$i],
allOffsets,
${property.targetSchema}.serialize,
$value,
);''';
break;
case IsarType.byteList:
code += 'writer.writeByteList(offsets[$i], $value);';
break;
case IsarType.boolList:
code += 'writer.writeBoolList(offsets[$i], $value);';
break;
case IsarType.intList:
code += 'writer.writeIntList(offsets[$i], $value);';
break;
case IsarType.longList:
code += 'writer.writeLongList(offsets[$i], $value);';
break;
case IsarType.floatList:
code += 'writer.writeFloatList(offsets[$i], $value);';
break;
case IsarType.doubleList:
code += 'writer.writeDoubleList(offsets[$i], $value);';
break;
case IsarType.dateTimeList:
code += 'writer.writeDateTimeList(offsets[$i], $value);';
break;
case IsarType.stringList:
code += 'writer.writeStringList(offsets[$i], $value);';
break;
case IsarType.objectList:
code += '''
writer.writeObjectList<${property.typeClassName}>(
offsets[$i],
allOffsets,
${property.targetSchema}.serialize,
$value,
);''';
break;
}
}
return '$code}';
}
String generateDeserialize(ObjectInfo object) {
var code = '''
${object.dartName} ${object.deserializeName}(
Id id,
IsarReader reader,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
final object = ${object.dartName}(''';
final propertiesByMode =
object.properties.groupBy((ObjectProperty p) => p.deserialize);
final positional = propertiesByMode[PropertyDeser.positionalParam] ?? [];
final sortedPositional =
positional.sortedBy((ObjectProperty p) => p.constructorPosition!);
for (final p in sortedPositional) {
final index = object.objectProperties.indexOf(p);
final deser = _deserializeProperty(object, p, 'offsets[$index]');
code += '$deser,';
}
final named = propertiesByMode[PropertyDeser.namedParam] ?? [];
for (final p in named) {
final index = object.objectProperties.indexOf(p);
final deser = _deserializeProperty(object, p, 'offsets[$index]');
code += '${p.dartName}: $deser,';
}
code += ');';
final assign = propertiesByMode[PropertyDeser.assign] ?? [];
for (final p in assign) {
final index = object.objectProperties.indexOf(p);
final deser = _deserializeProperty(object, p, 'offsets[$index]');
code += 'object.${p.dartName} = $deser;';
}
return '''
$code
return object;
}''';
}
String generateDeserializeProp(ObjectInfo object) {
var code = '''
P ${object.deserializePropName}<P>(
IsarReader reader,
int propertyId,
int offset,
Map<Type,
List<int>> allOffsets,
) {
switch (propertyId) {''';
for (var i = 0; i < object.objectProperties.length; i++) {
final property = object.objectProperties[i];
final deser = _deserializeProperty(object, property, 'offset');
code += 'case $i: return ($deser) as P;';
}
return '''
$code
default:
throw IsarError('Unknown property with id \$propertyId');
}
}
''';
}
String _deserializeProperty(
ObjectInfo object,
ObjectProperty property,
String propertyOffset,
) {
if (property.isId) {
return 'id';
}
final deser = _deserialize(property, propertyOffset);
var defaultValue = '';
if (!property.nullable) {
if (property.userDefaultValue != null) {
defaultValue = '?? ${property.userDefaultValue}';
} else if (property.isarType == IsarType.object) {
defaultValue = '?? ${property.typeClassName}()';
} else if (property.isarType.isList) {
defaultValue = '?? []';
} else if (property.isEnum) {
defaultValue = '?? ${property.defaultEnumElement}';
}
}
if (property.isEnum) {
if (property.isarType.isList) {
final elDefault =
!property.elementNullable ? '?? ${property.defaultEnumElement}' : '';
return '$deser?.map((e) => ${property.valueEnumMapName(object)}[e] '
'$elDefault).toList() $defaultValue';
} else {
return '${property.valueEnumMapName(object)}[$deser] $defaultValue';
}
} else {
return '$deser $defaultValue';
}
}
String _deserialize(ObjectProperty property, String propertyOffset) {
final orNull =
property.nullable || property.userDefaultValue != null || property.isEnum
? 'OrNull'
: '';
final orElNull = property.elementNullable ? 'OrNull' : '';
switch (property.isarType) {
case IsarType.bool:
return 'reader.readBool$orNull($propertyOffset)';
case IsarType.byte:
return 'reader.readByte$orNull($propertyOffset)';
case IsarType.int:
return 'reader.readInt$orNull($propertyOffset)';
case IsarType.float:
return 'reader.readFloat$orNull($propertyOffset)';
case IsarType.long:
return 'reader.readLong$orNull($propertyOffset)';
case IsarType.double:
return 'reader.readDouble$orNull($propertyOffset)';
case IsarType.dateTime:
return 'reader.readDateTime$orNull($propertyOffset)';
case IsarType.string:
return 'reader.readString$orNull($propertyOffset)';
case IsarType.object:
return '''
reader.readObjectOrNull<${property.typeClassName}>(
$propertyOffset,
${property.targetSchema}.deserialize,
allOffsets,
)''';
case IsarType.boolList:
return 'reader.readBool${orElNull}List($propertyOffset)';
case IsarType.byteList:
return 'reader.readByteList($propertyOffset)';
case IsarType.intList:
return 'reader.readInt${orElNull}List($propertyOffset)';
case IsarType.floatList:
return 'reader.readFloat${orElNull}List($propertyOffset)';
case IsarType.longList:
return 'reader.readLong${orElNull}List($propertyOffset)';
case IsarType.doubleList:
return 'reader.readDouble${orElNull}List($propertyOffset)';
case IsarType.dateTimeList:
return 'reader.readDateTime${orElNull}List($propertyOffset)';
case IsarType.stringList:
return 'reader.readString${orElNull}List($propertyOffset)';
case IsarType.objectList:
return '''
reader.readObject${orElNull}List<${property.typeClassName}>(
$propertyOffset,
${property.targetSchema}.deserialize,
allOffsets,
${!property.elementNullable ? '${property.typeClassName}(),' : ''}
)''';
}
}
String generateGetId(ObjectInfo object) {
final defaultVal = object.idProperty.nullable ? '?? Isar.autoIncrement' : '';
return '''
Id ${object.getIdName}(${object.dartName} object) {
return object.${object.idProperty.dartName} $defaultVal;
}
''';
}
String generateGetLinks(ObjectInfo object) {
return '''
List<IsarLinkBase<dynamic>> ${object.getLinksName}(${object.dartName} object) {
return [${object.links.map((e) => 'object.${e.dartName}').join(',')}];
}
''';
}
String generateAttach(ObjectInfo object) {
var code = '''
void ${object.attachName}(IsarCollection<dynamic> col, Id id, ${object.dartName} object) {''';
if (object.idProperty.assignable) {
code += 'object.${object.idProperty.dartName} = id;';
}
for (final link in object.links) {
// ignore: leading_newlines_in_multiline_strings
code += '''object.${link.dartName}.attach(
col,
col.isar.collection<${link.targetCollectionDartName}>(),
r'${link.isarName}',
id
);''';
}
return '$code}';
}
String generateEnumMaps(ObjectInfo object) {
var code = '';
for (final property in object.properties) {
final enumName = property.typeClassName;
if (property.isEnum) {
code += 'const ${property.enumValueMapName(object)} = {';
for (final enumElementName in property.enumMap!.keys) {
final value = property.enumMap![enumElementName];
if (value is String) {
code += "r'$enumElementName': r'$value',";
} else {
code += "'$enumElementName': $value,";
}
}
code += '};';
code += 'const ${property.valueEnumMapName(object)} = {';
for (final enumElementName in property.enumMap!.keys) {
final value = property.enumMap![enumElementName];
if (value is String) {
code += "r'$value': $enumName.$enumElementName,";
} else {
code += '$value: $enumName.$enumElementName,';
}
}
code += '};';
}
}
return code;
}

View file

@ -1,105 +0,0 @@
import 'dart:async';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:isar/isar.dart';
import 'package:isar_generator/src/code_gen/by_index_generator.dart';
import 'package:isar_generator/src/code_gen/collection_schema_generator.dart';
import 'package:isar_generator/src/code_gen/query_distinct_by_generator.dart';
import 'package:isar_generator/src/code_gen/query_filter_generator.dart';
import 'package:isar_generator/src/code_gen/query_link_generator.dart';
import 'package:isar_generator/src/code_gen/query_object_generator.dart';
import 'package:isar_generator/src/code_gen/query_property_generator.dart';
import 'package:isar_generator/src/code_gen/query_sort_by_generator.dart';
import 'package:isar_generator/src/code_gen/query_where_generator.dart';
import 'package:isar_generator/src/code_gen/type_adapter_generator.dart';
import 'package:isar_generator/src/isar_analyzer.dart';
import 'package:source_gen/source_gen.dart';
const ignoreLints = [
'duplicate_ignore',
'non_constant_identifier_names',
'constant_identifier_names',
'invalid_use_of_protected_member',
'unnecessary_cast',
'prefer_const_constructors',
'lines_longer_than_80_chars',
'require_trailing_commas',
'inference_failure_on_function_invocation',
'unnecessary_parenthesis',
'unnecessary_raw_strings',
'unnecessary_null_checks',
'join_return_with_assignment',
'prefer_final_locals',
'avoid_js_rounded_ints',
'avoid_positional_boolean_parameters',
'always_specify_types',
];
class IsarCollectionGenerator extends GeneratorForAnnotation<Collection> {
@override
Future<String> generateForAnnotatedElement(
Element element,
ConstantReader annotation,
BuildStep buildStep,
) async {
final object = IsarAnalyzer().analyzeCollection(element);
return '''
// coverage:ignore-file
// ignore_for_file: ${ignoreLints.join(', ')}
extension Get${object.dartName}Collection on Isar {
IsarCollection<${object.dartName}> get ${object.accessor} => this.collection();
}
${generateSchema(object)}
${generateEstimateSerialize(object)}
${generateSerialize(object)}
${generateDeserialize(object)}
${generateDeserializeProp(object)}
${generateEnumMaps(object)}
${generateGetId(object)}
${generateGetLinks(object)}
${generateAttach(object)}
${generateByIndexExtension(object)}
${WhereGenerator(object).generate()}
${FilterGenerator(object).generate()}
${generateQueryObjects(object)}
${generateQueryLinks(object)}
${generateSortBy(object)}
${generateDistinctBy(object)}
${generatePropertyQuery(object)}
''';
}
}
class IsarEmbeddedGenerator extends GeneratorForAnnotation<Embedded> {
@override
Future<String> generateForAnnotatedElement(
Element element,
ConstantReader annotation,
BuildStep buildStep,
) async {
final object = IsarAnalyzer().analyzeEmbedded(element);
return '''
// coverage:ignore-file
// ignore_for_file: ${ignoreLints.join(', ')}
${generateSchema(object)}
${generateEstimateSerialize(object)}
${generateSerialize(object)}
${generateDeserialize(object)}
${generateDeserializeProp(object)}
${generateEnumMaps(object)}
${FilterGenerator(object).generate()}
${generateQueryObjects(object)}
''';
}
}

View file

@ -1,184 +0,0 @@
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:dartx/dartx.dart';
import 'package:isar/isar.dart';
import 'package:source_gen/source_gen.dart';
const TypeChecker _collectionChecker = TypeChecker.fromRuntime(Collection);
const TypeChecker _enumeratedChecker = TypeChecker.fromRuntime(Enumerated);
const TypeChecker _embeddedChecker = TypeChecker.fromRuntime(Embedded);
const TypeChecker _ignoreChecker = TypeChecker.fromRuntime(Ignore);
const TypeChecker _nameChecker = TypeChecker.fromRuntime(Name);
const TypeChecker _indexChecker = TypeChecker.fromRuntime(Index);
const TypeChecker _backlinkChecker = TypeChecker.fromRuntime(Backlink);
extension ClassElementX on ClassElement {
bool get hasZeroArgsConstructor {
return constructors.any(
(ConstructorElement c) =>
c.isPublic &&
!c.parameters.any((ParameterElement p) => !p.isOptional),
);
}
List<PropertyInducingElement> get allAccessors {
final ignoreFields =
collectionAnnotation?.ignore ?? embeddedAnnotation!.ignore;
return [
...accessors.mapNotNull((e) => e.variable),
if (collectionAnnotation?.inheritance ?? embeddedAnnotation!.inheritance)
for (InterfaceType supertype in allSupertypes) ...[
if (!supertype.isDartCoreObject)
...supertype.accessors.mapNotNull((e) => e.variable)
]
]
.where(
(PropertyInducingElement e) =>
e.isPublic &&
!e.isStatic &&
!_ignoreChecker.hasAnnotationOf(e.nonSynthetic) &&
!ignoreFields.contains(e.name),
)
.distinctBy((e) => e.name)
.toList();
}
List<String> get enumConsts {
return fields.where((e) => e.isEnumConstant).map((e) => e.name).toList();
}
}
extension PropertyElementX on PropertyInducingElement {
bool get isLink => type.element2!.name == 'IsarLink';
bool get isLinks => type.element2!.name == 'IsarLinks';
Enumerated? get enumeratedAnnotation {
final ann = _enumeratedChecker.firstAnnotationOfExact(nonSynthetic);
if (ann == null) {
return null;
}
final typeIndex = ann.getField('type')!.getField('index')!.toIntValue()!;
return Enumerated(
EnumType.values[typeIndex],
ann.getField('property')?.toStringValue(),
);
}
Backlink? get backlinkAnnotation {
final ann = _backlinkChecker.firstAnnotationOfExact(nonSynthetic);
if (ann == null) {
return null;
}
return Backlink(to: ann.getField('to')!.toStringValue()!);
}
List<Index> get indexAnnotations {
return _indexChecker.annotationsOfExact(nonSynthetic).map((DartObject ann) {
final rawComposite = ann.getField('composite')!.toListValue();
final composite = <CompositeIndex>[];
if (rawComposite != null) {
for (final c in rawComposite) {
final indexTypeField = c.getField('type')!;
IndexType? indexType;
if (!indexTypeField.isNull) {
final indexTypeIndex =
indexTypeField.getField('index')!.toIntValue()!;
indexType = IndexType.values[indexTypeIndex];
}
composite.add(
CompositeIndex(
c.getField('property')!.toStringValue()!,
type: indexType,
caseSensitive: c.getField('caseSensitive')!.toBoolValue(),
),
);
}
}
final indexTypeField = ann.getField('type')!;
IndexType? indexType;
if (!indexTypeField.isNull) {
final indexTypeIndex = indexTypeField.getField('index')!.toIntValue()!;
indexType = IndexType.values[indexTypeIndex];
}
return Index(
name: ann.getField('name')!.toStringValue(),
composite: composite,
unique: ann.getField('unique')!.toBoolValue()!,
replace: ann.getField('replace')!.toBoolValue()!,
type: indexType,
caseSensitive: ann.getField('caseSensitive')!.toBoolValue(),
);
}).toList();
}
}
extension ElementX on Element {
String get isarName {
final ann = _nameChecker.firstAnnotationOfExact(nonSynthetic);
late String name;
if (ann == null) {
name = displayName;
} else {
name = ann.getField('name')!.toStringValue()!;
}
checkIsarName(name, this);
return name;
}
Collection? get collectionAnnotation {
final ann = _collectionChecker.firstAnnotationOfExact(nonSynthetic);
if (ann == null) {
return null;
}
return Collection(
inheritance: ann.getField('inheritance')!.toBoolValue()!,
accessor: ann.getField('accessor')!.toStringValue(),
ignore: ann
.getField('ignore')!
.toSetValue()!
.map((e) => e.toStringValue()!)
.toSet(),
);
}
String get collectionAccessor {
var accessor = collectionAnnotation?.accessor;
if (accessor != null) {
return accessor;
}
accessor = displayName.decapitalize();
if (!accessor.endsWith('s')) {
accessor += 's';
}
return accessor;
}
Embedded? get embeddedAnnotation {
final ann = _embeddedChecker.firstAnnotationOfExact(nonSynthetic);
if (ann == null) {
return null;
}
return Embedded(
inheritance: ann.getField('inheritance')!.toBoolValue()!,
ignore: ann
.getField('ignore')!
.toSetValue()!
.map((e) => e.toStringValue()!)
.toSet(),
);
}
}
void checkIsarName(String name, Element element) {
if (name.isBlank || name.startsWith('_')) {
err('Names must not be blank or start with "_".', element);
}
}
Never err(String msg, [Element? element]) {
throw InvalidGenerationSourceError(msg, element: element);
}

View file

@ -1,502 +0,0 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:dartx/dartx.dart';
import 'package:isar/isar.dart';
import 'package:isar_generator/src/helper.dart';
import 'package:isar_generator/src/isar_type.dart';
import 'package:isar_generator/src/object_info.dart';
class IsarAnalyzer {
ObjectInfo analyzeCollection(Element element) {
final constructor = _checkValidClass(element);
final modelClass = element as ClassElement;
final properties = <ObjectProperty>[];
final links = <ObjectLink>[];
for (final propertyElement in modelClass.allAccessors) {
if (propertyElement.isLink || propertyElement.isLinks) {
final link = analyzeObjectLink(propertyElement);
links.add(link);
} else {
final property = analyzeObjectProperty(propertyElement, constructor);
properties.add(property);
}
}
_checkValidPropertiesConstructor(properties, constructor);
if (links.map((e) => e.isarName).distinct().length != links.length) {
err('Two or more links have the same name.', modelClass);
}
final indexes = <ObjectIndex>[];
for (final propertyElement in modelClass.allAccessors) {
indexes.addAll(analyzeObjectIndex(properties, propertyElement));
}
if (indexes.map((e) => e.name).distinct().length != indexes.length) {
err('Two or more indexes have the same name.', modelClass);
}
final idProperties = properties.where((it) => it.isId);
if (idProperties.isEmpty) {
err(
'No id property defined. Use the "Id" type for your id property.',
modelClass,
);
} else if (idProperties.length > 1) {
err('Two or more properties with type "Id" defined.', modelClass);
}
return ObjectInfo(
dartName: modelClass.displayName,
isarName: modelClass.isarName,
accessor: modelClass.collectionAccessor,
properties: properties,
embeddedDartNames: _getEmbeddedDartNames(element),
indexes: indexes,
links: links,
);
}
ObjectInfo analyzeEmbedded(Element element) {
final constructor = _checkValidClass(element);
final modelClass = element as ClassElement;
if (constructor.parameters.any((e) => e.isRequired)) {
err(
'Constructors of embedded objects must not have required parameters.',
constructor,
);
}
final properties = <ObjectProperty>[];
for (final propertyElement in modelClass.allAccessors) {
if (propertyElement.isLink || propertyElement.isLinks) {
err('Embedded objects must not contain links', propertyElement);
} else {
final property = analyzeObjectProperty(propertyElement, constructor);
properties.add(property);
}
}
_checkValidPropertiesConstructor(properties, constructor);
final hasIndex = modelClass.allAccessors.any(
(it) => it.indexAnnotations.isNotEmpty,
);
if (hasIndex) {
err('Embedded objects must not have indexes.', modelClass);
}
final hasIdProperty = properties.any((it) => it.isId);
if (hasIdProperty) {
err('Embedded objects must not define an id.', modelClass);
}
return ObjectInfo(
dartName: modelClass.displayName,
isarName: modelClass.isarName,
properties: properties,
);
}
ConstructorElement _checkValidClass(Element modelClass) {
if (modelClass is! ClassElement ||
modelClass is EnumElement ||
modelClass is MixinElement) {
err(
'Only classes may be annotated with @Collection or @Embedded.',
modelClass,
);
}
if (modelClass.isAbstract) {
err('Class must not be abstract.', modelClass);
}
if (!modelClass.isPublic) {
err('Class must be public.', modelClass);
}
final constructor = modelClass.constructors
.firstOrNullWhere((ConstructorElement c) => c.periodOffset == null);
if (constructor == null) {
err('Class needs an unnamed constructor.', modelClass);
}
final hasCollectionSupertype = modelClass.allSupertypes.any((type) {
return type.element.collectionAnnotation != null ||
type.element.embeddedAnnotation != null;
});
if (hasCollectionSupertype) {
err(
'Class must not have a supertype annotated with @Collection or '
'@Embedded.',
modelClass,
);
}
return constructor;
}
void _checkValidPropertiesConstructor(
List<ObjectProperty> properties,
ConstructorElement constructor,
) {
if (properties.map((e) => e.isarName).distinct().length !=
properties.length) {
err(
'Two or more properties have the same name.',
constructor.enclosingElement,
);
}
final unknownConstructorParameter = constructor.parameters.firstOrNullWhere(
(p) => p.isRequired && properties.none((e) => e.dartName == p.name),
);
if (unknownConstructorParameter != null) {
err(
'Constructor parameter does not match a property.',
unknownConstructorParameter,
);
}
}
Map<String, String> _getEmbeddedDartNames(ClassElement element) {
void _fillNames(Map<String, String> names, ClassElement element) {
for (final property in element.allAccessors) {
final type = property.type.scalarType.element;
if (type is ClassElement && type.embeddedAnnotation != null) {
final isarName = type.isarName;
if (!names.containsKey(isarName)) {
names[type.isarName] = type.displayName;
_fillNames(names, type);
}
}
}
}
final names = <String, String>{};
_fillNames(names, element);
return names;
}
ObjectProperty analyzeObjectProperty(
PropertyInducingElement property,
ConstructorElement constructor,
) {
final dartType = property.type;
final scalarDartType = dartType.scalarType;
Map<String, dynamic>? enumMap;
String? enumPropertyName;
String? defaultEnumElement;
late final IsarType isarType;
if (scalarDartType.element is EnumElement) {
final enumeratedAnn = property.enumeratedAnnotation;
if (enumeratedAnn == null) {
err('Enum property must be annotated with @enumerated.', property);
}
final enumClass = scalarDartType.element! as EnumElement;
final enumElements =
enumClass.fields.where((f) => f.isEnumConstant).toList();
defaultEnumElement = '${enumClass.name}.${enumElements.first.name}';
if (enumeratedAnn.type == EnumType.ordinal) {
isarType = dartType.isDartCoreList ? IsarType.byteList : IsarType.byte;
enumMap = {
for (var i = 0; i < enumElements.length; i++) enumElements[i].name: i,
};
enumPropertyName = 'index';
} else if (enumeratedAnn.type == EnumType.ordinal32) {
isarType = dartType.isDartCoreList ? IsarType.intList : IsarType.int;
enumMap = {
for (var i = 0; i < enumElements.length; i++) enumElements[i].name: i,
};
enumPropertyName = 'index';
} else if (enumeratedAnn.type == EnumType.name) {
isarType =
dartType.isDartCoreList ? IsarType.stringList : IsarType.string;
enumMap = {
for (final value in enumElements) value.name: value.name,
};
enumPropertyName = 'name';
} else {
enumPropertyName = enumeratedAnn.property;
if (enumPropertyName == null) {
err(
'Enums with type EnumType.value must specify which property '
'should be used.',
property,
);
}
final enumProperty = enumClass.getField(enumPropertyName);
if (enumProperty == null || enumProperty.isEnumConstant) {
err('Enum property "$enumProperty" does not exist.', property);
} else if (enumProperty.nonSynthetic is PropertyAccessorElement) {
err('Only fields are supported for enum properties', enumProperty);
}
final enumIsarType = enumProperty.type.isarType;
if (enumIsarType != IsarType.byte &&
enumIsarType != IsarType.int &&
enumIsarType != IsarType.long &&
enumIsarType != IsarType.string) {
err('Unsupported enum property type.', enumProperty);
}
isarType =
dartType.isDartCoreList ? enumIsarType!.listType : enumIsarType!;
enumMap = {};
for (final element in enumElements) {
final property =
element.computeConstantValue()!.getField(enumPropertyName)!;
final propertyValue = property.toBoolValue() ??
property.toIntValue() ??
property.toDoubleValue() ??
property.toStringValue();
if (propertyValue == null) {
err(
'Null values are not supported for enum properties.',
enumProperty,
);
}
if (enumMap.values.contains(propertyValue)) {
err(
'Enum property has duplicate values.',
enumProperty,
);
}
enumMap[element.name] = propertyValue;
}
}
} else {
if (dartType.isarType != null) {
isarType = dartType.isarType!;
} else {
err(
'Unsupported type. Please annotate the property with @ignore.',
property,
);
}
}
final nullable = dartType.nullabilitySuffix != NullabilitySuffix.none;
final elementNullable = isarType.isList &&
dartType.scalarType.nullabilitySuffix != NullabilitySuffix.none;
if ((isarType == IsarType.byte && nullable) ||
(isarType == IsarType.byteList && elementNullable)) {
err('Bytes must not be nullable.', property);
}
final constructorParameter =
constructor.parameters.firstOrNullWhere((p) => p.name == property.name);
int? constructorPosition;
late PropertyDeser deserialize;
if (constructorParameter != null) {
if (constructorParameter.type != property.type) {
err(
'Constructor parameter type does not match property type',
constructorParameter,
);
}
deserialize = constructorParameter.isNamed
? PropertyDeser.namedParam
: PropertyDeser.positionalParam;
constructorPosition =
constructor.parameters.indexOf(constructorParameter);
} else {
deserialize =
property.setter == null ? PropertyDeser.none : PropertyDeser.assign;
}
return ObjectProperty(
dartName: property.displayName,
isarName: property.isarName,
typeClassName: dartType.scalarType.element!.name!,
targetIsarName: isarType.containsObject
? dartType.scalarType.element!.isarName
: null,
isarType: isarType,
isId: dartType.isIsarId,
enumMap: enumMap,
enumProperty: enumPropertyName,
defaultEnumElement: defaultEnumElement,
nullable: nullable,
elementNullable: elementNullable,
userDefaultValue: constructorParameter?.defaultValueCode,
deserialize: deserialize,
assignable: property.setter != null,
constructorPosition: constructorPosition,
);
}
ObjectLink analyzeObjectLink(PropertyInducingElement property) {
if (property.type.nullabilitySuffix != NullabilitySuffix.none) {
err('Link properties must not be nullable.', property);
} else if (property.isLate) {
err('Link properties must not be late.', property);
}
final type = property.type as ParameterizedType;
final linkType = type.typeArguments[0];
if (linkType.nullabilitySuffix != NullabilitySuffix.none) {
err('Links type must not be nullable.', property);
}
final targetCol = linkType.element! as ClassElement;
if (targetCol.collectionAnnotation == null) {
err('Link target is not annotated with @collection');
}
final backlinkAnn = property.backlinkAnnotation;
String? targetLinkIsarName;
if (backlinkAnn != null) {
final targetProperty = targetCol.allAccessors
.firstOrNullWhere((e) => e.displayName == backlinkAnn.to);
if (targetProperty == null) {
err('Target of Backlink does not exist', property);
} else if (targetProperty.backlinkAnnotation != null) {
err('Target of Backlink is also a backlink', property);
}
if (!targetProperty.isLink && !targetProperty.isLinks) {
err('Target of backlink is not a link', property);
}
final targetLink = analyzeObjectLink(targetProperty);
targetLinkIsarName = targetLink.isarName;
}
return ObjectLink(
dartName: property.displayName,
isarName: property.isarName,
targetLinkIsarName: targetLinkIsarName,
targetCollectionDartName: linkType.element!.name!,
targetCollectionIsarName: targetCol.isarName,
isSingle: property.isLink,
);
}
Iterable<ObjectIndex> analyzeObjectIndex(
List<ObjectProperty> properties,
PropertyInducingElement element,
) sync* {
final property =
properties.firstOrNullWhere((it) => it.dartName == element.name);
if (property == null || property.isId) {
return;
}
for (final index in element.indexAnnotations) {
final indexProperties = <ObjectIndexProperty>[];
final isString = property.isarType == IsarType.string ||
property.isarType == IsarType.stringList;
final defaultType = property.isarType.isList || isString
? IndexType.hash
: IndexType.value;
indexProperties.add(
ObjectIndexProperty(
property: property,
type: index.type ?? defaultType,
caseSensitive: index.caseSensitive ?? isString,
),
);
for (final c in index.composite) {
final compositeProperty =
properties.firstOrNullWhere((it) => it.dartName == c.property);
if (compositeProperty == null) {
err('Property does not exist: "${c.property}".', element);
} else if (compositeProperty.isId) {
err('Ids cannot be indexed', element);
} else {
final isString = compositeProperty.isarType == IsarType.string ||
compositeProperty.isarType == IsarType.stringList;
final defaultType = compositeProperty.isarType.isList || isString
? IndexType.hash
: IndexType.value;
indexProperties.add(
ObjectIndexProperty(
property: compositeProperty,
type: c.type ?? defaultType,
caseSensitive: c.caseSensitive ?? isString,
),
);
}
}
final name = index.name ??
indexProperties.map((e) => e.property.isarName).join('_');
checkIsarName(name, element);
final objectIndex = ObjectIndex(
name: name,
properties: indexProperties,
unique: index.unique,
replace: index.replace,
);
_verifyObjectIndex(objectIndex, element);
yield objectIndex;
}
}
void _verifyObjectIndex(ObjectIndex index, Element element) {
final properties = index.properties;
if (properties.map((it) => it.property.isarName).distinct().length !=
properties.length) {
err('Composite index contains duplicate properties.', element);
}
for (var i = 0; i < properties.length; i++) {
final property = properties[i];
if (property.isarType.isList &&
property.type != IndexType.hash &&
properties.length > 1) {
err('Composite indexes do not support non-hashed lists.', element);
}
if (property.isarType.containsFloat && i != properties.lastIndex) {
err(
'Only the last property of a composite index may be a '
'double value.',
element,
);
}
if (property.isarType == IsarType.string) {
if (property.type != IndexType.hash && i != properties.lastIndex) {
err(
'Only the last property of a composite index may be a '
'non-hashed String.',
element,
);
}
}
if (property.isarType.containsObject) {
err(
'Embedded objects may not be indexed.',
element,
);
}
if (property.type != IndexType.value) {
if (!property.isarType.isList && property.isarType != IsarType.string) {
err('Only Strings and Lists may be hashed.', element);
} else if (property.isarType.containsFloat) {
err('List<double> may must not be hashed.', element);
}
}
if (property.isarType != IsarType.stringList &&
property.type == IndexType.hashElements) {
err('Only String lists may have hashed elements.', element);
}
}
if (!index.unique && index.replace) {
err('Only unique indexes can replace.', element);
}
}
}

View file

@ -1,107 +0,0 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:isar/isar.dart';
import 'package:isar_generator/src/helper.dart';
import 'package:source_gen/source_gen.dart';
const TypeChecker _dateTimeChecker = TypeChecker.fromRuntime(DateTime);
bool _isDateTime(Element element) => _dateTimeChecker.isExactly(element);
extension DartTypeX on DartType {
IsarType? get _primitiveIsarType {
if (isDartCoreBool) {
return IsarType.bool;
} else if (isDartCoreInt) {
if (alias?.element.name == 'byte') {
return IsarType.byte;
} else if (alias?.element.name == 'short') {
return IsarType.int;
} else {
return IsarType.long;
}
} else if (isDartCoreDouble) {
if (alias?.element.name == 'float') {
return IsarType.float;
} else {
return IsarType.double;
}
} else if (isDartCoreString) {
return IsarType.string;
} else if (_isDateTime(element2!)) {
return IsarType.dateTime;
} else if (element2!.embeddedAnnotation != null) {
return IsarType.object;
}
return null;
}
bool get isIsarId {
return alias?.element.name == 'Id';
}
DartType get scalarType {
if (isDartCoreList) {
final parameterizedType = this as ParameterizedType;
final typeArguments = parameterizedType.typeArguments;
if (typeArguments.isNotEmpty) {
return typeArguments[0];
}
}
return this;
}
IsarType? get isarType {
final primitiveType = _primitiveIsarType;
if (primitiveType != null) {
return primitiveType;
}
if (isDartCoreList) {
switch (scalarType._primitiveIsarType) {
case IsarType.bool:
return IsarType.boolList;
case IsarType.byte:
return IsarType.byteList;
case IsarType.int:
return IsarType.intList;
case IsarType.float:
return IsarType.floatList;
case IsarType.long:
return IsarType.longList;
case IsarType.double:
return IsarType.doubleList;
case IsarType.dateTime:
return IsarType.dateTimeList;
case IsarType.string:
return IsarType.stringList;
case IsarType.object:
return IsarType.objectList;
// ignore: no_default_cases
default:
return null;
}
}
return null;
}
}
extension IsarTypeX on IsarType {
bool get containsBool => this == IsarType.bool || this == IsarType.boolList;
bool get containsFloat =>
this == IsarType.float ||
this == IsarType.floatList ||
this == IsarType.double ||
this == IsarType.doubleList;
bool get containsDate =>
this == IsarType.dateTime || this == IsarType.dateTimeList;
bool get containsString =>
this == IsarType.string || this == IsarType.stringList;
bool get containsObject =>
this == IsarType.object || this == IsarType.objectList;
}

View file

@ -1,211 +0,0 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:dartx/dartx.dart';
import 'package:isar/isar.dart';
import 'package:xxh3/xxh3.dart';
class ObjectInfo {
ObjectInfo({
required this.dartName,
required this.isarName,
this.accessor,
required List<ObjectProperty> properties,
this.embeddedDartNames = const {},
this.indexes = const [],
this.links = const [],
}) {
this.properties = properties.sortedBy((e) => e.isarName).toList();
}
final String dartName;
final String isarName;
final String? accessor;
late final List<ObjectProperty> properties;
final Map<String, String> embeddedDartNames;
final List<ObjectIndex> indexes;
final List<ObjectLink> links;
int get id => xxh3(utf8.encode(isarName) as Uint8List);
bool get isEmbedded => accessor == null;
ObjectProperty get idProperty => properties.firstWhere((it) => it.isId);
List<ObjectProperty> get objectProperties =>
properties.where((it) => !it.isId).toList();
String get getIdName => '_${dartName.decapitalize()}GetId';
String get getLinksName => '_${dartName.decapitalize()}GetLinks';
String get attachName => '_${dartName.decapitalize()}Attach';
String get estimateSizeName => '_${dartName.decapitalize()}EstimateSize';
String get serializeName => '_${dartName.decapitalize()}Serialize';
String get deserializeName => '_${dartName.decapitalize()}Deserialize';
String get deserializePropName =>
'_${dartName.decapitalize()}DeserializeProp';
}
enum PropertyDeser {
none,
assign,
positionalParam,
namedParam,
}
class ObjectProperty {
ObjectProperty({
required this.dartName,
required this.isarName,
required this.typeClassName,
this.targetIsarName,
required this.isarType,
required this.isId,
required this.enumMap,
required this.enumProperty,
required this.defaultEnumElement,
required this.nullable,
required this.elementNullable,
this.userDefaultValue,
required this.deserialize,
required this.assignable,
this.constructorPosition,
});
final String dartName;
final String isarName;
final String typeClassName;
final String? targetIsarName;
final bool isId;
final IsarType isarType;
final Map<String, dynamic>? enumMap;
final String? enumProperty;
final String? defaultEnumElement;
final bool nullable;
final bool elementNullable;
final String? userDefaultValue;
final PropertyDeser deserialize;
final bool assignable;
final int? constructorPosition;
bool get isEnum => enumMap != null;
String get scalarDartType {
if (isId) {
return 'Id';
} else if (isEnum) {
return typeClassName;
}
switch (isarType) {
case IsarType.bool:
case IsarType.boolList:
return 'bool';
case IsarType.byte:
case IsarType.byteList:
case IsarType.int:
case IsarType.intList:
case IsarType.long:
case IsarType.longList:
return 'int';
case IsarType.float:
case IsarType.floatList:
case IsarType.double:
case IsarType.doubleList:
return 'double';
case IsarType.dateTime:
case IsarType.dateTimeList:
return 'DateTime';
case IsarType.object:
case IsarType.objectList:
return typeClassName;
case IsarType.string:
case IsarType.stringList:
return 'String';
}
}
String get nScalarDartType => isarType.isList
? '$scalarDartType${elementNullable ? '?' : ''}'
: '$scalarDartType${nullable ? '?' : ''}';
String get dartType => isarType.isList
? 'List<$nScalarDartType>${nullable ? '?' : ''}'
: nScalarDartType;
String get targetSchema => '${scalarDartType.capitalize()}Schema';
String enumValueMapName(ObjectInfo object) {
return '_${object.dartName}${dartName}EnumValueMap';
}
String valueEnumMapName(ObjectInfo object) {
return '_${object.dartName}${dartName}ValueEnumMap';
}
}
class ObjectIndexProperty {
const ObjectIndexProperty({
required this.property,
required this.type,
required this.caseSensitive,
});
final ObjectProperty property;
final IndexType type;
final bool caseSensitive;
IsarType get isarType => property.isarType;
bool get isMultiEntry => isarType.isList && type != IndexType.hash;
}
class ObjectIndex {
ObjectIndex({
required this.name,
required this.properties,
required this.unique,
required this.replace,
});
final String name;
final List<ObjectIndexProperty> properties;
final bool unique;
final bool replace;
late final id = xxh3(utf8.encode(name) as Uint8List);
}
class ObjectLink {
const ObjectLink({
required this.dartName,
required this.isarName,
this.targetLinkIsarName,
required this.targetCollectionDartName,
required this.targetCollectionIsarName,
required this.isSingle,
});
final String dartName;
final String isarName;
// isar name of the original link (only for backlinks)
final String? targetLinkIsarName;
final String targetCollectionDartName;
final String targetCollectionIsarName;
final bool isSingle;
bool get isBacklink => targetLinkIsarName != null;
int id(String objectIsarName) {
final col = isBacklink ? targetCollectionIsarName : objectIsarName;
final colId = xxh3(utf8.encode(col) as Uint8List, seed: isBacklink ? 1 : 0);
final name = targetLinkIsarName ?? isarName;
return xxh3(utf8.encode(name) as Uint8List, seed: colId);
}
}

View file

@ -1,533 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051
url: "https://pub.dev"
source: hosted
version: "64.0.0"
analyzer:
dependency: "direct main"
description:
name: analyzer
sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893"
url: "https://pub.dev"
source: hosted
version: "6.2.0"
args:
dependency: transitive
description:
name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
url: "https://pub.dev"
source: hosted
version: "2.4.2"
async:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev"
source: hosted
version: "2.11.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
build:
dependency: "direct main"
description:
name: build
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
build_config:
dependency: transitive
description:
name: build_config
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
url: "https://pub.dev"
source: hosted
version: "1.1.1"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
sha256: "64e12b0521812d1684b1917bc80945625391cb9bdd4312536b1d69dcb6133ed8"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
build_test:
dependency: "direct dev"
description:
name: build_test
sha256: "178a9e8989cbd40b3104b88cb6ab8cbf6e3293d90b31ba44420745cba54730f1"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
characters:
dependency: transitive
description:
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
url: "https://pub.dev"
source: hosted
version: "2.0.3"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.dev"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
url: "https://pub.dev"
source: hosted
version: "1.18.0"
convert:
dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
coverage:
dependency: transitive
description:
name: coverage
sha256: "595a29b55ce82d53398e1bcc2cba525d7bd7c59faeb2d2540e9d42c390cfeeeb"
url: "https://pub.dev"
source: hosted
version: "1.6.4"
crypto:
dependency: transitive
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev"
source: hosted
version: "3.0.3"
csslib:
dependency: transitive
description:
name: csslib
sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
dart_style:
dependency: "direct main"
description:
name: dart_style
sha256: abd7625e16f51f554ea244d090292945ec4d4be7bfbaf2ec8cccea568919d334
url: "https://pub.dev"
source: hosted
version: "2.3.3"
dartx:
dependency: "direct main"
description:
name: dartx
sha256: "8b25435617027257d43e6508b5fe061012880ddfdaa75a71d607c3de2a13d244"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
ffi:
dependency: transitive
description:
name: ffi
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
file:
dependency: transitive
description:
name: file
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
url: "https://pub.dev"
source: hosted
version: "3.2.0"
glob:
dependency: "direct main"
description:
name: glob
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
graphs:
dependency: transitive
description:
name: graphs
sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
url: "https://pub.dev"
source: hosted
version: "2.3.1"
html:
dependency: transitive
description:
name: html
sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
url: "https://pub.dev"
source: hosted
version: "0.15.4"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
url: "https://pub.dev"
source: hosted
version: "3.2.1"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
io:
dependency: transitive
description:
name: io
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
isar:
dependency: "direct main"
description:
name: isar
sha256: "99165dadb2cf2329d3140198363a7e7bff9bbd441871898a87e26914d25cf1ea"
url: "https://pub.dev"
source: hosted
version: "3.1.0+1"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
json_annotation:
dependency: transitive
description:
name: json_annotation
sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
url: "https://pub.dev"
source: hosted
version: "4.8.1"
logging:
dependency: transitive
description:
name: logging
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
matcher:
dependency: "direct dev"
description:
name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev"
source: hosted
version: "0.12.16"
meta:
dependency: transitive
description:
name: meta
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
url: "https://pub.dev"
source: hosted
version: "1.10.0"
mime:
dependency: transitive
description:
name: mime
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
url: "https://pub.dev"
source: hosted
version: "1.0.4"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
package_config:
dependency: transitive
description:
name: package_config
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
path:
dependency: "direct main"
description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
source: hosted
version: "1.8.3"
pool:
dependency: transitive
description:
name: pool
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
url: "https://pub.dev"
source: hosted
version: "1.5.1"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
url: "https://pub.dev"
source: hosted
version: "1.2.3"
shelf:
dependency: transitive
description:
name: shelf
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
url: "https://pub.dev"
source: hosted
version: "1.4.1"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e
url: "https://pub.dev"
source: hosted
version: "1.1.2"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
source_gen:
dependency: "direct main"
description:
name: source_gen
sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16
url: "https://pub.dev"
source: hosted
version: "1.4.0"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
url: "https://pub.dev"
source: hosted
version: "0.10.12"
source_span:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
url: "https://pub.dev"
source: hosted
version: "1.11.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.dev"
source: hosted
version: "2.1.2"
stream_transform:
dependency: transitive
description:
name: stream_transform
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.dev"
source: hosted
version: "1.2.1"
test:
dependency: "direct dev"
description:
name: test
sha256: a20ddc0723556dc6dd56094e58ec1529196d5d7774156604cb14e8445a5a82ff
url: "https://pub.dev"
source: hosted
version: "1.24.7"
test_api:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
url: "https://pub.dev"
source: hosted
version: "0.6.1"
test_core:
dependency: transitive
description:
name: test_core
sha256: "96382d0bc826e260b077bb496259e58bc82e90b603ab16cd5ae95dfe1dfcba8b"
url: "https://pub.dev"
source: hosted
version: "0.5.7"
time:
dependency: transitive
description:
name: time
sha256: "83427e11d9072e038364a5e4da559e85869b227cf699a541be0da74f14140124"
url: "https://pub.dev"
source: hosted
version: "2.1.3"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev"
source: hosted
version: "1.3.2"
very_good_analysis:
dependency: "direct dev"
description:
name: very_good_analysis
sha256: "4815adc7ded57657038d2bb2a7f332c50e3c8152f7d3c6acf8f6b7c0cc81e5e2"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: a13d5503b4facefc515c8c587ce3cf69577a7b064a9f1220e005449cf1f64aad
url: "https://pub.dev"
source: hosted
version: "12.0.0"
watcher:
dependency: transitive
description:
name: watcher
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
url: "https://pub.dev"
source: hosted
version: "2.4.0"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
xxh3:
dependency: "direct main"
description:
name: xxh3
sha256: a92b30944a9aeb4e3d4f3c3d4ddb3c7816ca73475cd603682c4f8149690f56d7
url: "https://pub.dev"
source: hosted
version: "1.0.1"
yaml:
dependency: transitive
description:
name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.0.0 <4.0.0"

View file

@ -1,25 +0,0 @@
name: isar_generator
description: Code generator for the Isar Database. Finds classes annotated with @Collection.
version: 3.1.0+1
repository: https://github.com/isar/isar
homepage: https://isar.dev
environment:
sdk: ">=2.17.0 <3.0.0"
dependencies:
analyzer: ">=5.2.0 <7.0.0"
build: ^2.3.0
dart_style: ^2.2.3
dartx: ^1.1.0
glob: ^2.0.2
isar: 3.1.0+1
path: ^1.8.1
source_gen: ^1.2.2
xxh3: ^1.0.1
dev_dependencies:
build_test: ^2.1.5
matcher: ^0.12.12
test: ^1.21.0
very_good_analysis: ^3.0.1

View file

@ -1,33 +0,0 @@
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()));
});
}
});
}

View file

@ -1,8 +0,0 @@
// must not be abstract
import 'package:isar/isar.dart';
@collection
abstract class Model {
Id? id;
}

View file

@ -1,19 +0,0 @@
// supertype annotated with @collection
import 'package:isar/isar.dart';
@collection
class Supertype {
Id? id;
}
class Subtype implements Supertype {
@override
Id? id;
}
@collection
class Model implements Subtype {
@override
Id? id;
}

View file

@ -1,10 +0,0 @@
// unnamed constructor
import 'package:isar/isar.dart';
@collection
class Model {
Model.create();
Id? id;
}

View file

@ -1,13 +0,0 @@
// 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);
Id? id;
final String prop1;
}

View file

@ -1,13 +0,0 @@
// constructor parameter type does not match property type
import 'package:isar/isar.dart';
@collection
class Model {
// ignore: avoid_unused_constructor_parameters
Model(int prop1);
Id? id;
String prop1 = '5';
}

View file

@ -1,7 +0,0 @@
// only classes
import 'package:isar/isar.dart';
// ignore: invalid_annotation_target
@collection
enum Test { a, b, c }

View file

@ -1,8 +0,0 @@
// must not be abstract
import 'package:isar/isar.dart';
@collection
abstract class Model {
Id? id;
}

View file

@ -1,7 +0,0 @@
// only classes
import 'package:isar/isar.dart';
// ignore: invalid_annotation_target
@collection
mixin Test {}

View file

@ -1,9 +0,0 @@
// must be public
import 'package:isar/isar.dart';
@collection
// ignore: unused_element
class _Model {
Id? id;
}

View file

@ -1,7 +0,0 @@
// only classes
import 'package:isar/isar.dart';
// ignore: invalid_annotation_target
@collection
const t = 'hello';

View file

@ -1,10 +0,0 @@
// two or more properties with type "Id" defined
import 'package:isar/isar.dart';
@collection
class Test {
Id? id1;
Id? id2;
}

View file

@ -1,10 +0,0 @@
// no id property defined
import 'package:isar/isar.dart';
@collection
class Test {
late int id;
late String name;
}

View file

@ -1,13 +0,0 @@
// only the last property of a composite index may be a double value
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(composite: [CompositeIndex('val2')])
double? val1;
String? val2;
}

View file

@ -1,13 +0,0 @@
// composite indexes do not support non-hashed lists
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(composite: [CompositeIndex('str')], type: IndexType.value)
List<int>? list;
String? str;
}

View file

@ -1,13 +0,0 @@
// last property of a composite index may be a non-hashed string
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(composite: [CompositeIndex('str2')], type: IndexType.value)
String? str1;
String? str2;
}

View file

@ -1,11 +0,0 @@
// ids cannot be indexed
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(composite: [CompositeIndex('id')])
String? str;
}

View file

@ -1,11 +0,0 @@
// list<double> may must not be hashed
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(type: IndexType.hash)
List<double>? list;
}

View file

@ -1,14 +0,0 @@
// same name
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(name: 'myindex')
String? prop1;
@Index(name: 'myindex')
String? prop2;
}

View file

@ -1,13 +0,0 @@
// composite index contains duplicate properties
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(composite: [CompositeIndex('str1')], type: IndexType.value)
String? str1;
String? str2;
}

View file

@ -1,11 +0,0 @@
// names must not be blank or start with "_"
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(name: '_index')
String? str;
}

View file

@ -1,11 +0,0 @@
// only strings and lists may be hashed
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(type: IndexType.hash)
int? val;
}

View file

@ -1,11 +0,0 @@
// only string lists may have hashed elements
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(type: IndexType.hashElements)
List<int>? list;
}

View file

@ -1,11 +0,0 @@
// only unique indexes can replace
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(replace: true)
String? str;
}

View file

@ -1,14 +0,0 @@
// objects may not be indexed
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index()
EmbeddedModel? obj;
}
@embedded
class EmbeddedModel {}

View file

@ -1,14 +0,0 @@
// objects may not be indexed
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(type: IndexType.hash)
List<EmbeddedModel>? list;
}
@embedded
class EmbeddedModel {}

View file

@ -1,11 +0,0 @@
// property does not exist
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Index(composite: [CompositeIndex('myProp')])
String? str;
}

View file

@ -1,16 +0,0 @@
// target of backlink does not exist
import 'package:isar/isar.dart';
@collection
class Model1 {
Id? id;
@Backlink(to: 'abc')
final IsarLink<Model2> link = IsarLink();
}
@collection
class Model2 {
Id? id;
}

View file

@ -1,19 +0,0 @@
// target of backlink is also a backlink
import 'package:isar/isar.dart';
@collection
class Model1 {
Id? id;
@Backlink(to: 'link')
final IsarLink<Model2> link = IsarLink();
}
@collection
class Model2 {
Id? id;
@Backlink(to: 'link')
final IsarLink<Model1> link = IsarLink();
}

View file

@ -1,18 +0,0 @@
// target of backlink is not a link
import 'package:isar/isar.dart';
@collection
class Model1 {
Id? id;
@Backlink(to: 'str')
final IsarLink<Model2> link = IsarLink();
}
@collection
class Model2 {
Id? id;
String? str;
}

View file

@ -1,18 +0,0 @@
// same name
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
final IsarLink<Model2> prop1 = IsarLink();
@Name('prop1')
final IsarLinks<Model2> prop2 = IsarLinks();
}
@collection
class Model2 {
Id? id;
}

View file

@ -1,16 +0,0 @@
// names must not be blank or start with
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Name('_link')
final IsarLink<Model2> link = IsarLink();
}
@collection
class Model2 {
Id? id;
}

View file

@ -1,15 +0,0 @@
// must not be late
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
late IsarLink<Model2> link;
}
@collection
class Model2 {
Id? id;
}

View file

@ -1,15 +0,0 @@
// must not be nullable
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
IsarLink<Model2>? link;
}
@collection
class Model2 {
Id? id;
}

View file

@ -1,10 +0,0 @@
// link target is not annotated with @collection
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
final IsarLink<int> link = IsarLink();
}

View file

@ -1,15 +0,0 @@
// links type must not be nullable
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
final IsarLink<Model2?> link = IsarLink();
}
@collection
class Model2 {
Id? id;
}

View file

@ -1,13 +0,0 @@
// same name
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
String? prop1;
@Name('prop1')
String? prop2;
}

View file

@ -1,17 +0,0 @@
// unsupported enum property type
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Enumerated(EnumType.value, 'value')
late MyEnum field;
}
enum MyEnum {
optionA;
final bool value = true;
}

View file

@ -1,17 +0,0 @@
// unsupported enum property type
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Enumerated(EnumType.value, 'value')
late MyEnum field;
}
enum MyEnum {
optionA;
final double value = 5.5;
}

View file

@ -1,21 +0,0 @@
// has duplicate values
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Enumerated(EnumType.value, 'value')
late MyEnum field;
}
enum MyEnum {
option1(1),
option2(2),
option3(1);
const MyEnum(this.value);
final int value;
}

View file

@ -1,17 +0,0 @@
// unsupported enum property type
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Enumerated(EnumType.value, 'value')
late MyEnum field;
}
enum MyEnum {
optionA;
final float value = 5.5;
}

View file

@ -1,17 +0,0 @@
// unsupported enum property type
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Enumerated(EnumType.value, 'value')
late MyEnum prop;
}
enum MyEnum {
optionA;
final List<String> value = [];
}

View file

@ -1,14 +0,0 @@
// enum property must be annotated with @enumerated
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
late MyEnum? prop;
}
enum MyEnum {
a;
}

View file

@ -1,17 +0,0 @@
// null values are not supported
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Enumerated(EnumType.value, 'value')
late MyEnum prop;
}
enum MyEnum {
optionA;
final String? value = null;
}

View file

@ -1,20 +0,0 @@
// unsupported enum property type
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Enumerated(EnumType.value, 'value')
late MyEnum prop;
}
enum MyEnum {
optionA;
final value = EmbeddedModel();
}
@embedded
class EmbeddedModel {}

View file

@ -1,11 +0,0 @@
// names must not be blank or start with "_"
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
@Name('_prop')
String? prop;
}

View file

@ -1,10 +0,0 @@
// bytes must not be nullable
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
late byte? prop;
}

View file

@ -1,10 +0,0 @@
// bytes must not be nullable
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
late List<byte?> prop;
}

View file

@ -1,10 +0,0 @@
// unsupported type
import 'package:isar/isar.dart';
@collection
class Model {
Id? id;
late Set<String>? prop;
}

View file

@ -10,7 +10,7 @@ packages:
source: hosted
version: "64.0.0"
analyzer:
dependency: transitive
dependency: "direct overridden"
description:
name: analyzer
sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893"
@ -697,9 +697,10 @@ packages:
isar_generator:
dependency: "direct dev"
description:
path: "packages/isar_generator"
relative: true
source: path
name: isar_generator
sha256: "76c121e1295a30423604f2f819bc255bc79f852f3bc8743a24017df6068ad133"
url: "https://pub.dev"
source: hosted
version: "3.1.0+1"
js:
dependency: transitive

View file

@ -58,10 +58,11 @@ dependencies:
crypto: ^3.0.3
rinf: ^4.13.1
protobuf: ^3.1.0
cupertino_icons: ^1.0.2
cupertino_icons: ^1.0.2
dependency_overrides:
analyzer: ">=5.2.0 <7.0.0"
dev_dependencies:
flutter_test:
@ -69,8 +70,7 @@ dev_dependencies:
build_runner: ^2.4.6
riverpod_generator: ^2.3.2
flutter_launcher_icons: ^0.13.1
isar_generator:
path: ./packages/isar_generator
isar_generator: ^3.1.0+1
flutter_lints: ^2.0.1
flutter: