From 4eba4e70705bd8a32b932a7a494957392eedecbc Mon Sep 17 00:00:00 2001 From: Gustav Bylund Date: Mon, 19 Oct 2020 19:15:40 +0200 Subject: [PATCH 1/2] feat: add support for documentation comments --- .../tests/lib/database/database.dart | 7 +++++++ .../tests/lib/database/database.g.dart | 5 +++++ .../lib/src/analyzer/dart/column_parser.dart | 4 ++++ moor_generator/lib/src/model/column.dart | 6 ++++++ .../src/writer/tables/data_class_writer.dart | 3 +++ .../test/analyzer/dart/table_parser_test.dart | 19 +++++++++++++++++++ 6 files changed, 44 insertions(+) diff --git a/extras/integration_tests/tests/lib/database/database.dart b/extras/integration_tests/tests/lib/database/database.dart index 12d6ee6c..5439ecde 100644 --- a/extras/integration_tests/tests/lib/database/database.dart +++ b/extras/integration_tests/tests/lib/database/database.dart @@ -8,8 +8,15 @@ import 'package:tests/data/sample_data.dart' as people; part 'database.g.dart'; class Users extends Table { + /// The user id IntColumn get id => integer().autoIncrement()(); + + // The user name TextColumn get name => text()(); + + /// The users birth date + /// + /// Mapped from json `born_on` @JsonKey('born_on') DateTimeColumn get birthDate => dateTime()(); diff --git a/extras/integration_tests/tests/lib/database/database.g.dart b/extras/integration_tests/tests/lib/database/database.g.dart index 901e6133..8fd8f62e 100644 --- a/extras/integration_tests/tests/lib/database/database.g.dart +++ b/extras/integration_tests/tests/lib/database/database.g.dart @@ -23,8 +23,13 @@ Map _$PreferencesToJson(Preferences instance) => // ignore_for_file: unnecessary_brace_in_string_interps, unnecessary_this class User extends DataClass implements Insertable { + /// The user id final int id; final String name; + + /// The users birth date + /// + /// Mapped from json `born_on` final DateTime birthDate; final Uint8List profilePicture; final Preferences preferences; diff --git a/moor_generator/lib/src/analyzer/dart/column_parser.dart b/moor_generator/lib/src/analyzer/dart/column_parser.dart index e25b7118..3efa8d7e 100644 --- a/moor_generator/lib/src/analyzer/dart/column_parser.dart +++ b/moor_generator/lib/src/analyzer/dart/column_parser.dart @@ -221,6 +221,9 @@ class ColumnParser { ); } + final docString = getter.documentationComment?.tokens + ?.map((t) => t.toString()) + ?.join('\n'); return MoorColumn( type: columnType, dartGetterName: getter.name.name, @@ -233,6 +236,7 @@ class ColumnParser { clientDefaultCode: clientDefaultExpression?.toSource(), typeConverter: converter, declaration: DartColumnDeclaration(element, base.step.file), + documentationComment: docString, ); } diff --git a/moor_generator/lib/src/model/column.dart b/moor_generator/lib/src/model/column.dart index c7aea3c5..b3d03691 100644 --- a/moor_generator/lib/src/model/column.dart +++ b/moor_generator/lib/src/model/column.dart @@ -96,6 +96,11 @@ class MoorColumn implements HasDeclaration, HasType { @override final UsedTypeConverter typeConverter; + /// The documentation comment associated with this column + /// + /// Stored as a multi line string with leading triple-slashes `///` for every line + final String documentationComment; + /// The column type from the dsl library. For instance, if a table has /// declared an `IntColumn`, the matching dsl column name would also be an /// `IntColumn`. @@ -132,6 +137,7 @@ class MoorColumn implements HasDeclaration, HasType { this.clientDefaultCode, this.typeConverter, this.declaration, + this.documentationComment, }); } diff --git a/moor_generator/lib/src/writer/tables/data_class_writer.dart b/moor_generator/lib/src/writer/tables/data_class_writer.dart index 312fc44d..f9fce0d2 100644 --- a/moor_generator/lib/src/writer/tables/data_class_writer.dart +++ b/moor_generator/lib/src/writer/tables/data_class_writer.dart @@ -22,6 +22,9 @@ class DataClassWriter { // write individual fields for (final column in table.columns) { + if (column.documentationComment != null) { + _buffer.write('${column.documentationComment}\n'); + } final modifier = scope.options.fieldModifier; _buffer.write('$modifier ${column.dartTypeCode(scope.generationOptions)} ' '${column.dartGetterName}; \n'); diff --git a/moor_generator/test/analyzer/dart/table_parser_test.dart b/moor_generator/test/analyzer/dart/table_parser_test.dart index 55c65a2f..7da510a9 100644 --- a/moor_generator/test/analyzer/dart/table_parser_test.dart +++ b/moor_generator/test/analyzer/dart/table_parser_test.dart @@ -26,7 +26,11 @@ void main() { } class Users extends Table { + /// The user id IntColumn get id => integer().autoIncrement()(); + /// The username + /// + /// The username must be between 6-32 characters TextColumn get name => text().named("user_name").withLength(min: 6, max: 32)(); TextColumn get onlyMax => text().withLength(max: 100)(); @@ -187,6 +191,21 @@ void main() { expect(defaultsColumn.defaultArgument.toString(), 'currentDate'); }); + + test('parses documentation comments', () async { + final table = await parse('Users'); + final idColumn = + table.columns.singleWhere((col) => col.name.name == 'id'); + + final usernameColumn = + table.columns.singleWhere((col) => col.name.name == 'user_name'); + + expect(idColumn.documentationComment, '/// The user id'); + expect( + usernameColumn.documentationComment, + '/// The username\n///\n/// The username must be between 6-32 characters', + ); + }); }); test('parses custom primary keys', () async { From 3415c3e84c77af0eabad03a7f870038e8c89d57f Mon Sep 17 00:00:00 2001 From: Gustav Bylund Date: Mon, 19 Oct 2020 19:16:02 +0200 Subject: [PATCH 2/2] chore: regenerate integratation test database.g.dart --- .../tests/lib/database/database.g.dart | 89 ++++++++++++++----- 1 file changed, 68 insertions(+), 21 deletions(-) diff --git a/extras/integration_tests/tests/lib/database/database.g.dart b/extras/integration_tests/tests/lib/database/database.g.dart index 8fd8f62e..fd91f9aa 100644 --- a/extras/integration_tests/tests/lib/database/database.g.dart +++ b/extras/integration_tests/tests/lib/database/database.g.dart @@ -79,6 +79,22 @@ class User extends DataClass implements Insertable { return map; } + UsersCompanion toCompanion(bool nullToAbsent) { + return UsersCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + name: name == null && nullToAbsent ? const Value.absent() : Value(name), + birthDate: birthDate == null && nullToAbsent + ? const Value.absent() + : Value(birthDate), + profilePicture: profilePicture == null && nullToAbsent + ? const Value.absent() + : Value(profilePicture), + preferences: preferences == null && nullToAbsent + ? const Value.absent() + : Value(preferences), + ); + } + factory User.fromJson(Map json, {ValueSerializer serializer}) { serializer ??= moorRuntimeOptions.defaultSerializer; @@ -219,6 +235,18 @@ class UsersCompanion extends UpdateCompanion { } return map; } + + @override + String toString() { + return (StringBuffer('UsersCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('birthDate: $birthDate, ') + ..write('profilePicture: $profilePicture, ') + ..write('preferences: $preferences') + ..write(')')) + .toString(); + } } class $UsersTable extends Users with TableInfo<$UsersTable, User> { @@ -379,6 +407,20 @@ class Friendship extends DataClass implements Insertable { return map; } + FriendshipsCompanion toCompanion(bool nullToAbsent) { + return FriendshipsCompanion( + firstUser: firstUser == null && nullToAbsent + ? const Value.absent() + : Value(firstUser), + secondUser: secondUser == null && nullToAbsent + ? const Value.absent() + : Value(secondUser), + reallyGoodFriends: reallyGoodFriends == null && nullToAbsent + ? const Value.absent() + : Value(reallyGoodFriends), + ); + } + factory Friendship.fromJson(Map json, {ValueSerializer serializer}) { serializer ??= moorRuntimeOptions.defaultSerializer; @@ -479,6 +521,16 @@ class FriendshipsCompanion extends UpdateCompanion { } return map; } + + @override + String toString() { + return (StringBuffer('FriendshipsCompanion(') + ..write('firstUser: $firstUser, ') + ..write('secondUser: $secondUser, ') + ..write('reallyGoodFriends: $reallyGoodFriends') + ..write(')')) + .toString(); + } } class $FriendshipsTable extends Friendships @@ -579,22 +631,11 @@ abstract class _$Database extends GeneratedDatabase { $UsersTable get users => _users ??= $UsersTable(this); $FriendshipsTable _friendships; $FriendshipsTable get friendships => _friendships ??= $FriendshipsTable(this); - User _rowToUser(QueryRow row) { - return User( - id: row.readInt('id'), - name: row.readString('name'), - birthDate: row.readDateTime('birth_date'), - profilePicture: row.readBlob('profile_picture'), - preferences: - $UsersTable.$converter0.mapToDart(row.readString('preferences')), - ); - } - Selectable mostPopularUsers(int amount) { return customSelect( 'SELECT * FROM users u ORDER BY (SELECT COUNT(*) FROM friendships WHERE first_user = u.id OR second_user = u.id) DESC LIMIT :amount', variables: [Variable.withInt(amount)], - readsFrom: {users, friendships}).map(_rowToUser); + readsFrom: {users, friendships}).map(users.mapFromRow); } Selectable amountOfGoodFriends(int user) { @@ -608,18 +649,16 @@ abstract class _$Database extends GeneratedDatabase { }).map((QueryRow row) => row.readInt('COUNT(*)')); } - FriendshipsOfResult _rowToFriendshipsOfResult(QueryRow row) { - return FriendshipsOfResult( - reallyGoodFriends: row.readBool('really_good_friends'), - user: users.mapFromRowOrNull(row, tablePrefix: 'nested_0'), - ); - } - Selectable friendshipsOf(int user) { return customSelect( 'SELECT \n f.really_good_friends, "user"."id" AS "nested_0.id", "user"."name" AS "nested_0.name", "user"."birth_date" AS "nested_0.birth_date", "user"."profile_picture" AS "nested_0.profile_picture", "user"."preferences" AS "nested_0.preferences"\n FROM friendships f\n INNER JOIN users user ON user.id IN (f.first_user, f.second_user) AND\n user.id != :user\n WHERE (f.first_user = :user OR f.second_user = :user)', variables: [Variable.withInt(user)], - readsFrom: {friendships, users}).map(_rowToFriendshipsOfResult); + readsFrom: {friendships, users}).map((QueryRow row) { + return FriendshipsOfResult( + reallyGoodFriends: row.readBool('really_good_friends'), + user: users.mapFromRowOrNull(row, tablePrefix: 'nested_0'), + ); + }); } Selectable userCount() { @@ -641,7 +680,7 @@ abstract class _$Database extends GeneratedDatabase { $arrayStartIndex += var1.length; return customSelect('SELECT * FROM users WHERE id IN ($expandedvar1)', variables: [for (var $ in var1) Variable.withInt($)], - readsFrom: {users}).map(_rowToUser); + readsFrom: {users}).map(users.mapFromRow); } @override @@ -665,4 +704,12 @@ class FriendshipsOfResult { (other is FriendshipsOfResult && other.reallyGoodFriends == this.reallyGoodFriends && other.user == this.user); + @override + String toString() { + return (StringBuffer('FriendshipsOfResult(') + ..write('reallyGoodFriends: $reallyGoodFriends, ') + ..write('user: $user') + ..write(')')) + .toString(); + } }