From 78c7efaba87abd2e3b808e71240281ea9447ced2 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Wed, 19 Aug 2026 22:27:52 -0700 Subject: [PATCH 01/17] Migrate active packages to pub workspace Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .devcontainer/devcontainer.json | 2 +- .github/workflows/build_devtool.yml | 5 +- .github/workflows/coverage.yml | 6 + .github/workflows/general.yml | 18 ++- CHANGELOG.md | 24 ++++ CONTRIBUTING.md | 93 +++++++++++- analysis_options.yaml | 7 + packages/rohd_hierarchy/analysis_options.yaml | 9 ++ packages/rohd_hierarchy/pubspec.yaml | 4 +- packages/rohd_waveform/analysis_options.yaml | 9 ++ packages/rohd_waveform/pubspec.yaml | 10 +- pubspec.yaml | 9 +- rohd-multipackage.code-workspace | 7 +- rohd_devtools_extension/analysis_options.yaml | 8 ++ .../analysis_options.yaml | 9 ++ .../rohd_devtools_widgets/pubspec.yaml | 8 +- rohd_devtools_extension/pubspec.yaml | 9 +- rohd_extension/dart/pubspec.yaml | 5 +- tool/gh_actions/analyze_source.sh | 9 +- tool/gh_actions/devtool/install_devtools.sh | 2 - tool/gh_actions/devtool/run_devtool_test.sh | 4 +- tool/gh_actions/install_dependencies.sh | 13 +- tool/gh_actions/run_tests.sh | 16 ++- tool/gh_codespaces/install_flutter.sh | 36 +++++ tool/gh_codespaces/run_setup.sh | 6 +- tool/workspace.dart | 136 ++++++++++++++++++ 26 files changed, 416 insertions(+), 48 deletions(-) create mode 100755 tool/gh_codespaces/install_flutter.sh create mode 100644 tool/workspace.dart diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 12e172c74..dd4d9d280 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,7 +4,7 @@ { "image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04", - "updateContentCommand": "tool/gh_codespaces/run_setup.sh", + "postCreateCommand": "tool/gh_codespaces/run_setup.sh", "customizations": { "codespaces": { diff --git a/.github/workflows/build_devtool.yml b/.github/workflows/build_devtool.yml index 6263bb692..d88476cd6 100644 --- a/.github/workflows/build_devtool.yml +++ b/.github/workflows/build_devtool.yml @@ -22,7 +22,10 @@ jobs: uses: flutter-actions/setup-flutter@v2 with: channel: stable - version: 3.29.0 + version: 3.47.0 + + - name: Install project dependencies + run: tool/gh_actions/install_dependencies.sh - name: Run Flutter Test run: tool/gh_actions/devtool/run_devtool_test.sh diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ef6dbffd0..9a275cfc4 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,6 +23,12 @@ jobs: - name: Setup Dart uses: dart-lang/setup-dart@v1 + - name: Setup Flutter + uses: flutter-actions/setup-flutter@v2 + with: + channel: stable + version: 3.47.0 + - name: Install dependencies run: tool/gh_actions/install_dependencies.sh diff --git a/.github/workflows/general.yml b/.github/workflows/general.yml index f2ed2cf65..6948f8c34 100644 --- a/.github/workflows/general.yml +++ b/.github/workflows/general.yml @@ -35,6 +35,12 @@ jobs: - name: Setup Dart uses: dart-lang/setup-dart@v1 + - name: Setup Flutter + uses: flutter-actions/setup-flutter@v2 + with: + channel: stable + version: 3.47.0 + - name: Setup Node uses: actions/setup-node@v4 with: @@ -88,6 +94,12 @@ jobs: - name: Setup Dart uses: dart-lang/setup-dart@v1 + - name: Setup Flutter + uses: flutter-actions/setup-flutter@v2 + with: + channel: stable + version: 3.47.0 + - name: Install project dependencies run: tool/gh_actions/install_dependencies.sh @@ -111,7 +123,10 @@ jobs: uses: flutter-actions/setup-flutter@v2 with: channel: stable - version: 3.29.0 + version: 3.47.0 + + - name: Install project dependencies + run: tool/gh_actions/install_dependencies.sh - name: Run Flutter Test run: tool/gh_actions/devtool/run_devtool_test.sh @@ -121,4 +136,3 @@ jobs: - name: Test DevTools Installation run: tool/gh_actions/devtool/test_devtools_install.sh extension/devtools - diff --git a/CHANGELOG.md b/CHANGELOG.md index 6294c1c42..acbcc9cdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,27 @@ +## Next Release + +- Migrated active packages to a pub workspace. The root `workspace:` list is + the single package roster, and `tool/workspace.dart` now provides + repository-wide analysis, native and Node.js test commands, and generation of + the multi-root VSCode workspace. +- Added the `ModuleService` API for module-scoped generation, capture, and + inspection services. `ModuleServices` registers and looks up services for a + built module hierarchy, and `hierarchyJson` exposes its hierarchy as JSON. +- Added `ArtifactProducingService` and `ModuleServiceArtifact` for + transport-neutral output. Artifact-producing services default + `outputDirectory` to the current directory and `outputBaseName` to the + module definition name, and expose named, media-typed byte streams without + requiring filesystem output. +- Added `SystemVerilogService` for configured SystemVerilog synthesis, + in-memory source output, artifact inspection, and explicit directory writes. + Added `WaveformService` for in-memory waveform capture with optional file + writing through `writeToFile`. +- Added legacy-compatible `Module.dumpSystemVerilog` and `Module.dumpWaves` + convenience methods. `dumpSystemVerilog()` provides simple in-memory output + or writes an optional `outputPath`; `dumpWaves()` replaces `dumpWaveforms` + for standard VCD capture. `WaveDumper` and `generateSynth` are deprecated in + favor of these `Module` methods. + ## 0.6.10 - Improved `Logic.replicate(1)` and same-width `signExtend` to return the original signal, eliminating redundant replication modules and generated SystemVerilog (). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6bb9116ce..3ac94ceba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ Anyone interested in participating in ROHD is more than welcome to help! ## Code of Conduct -ROHD adopts the [Contributor Covenant](https://www.contributor-covenant.org/) v2.1 for the code of conduct. It can be accessed [here](CODE_OF_CONDUCT.md). +ROHD adopts the [Contributor Covenant](https://www.contributor-covenant.org/) v2.1 for the code of conduct. It can be accessed [Code of Conduct](CODE_OF_CONDUCT.md). ## Getting Help @@ -40,7 +40,12 @@ The [ROHD Forum](https://intel.github.io/rohd-website/forum/rohd-forum/) is a pe ### Requirements -You must have [Dart](https://dart.dev/) installed on your system to use ROHD. You can find detailed instructions for how to install Dart here: +ROHD uses a [pub workspace](https://dart.dev/tools/pub/workspaces) for its +active packages. [Dart](https://dart.dev/get-dart) is sufficient to develop, +analyze, and test the core ROHD package. Install +[Flutter](https://docs.flutter.dev/get-started/install), which includes a +compatible Dart SDK, to develop the DevTools application or validate the full +mixed Dart/Flutter workspace. To run the complete ROHD test suite for development, you need to install [Icarus Verilog](https://steveicarus.github.io/iverilog/). It is used to compare SystemVerilog functionality with the ROHD simulator functionality. Installation instructions are available here: @@ -64,17 +69,87 @@ The below button will allow you to create a GitHub Codespace with ROHD already c [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=409325108) -### Cloning and Running the Tests +### Core ROHD Setup and Validation -Once requirements are installed, you can clone and run the test suite: +The root [`pubspec.yaml`](pubspec.yaml) `workspace:` list defines the active +packages. The legacy +[`doc/tutorials/chapter_9/rohd_vf_example`](doc/tutorials/chapter_9/rohd_vf_example) +is intentionally outside the workspace because it demonstrates an older +published ROHD release. + +For core ROHD development, clone the repository and use Dart from the +repository root: ```shell git clone https://github.com/intel/rohd.git cd rohd + +# Resolve the core package and workspace dependencies. dart pub get + +# Open Folder: open only the root ROHD package in VSCode. +code . + +# Analyze and test the core package. +dart analyze dart test ``` +As a local convenience, `tool/gh_actions/install_dependencies.sh` performs the +same dependency-resolution step. It uses Flutter for the full workspace when +Flutter is installed and otherwise uses Dart for the core package. + +In VSCode, this is equivalent to **File > Open Folder...** and selecting the +repository root. Use this mode when working only on the core ROHD package. + +### Full Workspace Setup, VSCode, and Validation + +For DevTools development or repository-wide validation, use Flutter to resolve +the mixed Dart/Flutter workspace. The checked-in +[`rohd-multipackage.code-workspace`](rohd-multipackage.code-workspace) is +generated from the root `workspace:` list, so it can be opened immediately +after cloning: + +```shell +# Open Workspace from File: open every active member in its own package context. +code rohd-multipackage.code-workspace + +# Resolve every workspace member from a terminal at the repository root. +flutter pub get +``` + +In VSCode, this is equivalent to **File > Open Workspace from File...** and +selecting `rohd-multipackage.code-workspace`. Do not use **Open Folder** for +all-package work: the generated multi-root workspace gives each active package +its own Dart or Flutter package context. + +After opening the generated workspace, select the Flutter-bundled Dart SDK if +the Dart extension does not select it automatically. The generated workspace +includes every active member, so Dart and Flutter analysis can resolve package +boundaries correctly. + +Run repository-wide validation from the repository root: + +```shell +# Analyze every active workspace member. +dart run tool/workspace.dart analyze + +# Run native tests, using flutter test for Flutter packages. +dart run tool/workspace.dart test + +# Run Node.js tests for each non-Flutter workspace member. +dart run tool/workspace.dart test-node +``` + +The Node.js pass can take substantially longer than native tests because Dart +compiles browser test bundles. Run an individual package or test file directly +while iterating, then use the workspace commands before submitting a change. + +When adding or removing an active package, update the root `workspace:` list, +regenerate `rohd-multipackage.code-workspace` with +`dart run tool/workspace.dart vscode`, and commit the generated workspace file +alongside the `pubspec.yaml` change. Then run `flutter pub get`. + ## How to Contribute ### Reporting Vulnerabilities @@ -109,7 +184,13 @@ Take a look around the issues on the repo and see if there's any you'd like to t If you have a change that you have implemented and would like to contribute, you can open a pull request. Please try to make sure you have implemented tests covering the changes, if applicable. Smaller, simpler pull requests are easier to review. -Be sure to run the test suite (`dart test`) before asking for your code to be merged. You may also locally generate API documentation (`dart doc`) to make sure it looks right and doesn't have any errors. You should use the dart formatter on all code (`dart format .`), and may prefer to have it automatically format on every file save. If you are using VSCode with the Dart extension, then consider using the recommended settings: +Be sure to run the applicable workspace validation commands described above +before asking for your code to be merged. You may also locally generate API +documentation (`dart doc`) to make sure it looks right and doesn't have any +errors. You should use the dart formatter on all code (`dart format .`), and +may prefer to have it automatically format on every file save. If you are using +VSCode with the Dart extension, then consider using the recommended settings: + **Tests must pass, documentation must generate, and the formatter must be run on every pull request or the automated GitHub Actions flow will fail.** @@ -124,7 +205,7 @@ Please include the SPDX tag near the top of any new files you create: Here is an example of a recommended file header template: ```dart -// Copyright (C) 2021-2023 Intel Corporation +// Copyright (C) 2021-2026 Intel Corporation // SPDX-License-Identifier: BSD-3-Clause // // example.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index b4e2c5480..2399314f3 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -12,6 +12,13 @@ analyzer: - packages/rohd_waveform - rohd_devtools_extension - rohd_extension + - build/** + - android/** + - ios/** + - web/** + - windows/** + - macos/** + - linux/** # keep up to date, matching https://dart.dev/tools/linter-rules/all # some lints are not yet available, so disabled and marked with [not currently recognized] diff --git a/packages/rohd_hierarchy/analysis_options.yaml b/packages/rohd_hierarchy/analysis_options.yaml index f04c6cf0f..a96029588 100644 --- a/packages/rohd_hierarchy/analysis_options.yaml +++ b/packages/rohd_hierarchy/analysis_options.yaml @@ -1 +1,10 @@ +analyzer: + exclude: + - build/** + - android/** + - ios/** + - web/** + - windows/** + - macos/** + - linux/** include: ../../analysis_options.yaml diff --git a/packages/rohd_hierarchy/pubspec.yaml b/packages/rohd_hierarchy/pubspec.yaml index c75cd3d34..65b6de369 100644 --- a/packages/rohd_hierarchy/pubspec.yaml +++ b/packages/rohd_hierarchy/pubspec.yaml @@ -7,8 +7,10 @@ issue_tracker: https://github.com/intel/rohd/issues publish_to: none +resolution: workspace + environment: - sdk: '>=3.0.0 <4.0.0' + sdk: ^3.6.0 dependencies: collection: ^1.15.0 diff --git a/packages/rohd_waveform/analysis_options.yaml b/packages/rohd_waveform/analysis_options.yaml index f04c6cf0f..a96029588 100644 --- a/packages/rohd_waveform/analysis_options.yaml +++ b/packages/rohd_waveform/analysis_options.yaml @@ -1 +1,10 @@ +analyzer: + exclude: + - build/** + - android/** + - ios/** + - web/** + - windows/** + - macos/** + - linux/** include: ../../analysis_options.yaml diff --git a/packages/rohd_waveform/pubspec.yaml b/packages/rohd_waveform/pubspec.yaml index 9ec84a97e..70069d0eb 100644 --- a/packages/rohd_waveform/pubspec.yaml +++ b/packages/rohd_waveform/pubspec.yaml @@ -7,8 +7,10 @@ issue_tracker: https://github.com/intel/rohd/issues publish_to: none +resolution: workspace + environment: - sdk: '>=3.0.0 <4.0.0' + sdk: ^3.6.0 dependencies: collection: ^1.15.0 @@ -16,9 +18,5 @@ dependencies: rohd_hierarchy: ^0.1.0 dev_dependencies: - lints: ^3.0.0 + lints: ^5.0.0 test: ^1.17.3 - -dependency_overrides: - rohd_hierarchy: - path: ../rohd_hierarchy diff --git a/pubspec.yaml b/pubspec.yaml index 42949a933..0b4e5d171 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,14 @@ issue_tracker: https://github.com/intel/rohd/issues documentation: https://intel.github.io/rohd-website/docs/sample-example/ environment: - sdk: '>=3.0.0 <4.0.0' + sdk: ^3.6.0 + +workspace: + - packages/rohd_hierarchy + - packages/rohd_waveform + - rohd_devtools_extension + - rohd_devtools_extension/packages/rohd_devtools_widgets + - rohd_extension/dart dependencies: collection: ^1.15.0 diff --git a/rohd-multipackage.code-workspace b/rohd-multipackage.code-workspace index 3c0ed09fc..92a381b9d 100644 --- a/rohd-multipackage.code-workspace +++ b/rohd-multipackage.code-workspace @@ -1,6 +1,3 @@ -// Opens each nested Dart package as a workspace root so the Dart analyzer uses -// its own package context and reports fewer cross-package Problems. Open this -// file in VS Code with File > Open Workspace from File... . { "folders": [ { @@ -22,6 +19,10 @@ { "name": "rohd_devtools_widgets", "path": "rohd_devtools_extension/packages/rohd_devtools_widgets" + }, + { + "name": "dart", + "path": "rohd_extension/dart" } ], "settings": { diff --git a/rohd_devtools_extension/analysis_options.yaml b/rohd_devtools_extension/analysis_options.yaml index f82d6cc51..1bfb3d100 100644 --- a/rohd_devtools_extension/analysis_options.yaml +++ b/rohd_devtools_extension/analysis_options.yaml @@ -2,6 +2,14 @@ # https://rydmike.com/blog_flutter_linting.html analyzer: + exclude: + - build/** + - android/** + - ios/** + - web/** + - windows/** + - macos/** + - linux/** language: strict-casts: true strict-inference: true diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/analysis_options.yaml b/rohd_devtools_extension/packages/rohd_devtools_widgets/analysis_options.yaml index 572dd239d..c3810a1c8 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/analysis_options.yaml +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/analysis_options.yaml @@ -1 +1,10 @@ +analyzer: + exclude: + - build/** + - android/** + - ios/** + - web/** + - windows/** + - macos/** + - linux/** include: package:lints/recommended.yaml diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/pubspec.yaml b/rohd_devtools_extension/packages/rohd_devtools_widgets/pubspec.yaml index dcb1b7a95..5740acd0b 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/pubspec.yaml +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/pubspec.yaml @@ -2,8 +2,10 @@ name: rohd_devtools_widgets description: "Shared widgets for ROHD DevTools sub-packages: help button, PNG export, auto-hiding overlay." version: 0.1.0 publish_to: none +resolution: workspace + environment: - sdk: '>=3.4.0 <4.0.0' + sdk: ^3.6.0 flutter: '>=3.0.0' dependencies: flutter: {sdk: flutter} @@ -12,7 +14,3 @@ dependencies: dev_dependencies: flutter_test: {sdk: flutter} lints: ^5.0.0 - -dependency_overrides: - rohd: - path: ../../.. diff --git a/rohd_devtools_extension/pubspec.yaml b/rohd_devtools_extension/pubspec.yaml index c6d89e98b..5ff05e6ec 100644 --- a/rohd_devtools_extension/pubspec.yaml +++ b/rohd_devtools_extension/pubspec.yaml @@ -6,6 +6,8 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 +resolution: workspace + environment: sdk: ^3.6.0 @@ -19,8 +21,9 @@ dependencies: flutter_bloc: ^9.0.0 flutter_simple_treeview: ^3.0.2 logging: ^1.2.0 + rohd: ^0.6.10 rohd_devtools_widgets: - path: packages/rohd_devtools_widgets + ^0.1.0 vm_service: ^14.3.1 web: ^1.0.0 web_socket_channel: ^3.0.0 @@ -37,7 +40,3 @@ flutter: assets: - assets/help/ - assets/icons/ - -dependency_overrides: - rohd: - path: ../ diff --git a/rohd_extension/dart/pubspec.yaml b/rohd_extension/dart/pubspec.yaml index c7807621a..0f16d0c5d 100644 --- a/rohd_extension/dart/pubspec.yaml +++ b/rohd_extension/dart/pubspec.yaml @@ -4,8 +4,11 @@ description: > frame cycling, and DTD service for cross-probe source navigation. version: 0.1.0 +publish_to: none +resolution: workspace + environment: - sdk: ^3.0.0 + sdk: ^3.6.0 dependencies: json_rpc_2: ^3.0.0 diff --git a/tool/gh_actions/analyze_source.sh b/tool/gh_actions/analyze_source.sh index 8fc260b6b..3a7471e07 100755 --- a/tool/gh_actions/analyze_source.sh +++ b/tool/gh_actions/analyze_source.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (C) 2022 Intel Corporation +# Copyright (C) 2022-2026 Intel Corporation # SPDX-License-Identifier: BSD-3-Clause # # analyze_source.sh @@ -11,4 +11,9 @@ set -euo pipefail -dart analyze --fatal-infos +if command -v flutter >/dev/null 2>&1; then + dart run tool/workspace.dart analyze +else + echo "Flutter is unavailable; analyzing the core ROHD package only." + dart analyze +fi diff --git a/tool/gh_actions/devtool/install_devtools.sh b/tool/gh_actions/devtool/install_devtools.sh index 6174a7c53..44163a108 100755 --- a/tool/gh_actions/devtool/install_devtools.sh +++ b/tool/gh_actions/devtool/install_devtools.sh @@ -23,8 +23,6 @@ DEST="../extension/devtools" cd rohd_devtools_extension -flutter pub get - echo "" echo "════════════════════════════════════════════════════════════" echo " Building DevTools extension..." diff --git a/tool/gh_actions/devtool/run_devtool_test.sh b/tool/gh_actions/devtool/run_devtool_test.sh index 3d1227985..14e2da071 100755 --- a/tool/gh_actions/devtool/run_devtool_test.sh +++ b/tool/gh_actions/devtool/run_devtool_test.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (C) 2024 Intel Corporation +# Copyright (C) 2024-2026 Intel Corporation # SPDX-License-Identifier: BSD-3-Clause # # run_devtool_test.sh @@ -13,6 +13,4 @@ set -euo pipefail cd rohd_devtools_extension -flutter pub get - flutter test --platform chrome \ No newline at end of file diff --git a/tool/gh_actions/install_dependencies.sh b/tool/gh_actions/install_dependencies.sh index 7aef34082..f6e2160a8 100755 --- a/tool/gh_actions/install_dependencies.sh +++ b/tool/gh_actions/install_dependencies.sh @@ -1,14 +1,21 @@ #!/bin/bash -# Copyright (C) 2022-2023 Intel Corporation +# Copyright (C) 2022-2026 Intel Corporation # SPDX-License-Identifier: BSD-3-Clause # # install_dependencies.sh -# GitHub Actions step: Install project dependencies. +# Installs dependencies from the repository root for local development or CI. +# Uses Flutter for the full workspace when available, otherwise Dart for core +# ROHD development. # # 2022 October 7 # Author: Chykon set -euo pipefail -dart pub get +if command -v flutter >/dev/null 2>&1; then + flutter pub get +else + echo "Flutter is unavailable; resolving the core ROHD package with Dart." + dart pub get +fi diff --git a/tool/gh_actions/run_tests.sh b/tool/gh_actions/run_tests.sh index 160352cd2..c230624bc 100755 --- a/tool/gh_actions/run_tests.sh +++ b/tool/gh_actions/run_tests.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (C) 2022-2023 Intel Corporation +# Copyright (C) 2022-2026 Intel Corporation # SPDX-License-Identifier: BSD-3-Clause # # run_tests.sh @@ -11,8 +11,14 @@ set -euo pipefail -dart test +if command -v flutter >/dev/null 2>&1; then + # Run workspace tests using each package's Dart or Flutter runner. + dart run tool/workspace.dart test -# run tests in JS (increase heap size also) -export NODE_OPTIONS="--max-old-space-size=8192" -dart test --platform node \ No newline at end of file + # Run workspace Dart tests in JS (increase heap size for large synthesis tests). + export NODE_OPTIONS="--max-old-space-size=8192" + dart run tool/workspace.dart test-node +else + echo "Flutter is unavailable; running native tests for the core ROHD package only." + dart test +fi \ No newline at end of file diff --git a/tool/gh_codespaces/install_flutter.sh b/tool/gh_codespaces/install_flutter.sh new file mode 100755 index 000000000..1bd32bcff --- /dev/null +++ b/tool/gh_codespaces/install_flutter.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# Copyright (C) 2026 Intel Corporation +# SPDX-License-Identifier: BSD-3-Clause +# +# install_flutter.sh +# GitHub Codespaces setup: Install the Flutter SDK used by CI. +# +# 2026 August +# Author: Desmond Kirkpatrick + +set -euo pipefail + +declare -r flutter_version='3.47.0' +declare -r flutter_sdk_dir='/opt/flutter' +declare -r flutter_archive_url="https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${flutter_version}-stable.tar.xz" + +if [[ -x "${flutter_sdk_dir}/bin/flutter" ]] && + "${flutter_sdk_dir}/bin/flutter" --version | grep -q "Flutter ${flutter_version}"; then + echo "Flutter ${flutter_version} is already installed." + exit 0 +fi + +sudo rm -rf "${flutter_sdk_dir}" +sudo apt-get update +sudo apt-get install -y curl xz-utils + +archive="$(mktemp)" +trap 'rm -f "${archive}"' EXIT + +curl --fail --location --silent --show-error "${flutter_archive_url}" \ + --output "${archive}" +sudo tar --extract --xz --file "${archive}" --directory /opt +sudo ln --force --symbolic "${flutter_sdk_dir}/bin/flutter" /usr/local/bin/flutter + +flutter --version diff --git a/tool/gh_codespaces/run_setup.sh b/tool/gh_codespaces/run_setup.sh index 6523e4147..47a9bdff3 100755 --- a/tool/gh_codespaces/run_setup.sh +++ b/tool/gh_codespaces/run_setup.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Copyright (C) 2023 Intel Corporation +# Copyright (C) 2023-2026 Intel Corporation # SPDX-License-Identifier: BSD-3-Clause # # run_setup.sh @@ -14,6 +14,10 @@ set -euo pipefail # Install Dart SDK. tool/gh_codespaces/install_dart.sh +# Install Flutter SDK. The workspace contains Flutter packages, so +# dependencies must be resolved through `flutter pub`. +tool/gh_codespaces/install_flutter.sh + # Install Pub dependencies. tool/gh_actions/install_dependencies.sh diff --git a/tool/workspace.dart b/tool/workspace.dart new file mode 100644 index 000000000..c77c91799 --- /dev/null +++ b/tool/workspace.dart @@ -0,0 +1,136 @@ +// Copyright (C) 2026 Intel Corporation +// SPDX-License-Identifier: BSD-3-Clause +// +// workspace.dart +// Pub workspace automation for ROHD packages. + +import 'dart:convert'; +import 'dart:io'; + +import 'package:yaml/yaml.dart'; + +const _usage = ''' +Usage: dart run tool/workspace.dart + +Commands: + analyze Analyze every workspace package. + clean Delete build artifacts from every workspace package. + test Run native tests in every workspace package. + test-node Run Node.js tests in every non-Flutter workspace package. + vscode Generate rohd-multipackage.code-workspace. +'''; + +Future main(List arguments) async { + if (arguments.length != 1 || + !{'analyze', 'clean', 'test', 'test-node', 'vscode'} + .contains(arguments.single)) { + stderr.write(_usage); + exitCode = 64; + return; + } + + final root = Directory.current.absolute; + final packages = _workspacePackages(root); + + if (arguments.single == 'vscode') { + _generateVsCodeWorkspace(root, packages); + return; + } + + for (final package in packages) { + final command = _usesFlutter(package) ? 'flutter' : 'dart'; + if (arguments.single == 'test-node' && command == 'flutter') { + continue; + } + + final commandArguments = switch (arguments.single) { + 'analyze' => const ['analyze', '--no-fatal-warnings'], + 'clean' => const ['clean'], + 'test' => const ['test'], + 'test-node' => const ['test', '--platform', 'node'], + _ => throw StateError('Unexpected command.'), + }; + await _run(command, commandArguments, package); + } +} + +List _workspacePackages(Directory root) { + final pubspec = _readPubspec(root); + final workspace = pubspec['workspace']; + if (workspace is! YamlList) { + throw StateError('Root pubspec.yaml must declare a workspace list.'); + } + + return [ + root, + for (final member in workspace) + Directory('${root.path}${Platform.pathSeparator}$member').absolute, + ]; +} + +bool _usesFlutter(Directory package) { + final pubspec = _readPubspec(package); + return _containsFlutterSdkDependency(pubspec['dependencies']) || + _containsFlutterSdkDependency(pubspec['dev_dependencies']); +} + +bool _containsFlutterSdkDependency(Object? dependencies) { + if (dependencies is! YamlMap) { + return false; + } + final flutter = dependencies['flutter']; + return flutter is YamlMap && flutter['sdk'] == 'flutter'; +} + +YamlMap _readPubspec(Directory package) { + final pubspec = File('${package.path}${Platform.pathSeparator}pubspec.yaml'); + final parsed = loadYaml(pubspec.readAsStringSync()); + if (parsed is! YamlMap) { + throw FormatException('Expected a YAML map in ${pubspec.path}.'); + } + return parsed; +} + +Future _run( + String command, + List arguments, + Directory workingDirectory, +) async { + stdout.writeln( + 'Running $command ${arguments.join(' ')} in ${workingDirectory.path}', + ); + final process = await Process.start( + command, + arguments, + workingDirectory: workingDirectory.path, + mode: ProcessStartMode.inheritStdio, + ); + final exitCode = await process.exitCode; + if (exitCode != 0) { + throw ProcessException(command, arguments, 'Command failed.', exitCode); + } +} + +void _generateVsCodeWorkspace(Directory root, List packages) { + final workspace = { + 'folders': [ + for (final package in packages) + { + 'name': package.path == root.path ? 'rohd' : _baseName(package.path), + 'path': package.path == root.path + ? '.' + : package.path.substring(root.path.length + 1), + }, + ], + 'settings': {'dart.projectSearchDepth': 8}, + }; + File('${root.path}${Platform.pathSeparator}rohd-multipackage.code-workspace') + .writeAsStringSync( + '${const JsonEncoder.withIndent(' ').convert(workspace)}\n', + ); +} + +String _baseName(String path) { + final separator = path.lastIndexOf(Platform.pathSeparator); + return separator < 0 ? path : path.substring(separator + 1); +} From e9429cf1ca70802060e8fd3d54524b34dbb76be3 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Wed, 19 Aug 2026 22:36:37 -0700 Subject: [PATCH 02/17] minor fixes in analysis --- lib/src/collections/iterable_removable_queue.dart | 8 ++++---- lib/src/modules/conditionals/flop.dart | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/src/collections/iterable_removable_queue.dart b/lib/src/collections/iterable_removable_queue.dart index 06b7981e7..c6042da5d 100644 --- a/lib/src/collections/iterable_removable_queue.dart +++ b/lib/src/collections/iterable_removable_queue.dart @@ -58,7 +58,7 @@ class IterableRemovableQueue { return; } - if (_first == _last && _removeWhere!(_first!.item)) { + if (_first == _last && _removeWhere(_first!.item)) { // if size is 1 and its removable, then we can just clear the queue and be // done with it clear(); @@ -77,7 +77,7 @@ class IterableRemovableQueue { } while (_patrol != null) { - if (_removeWhere!(_patrol!.item)) { + if (_removeWhere(_patrol!.item)) { assert(size > 0, 'Should not be removing if size is already 0.'); if (_patrol == _first && _first == _last) { @@ -118,7 +118,7 @@ class IterableRemovableQueue { /// Also may remove items from the queue if they are indicated by /// [_removeWhere]. void add(T item) { - if (_removeWhere != null && _removeWhere!(item)) { + if (_removeWhere != null && _removeWhere(item)) { // If the item should be removed, we don't add it. return; } @@ -184,7 +184,7 @@ class IterableRemovableQueue { var element = _first; _IterableRemovableElement? previous; while (element != null) { - if (_removeWhere != null && _removeWhere!(element.item)) { + if (_removeWhere != null && _removeWhere(element.item)) { assert(size > 0, 'Should not be removing if size is already 0.'); previous?.next = element.next; diff --git a/lib/src/modules/conditionals/flop.dart b/lib/src/modules/conditionals/flop.dart index cd9aa8750..c647479c5 100644 --- a/lib/src/modules/conditionals/flop.dart +++ b/lib/src/modules/conditionals/flop.dart @@ -146,7 +146,7 @@ class FlipFlop extends Module with SystemVerilog { var contents = [q < _d]; if (_en != null) { - contents = [If(_en!, then: contents)]; + contents = [If(_en, then: contents)]; } Sequential( From 3573caacffb5289da2a65cef4e5292f1489d9bd1 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Wed, 19 Aug 2026 22:39:46 -0700 Subject: [PATCH 03/17] install flutter in devcontainer --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index dd4d9d280..12e172c74 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,7 +4,7 @@ { "image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04", - "postCreateCommand": "tool/gh_codespaces/run_setup.sh", + "updateContentCommand": "tool/gh_codespaces/run_setup.sh", "customizations": { "codespaces": { From 8dee009ce2aba68d064c4daedea84597e8ac1547 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Wed, 19 Aug 2026 23:06:57 -0700 Subject: [PATCH 04/17] fix devtools install --- rohd_devtools_extension/tool/test_devtools_install.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rohd_devtools_extension/tool/test_devtools_install.dart b/rohd_devtools_extension/tool/test_devtools_install.dart index 01e6a1c04..aee336596 100644 --- a/rohd_devtools_extension/tool/test_devtools_install.dart +++ b/rohd_devtools_extension/tool/test_devtools_install.dart @@ -61,7 +61,7 @@ Future main(List args) async { _requireFile(extensionAssetsPath, 'flutter.js'); _requireFile(extensionAssetsPath, 'main.dart.js'); _requireFile(extensionAssetsPath, 'version.json'); - _requireFile(extensionAssetsPath, p.join('assets', 'AssetManifest.json')); + _requireFile(extensionAssetsPath, p.join('assets', 'AssetManifest.bin.json')); _requireFile(extensionAssetsPath, p.join('assets', 'FontManifest.json')); _requireFile(extensionAssetsPath, p.join('canvaskit', 'canvaskit.js')); _requireFile(extensionAssetsPath, p.join('canvaskit', 'canvaskit.wasm')); From aa37227b7a7ab3b59905c0470e261f40ae4e04f7 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Wed, 19 Aug 2026 23:18:41 -0700 Subject: [PATCH 05/17] format issue --- rohd_devtools_extension/tool/test_devtools_install.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rohd_devtools_extension/tool/test_devtools_install.dart b/rohd_devtools_extension/tool/test_devtools_install.dart index aee336596..0fe167819 100644 --- a/rohd_devtools_extension/tool/test_devtools_install.dart +++ b/rohd_devtools_extension/tool/test_devtools_install.dart @@ -61,7 +61,8 @@ Future main(List args) async { _requireFile(extensionAssetsPath, 'flutter.js'); _requireFile(extensionAssetsPath, 'main.dart.js'); _requireFile(extensionAssetsPath, 'version.json'); - _requireFile(extensionAssetsPath, p.join('assets', 'AssetManifest.bin.json')); + _requireFile( + extensionAssetsPath, p.join('assets', 'AssetManifest.bin.json')); _requireFile(extensionAssetsPath, p.join('assets', 'FontManifest.json')); _requireFile(extensionAssetsPath, p.join('canvaskit', 'canvaskit.js')); _requireFile(extensionAssetsPath, p.join('canvaskit', 'canvaskit.wasm')); From 33d6bef7d54a1bd0b8b98d530db5e3b44a354256 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 00:35:48 -0700 Subject: [PATCH 06/17] vm test for filter_bank --- .../test/filter_bank_integration_test.dart | 77 +------------------ .../test/hierarchy_model_test.dart | 71 +++++++++++++++++ 2 files changed, 74 insertions(+), 74 deletions(-) create mode 100644 packages/rohd_hierarchy/test/hierarchy_model_test.dart diff --git a/packages/rohd_hierarchy/test/filter_bank_integration_test.dart b/packages/rohd_hierarchy/test/filter_bank_integration_test.dart index 6a8fe173a..561b1dc84 100644 --- a/packages/rohd_hierarchy/test/filter_bank_integration_test.dart +++ b/packages/rohd_hierarchy/test/filter_bank_integration_test.dart @@ -8,6 +8,9 @@ // 2026 April // Author: Desmond Kirkpatrick +@TestOn('vm') +library; + import 'dart:io'; import 'package:rohd_hierarchy/rohd_hierarchy.dart'; @@ -172,19 +175,6 @@ void main() { expect(outputs.map((s) => s.name), contains('done')); }); - test(r'isPrimitiveType is true for $-prefixed types', () { - expect(HierarchyOccurrence.isPrimitiveType(r'$mux'), isTrue); - expect(HierarchyOccurrence.isPrimitiveType(r'$and'), isTrue); - }); - - test(r'isPrimitiveType is false for non-$-prefixed types', () { - expect(HierarchyOccurrence.isPrimitiveType('FilterBank'), isFalse); - }); - - test('isPrimitiveType is false for empty string', () { - expect(HierarchyOccurrence.isPrimitiveType(''), isFalse); - }); - test('isPrimitiveCell reflects isPrimitive field and type', () { // A node marked isPrimitive=true final primCell = service.root.children.firstWhere((c) => c.isPrimitive); @@ -294,55 +284,6 @@ void main() { expect(withSlash, isNotEmpty); }); - test('hasRegexChars is false for plain text', () { - expect(HierarchyService.hasRegexChars('clk'), isFalse); - }); - - test('hasRegexChars detects * glob', () { - expect(HierarchyService.hasRegexChars('c*'), isTrue); - }); - - test('hasRegexChars detects ? glob', () { - expect(HierarchyService.hasRegexChars('cl?'), isTrue); - }); - - test('hasRegexChars detects character class', () { - expect(HierarchyService.hasRegexChars('[a-z]'), isTrue); - }); - - test('hasRegexChars detects group alternation', () { - expect(HierarchyService.hasRegexChars('(a|b)'), isTrue); - }); - - test('hasRegexChars detects + quantifier', () { - expect(HierarchyService.hasRegexChars('a+'), isTrue); - }); - - test('longestCommonPrefix finds shared prefix', () { - expect( - HierarchyService.longestCommonPrefix([ - 'FilterBank/ch0', - 'FilterBank/ch1', - ]), - 'FilterBank/ch', - ); - }); - - test('longestCommonPrefix returns null for empty list', () { - expect(HierarchyService.longestCommonPrefix([]), isNull); - }); - - test('longestCommonPrefix returns null for no common prefix', () { - expect(HierarchyService.longestCommonPrefix(['abc', 'xyz']), isNull); - }); - - test('longestCommonPrefix is case-sensitive', () { - final prefix = HierarchyService.longestCommonPrefix([ - 'Filter/abc', - 'Filter/abd', - ]); - expect(prefix, 'Filter/ab'); - }); }); // ─────────────── HierarchySearchController ─────────────── @@ -456,18 +397,6 @@ void main() { }); }); - // ─────────────── BaseHierarchyAdapter edge case ─────────────── - // The real uninitialized-root StateError test lives in - // coverage_gaps_test.dart. Here we just verify fromTree works. - - group('BaseHierarchyAdapter — fromTree produces usable root', () { - test('fromTree immediately sets root', () { - final tree = HierarchyOccurrence(name: 'r'); - final svc = BaseHierarchyAdapter.fromTree(tree); - expect(svc.root.name, 'r'); - }); - }); - // ─────────────── Multiple instantiation (dedup) ─────────────── group('Multiple instantiation — FilterChannel dedup', () { diff --git a/packages/rohd_hierarchy/test/hierarchy_model_test.dart b/packages/rohd_hierarchy/test/hierarchy_model_test.dart new file mode 100644 index 000000000..9ef3485c6 --- /dev/null +++ b/packages/rohd_hierarchy/test/hierarchy_model_test.dart @@ -0,0 +1,71 @@ +// Copyright (C) 2026 Intel Corporation +// SPDX-License-Identifier: BSD-3-Clause +// +// hierarchy_model_test.dart +// Cross-platform hierarchy model and utility tests. +// +// 2026 August +// Author: Desmond Kirkpatrick + +import 'package:rohd_hierarchy/rohd_hierarchy.dart'; +import 'package:test/test.dart'; + +void main() { + group('HierarchyOccurrence primitive detection', () { + test(r'isPrimitiveType is true for $-prefixed types', () { + expect(HierarchyOccurrence.isPrimitiveType(r'$mux'), isTrue); + expect(HierarchyOccurrence.isPrimitiveType(r'$and'), isTrue); + }); + + test(r'isPrimitiveType is false for non-$-prefixed types', () { + expect(HierarchyOccurrence.isPrimitiveType('FilterBank'), isFalse); + }); + + test('isPrimitiveType is false for empty string', () { + expect(HierarchyOccurrence.isPrimitiveType(''), isFalse); + }); + }); + + group('HierarchyService search utilities', () { + test('hasRegexChars is false for plain text', () { + expect(HierarchyService.hasRegexChars('clk'), isFalse); + }); + + test('hasRegexChars detects glob and regex syntax', () { + for (final query in ['c*', 'cl?', '[a-z]', '(a|b)', 'a+']) { + expect(HierarchyService.hasRegexChars(query), isTrue); + } + }); + + test('longestCommonPrefix finds shared prefix', () { + expect( + HierarchyService.longestCommonPrefix([ + 'FilterBank/ch0', + 'FilterBank/ch1', + ]), + 'FilterBank/ch', + ); + }); + + test('longestCommonPrefix returns null without a shared prefix', () { + expect(HierarchyService.longestCommonPrefix([]), isNull); + expect(HierarchyService.longestCommonPrefix(['abc', 'xyz']), isNull); + }); + + test('longestCommonPrefix is case-sensitive', () { + expect( + HierarchyService.longestCommonPrefix(['Filter/abc', 'Filter/abd']), + 'Filter/ab', + ); + }); + }); + + group('BaseHierarchyAdapter', () { + test('fromTree immediately sets root', () { + final service = + BaseHierarchyAdapter.fromTree(HierarchyOccurrence(name: 'r')); + + expect(service.root.name, 'r'); + }); + }); +} From 9bd72e41bfdd1fe4856b053782817558a6c57f54 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 00:43:58 -0700 Subject: [PATCH 07/17] format change --- packages/rohd_hierarchy/test/filter_bank_integration_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/rohd_hierarchy/test/filter_bank_integration_test.dart b/packages/rohd_hierarchy/test/filter_bank_integration_test.dart index 561b1dc84..b7778fd54 100644 --- a/packages/rohd_hierarchy/test/filter_bank_integration_test.dart +++ b/packages/rohd_hierarchy/test/filter_bank_integration_test.dart @@ -283,7 +283,6 @@ void main() { // At least ch0_1 and ch1_1 have children expect(withSlash, isNotEmpty); }); - }); // ─────────────── HierarchySearchController ─────────────── From 0187d9f099c87bdf5f89a323bb5b5f6bfc33952a Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 00:58:33 -0700 Subject: [PATCH 08/17] package lint --- .../rohd_waveform/lib/src/waveform_api.dart | 34 +++++++++---------- .../lib/src/waveform_repository.dart | 6 ++-- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/packages/rohd_waveform/lib/src/waveform_api.dart b/packages/rohd_waveform/lib/src/waveform_api.dart index 8daa6ffa7..65962c6a3 100644 --- a/packages/rohd_waveform/lib/src/waveform_api.dart +++ b/packages/rohd_waveform/lib/src/waveform_api.dart @@ -33,14 +33,13 @@ abstract class SignalWaveformApi { required List signalIds, int? startTime, int? endTime, - }) async { - // Base implementation: must be overridden by concrete implementations - // Port no longer contains data - implementations must fetch from - // their source. - throw UnimplementedError( - 'getWaveformData must be implemented by subclasses', - ); - } + }) => + // Base implementation: must be overridden by concrete implementations + // Port no longer contains data - implementations must fetch from + // their source. + Future.error(UnimplementedError( + 'getWaveformData must be implemented by subclasses', + )); /// Streams waveform data incrementally for specific signals. /// @@ -71,12 +70,11 @@ abstract class SignalWaveformApi { /// /// Returns a [Future] that completes with the current time as an integer, /// or null if the time cannot be determined. - Future getCurrentTime() async { - // Default implementation: must be overridden by concrete implementations - throw UnimplementedError( - 'getCurrentTime must be implemented by subclasses', - ); - } + Future getCurrentTime() => + // Default implementation: must be overridden by concrete implementations + Future.error(UnimplementedError( + 'getCurrentTime must be implemented by subclasses', + )); /// Retrieves a snapshot of all signal values at the given [time]. /// @@ -87,9 +85,9 @@ abstract class SignalWaveformApi { /// - `direction`: signal direction (if port) /// /// Returns null if the snapshot could not be retrieved. - Future>?> getSnapshot(int time) async { - throw UnimplementedError('getSnapshot must be implemented by subclasses'); - } + Future>?> getSnapshot(int time) => + Future.error( + UnimplementedError('getSnapshot must be implemented by subclasses')); /// Proactively expand all slim module definitions so the client-side /// evaluator can compute internal signals immediately. @@ -97,5 +95,5 @@ abstract class SignalWaveformApi { /// Called when the user enables "internal signals" in the wave viewer. /// Default implementation is a no-op; overridden by implementations /// that support client-side synthesis. - Future expandAllSlimModules() async {} + Future expandAllSlimModules() => Future.value(); } diff --git a/packages/rohd_waveform/lib/src/waveform_repository.dart b/packages/rohd_waveform/lib/src/waveform_repository.dart index ba24cf12d..27d04f006 100644 --- a/packages/rohd_waveform/lib/src/waveform_repository.dart +++ b/packages/rohd_waveform/lib/src/waveform_repository.dart @@ -152,10 +152,8 @@ class SignalWaveformRepository { } /// Get the current simulation time from the waveform API. - Future getCurrentTime() async { - await _ensureReady(); - return _signalWaveformApi.getCurrentTime(); - } + Future getCurrentTime() => + _ensureReady().then((_) => _signalWaveformApi.getCurrentTime()); /// Retrieves waveform data for specific signals. /// From 839eb034f5f0c38ef06dd918318f9bbc4bcf80ce Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 07:23:57 -0700 Subject: [PATCH 09/17] flutter setup for devcontainer --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 12e172c74..dd4d9d280 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,7 +4,7 @@ { "image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04", - "updateContentCommand": "tool/gh_codespaces/run_setup.sh", + "postCreateCommand": "tool/gh_codespaces/run_setup.sh", "customizations": { "codespaces": { From 40ae9ede85f0ed3777e53f857237e0d938683099 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 08:06:19 -0700 Subject: [PATCH 10/17] installing flutter in devcontainer was failing --- .github/workflows/general.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/general.yml b/.github/workflows/general.yml index 6948f8c34..043783a3b 100644 --- a/.github/workflows/general.yml +++ b/.github/workflows/general.yml @@ -77,7 +77,9 @@ jobs: - name: Build dev container and run tests in it uses: devcontainers/ci@v0.3 with: - runCmd: tool/gh_actions/run_tests.sh + runCmd: >- + tool/gh_codespaces/install_flutter.sh && + tool/gh_actions/run_tests.sh deploy-documentation: name: Deploy Documentation From 6c54b6ee7a9627c7196faa61f9ab7dfcdd58e0ff Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 09:01:57 -0700 Subject: [PATCH 11/17] need to use flutter pub --- tool/workspace.dart | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tool/workspace.dart b/tool/workspace.dart index c77c91799..2d2de6256 100644 --- a/tool/workspace.dart +++ b/tool/workspace.dart @@ -31,6 +31,7 @@ Future main(List arguments) async { final root = Directory.current.absolute; final packages = _workspacePackages(root); + final workspaceUsesFlutter = packages.any(_usesFlutter); if (arguments.single == 'vscode') { _generateVsCodeWorkspace(root, packages); @@ -38,10 +39,16 @@ Future main(List arguments) async { } for (final package in packages) { - final command = _usesFlutter(package) ? 'flutter' : 'dart'; - if (arguments.single == 'test-node' && command == 'flutter') { + final packageUsesFlutter = _usesFlutter(package); + if (arguments.single == 'test-node' && packageUsesFlutter) { continue; } + final command = packageUsesFlutter || + (arguments.single != 'test-node' && + package.path == root.path && + workspaceUsesFlutter) + ? 'flutter' + : 'dart'; final commandArguments = switch (arguments.single) { 'analyze' => const ['analyze', '--no-fatal-warnings'], From 40baf999591a47fa2b0ca457ec761d110af30ad1 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 09:55:59 -0700 Subject: [PATCH 12/17] migrate benchmarks off main test --- CONTRIBUTING.md | 6 ++++-- tool/workspace.dart | 20 ++++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3ac94ceba..8ef83f035 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -134,16 +134,18 @@ Run repository-wide validation from the repository root: # Analyze every active workspace member. dart run tool/workspace.dart analyze -# Run native tests, using flutter test for Flutter packages. +# Run native non-benchmark tests, using flutter test for Flutter packages. dart run tool/workspace.dart test -# Run Node.js tests for each non-Flutter workspace member. +# Run non-benchmark Node.js tests for each non-Flutter workspace member. dart run tool/workspace.dart test-node ``` The Node.js pass can take substantially longer than native tests because Dart compiles browser test bundles. Run an individual package or test file directly while iterating, then use the workspace commands before submitting a change. +The workspace test commands exclude the long-running `benchmark` tag; run the +[benchmark suite](benchmark/README.md) separately when measuring performance. When adding or removing an active package, update the root `workspace:` list, regenerate `rohd-multipackage.code-workspace` with diff --git a/tool/workspace.dart b/tool/workspace.dart index 2d2de6256..5811aad6b 100644 --- a/tool/workspace.dart +++ b/tool/workspace.dart @@ -15,8 +15,8 @@ Usage: dart run tool/workspace.dart Commands: analyze Analyze every workspace package. clean Delete build artifacts from every workspace package. - test Run native tests in every workspace package. - test-node Run Node.js tests in every non-Flutter workspace package. + test Run native non-benchmark tests in every workspace package. + test-node Run Node.js non-benchmark tests in every non-Flutter workspace package. vscode Generate rohd-multipackage.code-workspace. '''; @@ -53,8 +53,14 @@ Future main(List arguments) async { final commandArguments = switch (arguments.single) { 'analyze' => const ['analyze', '--no-fatal-warnings'], 'clean' => const ['clean'], - 'test' => const ['test'], - 'test-node' => const ['test', '--platform', 'node'], + 'test' => const ['test', '--exclude-tags', 'benchmark'], + 'test-node' => const [ + 'test', + '--platform', + 'node', + '--exclude-tags', + 'benchmark', + ], _ => throw StateError('Unexpected command.'), }; await _run(command, commandArguments, package); @@ -106,6 +112,7 @@ Future _run( stdout.writeln( 'Running $command ${arguments.join(' ')} in ${workingDirectory.path}', ); + final stopwatch = Stopwatch()..start(); final process = await Process.start( command, arguments, @@ -113,6 +120,11 @@ Future _run( mode: ProcessStartMode.inheritStdio, ); final exitCode = await process.exitCode; + stopwatch.stop(); + stdout.writeln( + 'Completed $command ${arguments.join(' ')} in ${workingDirectory.path} ' + 'in ${stopwatch.elapsed}.', + ); if (exitCode != 0) { throw ProcessException(command, arguments, 'Command failed.', exitCode); } From 015e183a8edbcbe866f1b981bece34a63080cff4 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 10:33:53 -0700 Subject: [PATCH 13/17] fix for devcontainer flutter test failure --- tool/workspace.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tool/workspace.dart b/tool/workspace.dart index 5811aad6b..07dbfeb2e 100644 --- a/tool/workspace.dart +++ b/tool/workspace.dart @@ -44,9 +44,7 @@ Future main(List arguments) async { continue; } final command = packageUsesFlutter || - (arguments.single != 'test-node' && - package.path == root.path && - workspaceUsesFlutter) + (arguments.single != 'test-node' && workspaceUsesFlutter) ? 'flutter' : 'dart'; From 21f32c97079624f788c5b93bfd1cb178a9fd7cbd Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 11:49:45 -0700 Subject: [PATCH 14/17] lint issue blocked by analysis_options --- analysis_options.yaml | 4 ---- rohd_extension/dart/lib/dtd_service.dart | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 2399314f3..37e6cd6c3 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -8,10 +8,6 @@ analyzer: strict-raw-types: true exclude: - doc/tutorials/chapter_9/rohd_vf_example - - packages/rohd_hierarchy - - packages/rohd_waveform - - rohd_devtools_extension - - rohd_extension - build/** - android/** - ios/** diff --git a/rohd_extension/dart/lib/dtd_service.dart b/rohd_extension/dart/lib/dtd_service.dart index 917017986..7e1103ebd 100644 --- a/rohd_extension/dart/lib/dtd_service.dart +++ b/rohd_extension/dart/lib/dtd_service.dart @@ -44,7 +44,9 @@ class DtdService { /// /// Returns `true` if connection and registration succeeded. Future connect(String uri) async { - if (_disposed) return false; + if (_disposed) { + return false; + } try { _channel = WebSocketChannel.connect(Uri.parse(uri)); @@ -66,6 +68,7 @@ class DtdService { } on Exception catch (e) { _peer = null; _channel = null; + // Surface connection failures in the extension-host log for diagnosis. // ignore: avoid_print print('[DtdService] Failed to connect to DTD at $uri: $e'); return false; From 2d305b1ff33046cad507c2963049253bba7c1c2c Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 13:39:19 -0700 Subject: [PATCH 15/17] another codespace fix --- tool/gh_codespaces/install_flutter.sh | 2 ++ tool/workspace.dart | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/tool/gh_codespaces/install_flutter.sh b/tool/gh_codespaces/install_flutter.sh index 1bd32bcff..9b84ce08e 100755 --- a/tool/gh_codespaces/install_flutter.sh +++ b/tool/gh_codespaces/install_flutter.sh @@ -17,6 +17,7 @@ declare -r flutter_archive_url="https://storage.googleapis.com/flutter_infra_rel if [[ -x "${flutter_sdk_dir}/bin/flutter" ]] && "${flutter_sdk_dir}/bin/flutter" --version | grep -q "Flutter ${flutter_version}"; then + sudo ln --force --symbolic "${flutter_sdk_dir}/bin/dart" /usr/local/bin/dart echo "Flutter ${flutter_version} is already installed." exit 0 fi @@ -32,5 +33,6 @@ curl --fail --location --silent --show-error "${flutter_archive_url}" \ --output "${archive}" sudo tar --extract --xz --file "${archive}" --directory /opt sudo ln --force --symbolic "${flutter_sdk_dir}/bin/flutter" /usr/local/bin/flutter +sudo ln --force --symbolic "${flutter_sdk_dir}/bin/dart" /usr/local/bin/dart flutter --version diff --git a/tool/workspace.dart b/tool/workspace.dart index 07dbfeb2e..fba4164a3 100644 --- a/tool/workspace.dart +++ b/tool/workspace.dart @@ -38,15 +38,20 @@ Future main(List arguments) async { return; } + if (arguments.single == 'test-node' && workspaceUsesFlutter) { + await _run('flutter', const ['pub', 'get'], root); + } + for (final package in packages) { final packageUsesFlutter = _usesFlutter(package); if (arguments.single == 'test-node' && packageUsesFlutter) { continue; } - final command = packageUsesFlutter || - (arguments.single != 'test-node' && workspaceUsesFlutter) - ? 'flutter' - : 'dart'; + final command = arguments.single == 'test-node' + ? 'dart' + : workspaceUsesFlutter + ? 'flutter' + : 'dart'; final commandArguments = switch (arguments.single) { 'analyze' => const ['analyze', '--no-fatal-warnings'], From da5e2a53a0c9dfb8c44e5e9ac7991f043aa428dc Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Thu, 20 Aug 2026 19:22:30 -0700 Subject: [PATCH 16/17] clean workflow and full analysis options throughout, plus all fixes --- .github/workflows/build_devtool.yml | 7 +- .github/workflows/coverage.yml | 10 +- .github/workflows/general.yml | 31 +-- CHANGELOG.md | 24 -- CONTRIBUTING.md | 7 +- packages/rohd_hierarchy/analysis_options.yaml | 10 - packages/rohd_waveform/analysis_options.yaml | 10 - pubspec.yaml | 2 +- rohd-multipackage.code-workspace | 4 +- rohd_devtools_extension/analysis_options.yaml | 250 +----------------- rohd_devtools_extension/lib/main.dart | 2 +- .../lib/main_standalone.dart | 2 +- .../lib/rohd_devtools/const/app_theme.dart | 2 +- .../rohd_devtools/ui/details_help_button.dart | 2 +- .../lib/rohd_devtools/ui/devtool_appbar.dart | 2 +- .../ui/devtools_connection_host.dart | 4 +- .../ui/devtools_help_button.dart | 2 +- .../rohd_devtools/ui/module_tree_card.dart | 3 +- .../ui/module_tree_details_navbar.dart | 2 +- .../lib/rohd_devtools/ui/platform_icon.dart | 2 +- .../lib/rohd_devtools/ui/schematic_icon.dart | 2 +- .../rohd_devtools/ui/signal_details_card.dart | 2 +- .../lib/rohd_devtools/ui/signal_table.dart | 2 +- .../ui/signal_table_text_field.dart | 2 +- .../ui/standalone_app_shell.dart | 2 +- .../rohd_devtools/ui/vm_connection_form.dart | 2 +- .../view/rohd_devtools_page.dart | 2 +- .../view/tree_structure_page.dart | 2 +- .../analysis_options.yaml | 2 +- .../lib/rohd_devtools_widgets.dart | 35 +-- .../lib/src/app_bar_overlay.dart | 22 +- .../lib/src/bit_expansion_menu.dart | 52 ++-- .../lib/src/bit_field_utils.dart | 167 ++++++------ .../lib/src/capture_boundary.dart | 3 +- .../lib/src/cross_probe_button.dart | 45 ++-- .../lib/src/cross_probe_menu.dart | 8 +- .../lib/src/cross_probe_service.dart | 18 +- .../lib/src/export_button.dart | 14 +- .../lib/src/export_toast.dart | 2 +- .../lib/src/markdown_help_button.dart | 41 ++- .../lib/src/rohd_extension_client.dart | 3 +- .../lib/src/rohd_extension_status.dart | 6 +- .../lib/src/save_png_web.dart | 5 +- .../rohd_devtools_widgets/pubspec.yaml | 3 +- .../test/app_bar_overlay_test.dart | 2 +- .../test/bit_expansion_menu_test.dart | 6 +- .../test/bit_field_utils_test.dart | 2 +- .../test/capture_boundary_test.dart | 6 +- .../test/cross_probe_button_test.dart | 2 +- .../test/cross_probe_menu_test.dart | 18 +- .../test/export_button_test.dart | 2 +- .../test/export_toast_test.dart | 2 +- .../test/logic_type_utils_test.dart | 3 +- .../test/markdown_help_button_test.dart | 2 +- rohd_devtools_extension/pubspec.yaml | 1 + .../test/const/app_theme_test.dart | 2 +- .../test/cubit/basic_cubits_test.dart | 10 +- .../test/cubit/snapshot_cubit_test.dart | 2 +- .../tree_structure/model_tree_card_test.dart | 2 +- .../tree_structure_page_test.dart | 2 +- .../test/ui/devtool_appbar_test.dart | 2 +- ...vtools_connection_host_lifecycle_test.dart | 4 +- .../test/ui/diagnostic_properties_test.dart | 2 +- .../ui/module_tree_details_navbar_test.dart | 2 +- .../test/ui/presentation_widgets_test.dart | 2 +- .../test/ui/signal_details_card_test.dart | 2 +- .../test/ui/signal_table_test.dart | 2 +- .../test/ui/signal_table_text_field_test.dart | 2 +- .../test/ui/vm_connection_form_test.dart | 2 +- .../test/view/rohd_devtools_page_test.dart | 2 +- .../tool/test_devtools_install.dart | 8 +- rohd_extension/{dart => vscode}/LICENSE | 0 .../{dart => vscode}/lib/dtd_service.dart | 0 .../{dart => vscode}/lib/flc_data.dart | 0 .../lib/rohd_source_navigator.dart | 0 .../lib/source_navigator.dart | 0 rohd_extension/{dart => vscode}/pubspec.yaml | 0 .../{dart => vscode}/test/flc_data_test.dart | 0 tool/gh_codespaces/install_flutter.sh | 43 ++- 79 files changed, 373 insertions(+), 584 deletions(-) delete mode 100644 packages/rohd_hierarchy/analysis_options.yaml delete mode 100644 packages/rohd_waveform/analysis_options.yaml rename rohd_extension/{dart => vscode}/LICENSE (100%) rename rohd_extension/{dart => vscode}/lib/dtd_service.dart (100%) rename rohd_extension/{dart => vscode}/lib/flc_data.dart (100%) rename rohd_extension/{dart => vscode}/lib/rohd_source_navigator.dart (100%) rename rohd_extension/{dart => vscode}/lib/source_navigator.dart (100%) rename rohd_extension/{dart => vscode}/pubspec.yaml (100%) rename rohd_extension/{dart => vscode}/test/flc_data_test.dart (100%) diff --git a/.github/workflows/build_devtool.yml b/.github/workflows/build_devtool.yml index d88476cd6..12e761153 100644 --- a/.github/workflows/build_devtool.yml +++ b/.github/workflows/build_devtool.yml @@ -18,11 +18,8 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup Flutter SDK - uses: flutter-actions/setup-flutter@v2 - with: - channel: stable - version: 3.47.0 + - name: Setup Flutter and Dart + run: tool/gh_codespaces/install_flutter.sh - name: Install project dependencies run: tool/gh_actions/install_dependencies.sh diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 9a275cfc4..0f070a93e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -20,14 +20,8 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Setup Dart - uses: dart-lang/setup-dart@v1 - - - name: Setup Flutter - uses: flutter-actions/setup-flutter@v2 - with: - channel: stable - version: 3.47.0 + - name: Setup Flutter and Dart + run: tool/gh_codespaces/install_flutter.sh - name: Install dependencies run: tool/gh_actions/install_dependencies.sh diff --git a/.github/workflows/general.yml b/.github/workflows/general.yml index 043783a3b..0739eea6b 100644 --- a/.github/workflows/general.yml +++ b/.github/workflows/general.yml @@ -32,14 +32,8 @@ jobs: use-quiet-mode: yes # output is too noisy, see https://github.com/gaurav-nelson/github-action-markdown-link-check/issues/121 config-file: .github/configs/mlc_config.json - - name: Setup Dart - uses: dart-lang/setup-dart@v1 - - - name: Setup Flutter - uses: flutter-actions/setup-flutter@v2 - with: - channel: stable - version: 3.47.0 + - name: Setup Flutter and Dart + run: tool/gh_codespaces/install_flutter.sh - name: Setup Node uses: actions/setup-node@v4 @@ -77,9 +71,7 @@ jobs: - name: Build dev container and run tests in it uses: devcontainers/ci@v0.3 with: - runCmd: >- - tool/gh_codespaces/install_flutter.sh && - tool/gh_actions/run_tests.sh + runCmd: tool/gh_actions/run_tests.sh deploy-documentation: name: Deploy Documentation @@ -93,14 +85,8 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Setup Dart - uses: dart-lang/setup-dart@v1 - - - name: Setup Flutter - uses: flutter-actions/setup-flutter@v2 - with: - channel: stable - version: 3.47.0 + - name: Setup Flutter and Dart + run: tool/gh_codespaces/install_flutter.sh - name: Install project dependencies run: tool/gh_actions/install_dependencies.sh @@ -121,11 +107,8 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup Flutter SDK - uses: flutter-actions/setup-flutter@v2 - with: - channel: stable - version: 3.47.0 + - name: Setup Flutter and Dart + run: tool/gh_codespaces/install_flutter.sh - name: Install project dependencies run: tool/gh_actions/install_dependencies.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index acbcc9cdb..6294c1c42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,27 +1,3 @@ -## Next Release - -- Migrated active packages to a pub workspace. The root `workspace:` list is - the single package roster, and `tool/workspace.dart` now provides - repository-wide analysis, native and Node.js test commands, and generation of - the multi-root VSCode workspace. -- Added the `ModuleService` API for module-scoped generation, capture, and - inspection services. `ModuleServices` registers and looks up services for a - built module hierarchy, and `hierarchyJson` exposes its hierarchy as JSON. -- Added `ArtifactProducingService` and `ModuleServiceArtifact` for - transport-neutral output. Artifact-producing services default - `outputDirectory` to the current directory and `outputBaseName` to the - module definition name, and expose named, media-typed byte streams without - requiring filesystem output. -- Added `SystemVerilogService` for configured SystemVerilog synthesis, - in-memory source output, artifact inspection, and explicit directory writes. - Added `WaveformService` for in-memory waveform capture with optional file - writing through `writeToFile`. -- Added legacy-compatible `Module.dumpSystemVerilog` and `Module.dumpWaves` - convenience methods. `dumpSystemVerilog()` provides simple in-memory output - or writes an optional `outputPath`; `dumpWaves()` replaces `dumpWaveforms` - for standard VCD capture. `WaveDumper` and `generateSynth` are deprecated in - favor of these `Module` methods. - ## 0.6.10 - Improved `Logic.replicate(1)` and same-width `signExtend` to return the original signal, eliminating redundant replication modules and generated SystemVerilog (). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ef83f035..81acfb9d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ Anyone interested in participating in ROHD is more than welcome to help! ## Code of Conduct -ROHD adopts the [Contributor Covenant](https://www.contributor-covenant.org/) v2.1 for the code of conduct. It can be accessed [Code of Conduct](CODE_OF_CONDUCT.md). +ROHD adopts the [Contributor Covenant](https://www.contributor-covenant.org/) v2.1 for the [Code of Conduct](CODE_OF_CONDUCT.md). ## Getting Help @@ -72,10 +72,7 @@ The below button will allow you to create a GitHub Codespace with ROHD already c ### Core ROHD Setup and Validation The root [`pubspec.yaml`](pubspec.yaml) `workspace:` list defines the active -packages. The legacy -[`doc/tutorials/chapter_9/rohd_vf_example`](doc/tutorials/chapter_9/rohd_vf_example) -is intentionally outside the workspace because it demonstrates an older -published ROHD release. +packages. For core ROHD development, clone the repository and use Dart from the repository root: diff --git a/packages/rohd_hierarchy/analysis_options.yaml b/packages/rohd_hierarchy/analysis_options.yaml deleted file mode 100644 index a96029588..000000000 --- a/packages/rohd_hierarchy/analysis_options.yaml +++ /dev/null @@ -1,10 +0,0 @@ -analyzer: - exclude: - - build/** - - android/** - - ios/** - - web/** - - windows/** - - macos/** - - linux/** -include: ../../analysis_options.yaml diff --git a/packages/rohd_waveform/analysis_options.yaml b/packages/rohd_waveform/analysis_options.yaml deleted file mode 100644 index a96029588..000000000 --- a/packages/rohd_waveform/analysis_options.yaml +++ /dev/null @@ -1,10 +0,0 @@ -analyzer: - exclude: - - build/** - - android/** - - ios/** - - web/** - - windows/** - - macos/** - - linux/** -include: ../../analysis_options.yaml diff --git a/pubspec.yaml b/pubspec.yaml index 0b4e5d171..d4acd9649 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,7 @@ workspace: - packages/rohd_waveform - rohd_devtools_extension - rohd_devtools_extension/packages/rohd_devtools_widgets - - rohd_extension/dart + - rohd_extension/vscode dependencies: collection: ^1.15.0 diff --git a/rohd-multipackage.code-workspace b/rohd-multipackage.code-workspace index 92a381b9d..3b6e3aaa8 100644 --- a/rohd-multipackage.code-workspace +++ b/rohd-multipackage.code-workspace @@ -21,8 +21,8 @@ "path": "rohd_devtools_extension/packages/rohd_devtools_widgets" }, { - "name": "dart", - "path": "rohd_extension/dart" + "name": "vscode", + "path": "rohd_extension/vscode" } ], "settings": { diff --git a/rohd_devtools_extension/analysis_options.yaml b/rohd_devtools_extension/analysis_options.yaml index 1bfb3d100..d770e9ca6 100644 --- a/rohd_devtools_extension/analysis_options.yaml +++ b/rohd_devtools_extension/analysis_options.yaml @@ -1,6 +1,3 @@ -# Lints set up with some guidance from here: -# https://rydmike.com/blog_flutter_linting.html - analyzer: exclude: - build/** @@ -10,249 +7,4 @@ analyzer: - windows/** - macos/** - linux/** - language: - strict-casts: true - strict-inference: true - strict-raw-types: true - -# keep up to date, matching https://dart.dev/tools/linter-rules/all -# some lints are not yet available, so disabled and marked with [not currently recognized] -linter: - rules: - - always_declare_return_types - - always_put_control_body_on_new_line - - always_put_required_named_parameters_first - # - always_specify_types - - always_use_package_imports - - annotate_overrides - - annotate_redeclares - # - avoid_annotating_with_dynamic - - avoid_bool_literals_in_conditional_expressions - - avoid_catches_without_on_clauses - - avoid_catching_errors - # - avoid_classes_with_only_static_members - - avoid_double_and_int_checks - - avoid_dynamic_calls - - avoid_empty_else - - avoid_equals_and_hash_code_on_mutable_classes - - avoid_escaping_inner_quotes - - 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_multiple_declarations_per_line - - avoid_null_checks_in_equality_operators - - avoid_positional_boolean_parameters - - avoid_print - - avoid_private_typedef_functions - - avoid_redundant_argument_values - - avoid_relative_lib_imports - - avoid_renaming_method_parameters - - avoid_return_types_on_setters - - avoid_returning_null_for_void - - avoid_returning_this - - avoid_setters_without_getters - - avoid_shadowing_type_parameters - - avoid_single_cascade_in_expression_statements - - avoid_slow_async_io - - avoid_type_to_string - - avoid_types_as_parameter_names - - avoid_types_on_closure_parameters - - avoid_unnecessary_containers - - avoid_unused_constructor_parameters - - avoid_void_async - - avoid_web_libraries_in_flutter - - await_only_futures - - camel_case_extensions - - camel_case_types - - cancel_subscriptions - - cascade_invocations - - cast_nullable_to_non_nullable - - close_sinks - - collection_methods_unrelated_type - - combinators_ordering - - comment_references - - conditional_uri_does_not_exist - - constant_identifier_names - - control_flow_in_finally - - curly_braces_in_flow_control_structures - - dangling_library_doc_comments - - depend_on_referenced_packages - - deprecated_consistency - - deprecated_member_use_from_same_package - - diagnostic_describe_all_properties - - directives_ordering - - discarded_futures - - do_not_use_environment - # - document_ignores - - empty_catches - - empty_constructor_bodies - - empty_statements - - eol_at_end_of_file - - exhaustive_cases - - file_names - - flutter_style_todos - - hash_and_equals - - implementation_imports - - 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 - - library_names - - library_prefixes - - library_private_types_in_public_api - - 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 - - no_duplicate_case_values - - no_leading_underscores_for_library_prefixes - - no_leading_underscores_for_local_identifiers - - no_literal_bool_comparisons - - no_logic_in_create_state - - no_runtimeType_toString - - no_self_assignments - - no_wildcard_variable_uses - - non_constant_identifier_names - - noop_primitive_operations - - 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_names - - package_prefixed_library_names - # parameter_assignments - disabled; ROHD idiomatically reassigns - # constructor parameters via addInput/addOutput. - # - parameter_assignments - - prefer_adjacent_string_concatenation - - prefer_asserts_in_initializer_lists - - prefer_asserts_with_message - - prefer_collection_literals - - prefer_conditional_assignment - - prefer_const_constructors - - prefer_const_constructors_in_immutables - - prefer_const_declarations - - prefer_const_literals_to_create_immutables - - prefer_constructors_over_static_methods - - prefer_contains - # - prefer_double_quotes - - prefer_expression_function_bodies - - prefer_final_fields - - prefer_final_in_for_each - - prefer_final_locals - # - prefer_final_parameters - - prefer_for_elements_to_map_fromIterable - - prefer_foreach - - prefer_function_declarations_over_variables - - prefer_generic_function_type_aliases - - prefer_if_elements_to_conditional_expressions - - prefer_if_null_operators - - prefer_initializing_formals - - prefer_inlined_adds - - prefer_int_literals - - prefer_interpolation_to_compose_strings - - prefer_is_empty - - prefer_is_not_empty - - prefer_is_not_operator - - prefer_iterable_whereType - - prefer_mixin - - prefer_null_aware_method_calls - - prefer_null_aware_operators - # - prefer_relative_imports - - prefer_single_quotes - - prefer_spread_collections - - prefer_typing_uninitialized_variables - - prefer_void_to_null - - provide_deprecation_message - - public_member_api_docs - - recursive_getters - # - require_trailing_commas - - secure_pubspec_urls - - sized_box_for_whitespace - - sized_box_shrink_expand - - slash_for_doc_comments - - sort_child_properties_last - # - 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 - - type_annotate_public_apis - - 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 - - unnecessary_const - - 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 - - unnecessary_null_checks - - unnecessary_null_in_if_null_operators - - unnecessary_nullable_for_final_variable_declarations - - unnecessary_overrides - - unnecessary_parenthesis - - unnecessary_raw_strings - # - unnecessary_statements - - unnecessary_string_escapes - - unnecessary_string_interpolations - - unnecessary_this - - unnecessary_to_list_in_spreads - # - unnecessary_unawaited - - unnecessary_underscores - # - unreachable_from_main - - unrelated_type_equality_checks - # - unsafe_variance - - use_build_context_synchronously - - use_colored_box - - use_decorated_box - - use_enums - - use_full_hex_values_for_flutter_colors - - use_function_type_syntax_for_parameters - - use_if_null_to_convert_nulls_to_bools - - use_is_even_rather_than_modulo - - 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 - - use_string_buffers - - use_string_in_part_of_directives - - use_super_parameters - - use_test_throws_matchers - - use_to_and_as_if_applicable - - use_truncating_division - - valid_regexps - - void_checks \ No newline at end of file +include: ../analysis_options.yaml diff --git a/rohd_devtools_extension/lib/main.dart b/rohd_devtools_extension/lib/main.dart index 278c04212..98336fa23 100644 --- a/rohd_devtools_extension/lib/main.dart +++ b/rohd_devtools_extension/lib/main.dart @@ -14,8 +14,8 @@ import 'package:devtools_app_shared/utils.dart'; import 'package:devtools_extensions/api.dart'; import 'package:devtools_extensions/devtools_extensions.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/const/app_theme.dart'; import 'package:rohd_devtools_extension/rohd_devtools/view/rohd_devtools_page.dart'; import 'package:rohd_devtools_extension/rohd_devtools_observer.dart'; diff --git a/rohd_devtools_extension/lib/main_standalone.dart b/rohd_devtools_extension/lib/main_standalone.dart index f42e8c4f6..565811e66 100644 --- a/rohd_devtools_extension/lib/main_standalone.dart +++ b/rohd_devtools_extension/lib/main_standalone.dart @@ -14,8 +14,8 @@ // Author: Desmond Kirkpatrick import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/services/services.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/standalone_app_shell.dart'; diff --git a/rohd_devtools_extension/lib/rohd_devtools/const/app_theme.dart b/rohd_devtools_extension/lib/rohd_devtools/const/app_theme.dart index 2c6df9e89..fac67eab0 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/const/app_theme.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/const/app_theme.dart @@ -7,7 +7,7 @@ // 2026 January // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; const _fontFallback = ['Noto Color Emoji']; diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/details_help_button.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/details_help_button.dart index 4d5278be6..3d9753ef6 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/details_help_button.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/details_help_button.dart @@ -11,7 +11,7 @@ // Author: Desmond Kirkpatrick import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/devtool_appbar.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/devtool_appbar.dart index 53fc54e6a..83898f5e0 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/devtool_appbar.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/devtool_appbar.dart @@ -8,8 +8,8 @@ // Author: Yao Jing Quek import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/cubits.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/devtools_help_button.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/platform_icon.dart'; diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/devtools_connection_host.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/devtools_connection_host.dart index de4b5d010..259b355c5 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/devtools_connection_host.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/devtools_connection_host.dart @@ -12,7 +12,7 @@ import 'dart:async'; import 'package:dtd/dtd.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/dtd_vm_service_info.dart'; import 'package:rohd_devtools_extension/rohd_devtools/services/services.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/ui.dart'; @@ -1084,7 +1084,7 @@ abstract class DevToolsConnectionHostState /// /// Connects to DTD, calls getVmServices(), returns the list. /// Also probes for registered services (new DTD 4.0 API). - Future> discoverVmServices(String dtdUri) async => + Future> discoverVmServices(String dtdUri) => discoverVmServicesViaDtd( dtdUri, onRegisteredServices: (serviceNames) { diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/devtools_help_button.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/devtools_help_button.dart index 2e7ff4c16..ca698bc0a 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/devtools_help_button.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/devtools_help_button.dart @@ -11,7 +11,7 @@ // Author: Desmond Kirkpatrick import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/module_tree_card.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/module_tree_card.dart index 9cf9e0741..ec9d0a4a4 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/module_tree_card.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/module_tree_card.dart @@ -8,10 +8,9 @@ // Author: Yao Jing Quek import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_simple_treeview/flutter_simple_treeview.dart'; - +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/cubits.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/tree_model.dart'; import 'package:rohd_devtools_extension/rohd_devtools/services/services.dart'; diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/module_tree_details_navbar.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/module_tree_details_navbar.dart index 183684ce2..8883b2c8f 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/module_tree_details_navbar.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/module_tree_details_navbar.dart @@ -8,8 +8,8 @@ // Author: Yao Jing Quek import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/cubits.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/details_help_button.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/platform_icon.dart'; diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/platform_icon.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/platform_icon.dart index 821c515d9..bbf908e9e 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/platform_icon.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/platform_icon.dart @@ -10,7 +10,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; /// A widget that renders either a Material Icon or emoji text based on /// platform emoji font availability. diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/schematic_icon.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/schematic_icon.dart index b8a5c69df..d71f7b14c 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/schematic_icon.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/schematic_icon.dart @@ -9,7 +9,7 @@ // Author: Desmond Kirkpatrick import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; /// A custom-painted icon showing three colored rectangles connected /// by orthogonal (right-angle) wires — a miniature schematic diagram. diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/signal_details_card.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/signal_details_card.dart index c3972ff40..d1eaac830 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/signal_details_card.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/signal_details_card.dart @@ -10,7 +10,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/snapshot_cubit.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/tree_model.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/details_help_button.dart'; diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/signal_table.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/signal_table.dart index 140da744b..308d8a121 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/signal_table.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/signal_table.dart @@ -8,7 +8,7 @@ // Author: Yao Jing Quek import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/snapshot_cubit.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/signal_model.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/tree_model.dart'; diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/signal_table_text_field.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/signal_table_text_field.dart index 23a4e480b..1f23f2175 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/signal_table_text_field.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/signal_table_text_field.dart @@ -8,7 +8,7 @@ // Author: Yao Jing Quek import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; /// A text field widget for filtering signals in the signal table. /// diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/standalone_app_shell.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/standalone_app_shell.dart index 62cbe2ed2..2c1a04581 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/standalone_app_shell.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/standalone_app_shell.dart @@ -10,8 +10,8 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/const/app_theme.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/cubits.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/dtd_vm_service_info.dart'; diff --git a/rohd_devtools_extension/lib/rohd_devtools/ui/vm_connection_form.dart b/rohd_devtools_extension/lib/rohd_devtools/ui/vm_connection_form.dart index 421bf5433..6d51e52e4 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/ui/vm_connection_form.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/ui/vm_connection_form.dart @@ -10,7 +10,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/platform_icon.dart'; /// Describes a single VM service discovered via DTD. diff --git a/rohd_devtools_extension/lib/rohd_devtools/view/rohd_devtools_page.dart b/rohd_devtools_extension/lib/rohd_devtools/view/rohd_devtools_page.dart index c999cb61b..a17923cd2 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/view/rohd_devtools_page.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/view/rohd_devtools_page.dart @@ -8,8 +8,8 @@ // Author: Roberto Torres import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/const/app_theme.dart'; import 'package:rohd_devtools_extension/rohd_devtools/rohd_devtools.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/ui.dart'; diff --git a/rohd_devtools_extension/lib/rohd_devtools/view/tree_structure_page.dart b/rohd_devtools_extension/lib/rohd_devtools/view/tree_structure_page.dart index 83dca6df7..8369557ff 100644 --- a/rohd_devtools_extension/lib/rohd_devtools/view/tree_structure_page.dart +++ b/rohd_devtools_extension/lib/rohd_devtools/view/tree_structure_page.dart @@ -8,8 +8,8 @@ // Author: Yao Jing Quek import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/cubits.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/analysis_options.yaml b/rohd_devtools_extension/packages/rohd_devtools_widgets/analysis_options.yaml index c3810a1c8..0d5eaab35 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/analysis_options.yaml +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/analysis_options.yaml @@ -7,4 +7,4 @@ analyzer: - windows/** - macos/** - linux/** -include: package:lints/recommended.yaml +include: ../../../analysis_options.yaml diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/rohd_devtools_widgets.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/rohd_devtools_widgets.dart index 452567fae..799f4e945 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/rohd_devtools_widgets.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/rohd_devtools_widgets.dart @@ -8,34 +8,27 @@ // 2026 April // Author: Desmond Kirkpatrick -// Help -export 'src/markdown_help_button.dart'; - // Overlay export 'src/app_bar_overlay.dart'; - +// Shared "Expand Bits" / "Define Bit Fields" popup-menu helpers +export 'src/bit_expansion_menu.dart'; +// Bit-field parsing, formatting, and dialog utilities +export 'src/bit_field_utils.dart'; // PNG export export 'src/capture_boundary.dart'; -export 'src/export_button.dart'; -export 'src/export_toast.dart'; -export 'src/save_png_stub.dart' - if (dart.library.io) 'src/save_png_native.dart' - if (dart.library.js_interop) 'src/save_png_web.dart'; - -// Cross-probing -export 'src/cross_probe_service.dart'; export 'src/cross_probe_button.dart'; export 'src/cross_probe_menu.dart'; - +// Cross-probing +export 'src/cross_probe_service.dart'; +export 'src/export_button.dart'; +export 'src/export_toast.dart'; // Logic type utilities export 'src/logic_type_utils.dart'; - -// Bit-field parsing, formatting, and dialog utilities -export 'src/bit_field_utils.dart'; - -// Shared "Expand Bits" / "Define Bit Fields" popup-menu helpers -export 'src/bit_expansion_menu.dart'; - +// Help +export 'src/markdown_help_button.dart'; +export 'src/rohd_extension_client.dart'; // ROHD extension client export 'src/rohd_extension_status.dart'; -export 'src/rohd_extension_client.dart'; +export 'src/save_png_stub.dart' + if (dart.library.io) 'src/save_png_native.dart' + if (dart.library.js_interop) 'src/save_png_web.dart'; diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/app_bar_overlay.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/app_bar_overlay.dart index ba210d5b2..ce2c8b992 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/app_bar_overlay.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/app_bar_overlay.dart @@ -14,7 +14,8 @@ // 2026 April // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +import 'package:material_ui/material_ui.dart'; /// Wraps a [body] widget and an [appBar] widget, where the AppBar /// auto-hides by sliding up when [autoHide] is true. @@ -41,10 +42,11 @@ class AppBarOverlay extends StatefulWidget { /// Duration of the slide animation. final Duration animationDuration; + /// Creates an [AppBarOverlay]. const AppBarOverlay({ - super.key, required this.appBar, required this.body, + super.key, this.autoHide = false, this.triggerHeight = 12, this.panelOpacity = 0.92, @@ -53,6 +55,18 @@ class AppBarOverlay extends StatefulWidget { @override State createState() => _AppBarOverlayState(); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('autoHide', autoHide)) + ..add(DoubleProperty('triggerHeight', triggerHeight)) + ..add(DoubleProperty('panelOpacity', panelOpacity)) + ..add( + DiagnosticsProperty('animationDuration', animationDuration), + ); + } } class _AppBarOverlayState extends State @@ -105,7 +119,9 @@ class _AppBarOverlayState extends State } void _hide() { - if (!widget.autoHide) return; + if (!widget.autoHide) { + return; + } _controller.reverse(); } diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/bit_expansion_menu.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/bit_expansion_menu.dart index c01c55e31..7c707870d 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/bit_expansion_menu.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/bit_expansion_menu.dart @@ -10,20 +10,20 @@ // 2026 January // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; -import 'bit_field_utils.dart'; +import 'package:rohd_devtools_widgets/src/bit_field_utils.dart'; /// Popup-menu values used by the bit-expansion items. /// /// Callers may match against these string constants when handling a /// `showMenu` result that includes bit-expansion items. abstract final class BitExpansionMenuValues { - /// Menu item: "Expand Bits [N]" — expand each bit (or a chosen range) + /// Menu item: "Expand Bits \[N\]" — expand each bit (or a chosen range) /// as a synthesized 1-bit waveform. static const String expandBits = 'expand_bits'; - /// Menu item: "Define Bit Fields [N]..." — open a dialog that lets the + /// Menu item: "Define Bit Fields \[N\]..." — open a dialog that lets the /// user name arbitrary bit ranges. static const String defineFields = 'define_fields'; } @@ -44,6 +44,7 @@ class BitExpandRangeAction extends BitExpansionAction { /// High bit (inclusive) of the range to expand. final int bitEnd; + /// Creates an action that expands the inclusive bit range. const BitExpandRangeAction(this.bitStart, this.bitEnd); } @@ -53,6 +54,7 @@ class BitDefineFieldsAction extends BitExpansionAction { /// The user-defined bit fields. final List fields; + /// Creates an action that defines [fields]. const BitDefineFieldsAction(this.fields); } @@ -73,24 +75,24 @@ List> buildBitExpansionMenuItems({ double fontSize = 13, double itemHeight = 32, bool includeDivider = false, -}) { - return >[ - if (includeDivider) const PopupMenuDivider(height: 8), - PopupMenuItem( - height: itemHeight, - value: BitExpansionMenuValues.expandBits, - child: Text('Expand Bits [$width]', style: TextStyle(fontSize: fontSize)), - ), - PopupMenuItem( - height: itemHeight, - value: BitExpansionMenuValues.defineFields, - child: Text( - 'Define Bit Fields [$width]...', - style: TextStyle(fontSize: fontSize), +}) => + >[ + if (includeDivider) const PopupMenuDivider(height: 8), + PopupMenuItem( + height: itemHeight, + value: BitExpansionMenuValues.expandBits, + child: + Text('Expand Bits [$width]', style: TextStyle(fontSize: fontSize)), ), - ), - ]; -} + PopupMenuItem( + height: itemHeight, + value: BitExpansionMenuValues.defineFields, + child: Text( + 'Define Bit Fields [$width]...', + style: TextStyle(fontSize: fontSize), + ), + ), + ]; /// Translate a popup-menu [value] returned by `showMenu` into a /// [BitExpansionAction], showing any follow-up dialog as needed. @@ -122,7 +124,9 @@ Future resolveBitExpansionMenuValue( signalName: signalName, width: width, ); - if (parsed == null) return null; + if (parsed == null) { + return null; + } final (high, low) = parsed; return BitExpandRangeAction(low, high); } @@ -132,7 +136,9 @@ Future resolveBitExpansionMenuValue( signalName: signalName, width: width, ); - if (fields == null || fields.isEmpty) return null; + if (fields == null || fields.isEmpty) { + return null; + } return BitDefineFieldsAction(fields); } return null; diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/bit_field_utils.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/bit_field_utils.dart index efb61eb93..bb27b841b 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/bit_field_utils.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/bit_field_utils.dart @@ -7,7 +7,7 @@ // 2025 May // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; /// A named bit-field definition within a bitvector signal. class BitFieldDef { @@ -20,6 +20,7 @@ class BitFieldDef { /// Low bit (inclusive, LSB of the field). final int low; + /// Creates a bit-field definition. const BitFieldDef({ required this.name, required this.high, @@ -50,16 +51,22 @@ abstract final class BitFieldUtils { static (int, int)? parseBitRange(String input, int maxBit) { if (input.contains(':')) { final parts = input.split(':'); - if (parts.length != 2) return null; + if (parts.length != 2) { + return null; + } final high = int.tryParse(parts[0].trim()); final low = int.tryParse(parts[1].trim()); - if (high == null || low == null) return null; + if (high == null || low == null) { + return null; + } final h = high.clamp(0, maxBit); final l = low.clamp(0, maxBit); return h >= l ? (h, l) : (l, h); } final bit = int.tryParse(input); - if (bit == null) return null; + if (bit == null) { + return null; + } final clamped = bit.clamp(0, maxBit); return (clamped, clamped); } @@ -76,7 +83,9 @@ abstract final class BitFieldUtils { final fields = []; for (final rawLine in lines) { final line = rawLine.trim(); - if (line.isEmpty) continue; + if (line.isEmpty) { + continue; + } final tokens = _splitAsciiWhitespace(line); // Try: name high:low @@ -158,7 +167,9 @@ abstract final class BitFieldUtils { } static bool _isWord(String value) { - if (value.isEmpty) return false; + if (value.isEmpty) { + return false; + } for (var i = 0; i < value.length; i++) { final char = value.codeUnitAt(i); final isUppercase = char >= 65 && char <= 90; @@ -173,10 +184,14 @@ abstract final class BitFieldUtils { } static bool _isUnsignedDecimal(String value) { - if (value.isEmpty) return false; + if (value.isEmpty) { + return false; + } for (var i = 0; i < value.length; i++) { final char = value.codeUnitAt(i); - if (char < 48 || char > 57) return false; + if (char < 48 || char > 57) { + return false; + } } return true; } @@ -208,37 +223,37 @@ Future<(int, int)?> showBitRangeDialog( final result = await showDialog( context: context, barrierColor: Colors.black26, - builder: (ctx) { - return AlertDialog( - title: Text( - '$signalName [$width bits]', - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), + builder: (ctx) => AlertDialog( + title: Text( + '$signalName [$width bits]', + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), + ), + content: TextField( + controller: controller, + autofocus: true, + decoration: InputDecoration( + labelText: 'Bit range (high:low) or single bit', + hintText: '$maxBit:0', + isDense: true, ), - content: TextField( - controller: controller, - autofocus: true, - decoration: InputDecoration( - labelText: 'Bit range (high:low) or single bit', - hintText: '$maxBit:0', - isDense: true, - ), - onSubmitted: (value) => Navigator.of(ctx).pop(value), + onSubmitted: (value) => Navigator.of(ctx).pop(value), + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(ctx).pop(), + child: const Text('Cancel'), ), - actions: [ - TextButton( - onPressed: () => Navigator.of(ctx).pop(), - child: const Text('Cancel'), - ), - TextButton( - onPressed: () => Navigator.of(ctx).pop(controller.text), - child: const Text('OK'), - ), - ], - ); - }, + TextButton( + onPressed: () => Navigator.of(ctx).pop(controller.text), + child: const Text('OK'), + ), + ], + ), ); - if (result == null || result.trim().isEmpty) return null; + if (result == null || result.trim().isEmpty) { + return null; + } return BitFieldUtils.parseBitRange(result.trim(), maxBit); } @@ -258,11 +273,7 @@ Future?> showDefineBitFieldsDialog( // type additional fields without accidentally replacing existing ones. final hasExisting = existingDefs != null && existingDefs.isNotEmpty; final initialText = hasExisting - ? '${existingDefs.map((f) { - return f.high == f.low - ? '${f.name} ${f.high}' - : '${f.name} ${f.high}:${f.low}'; - }).join('\n')}\n' + ? '${_formatBitFieldDefs(existingDefs)}\n' : 'field0 $maxBit:0'; final controller = TextEditingController(text: initialText); @@ -282,44 +293,52 @@ Future?> showDefineBitFieldsDialog( final result = await showDialog( context: context, barrierColor: Colors.black26, - builder: (ctx) { - return AlertDialog( - title: Text( - '$signalName [$width bits] — Define Fields', - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), - ), - content: SizedBox( - width: 320, - child: TextField( - controller: controller, - autofocus: true, - maxLines: 8, - minLines: 3, - style: const TextStyle(fontFamily: 'monospace', fontSize: 13), - decoration: InputDecoration( - labelText: 'One field per line: name high:low', - hintText: 'exponent $maxBit:${maxBit - 10}\n' - 'mantissa ${maxBit - 11}:0', - isDense: true, - border: const OutlineInputBorder(), - ), + builder: (ctx) => AlertDialog( + title: Text( + '$signalName [$width bits] — Define Fields', + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), + ), + content: SizedBox( + width: 320, + child: TextField( + controller: controller, + autofocus: true, + maxLines: 8, + minLines: 3, + style: const TextStyle(fontFamily: 'monospace', fontSize: 13), + decoration: InputDecoration( + labelText: 'One field per line: name high:low', + hintText: 'exponent $maxBit:${maxBit - 10}\n' + 'mantissa ${maxBit - 11}:0', + isDense: true, + border: const OutlineInputBorder(), ), ), - actions: [ - TextButton( - onPressed: () => Navigator.of(ctx).pop(), - child: const Text('Cancel'), - ), - TextButton( - onPressed: () => Navigator.of(ctx).pop(controller.text), - child: const Text('OK'), - ), - ], - ); - }, + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(ctx).pop(), + child: const Text('Cancel'), + ), + TextButton( + onPressed: () => Navigator.of(ctx).pop(controller.text), + child: const Text('OK'), + ), + ], + ), ); - if (result == null || result.trim().isEmpty) return null; + if (result == null || result.trim().isEmpty) { + return null; + } final fields = BitFieldUtils.parseBitFieldDefs(result, maxBit); return fields.isEmpty ? null : fields; } + +String _formatBitFieldDefs(List fields) => fields + .map( + (field) => field.high == field.low + ? '${field.name} ${field.high}' + : '${field.name} ${field.high}:${field.low}', + ) + .join('\n'); diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/capture_boundary.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/capture_boundary.dart index 9c3e05ab8..fd14c3848 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/capture_boundary.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/capture_boundary.dart @@ -10,9 +10,8 @@ import 'dart:typed_data' show Uint8List; import 'dart:ui' as ui; -import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart' show RenderRepaintBoundary; - +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart' as export_png; /// Capture a [RepaintBoundary] identified by [boundaryKey], encode to PNG, diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_button.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_button.dart index ea6148492..857ed07c9 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_button.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_button.dart @@ -7,8 +7,9 @@ // 2026 June // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; -import 'cross_probe_service.dart'; +import 'package:flutter/foundation.dart'; +import 'package:material_ui/material_ui.dart'; +import 'package:rohd_devtools_widgets/src/cross_probe_service.dart'; /// A toolbar icon button for cross-probing signal selections between viewers. /// @@ -26,23 +27,27 @@ class CrossProbeButton extends StatelessWidget { const CrossProbeButton({required this.service, super.key}); @override - Widget build(BuildContext context) { - return ValueListenableBuilder( - valueListenable: service.isActive, - builder: (context, active, _) { - final color = active - ? Theme.of(context).colorScheme.primary - : Theme.of(context).disabledColor; - return Tooltip( - message: active - ? 'Cross-probing active — tap to disable' - : 'Cross-probing disabled — tap to enable', - child: IconButton( - icon: Icon(Icons.compare_arrows, color: color), - onPressed: () => service.isActive.value = !service.isActive.value, - ), - ); - }, - ); + Widget build(BuildContext context) => ValueListenableBuilder( + valueListenable: service.isActive, + builder: (context, active, _) { + final color = active + ? Theme.of(context).colorScheme.primary + : Theme.of(context).disabledColor; + return Tooltip( + message: active + ? 'Cross-probing active — tap to disable' + : 'Cross-probing disabled — tap to enable', + child: IconButton( + icon: Icon(Icons.compare_arrows, color: color), + onPressed: () => service.isActive.value = !service.isActive.value, + ), + ); + }, + ); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties.add(DiagnosticsProperty('service', service)); } } diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_menu.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_menu.dart index b8134e4ad..8aafe3bef 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_menu.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_menu.dart @@ -15,9 +15,9 @@ // 2026 June // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; -import 'rohd_extension_status.dart'; +import 'package:rohd_devtools_widgets/src/rohd_extension_status.dart'; /// Returns the source formats currently navigable for the active module. /// @@ -139,7 +139,9 @@ Widget _sourceFormatAssetIcon( ), ); - if (!isDark) return image; + if (!isDark) { + return image; + } return Container( width: size + 4, diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_service.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_service.dart index 694950740..7c6b5350a 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_service.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/cross_probe_service.dart @@ -64,7 +64,9 @@ class LocalCrossProbeChannel extends ChangeNotifier { /// /// Does nothing when [signalPaths] is empty. void broadcast(List signalPaths, String source) { - if (signalPaths.isEmpty) return; + if (signalPaths.isEmpty) { + return; + } _lastSource = source; _lastPaths = List.unmodifiable(signalPaths); notifyListeners(); @@ -75,7 +77,7 @@ class LocalCrossProbeChannel extends ChangeNotifier { /// /// Create one [LocalCrossProbeService] per viewer, all sharing the same /// [LocalCrossProbeChannel]. Each service filters out its own broadcasts -/// (matched by [source]) so viewers do not receive their own selections. +/// (matched by the source tag) so viewers do not receive their own selections. /// /// ```dart /// final channel = LocalCrossProbeChannel(); @@ -109,15 +111,21 @@ class LocalCrossProbeService implements CrossProbeService { } void _onChannelMessage() { - if (!isActive.value) return; + if (!isActive.value) { + return; + } final src = _channel.lastSource; - if (src == null || src == _source) return; // ignore own broadcasts + if (src == null || src == _source) { + return; + } incomingSignals.value = _channel.lastPaths; } @override void send(List signalPaths, {required String source}) { - if (!isActive.value || signalPaths.isEmpty) return; + if (!isActive.value || signalPaths.isEmpty) { + return; + } _channel.broadcast(signalPaths, source); } diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/export_button.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/export_button.dart index 4c0dd1327..c7f8e2bcb 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/export_button.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/export_button.dart @@ -7,7 +7,8 @@ // 2026 April // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +import 'package:material_ui/material_ui.dart'; /// Small camera-icon button for triggering PNG export. /// @@ -20,9 +21,10 @@ class ExportPngButton extends StatelessWidget { /// Tooltip text shown on hover. final String tooltip; + /// Creates an [ExportPngButton]. const ExportPngButton({ - super.key, required this.onPressed, + super.key, this.tooltip = 'Export as PNG', }); @@ -50,4 +52,12 @@ class ExportPngButton extends StatelessWidget { ), ); } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(ObjectFlagProperty.has('onPressed', onPressed)) + ..add(StringProperty('tooltip', tooltip)); + } } diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/export_toast.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/export_toast.dart index e962a6dd0..967e99177 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/export_toast.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/export_toast.dart @@ -9,7 +9,7 @@ import 'dart:async'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; /// Show a brief floating toast at the bottom of the screen. /// diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/markdown_help_button.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/markdown_help_button.dart index ddc373afd..9734a5c9a 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/markdown_help_button.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/markdown_help_button.dart @@ -20,7 +20,10 @@ // 2026 March // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:material_ui/material_ui.dart'; /// A help button that loads its content from a markdown asset file. /// @@ -109,6 +112,22 @@ class MarkdownHelpButton extends StatefulWidget { @override State createState() => _MarkdownHelpButtonState(); + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(StringProperty('assetPath', assetPath)) + ..add(DiagnosticsProperty('isDark', isDark)) + ..add(StringProperty('label', label)) + ..add(StringProperty('package', package)) + ..add( + DiagnosticsProperty?>( + 'substitutions', + substitutions, + ), + ); + } } class _MarkdownHelpButtonState extends State { @@ -118,7 +137,7 @@ class _MarkdownHelpButtonState extends State { @override void didChangeDependencies() { super.didChangeDependencies(); - _loadContent(); + unawaited(_loadContent()); } @override @@ -126,7 +145,7 @@ class _MarkdownHelpButtonState extends State { super.didUpdateWidget(oldWidget); if (oldWidget.assetPath != widget.assetPath || oldWidget.package != widget.package) { - _loadContent(); + unawaited(_loadContent()); } } @@ -139,13 +158,10 @@ class _MarkdownHelpButtonState extends State { // dependency in a host app), then fall back to the bare asset path // (standalone mode). This order avoids a spurious 404 on the web // when the bare path doesn't exist. - // Use catch-all because AssetBundle.loadString throws FlutterError - // (an Error, not Exception) when the asset is missing. try { raw = await assetBundle .loadString('packages/${widget.package}/${widget.assetPath}'); - // ignore: avoid_catches_without_on_clauses - } catch (_) { + } on Object { raw = await assetBundle.loadString(widget.assetPath); } } else { @@ -163,8 +179,7 @@ class _MarkdownHelpButtonState extends State { _content = _HelpContent.parse(raw); }); } - // ignore: avoid_catches_without_on_clauses - } catch (e) { + } on Object catch (e) { debugPrint('Failed to load help asset: $e'); if (mounted) { setState(() { @@ -281,7 +296,7 @@ class _MarkdownHelpButtonState extends State { } } - showDialog( + unawaited(showDialog( context: context, builder: (ctx) => Dialog( backgroundColor: bgColor, @@ -330,7 +345,7 @@ class _MarkdownHelpButtonState extends State { ), ), ), - ); + )); } } @@ -367,7 +382,7 @@ class _HelpContent { final title = _extractTitle(raw) ?? 'Help'; // Extract tooltip text. - String tooltip = ''; + var tooltip = ''; if (tooltipIdx >= 0 && detailsIdx > tooltipIdx) { tooltip = raw.substring(tooltipIdx + tooltipMarker.length, detailsIdx).trim(); @@ -392,7 +407,7 @@ class _HelpContent { final blocks = <_DetailBlock>[]; final lines = raw.split('\n'); - for (int i = 0; i < lines.length; i++) { + for (var i = 0; i < lines.length; i++) { final line = lines[i]; final trimmed = line.trim(); diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/rohd_extension_client.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/rohd_extension_client.dart index 6c1c59d69..155197562 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/rohd_extension_client.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/rohd_extension_client.dart @@ -13,8 +13,9 @@ // Author: Desmond Kirkpatrick import 'package:flutter/foundation.dart'; +import 'package:rohd_devtools_widgets/src/rohd_extension_status.dart'; + export 'rohd_extension_status.dart'; -import 'rohd_extension_status.dart'; /// Abstract client for the ROHD VS Code extension handshake. /// diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/rohd_extension_status.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/rohd_extension_status.dart index f87428254..9cfe3c74d 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/rohd_extension_status.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/rohd_extension_status.dart @@ -39,6 +39,7 @@ class RohdFormatInfo { /// Resolved absolute path to the file, if known. final String? path; + /// Creates information for one source format. const RohdFormatInfo({ required this.available, this.fileFound = false, @@ -92,6 +93,7 @@ class RohdModuleInfo { /// `true` while the extension is still loading an FST file asynchronously. final bool fstLoading; + /// Creates information for one ROHD module. const RohdModuleInfo({ required this.extensionAvailable, this.module, @@ -165,7 +167,9 @@ class RohdModuleInfo { final formats = {}; for (final entry in rawFormats.entries) { final fmt = _parseFormat(entry.key); - if (fmt == null) continue; + if (fmt == null) { + continue; + } final fmtMap = entry.value as Map? ?? const {}; formats[fmt] = RohdFormatInfo( available: fmtMap['available'] as bool? ?? false, diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/save_png_web.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/save_png_web.dart index 5b0b9221e..555d3cc0e 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/save_png_web.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/lib/src/save_png_web.dart @@ -25,8 +25,9 @@ Future savePngBytes(Uint8List pngBytes, String fileName) async { ..download = fileName ..style.display = 'none'; web.document.body!.append(anchor); - anchor.click(); - anchor.remove(); + anchor + ..click() + ..remove(); web.URL.revokeObjectURL(url); return null; } diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/pubspec.yaml b/rohd_devtools_extension/packages/rohd_devtools_widgets/pubspec.yaml index 5740acd0b..220459bc0 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/pubspec.yaml +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/pubspec.yaml @@ -5,10 +5,11 @@ publish_to: none resolution: workspace environment: - sdk: ^3.6.0 + sdk: '>=3.6.0 <4.0.0' flutter: '>=3.0.0' dependencies: flutter: {sdk: flutter} + material_ui: ^1.0.1 rohd: ^0.6.9 web: ^1.0.0 dev_dependencies: diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/app_bar_overlay_test.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/app_bar_overlay_test.dart index 080f41c11..acf9926b9 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/app_bar_overlay_test.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/app_bar_overlay_test.dart @@ -9,8 +9,8 @@ import 'dart:ui' show PointerDeviceKind; -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; void main() { diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/bit_expansion_menu_test.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/bit_expansion_menu_test.dart index 921ebe684..2575d494c 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/bit_expansion_menu_test.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/bit_expansion_menu_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; void main() { @@ -112,7 +112,7 @@ void main() { await tester.tap(find.text('OK')); await tester.pumpAndSettle(); - final range = await rangeFuture as BitExpandRangeAction; + final range = (await rangeFuture)! as BitExpandRangeAction; expect(range.bitStart, 3); expect(range.bitEnd, 6); @@ -127,7 +127,7 @@ void main() { await tester.tap(find.text('OK')); await tester.pumpAndSettle(); - final fields = await fieldsFuture as BitDefineFieldsAction; + final fields = (await fieldsFuture)! as BitDefineFieldsAction; expect(fields.fields.map((field) => field.name), ['upper', 'lower']); }); } diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/bit_field_utils_test.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/bit_field_utils_test.dart index 3999dfe58..2702a5048 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/bit_field_utils_test.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/bit_field_utils_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; void main() { diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/capture_boundary_test.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/capture_boundary_test.dart index d1574c192..a56d3b800 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/capture_boundary_test.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/capture_boundary_test.dart @@ -9,9 +9,9 @@ import 'dart:typed_data'; -import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart' show RenderRepaintBoundary; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; void main() { @@ -100,7 +100,7 @@ void main() { find.byWidgetPredicate( (widget) => widget is Text && - widget.data?.startsWith('Saved: /tmp/wave_') == true, + (widget.data?.startsWith('Saved: /tmp/wave_') ?? false), ), findsOneWidget, ); @@ -132,7 +132,7 @@ void main() { find.byWidgetPredicate( (widget) => widget is Text && - widget.data?.startsWith('Downloaded capture_') == true, + (widget.data?.startsWith('Downloaded capture_') ?? false), ), findsOneWidget, ); diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/cross_probe_button_test.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/cross_probe_button_test.dart index 22df3efc5..22e6064c9 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/cross_probe_button_test.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/cross_probe_button_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; void main() { diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/cross_probe_menu_test.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/cross_probe_menu_test.dart index 4da66a7af..454e2fa79 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/cross_probe_menu_test.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/cross_probe_menu_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; void main() { @@ -39,7 +39,7 @@ void main() { test('resolves default and exact navigable formats', () { expect(resolveNavigableFormats(null), kDefaultNavigableFormats); expect( - resolveNavigableFormats(const RohdModuleInfo(extensionAvailable: false)), + resolveNavigableFormats(RohdModuleInfo.unavailable), kDefaultNavigableFormats, ); expect( @@ -55,7 +55,6 @@ void main() { formats: { RohdSourceFormat.rohd: RohdFormatInfo( available: true, - fileFound: false, ), RohdSourceFormat.sv: RohdFormatInfo( available: false, @@ -67,18 +66,18 @@ void main() { isEmpty, ); - final info = RohdModuleInfo( + const info = RohdModuleInfo( extensionAvailable: true, formats: { - RohdSourceFormat.rohd: const RohdFormatInfo( + RohdSourceFormat.rohd: RohdFormatInfo( available: true, fileFound: true, ), - RohdSourceFormat.sc: const RohdFormatInfo( + RohdSourceFormat.sc: RohdFormatInfo( available: true, fileFound: true, ), - RohdSourceFormat.fst: const RohdFormatInfo( + RohdSourceFormat.fst: RohdFormatInfo( available: true, fileFound: true, ), @@ -96,8 +95,7 @@ void main() { final items = buildGotoSourceMenuItems( formats: [RohdSourceFormat.rohd, RohdSourceFormat.sv], count: 2, - showIcons: true, - iconBuilder: (format, {double size = 18}) => Icon( + iconBuilder: (format, {size = 18}) => Icon( Icons.code, key: ValueKey(format), size: size, @@ -185,7 +183,7 @@ void main() { ], size: 13, gap: 5, - iconBuilder: (format, {double size = 16}) => Icon( + iconBuilder: (format, {size = 16}) => Icon( Icons.code, key: ValueKey('strip-${format.name}'), size: size, diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/export_button_test.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/export_button_test.dart index bdabebc52..0fc8bc907 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/export_button_test.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/export_button_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; void main() { diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/export_toast_test.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/export_toast_test.dart index b2fa49cf9..51be8f170 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/export_toast_test.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/export_toast_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; void main() { diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/logic_type_utils_test.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/logic_type_utils_test.dart index 86c9b6e68..23675737a 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/logic_type_utils_test.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/logic_type_utils_test.dart @@ -151,7 +151,8 @@ void main() { expect( tooltip, - '''packet (Packet) + ''' +packet (Packet) payload: 4'b1010 nibble: 4'b1010 ...''', diff --git a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/markdown_help_button_test.dart b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/markdown_help_button_test.dart index c1731db48..ca5aae295 100644 --- a/rohd_devtools_extension/packages/rohd_devtools_widgets/test/markdown_help_button_test.dart +++ b/rohd_devtools_extension/packages/rohd_devtools_widgets/test/markdown_help_button_test.dart @@ -9,9 +9,9 @@ import 'dart:convert'; -import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_widgets/rohd_devtools_widgets.dart'; void main() { diff --git a/rohd_devtools_extension/pubspec.yaml b/rohd_devtools_extension/pubspec.yaml index 5ff05e6ec..94f880b23 100644 --- a/rohd_devtools_extension/pubspec.yaml +++ b/rohd_devtools_extension/pubspec.yaml @@ -21,6 +21,7 @@ dependencies: flutter_bloc: ^9.0.0 flutter_simple_treeview: ^3.0.2 logging: ^1.2.0 + material_ui: ^1.0.1 rohd: ^0.6.10 rohd_devtools_widgets: ^0.1.0 diff --git a/rohd_devtools_extension/test/const/app_theme_test.dart b/rohd_devtools_extension/test/const/app_theme_test.dart index b7510c70b..99b1199f9 100644 --- a/rohd_devtools_extension/test/const/app_theme_test.dart +++ b/rohd_devtools_extension/test/const/app_theme_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/const/app_theme.dart'; void main() { diff --git a/rohd_devtools_extension/test/cubit/basic_cubits_test.dart b/rohd_devtools_extension/test/cubit/basic_cubits_test.dart index d8a7d5d3c..9dd1847e3 100644 --- a/rohd_devtools_extension/test/cubit/basic_cubits_test.dart +++ b/rohd_devtools_extension/test/cubit/basic_cubits_test.dart @@ -17,7 +17,7 @@ import 'package:rohd_devtools_extension/rohd_devtools/models/tree_model.dart'; void main() { group('search term cubits', () { - test('store the latest signal and tree search terms', () async { + test('store the latest signal and tree search terms', () { final signalCubit = SignalSearchTermCubit(); final treeCubit = TreeSearchTermCubit(); addTearDown(signalCubit.close); @@ -34,7 +34,7 @@ void main() { }); }); - test('DetailsTabCubit selects each available details view', () async { + test('DetailsTabCubit selects each available details view', () { final cubit = DetailsTabCubit(); addTearDown(cubit.close); @@ -47,7 +47,7 @@ void main() { expect(cubit.state, DetailsTab.schematic); }); - test('SelectedModuleCubit exposes the selected module', () async { + test('SelectedModuleCubit exposes the selected module', () { final cubit = SelectedModuleCubit(); addTearDown(cubit.close); final module = TreeModel( @@ -66,7 +66,7 @@ void main() { }); group('DevToolsThemeCubit', () { - test('starts dark and toggles between the supported modes', () async { + test('starts dark and toggles between the supported modes', () { final cubit = DevToolsThemeCubit(); addTearDown(cubit.close); @@ -81,7 +81,7 @@ void main() { expect(cubit.state, DevToolsThemeMode.dark); }); - test('sets an explicit theme mode', () async { + test('sets an explicit theme mode', () { final cubit = DevToolsThemeCubit(); addTearDown(cubit.close); diff --git a/rohd_devtools_extension/test/cubit/snapshot_cubit_test.dart b/rohd_devtools_extension/test/cubit/snapshot_cubit_test.dart index 58f7d79d4..0e0fbbc08 100644 --- a/rohd_devtools_extension/test/cubit/snapshot_cubit_test.dart +++ b/rohd_devtools_extension/test/cubit/snapshot_cubit_test.dart @@ -156,7 +156,7 @@ void main() { expect(state.getSignal('top.counter')!.width, 8); }); - test('clear returns to camera mode and its initial state', () async { + test('clear returns to camera mode and its initial state', () { final cubit = SnapshotCubit(); addTearDown(cubit.close); diff --git a/rohd_devtools_extension/test/modules/tree_structure/model_tree_card_test.dart b/rohd_devtools_extension/test/modules/tree_structure/model_tree_card_test.dart index 85aa22124..9761386a1 100644 --- a/rohd_devtools_extension/test/modules/tree_structure/model_tree_card_test.dart +++ b/rohd_devtools_extension/test/modules/tree_structure/model_tree_card_test.dart @@ -7,9 +7,9 @@ // 2024 January 9 // Author: Yao Jing Quek -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/rohd_devtools.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/module_tree_card.dart'; diff --git a/rohd_devtools_extension/test/modules/tree_structure/tree_structure_page_test.dart b/rohd_devtools_extension/test/modules/tree_structure/tree_structure_page_test.dart index df8936c46..09cb13d5b 100644 --- a/rohd_devtools_extension/test/modules/tree_structure/tree_structure_page_test.dart +++ b/rohd_devtools_extension/test/modules/tree_structure/tree_structure_page_test.dart @@ -7,9 +7,9 @@ // 2024 January 9 // Author: Yao Jing Quek -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:mocktail/mocktail.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/tree_model.dart'; import 'package:rohd_devtools_extension/rohd_devtools/rohd_devtools.dart'; diff --git a/rohd_devtools_extension/test/ui/devtool_appbar_test.dart b/rohd_devtools_extension/test/ui/devtool_appbar_test.dart index e73fe2f61..771bd8b79 100644 --- a/rohd_devtools_extension/test/ui/devtool_appbar_test.dart +++ b/rohd_devtools_extension/test/ui/devtool_appbar_test.dart @@ -7,9 +7,9 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/theme_cubit.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/devtool_appbar.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/devtools_help_button.dart'; diff --git a/rohd_devtools_extension/test/ui/devtools_connection_host_lifecycle_test.dart b/rohd_devtools_extension/test/ui/devtools_connection_host_lifecycle_test.dart index 066efd90b..a14c4a632 100644 --- a/rohd_devtools_extension/test/ui/devtools_connection_host_lifecycle_test.dart +++ b/rohd_devtools_extension/test/ui/devtools_connection_host_lifecycle_test.dart @@ -10,8 +10,8 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:mocktail/mocktail.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/dtd_vm_service_info.dart'; import 'package:rohd_devtools_extension/rohd_devtools/services/connection_state_machine.dart'; @@ -80,7 +80,7 @@ class _TestConnectionHostState VmConnectionStrategy? get connectionStrategy => widget.strategy; @override - Future> discoverVmServices(String dtdUri) async => + Future> discoverVmServices(String dtdUri) => widget.discoverVmServices?.call(dtdUri) ?? super.discoverVmServices(dtdUri); diff --git a/rohd_devtools_extension/test/ui/diagnostic_properties_test.dart b/rohd_devtools_extension/test/ui/diagnostic_properties_test.dart index d6a6bdc2e..127968ce9 100644 --- a/rohd_devtools_extension/test/ui/diagnostic_properties_test.dart +++ b/rohd_devtools_extension/test/ui/diagnostic_properties_test.dart @@ -8,8 +8,8 @@ // Author: Desmond Kirkpatrick import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/snapshot_cubit.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/tree_model.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/ui.dart'; diff --git a/rohd_devtools_extension/test/ui/module_tree_details_navbar_test.dart b/rohd_devtools_extension/test/ui/module_tree_details_navbar_test.dart index 41c38b4d4..9895a4c2d 100644 --- a/rohd_devtools_extension/test/ui/module_tree_details_navbar_test.dart +++ b/rohd_devtools_extension/test/ui/module_tree_details_navbar_test.dart @@ -7,9 +7,9 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/details_tab_cubit.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/module_tree_details_navbar.dart'; diff --git a/rohd_devtools_extension/test/ui/presentation_widgets_test.dart b/rohd_devtools_extension/test/ui/presentation_widgets_test.dart index 6ed702aa3..0886bbe89 100644 --- a/rohd_devtools_extension/test/ui/presentation_widgets_test.dart +++ b/rohd_devtools_extension/test/ui/presentation_widgets_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/platform_icon.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/simulation_time_display.dart'; diff --git a/rohd_devtools_extension/test/ui/signal_details_card_test.dart b/rohd_devtools_extension/test/ui/signal_details_card_test.dart index ed9753a17..866af8cd1 100644 --- a/rohd_devtools_extension/test/ui/signal_details_card_test.dart +++ b/rohd_devtools_extension/test/ui/signal_details_card_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/snapshot_cubit.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/signal_model.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/tree_model.dart'; diff --git a/rohd_devtools_extension/test/ui/signal_table_test.dart b/rohd_devtools_extension/test/ui/signal_table_test.dart index 830db6c37..ec54e2d5b 100644 --- a/rohd_devtools_extension/test/ui/signal_table_test.dart +++ b/rohd_devtools_extension/test/ui/signal_table_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/cubit/snapshot_cubit.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/signal_model.dart'; import 'package:rohd_devtools_extension/rohd_devtools/models/tree_model.dart'; diff --git a/rohd_devtools_extension/test/ui/signal_table_text_field_test.dart b/rohd_devtools_extension/test/ui/signal_table_text_field_test.dart index 21848dbba..9a4cdae4c 100644 --- a/rohd_devtools_extension/test/ui/signal_table_text_field_test.dart +++ b/rohd_devtools_extension/test/ui/signal_table_text_field_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/signal_table_text_field.dart'; void main() { diff --git a/rohd_devtools_extension/test/ui/vm_connection_form_test.dart b/rohd_devtools_extension/test/ui/vm_connection_form_test.dart index 7d8cc2464..75eba4158 100644 --- a/rohd_devtools_extension/test/ui/vm_connection_form_test.dart +++ b/rohd_devtools_extension/test/ui/vm_connection_form_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/vm_connection_form.dart'; void main() { diff --git a/rohd_devtools_extension/test/view/rohd_devtools_page_test.dart b/rohd_devtools_extension/test/view/rohd_devtools_page_test.dart index 3b3d2c94d..70e393e96 100644 --- a/rohd_devtools_extension/test/view/rohd_devtools_page_test.dart +++ b/rohd_devtools_extension/test/view/rohd_devtools_page_test.dart @@ -7,8 +7,8 @@ // 2026 July // Author: Desmond Kirkpatrick -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:rohd_devtools_extension/rohd_devtools/rohd_devtools.dart'; import 'package:rohd_devtools_extension/rohd_devtools/ui/ui.dart'; diff --git a/rohd_devtools_extension/tool/test_devtools_install.dart b/rohd_devtools_extension/tool/test_devtools_install.dart index 0fe167819..2162c3ca1 100644 --- a/rohd_devtools_extension/tool/test_devtools_install.dart +++ b/rohd_devtools_extension/tool/test_devtools_install.dart @@ -77,7 +77,7 @@ Future main(List args) async { } } -Future<_ResolvedTarget> _resolveTarget(String target) async { +Future<_ResolvedTarget> _resolveTarget(String target) { final githubTree = _parseGithubTreeTarget(target); if (githubTree != null) { return _downloadGithubTree(githubTree); @@ -90,8 +90,10 @@ Future<_ResolvedTarget> _resolveTarget(String target) async { ); } - return _ResolvedTarget( - Directory(p.normalize(p.absolute(target))), + return Future.value( + _ResolvedTarget( + Directory(p.normalize(p.absolute(target))), + ), ); } diff --git a/rohd_extension/dart/LICENSE b/rohd_extension/vscode/LICENSE similarity index 100% rename from rohd_extension/dart/LICENSE rename to rohd_extension/vscode/LICENSE diff --git a/rohd_extension/dart/lib/dtd_service.dart b/rohd_extension/vscode/lib/dtd_service.dart similarity index 100% rename from rohd_extension/dart/lib/dtd_service.dart rename to rohd_extension/vscode/lib/dtd_service.dart diff --git a/rohd_extension/dart/lib/flc_data.dart b/rohd_extension/vscode/lib/flc_data.dart similarity index 100% rename from rohd_extension/dart/lib/flc_data.dart rename to rohd_extension/vscode/lib/flc_data.dart diff --git a/rohd_extension/dart/lib/rohd_source_navigator.dart b/rohd_extension/vscode/lib/rohd_source_navigator.dart similarity index 100% rename from rohd_extension/dart/lib/rohd_source_navigator.dart rename to rohd_extension/vscode/lib/rohd_source_navigator.dart diff --git a/rohd_extension/dart/lib/source_navigator.dart b/rohd_extension/vscode/lib/source_navigator.dart similarity index 100% rename from rohd_extension/dart/lib/source_navigator.dart rename to rohd_extension/vscode/lib/source_navigator.dart diff --git a/rohd_extension/dart/pubspec.yaml b/rohd_extension/vscode/pubspec.yaml similarity index 100% rename from rohd_extension/dart/pubspec.yaml rename to rohd_extension/vscode/pubspec.yaml diff --git a/rohd_extension/dart/test/flc_data_test.dart b/rohd_extension/vscode/test/flc_data_test.dart similarity index 100% rename from rohd_extension/dart/test/flc_data_test.dart rename to rohd_extension/vscode/test/flc_data_test.dart diff --git a/tool/gh_codespaces/install_flutter.sh b/tool/gh_codespaces/install_flutter.sh index 9b84ce08e..221283949 100755 --- a/tool/gh_codespaces/install_flutter.sh +++ b/tool/gh_codespaces/install_flutter.sh @@ -4,16 +4,48 @@ # SPDX-License-Identifier: BSD-3-Clause # # install_flutter.sh -# GitHub Codespaces setup: Install the Flutter SDK used by CI. +# Install the current stable Flutter SDK and its bundled Dart SDK. # # 2026 August # Author: Desmond Kirkpatrick set -euo pipefail -declare -r flutter_version='3.47.0' declare -r flutter_sdk_dir='/opt/flutter' -declare -r flutter_archive_url="https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${flutter_version}-stable.tar.xz" +declare -r flutter_releases_url='https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json' + +if ! command -v curl >/dev/null 2>&1 || + ! command -v python3 >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y curl python3 +fi + +release_manifest="$(mktemp)" +archive="$(mktemp)" +trap 'rm -f "${release_manifest}" "${archive}"' EXIT + +curl --fail --location --silent --show-error "${flutter_releases_url}" \ + --output "${release_manifest}" + +flutter_release="$( + python3 - "${release_manifest}" <<'PYTHON' +import json +import sys + +with open(sys.argv[1]) as manifest: + release_data = json.load(manifest) +stable_hash = release_data['current_release']['stable'] +stable_release = next( + release for release in release_data['releases'] + if release['hash'] == stable_hash +) +print(stable_release['version'], stable_release['archive']) +PYTHON +)" +read -r flutter_version flutter_archive_path <<< "${flutter_release}" +declare -r flutter_version +declare -r flutter_archive_path +declare -r flutter_archive_url="https://storage.googleapis.com/flutter_infra_release/releases/${flutter_archive_path}" if [[ -x "${flutter_sdk_dir}/bin/flutter" ]] && "${flutter_sdk_dir}/bin/flutter" --version | grep -q "Flutter ${flutter_version}"; then @@ -24,10 +56,7 @@ fi sudo rm -rf "${flutter_sdk_dir}" sudo apt-get update -sudo apt-get install -y curl xz-utils - -archive="$(mktemp)" -trap 'rm -f "${archive}"' EXIT +sudo apt-get install -y xz-utils curl --fail --location --silent --show-error "${flutter_archive_url}" \ --output "${archive}" From f98028a8628bcefa0efe5239609f5ad9b063fd94 Mon Sep 17 00:00:00 2001 From: "Desmond A. Kirkpatrick" Date: Mon, 24 Aug 2026 10:54:28 -0700 Subject: [PATCH 17/17] converge on proper support of dart -only as well as full flutter builds --- CONTRIBUTING.md | 23 +++++++++++++---------- tool/gh_actions/analyze_source.sh | 7 +------ tool/gh_actions/install_dependencies.sh | 19 ++++++++++++------- tool/gh_actions/run_tests.sh | 15 +++++---------- tool/gh_codespaces/install_flutter.sh | 7 +++++++ tool/workspace.dart | 15 +++++++++------ 6 files changed, 47 insertions(+), 39 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 81acfb9d7..17940eed8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,11 +41,13 @@ The [ROHD Forum](https://intel.github.io/rohd-website/forum/rohd-forum/) is a pe ### Requirements ROHD uses a [pub workspace](https://dart.dev/tools/pub/workspaces) for its -active packages. [Dart](https://dart.dev/get-dart) is sufficient to develop, -analyze, and test the core ROHD package. Install +active packages. Pub resolves every workspace member together, and some +members declare `sdk: flutter`, so [Flutter](https://docs.flutter.dev/get-started/install), which includes a -compatible Dart SDK, to develop the DevTools application or validate the full -mixed Dart/Flutter workspace. +compatible Dart SDK, is required to resolve dependencies anywhere in the +workspace, even for core-ROHD-only development. Once dependencies are +resolved, day-to-day analysis and testing of the core ROHD package uses plain +[Dart](https://dart.dev/get-dart) tooling (`dart analyze`, `dart test`). To run the complete ROHD test suite for development, you need to install [Icarus Verilog](https://steveicarus.github.io/iverilog/). It is used to compare SystemVerilog functionality with the ROHD simulator functionality. Installation instructions are available here: @@ -74,15 +76,17 @@ The below button will allow you to create a GitHub Codespace with ROHD already c The root [`pubspec.yaml`](pubspec.yaml) `workspace:` list defines the active packages. -For core ROHD development, clone the repository and use Dart from the -repository root: +For core ROHD development, clone the repository and resolve the workspace with +Flutter, then use Dart for everyday analysis and testing: ```shell git clone https://github.com/intel/rohd.git cd rohd -# Resolve the core package and workspace dependencies. -dart pub get +# Resolve the workspace dependencies. Flutter is required because pub +# resolves every workspace member together and some members declare +# `sdk: flutter`. +flutter pub get # Open Folder: open only the root ROHD package in VSCode. code . @@ -93,8 +97,7 @@ dart test ``` As a local convenience, `tool/gh_actions/install_dependencies.sh` performs the -same dependency-resolution step. It uses Flutter for the full workspace when -Flutter is installed and otherwise uses Dart for the core package. +same dependency-resolution step and requires Flutter to be installed. In VSCode, this is equivalent to **File > Open Folder...** and selecting the repository root. Use this mode when working only on the core ROHD package. diff --git a/tool/gh_actions/analyze_source.sh b/tool/gh_actions/analyze_source.sh index 3a7471e07..f9bfe8ee8 100755 --- a/tool/gh_actions/analyze_source.sh +++ b/tool/gh_actions/analyze_source.sh @@ -11,9 +11,4 @@ set -euo pipefail -if command -v flutter >/dev/null 2>&1; then - dart run tool/workspace.dart analyze -else - echo "Flutter is unavailable; analyzing the core ROHD package only." - dart analyze -fi +dart run tool/workspace.dart analyze diff --git a/tool/gh_actions/install_dependencies.sh b/tool/gh_actions/install_dependencies.sh index f6e2160a8..b6d1017e0 100755 --- a/tool/gh_actions/install_dependencies.sh +++ b/tool/gh_actions/install_dependencies.sh @@ -5,17 +5,22 @@ # # install_dependencies.sh # Installs dependencies from the repository root for local development or CI. -# Uses Flutter for the full workspace when available, otherwise Dart for core -# ROHD development. +# Pub resolves every member of this pub workspace together, and some members +# declare `sdk: flutter`, so Flutter is required to resolve the workspace, +# including the core ROHD package. # # 2022 October 7 # Author: Chykon set -euo pipefail -if command -v flutter >/dev/null 2>&1; then - flutter pub get -else - echo "Flutter is unavailable; resolving the core ROHD package with Dart." - dart pub get +if ! command -v flutter >/dev/null 2>&1; then + echo "Flutter is required to resolve this pub workspace. Pub resolves" >&2 + echo "every workspace member together, and some members declare" >&2 + echo "'sdk: flutter', so 'dart pub get' cannot resolve the workspace" >&2 + echo "without Flutter, even for core-ROHD-only development. Install" >&2 + echo "Flutter (see tool/gh_codespaces/install_flutter.sh) and retry." >&2 + exit 1 fi + +flutter pub get diff --git a/tool/gh_actions/run_tests.sh b/tool/gh_actions/run_tests.sh index c230624bc..6e5caf166 100755 --- a/tool/gh_actions/run_tests.sh +++ b/tool/gh_actions/run_tests.sh @@ -11,14 +11,9 @@ set -euo pipefail -if command -v flutter >/dev/null 2>&1; then - # Run workspace tests using each package's Dart or Flutter runner. - dart run tool/workspace.dart test +# Run workspace tests using each package's Dart or Flutter runner. +dart run tool/workspace.dart test - # Run workspace Dart tests in JS (increase heap size for large synthesis tests). - export NODE_OPTIONS="--max-old-space-size=8192" - dart run tool/workspace.dart test-node -else - echo "Flutter is unavailable; running native tests for the core ROHD package only." - dart test -fi \ No newline at end of file +# Run workspace Dart tests in JS (increase heap size for large synthesis tests). +export NODE_OPTIONS="--max-old-space-size=8192" +dart run tool/workspace.dart test-node \ No newline at end of file diff --git a/tool/gh_codespaces/install_flutter.sh b/tool/gh_codespaces/install_flutter.sh index 221283949..5ff09a870 100755 --- a/tool/gh_codespaces/install_flutter.sh +++ b/tool/gh_codespaces/install_flutter.sh @@ -49,6 +49,7 @@ declare -r flutter_archive_url="https://storage.googleapis.com/flutter_infra_rel if [[ -x "${flutter_sdk_dir}/bin/flutter" ]] && "${flutter_sdk_dir}/bin/flutter" --version | grep -q "Flutter ${flutter_version}"; then + sudo ln --force --symbolic "${flutter_sdk_dir}/bin/flutter" /usr/local/bin/flutter sudo ln --force --symbolic "${flutter_sdk_dir}/bin/dart" /usr/local/bin/dart echo "Flutter ${flutter_version} is already installed." exit 0 @@ -61,6 +62,12 @@ sudo apt-get install -y xz-utils curl --fail --location --silent --show-error "${flutter_archive_url}" \ --output "${archive}" sudo tar --extract --xz --file "${archive}" --directory /opt + +# The archive is extracted as root; transfer ownership to the invoking user so +# Flutter (run unprivileged below and by later steps) can write to its own SDK +# cache and Git does not reject the checkout for having dubious ownership. +sudo chown --recursive "$(id --user):$(id --group)" "${flutter_sdk_dir}" + sudo ln --force --symbolic "${flutter_sdk_dir}/bin/flutter" /usr/local/bin/flutter sudo ln --force --symbolic "${flutter_sdk_dir}/bin/dart" /usr/local/bin/dart diff --git a/tool/workspace.dart b/tool/workspace.dart index fba4164a3..3003e5ce0 100644 --- a/tool/workspace.dart +++ b/tool/workspace.dart @@ -47,14 +47,17 @@ Future main(List arguments) async { if (arguments.single == 'test-node' && packageUsesFlutter) { continue; } - final command = arguments.single == 'test-node' - ? 'dart' - : workspaceUsesFlutter - ? 'flutter' - : 'dart'; + + final command = switch (arguments.single) { + // There is no `dart clean`; `flutter clean` works for both Dart-only + // and Flutter packages. + 'clean' => 'flutter', + 'test-node' => 'dart', + _ => packageUsesFlutter ? 'flutter' : 'dart', + }; final commandArguments = switch (arguments.single) { - 'analyze' => const ['analyze', '--no-fatal-warnings'], + 'analyze' => const ['analyze', '--fatal-infos'], 'clean' => const ['clean'], 'test' => const ['test', '--exclude-tags', 'benchmark'], 'test-node' => const [