From 3163868f245cf290bd97c1f1a3aed56574a5eb52 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Sun, 26 Apr 2026 11:30:28 +0100 Subject: [PATCH 01/47] add lints (wip) --- .github/workflows/lint_check.yml | 56 ++++++ analysis_options.yaml | 183 +++++++++++------- cw_bitcoin/pubspec.yaml | 2 +- cw_custom_lints/lib/cw_custom_lints.dart | 15 ++ .../http_force_proxy_rule.dart | 51 +++++ .../lib/print_verbose/print_verbose_fix.dart | 41 ++++ .../lib/print_verbose/print_verbose_rule.dart | 46 +++++ .../restricted_imports_rule.dart | 69 +++++++ cw_custom_lints/pubspec.yaml | 8 + cw_nano/pubspec.yaml | 2 +- cw_zano/pubspec.yaml | 2 +- lib/new-ui/pages/card_customizer.dart | 4 +- lint.sh | 58 ++++++ pubspec_base.yaml | 6 + tool/append_translation.dart | 6 +- tool/download_moneroc_prebuilds.dart | 10 +- tool/fiat_api_check.dart | 14 +- tool/generate_localization.dart | 10 +- tool/print_verbose_dummy.dart | 1 - tool/translate_changelog.dart | 2 +- tool/translate_using_llm.dart | 58 +++--- tool/translation_add_lang.dart | 2 +- tool/translation_consistence.dart | 8 +- tool/utils/translation/arb_file_utils.dart | 2 +- tool/utils/translation/translation_utils.dart | 2 +- 25 files changed, 528 insertions(+), 130 deletions(-) create mode 100644 .github/workflows/lint_check.yml create mode 100644 cw_custom_lints/lib/cw_custom_lints.dart create mode 100644 cw_custom_lints/lib/http_force_proxy/http_force_proxy_rule.dart create mode 100644 cw_custom_lints/lib/print_verbose/print_verbose_fix.dart create mode 100644 cw_custom_lints/lib/print_verbose/print_verbose_rule.dart create mode 100644 cw_custom_lints/lib/restricted_imports/restricted_imports_rule.dart create mode 100644 cw_custom_lints/pubspec.yaml create mode 100644 lint.sh diff --git a/.github/workflows/lint_check.yml b/.github/workflows/lint_check.yml new file mode 100644 index 0000000000..441ce5315e --- /dev/null +++ b/.github/workflows/lint_check.yml @@ -0,0 +1,56 @@ +name: PR Formatting & Lint Check + +on: [pull_request] + +jobs: + fast_lint_check: + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: subosito/flutter-action@v2 + with: + channel: 'stable' + + - name: Install dependencies + run: flutter pub get + + - name: Incremental Format and Lint + run: | + PR_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep '\.dart$' || true) + + if [ -z "$PR_FILES" ]; then + exit 0 + fi + + FAILED=false + + if ! dart format --output=none --set-exit-if-changed $PR_FILES; then + FAILED=true + fi + + dart run custom_lint > custom_lint_output 2>&1 || true + + for file in $PR_FILES; do + if grep -q "$file" custom_lint_output; then + grep -C 2 "$file" custom_lint_output + FAILED=true + fi + done + + dart analyze > dart_analyze_output 2>&1 || true + + for file in $PR_FILES; do + if grep -q "$file" dart_analyze_output; then + grep -C 2 "$file" dart_analyze_output + FAILED=true + fi + done + + if [ "$FAILED" = true ]; then + echo "ci failed because you didn't format or lint." + exit 1 + fi \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml index 7f76d27217..50a92ca407 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,4 +1,3 @@ -include: package:lints/recommended.yaml analyzer: @@ -9,87 +8,139 @@ 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/**, shared_external/**, - lib/bitcoin/cw_bitcoin.dart, - lib/bitcoin_cash/cw_bitcoin_cash.dart, - lib/ethereum/cw_ethereum.dart, - lib/haven/cw_haven.dart, - lib/monero/cw_monero.dart, - lib/nano/cw_nano.dart, - lib/polygon/cw_polygon.dart, - lib/solana/cw_solana.dart, - lib/tron/cw_tron.dart, - lib/wownero/cw_wownero.dart, - lib/zano/cw_zano.dart, - lib/base/cw_base.dart, - lib/arbitrum/cw_arbitrum.dart, ] language: strict-casts: true strict-raw-types: true + plugins: + - custom_lint 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 + - omit_obvious_local_variable_types + - 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_final_locals + - 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 + # TODO uncomment after we update flutter version to something that supports this rule + # - 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_decorated_box + - use_full_hex_values_for_flutter_colors + - use_function_type_syntax_for_parameters + - use_is_even_rather_than_modulo + - use_key_in_widget_constructors + - 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 -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/**] +formatter: + page_width: 100 -# 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 +custom_lint: + debug: true + verbose: true + rules: + - use_print_v diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index d58919ea15..88b0500a84 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -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: diff --git a/cw_custom_lints/lib/cw_custom_lints.dart b/cw_custom_lints/lib/cw_custom_lints.dart new file mode 100644 index 0000000000..61571f530c --- /dev/null +++ b/cw_custom_lints/lib/cw_custom_lints.dart @@ -0,0 +1,15 @@ +import "package:custom_lint_builder/custom_lint_builder.dart"; +import "package:cw_custom_lints/http_force_proxy/http_force_proxy_rule.dart"; +import "package:cw_custom_lints/print_verbose/print_verbose_rule.dart"; +import "package:cw_custom_lints/restricted_imports/restricted_imports_rule.dart"; + +PluginBase createPlugin() => _CustomLintsPlugin(); + +class _CustomLintsPlugin extends PluginBase { + @override + List getLintRules(CustomLintConfigs configs) => [ + const PrintVerboseRule(), + const RestrictedImportsRule(), + const HttpForceProxyRule(), + ]; +} diff --git a/cw_custom_lints/lib/http_force_proxy/http_force_proxy_rule.dart b/cw_custom_lints/lib/http_force_proxy/http_force_proxy_rule.dart new file mode 100644 index 0000000000..8d4a0f80eb --- /dev/null +++ b/cw_custom_lints/lib/http_force_proxy/http_force_proxy_rule.dart @@ -0,0 +1,51 @@ +import "package:analyzer/error/error.dart" hide LintCode; +import "package:analyzer/error/listener.dart"; +import "package:custom_lint_builder/custom_lint_builder.dart"; + +class HttpForceProxyRule extends DartLintRule { + const HttpForceProxyRule() : super(code: _code); + + static const _code = LintCode( + name: "no_http_imports", + problemMessage: + "Using the http package breaks proxy integration. Please use ProxyWrapper or alias it as \"very_insecure_http_do_not_use\".", + errorSeverity: ErrorSeverity.WARNING, + ); + + @override + void run( + CustomLintResolver resolver, + ErrorReporter reporter, + CustomLintContext context, + ) { + final filePath = resolver.source.fullName; + + if (filePath.endsWith("proxy_wrapper.dart")) { + return; + } + + context.registry.addImportDirective((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; + } + + reporter.reportError( + AnalysisError.forValues( + source: resolver.source, + offset: node.offset, + length: node.length, + errorCode: _code, + message: _code.problemMessage, + ), + ); + } + }); + } +} diff --git a/cw_custom_lints/lib/print_verbose/print_verbose_fix.dart b/cw_custom_lints/lib/print_verbose/print_verbose_fix.dart new file mode 100644 index 0000000000..ae31f83793 --- /dev/null +++ b/cw_custom_lints/lib/print_verbose/print_verbose_fix.dart @@ -0,0 +1,41 @@ +import "package:analyzer/dart/ast/ast.dart"; +import "package:analyzer/error/error.dart" hide LintCode; +import "package:custom_lint_builder/custom_lint_builder.dart"; + +class ReplaceWithPrintV extends DartFix { + @override + void run( + CustomLintResolver resolver, + ChangeReporter reporter, + CustomLintContext context, + AnalysisError error, + List others, + ) { + context.registry.addMethodInvocation((node) { + const importString = "package:cw_core/utils/print_verbose.dart"; + + if (!error.sourceRange.intersects(node.sourceRange)) { + return; + } + + final root = node.root; + final hasImport = root is CompilationUnit && + root.directives.whereType().any( + (directive) => directive.uri.stringValue == importString, + ); + + final changeBuilder = reporter.createChangeBuilder( + message: "Replace with printV()", + priority: 999999, + ); + + changeBuilder.addDartFileEdit((builder) { + builder.addSimpleReplacement(node.methodName.sourceRange, "printV"); + + if (!hasImport) { + builder.importLibrary(Uri.parse(importString)); + } + }); + }); + } +} diff --git a/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart b/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart new file mode 100644 index 0000000000..acee0b6079 --- /dev/null +++ b/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart @@ -0,0 +1,46 @@ +import "package:analyzer/error/error.dart" hide LintCode; +import "package:analyzer/error/listener.dart"; +import "package:custom_lint_builder/custom_lint_builder.dart"; +import "package:cw_custom_lints/print_verbose/print_verbose_fix.dart"; + +class PrintVerboseRule extends DartLintRule { + const PrintVerboseRule() : super(code: _code); + + static const _code = LintCode( + name: "use_print_v", + problemMessage: "Use printV() from cw_core instead", + correctionMessage: "Replace print with printV", + errorSeverity: ErrorSeverity.WARNING, + ); + + @override + void run( + CustomLintResolver resolver, + ErrorReporter reporter, + CustomLintContext context, + ) { + final filePath = resolver.source.fullName; + + if (filePath.contains("/tool/")) { + // tool/ is allowed to use print as it never makes its way into the app + return; + } + + context.registry.addMethodInvocation((node) { + if (node.methodName.name == "print" && node.target == null) { + reporter.reportError( + AnalysisError.forValues( + source: resolver.source, + offset: node.offset, + length: node.length, + errorCode: _code, + message: _code.problemMessage, + ), + ); + } + }); + } + + @override + List getFixes() => [ReplaceWithPrintV()]; +} diff --git a/cw_custom_lints/lib/restricted_imports/restricted_imports_rule.dart b/cw_custom_lints/lib/restricted_imports/restricted_imports_rule.dart new file mode 100644 index 0000000000..9ded21e405 --- /dev/null +++ b/cw_custom_lints/lib/restricted_imports/restricted_imports_rule.dart @@ -0,0 +1,69 @@ +import "package:analyzer/error/error.dart" hide LintCode; +import "package:analyzer/error/listener.dart"; +import "package:custom_lint_builder/custom_lint_builder.dart"; + +class RestrictedImportsRule extends DartLintRule { + const RestrictedImportsRule() : super(code: _code); + + static const _code = LintCode( + name: "no_restricted_imports_in_lib", + problemMessage: + "Do not import from coin-specific packages. If necessary, wire your logic through configure.dart", + errorSeverity: ErrorSeverity.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 + void run( + CustomLintResolver resolver, + ErrorReporter reporter, + CustomLintContext context, + ) { + final filePath = resolver.source.fullName; + 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; + } + + context.registry.addImportDirective((node) { + final uriString = node.uri.stringValue; + if (uriString == null || !uriString.startsWith("package:")) { + return; + } + + final pathWithoutScheme = uriString.replaceFirst("package:", ""); + final packageName = pathWithoutScheme.split("/").first; + + if (_restrictedPackages.contains(packageName)) { + reporter.reportError( + AnalysisError.forValues( + source: resolver.source, + offset: node.offset, + length: node.length, + errorCode: _code, + message: _code.problemMessage, + ), + ); + } + }); + } +} diff --git a/cw_custom_lints/pubspec.yaml b/cw_custom_lints/pubspec.yaml new file mode 100644 index 0000000000..a114588645 --- /dev/null +++ b/cw_custom_lints/pubspec.yaml @@ -0,0 +1,8 @@ +name: cw_custom_lints +version: 0.0.1 +environment: + sdk: '>=3.0.0 <4.0.0' + +dependencies: + # FIXME update once we get rid of hive and therefore can move away from flutter 3.32 and analyzer v6 + custom_lint_builder: 0.6.2 \ No newline at end of file diff --git a/cw_nano/pubspec.yaml b/cw_nano/pubspec.yaml index a85a4aee55..fae53fddb7 100644 --- a/cw_nano/pubspec.yaml +++ b/cw_nano/pubspec.yaml @@ -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: diff --git a/cw_zano/pubspec.yaml b/cw_zano/pubspec.yaml index 8eb5d3e149..818a961099 100644 --- a/cw_zano/pubspec.yaml +++ b/cw_zano/pubspec.yaml @@ -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: diff --git a/lib/new-ui/pages/card_customizer.dart b/lib/new-ui/pages/card_customizer.dart index 47d91c9529..8ce9e885ce 100644 --- a/lib/new-ui/pages/card_customizer.dart +++ b/lib/new-ui/pages/card_customizer.dart @@ -47,8 +47,7 @@ class _CardCustomizerState extends State { } @override - Widget build(BuildContext context) { - return BlocListener( + Widget build(BuildContext context) => BlocListener( listenWhen: (previous, current) => previous.accountName != current.accountName, listener: (context, state) { @@ -233,5 +232,4 @@ class _CardCustomizerState extends State { }, ), ); - } } diff --git a/lint.sh b/lint.sh new file mode 100644 index 0000000000..a20d347c9c --- /dev/null +++ b/lint.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +set -e + +CHECK_ONLY=false +TARGET_DIFF="HEAD" + +while [[ "$#" -gt 0 ]]; do + case $1 in + check) CHECK_ONLY=true; shift ;; + *) TARGET_DIFF="$1"; shift ;; + esac +done + +if [ $# -eq 0 ]; then + echo "warning: no target branch provided, cannot reliably determine diff. will only lint uncommitted files." + echo "recommended to use ./lint.sh [target_branch], for example ./lint.sh dev" +fi + +PR_FILES=$(git diff --name-only "$TARGET_DIFF" | grep '\.dart$') + +if [ -z "$PR_FILES" ]; then + echo "you ain't got no diff (nothing lintable since $TARGET_DIFF)" + exit 0 +fi + +FAILED=false + +if ! dart format --output=none --set-exit-if-changed "$PR_FILES"; then + FAILED=true +fi + +CUSTOM_LINT_LOG=$(mktemp) +DART_LINT_LOG=$(mktemp) + +dart run custom_lint > "$CUSTOM_LINT_LOG" 2>&1 || true + +dart analyze > "$DART_LINT_LOG" 2>&1 || true + +for file in $PR_FILES; do + if grep -q "$file" "$CUSTOM_LINT_LOG"; then + grep -C 2 "$file" "$CUSTOM_LINT_LOG" + FAILED=true + fi + + if grep -q "$file" "$DART_LINT_LOG"; then + grep -C 2 "$file" "$DART_LINT_LOG" + FAILED=true + fi +done + +rm -rf "$CUSTOM_LINT_LOG" "$DART_LINT_LOG" + +if [ "$FAILED" = true ]; then + exit 1 +else + exit 0 +fi \ No newline at end of file diff --git a/pubspec_base.yaml b/pubspec_base.yaml index ff54ecaaf8..c463dadb72 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -185,8 +185,14 @@ dev_dependencies: url: https://github.com/cake-tech/google-translator.git version: 1.0.0 msix: ^3.16.9 + cw_custom_lints: + path: cw_custom_lints + custom_lint: 0.6.2 dependency_overrides: + rxdart: 0.28.0 + dart_style: 2.3.6 + analyzer: 6.4.1 bech32: git: url: https://github.com/cake-tech/bech32.git diff --git a/tool/append_translation.dart b/tool/append_translation.dart index 7232f308b9..1cc6336b85 100644 --- a/tool/append_translation.dart +++ b/tool/append_translation.dart @@ -15,7 +15,7 @@ void main(List 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 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!'); } \ No newline at end of file diff --git a/tool/download_moneroc_prebuilds.dart b/tool/download_moneroc_prebuilds.dart index a12777ad56..dee0461240 100644 --- a/tool/download_moneroc_prebuilds.dart +++ b/tool/download_moneroc_prebuilds.dart @@ -31,7 +31,7 @@ Future 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; for (var i = 0; i < assets.length; i++) { for (var triplet in triplets) { @@ -42,10 +42,10 @@ Future 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 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()); } } \ No newline at end of file diff --git a/tool/fiat_api_check.dart b/tool/fiat_api_check.dart index 5f3fe49078..c70fa33728 100755 --- a/tool/fiat_api_check.dart +++ b/tool/fiat_api_check.dart @@ -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> workingPairs = {}; final Map> 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 --- diff --git a/tool/generate_localization.dart b/tool/generate_localization.dart index 0e07dc2c35..6819cbd416 100644 --- a/tool/generate_localization.dart +++ b/tool/generate_localization.dart @@ -37,7 +37,7 @@ Future main(List 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 main(List args) async { final dir = Directory(dirPath); if (!await dir.exists()) { - printV('Wrong directory path: $dirPath'); + print('Wrong directory path: $dirPath'); return; } @@ -55,12 +55,12 @@ Future main(List args) async { final shortLocale = element.path.split('_',)[1].split('.')[0]; localePath[shortLocale] = element.path; } catch (e) { - printV('Wrong file: ${element.path}'); + print('Wrong file: ${element.path}'); } }); if (!localePath.keys.contains(defaultLocale)) { - printV("Locale list doesn't contain $defaultLocale"); + print("Locale list doesn't contain $defaultLocale"); return; } @@ -117,7 +117,7 @@ Future main(List args) async { await File(outputPath + localeListFileName).writeAsString(locales); } catch (e) { - printV(e.toString()); + print(e.toString()); } }); } diff --git a/tool/print_verbose_dummy.dart b/tool/print_verbose_dummy.dart index f7286e1f9f..e69de29bb2 100644 --- a/tool/print_verbose_dummy.dart +++ b/tool/print_verbose_dummy.dart @@ -1 +0,0 @@ -void printV(dynamic content) => print(content); \ No newline at end of file diff --git a/tool/translate_changelog.dart b/tool/translate_changelog.dart index e044cc2088..609c969a60 100644 --- a/tool/translate_changelog.dart +++ b/tool/translate_changelog.dart @@ -46,7 +46,7 @@ void main() async { }); currentItem++; - printV( + print( "\r$currentLang/${langs.length} langs done, $currentItem/${defaultLangChangelog.length} items done"); } currentLang++; diff --git a/tool/translate_using_llm.dart b/tool/translate_using_llm.dart index 3ca92d784d..e5c22efe1a 100644 --- a/tool/translate_using_llm.dart +++ b/tool/translate_using_llm.dart @@ -25,18 +25,18 @@ class TranslationChecker { final sourceMap = json.decode(sourceContent) as Map; final destinationMap = json.decode(destinationContent) as Map; - 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] : []) : 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 _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 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 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 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); } } diff --git a/tool/translation_add_lang.dart b/tool/translation_add_lang.dart index e3c372a8c7..3f509090e5 100644 --- a/tool/translation_add_lang.dart +++ b/tool/translation_add_lang.dart @@ -34,5 +34,5 @@ void main(List 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"); } diff --git a/tool/translation_consistence.dart b/tool/translation_consistence.dart index 2cdd358c8b..f3d3120b02 100644 --- a/tool/translation_consistence.dart +++ b/tool/translation_consistence.dart @@ -7,14 +7,14 @@ import 'utils/translation/translation_constants.dart'; import 'utils/translation/translation_utils.dart'; void main(List 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 args) async { final missingDefaults = {}; missingKeys.forEach((key) { - printV('Missing in "$lang": "$key"'); + print('Missing in "$lang": "$key"'); if (doFix) missingDefaults[key] = arbObj[key] as String; }); diff --git a/tool/utils/translation/arb_file_utils.dart b/tool/utils/translation/arb_file_utils.dart index 92a8f6e2e8..c8633c09cf 100644 --- a/tool/utils/translation/arb_file_utils.dart +++ b/tool/utils/translation/arb_file_utils.dart @@ -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; } diff --git a/tool/utils/translation/translation_utils.dart b/tool/utils/translation/translation_utils.dart index f53a8d13ab..4498e279a6 100644 --- a/tool/utils/translation/translation_utils.dart +++ b/tool/utils/translation/translation_utils.dart @@ -38,7 +38,7 @@ Future 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]; From ce86bb8258348262d1b8f43340c317e49c765432 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 12:40:21 +0200 Subject: [PATCH 02/47] move to builtin custom lint api --- analysis_options.yaml | 15 ++-- cw_custom_lints/lib/cw_custom_lints.dart | 15 ---- .../http_force_proxy_rule.dart | 85 +++++++++++-------- .../lib/print_verbose/print_verbose_fix.dart | 71 +++++++++------- .../lib/print_verbose/print_verbose_rule.dart | 66 +++++++------- .../restricted_imports_rule.dart | 80 +++++++++-------- cw_custom_lints/pubspec.yaml | 13 ++- cw_monero/pubspec.lock | 8 -- pubspec_base.yaml | 5 -- 9 files changed, 184 insertions(+), 174 deletions(-) delete mode 100644 cw_custom_lints/lib/cw_custom_lints.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index 50a92ca407..2fab48e342 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -17,8 +17,10 @@ analyzer: language: strict-casts: true strict-raw-types: true - plugins: - - custom_lint + +plugins: + cw_custom_lints: + path: cw_custom_lints linter: rules: @@ -83,8 +85,7 @@ linter: - prefer_is_empty - prefer_is_not_empty - prefer_is_not_operator - # TODO uncomment after we update flutter version to something that supports this rule - # - prefer_iterable_wheretype + - prefer_iterable_wheretype - prefer_null_aware_operators - prefer_spread_collections - prefer_typing_uninitialized_variables @@ -138,9 +139,3 @@ linter: formatter: page_width: 100 - -custom_lint: - debug: true - verbose: true - rules: - - use_print_v diff --git a/cw_custom_lints/lib/cw_custom_lints.dart b/cw_custom_lints/lib/cw_custom_lints.dart deleted file mode 100644 index 61571f530c..0000000000 --- a/cw_custom_lints/lib/cw_custom_lints.dart +++ /dev/null @@ -1,15 +0,0 @@ -import "package:custom_lint_builder/custom_lint_builder.dart"; -import "package:cw_custom_lints/http_force_proxy/http_force_proxy_rule.dart"; -import "package:cw_custom_lints/print_verbose/print_verbose_rule.dart"; -import "package:cw_custom_lints/restricted_imports/restricted_imports_rule.dart"; - -PluginBase createPlugin() => _CustomLintsPlugin(); - -class _CustomLintsPlugin extends PluginBase { - @override - List getLintRules(CustomLintConfigs configs) => [ - const PrintVerboseRule(), - const RestrictedImportsRule(), - const HttpForceProxyRule(), - ]; -} diff --git a/cw_custom_lints/lib/http_force_proxy/http_force_proxy_rule.dart b/cw_custom_lints/lib/http_force_proxy/http_force_proxy_rule.dart index 8d4a0f80eb..69d0ea7f7d 100644 --- a/cw_custom_lints/lib/http_force_proxy/http_force_proxy_rule.dart +++ b/cw_custom_lints/lib/http_force_proxy/http_force_proxy_rule.dart @@ -1,51 +1,62 @@ -import "package:analyzer/error/error.dart" hide LintCode; -import "package:analyzer/error/listener.dart"; -import "package:custom_lint_builder/custom_lint_builder.dart"; - -class HttpForceProxyRule extends DartLintRule { - const HttpForceProxyRule() : super(code: _code); - - static const _code = LintCode( - name: "no_http_imports", - problemMessage: - "Using the http package breaks proxy integration. Please use ProxyWrapper or alias it as \"very_insecure_http_do_not_use\".", - errorSeverity: ErrorSeverity.WARNING, +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 - void run( - CustomLintResolver resolver, - ErrorReporter reporter, - CustomLintContext context, + LintCode get diagnosticCode => code; + + @override + void registerNodeProcessors( + RuleVisitorRegistry registry, + RuleContext context, ) { - final filePath = resolver.source.fullName; + final filePath = context.definingUnit.file.path; if (filePath.endsWith("proxy_wrapper.dart")) { return; } - context.registry.addImportDirective((node) { - final uriString = node.uri.stringValue; - if (uriString == null) { + registry.addImportDirective(this, _Visitor(this)); + } +} + +class _Visitor extends SimpleAstVisitor { + _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; } - if (uriString.startsWith("package:http")) { - final prefixNode = node.prefix; - if (prefixNode != null && prefixNode.name == "very_insecure_http_do_not_use") { - return; - } - - reporter.reportError( - AnalysisError.forValues( - source: resolver.source, - offset: node.offset, - length: node.length, - errorCode: _code, - message: _code.problemMessage, - ), - ); - } - }); + rule.reportAtNode(node); + } } } diff --git a/cw_custom_lints/lib/print_verbose/print_verbose_fix.dart b/cw_custom_lints/lib/print_verbose/print_verbose_fix.dart index ae31f83793..b7a2daf52c 100644 --- a/cw_custom_lints/lib/print_verbose/print_verbose_fix.dart +++ b/cw_custom_lints/lib/print_verbose/print_verbose_fix.dart @@ -1,41 +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/error/error.dart" hide LintCode; -import "package:custom_lint_builder/custom_lint_builder.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()", + ); -class ReplaceWithPrintV extends DartFix { @override - void run( - CustomLintResolver resolver, - ChangeReporter reporter, - CustomLintContext context, - AnalysisError error, - List others, - ) { - context.registry.addMethodInvocation((node) { - const importString = "package:cw_core/utils/print_verbose.dart"; - - if (!error.sourceRange.intersects(node.sourceRange)) { - return; - } + CorrectionApplicability get applicability => + CorrectionApplicability.singleLocation; + + @override + FixKind get fixKind => _fixKind; - final root = node.root; - final hasImport = root is CompilationUnit && - root.directives.whereType().any( - (directive) => directive.uri.stringValue == importString, - ); + @override + Future compute(ChangeBuilder builder) async { + final invocation = node.thisOrAncestorOfType(); + if (invocation == null) { + return; + } - final changeBuilder = reporter.createChangeBuilder( - message: "Replace with printV()", - priority: 999999, - ); + final root = invocation.root; + final hasImport = root is CompilationUnit && + root.directives.whereType().any( + (directive) => directive.uri.stringValue == _importString, + ); - changeBuilder.addDartFileEdit((builder) { - builder.addSimpleReplacement(node.methodName.sourceRange, "printV"); + await builder.addDartFileEdit(file, (builder) { + builder.addSimpleReplacement( + range.node(invocation.methodName), + "printV", + ); - if (!hasImport) { - builder.importLibrary(Uri.parse(importString)); - } - }); + if (!hasImport) { + builder.importLibrary(Uri.parse(_importString)); + } }); } } diff --git a/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart b/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart index acee0b6079..743474e127 100644 --- a/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart +++ b/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart @@ -1,46 +1,52 @@ -import "package:analyzer/error/error.dart" hide LintCode; -import "package:analyzer/error/listener.dart"; -import "package:custom_lint_builder/custom_lint_builder.dart"; -import "package:cw_custom_lints/print_verbose/print_verbose_fix.dart"; +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 DartLintRule { - const PrintVerboseRule() : super(code: _code); +class PrintVerboseRule extends AnalysisRule { + PrintVerboseRule() + : super( + name: "use_print_v", + description: "Use printV() from cw_core instead of print().", + ); - static const _code = LintCode( - name: "use_print_v", - problemMessage: "Use printV() from cw_core instead", + static const LintCode code = LintCode( + "use_print_v", + "Use printV() from cw_core instead", correctionMessage: "Replace print with printV", - errorSeverity: ErrorSeverity.WARNING, + severity: DiagnosticSeverity.WARNING, ); @override - void run( - CustomLintResolver resolver, - ErrorReporter reporter, - CustomLintContext context, - ) { - final filePath = resolver.source.fullName; + LintCode get diagnosticCode => code; + + @override + void registerNodeProcessors( + RuleVisitorRegistry registry, + RuleContext context, + ) { + final filePath = context.definingUnit.file.path; if (filePath.contains("/tool/")) { // tool/ is allowed to use print as it never makes its way into the app return; } - context.registry.addMethodInvocation((node) { - if (node.methodName.name == "print" && node.target == null) { - reporter.reportError( - AnalysisError.forValues( - source: resolver.source, - offset: node.offset, - length: node.length, - errorCode: _code, - message: _code.problemMessage, - ), - ); - } - }); + registry.addMethodInvocation(this, _Visitor(this)); } +} + +class _Visitor extends SimpleAstVisitor { + _Visitor(this.rule); + + final AnalysisRule rule; @override - List getFixes() => [ReplaceWithPrintV()]; + void visitMethodInvocation(MethodInvocation node) { + if (node.methodName.name == "print" && node.target == null) { + rule.reportAtNode(node); + } + } } diff --git a/cw_custom_lints/lib/restricted_imports/restricted_imports_rule.dart b/cw_custom_lints/lib/restricted_imports/restricted_imports_rule.dart index 9ded21e405..80680af87f 100644 --- a/cw_custom_lints/lib/restricted_imports/restricted_imports_rule.dart +++ b/cw_custom_lints/lib/restricted_imports/restricted_imports_rule.dart @@ -1,15 +1,22 @@ -import "package:analyzer/error/error.dart" hide LintCode; -import "package:analyzer/error/listener.dart"; -import "package:custom_lint_builder/custom_lint_builder.dart"; +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 DartLintRule { - const RestrictedImportsRule() : super(code: _code); +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 _code = LintCode( - name: "no_restricted_imports_in_lib", - problemMessage: - "Do not import from coin-specific packages. If necessary, wire your logic through configure.dart", - errorSeverity: ErrorSeverity.ERROR, + 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 = { @@ -26,12 +33,14 @@ class RestrictedImportsRule extends DartLintRule { }; @override - void run( - CustomLintResolver resolver, - ErrorReporter reporter, - CustomLintContext context, + LintCode get diagnosticCode => code; + + @override + void registerNodeProcessors( + RuleVisitorRegistry registry, + RuleContext context, ) { - final filePath = resolver.source.fullName; + final filePath = context.definingUnit.file.path; final fileName = filePath.split("/").last; // ignore cw_something folders @@ -40,30 +49,31 @@ class RestrictedImportsRule extends DartLintRule { } // allow ex. cw_bitcoin in bitcoin.dart - if(_restrictedPackages.contains("cw_"+fileName.replaceAll(".dart", ""))) { + if (_restrictedPackages.contains("cw_" + fileName.replaceAll(".dart", ""))) { return; } - context.registry.addImportDirective((node) { - final uriString = node.uri.stringValue; - if (uriString == null || !uriString.startsWith("package:")) { - return; - } + registry.addImportDirective(this, _Visitor(this)); + } +} - final pathWithoutScheme = uriString.replaceFirst("package:", ""); - final packageName = pathWithoutScheme.split("/").first; +class _Visitor extends SimpleAstVisitor { + _Visitor(this.rule); - if (_restrictedPackages.contains(packageName)) { - reporter.reportError( - AnalysisError.forValues( - source: resolver.source, - offset: node.offset, - length: node.length, - errorCode: _code, - message: _code.problemMessage, - ), - ); - } - }); + 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); + } } } diff --git a/cw_custom_lints/pubspec.yaml b/cw_custom_lints/pubspec.yaml index a114588645..399fa59c67 100644 --- a/cw_custom_lints/pubspec.yaml +++ b/cw_custom_lints/pubspec.yaml @@ -1,8 +1,15 @@ name: cw_custom_lints version: 0.0.1 environment: - sdk: '>=3.0.0 <4.0.0' + sdk: '>=3.9.0 <4.0.0' + dependencies: - # FIXME update once we get rid of hive and therefore can move away from flutter 3.32 and analyzer v6 - custom_lint_builder: 0.6.2 \ No newline at end of file + 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 diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index 58652bc8c9..79da369441 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -333,14 +333,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" - source: hosted - version: "4.0.0" glob: dependency: transitive description: diff --git a/pubspec_base.yaml b/pubspec_base.yaml index e9d39f027f..683d69834d 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -184,14 +184,9 @@ dev_dependencies: url: https://github.com/cake-tech/google-translator.git version: 1.0.0 msix: ^3.16.9 - cw_custom_lints: - path: cw_custom_lints - custom_lint: 0.6.2 dependency_overrides: rxdart: 0.28.0 - dart_style: 2.3.6 - analyzer: 6.4.1 bech32: git: url: https://github.com/cake-tech/bech32.git From 6356db6ecda735f7bf3f2cbc96e4fdc5e851ffed Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 12:42:31 +0200 Subject: [PATCH 03/47] remove broken lint.sh --- lint.sh | 58 --------------------------------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 lint.sh diff --git a/lint.sh b/lint.sh deleted file mode 100644 index a20d347c9c..0000000000 --- a/lint.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -set -e - -CHECK_ONLY=false -TARGET_DIFF="HEAD" - -while [[ "$#" -gt 0 ]]; do - case $1 in - check) CHECK_ONLY=true; shift ;; - *) TARGET_DIFF="$1"; shift ;; - esac -done - -if [ $# -eq 0 ]; then - echo "warning: no target branch provided, cannot reliably determine diff. will only lint uncommitted files." - echo "recommended to use ./lint.sh [target_branch], for example ./lint.sh dev" -fi - -PR_FILES=$(git diff --name-only "$TARGET_DIFF" | grep '\.dart$') - -if [ -z "$PR_FILES" ]; then - echo "you ain't got no diff (nothing lintable since $TARGET_DIFF)" - exit 0 -fi - -FAILED=false - -if ! dart format --output=none --set-exit-if-changed "$PR_FILES"; then - FAILED=true -fi - -CUSTOM_LINT_LOG=$(mktemp) -DART_LINT_LOG=$(mktemp) - -dart run custom_lint > "$CUSTOM_LINT_LOG" 2>&1 || true - -dart analyze > "$DART_LINT_LOG" 2>&1 || true - -for file in $PR_FILES; do - if grep -q "$file" "$CUSTOM_LINT_LOG"; then - grep -C 2 "$file" "$CUSTOM_LINT_LOG" - FAILED=true - fi - - if grep -q "$file" "$DART_LINT_LOG"; then - grep -C 2 "$file" "$DART_LINT_LOG" - FAILED=true - fi -done - -rm -rf "$CUSTOM_LINT_LOG" "$DART_LINT_LOG" - -if [ "$FAILED" = true ]; then - exit 1 -else - exit 0 -fi \ No newline at end of file From 639347bdfdcac8f993732ab64db2e451b2aae8c9 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 13:09:09 +0200 Subject: [PATCH 04/47] remove use_decorated_box --- analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 2fab48e342..d79842bd5b 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -119,7 +119,6 @@ linter: - unrelated_type_equality_checks - use_build_context_synchronously - use_colored_box - - use_decorated_box - use_full_hex_values_for_flutter_colors - use_function_type_syntax_for_parameters - use_is_even_rather_than_modulo From 120699c3f7eec384b8c7beb834d5ceaf956f057c Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 14:06:04 +0200 Subject: [PATCH 05/47] connect lint_check ci to lint.sh --- .github/workflows/lint_check.yml | 35 +------------------------------- scripts/lint.sh | 21 ++++++++----------- 2 files changed, 9 insertions(+), 47 deletions(-) diff --git a/.github/workflows/lint_check.yml b/.github/workflows/lint_check.yml index 441ce5315e..cb7f3f38f3 100644 --- a/.github/workflows/lint_check.yml +++ b/.github/workflows/lint_check.yml @@ -20,37 +20,4 @@ jobs: - name: Incremental Format and Lint run: | - PR_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | grep '\.dart$' || true) - - if [ -z "$PR_FILES" ]; then - exit 0 - fi - - FAILED=false - - if ! dart format --output=none --set-exit-if-changed $PR_FILES; then - FAILED=true - fi - - dart run custom_lint > custom_lint_output 2>&1 || true - - for file in $PR_FILES; do - if grep -q "$file" custom_lint_output; then - grep -C 2 "$file" custom_lint_output - FAILED=true - fi - done - - dart analyze > dart_analyze_output 2>&1 || true - - for file in $PR_FILES; do - if grep -q "$file" dart_analyze_output; then - grep -C 2 "$file" dart_analyze_output - FAILED=true - fi - done - - if [ "$FAILED" = true ]; then - echo "ci failed because you didn't format or lint." - exit 1 - fi \ No newline at end of file + scripts/lint.sh \ No newline at end of file diff --git a/scripts/lint.sh b/scripts/lint.sh index c4b1b4e4f6..6b093f3af0 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -3,16 +3,11 @@ set -x -e cd $(dirname $0) cd .. -for i in cw_zcash; -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)" - exit 1 - fi - fi -done +dart fix --apply . +dart format --line-length=100 . +if [[ ! "x$ABORT_ON_CHANGE" == "x" ]]; then + if [[ ! -z "$(git status --porcelain -- $(find .))" ]]; then + echo "Please run scripts/lint.sh" + exit 1 + fi +fi From c83d53b6edd0b7ed256596ddd42aeb9e2642f14d Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 18:24:22 +0200 Subject: [PATCH 06/47] add typecast so app builds without disabling analyzer --- lib/bitcoin/cw_bitcoin.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 6f5b9bfa49..08361e0107 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -178,7 +178,7 @@ class CWBitcoin extends Bitcoin { List getSubAddresses(Object wallet) { final electrumWallet = wallet as ElectrumWallet; return electrumWallet.walletAddresses.addressesByReceiveType - .map((BaseBitcoinAddressRecord addr) => ElectrumSubAddress( + .map((addr) => ElectrumSubAddress( id: addr.index, name: addr.name, address: addr.address, From a6fff486148aa3b5177244ad41f648196e48d03a Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 18:25:49 +0200 Subject: [PATCH 07/47] remove broken analysis_options from cw_* packages --- cw_bitcoin_cash/analysis_options.yaml | 4 ---- cw_decred/analysis_options.yaml | 4 ---- cw_dogecoin/analysis_options.yaml | 4 ---- cw_evm/analysis_options.yaml | 4 ---- cw_monero/analysis_options.yaml | 4 ---- cw_mweb/analysis_options.yaml | 4 ---- cw_solana/analysis_options.yaml | 4 ---- cw_tron/analysis_options.yaml | 4 ---- cw_wownero/analysis_options.yaml | 4 ---- cw_zcash/analysis_options.yaml | 31 --------------------------- 10 files changed, 67 deletions(-) delete mode 100644 cw_bitcoin_cash/analysis_options.yaml delete mode 100644 cw_decred/analysis_options.yaml delete mode 100644 cw_dogecoin/analysis_options.yaml delete mode 100644 cw_evm/analysis_options.yaml delete mode 100644 cw_monero/analysis_options.yaml delete mode 100644 cw_mweb/analysis_options.yaml delete mode 100644 cw_solana/analysis_options.yaml delete mode 100644 cw_tron/analysis_options.yaml delete mode 100644 cw_wownero/analysis_options.yaml delete mode 100644 cw_zcash/analysis_options.yaml diff --git a/cw_bitcoin_cash/analysis_options.yaml b/cw_bitcoin_cash/analysis_options.yaml deleted file mode 100644 index a5744c1cfb..0000000000 --- a/cw_bitcoin_cash/analysis_options.yaml +++ /dev/null @@ -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 diff --git a/cw_decred/analysis_options.yaml b/cw_decred/analysis_options.yaml deleted file mode 100644 index a5744c1cfb..0000000000 --- a/cw_decred/analysis_options.yaml +++ /dev/null @@ -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 diff --git a/cw_dogecoin/analysis_options.yaml b/cw_dogecoin/analysis_options.yaml deleted file mode 100644 index a5744c1cfb..0000000000 --- a/cw_dogecoin/analysis_options.yaml +++ /dev/null @@ -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 diff --git a/cw_evm/analysis_options.yaml b/cw_evm/analysis_options.yaml deleted file mode 100644 index a5744c1cfb..0000000000 --- a/cw_evm/analysis_options.yaml +++ /dev/null @@ -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 diff --git a/cw_monero/analysis_options.yaml b/cw_monero/analysis_options.yaml deleted file mode 100644 index a5744c1cfb..0000000000 --- a/cw_monero/analysis_options.yaml +++ /dev/null @@ -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 diff --git a/cw_mweb/analysis_options.yaml b/cw_mweb/analysis_options.yaml deleted file mode 100644 index a5744c1cfb..0000000000 --- a/cw_mweb/analysis_options.yaml +++ /dev/null @@ -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 diff --git a/cw_solana/analysis_options.yaml b/cw_solana/analysis_options.yaml deleted file mode 100644 index a5744c1cfb..0000000000 --- a/cw_solana/analysis_options.yaml +++ /dev/null @@ -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 diff --git a/cw_tron/analysis_options.yaml b/cw_tron/analysis_options.yaml deleted file mode 100644 index a5744c1cfb..0000000000 --- a/cw_tron/analysis_options.yaml +++ /dev/null @@ -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 diff --git a/cw_wownero/analysis_options.yaml b/cw_wownero/analysis_options.yaml deleted file mode 100644 index a5744c1cfb..0000000000 --- a/cw_wownero/analysis_options.yaml +++ /dev/null @@ -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 diff --git a/cw_zcash/analysis_options.yaml b/cw_zcash/analysis_options.yaml deleted file mode 100644 index f43bd483da..0000000000 --- a/cw_zcash/analysis_options.yaml +++ /dev/null @@ -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 From b6ea25083300cd9b54a6f5bb48bae061a7ecb66b Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 18:38:38 +0200 Subject: [PATCH 08/47] remove unneeded dependency override --- pubspec_base.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 683d69834d..c5525007bc 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -186,7 +186,6 @@ dev_dependencies: msix: ^3.16.9 dependency_overrides: - rxdart: 0.28.0 bech32: git: url: https://github.com/cake-tech/bech32.git From 720f2d556f7088e8d82924c89f7fdd0ee1438472 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 18:58:49 +0200 Subject: [PATCH 09/47] fix stupid naming --- .github/workflows/lint_check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint_check.yml b/.github/workflows/lint_check.yml index cb7f3f38f3..a3162a685e 100644 --- a/.github/workflows/lint_check.yml +++ b/.github/workflows/lint_check.yml @@ -18,6 +18,6 @@ jobs: - name: Install dependencies run: flutter pub get - - name: Incremental Format and Lint + - name: Lint run: | scripts/lint.sh \ No newline at end of file From 9803d1217dd63c2d0d944252d52654d3ddbc644d Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 19:07:17 +0200 Subject: [PATCH 10/47] add configure to ci --- .github/workflows/lint_check.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/lint_check.yml b/.github/workflows/lint_check.yml index a3162a685e..4950a35163 100644 --- a/.github/workflows/lint_check.yml +++ b/.github/workflows/lint_check.yml @@ -15,6 +15,15 @@ jobs: with: channel: 'stable' + - 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 dependencies run: flutter pub get From 961dad15e61d6fd299163b3a99d041d806dbb265 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 19:11:03 +0200 Subject: [PATCH 11/47] move lint call to reusable-build.yml --- .github/workflows/lint_check.yml | 32 ---------------------------- .github/workflows/reusable-build.yml | 4 ++++ 2 files changed, 4 insertions(+), 32 deletions(-) delete mode 100644 .github/workflows/lint_check.yml diff --git a/.github/workflows/lint_check.yml b/.github/workflows/lint_check.yml deleted file mode 100644 index 4950a35163..0000000000 --- a/.github/workflows/lint_check.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: PR Formatting & Lint Check - -on: [pull_request] - -jobs: - fast_lint_check: - runs-on: ubuntu-24.04 - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - uses: subosito/flutter-action@v2 - with: - channel: 'stable' - - - 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 dependencies - run: flutter pub get - - - name: Lint - run: | - scripts/lint.sh \ No newline at end of file diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml index c6082d4e08..11deb659f0 100644 --- a/.github/workflows/reusable-build.yml +++ b/.github/workflows/reusable-build.yml @@ -144,6 +144,10 @@ jobs: run: | ./compile_graphics.sh + - name: Lint + run: | + scripts/lint.sh + - name: Rename app run: | sanitized_branch_name=${BRANCH_NAME#origin/} # Remove 'origin/' prefix if it exists From 064362bc32ba9b9b301110c3adf01d8e40bc9508 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 19:51:52 +0200 Subject: [PATCH 12/47] workaround weird analyzer bug by reordering linter rules --- analysis_options.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index d79842bd5b..6d258c10f4 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -76,7 +76,6 @@ linter: - prefer_double_quotes - prefer_expression_function_bodies - prefer_final_in_for_each - - prefer_final_locals - prefer_function_declarations_over_variables - prefer_if_null_operators - prefer_initializing_formals @@ -132,6 +131,7 @@ linter: - use_truncating_division - valid_regexps - void_checks + - prefer_final_locals From 676d24b769bafb10175628896beab66978031758 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 19:53:47 +0200 Subject: [PATCH 13/47] return to old lint.sh to not format deps in scripts --- scripts/lint.sh | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/scripts/lint.sh b/scripts/lint.sh index 6b093f3af0..a494c1cb9b 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -3,11 +3,16 @@ set -x -e cd $(dirname $0) cd .. -dart fix --apply . -dart format --line-length=100 . -if [[ ! "x$ABORT_ON_CHANGE" == "x" ]]; then - if [[ ! -z "$(git status --porcelain -- $(find .))" ]]; then - echo "Please run scripts/lint.sh" - exit 1 - fi -fi +for i in lib cw_zcash; +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)" + exit 1 + fi + fi +done From 4869f0bab0777ea9b784299bc9a9144eb8090b72 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:01:11 +0200 Subject: [PATCH 14/47] add super.key to BasePage constructor --- lib/src/screens/base_page.dart | 2 +- lib/src/screens/receive/anonpay_invoice_page.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/screens/base_page.dart b/lib/src/screens/base_page.dart index 4602c92b6d..73c7a88dc2 100644 --- a/lib/src/screens/base_page.dart +++ b/lib/src/screens/base_page.dart @@ -15,7 +15,7 @@ import 'package:flutter_mobx/flutter_mobx.dart'; enum AppBarStyle { regular, withShadow, transparent, completelyTransparent } abstract class BasePage extends StatelessWidget { - BasePage() : _scaffoldKey = GlobalKey(); + BasePage({super.key}) : _scaffoldKey = GlobalKey(); final GlobalKey _scaffoldKey; final Image closeButtonImage = Image.asset('assets/images/close_button.png'); diff --git a/lib/src/screens/receive/anonpay_invoice_page.dart b/lib/src/screens/receive/anonpay_invoice_page.dart index f71488b4d5..74f3da1d68 100644 --- a/lib/src/screens/receive/anonpay_invoice_page.dart +++ b/lib/src/screens/receive/anonpay_invoice_page.dart @@ -29,8 +29,8 @@ import 'package:shared_preferences/shared_preferences.dart'; class AnonPayInvoicePage extends BasePage { AnonPayInvoicePage( this.anonInvoicePageViewModel, - this.receiveOptionViewModel, - ) : _amountFocusNode = FocusNode() {} + this.receiveOptionViewModel, {super.key} + ) : _amountFocusNode = FocusNode(); final _nameController = TextEditingController(); final _emailController = TextEditingController(); From 780070021b90b834d066754bdf2b88db82653ea6 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:05:24 +0200 Subject: [PATCH 15/47] disable use_key lint because it's bugged --- analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 6d258c10f4..2b08e49a9a 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -121,7 +121,6 @@ linter: - use_full_hex_values_for_flutter_colors - use_function_type_syntax_for_parameters - use_is_even_rather_than_modulo - - use_key_in_widget_constructors - use_named_constants - use_null_aware_elements - use_raw_strings From 1e2be9005daddd2cfff60835320a7e9adc994d63 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:07:44 +0200 Subject: [PATCH 16/47] Revert "add super.key to BasePage constructor" This reverts commit 4869f0bab0777ea9b784299bc9a9144eb8090b72. --- lib/src/screens/base_page.dart | 2 +- lib/src/screens/receive/anonpay_invoice_page.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/screens/base_page.dart b/lib/src/screens/base_page.dart index 73c7a88dc2..4602c92b6d 100644 --- a/lib/src/screens/base_page.dart +++ b/lib/src/screens/base_page.dart @@ -15,7 +15,7 @@ import 'package:flutter_mobx/flutter_mobx.dart'; enum AppBarStyle { regular, withShadow, transparent, completelyTransparent } abstract class BasePage extends StatelessWidget { - BasePage({super.key}) : _scaffoldKey = GlobalKey(); + BasePage() : _scaffoldKey = GlobalKey(); final GlobalKey _scaffoldKey; final Image closeButtonImage = Image.asset('assets/images/close_button.png'); diff --git a/lib/src/screens/receive/anonpay_invoice_page.dart b/lib/src/screens/receive/anonpay_invoice_page.dart index 74f3da1d68..f71488b4d5 100644 --- a/lib/src/screens/receive/anonpay_invoice_page.dart +++ b/lib/src/screens/receive/anonpay_invoice_page.dart @@ -29,8 +29,8 @@ import 'package:shared_preferences/shared_preferences.dart'; class AnonPayInvoicePage extends BasePage { AnonPayInvoicePage( this.anonInvoicePageViewModel, - this.receiveOptionViewModel, {super.key} - ) : _amountFocusNode = FocusNode(); + this.receiveOptionViewModel, + ) : _amountFocusNode = FocusNode() {} final _nameController = TextEditingController(); final _emailController = TextEditingController(); From a78b4f004b8d397e3930ed19814595e6ee1b29d6 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:13:19 +0200 Subject: [PATCH 17/47] add cw_* to lint.sh --- scripts/lint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/lint.sh b/scripts/lint.sh index a494c1cb9b..df4842aafa 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -3,7 +3,7 @@ set -x -e cd $(dirname $0) cd .. -for i in lib 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/ From c1e52ede76e59d0a29e0d645c84bd8bf1cb9a067 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:15:03 +0200 Subject: [PATCH 18/47] remove obvious type lint because it's bugged again (thanks google!) --- analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 2b08e49a9a..379434474b 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -63,7 +63,6 @@ linter: - implicit_reopen - library_private_types_in_public_api - non_constant_identifier_names - - omit_obvious_local_variable_types - only_throw_errors - package_names - prefer_asserts_with_message From e8b5771f8ddcefbe4c772b7e9864536234aa8a7b Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:27:23 +0200 Subject: [PATCH 19/47] ABORT_ON_CHANGE --- .github/workflows/reusable-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml index 11deb659f0..50c52951d9 100644 --- a/.github/workflows/reusable-build.yml +++ b/.github/workflows/reusable-build.yml @@ -146,7 +146,7 @@ jobs: - name: Lint run: | - scripts/lint.sh + ABORT_ON_CHANGE=yeah scripts/lint.sh - name: Rename app run: | From 266c72a1ce7fccc539fdb69438f691ba34dd3230 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:36:43 +0200 Subject: [PATCH 20/47] exclude tool and cw_custom_lints from printV check --- .github/workflows/no_print_in_dart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/no_print_in_dart.yaml b/.github/workflows/no_print_in_dart.yaml index 507793bd81..69885c9b5c 100644 --- a/.github/workflows/no_print_in_dart.yaml +++ b/.github/workflows/no_print_in_dart.yaml @@ -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" From e59744389236dd98a3527dc0c4c4051e0db205de Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:38:19 +0200 Subject: [PATCH 21/47] exclude cw_custom_lints from http import check --- .github/workflows/no_http_imports.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/no_http_imports.yaml b/.github/workflows/no_http_imports.yaml index dad6821ac1..0bfca1d063 100644 --- a/.github/workflows/no_http_imports.yaml +++ b/.github/workflows/no_http_imports.yaml @@ -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 - \ No newline at end of file From 6022ebfc5a622e7561e75690c2154538c81783da Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:46:21 +0200 Subject: [PATCH 22/47] test add lint as separate action --- .github/workflows/lint.yml | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000000..cd6be5bd8f --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,54 @@ +name: Lint + +on: [pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build dependencies utilizing ghcr cache + run: | + env \ + CW_DOCKER_REGISTRY=ghcr.io/cake-tech/cake_wallet \ + CW_DOCKER_USE_CLOUD=true \ + ./scripts/android/docker/build.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: Compile graphics + run: | + ./compile_graphics.sh + + - name: Lint + run: | + ABORT_ON_CHANGE=yeah scripts/lint.sh \ No newline at end of file From 30cde78d4840e2d460c2fbe1a93de7e1d98184be Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:47:08 +0200 Subject: [PATCH 23/47] remove compile graphics from lint ci --- .github/workflows/lint.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index cd6be5bd8f..726b5c6653 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -45,10 +45,6 @@ jobs: run: | dart run tool/generate_localization.dart - - name: Compile graphics - run: | - ./compile_graphics.sh - - name: Lint run: | ABORT_ON_CHANGE=yeah scripts/lint.sh \ No newline at end of file From 1a77817cc8269107ba679214057a885796e0064c Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:49:03 +0200 Subject: [PATCH 24/47] add container info to ci --- .github/workflows/lint.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 726b5c6653..c2ccf143d5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,6 +5,29 @@ on: [pull_request] jobs: lint: runs-on: ubuntu-latest + 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: Log in to GitHub Container Registry uses: docker/login-action@v3 From cefd15ce639319bf35c840e0cf36875757851ded Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:55:18 +0200 Subject: [PATCH 25/47] fix --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c2ccf143d5..222c0c74f1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,7 +4,7 @@ on: [pull_request] jobs: lint: - runs-on: ubuntu-latest + runs-on: [Linux, amd64, android] container: image: ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly env: From 73c8a55472b8c77eab594c8fb14bbbdebcd556db Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 20:58:11 +0200 Subject: [PATCH 26/47] fix --- .github/workflows/lint.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 222c0c74f1..4e35a09f40 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,6 +2,9 @@ name: Lint on: [pull_request] +defaults: + run: + shell: bash jobs: lint: runs-on: [Linux, amd64, android] From 337c15fb694ff7d45aea8f46cab14d7506bc9360 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 21:25:15 +0200 Subject: [PATCH 27/47] format only files after te 29th --- scripts/lint.sh | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/scripts/lint.sh b/scripts/lint.sh index df4842aafa..30d43a32af 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -1,16 +1,13 @@ #!/bin/bash set -x -e -cd $(dirname $0) +cd "$(dirname "$0")" cd .. 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 + find "$i" -type f -name "*.dart" -newermt "2026-06-29 23:59:59" -exec bash -c 'dart fix --apply "$@" && dart format --line-length=100 "$@"' _ {} + + if [[ -n "$ABORT_ON_CHANGE" ]]; then + if [[ -n "$(git status --porcelain -- "$i")" ]]; then echo "Please run scripts/lint.sh ($i has changes)" exit 1 fi From 83f03c5be3bc7304ee46a90afa441cd930e4f722 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 21:33:55 +0200 Subject: [PATCH 28/47] git-based date check --- scripts/lint.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/lint.sh b/scripts/lint.sh index 30d43a32af..c7d16128ed 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -5,11 +5,21 @@ cd .. 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 - find "$i" -type f -name "*.dart" -newermt "2026-06-29 23:59:59" -exec bash -c 'dart fix --apply "$@" && dart format --line-length=100 "$@"' _ {} + + { + # files modified after the 29th and committed + git log --since="2026-06-29 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 + if [[ -f "$file" ]]; then + dart fix --apply "$file" && dart format --line-length=100 "$file" + fi + done + if [[ -n "$ABORT_ON_CHANGE" ]]; then if [[ -n "$(git status --porcelain -- "$i")" ]]; then echo "Please run scripts/lint.sh ($i has changes)" exit 1 fi fi -done +done \ No newline at end of file From 004327b89ef4f799259ccc041aeb0c79141453e2 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 22:18:26 +0200 Subject: [PATCH 29/47] remove lint from reusable-build.yml --- .github/workflows/reusable-build.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml index 50c52951d9..c6082d4e08 100644 --- a/.github/workflows/reusable-build.yml +++ b/.github/workflows/reusable-build.yml @@ -144,10 +144,6 @@ jobs: run: | ./compile_graphics.sh - - name: Lint - run: | - ABORT_ON_CHANGE=yeah scripts/lint.sh - - name: Rename app run: | sanitized_branch_name=${BRANCH_NAME#origin/} # Remove 'origin/' prefix if it exists From f596e4b0904e8dcfb53412bd8e43a6f588d4e361 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 22:24:30 +0200 Subject: [PATCH 30/47] move lint.sh out of scripts --- .github/workflows/lint.yml | 2 +- scripts/lint.sh => lint.sh | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename scripts/lint.sh => lint.sh (100%) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4e35a09f40..cd335aeae7 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -73,4 +73,4 @@ jobs: - name: Lint run: | - ABORT_ON_CHANGE=yeah scripts/lint.sh \ No newline at end of file + ABORT_ON_CHANGE=yeah lint.sh \ No newline at end of file diff --git a/scripts/lint.sh b/lint.sh similarity index 100% rename from scripts/lint.sh rename to lint.sh From e469bc48db19799a7c607082188c1c94c7bd2c52 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 22:28:39 +0200 Subject: [PATCH 31/47] ./ --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index cd335aeae7..9c0c15e738 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -73,4 +73,4 @@ jobs: - name: Lint run: | - ABORT_ON_CHANGE=yeah lint.sh \ No newline at end of file + ABORT_ON_CHANGE=yeah ./lint.sh \ No newline at end of file From 20ec6d3aad90153d2bc7c1b81a3f04e56c428b71 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 23:03:34 +0200 Subject: [PATCH 32/47] test fix ci --- scripts/android/docker/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/android/docker/build.sh b/scripts/android/docker/build.sh index 74e213799d..9900500a6e 100755 --- a/scripts/android/docker/build.sh +++ b/scripts/android/docker/build.sh @@ -50,7 +50,7 @@ img() { echo "$CW_DOCKER_REGISTRY:android-deps-${1}-$(tinysha "$SCRIPT_DIR/Dockerfile.${1}")-${2}" } -base_ver="latest" +base_ver="$(tinysha $REPO_ROOT/lint.sh)" torch_ver="$(tinysha $SCRIPT_DIR/Dockerfile.torch $REPO_ROOT/scripts/prepare_torch.sh $REPO_ROOT/scripts/android/build_torch.sh)" reown_ver=$(tinysha $SCRIPT_DIR/Dockerfile.reown $REPO_ROOT/scripts/prepare_reown.sh $REPO_ROOT/scripts/android/build_reown_deps.sh) bitbox_ver=$(tinysha $SCRIPT_DIR/Dockerfile.bitbox $REPO_ROOT/scripts/build_bitbox_flutter.sh) From 2228a9b50687f5f4bbc2f510676d51d258c76dfe Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 23:04:41 +0200 Subject: [PATCH 33/47] move lint.sh --- scripts/android/docker/build.sh | 2 +- lint.sh => scripts/lint.sh | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename lint.sh => scripts/lint.sh (100%) diff --git a/scripts/android/docker/build.sh b/scripts/android/docker/build.sh index 9900500a6e..ac7ebdc1ae 100755 --- a/scripts/android/docker/build.sh +++ b/scripts/android/docker/build.sh @@ -50,7 +50,7 @@ img() { echo "$CW_DOCKER_REGISTRY:android-deps-${1}-$(tinysha "$SCRIPT_DIR/Dockerfile.${1}")-${2}" } -base_ver="$(tinysha $REPO_ROOT/lint.sh)" +base_ver="$(tinysha $REPO_ROOT/scripts/lint.sh)" torch_ver="$(tinysha $SCRIPT_DIR/Dockerfile.torch $REPO_ROOT/scripts/prepare_torch.sh $REPO_ROOT/scripts/android/build_torch.sh)" reown_ver=$(tinysha $SCRIPT_DIR/Dockerfile.reown $REPO_ROOT/scripts/prepare_reown.sh $REPO_ROOT/scripts/android/build_reown_deps.sh) bitbox_ver=$(tinysha $SCRIPT_DIR/Dockerfile.bitbox $REPO_ROOT/scripts/build_bitbox_flutter.sh) diff --git a/lint.sh b/scripts/lint.sh similarity index 100% rename from lint.sh rename to scripts/lint.sh From 62c7edefe64aa34b97ed27159ee7b10f47f39995 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 23:20:50 +0200 Subject: [PATCH 34/47] move lint.sh --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 9c0c15e738..4e35a09f40 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -73,4 +73,4 @@ jobs: - name: Lint run: | - ABORT_ON_CHANGE=yeah ./lint.sh \ No newline at end of file + ABORT_ON_CHANGE=yeah scripts/lint.sh \ No newline at end of file From 7f3d15bfadcce60d3aed3f66c18f5c1f70dc37c9 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 29 Jun 2026 23:41:26 +0200 Subject: [PATCH 35/47] print all changed files --- scripts/lint.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/lint.sh b/scripts/lint.sh index c7d16128ed..0fcf8a7558 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -x -e +set -e cd "$(dirname "$0")" cd .. @@ -11,6 +11,7 @@ do # 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 From df4e8432e343917c08882612308946a1c905e85b Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Tue, 30 Jun 2026 00:02:33 +0200 Subject: [PATCH 36/47] fix ci hopefully --- scripts/android/docker/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/android/docker/build.sh b/scripts/android/docker/build.sh index ac7ebdc1ae..a664c63553 100755 --- a/scripts/android/docker/build.sh +++ b/scripts/android/docker/build.sh @@ -50,7 +50,7 @@ img() { echo "$CW_DOCKER_REGISTRY:android-deps-${1}-$(tinysha "$SCRIPT_DIR/Dockerfile.${1}")-${2}" } -base_ver="$(tinysha $REPO_ROOT/scripts/lint.sh)" +base_ver="latest $(tinysha $REPO_ROOT/scripts/lint.sh)" torch_ver="$(tinysha $SCRIPT_DIR/Dockerfile.torch $REPO_ROOT/scripts/prepare_torch.sh $REPO_ROOT/scripts/android/build_torch.sh)" reown_ver=$(tinysha $SCRIPT_DIR/Dockerfile.reown $REPO_ROOT/scripts/prepare_reown.sh $REPO_ROOT/scripts/android/build_reown_deps.sh) bitbox_ver=$(tinysha $SCRIPT_DIR/Dockerfile.bitbox $REPO_ROOT/scripts/build_bitbox_flutter.sh) From 5f610cdf34b6f59a0e6feda3b45efef2a5b3b8dc Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Tue, 30 Jun 2026 00:07:29 +0200 Subject: [PATCH 37/47] revert --- scripts/android/docker/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/android/docker/build.sh b/scripts/android/docker/build.sh index a664c63553..74e213799d 100755 --- a/scripts/android/docker/build.sh +++ b/scripts/android/docker/build.sh @@ -50,7 +50,7 @@ img() { echo "$CW_DOCKER_REGISTRY:android-deps-${1}-$(tinysha "$SCRIPT_DIR/Dockerfile.${1}")-${2}" } -base_ver="latest $(tinysha $REPO_ROOT/scripts/lint.sh)" +base_ver="latest" torch_ver="$(tinysha $SCRIPT_DIR/Dockerfile.torch $REPO_ROOT/scripts/prepare_torch.sh $REPO_ROOT/scripts/android/build_torch.sh)" reown_ver=$(tinysha $SCRIPT_DIR/Dockerfile.reown $REPO_ROOT/scripts/prepare_reown.sh $REPO_ROOT/scripts/android/build_reown_deps.sh) bitbox_ver=$(tinysha $SCRIPT_DIR/Dockerfile.bitbox $REPO_ROOT/scripts/build_bitbox_flutter.sh) From 8bf8fa2f8c3d11e1e2de76451ac8ad33fc10537a Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Tue, 30 Jun 2026 00:09:24 +0200 Subject: [PATCH 38/47] try ci without cache --- .github/workflows/lint.yml | 42 ++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4e35a09f40..41dc5ef3c8 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -32,19 +32,39 @@ jobs: api-level: [ 29 ] steps: - - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - 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 + mkdir torch_dart + pushd torch_dart + tar -xzf ../torch_dart.tar.gz + popd + rm ./torch_dart.tar.gz + popd - - name: Build dependencies utilizing ghcr cache + - name: Fetch prebuilt Reown run: | - env \ - CW_DOCKER_REGISTRY=ghcr.io/cake-tech/cake_wallet \ - CW_DOCKER_USE_CLOUD=true \ - ./scripts/android/docker/build.sh + 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: Execute Build and Setup Commands run: | From 800eda6e2be966fe4016a334c6a27aae045cf713 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Tue, 30 Jun 2026 00:13:07 +0200 Subject: [PATCH 39/47] fix torch, apparently --- .github/workflows/lint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 41dc5ef3c8..b7d7160836 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -43,6 +43,7 @@ jobs: 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 From 904da2b10e8238c70e7ca54872fa0955ca65d743 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Tue, 30 Jun 2026 00:19:55 +0200 Subject: [PATCH 40/47] nicer logging --- scripts/lint.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/lint.sh b/scripts/lint.sh index 0fcf8a7558..c2714b87e8 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -18,8 +18,10 @@ do done if [[ -n "$ABORT_ON_CHANGE" ]]; then - if [[ -n "$(git status --porcelain -- "$i")" ]]; then - echo "Please run scripts/lint.sh ($i has changes)" + if [[ -n "$(git status --porcelain -- $(find $i))" ]]; then + echo "Please run scripts/lint.sh" + echo "changes in $i:" + git status --porcelain -- "$i" exit 1 fi fi From 48110d2796f009f9e91ad6a88e119667b962391e Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Tue, 30 Jun 2026 00:21:50 +0200 Subject: [PATCH 41/47] add bitbox --- .github/workflows/lint.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b7d7160836..4c2409cd72 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -67,6 +67,19 @@ jobs: rm ./reown_flutter.tar.gz popd + - name: Build Bitbox Flutter + run: | + set -x -e + pushd scripts + ./build_bitbox_flutter.sh + popd + - name: Build Zcash Lib + run: | + set -x -e + pushd scripts/android + ./build_zcash.sh + popd + - name: Execute Build and Setup Commands run: | pushd scripts/android From 53ac8e0bba8b43fcd27f4da774ce786eb187a66b Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Tue, 30 Jun 2026 00:22:42 +0200 Subject: [PATCH 42/47] remove zec --- .github/workflows/lint.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4c2409cd72..12fc6cb868 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -73,12 +73,6 @@ jobs: pushd scripts ./build_bitbox_flutter.sh popd - - name: Build Zcash Lib - run: | - set -x -e - pushd scripts/android - ./build_zcash.sh - popd - name: Execute Build and Setup Commands run: | From 54ad7563924f60b3bf335c2d8681e2ad8158cfb1 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Tue, 30 Jun 2026 00:32:24 +0200 Subject: [PATCH 43/47] add zec prep-only --- .github/workflows/lint.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 12fc6cb868..bdcd36a4cc 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -74,6 +74,11 @@ jobs: ./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 From a3897be044d7ee3effed73d8facb3528c8c8adef Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Tue, 30 Jun 2026 00:43:31 +0200 Subject: [PATCH 44/47] only detect changes in dart files --- scripts/lint.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/lint.sh b/scripts/lint.sh index c2714b87e8..2c73c051d7 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -18,11 +18,13 @@ do done if [[ -n "$ABORT_ON_CHANGE" ]]; then - if [[ -n "$(git status --porcelain -- $(find $i))" ]]; 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:" - git status --porcelain -- "$i" + echo "$DART_CHANGES" exit 1 fi fi -done \ No newline at end of file +done From 6d702ece11643d857e9827ddeb094660050bb647 Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Tue, 30 Jun 2026 22:07:23 +0200 Subject: [PATCH 45/47] add main.dart --- cw_custom_lints/lib/main.dart | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 cw_custom_lints/lib/main.dart diff --git a/cw_custom_lints/lib/main.dart b/cw_custom_lints/lib/main.dart new file mode 100644 index 0000000000..39e07ba30a --- /dev/null +++ b/cw_custom_lints/lib/main.dart @@ -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); + } +} From 6920430036f48cab408346187546a3447d596d8f Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Wed, 8 Jul 2026 16:50:35 +0200 Subject: [PATCH 46/47] update lints --- analysis_options.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/analysis_options.yaml b/analysis_options.yaml index 379434474b..70e87faf31 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -130,6 +130,9 @@ linter: - valid_regexps - void_checks - prefer_final_locals + - prefer_interpolation_to_compose_strings + - null_closures + - no_wildcard_variable_uses From 990adc18d16c4a991844c9bc2c642a1d553c907b Mon Sep 17 00:00:00 2001 From: Robert Malikowski Date: Mon, 13 Jul 2026 17:00:01 +0200 Subject: [PATCH 47/47] fix printV warnings being displayed when editing printV --- cw_custom_lints/lib/print_verbose/print_verbose_rule.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart b/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart index 743474e127..0fee39bc62 100644 --- a/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart +++ b/cw_custom_lints/lib/print_verbose/print_verbose_rule.dart @@ -29,7 +29,7 @@ class PrintVerboseRule extends AnalysisRule { ) { final filePath = context.definingUnit.file.path; - if (filePath.contains("/tool/")) { + 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; }