From 29496ffdb996b41d609e1abb241cd320c07ac6fa Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Mon, 6 Oct 2025 13:38:41 -0700 Subject: [PATCH 1/2] Improve static analysis, new lints, add pana, fix #64 --- .github/workflows/general.yml | 6 ++++++ analysis_options.yaml | 24 +++++++++++++++++++++--- example/counter.dart | 10 +++++++--- example/main.dart | 8 ++++++-- lib/src/quiesce_objector.dart | 23 ++++++++--------------- lib/src/test.dart | 1 + lib/src/tracker.dart | 2 +- pubspec.yaml | 2 +- test/test_test.dart | 2 +- test/tracker_test.dart | 1 + test/waiter_test.dart | 12 ++++++------ tool/gh_actions/install_pana.sh | 12 ++++++++++++ tool/gh_actions/pana_source.sh | 14 ++++++++++++++ 13 files changed, 85 insertions(+), 32 deletions(-) create mode 100755 tool/gh_actions/install_pana.sh create mode 100755 tool/gh_actions/pana_source.sh diff --git a/.github/workflows/general.yml b/.github/workflows/general.yml index e196908..1f083a3 100644 --- a/.github/workflows/general.yml +++ b/.github/workflows/general.yml @@ -34,6 +34,9 @@ jobs: - name: Setup Dart uses: dart-lang/setup-dart@v1 + - name: Setup Pana source analysis + run: tool/gh_actions/install_pana.sh + - name: Install project dependencies run: tool/gh_actions/install_dependencies.sh @@ -43,6 +46,9 @@ jobs: - name: Analyze project source run: tool/gh_actions/analyze_source.sh + - name: Run Pana on project source + run: tool/gh_actions/pana_source.sh + - name: Check project documentation run: tool/gh_actions/generate_documentation.sh diff --git a/analysis_options.yaml b/analysis_options.yaml index eb356ac..a0e8023 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -31,9 +31,10 @@ linter: - avoid_field_initializers_in_const_classes - avoid_final_parameters - avoid_function_literals_in_foreach_calls + - avoid_futureor_void - avoid_implementing_value_types - avoid_init_to_null - # - avoid_js_rounded_ints + - avoid_js_rounded_ints - avoid_multiple_declarations_per_line - avoid_null_checks_in_equality_operators - avoid_positional_boolean_parameters @@ -78,6 +79,7 @@ linter: - directives_ordering - discarded_futures - do_not_use_environment + - document_ignores - empty_catches - empty_constructor_bodies - empty_statements @@ -90,6 +92,7 @@ linter: - implicit_call_tearoffs - implicit_reopen - invalid_case_patterns + - invalid_runtime_check_with_js_interop_types - join_return_with_assignment - leading_newlines_in_multiline_strings - library_annotations @@ -99,6 +102,7 @@ linter: - lines_longer_than_80_chars - literal_only_boolean_expressions - matching_super_parameters + - missing_code_block_language_in_doc_comment - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_default_cases @@ -115,10 +119,11 @@ linter: - null_check_on_nullable_type_parameter - null_closures - omit_local_variable_types + - omit_obvious_local_variable_types + # - omit_obvious_property_types - one_member_abstracts - only_throw_errors - overridden_fields - - package_api_docs - package_names - package_prefixed_library_names - parameter_assignments @@ -173,6 +178,11 @@ linter: # - sort_constructors_first - sort_pub_dependencies - sort_unnamed_constructors_first + # conflicts with omit_obvious_local_variable_types + # - specify_nonobvious_local_variable_types + # - specify_nonobvious_property_types + - strict_top_level_inference + - switch_on_type - test_types_in_equals - throw_in_finally - tighten_type_of_initializing_formals @@ -180,6 +190,8 @@ linter: - type_init_formals - type_literal_in_constant_pattern - unawaited_futures + - unintended_html_in_doc_comment + - unnecessary_async - unnecessary_await_in_return - unnecessary_brace_in_string_interps - unnecessary_breaks @@ -187,9 +199,11 @@ linter: - unnecessary_constructor_name # - unnecessary_final - unnecessary_getters_setters + - unnecessary_ignore - unnecessary_lambdas - unnecessary_late - unnecessary_library_directive + - unnecessary_library_name - unnecessary_new - unnecessary_null_aware_assignments - unnecessary_null_aware_operator_on_extension_on_nullable @@ -204,9 +218,11 @@ linter: - unnecessary_string_interpolations - unnecessary_this - unnecessary_to_list_in_spreads + - unnecessary_unawaited + - unnecessary_underscores # - unreachable_from_main - unrelated_type_equality_checks - - unsafe_html + - unsafe_variance - use_build_context_synchronously - use_colored_box - use_decorated_box @@ -218,6 +234,7 @@ linter: - use_key_in_widget_constructors - use_late_for_private_fields_and_variables - use_named_constants + - use_null_aware_elements - use_raw_strings - use_rethrow_when_possible - use_setters_to_change_properties @@ -226,5 +243,6 @@ linter: - use_super_parameters - use_test_throws_matchers - use_to_and_as_if_applicable + - use_truncating_division - valid_regexps - void_checks diff --git a/example/counter.dart b/example/counter.dart index 95ad96c..78b699c 100644 --- a/example/counter.dart +++ b/example/counter.dart @@ -20,16 +20,20 @@ class CounterInterface extends Interface { final int width; CounterInterface({this.width = 8}) { - setPorts([Port('en'), Port('reset')], [CounterDirection.inward]); + setPorts( + [Logic.port('en'), Logic.port('reset')], [CounterDirection.inward]); setPorts([ - Port('val', width), + Logic.port('val', width), ], [ CounterDirection.outward ]); - setPorts([Port('clk')], [CounterDirection.misc]); + setPorts([Logic.port('clk')], [CounterDirection.misc]); } + + @override + CounterInterface clone() => CounterInterface(width: width); } /// A simple counter which increments once per `clk` edge whenever diff --git a/example/main.dart b/example/main.dart index 0e0fdb1..b695973 100644 --- a/example/main.dart +++ b/example/main.dart @@ -198,6 +198,7 @@ class CounterSequence extends Sequence { class CounterSeqItem extends SequenceItem { final bool _enable; + // We use a positional bool since that's the whole value of this item. // ignore: avoid_positional_boolean_parameters CounterSeqItem(this._enable); @@ -226,8 +227,11 @@ class CounterDriver extends Driver { // Listen to new items coming from the sequencer, and add them to a queue sequencer.stream.listen((newItem) { - _driverObjection ??= phase.raiseObjection('counter_driver') - ..dropped.then((value) => logger.fine('Driver objection dropped')); + _driverObjection ??= phase.raiseObjection('counter_driver'); + + unawaited(_driverObjection!.dropped + .then((value) => logger.fine('Driver objection dropped'))); + _pendingItems.add(newItem); }); diff --git a/lib/src/quiesce_objector.dart b/lib/src/quiesce_objector.dart index a095cb5..6473763 100644 --- a/lib/src/quiesce_objector.dart +++ b/lib/src/quiesce_objector.dart @@ -78,8 +78,7 @@ class QuiesceObjector extends Component { /// Actually drop the objection, with whatever bookkeeping is required. void _doDrop() { - // ignore: discarded_futures - _pendingTimeout?.cancel(); + unawaited(_pendingTimeout?.cancel()); _pendingTimeout = null; _objection?.drop(); @@ -89,11 +88,9 @@ class QuiesceObjector extends Component { /// Drop the objection, pending a [dropDelay] if it is provided. void dropObjection() { if (dropDelay != null) { - // ignore: discarded_futures - _pendingDrop?.cancel(); + unawaited(_pendingDrop?.cancel()); logger.finest( 'Planning to drop objection after delay if nothing stops it.'); - // ignore: discarded_futures _pendingDrop = CancelableOperation.fromFuture(dropDelay!(), onCancel: () => logger.finest('Cancelling objection drop.')); _pendingDrop!.then((_) => _doDrop()); @@ -110,22 +107,18 @@ class QuiesceObjector extends Component { throw Exception('Cannot raise objection before run phase.'); } - // ignore: discarded_futures - _pendingDrop?.cancel(); + unawaited(_pendingDrop?.cancel()); _pendingDrop = null; - _objection ??= _runPhase!.raiseObjection('quiesce') - // ignore: discarded_futures - ..dropped.then((value) => logger.finest('Quiesce objection dropped')); + _objection ??= _runPhase!.raiseObjection('quiesce'); + + unawaited(_objection!.dropped + .then((value) => logger.finest('Quiesce objection dropped'))); if (timeout != null) { - // ignore: discarded_futures - _pendingTimeout?.cancel(); - // ignore: discarded_futures + unawaited(_pendingTimeout?.cancel()); _pendingTimeout = CancelableOperation.fromFuture( - // ignore: discarded_futures timeout!(), - // onCancel: () => logger.finest('Timeout avoided!'), ); _pendingTimeout!.then((_) => logger.severe('Objection has timed out!')); } diff --git a/lib/src/test.dart b/lib/src/test.dart index b1e73b4..af7464b 100644 --- a/lib/src/test.dart +++ b/lib/src/test.dart @@ -119,6 +119,7 @@ abstract class Test extends Component { /// Prints a message to `stdout`, guarded by the [printLevel]. void _testPrint(String message, Level messageLevel) { if (messageLevel >= printLevel) { + // This is for logging purposes, so we actually do want to print. // ignore: avoid_print print(message); } diff --git a/lib/src/tracker.dart b/lib/src/tracker.dart index 75cda81..4973d61 100644 --- a/lib/src/tracker.dart +++ b/lib/src/tracker.dart @@ -64,7 +64,7 @@ abstract class Trackable { /// formats. /// /// By default, [Tracker] outputs to both a ASCII table format -/// (.tracker.log) and a JSON format (.tracker.json). +/// (`.tracker.log`) and a JSON format (`.tracker.json`). class Tracker { /// An optional output directory for the logs. /// diff --git a/pubspec.yaml b/pubspec.yaml index dd145d1..e4b8a20 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: async: ^2.11.0 logging: ^1.0.1 meta: ^1.3.0 - rohd: ^0.6.0 + rohd: ^0.6.4 dev_dependencies: test: ^1.17.3 diff --git a/test/test_test.dart b/test/test_test.dart index f39c28b..189c403 100644 --- a/test/test_test.dart +++ b/test/test_test.dart @@ -187,7 +187,7 @@ void main() { } }); - Simulator.registerEndOfSimulationAction(() async { + Simulator.registerEndOfSimulationAction(() { throw Exception('endofsim'); }); diff --git a/test/tracker_test.dart b/test/tracker_test.dart index 562c44e..316f29a 100644 --- a/test/tracker_test.dart +++ b/test/tracker_test.dart @@ -7,6 +7,7 @@ // 2021 December 6 // Author: Max Korbel +// We're dealing with and testing json long strings, so ignore these for here. // ignore_for_file: lines_longer_than_80_chars, avoid_dynamic_calls import 'dart:convert'; diff --git a/test/waiter_test.dart b/test/waiter_test.dart index 043e964..ccb32b1 100644 --- a/test/waiter_test.dart +++ b/test/waiter_test.dart @@ -44,10 +44,10 @@ void main() { Simulator.registerAction(18, () { // 25, 35, 45 - clk.waitCycles(3).then((value) { + unawaited(clk.waitCycles(3).then((value) { expect(Simulator.time, 45); checkHappened = true; - }); + })); }); unawaited(Simulator.run()); @@ -62,10 +62,10 @@ void main() { Simulator.registerAction(18, () { // 20, 30, 40 - clk.waitCycles(3, edge: Edge.neg).then((value) { + unawaited(clk.waitCycles(3, edge: Edge.neg).then((value) { expect(Simulator.time, 40); checkHappened = true; - }); + })); }); unawaited(Simulator.run()); @@ -80,10 +80,10 @@ void main() { Simulator.registerAction(18, () { // 20, 25, 30 - clk.waitCycles(3, edge: Edge.any).then((value) { + unawaited(clk.waitCycles(3, edge: Edge.any).then((value) { expect(Simulator.time, 30); checkHappened = true; - }); + })); }); unawaited(Simulator.run()); diff --git a/tool/gh_actions/install_pana.sh b/tool/gh_actions/install_pana.sh new file mode 100755 index 0000000..d934c20 --- /dev/null +++ b/tool/gh_actions/install_pana.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause +# +# install_pana.sh +# GitHub Actions step: Install pana dart analysis. +# +# 2025 September 26 +# Author: Desmond A. Kirkpatrick + +dart pub global activate pana diff --git a/tool/gh_actions/pana_source.sh b/tool/gh_actions/pana_source.sh new file mode 100755 index 0000000..7f36d92 --- /dev/null +++ b/tool/gh_actions/pana_source.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Copyright (C) 2025 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause +# +# pana_source.sh +# GitHub Actions step: execute pana analysis on project source. +# +# 2025 September 26 +# Author: Desmond A. Kirkpatrick + +PATH="$PATH":"$HOME/.pub-cache/bin" + +pana --exit-code-threshold 0 . From 92aae919c18a1f88b2639a4e1321a6f4eabdcc7c Mon Sep 17 00:00:00 2001 From: "Korbel, Max" Date: Mon, 6 Oct 2025 13:48:29 -0700 Subject: [PATCH 2/2] update copyright years --- README.md | 2 +- example/counter.dart | 2 +- example/main.dart | 2 +- lib/src/quiesce_objector.dart | 2 +- lib/src/test.dart | 2 +- lib/src/tracker.dart | 2 +- test/test_test.dart | 2 +- test/tracker_test.dart | 2 +- test/waiter_test.dart | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 5cd6c5f..bec35c3 100644 --- a/README.md +++ b/README.md @@ -105,5 +105,5 @@ ROHD-VF comes with a flexible [`Tracker`](https://intel.github.io/rohd-vf/rohd_v 2021 November 9 Author: Max Korbel <> -Copyright (C) 2021-2023 Intel Corporation +Copyright (C) 2021-2025 Intel Corporation SPDX-License-Identifier: BSD-3-Clause diff --git a/example/counter.dart b/example/counter.dart index 78b699c..78f4061 100644 --- a/example/counter.dart +++ b/example/counter.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2023 Intel Corporation +// Copyright (C) 2021-2025 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // counter.dart diff --git a/example/main.dart b/example/main.dart index b695973..f90d7ca 100644 --- a/example/main.dart +++ b/example/main.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2023 Intel Corporation +// Copyright (C) 2021-2025 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // main.dart diff --git a/lib/src/quiesce_objector.dart b/lib/src/quiesce_objector.dart index 6473763..6d072de 100644 --- a/lib/src/quiesce_objector.dart +++ b/lib/src/quiesce_objector.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2023 Intel Corporation +// Copyright (C) 2023-2025 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // quiesce_objector.dart diff --git a/lib/src/test.dart b/lib/src/test.dart index af7464b..d12dd9a 100644 --- a/lib/src/test.dart +++ b/lib/src/test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2023 Intel Corporation +// Copyright (C) 2021-2025 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // test.dart diff --git a/lib/src/tracker.dart b/lib/src/tracker.dart index 4973d61..01e4776 100644 --- a/lib/src/tracker.dart +++ b/lib/src/tracker.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2023 Intel Corporation +// Copyright (C) 2021-2025 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // tracker.dart diff --git a/test/test_test.dart b/test/test_test.dart index 189c403..e8aa09c 100644 --- a/test/test_test.dart +++ b/test/test_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2022-2023 Intel Corporation +// Copyright (C) 2022-2025 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // test_test.dart diff --git a/test/tracker_test.dart b/test/tracker_test.dart index 316f29a..c2eb214 100644 --- a/test/tracker_test.dart +++ b/test/tracker_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2021-2023 Intel Corporation +// Copyright (C) 2021-2025 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // tracker_test.dart diff --git a/test/waiter_test.dart b/test/waiter_test.dart index ccb32b1..6526248 100644 --- a/test/waiter_test.dart +++ b/test/waiter_test.dart @@ -1,4 +1,4 @@ -// Copyright (C) 2023 Intel Corporation +// Copyright (C) 2023-2025 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // waiter_test.dart