* test add lint as separate action
* nicer logging
* only detect changes in dart files
* fix printV warnings being displayed when editing printV

---------

Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net>
This commit is contained in:
malik1004x
2026-07-14 12:50:19 +02:00
committed by GitHub
co-authored by Czarek Nakamoto
parent 031a117f2e
commit 01c977e82b
37 changed files with 587 additions and 199 deletions
+109
View File
@@ -0,0 +1,109 @@
name: Lint
on: [pull_request]
defaults:
run:
shell: bash
jobs:
lint:
runs-on: [Linux, amd64, android]
container:
image: ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly
env:
STORE_PASS: test@cake_wallet
KEY_PASS: test@cake_wallet
MONEROC_CACHE_DIR_ROOT: /opt/generic_cache
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
ANDROID_AVD_HOME: /root/.android/avd
volumes:
- /opt/cw_cache_android/root/.cache:/root/.cache
- /opt/cw_cache_android/root/.android/avd/:/root/.android/avd
- /opt/cw_cache_android/root/.ccache:/root/.ccache
- /opt/cw_cache_android/root/.pub-cache/:/root/.pub-cache
- /opt/cw_cache_android/root/.gradle/:/root/.gradle
- /opt/cw_cache_android/root/.android/:/root/.android
- /opt/cw_cache_android/root/go/pkg:/root/go/pkg
- /opt/cw_cache_android/opt/generic_cache:/opt/generic_cache
- /dev/kvm:/dev/kvm
- /var/run/docker.sock:/var/run/docker.sock
strategy:
matrix:
api-level: [ 29 ]
steps:
- name: configure git
run: |
git config --global --add safe.directory '*'
git config --global user.email "ci@cakewallet.com"
git config --global user.name "CakeWallet CI"
- name: Fetch prebuilt Torch
run: |
set -x -e
pushd scripts
wget https://github.com/MrCyjaneK/torch_dart/releases/download/v1.0.17/torch_dart-v1.0.17.tar.gz -O torch_dart.tar.gz
rm -rf torch_dart
mkdir torch_dart
pushd torch_dart
tar -xzf ../torch_dart.tar.gz
popd
rm ./torch_dart.tar.gz
popd
- name: Fetch prebuilt Reown
run: |
set -x -e
pushd scripts
# cleaning
rm -rf reown_flutter
rm -f reown_flutter.tar.gz
wget https://github.com/cake-tech/reown_flutter/releases/download/v0.0.4/reown_flutter-v0.0.4.tar.gz -O reown_flutter.tar.gz
mkdir reown_flutter
pushd reown_flutter
tar -xzf ../reown_flutter.tar.gz
popd
rm ./reown_flutter.tar.gz
popd
- name: Build Bitbox Flutter
run: |
set -x -e
pushd scripts
./build_bitbox_flutter.sh
popd
- name: Prepare Zcash
run: |
set -x -e
scripts/prepare_zcash.sh
- name: Execute Build and Setup Commands
run: |
pushd scripts/android
source ./app_env.sh cakewallet
export GITHUB_HUH=yeah
./app_config.sh
popd
- name: Install Flutter dependencies
run: |
flutter pub get
- name: Build generated code
run: |
flutter --version
flutter clean
rm -rf .dart_tool
rm pubspec.lock
flutter pub get
./model_generator.sh async
- name: Generate localization
run: |
dart run tool/generate_localization.dart
- name: Lint
run: |
ABORT_ON_CHANGE=yeah scripts/lint.sh
+1 -2
View File
@@ -11,11 +11,10 @@ jobs:
- name: Check for http package usage
if: github.event_name == 'pull_request'
run: |
GIT_GREP_OUT="$(git grep package:http | (grep .dart: || test $? = 1) | (grep -v proxy_wrapper.dart || test $? = 1) | (grep -v very_insecure_http_do_not_use || test $? = 1) || true)"
GIT_GREP_OUT="$(git grep package:http | (grep .dart: || test $? = 1) | (grep -v proxy_wrapper.dart || test $? = 1) | (grep -v very_insecure_http_do_not_use || test $? = 1) | (grep -v '^cw_custom_lints/' || test $? = 1) || true)"
[[ "x$GIT_GREP_OUT" == "x" ]] && exit 0
echo "$GIT_GREP_OUT"
echo "There are .dart files which use http imports"
echo "Using http package breaks proxy integration"
echo "Please use ProxyWrapper.getHttpClient() from package:cw_core/utils/proxy_wrapper.dart"
exit 1
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
- name: Check for print() statements in dart code (use printV() instead)
if: github.event_name == 'pull_request'
run: |
GIT_GREP_OUT="$(git grep ' print(' | (grep .dart: || test $? = 1) | (grep -v print_verbose.dart || test $? = 1) | (grep -v print_verbose_dummy.dart || test $? = 1) || true)"
GIT_GREP_OUT="$(git grep ' print(' | (grep .dart: || test $? = 1) | (grep -v print_verbose.dart || test $? = 1) | (grep -v print_verbose_dummy.dart || test $? = 1) | (grep -v '^tool/' || test $? = 1) | (grep -v '^cw_custom_lints/' || test $? = 1) || true)"
[[ "x$GIT_GREP_OUT" == "x" ]] && exit 0
echo "$GIT_GREP_OUT"
echo "There are .dart files which use print() statements"
@@ -179,9 +179,6 @@ jobs:
with:
path: ${{ github.workspace }}/build/linux/x64/release/cakewallet_linux.zip
name: cakewallet_linux
- name: Verify lint
run: |
exec env ABORT_ON_CHANGE=true ./scripts/lint.sh
- name: Prepare virtual desktop
if: ${{ contains(env.message, 'run tests') }}
+113 -54
View File
@@ -1,4 +1,3 @@
include: package:lints/recommended.yaml
analyzer:
@@ -9,6 +8,7 @@ analyzer:
cw_core/lib/**.g.dart,
cw_haven/lib/**.g.dart,
cw_monero/lib/**.g.dart,
cw_mweb/lib/**.g.dart,
lib/generated/*.dart,
cw_monero/ios/External/**,
cw_shared_external/**,
@@ -18,65 +18,124 @@ analyzer:
strict-casts: true
strict-raw-types: true
plugins:
cw_custom_lints:
path: cw_custom_lints
linter:
rules:
- cancel_subscriptions
- always_declare_return_types
- prefer_final_fields
- always_put_control_body_on_new_line
- always_put_required_named_parameters_first
- always_use_package_imports
- annotate_overrides
- annotate_redeclares
- avoid_empty_else
- avoid_function_literals_in_foreach_calls
- avoid_init_to_null
- avoid_multiple_declarations_per_line
- avoid_positional_boolean_parameters
- avoid_relative_lib_imports
- avoid_renaming_method_parameters
- avoid_return_types_on_setters
- avoid_returning_null_for_void
- avoid_slow_async_io
- avoid_types_as_parameter_names
- avoid_types_on_closure_parameters
- avoid_unnecessary_containers
- avoid_unused_constructor_parameters
- avoid_void_async
- await_only_futures
- camel_case_extensions
- camel_case_types
- cast_nullable_to_non_nullable
- collection_methods_unrelated_type
- constant_identifier_names
- curly_braces_in_flow_control_structures
- directives_ordering
- empty_constructor_bodies
- empty_statements
- eol_at_end_of_file
- flutter_style_todos
- hash_and_equals
- implicit_reopen
- library_private_types_in_public_api
- non_constant_identifier_names
- only_throw_errors
- package_names
- prefer_asserts_with_message
- prefer_conditional_assignment
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_constructors_over_static_methods
- prefer_contains
- prefer_double_quotes
- prefer_expression_function_bodies
- prefer_final_in_for_each
- prefer_function_declarations_over_variables
- prefer_if_null_operators
- prefer_initializing_formals
- prefer_inlined_adds
- prefer_int_literals
- prefer_is_empty
- prefer_is_not_empty
- prefer_is_not_operator
- prefer_iterable_wheretype
- prefer_null_aware_operators
- prefer_spread_collections
- prefer_typing_uninitialized_variables
- recursive_getters
- require_trailing_commas
- sized_box_for_whitespace
- sort_child_properties_last
- sort_constructors_first
- sort_unnamed_constructors_first
- test_types_in_equals
- unawaited_futures
- unnecessary_async
- unnecessary_await_in_return
- unnecessary_const
- unnecessary_constructor_name
- unnecessary_lambdas
- unnecessary_late
- unnecessary_new
- unnecessary_null_aware_assignments
- unnecessary_null_checks
- unnecessary_null_in_if_null_operators
- unnecessary_nullable_for_final_variable_declarations
- unnecessary_overrides
- unnecessary_parenthesis
- unnecessary_string_escapes
- unnecessary_string_interpolations
- unnecessary_this
- unnecessary_to_list_in_spreads
- unnecessary_underscores
- unreachable_from_main
- unrelated_type_equality_checks
- use_build_context_synchronously
- use_colored_box
- use_full_hex_values_for_flutter_colors
- use_function_type_syntax_for_parameters
- use_is_even_rather_than_modulo
- use_named_constants
- use_null_aware_elements
- use_raw_strings
- use_rethrow_when_possible
- use_string_buffers
- use_super_parameters
- use_truncating_division
- valid_regexps
- void_checks
- prefer_final_locals
- prefer_interpolation_to_compose_strings
- null_closures
- no_wildcard_variable_uses
formatter:
page_width: 100
# analyzer:
# strong-mode:
# implicit-casts: false
# implicit-dynamic: false
# exclude: [build/**, lib/generated/*.dart, lib/**.g.dart, cw_monero/ios/External/**, cw_shared_external/**, shared_external/**]
# linter:
# rules:
# - always_declare_return_types
# - annotate_overrides
# - avoid_empty_else
# - avoid_init_to_null
# - avoid_return_types_on_setters
# - await_only_futures
# - camel_case_types
# - cancel_subscriptions
# - close_sinks
# - comment_references
# - constant_identifier_names
# - control_flow_in_finally
# - empty_catches
# - empty_constructor_bodies
# - empty_statements
# - hash_and_equals
# - invariant_booleans
# - iterable_contains_unrelated_type
# - library_names
# - library_prefixes
# - list_remove_unrelated_type
# - literal_only_boolean_expressions
# - non_constant_identifier_names
# - one_member_abstracts
# - only_throw_errors
# - overridden_fields
# - package_api_docs
# - package_names
# - package_prefixed_library_names
# - parameter_assignments
# - prefer_final_fields
# - prefer_final_locals
# - prefer_is_not_empty
# - slash_for_doc_comments
# - sort_constructors_first
# - sort_unnamed_constructors_first
# - test_types_in_equals
# - throw_in_finally
# - type_init_formals
# - unawaited_futures
# - unnecessary_getters_setters
# - unrelated_type_equality_checks
# - valid_regexps
+1 -1
View File
@@ -6,7 +6,7 @@ author: Cake Wallet
homepage: https://cakewallet.com
environment:
sdk: ">=2.17.5 <3.0.0"
sdk: ">=3.0.0 <4.0.0"
flutter: ">=1.20.0"
dependencies:
-4
View File
@@ -1,4 +0,0 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
@@ -0,0 +1,62 @@
import "package:analyzer/analysis_rule/analysis_rule.dart";
import "package:analyzer/analysis_rule/rule_context.dart";
import "package:analyzer/analysis_rule/rule_visitor_registry.dart";
import "package:analyzer/dart/ast/ast.dart";
import "package:analyzer/dart/ast/visitor.dart";
import "package:analyzer/error/error.dart";
class HttpForceProxyRule extends AnalysisRule {
HttpForceProxyRule()
: super(
name: "no_http_imports",
description:
"Using the http package breaks proxy integration. Please use ProxyWrapper or alias it as \"very_insecure_http_do_not_use\".",
);
static const LintCode code = LintCode(
"no_http_imports",
"Using the http package breaks proxy integration. Please use ProxyWrapper or alias it as \"very_insecure_http_do_not_use\".",
severity: DiagnosticSeverity.WARNING,
);
@override
LintCode get diagnosticCode => code;
@override
void registerNodeProcessors(
RuleVisitorRegistry registry,
RuleContext context,
) {
final filePath = context.definingUnit.file.path;
if (filePath.endsWith("proxy_wrapper.dart")) {
return;
}
registry.addImportDirective(this, _Visitor(this));
}
}
class _Visitor extends SimpleAstVisitor<void> {
_Visitor(this.rule);
final AnalysisRule rule;
@override
void visitImportDirective(ImportDirective node) {
final uriString = node.uri.stringValue;
if (uriString == null) {
return;
}
if (uriString.startsWith("package:http")) {
final prefixNode = node.prefix;
if (prefixNode != null &&
prefixNode.name == "very_insecure_http_do_not_use") {
return;
}
rule.reportAtNode(node);
}
}
}
+22
View File
@@ -0,0 +1,22 @@
import "package:analysis_server_plugin/plugin.dart";
import "package:analysis_server_plugin/registry.dart";
import "package:cw_custom_lints/http_force_proxy/http_force_proxy_rule.dart";
import "package:cw_custom_lints/print_verbose/print_verbose_fix.dart";
import "package:cw_custom_lints/print_verbose/print_verbose_rule.dart";
import "package:cw_custom_lints/restricted_imports/restricted_imports_rule.dart";
final plugin = CwCustomLintsPlugin();
class CwCustomLintsPlugin extends Plugin {
@override
String get name => "cw_custom_lints";
@override
void register(PluginRegistry registry) {
registry.registerWarningRule(PrintVerboseRule());
registry.registerWarningRule(RestrictedImportsRule());
registry.registerWarningRule(HttpForceProxyRule());
registry.registerFixForRule(PrintVerboseRule.code, ReplaceWithPrintV.new);
}
}
@@ -0,0 +1,50 @@
import "package:analysis_server_plugin/edit/dart/correction_producer.dart";
import "package:analysis_server_plugin/edit/dart/dart_fix_kind_priority.dart";
import "package:analyzer/dart/ast/ast.dart";
import "package:analyzer_plugin/utilities/change_builder/change_builder_core.dart";
import "package:analyzer_plugin/utilities/fixes/fixes.dart";
import "package:analyzer_plugin/utilities/range_factory.dart";
class ReplaceWithPrintV extends ResolvedCorrectionProducer {
ReplaceWithPrintV({required super.context});
static const _importString = "package:cw_core/utils/print_verbose.dart";
static const _fixKind = FixKind(
"dart.fix.replaceWithPrintV",
DartFixKindPriority.standard,
"Replace with printV()",
);
@override
CorrectionApplicability get applicability =>
CorrectionApplicability.singleLocation;
@override
FixKind get fixKind => _fixKind;
@override
Future<void> compute(ChangeBuilder builder) async {
final invocation = node.thisOrAncestorOfType<MethodInvocation>();
if (invocation == null) {
return;
}
final root = invocation.root;
final hasImport = root is CompilationUnit &&
root.directives.whereType<ImportDirective>().any(
(directive) => directive.uri.stringValue == _importString,
);
await builder.addDartFileEdit(file, (builder) {
builder.addSimpleReplacement(
range.node(invocation.methodName),
"printV",
);
if (!hasImport) {
builder.importLibrary(Uri.parse(_importString));
}
});
}
}
@@ -0,0 +1,52 @@
import "package:analyzer/analysis_rule/analysis_rule.dart";
import "package:analyzer/analysis_rule/rule_context.dart";
import "package:analyzer/analysis_rule/rule_visitor_registry.dart";
import "package:analyzer/dart/ast/ast.dart";
import "package:analyzer/dart/ast/visitor.dart";
import "package:analyzer/error/error.dart";
class PrintVerboseRule extends AnalysisRule {
PrintVerboseRule()
: super(
name: "use_print_v",
description: "Use printV() from cw_core instead of print().",
);
static const LintCode code = LintCode(
"use_print_v",
"Use printV() from cw_core instead",
correctionMessage: "Replace print with printV",
severity: DiagnosticSeverity.WARNING,
);
@override
LintCode get diagnosticCode => code;
@override
void registerNodeProcessors(
RuleVisitorRegistry registry,
RuleContext context,
) {
final filePath = context.definingUnit.file.path;
if (filePath.contains("/tool/") || filePath.contains("print_verbose.dart")) {
// tool/ is allowed to use print as it never makes its way into the app
return;
}
registry.addMethodInvocation(this, _Visitor(this));
}
}
class _Visitor extends SimpleAstVisitor<void> {
_Visitor(this.rule);
final AnalysisRule rule;
@override
void visitMethodInvocation(MethodInvocation node) {
if (node.methodName.name == "print" && node.target == null) {
rule.reportAtNode(node);
}
}
}
@@ -0,0 +1,79 @@
import "package:analyzer/analysis_rule/analysis_rule.dart";
import "package:analyzer/analysis_rule/rule_context.dart";
import "package:analyzer/analysis_rule/rule_visitor_registry.dart";
import "package:analyzer/dart/ast/ast.dart";
import "package:analyzer/dart/ast/visitor.dart";
import "package:analyzer/error/error.dart";
class RestrictedImportsRule extends AnalysisRule {
RestrictedImportsRule()
: super(
name: "no_restricted_imports_in_lib",
description:
"Do not import from coin-specific packages. If necessary, wire your logic through configure.dart",
);
static const LintCode code = LintCode(
"no_restricted_imports_in_lib",
"Do not import from coin-specific packages. If necessary, wire your logic through configure.dart",
severity: DiagnosticSeverity.ERROR,
);
static const _restrictedPackages = {
"cw_bitcoin",
"cw_bitcoin_cash",
"cw_electrum",
"cw_litecoin",
"cw_evm",
"cw_mweb",
"cw_nano",
"cw_solana",
"cw_tron",
"cw_zano",
};
@override
LintCode get diagnosticCode => code;
@override
void registerNodeProcessors(
RuleVisitorRegistry registry,
RuleContext context,
) {
final filePath = context.definingUnit.file.path;
final fileName = filePath.split("/").last;
// ignore cw_something folders
if (filePath.contains("cw_")) {
return;
}
// allow ex. cw_bitcoin in bitcoin.dart
if (_restrictedPackages.contains("cw_" + fileName.replaceAll(".dart", ""))) {
return;
}
registry.addImportDirective(this, _Visitor(this));
}
}
class _Visitor extends SimpleAstVisitor<void> {
_Visitor(this.rule);
final AnalysisRule rule;
@override
void visitImportDirective(ImportDirective node) {
final uriString = node.uri.stringValue;
if (uriString == null || !uriString.startsWith("package:")) {
return;
}
final pathWithoutScheme = uriString.replaceFirst("package:", "");
final packageName = pathWithoutScheme.split("/").first;
if (RestrictedImportsRule._restrictedPackages.contains(packageName)) {
rule.reportAtNode(node);
}
}
}
+15
View File
@@ -0,0 +1,15 @@
name: cw_custom_lints
version: 0.0.1
environment:
sdk: '>=3.9.0 <4.0.0'
dependencies:
analysis_server_plugin: 0.3.15
analyzer: 13.0.0
analyzer_plugin: 0.14.9
dev_dependencies:
analyzer_testing: 0.2.6
test_reflective_loader: 0.4.0
test: 1.31.2
-4
View File
@@ -1,4 +0,0 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
-4
View File
@@ -1,4 +0,0 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
-4
View File
@@ -1,4 +0,0 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
-4
View File
@@ -1,4 +0,0 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
-4
View File
@@ -1,4 +0,0 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
+1 -1
View File
@@ -6,7 +6,7 @@ author: Cake Wallet
homepage: https://cakewallet.com
environment:
sdk: '>=2.18.2 <3.0.0'
sdk: '>=3.0.0 <4.0.0'
flutter: ">=1.17.0"
dependencies:
-4
View File
@@ -1,4 +0,0 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
-4
View File
@@ -1,4 +0,0 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
-4
View File
@@ -1,4 +0,0 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
+1 -1
View File
@@ -5,7 +5,7 @@ publish_to: none
homepage: https://cakewallet.com
environment:
sdk: ">=2.19.0 <3.0.0"
sdk: ">=3.0.0 <4.0.0"
flutter: ">=1.20.0"
dependencies:
-31
View File
@@ -1,31 +0,0 @@
analyzer:
errors:
implementation_imports: ignore
must_be_immutable: ignore
overridden_fields: ignore
exclude:
- "**.g.dart"
- "external/**"
linter:
rules:
unawaited_futures: true
avoid_print: false
parameter_assignments: true
prefer_const_declarations: true
prefer_final_fields: true
prefer_final_in_for_each: true
prefer_final_locals: true
prefer_final_parameters: true
avoid_void_async: true
require_trailing_commas: true
sort_child_properties_last: true
sort_constructors_first: true
sort_unnamed_constructors_first: true
unnecessary_async: true
unnecessary_await_in_return: true
unnecessary_string_interpolations: true
always_declare_return_types: true
formatter:
page_width: 100
+1 -1
View File
@@ -177,7 +177,7 @@ class CWBitcoin extends Bitcoin {
List<ElectrumSubAddress> getSubAddresses(Object wallet) {
final electrumWallet = wallet as ElectrumWallet;
return electrumWallet.walletAddresses.addressesByReceiveType
.map((BaseBitcoinAddressRecord addr) => ElectrumSubAddress(
.map<ElectrumSubAddress>((addr) => ElectrumSubAddress(
id: addr.index,
name: addr.name,
address: addr.address,
+22 -10
View File
@@ -1,17 +1,29 @@
#!/bin/bash
set -x -e
cd $(dirname $0)
set -e
cd "$(dirname "$0")"
cd ..
for i in cw_zcash;
for i in cw_bitcoin cw_bitcoin_cash cw_core cw_decred cw_dogecoin cw_evm cw_monero cw_mweb cw_nano cw_solana cw_tron cw_zano cw_zcash lib;
do
dart fix --apply $i/
dart format --line-length=100 $i/
if [[ ! "x$ABORT_ON_CHANGE" == "x" ]];
then
if [[ ! -z "$(git status --porcelain -- $(find $i))" ]];
then
echo "Please run scripts/lint.sh ($i has changes)"
{
# files modified after the lints got enabled and committed
git log --since="2026-07-14 23:59:59" --name-only --diff-filter=d --format="" -- "$i"
# uncommitted files (assumed to have been modified after the 29th)
git diff --name-only --diff-filter=d HEAD -- "$i"
} | grep '\.dart$' | sort -u | while IFS= read -r file; do
echo $file
if [[ -f "$file" ]]; then
dart fix --apply "$file" && dart format --line-length=100 "$file"
fi
done
if [[ -n "$ABORT_ON_CHANGE" ]]; then
DART_CHANGES=$(git status --porcelain -- "$i" | grep '\.dart$' || true)
if [[ -n "$DART_CHANGES" ]]; then
echo "Please run scripts/lint.sh"
echo "changes in $i:"
echo "$DART_CHANGES"
exit 1
fi
fi
+3 -3
View File
@@ -15,7 +15,7 @@ void main(List<String> args) async {
final text = args[1];
final force = args.last == "--force";
printV('Appending "$name": "$text"');
print('Appending "$name": "$text"');
// add translation to all languages:
for (var lang in langs) {
@@ -25,12 +25,12 @@ void main(List<String> args) async {
appendStringToArbFile(fileName, name, translation, force: force);
}
printV('Alphabetizing all files...');
print('Alphabetizing all files...');
for (var lang in langs) {
final fileName = getArbFileName(lang);
alphabetizeArbFile(fileName);
}
printV('Done!');
print('Done!');
}
+5 -5
View File
@@ -31,7 +31,7 @@ Future<void> main() async {
final resp = await _dio.get("https://api.github.com/repos/mrcyjanek/monero_c/releases");
final data = resp.data[0];
final tagName = data['tag_name'];
printV("Downloading artifacts for: ${tagName}");
print("Downloading artifacts for: ${tagName}");
final assets = data['assets'] as List<dynamic>;
for (var i = 0; i < assets.length; i++) {
for (var triplet in triplets) {
@@ -42,10 +42,10 @@ Future<void> main() async {
String localFilename = filename.replaceAll("${coin}_${triplet}_", "");
localFilename = "scripts/monero_c/release/${coin}/${triplet}_${localFilename}";
final url = asset["browser_download_url"] as String;
printV("- downloading $localFilename");
print("- downloading $localFilename");
await _dio.download(url, localFilename);
if (localFilename.endsWith(".xz")) {
printV(" extracting $localFilename");
print(" extracting $localFilename");
final inputStream = InputFileStream(localFilename);
final archive = XZDecoder().decodeBytes(inputStream.toUint8List());
final outputStream = OutputFileStream(localFilename.replaceAll(".xz", ""));
@@ -54,11 +54,11 @@ Future<void> main() async {
}
}
if (Platform.isMacOS) {
printV("Generating ios framework");
print("Generating ios framework");
final result = Process.runSync("bash", [
"-c",
"cd scripts/ios && ./gen_framework.sh && cd ../.."
]);
printV((result.stdout+result.stderr).toString().trim());
print((result.stdout+result.stderr).toString().trim());
}
}
+7 -7
View File
@@ -76,7 +76,7 @@ void main() {
// --- B. Run App in a Zone to Capture Prints ---
runZoned(
() async {
printV('--- Starting Verified Price Check ---');
print('--- Starting Verified Price Check ---');
final Map<String, List<String>> workingPairs = {};
final Map<String, List<String>> failedPairs = {};
@@ -130,7 +130,7 @@ void main() {
}
// Print immediate status (Captured by Zone)
printV('$logPrefix $logMessage');
print('$logPrefix $logMessage');
// Aggregate
if (isSuccess) {
@@ -148,25 +148,25 @@ void main() {
}
// --- FINAL SUMMARY ---
printV('\n\n=== SUMMARY ===\n');
print('\n\n=== SUMMARY ===\n');
// Print Successful
workingPairs.forEach((crypto, fiats) {
if (fiats.isNotEmpty) {
printV('✅ ${crypto.toUpperCase()}: ${fiats.join(", ")}');
print('✅ ${crypto.toUpperCase()}: ${fiats.join(", ")}');
}
});
printV('\n--------------------------------------------------\n');
print('\n--------------------------------------------------\n');
// Print Failed
failedPairs.forEach((crypto, fiats) {
if (fiats.isNotEmpty) {
printV('❌ ${crypto.toUpperCase()}: ${fiats.join(", ")}');
print('❌ ${crypto.toUpperCase()}: ${fiats.join(", ")}');
}
});
printV('\n=== DONE ===');
print('\n=== DONE ===');
},
// --- C. The Interceptor ---
+5 -5
View File
@@ -37,7 +37,7 @@ Future<void> main(List<String> args) async {
extraInfo.forEach((key, dynamic value) async {
if (key != srcDir) {
printV('Wrong key: $key');
print('Wrong key: $key');
return;
}
@@ -45,7 +45,7 @@ Future<void> main(List<String> args) async {
final dir = Directory(dirPath);
if (!await dir.exists()) {
printV('Wrong directory path: $dirPath');
print('Wrong directory path: $dirPath');
return;
}
@@ -55,7 +55,7 @@ Future<void> main(List<String> args) async {
// normalizing the case so keys match LanguageService.supportedLocales.
final fileName = element.uri.pathSegments.last;
if (!fileName.startsWith('strings_') || !fileName.endsWith('.arb')) {
printV('Wrong file: ${element.path}');
print('Wrong file: ${element.path}');
return;
}
final parts =
@@ -67,7 +67,7 @@ Future<void> main(List<String> args) async {
});
if (!localePath.keys.contains(defaultLocale)) {
printV("Locale list doesn't contain $defaultLocale");
print("Locale list doesn't contain $defaultLocale");
return;
}
@@ -124,7 +124,7 @@ Future<void> main(List<String> args) async {
await File(outputPath + localeListFileName).writeAsString(locales);
} catch (e) {
printV(e.toString());
print(e.toString());
}
});
}
-1
View File
@@ -1 +0,0 @@
void printV(dynamic content) => print(content);
+1 -1
View File
@@ -46,7 +46,7 @@ void main() async {
});
currentItem++;
printV(
print(
"\r$currentLang/${langs.length} langs done, $currentItem/${defaultLangChangelog.length} items done");
}
currentLang++;
+29 -29
View File
@@ -25,18 +25,18 @@ class TranslationChecker {
final sourceMap = json.decode(sourceContent) as Map<String, dynamic>;
final destinationMap = json.decode(destinationContent) as Map<String, dynamic>;
printV('Found ${sourceMap.length} keys in source, ${destinationMap.length} in destination');
print('Found ${sourceMap.length} keys in source, ${destinationMap.length} in destination');
final keysToProcess = specificKey != null
? (sourceMap.containsKey(specificKey) ? [specificKey] : <String>[])
: sourceMap.keys.toList();
if (specificKey != null && keysToProcess.isEmpty) {
printV('Error: Key "$specificKey" not found in source file');
print('Error: Key "$specificKey" not found in source file');
return;
}
printV('Processing ${keysToProcess.length} translations...');
print('Processing ${keysToProcess.length} translations...');
int processed = 0;
int corrected = 0;
@@ -57,16 +57,16 @@ class TranslationChecker {
if (correctedTranslation != destinationValue) {
destinationMap[key] = correctedTranslation;
corrected++;
printV('Processed: "$key" -> CORRECTED');
printV(' - eng : "$sourceValue"');
printV(' - dst orig: "$destinationValue"');
printV(' - dst new : "$correctedTranslation"');
print('Processed: "$key" -> CORRECTED');
print(' - eng : "$sourceValue"');
print(' - dst orig: "$destinationValue"');
print(' - dst new : "$correctedTranslation"');
await _writeArbFile(destinationArbPath, destinationMap);
} else {
printV('Processed: "$key" -> VERIFIED');
print('Processed: "$key" -> VERIFIED');
}
} else {
printV('Processed: "$key" -> SKIPPED (non-string)');
print('Processed: "$key" -> SKIPPED (non-string)');
}
processed++;
@@ -74,11 +74,11 @@ class TranslationChecker {
await _writeArbFile(destinationArbPath, destinationMap);
printV('');
printV('Summary:');
printV('Processed: $processed keys');
printV('Corrected: $corrected keys');
printV('Updated: $destinationArbPath');
print('');
print('Summary:');
print('Processed: $processed keys');
print('Corrected: $corrected keys');
print('Updated: $destinationArbPath');
}
Future<String> _checkSingleTranslation({
@@ -108,7 +108,7 @@ class TranslationChecker {
return currentTranslation;
} catch (e) {
printV('Error checking translation for key "$key": $e');
print('Error checking translation for key "$key": $e');
return currentTranslation;
}
}
@@ -186,7 +186,7 @@ IMPORTANT: Respond with a JSON object in the exact format, you must think about
final jsonEnd = response.lastIndexOf('}');
if (jsonStart == -1 || jsonEnd == -1 || jsonStart >= jsonEnd) {
printV('No valid JSON found in LLM response');
print('No valid JSON found in LLM response');
return null;
}
@@ -195,7 +195,7 @@ IMPORTANT: Respond with a JSON object in the exact format, you must think about
return parsed['corrected_translation'] as String?;
} catch (e) {
printV('Error extracting JSON from LLM response: $e');
print('Error extracting JSON from LLM response: $e');
return null;
}
}
@@ -228,7 +228,7 @@ void main(List<String> args) async {
final results = parser.parse(args);
if (results['help'] as bool) {
printV(parser.usage);
print(parser.usage);
return;
}
@@ -239,24 +239,24 @@ void main(List<String> args) async {
final model = results['model'] as String;
if (!File(sourcePath).existsSync()) {
printV('Error: Source ARB file not found: $sourcePath');
print('Error: Source ARB file not found: $sourcePath');
exit(1);
}
if (!File(destinationPath).existsSync()) {
printV('Error: Destination ARB file not found: $destinationPath');
print('Error: Destination ARB file not found: $destinationPath');
exit(1);
}
printV('Translation Checker');
printV('Source: $sourcePath');
printV('Destination: $destinationPath');
printV('Ollama URL: $ollamaUrl');
printV('Model: $model');
print('Translation Checker');
print('Source: $sourcePath');
print('Destination: $destinationPath');
print('Ollama URL: $ollamaUrl');
print('Model: $model');
if (specificKey != null) {
printV('Key: $specificKey');
print('Key: $specificKey');
}
printV('');
print('');
final checker = TranslationChecker(
ollamaBaseUrl: ollamaUrl,
@@ -270,8 +270,8 @@ void main(List<String> args) async {
);
} catch (e) {
printV('Error: $e');
printV('Run with --help for more information.');
print('Error: $e');
print('Run with --help for more information.');
exit(1);
}
}
+1 -1
View File
@@ -34,5 +34,5 @@ void main(List<String> args) async {
}
appendStringsToArbFile(targetFileName, translations);
printV("Success! Please add your Language Code to lib/entities/language_service.dart");
print("Success! Please add your Language Code to lib/entities/language_service.dart");
}
+4 -4
View File
@@ -7,14 +7,14 @@ import 'utils/translation/translation_constants.dart';
import 'utils/translation/translation_utils.dart';
void main(List<String> args) async {
printV('Checking Consistency of all arb-files. Default: $defaultLang');
print('Checking Consistency of all arb-files. Default: $defaultLang');
final doFix = args.contains("--fix");
if (doFix)
printV('Auto fixing enabled!\n');
print('Auto fixing enabled!\n');
else
printV('Auto fixing disabled!\nRun with arg "--fix" to enable autofix\n');
print('Auto fixing disabled!\nRun with arg "--fix" to enable autofix\n');
final fileName = getArbFileName(defaultLang);
final file = File(fileName);
@@ -27,7 +27,7 @@ void main(List<String> args) async {
final missingDefaults = <String, String>{};
missingKeys.forEach((key) {
printV('Missing in "$lang": "$key"');
print('Missing in "$lang": "$key"');
if (doFix)
missingDefaults[key] = arbObj[key] as String;
});
+1 -1
View File
@@ -8,7 +8,7 @@ void appendStringToArbFile(String fileName, String name, String text, {bool forc
final arbObj = readArbFile(file);
if (arbObj.containsKey(name) && !force) {
printV("String $name already exists in $fileName!");
print("String $name already exists in $fileName!");
return;
}
@@ -38,7 +38,7 @@ Future<String> getTranslation(String text, String lang) async {
try {
translation = (await translator.translate(text, from: defaultLang, to: lang)).text;
} catch (e) {
printV("$lang, $text, $e");
print("$lang, $text, $e");
}
placeholder.forEach((index, value) {
final translatedPlaceholder = regExp.allMatches(translation).toList()[index];