diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..c03528d --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,41 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: + - package:lints/recommended.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + always_declare_return_types: true + annotate_redeclares: true + avoid_print: false + avoid_setters_without_getters: true + avoid_slow_async_io: true + directives_ordering: true + eol_at_end_of_file: true + prefer_const_declarations: true + prefer_contains: true + prefer_final_fields: true + prefer_final_locals: true + prefer_single_quotes: true + use_key_in_widget_constructors: true + use_null_aware_elements: true + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/bin/jadb.dart b/bin/jadb.dart index 8c2d8e5..a8291fa 100644 --- a/bin/jadb.dart +++ b/bin/jadb.dart @@ -9,7 +9,7 @@ import 'package:jadb/cli/commands/query_word.dart'; Future main(List args) async { final runner = CommandRunner( 'jadb', - "CLI tool to help creating and testing the jadb database", + 'CLI tool to help creating and testing the jadb database', ); runner.addCommand(CreateDb()); diff --git a/lib/_data_ingestion/jmdict/objects.dart b/lib/_data_ingestion/jmdict/objects.dart index f932677..ea75d10 100644 --- a/lib/_data_ingestion/jmdict/objects.dart +++ b/lib/_data_ingestion/jmdict/objects.dart @@ -16,6 +16,7 @@ abstract class Element extends SQLWritable { this.nf, }); + @override Map get sqlValue => { 'reading': reading, 'news': news, @@ -33,20 +34,13 @@ class KanjiElement extends Element { KanjiElement({ this.info = const [], required this.orderNum, - required String reading, - int? news, - int? ichi, - int? spec, - int? gai, - int? nf, - }) : super( - reading: reading, - news: news, - ichi: ichi, - spec: spec, - gai: gai, - nf: nf, - ); + required super.reading, + super.news, + super.ichi, + super.spec, + super.gai, + super.nf, + }); @override Map get sqlValue => { @@ -66,20 +60,13 @@ class ReadingElement extends Element { required this.readingDoesNotMatchKanji, this.info = const [], this.restrictions = const [], - required String reading, - int? news, - int? ichi, - int? spec, - int? gai, - int? nf, - }) : super( - reading: reading, - news: news, - ichi: ichi, - spec: spec, - gai: gai, - nf: nf, - ); + required super.reading, + super.news, + super.ichi, + super.spec, + super.gai, + super.nf, + }); @override Map get sqlValue => { @@ -118,6 +105,7 @@ class Glossary extends SQLWritable { const Glossary({required this.language, required this.phrase, this.type}); + @override Map get sqlValue => { 'language': language, 'phrase': phrase, @@ -216,5 +204,6 @@ class Entry extends SQLWritable { required this.senses, }); + @override Map get sqlValue => {'entryId': entryId}; } diff --git a/lib/_data_ingestion/jmdict/seed_data.dart b/lib/_data_ingestion/jmdict/seed_data.dart index ff9a5b1..d84a929 100644 --- a/lib/_data_ingestion/jmdict/seed_data.dart +++ b/lib/_data_ingestion/jmdict/seed_data.dart @@ -21,9 +21,9 @@ ResolvedXref resolveXref( (null, null) => throw Exception( 'Xref $xref has no kanji or reading reference', ), - (String k, null) => entriesByKanji[k]!.toList(), - (null, String r) => entriesByReading[r]!.toList(), - (String k, String r) => + (final String k, null) => entriesByKanji[k]!.toList(), + (null, final String r) => entriesByReading[r]!.toList(), + (final String k, final String r) => entriesByKanji[k]!.intersection(entriesByReading[r]!).toList(), }; @@ -41,7 +41,7 @@ ResolvedXref resolveXref( xref.readingRef != null && candidateEntries.length > 1) { final candidatesWithEmptyKanji = candidateEntries - .where((entry) => entry.kanji.length == 0) + .where((entry) => entry.kanji.isEmpty) .toList(); if (candidatesWithEmptyKanji.isNotEmpty) { @@ -53,7 +53,7 @@ ResolvedXref resolveXref( // entry in case there are multiple candidates left. candidateEntries.sortBy((entry) => entry.senses.length); - if (candidateEntries.length == 0) { + if (candidateEntries.isEmpty) { throw Exception( 'SKIPPING: Xref $xref has ${candidateEntries.length} entries, ' 'kanjiRef: ${xref.kanjiRef}, readingRef: ${xref.readingRef}, ' @@ -180,7 +180,7 @@ Future seedJMDictData(List entries, Database db) async { await b.commit(noResult: true); print(' [JMdict] Building xref trees'); - SplayTreeMap> entriesByKanji = SplayTreeMap(); + final SplayTreeMap> entriesByKanji = SplayTreeMap(); for (final entry in entries) { for (final kanji in entry.kanji) { @@ -191,7 +191,7 @@ Future seedJMDictData(List entries, Database db) async { } } } - SplayTreeMap> entriesByReading = SplayTreeMap(); + final SplayTreeMap> entriesByReading = SplayTreeMap(); for (final entry in entries) { for (final reading in entry.readings) { if (entriesByReading.containsKey(reading.reading)) { diff --git a/lib/_data_ingestion/jmdict/xml_parser.dart b/lib/_data_ingestion/jmdict/xml_parser.dart index b877249..5e61e00 100644 --- a/lib/_data_ingestion/jmdict/xml_parser.dart +++ b/lib/_data_ingestion/jmdict/xml_parser.dart @@ -8,9 +8,9 @@ List getPriorityValues(XmlElement e, String prefix) { int? news, ichi, spec, gai, nf; for (final pri in e.findElements('${prefix}_pri')) { final txt = pri.innerText; - if (txt.startsWith('news')) + if (txt.startsWith('news')) { news = int.parse(txt.substring(4)); - else if (txt.startsWith('ichi')) + } else if (txt.startsWith('ichi')) ichi = int.parse(txt.substring(4)); else if (txt.startsWith('spec')) spec = int.parse(txt.substring(4)); @@ -80,7 +80,7 @@ List parseJMDictData(XmlElement root) { final List senses = []; for (final (kanjiNum, k_ele) in entry.findElements('k_ele').indexed) { - final ke_pri = getPriorityValues(k_ele, 'ke'); + final kePri = getPriorityValues(k_ele, 'ke'); kanjiEls.add( KanjiElement( orderNum: kanjiNum + 1, @@ -89,17 +89,17 @@ List parseJMDictData(XmlElement root) { .map((e) => e.innerText.substring(1, e.innerText.length - 1)) .toList(), reading: k_ele.findElements('keb').first.innerText, - news: ke_pri[0], - ichi: ke_pri[1], - spec: ke_pri[2], - gai: ke_pri[3], - nf: ke_pri[4], + news: kePri[0], + ichi: kePri[1], + spec: kePri[2], + gai: kePri[3], + nf: kePri[4], ), ); } for (final (orderNum, r_ele) in entry.findElements('r_ele').indexed) { - final re_pri = getPriorityValues(r_ele, 're'); + final rePri = getPriorityValues(r_ele, 're'); final readingDoesNotMatchKanji = r_ele .findElements('re_nokanji') .isNotEmpty; @@ -116,11 +116,11 @@ List parseJMDictData(XmlElement root) { .map((e) => e.innerText) .toList(), reading: r_ele.findElements('reb').first.innerText, - news: re_pri[0], - ichi: re_pri[1], - spec: re_pri[2], - gai: re_pri[3], - nf: re_pri[4], + news: rePri[0], + ichi: rePri[1], + spec: rePri[2], + gai: rePri[3], + nf: rePri[4], ), ); } diff --git a/lib/_data_ingestion/kanjidic/objects.dart b/lib/_data_ingestion/kanjidic/objects.dart index fba597a..cd7b462 100644 --- a/lib/_data_ingestion/kanjidic/objects.dart +++ b/lib/_data_ingestion/kanjidic/objects.dart @@ -245,6 +245,7 @@ class Character extends SQLWritable { this.nanori = const [], }); + @override Map get sqlValue => { 'literal': literal, 'grade': grade, diff --git a/lib/_data_ingestion/kanjidic/xml_parser.dart b/lib/_data_ingestion/kanjidic/xml_parser.dart index 4089e1c..b320791 100644 --- a/lib/_data_ingestion/kanjidic/xml_parser.dart +++ b/lib/_data_ingestion/kanjidic/xml_parser.dart @@ -10,9 +10,9 @@ List parseKANJIDICData(XmlElement root) { final codepoint = c.findElements('codepoint').firstOrNull; final radical = c.findElements('radical').firstOrNull; final misc = c.findElements('misc').first; - final dic_number = c.findElements('dic_number').firstOrNull; - final query_code = c.findElements('query_code').first; - final reading_meaning = c.findElements('reading_meaning').firstOrNull; + final dicNumber = c.findElements('dic_number').firstOrNull; + final queryCode = c.findElements('query_code').first; + final readingMeaning = c.findElements('reading_meaning').firstOrNull; // TODO: Group readings and meanings by their rmgroup parent node. @@ -70,7 +70,7 @@ List parseKANJIDICData(XmlElement root) { ) .toList(), dictionaryReferences: - dic_number + dicNumber ?.findElements('dic_ref') .where((e) => e.getAttribute('dr_type') != 'moro') .map( @@ -83,7 +83,7 @@ List parseKANJIDICData(XmlElement root) { .toList() ?? [], dictionaryReferencesMoro: - dic_number + dicNumber ?.findElements('dic_ref') .where((e) => e.getAttribute('dr_type') == 'moro') .map( @@ -96,7 +96,7 @@ List parseKANJIDICData(XmlElement root) { ) .toList() ?? [], - querycodes: query_code + querycodes: queryCode .findElements('q_code') .map( (e) => QueryCode( @@ -108,7 +108,7 @@ List parseKANJIDICData(XmlElement root) { ) .toList(), readings: - reading_meaning + readingMeaning ?.findAllElements('reading') .where( (e) => @@ -124,7 +124,7 @@ List parseKANJIDICData(XmlElement root) { .toList() ?? [], kunyomi: - reading_meaning + readingMeaning ?.findAllElements('reading') .where((e) => e.getAttribute('r_type') == 'ja_kun') .map( @@ -137,7 +137,7 @@ List parseKANJIDICData(XmlElement root) { .toList() ?? [], onyomi: - reading_meaning + readingMeaning ?.findAllElements('reading') .where((e) => e.getAttribute('r_type') == 'ja_on') .map( @@ -151,7 +151,7 @@ List parseKANJIDICData(XmlElement root) { .toList() ?? [], meanings: - reading_meaning + readingMeaning ?.findAllElements('meaning') .map( (e) => Meaning( @@ -163,7 +163,7 @@ List parseKANJIDICData(XmlElement root) { .toList() ?? [], nanori: - reading_meaning + readingMeaning ?.findElements('nanori') .map((e) => e.innerText) .toList() ?? diff --git a/lib/_data_ingestion/open_local_db.dart b/lib/_data_ingestion/open_local_db.dart index d29015e..0623b4a 100644 --- a/lib/_data_ingestion/open_local_db.dart +++ b/lib/_data_ingestion/open_local_db.dart @@ -22,15 +22,15 @@ Future openLocalDb({ jadbPath = File(jadbPath).resolveSymbolicLinksSync(); if (libsqlitePath == null) { - throw Exception("LIBSQLITE_PATH is not set"); + throw Exception('LIBSQLITE_PATH is not set'); } if (!File(libsqlitePath).existsSync()) { - throw Exception("LIBSQLITE_PATH does not exist: $libsqlitePath"); + throw Exception('LIBSQLITE_PATH does not exist: $libsqlitePath'); } if (!File(jadbPath).existsSync()) { - throw Exception("JADB_PATH does not exist: $jadbPath"); + throw Exception('JADB_PATH does not exist: $jadbPath'); } final db = @@ -42,9 +42,9 @@ Future openLocalDb({ options: OpenDatabaseOptions( onConfigure: (db) async { if (walMode) { - await db.execute("PRAGMA journal_mode = WAL"); + await db.execute('PRAGMA journal_mode = WAL'); } - await db.execute("PRAGMA foreign_keys = ON"); + await db.execute('PRAGMA foreign_keys = ON'); }, readOnly: !readWrite, ), diff --git a/lib/_data_ingestion/seed_database.dart b/lib/_data_ingestion/seed_database.dart index 0015d4f..1a67b09 100644 --- a/lib/_data_ingestion/seed_database.dart +++ b/lib/_data_ingestion/seed_database.dart @@ -24,10 +24,10 @@ Future seedData(Database db) async { Future parseAndSeedDataFromJMdict(Database db) async { print('[JMdict] Reading file content...'); - String rawXML = File('data/tmp/JMdict.xml').readAsStringSync(); + final String rawXML = File('data/tmp/JMdict.xml').readAsStringSync(); print('[JMdict] Parsing XML tags...'); - XmlElement root = XmlDocument.parse(rawXML).getElement('JMdict')!; + final XmlElement root = XmlDocument.parse(rawXML).getElement('JMdict')!; print('[JMdict] Parsing XML content...'); final entries = parseJMDictData(root); @@ -38,10 +38,10 @@ Future parseAndSeedDataFromJMdict(Database db) async { Future parseAndSeedDataFromKANJIDIC(Database db) async { print('[KANJIDIC2] Reading file...'); - String rawXML = File('data/tmp/kanjidic2.xml').readAsStringSync(); + final String rawXML = File('data/tmp/kanjidic2.xml').readAsStringSync(); print('[KANJIDIC2] Parsing XML...'); - XmlElement root = XmlDocument.parse(rawXML).getElement('kanjidic2')!; + final XmlElement root = XmlDocument.parse(rawXML).getElement('kanjidic2')!; print('[KANJIDIC2] Parsing XML content...'); final entries = parseKANJIDICData(root); @@ -52,7 +52,7 @@ Future parseAndSeedDataFromKANJIDIC(Database db) async { Future parseAndSeedDataFromRADKFILE(Database db) async { print('[RADKFILE] Reading file...'); - File raw = File('data/tmp/RADKFILE'); + final File raw = File('data/tmp/RADKFILE'); print('[RADKFILE] Parsing content...'); final blocks = parseRADKFILEBlocks(raw); @@ -63,7 +63,7 @@ Future parseAndSeedDataFromRADKFILE(Database db) async { Future parseAndSeedDataFromTanosJLPT(Database db) async { print('[TANOS-JLPT] Reading files...'); - Map files = { + final Map files = { 'N1': File('data/tanos-jlpt/n1.csv'), 'N2': File('data/tanos-jlpt/n2.csv'), 'N3': File('data/tanos-jlpt/n3.csv'), diff --git a/lib/_data_ingestion/tanos-jlpt/csv_parser.dart b/lib/_data_ingestion/tanos-jlpt/csv_parser.dart index 6228672..c0ab10a 100644 --- a/lib/_data_ingestion/tanos-jlpt/csv_parser.dart +++ b/lib/_data_ingestion/tanos-jlpt/csv_parser.dart @@ -14,7 +14,7 @@ Future> parseJLPTRankedWords( final file = entry.value; if (!file.existsSync()) { - throw Exception("File $jlptLevel does not exist"); + throw Exception('File $jlptLevel does not exist'); } final rows = await file @@ -25,7 +25,7 @@ Future> parseJLPTRankedWords( for (final row in rows) { if (row.length != 3) { - throw Exception("Invalid line in $jlptLevel: $row"); + throw Exception('Invalid line in $jlptLevel: $row'); } final kanji = (row[0] as String).isEmpty @@ -35,7 +35,7 @@ Future> parseJLPTRankedWords( .replaceAll(RegExp(r'(.*)'), ''); final readings = (row[1] as String) - .split(RegExp('[・/、(:?\s+)]')) + .split(RegExp('[・/、(:?s+)]')) .map((e) => e.trim()) .toList(); diff --git a/lib/_data_ingestion/tanos-jlpt/objects.dart b/lib/_data_ingestion/tanos-jlpt/objects.dart index 4deaac2..5829cf0 100644 --- a/lib/_data_ingestion/tanos-jlpt/objects.dart +++ b/lib/_data_ingestion/tanos-jlpt/objects.dart @@ -13,5 +13,5 @@ class JLPTRankedWord { @override String toString() => - '(${jlptLevel},${kanji},"${readings.join(",")}","${meanings.join(",")})'; + '($jlptLevel,$kanji,"${readings.join(",")}","${meanings.join(",")})'; } diff --git a/lib/_data_ingestion/tanos-jlpt/resolve.dart b/lib/_data_ingestion/tanos-jlpt/resolve.dart index 0fc723f..0b38170 100644 --- a/lib/_data_ingestion/tanos-jlpt/resolve.dart +++ b/lib/_data_ingestion/tanos-jlpt/resolve.dart @@ -1,6 +1,6 @@ -import 'package:jadb/table_names/jmdict.dart'; import 'package:jadb/_data_ingestion/tanos-jlpt/objects.dart'; import 'package:jadb/_data_ingestion/tanos-jlpt/overrides.dart'; +import 'package:jadb/table_names/jmdict.dart'; import 'package:sqflite_common/sqlite_api.dart'; Future> _findReadingCandidates(JLPTRankedWord word, Database db) => db @@ -84,7 +84,7 @@ Future findEntry( throw Exception( 'Multiple override entries found for ${word.toString()}: $entryIds', ); - } else if (overrideEntries.length == 0 && + } else if (overrideEntries.isEmpty && !word.readings.any( (reading) => TANOS_JLPT_OVERRIDES.containsKey((word.kanji, reading)), )) { diff --git a/lib/_data_ingestion/tanos-jlpt/seed_data.dart b/lib/_data_ingestion/tanos-jlpt/seed_data.dart index d928dcd..e38af22 100644 --- a/lib/_data_ingestion/tanos-jlpt/seed_data.dart +++ b/lib/_data_ingestion/tanos-jlpt/seed_data.dart @@ -5,7 +5,7 @@ Future seedTanosJLPTData( Map> resolvedEntries, Database db, ) async { - Batch b = db.batch(); + final Batch b = db.batch(); for (final jlptLevel in resolvedEntries.entries) { final level = jlptLevel.key; diff --git a/lib/cli/commands/create_db.dart b/lib/cli/commands/create_db.dart index 6fc0434..fde9a2a 100644 --- a/lib/cli/commands/create_db.dart +++ b/lib/cli/commands/create_db.dart @@ -1,14 +1,15 @@ import 'dart:io'; +import 'package:args/command_runner.dart'; import 'package:jadb/_data_ingestion/open_local_db.dart'; import 'package:jadb/_data_ingestion/seed_database.dart'; - -import 'package:args/command_runner.dart'; import 'package:jadb/cli/args.dart'; class CreateDb extends Command { - final name = "create-db"; - final description = "Create the database"; + @override + final name = 'create-db'; + @override + final description = 'Create the database'; CreateDb() { addLibsqliteArg(argParser); @@ -23,6 +24,7 @@ class CreateDb extends Command { ); } + @override Future run() async { if (argResults!.option('libsqlite') == null) { print(argParser.usage); @@ -38,10 +40,10 @@ class CreateDb extends Command { bool failed = false; await seedData(db) .then((_) { - print("Database created successfully"); + print('Database created successfully'); }) .catchError((error) { - print("Error creating database: $error"); + print('Error creating database: $error'); failed = true; }) .whenComplete(() { diff --git a/lib/cli/commands/create_tanos_jlpt_mappings.dart b/lib/cli/commands/create_tanos_jlpt_mappings.dart index 6ace3cb..99bee89 100644 --- a/lib/cli/commands/create_tanos_jlpt_mappings.dart +++ b/lib/cli/commands/create_tanos_jlpt_mappings.dart @@ -1,8 +1,7 @@ import 'dart:io'; -import 'package:jadb/_data_ingestion/open_local_db.dart'; - import 'package:args/command_runner.dart'; +import 'package:jadb/_data_ingestion/open_local_db.dart'; import 'package:jadb/_data_ingestion/tanos-jlpt/csv_parser.dart'; import 'package:jadb/_data_ingestion/tanos-jlpt/objects.dart'; import 'package:jadb/_data_ingestion/tanos-jlpt/resolve.dart'; @@ -10,9 +9,11 @@ import 'package:jadb/cli/args.dart'; import 'package:sqflite_common/sqlite_api.dart'; class CreateTanosJlptMappings extends Command { - final name = "create-tanos-jlpt-mappings"; + @override + final name = 'create-tanos-jlpt-mappings'; + @override final description = - "Resolve Tanos JLPT data against JMDict. This tool is useful to create overrides for ambiguous references"; + 'Resolve Tanos JLPT data against JMDict. This tool is useful to create overrides for ambiguous references'; CreateTanosJlptMappings() { addLibsqliteArg(argParser); @@ -26,6 +27,7 @@ class CreateTanosJlptMappings extends Command { ); } + @override Future run() async { if (argResults!.option('libsqlite') == null || argResults!.option('jadb') == null) { @@ -40,7 +42,7 @@ class CreateTanosJlptMappings extends Command { final useOverrides = argResults!.flag('overrides'); - Map files = { + final Map files = { 'N1': File('data/tanos-jlpt/n1.csv'), 'N2': File('data/tanos-jlpt/n2.csv'), 'N3': File('data/tanos-jlpt/n3.csv'), @@ -59,7 +61,7 @@ Future resolveExisting( Database db, bool useOverrides, ) async { - List missingWords = []; + final List missingWords = []; for (final (i, word) in rankedWords.indexed) { try { print( @@ -90,7 +92,7 @@ Future resolveExisting( .toStringAsFixed(2); print( - '${jlptLevel} failures: [${missingWordCount}/${totalWordCount}] (${failureRate}%)', + '$jlptLevel failures: [$missingWordCount/$totalWordCount] ($failureRate%)', ); } diff --git a/lib/cli/commands/lemmatize.dart b/lib/cli/commands/lemmatize.dart index 8586e4e..7177e94 100644 --- a/lib/cli/commands/lemmatize.dart +++ b/lib/cli/commands/lemmatize.dart @@ -1,14 +1,15 @@ // import 'dart:io'; +import 'package:args/command_runner.dart'; // import 'package:jadb/_data_ingestion/open_local_db.dart'; import 'package:jadb/cli/args.dart'; - -import 'package:args/command_runner.dart'; import 'package:jadb/util/lemmatizer/lemmatizer.dart'; class Lemmatize extends Command { - final name = "lemmatize"; - final description = "Lemmatize a word using the Jadb lemmatizer"; + @override + final name = 'lemmatize'; + @override + final description = 'Lemmatize a word using the Jadb lemmatizer'; Lemmatize() { addLibsqliteArg(argParser); @@ -21,6 +22,7 @@ class Lemmatize extends Command { ); } + @override Future run() async { // if (argResults!.option('libsqlite') == null || // argResults!.option('jadb') == null) { @@ -41,6 +43,6 @@ class Lemmatize extends Command { print(result.toString()); - print("Lemmatization took ${time.elapsedMilliseconds}ms"); + print('Lemmatization took ${time.elapsedMilliseconds}ms'); } } diff --git a/lib/cli/commands/query_kanji.dart b/lib/cli/commands/query_kanji.dart index a61589e..ee67d5d 100644 --- a/lib/cli/commands/query_kanji.dart +++ b/lib/cli/commands/query_kanji.dart @@ -1,22 +1,25 @@ import 'dart:convert'; import 'dart:io'; +import 'package:args/command_runner.dart'; import 'package:jadb/_data_ingestion/open_local_db.dart'; import 'package:jadb/cli/args.dart'; import 'package:jadb/search.dart'; -import 'package:args/command_runner.dart'; - class QueryKanji extends Command { - final name = "query-kanji"; - final description = "Query the database for kanji data"; - final invocation = "jadb query-kanji [options] "; + @override + final name = 'query-kanji'; + @override + final description = 'Query the database for kanji data'; + @override + final invocation = 'jadb query-kanji [options] '; QueryKanji() { addLibsqliteArg(argParser); addJadbArg(argParser); } + @override Future run() async { if (argResults!.option('libsqlite') == null || argResults!.option('jadb') == null) { @@ -43,11 +46,11 @@ class QueryKanji extends Command { time.stop(); if (result == null) { - print("No such kanji"); + print('No such kanji'); } else { print(JsonEncoder.withIndent(' ').convert(result.toJson())); } - print("Query took ${time.elapsedMilliseconds}ms"); + print('Query took ${time.elapsedMilliseconds}ms'); } } diff --git a/lib/cli/commands/query_word.dart b/lib/cli/commands/query_word.dart index 9b6b76f..dee46cf 100644 --- a/lib/cli/commands/query_word.dart +++ b/lib/cli/commands/query_word.dart @@ -1,17 +1,19 @@ import 'dart:convert'; import 'dart:io'; +import 'package:args/command_runner.dart'; import 'package:jadb/_data_ingestion/open_local_db.dart'; import 'package:jadb/cli/args.dart'; import 'package:jadb/search.dart'; - -import 'package:args/command_runner.dart'; import 'package:sqflite_common/sqflite.dart'; class QueryWord extends Command { - final name = "query-word"; - final description = "Query the database for word data"; - final invocation = "jadb query-word [options] ( | )"; + @override + final name = 'query-word'; + @override + final description = 'Query the database for word data'; + @override + final invocation = 'jadb query-word [options] ( | )'; QueryWord() { addLibsqliteArg(argParser); @@ -24,10 +26,11 @@ class QueryWord extends Command { argParser.addOption('pageSize', valueHelp: 'NUM', defaultsTo: '30'); } + @override Future run() async { if (argResults!.option('libsqlite') == null || argResults!.option('jadb') == null) { - print("You need to provide both libsqlite and jadb paths."); + print('You need to provide both libsqlite and jadb paths.'); print(''); printUsage(); exit(64); @@ -45,7 +48,7 @@ class QueryWord extends Command { exit(64); } - final String searchWord = argResults!.rest.join(" "); + final String searchWord = argResults!.rest.join(' '); final int? maybeId = int.tryParse(searchWord); if (maybeId != null && maybeId >= 1000000) { @@ -67,7 +70,7 @@ class QueryWord extends Command { time.stop(); if (result == null) { - print("Invalid ID"); + print('Invalid ID'); } else { if (jsonOutput) { print(JsonEncoder.withIndent(' ').convert(result)); @@ -76,7 +79,7 @@ class QueryWord extends Command { } } - print("Query took ${time.elapsedMilliseconds}ms"); + print('Query took ${time.elapsedMilliseconds}ms'); } Future _searchWord( @@ -97,22 +100,22 @@ class QueryWord extends Command { time2.stop(); if (result == null) { - print("Invalid search"); + print('Invalid search'); } else if (result.isEmpty) { - print("No matches"); + print('No matches'); } else { if (jsonOutput) { print(JsonEncoder.withIndent(' ').convert(result)); } else { for (final e in result) { print(e.toString()); - print(""); + print(''); } } } - print("Total count: ${count}"); - print("Count query took ${time.elapsedMilliseconds}ms"); - print("Query took ${time2.elapsedMilliseconds}ms"); + print('Total count: $count'); + print('Count query took ${time.elapsedMilliseconds}ms'); + print('Query took ${time2.elapsedMilliseconds}ms'); } } diff --git a/lib/models/common/jlpt_level.dart b/lib/models/common/jlpt_level.dart index 462c344..657ea9b 100644 --- a/lib/models/common/jlpt_level.dart +++ b/lib/models/common/jlpt_level.dart @@ -43,6 +43,7 @@ enum JlptLevel implements Comparable { int? get asInt => this == JlptLevel.none ? null : JlptLevel.values.indexOf(this); + @override String toString() => toNullableString() ?? 'N/A'; Object? toJson() => toNullableString(); diff --git a/lib/models/create_empty_db.dart b/lib/models/create_empty_db.dart index e3f80bd..c1a14f9 100644 --- a/lib/models/create_empty_db.dart +++ b/lib/models/create_empty_db.dart @@ -11,7 +11,7 @@ String migrationDirPath() { } Future createEmptyDb(DatabaseExecutor db) async { - List migrationFiles = []; + final List migrationFiles = []; for (final file in Directory(migrationDirPath()).listSync()) { if (file is File && file.path.endsWith('.sql')) { migrationFiles.add(file.path); diff --git a/lib/models/kanji_search/kanji_search_radical.dart b/lib/models/kanji_search/kanji_search_radical.dart index 3c52088..31b4268 100644 --- a/lib/models/kanji_search/kanji_search_radical.dart +++ b/lib/models/kanji_search/kanji_search_radical.dart @@ -26,7 +26,7 @@ class KanjiSearchRadical extends Equatable { }); @override - List get props => [symbol, this.names, forms, meanings]; + List get props => [symbol, names, forms, meanings]; Map toJson() => { 'symbol': symbol, diff --git a/lib/models/word_search/word_search_result.dart b/lib/models/word_search/word_search_result.dart index 5195c3c..7870964 100644 --- a/lib/models/word_search/word_search_result.dart +++ b/lib/models/word_search/word_search_result.dart @@ -82,16 +82,16 @@ class WordSearchResult { ); String _formatJapaneseWord(WordSearchRuby word) => - word.furigana == null ? word.base : "${word.base} (${word.furigana})"; + word.furigana == null ? word.base : '${word.base} (${word.furigana})'; @override String toString() { final japaneseWord = _formatJapaneseWord(japanese[0]); final isCommonString = isCommon ? '(C)' : ''; - final jlptLevelString = "(${jlptLevel.toString()})"; + final jlptLevelString = '(${jlptLevel.toString()})'; return ''' -${score} | [$entryId] $japaneseWord $isCommonString $jlptLevelString +$score | [$entryId] $japaneseWord $isCommonString $jlptLevelString Other forms: ${japanese.skip(1).map(_formatJapaneseWord).join(', ')} Senses: ${senses.map((s) => s.englishDefinitions).join(', ')} ''' diff --git a/lib/search.dart b/lib/search.dart index fdd8cf6..d06f5ab 100644 --- a/lib/search.dart +++ b/lib/search.dart @@ -1,12 +1,10 @@ +import 'package:jadb/models/kanji_search/kanji_search_result.dart'; import 'package:jadb/models/verify_tables.dart'; import 'package:jadb/models/word_search/word_search_result.dart'; -import 'package:jadb/models/kanji_search/kanji_search_result.dart'; import 'package:jadb/search/filter_kanji.dart'; +import 'package:jadb/search/kanji_search.dart'; import 'package:jadb/search/radical_search.dart'; import 'package:jadb/search/word_search/word_search.dart'; - -import 'package:jadb/search/kanji_search.dart'; - import 'package:sqflite_common/sqlite_api.dart'; extension JaDBConnection on DatabaseExecutor { diff --git a/lib/search/kanji_search.dart b/lib/search/kanji_search.dart index 5bca054..2482838 100644 --- a/lib/search/kanji_search.dart +++ b/lib/search/kanji_search.dart @@ -1,8 +1,8 @@ import 'package:collection/collection.dart'; -import 'package:jadb/table_names/kanjidic.dart'; -import 'package:jadb/table_names/radkfile.dart'; import 'package:jadb/models/kanji_search/kanji_search_radical.dart'; import 'package:jadb/models/kanji_search/kanji_search_result.dart'; +import 'package:jadb/table_names/kanjidic.dart'; +import 'package:jadb/table_names/radkfile.dart'; import 'package:jadb/util/romaji_transliteration.dart'; import 'package:sqflite_common/sqflite.dart'; @@ -11,66 +11,66 @@ Future searchKanjiWithDbConnection( String kanji, ) async { late final List> characters; - final characters_query = connection.query( + final charactersQuery = connection.query( KANJIDICTableNames.character, - where: "literal = ?", + where: 'literal = ?', whereArgs: [kanji], ); late final List> codepoints; - final codepoints_query = connection.query( + final codepointsQuery = connection.query( KANJIDICTableNames.codepoint, - where: "kanji = ?", + where: 'kanji = ?', whereArgs: [kanji], ); late final List> kunyomis; - final kunyomis_query = connection.query( + final kunyomisQuery = connection.query( KANJIDICTableNames.kunyomi, - where: "kanji = ?", + where: 'kanji = ?', whereArgs: [kanji], - orderBy: "orderNum", + orderBy: 'orderNum', ); late final List> onyomis; - final onyomis_query = connection.query( + final onyomisQuery = connection.query( KANJIDICTableNames.onyomi, - where: "kanji = ?", + where: 'kanji = ?', whereArgs: [kanji], - orderBy: "orderNum", + orderBy: 'orderNum', ); late final List> meanings; - final meanings_query = connection.query( + final meaningsQuery = connection.query( KANJIDICTableNames.meaning, - where: "kanji = ? AND language = ?", + where: 'kanji = ? AND language = ?', whereArgs: [kanji, 'eng'], - orderBy: "orderNum", + orderBy: 'orderNum', ); late final List> nanoris; - final nanoris_query = connection.query( + final nanorisQuery = connection.query( KANJIDICTableNames.nanori, - where: "kanji = ?", + where: 'kanji = ?', whereArgs: [kanji], ); - late final List> dictionary_references; - final dictionary_references_query = connection.query( + late final List> dictionaryReferences; + final dictionaryReferencesQuery = connection.query( KANJIDICTableNames.dictionaryReference, - where: "kanji = ?", + where: 'kanji = ?', whereArgs: [kanji], ); - late final List> query_codes; - final query_codes_query = connection.query( + late final List> queryCodes; + final queryCodesQuery = connection.query( KANJIDICTableNames.queryCode, - where: "kanji = ?", + where: 'kanji = ?', whereArgs: [kanji], ); late final List> radicals; - final radicals_query = connection.rawQuery( + final radicalsQuery = connection.rawQuery( ''' SELECT DISTINCT "XREF__KANJIDIC_Radical__RADKFILE"."radicalSymbol" AS "symbol", @@ -88,23 +88,23 @@ Future searchKanjiWithDbConnection( ); late final List> parts; - final parts_query = connection.query( + final partsQuery = connection.query( RADKFILETableNames.radkfile, - where: "kanji = ?", + where: 'kanji = ?', whereArgs: [kanji], ); late final List> readings; - final readings_query = connection.query( + final readingsQuery = connection.query( KANJIDICTableNames.reading, - where: "kanji = ?", + where: 'kanji = ?', whereArgs: [kanji], ); - late final List> stroke_miscounts; - final stroke_miscounts_query = connection.query( + late final List> strokeMiscounts; + final strokeMiscountsQuery = connection.query( KANJIDICTableNames.strokeMiscount, - where: "kanji = ?", + where: 'kanji = ?', whereArgs: [kanji], ); @@ -121,24 +121,24 @@ Future searchKanjiWithDbConnection( // filter JMdict_ReadingElement for kunyomi/onyomi, and then sort the main entry // by JLPT, news frequency, etc. - await characters_query.then((value) => characters = value); + await charactersQuery.then((value) => characters = value); if (characters.isEmpty) { return null; } await Future.wait({ - codepoints_query.then((value) => codepoints = value), - kunyomis_query.then((value) => kunyomis = value), - onyomis_query.then((value) => onyomis = value), - meanings_query.then((value) => meanings = value), - nanoris_query.then((value) => nanoris = value), - dictionary_references_query.then((value) => dictionary_references = value), - query_codes_query.then((value) => query_codes = value), - radicals_query.then((value) => radicals = value), - parts_query.then((value) => parts = value), - readings_query.then((value) => readings = value), - stroke_miscounts_query.then((value) => stroke_miscounts = value), + codepointsQuery.then((value) => codepoints = value), + kunyomisQuery.then((value) => kunyomis = value), + onyomisQuery.then((value) => onyomis = value), + meaningsQuery.then((value) => meanings = value), + nanorisQuery.then((value) => nanoris = value), + dictionaryReferencesQuery.then((value) => dictionaryReferences = value), + queryCodesQuery.then((value) => queryCodes = value), + radicalsQuery.then((value) => radicals = value), + partsQuery.then((value) => parts = value), + readingsQuery.then((value) => readings = value), + strokeMiscountsQuery.then((value) => strokeMiscounts = value), // variants_query.then((value) => variants = value), }); @@ -166,7 +166,7 @@ Future searchKanjiWithDbConnection( ); // TODO: Add `SKIPMisclassification` to the entries - final queryCodes = query_codes + final queryCodes_ = queryCodes .groupListsBy((item) => item['type'] as String) .map( (key, value) => @@ -174,8 +174,8 @@ Future searchKanjiWithDbConnection( ); // TODO: Add `volume` and `page` to the entries - final dictionaryReferences = { - for (final entry in dictionary_references) + final dictionaryReferences_ = { + for (final entry in dictionaryReferences) entry['type'] as String: entry['ref'] as String, }; @@ -207,11 +207,11 @@ Future searchKanjiWithDbConnection( }, nanori: nanoris.map((item) => item['nanori'] as String).toList(), alternativeLanguageReadings: alternativeLanguageReadings, - strokeMiscounts: stroke_miscounts + strokeMiscounts: strokeMiscounts .map((item) => item['strokeCount'] as int) .toList(), - queryCodes: queryCodes, - dictionaryReferences: dictionaryReferences, + queryCodes: queryCodes_, + dictionaryReferences: dictionaryReferences_, ); } diff --git a/lib/search/word_search/data_query.dart b/lib/search/word_search/data_query.dart index 6161a70..baa392e 100644 --- a/lib/search/word_search/data_query.dart +++ b/lib/search/word_search/data_query.dart @@ -59,14 +59,14 @@ Future fetchLinearWordQueryData( bool fetchXrefData = true, }) async { late final List> senses; - final Future>> senses_query = connection.query( + final Future>> sensesQuery = connection.query( JMdictTableNames.sense, where: 'entryId IN (${List.filled(entryIds.length, '?').join(',')})', whereArgs: entryIds, ); late final List> readingElements; - final Future>> readingElements_query = connection + final Future>> readingelementsQuery = connection .query( JMdictTableNames.readingElement, where: 'entryId IN (${List.filled(entryIds.length, '?').join(',')})', @@ -75,7 +75,7 @@ Future fetchLinearWordQueryData( ); late final List> kanjiElements; - final Future>> kanjiElements_query = connection + final Future>> kanjielementsQuery = connection .query( JMdictTableNames.kanjiElement, where: 'entryId IN (${List.filled(entryIds.length, '?').join(',')})', @@ -84,14 +84,14 @@ Future fetchLinearWordQueryData( ); late final List> jlptTags; - final Future>> jlptTags_query = connection.query( + final Future>> jlpttagsQuery = connection.query( TanosJLPTTableNames.jlptTag, where: 'entryId IN (${List.filled(entryIds.length, '?').join(',')})', whereArgs: entryIds, ); late final List> commonEntries; - final Future>> commonEntries_query = connection + final Future>> commonentriesQuery = connection .query( 'JMdict_EntryCommon', where: 'entryId IN (${List.filled(entryIds.length, '?').join(',')})', @@ -99,11 +99,11 @@ Future fetchLinearWordQueryData( ); await Future.wait([ - senses_query.then((value) => senses = value), - readingElements_query.then((value) => readingElements = value), - kanjiElements_query.then((value) => kanjiElements = value), - jlptTags_query.then((value) => jlptTags = value), - commonEntries_query.then((value) => commonEntries = value), + sensesQuery.then((value) => senses = value), + readingelementsQuery.then((value) => readingElements = value), + kanjielementsQuery.then((value) => kanjiElements = value), + jlpttagsQuery.then((value) => jlptTags = value), + commonentriesQuery.then((value) => commonEntries = value), ]); // Sense queries @@ -111,7 +111,7 @@ Future fetchLinearWordQueryData( final senseIds = senses.map((sense) => sense['senseId'] as int).toList(); late final List> senseAntonyms; - final Future>> senseAntonyms_query = connection + final Future>> senseantonymsQuery = connection .rawQuery( """ SELECT @@ -134,7 +134,7 @@ Future fetchLinearWordQueryData( ); late final List> senseDialects; - final Future>> senseDialects_query = connection + final Future>> sensedialectsQuery = connection .query( JMdictTableNames.senseDialect, where: 'senseId IN (${List.filled(senseIds.length, '?').join(',')})', @@ -142,14 +142,14 @@ Future fetchLinearWordQueryData( ); late final List> senseFields; - final Future>> senseFields_query = connection.query( + final Future>> sensefieldsQuery = connection.query( JMdictTableNames.senseField, where: 'senseId IN (${List.filled(senseIds.length, '?').join(',')})', whereArgs: senseIds, ); late final List> senseGlossaries; - final Future>> senseGlossaries_query = connection + final Future>> senseglossariesQuery = connection .query( JMdictTableNames.senseGlossary, where: 'senseId IN (${List.filled(senseIds.length, '?').join(',')})', @@ -157,14 +157,14 @@ Future fetchLinearWordQueryData( ); late final List> senseInfos; - final Future>> senseInfos_query = connection.query( + final Future>> senseinfosQuery = connection.query( JMdictTableNames.senseInfo, where: 'senseId IN (${List.filled(senseIds.length, '?').join(',')})', whereArgs: senseIds, ); late final List> senseLanguageSources; - final Future>> senseLanguageSources_query = + final Future>> senselanguagesourcesQuery = connection.query( JMdictTableNames.senseLanguageSource, where: 'senseId IN (${List.filled(senseIds.length, '?').join(',')})', @@ -172,21 +172,21 @@ Future fetchLinearWordQueryData( ); late final List> senseMiscs; - final Future>> senseMiscs_query = connection.query( + final Future>> sensemiscsQuery = connection.query( JMdictTableNames.senseMisc, where: 'senseId IN (${List.filled(senseIds.length, '?').join(',')})', whereArgs: senseIds, ); late final List> sensePOSs; - final Future>> sensePOSs_query = connection.query( + final Future>> sensepossQuery = connection.query( JMdictTableNames.sensePOS, where: 'senseId IN (${List.filled(senseIds.length, '?').join(',')})', whereArgs: senseIds, ); late final List> senseRestrictedToKanjis; - final Future>> senseRestrictedToKanjis_query = + final Future>> senserestrictedtokanjisQuery = connection.query( JMdictTableNames.senseRestrictedToKanji, where: 'senseId IN (${List.filled(senseIds.length, '?').join(',')})', @@ -194,7 +194,7 @@ Future fetchLinearWordQueryData( ); late final List> senseRestrictedToReadings; - final Future>> senseRestrictedToReadings_query = + final Future>> senserestrictedtoreadingsQuery = connection.query( JMdictTableNames.senseRestrictedToReading, where: 'senseId IN (${List.filled(senseIds.length, '?').join(',')})', @@ -202,7 +202,7 @@ Future fetchLinearWordQueryData( ); late final List> senseSeeAlsos; - final Future>> senseSeeAlsos_query = connection + final Future>> senseseealsosQuery = connection .rawQuery( """ SELECT @@ -225,7 +225,7 @@ Future fetchLinearWordQueryData( ); late final List> exampleSentences; - final Future>> exampleSentences_query = connection + final Future>> examplesentencesQuery = connection .query( 'JMdict_ExampleSentence', where: 'senseId IN (${List.filled(senseIds.length, '?').join(',')})', @@ -239,7 +239,7 @@ Future fetchLinearWordQueryData( .toList(); late final List> readingElementInfos; - final Future>> readingElementInfos_query = + final Future>> readingelementinfosQuery = connection.query( JMdictTableNames.readingInfo, where: @@ -248,7 +248,7 @@ Future fetchLinearWordQueryData( ); late final List> readingElementRestrictions; - final Future>> readingElementRestrictions_query = + final Future>> readingelementrestrictionsQuery = connection.query( JMdictTableNames.readingRestriction, where: @@ -263,7 +263,7 @@ Future fetchLinearWordQueryData( .toList(); late final List> kanjiElementInfos; - final Future>> kanjiElementInfos_query = connection + final Future>> kanjielementinfosQuery = connection .query( JMdictTableNames.kanjiInfo, where: @@ -273,12 +273,12 @@ Future fetchLinearWordQueryData( // Xref data queries await Future.wait([ - senseAntonyms_query.then((value) => senseAntonyms = value), - senseSeeAlsos_query.then((value) => senseSeeAlsos = value), + senseantonymsQuery.then((value) => senseAntonyms = value), + senseseealsosQuery.then((value) => senseSeeAlsos = value), ]); late final LinearWordQueryData? senseAntonymData; - final Future senseAntonymData_query = + final Future senseantonymdataQuery = fetchXrefData ? fetchLinearWordQueryData( connection, @@ -290,7 +290,7 @@ Future fetchLinearWordQueryData( : Future.value(null); late final LinearWordQueryData? senseSeeAlsoData; - final Future senseSeeAlsoData_query = + final Future senseseealsodataQuery = fetchXrefData ? fetchLinearWordQueryData( connection, @@ -300,27 +300,27 @@ Future fetchLinearWordQueryData( : Future.value(null); await Future.wait([ - senseDialects_query.then((value) => senseDialects = value), - senseFields_query.then((value) => senseFields = value), - senseGlossaries_query.then((value) => senseGlossaries = value), - senseInfos_query.then((value) => senseInfos = value), - senseLanguageSources_query.then((value) => senseLanguageSources = value), - senseMiscs_query.then((value) => senseMiscs = value), - sensePOSs_query.then((value) => sensePOSs = value), - senseRestrictedToKanjis_query.then( + sensedialectsQuery.then((value) => senseDialects = value), + sensefieldsQuery.then((value) => senseFields = value), + senseglossariesQuery.then((value) => senseGlossaries = value), + senseinfosQuery.then((value) => senseInfos = value), + senselanguagesourcesQuery.then((value) => senseLanguageSources = value), + sensemiscsQuery.then((value) => senseMiscs = value), + sensepossQuery.then((value) => sensePOSs = value), + senserestrictedtokanjisQuery.then( (value) => senseRestrictedToKanjis = value, ), - senseRestrictedToReadings_query.then( + senserestrictedtoreadingsQuery.then( (value) => senseRestrictedToReadings = value, ), - exampleSentences_query.then((value) => exampleSentences = value), - readingElementInfos_query.then((value) => readingElementInfos = value), - readingElementRestrictions_query.then( + examplesentencesQuery.then((value) => exampleSentences = value), + readingelementinfosQuery.then((value) => readingElementInfos = value), + readingelementrestrictionsQuery.then( (value) => readingElementRestrictions = value, ), - kanjiElementInfos_query.then((value) => kanjiElementInfos = value), - senseAntonymData_query.then((value) => senseAntonymData = value), - senseSeeAlsoData_query.then((value) => senseSeeAlsoData = value), + kanjielementinfosQuery.then((value) => kanjiElementInfos = value), + senseantonymdataQuery.then((value) => senseAntonymData = value), + senseseealsodataQuery.then((value) => senseSeeAlsoData = value), ]); return LinearWordQueryData( diff --git a/lib/search/word_search/entry_id_query.dart b/lib/search/word_search/entry_id_query.dart index cbbd78c..b96ea65 100644 --- a/lib/search/word_search/entry_id_query.dart +++ b/lib/search/word_search/entry_id_query.dart @@ -1,5 +1,5 @@ -import 'package:jadb/table_names/jmdict.dart'; import 'package:jadb/search/word_search/word_search.dart'; +import 'package:jadb/table_names/jmdict.dart'; import 'package:jadb/util/text_filtering.dart'; import 'package:sqflite_common/sqlite_api.dart'; @@ -37,7 +37,7 @@ String _filterFTSSensitiveCharacters(String word) { .replaceAll('(', '') .replaceAll(')', '') .replaceAll('^', '') - .replaceAll('\"', ''); + .replaceAll('"', ''); } (String, List) _kanjiReadingTemplate( @@ -65,27 +65,27 @@ String _filterFTSSensitiveCharacters(String word) { WITH fts_results AS ( SELECT DISTINCT - "${tableName}"."entryId", + "$tableName"."entryId", 100 + (("${tableName}FTS"."reading" = ?) * 10000) + "JMdict_EntryScore"."score" AS "score" FROM "${tableName}FTS" - JOIN "${tableName}" USING ("elementId") + JOIN "$tableName" USING ("elementId") JOIN "JMdict_EntryScore" USING ("elementId") WHERE "${tableName}FTS"."reading" MATCH ? || '*' AND "JMdict_EntryScore"."type" = '${tableName == JMdictTableNames.kanjiElement ? 'k' : 'r'}' ), non_fts_results AS ( SELECT DISTINCT - "${tableName}"."entryId", + "$tableName"."entryId", 50 + "JMdict_EntryScore"."score" AS "score" - FROM "${tableName}" + FROM "$tableName" JOIN "JMdict_EntryScore" USING ("elementId") WHERE "reading" LIKE '%' || ? || '%' - AND "${tableName}"."entryId" NOT IN (SELECT "entryId" FROM "fts_results") + AND "$tableName"."entryId" NOT IN (SELECT "entryId" FROM "fts_results") AND "JMdict_EntryScore"."type" = '${tableName == JMdictTableNames.kanjiElement ? 'k' : 'r'}' ) @@ -105,8 +105,8 @@ String _filterFTSSensitiveCharacters(String word) { _filterFTSSensitiveCharacters(word), _filterFTSSensitiveCharacters(word), _filterFTSSensitiveCharacters(word), - if (pageSize != null) pageSize, - if (offset != null) offset, + ?pageSize, + ?offset, ], ); } @@ -271,7 +271,6 @@ Future> fetchEntryIds( default: throw UnimplementedError('Search mode $searchMode is not implemented'); } - ; return entryIds; } diff --git a/lib/util/datetime_extensions.dart b/lib/util/datetime_extensions.dart index ba52464..059b783 100644 --- a/lib/util/datetime_extensions.dart +++ b/lib/util/datetime_extensions.dart @@ -276,14 +276,14 @@ extension on DateTime { /// See more info here: /// - https://en.wikipedia.org/wiki/Nanboku-ch%C5%8D_period /// - http://www.kumamotokokufu-h.ed.jp/kumamoto/bungaku/nengoui.html - String? japaneseEra({bool nanbokuchouPeriodUsesNorth = true}) { + String? japaneseEra() { throw UnimplementedError('This function is not implemented yet.'); - if (this.year < 645) { + if (year < 645) { return null; } - if (this.year < periodsNanbokuchouNorth.keys.first.$1) { + if (year < periodsNanbokuchouNorth.keys.first.$1) { // TODO: find first where year <= this.year and jump one period back. } } @@ -293,5 +293,5 @@ extension on DateTime { /// Returns the date in Japanese format. String japaneseDate({bool showWeekday = false}) => - '$month月$day日' + (showWeekday ? '($japaneseWeekdayPrefix)' : ''); + '$month月$day日${showWeekday ? '($japaneseWeekdayPrefix)' : ''}'; } diff --git a/lib/util/lemmatizer/lemmatizer.dart b/lib/util/lemmatizer/lemmatizer.dart index 29f4775..7e68d90 100644 --- a/lib/util/lemmatizer/lemmatizer.dart +++ b/lib/util/lemmatizer/lemmatizer.dart @@ -183,7 +183,7 @@ class Lemmatized { @override String toString() { final childrenString = children - .map((c) => ' - ' + c.toString().split('\n').join('\n ')) + .map((c) => ' - ${c.toString().split('\n').join('\n ')}') .join('\n'); if (children.isEmpty) { diff --git a/lib/util/romaji_transliteration.dart b/lib/util/romaji_transliteration.dart index d6f3b54..e3a5984 100644 --- a/lib/util/romaji_transliteration.dart +++ b/lib/util/romaji_transliteration.dart @@ -481,9 +481,9 @@ const Map latin_to_hiragana = { '#~': '〜', }; -bool _smallTsu(String for_conversion) => for_conversion == hiragana_small_tsu; -bool _nFollowedByYuYeYo(String for_conversion, String kana) => - for_conversion == hiragana_syllabic_n && +bool _smallTsu(String forConversion) => forConversion == hiragana_small_tsu; +bool _nFollowedByYuYeYo(String forConversion, String kana) => + forConversion == hiragana_syllabic_n && kana.length > 1 && 'やゆよ'.contains(kana.substring(1, 2)); @@ -495,17 +495,17 @@ String transliterateHiraganaToLatin(String hiragana) { while (kana.isNotEmpty) { final lengths = [if (kana.length > 1) 2, 1]; for (final length in lengths) { - final String for_conversion = kana.substring(0, length); + final String forConversion = kana.substring(0, length); String? mora; - if (_smallTsu(for_conversion)) { + if (_smallTsu(forConversion)) { geminate = true; kana = kana.replaceRange(0, length, ''); break; - } else if (_nFollowedByYuYeYo(for_conversion, kana)) { + } else if (_nFollowedByYuYeYo(forConversion, kana)) { mora = "n'"; } - mora ??= hiragana_to_latin[for_conversion]; + mora ??= hiragana_to_latin[forConversion]; if (mora != null) { if (geminate) { @@ -516,7 +516,7 @@ String transliterateHiraganaToLatin(String hiragana) { kana = kana.replaceRange(0, length, ''); break; } else if (length == 1) { - romaji += for_conversion; + romaji += forConversion; kana = kana.replaceRange(0, length, ''); } } @@ -524,14 +524,14 @@ String transliterateHiraganaToLatin(String hiragana) { return romaji; } -bool _doubleNFollowedByAIUEO(String for_conversion) => - RegExp(r'^nn[aiueo]$').hasMatch(for_conversion); -bool _hasTableMatch(String for_conversion) => - latin_to_hiragana[for_conversion] != null; -bool _hasDoubleConsonant(String for_conversion, int length) => - for_conversion == 'tch' || +bool _doubleNFollowedByAIUEO(String forConversion) => + RegExp(r'^nn[aiueo]$').hasMatch(forConversion); +bool _hasTableMatch(String forConversion) => + latin_to_hiragana[forConversion] != null; +bool _hasDoubleConsonant(String forConversion, int length) => + forConversion == 'tch' || (length == 2 && - RegExp(r'^([kgsztdnbpmyrlwchf])\1$').hasMatch(for_conversion)); + RegExp(r'^([kgsztdnbpmyrlwchf])\1$').hasMatch(forConversion)); String transliterateLatinToHiragana(String latin) { String romaji = latin @@ -545,25 +545,25 @@ String transliterateLatinToHiragana(String latin) { for (final length in lengths) { String? mora; - int for_removal = length; - final String for_conversion = romaji.substring(0, length); + int forRemoval = length; + final String forConversion = romaji.substring(0, length); - if (_doubleNFollowedByAIUEO(for_conversion)) { + if (_doubleNFollowedByAIUEO(forConversion)) { mora = hiragana_syllabic_n; - for_removal = 1; - } else if (_hasTableMatch(for_conversion)) { - mora = latin_to_hiragana[for_conversion]; - } else if (_hasDoubleConsonant(for_conversion, length)) { + forRemoval = 1; + } else if (_hasTableMatch(forConversion)) { + mora = latin_to_hiragana[forConversion]; + } else if (_hasDoubleConsonant(forConversion, length)) { mora = hiragana_small_tsu; - for_removal = 1; + forRemoval = 1; } if (mora != null) { kana += mora; - romaji = romaji.replaceRange(0, for_removal, ''); + romaji = romaji.replaceRange(0, forRemoval, ''); break; } else if (length == 1) { - kana += for_conversion; + kana += forConversion; romaji = romaji.replaceRange(0, 1, ''); } } diff --git a/lib/util/sqlite_utils.dart b/lib/util/sqlite_utils.dart index 08ad633..9e17937 100644 --- a/lib/util/sqlite_utils.dart +++ b/lib/util/sqlite_utils.dart @@ -1,3 +1,3 @@ String escapeStringValue(String value) { - return "'" + value.replaceAll("'", "''") + "'"; + return "'${value.replaceAll("'", "''")}'"; } diff --git a/pubspec.lock b/pubspec.lock index 46faf49..e29f1a0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: analyzer - sha256: "754aed101003afceca3e6637fe88150dbe9739068e0135788a62645a131867bb" + sha256: b1ade5707ab7a90dfd519eaac78a7184341d19adb6096c68d499b59c7c6cf880 url: "https://pub.dev" source: hosted - version: "7.5.9" + version: "7.7.0" args: dependency: "direct main" description: @@ -218,7 +218,7 @@ packages: source: hosted version: "2.2.0" path: - dependency: transitive + dependency: "direct main" description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" @@ -322,13 +322,13 @@ packages: source: hosted version: "2.3.6" sqlite3: - dependency: transitive + dependency: "direct main" description: name: sqlite3 - sha256: c0503c69b44d5714e6abbf4c1f51a3c3cc42b75ce785f44404765e4635481d38 + sha256: "608b56d594e4c8498c972c8f1507209f9fd74939971b948ddbbfbfd1c9cb3c15" url: "https://pub.dev" source: hosted - version: "2.7.6" + version: "2.7.7" stack_trace: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f4e0212..f123702 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -11,8 +11,10 @@ dependencies: collection: ^1.19.0 csv: ^6.0.0 equatable: ^2.0.0 + path: ^1.9.1 sqflite_common: ^2.5.0 sqflite_common_ffi: ^2.3.0 + sqlite3: ^2.7.7 xml: ^6.5.0 dev_dependencies: diff --git a/test/jouyou_kanji_test.dart b/test/jouyou_kanji_test.dart index b1bdce4..f7713d3 100644 --- a/test/jouyou_kanji_test.dart +++ b/test/jouyou_kanji_test.dart @@ -3,7 +3,7 @@ import 'package:jadb/const_data/kanji_grades.dart'; import 'package:test/test.dart'; void main() { - test("Assert 2136 kanji in jouyou set", () { + test('Assert 2136 kanji in jouyou set', () { expect(JOUYOU_KANJI_BY_GRADES.values.flattenedToSet.length, 2136); }); } diff --git a/test/models/create_empty_db_test.dart b/test/models/create_empty_db_test.dart index 9ced632..516fad2 100644 --- a/test/models/create_empty_db_test.dart +++ b/test/models/create_empty_db_test.dart @@ -4,26 +4,26 @@ import 'dart:io'; import 'package:jadb/models/create_empty_db.dart'; import 'package:jadb/search.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; -import 'package:test/test.dart'; import 'package:sqlite3/open.dart'; +import 'package:test/test.dart'; Future setup_inmemory_database() async { final libsqlitePath = Platform.environment['LIBSQLITE_PATH']; if (libsqlitePath == null) { - throw Exception("LIBSQLITE_PATH is not set"); + throw Exception('LIBSQLITE_PATH is not set'); } - final db_connection = await createDatabaseFactoryFfi( + final dbConnection = await createDatabaseFactoryFfi( ffiInit: () => open.overrideForAll(() => DynamicLibrary.open(libsqlitePath)), ).openDatabase(':memory:'); - return db_connection; + return dbConnection; } void main() { - test("Create empty db", () async { + test('Create empty db', () async { final db = await setup_inmemory_database(); await createEmptyDb(db); diff --git a/test/search/filter_kanji_test.dart b/test/search/filter_kanji_test.dart index 713f6fe..c985a20 100644 --- a/test/search/filter_kanji_test.dart +++ b/test/search/filter_kanji_test.dart @@ -4,26 +4,26 @@ import 'package:test/test.dart'; import 'setup_database_connection.dart'; void main() { - test("Filter kanji", () async { + test('Filter kanji', () async { final connection = await setup_database_connection(); final result = await connection.filterKanji([ - "a", - "b", - "c", - "漢", - "字", - "地", - "字", - "か", - "な", - ".", - "!", - "@", - ";", - "々", + 'a', + 'b', + 'c', + '漢', + '字', + '地', + '字', + 'か', + 'な', + '.', + '!', + '@', + ';', + '々', ], deduplicate: false); - expect(result.join(), "漢字地字"); + expect(result.join(), '漢字地字'); }); } diff --git a/test/search/kanji_search_test.dart b/test/search/kanji_search_test.dart index 86284d3..0e3f445 100644 --- a/test/search/kanji_search_test.dart +++ b/test/search/kanji_search_test.dart @@ -5,16 +5,16 @@ import 'package:test/test.dart'; import 'setup_database_connection.dart'; void main() { - test("Search a kanji", () async { + test('Search a kanji', () async { final connection = await setup_database_connection(); final result = await connection.jadbSearchKanji('漢'); expect(result, isNotNull); }); - group("Search all jouyou kanji", () { + group('Search all jouyou kanji', () { JOUYOU_KANJI_BY_GRADES.forEach((grade, characters) { - test("Search all kanji in grade $grade", () async { + test('Search all kanji in grade $grade', () async { final connection = await setup_database_connection(); for (final character in characters) { diff --git a/test/search/setup_database_connection.dart b/test/search/setup_database_connection.dart index 9f8d077..a7fe8b4 100644 --- a/test/search/setup_database_connection.dart +++ b/test/search/setup_database_connection.dart @@ -4,21 +4,21 @@ import 'package:jadb/_data_ingestion/open_local_db.dart'; import 'package:sqflite_common/sqlite_api.dart'; Future setup_database_connection() async { - final lib_sqlite_path = Platform.environment['LIBSQLITE_PATH']; - final jadb_path = Platform.environment['JADB_PATH']; + final libSqlitePath = Platform.environment['LIBSQLITE_PATH']; + final jadbPath = Platform.environment['JADB_PATH']; - if (lib_sqlite_path == null) { - throw Exception("LIBSQLITE_PATH is not set"); + if (libSqlitePath == null) { + throw Exception('LIBSQLITE_PATH is not set'); } - if (jadb_path == null) { - throw Exception("JADB_PATH is not set"); + if (jadbPath == null) { + throw Exception('JADB_PATH is not set'); } - final db_connection = await openLocalDb( - libsqlitePath: lib_sqlite_path, - jadbPath: jadb_path, + final dbConnection = await openLocalDb( + libsqlitePath: libSqlitePath, + jadbPath: jadbPath, ); - return db_connection; + return dbConnection; } diff --git a/test/search/word_search_test.dart b/test/search/word_search_test.dart index 5179335..287d5fd 100644 --- a/test/search/word_search_test.dart +++ b/test/search/word_search_test.dart @@ -4,59 +4,59 @@ import 'package:test/test.dart'; import 'setup_database_connection.dart'; void main() { - test("Search a word - english - auto", () async { + test('Search a word - english - auto', () async { final connection = await setup_database_connection(); - final result = await connection.jadbSearchWord("kana"); + final result = await connection.jadbSearchWord('kana'); expect(result, isNotNull); }); - test("Get word search count - english - auto", () async { + test('Get word search count - english - auto', () async { final connection = await setup_database_connection(); - final result = await connection.jadbSearchWordCount("kana"); + final result = await connection.jadbSearchWordCount('kana'); expect(result, isNotNull); }); - test("Search a word - japanese kana - auto", () async { + test('Search a word - japanese kana - auto', () async { final connection = await setup_database_connection(); - final result = await connection.jadbSearchWord("かな"); + final result = await connection.jadbSearchWord('かな'); expect(result, isNotNull); }); - test("Get word search count - japanese kana - auto", () async { + test('Get word search count - japanese kana - auto', () async { final connection = await setup_database_connection(); - final result = await connection.jadbSearchWordCount("かな"); + final result = await connection.jadbSearchWordCount('かな'); expect(result, isNotNull); }); - test("Search a word - japanese kanji - auto", () async { + test('Search a word - japanese kanji - auto', () async { final connection = await setup_database_connection(); - final result = await connection.jadbSearchWord("仮名"); + final result = await connection.jadbSearchWord('仮名'); expect(result, isNotNull); }); - test("Get word search count - japanese kanji - auto", () async { + test('Get word search count - japanese kanji - auto', () async { final connection = await setup_database_connection(); - final result = await connection.jadbSearchWordCount("仮名"); + final result = await connection.jadbSearchWordCount('仮名'); expect(result, isNotNull); }); - test("Get a word by id", () async { + test('Get a word by id', () async { final connection = await setup_database_connection(); final result = await connection.jadbGetWordById(1577090); expect(result, isNotNull); }); test( - "Serialize all words", + 'Serialize all words', () async { final connection = await setup_database_connection(); // Test serializing all words - for (final letter in "aiueoksthnmyrw".split("")) { + for (final letter in 'aiueoksthnmyrw'.split('')) { await connection.jadbSearchWord(letter); } }, timeout: Timeout.factor(100), - skip: "Very slow test", + skip: 'Very slow test', ); } diff --git a/test/util/romaji_transliteration_test.dart b/test/util/romaji_transliteration_test.dart index f4177aa..0324876 100644 --- a/test/util/romaji_transliteration_test.dart +++ b/test/util/romaji_transliteration_test.dart @@ -2,65 +2,65 @@ import 'package:jadb/util/romaji_transliteration.dart'; import 'package:test/test.dart'; void main() { - group("Romaji -> Hiragana", () { - test("Basic test", () { - final result = transliterateLatinToHiragana("katamari"); - expect(result, "かたまり"); + group('Romaji -> Hiragana', () { + test('Basic test', () { + final result = transliterateLatinToHiragana('katamari'); + expect(result, 'かたまり'); }); - test("Basic test with diacritics", () { - final result = transliterateLatinToHiragana("gadamari"); - expect(result, "がだまり"); + test('Basic test with diacritics', () { + final result = transliterateLatinToHiragana('gadamari'); + expect(result, 'がだまり'); }); - test("wi and we", () { - final result = transliterateLatinToHiragana("wiwe"); - expect(result, "うぃうぇ"); + test('wi and we', () { + final result = transliterateLatinToHiragana('wiwe'); + expect(result, 'うぃうぇ'); }); - test("nb = mb", () { - final result = transliterateLatinToHiragana("kanpai"); - expect(result, "かんぱい"); + test('nb = mb', () { + final result = transliterateLatinToHiragana('kanpai'); + expect(result, 'かんぱい'); - final result2 = transliterateLatinToHiragana("kampai"); - expect(result2, "かんぱい"); + final result2 = transliterateLatinToHiragana('kampai'); + expect(result2, 'かんぱい'); }); - test("Double n", () { - final result = transliterateLatinToHiragana("konnichiha"); - expect(result, "こんにちは"); + test('Double n', () { + final result = transliterateLatinToHiragana('konnichiha'); + expect(result, 'こんにちは'); }); - test("Double consonant", () { - final result = transliterateLatinToHiragana("kappa"); - expect(result, "かっぱ"); + test('Double consonant', () { + final result = transliterateLatinToHiragana('kappa'); + expect(result, 'かっぱ'); }); }); - group("Hiragana -> Romaji", () { - test("Basic test", () { - final result = transliterateHiraganaToLatin("かたまり"); - expect(result, "katamari"); + group('Hiragana -> Romaji', () { + test('Basic test', () { + final result = transliterateHiraganaToLatin('かたまり'); + expect(result, 'katamari'); }); - test("Basic test with diacritics", () { - final result = transliterateHiraganaToLatin("がだまり"); - expect(result, "gadamari"); + test('Basic test with diacritics', () { + final result = transliterateHiraganaToLatin('がだまり'); + expect(result, 'gadamari'); }); - test("whi and whe", () { - final result = transliterateHiraganaToLatin("うぃうぇ"); - expect(result, "whiwhe"); + test('whi and whe', () { + final result = transliterateHiraganaToLatin('うぃうぇ'); + expect(result, 'whiwhe'); }); - test("Double n", () { - final result = transliterateHiraganaToLatin("こんにちは"); - expect(result, "konnichiha"); + test('Double n', () { + final result = transliterateHiraganaToLatin('こんにちは'); + expect(result, 'konnichiha'); }); - test("Double consonant", () { - final result = transliterateHiraganaToLatin("かっぱ"); - expect(result, "kappa"); + test('Double consonant', () { + final result = transliterateHiraganaToLatin('かっぱ'); + expect(result, 'kappa'); }); }); }