Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/rohd_hierarchy/lib/src/hierarchy_models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export 'hierarchy_occurrence.dart';
export 'hierarchy_search_result.dart';
export 'occurrence_address.dart';
export 'occurrence_search_result.dart';
export 'occurrence_trie.dart';
export 'signal_occurrence.dart';
export 'signal_search_result.dart';
104 changes: 104 additions & 0 deletions packages/rohd_hierarchy/lib/src/occurrence_trie.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright (C) 2026 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// occurrence_trie.dart
// Compact storage for values keyed by hierarchy occurrence addresses.
//
// 2026 August
// Author: Desmond Kirkpatrick <desmond.a.kirkpatrick@intel.com>

import 'package:rohd_hierarchy/src/occurrence_address.dart';

/// A prefix-sharing map from [OccurrenceAddress] values to values of type [T].
///
/// Common address prefixes are stored once, making this more compact than a
/// conventional map when many values belong to the same hierarchy subtree.
class OccurrenceTrie<T extends Object> {
Comment thread
desmonddak marked this conversation as resolved.
/// The root node, which represents [OccurrenceAddress.root].
final _OccurrenceTrieNode<T> _root = _OccurrenceTrieNode<T>();

/// Whether this trie contains no values.
bool get isEmpty => _root.isEmpty;

/// The value stored at [address], if any.
T? operator [](OccurrenceAddress address) {
var node = _root;
for (final index in _validatedPath(address)) {
final child = node.children[index];
if (child == null) {
return null;
}
node = child;
}
return node.value;
}

/// Associates [value] with [address].
void operator []=(OccurrenceAddress address, T value) {
var node = _root;
for (final index in _validatedPath(address)) {
node = node.children.putIfAbsent(index, _OccurrenceTrieNode<T>.new);
}
node.value = value;
}

/// Removes and returns the value stored at [address], if any.
T? remove(OccurrenceAddress address) {
final path = _validatedPath(address);
final nodes = <_OccurrenceTrieNode<T>>[_root];
var node = _root;
for (final index in path) {
final child = node.children[index];
if (child == null) {
return null;
}
nodes.add(child);
node = child;
}

final previous = node.value;
if (previous == null) {
return null;
}
node.value = null;
for (var index = path.length - 1; index >= 0; index--) {
final child = nodes[index + 1];
if (!child.isEmpty) {
break;
}
nodes[index].children.remove(path[index]);
}
return previous;
}

/// Removes every value from this trie.
void clear() {
_root
..value = null
..children.clear();
}

/// Returns [address]'s valid, non-negative path.
static List<int> _validatedPath(OccurrenceAddress address) {
if (address.path.any((index) => index < 0)) {
throw ArgumentError.value(
address,
'address',
'An occurrence address must contain non-negative indices.',
);
}
return address.path;
}
}

/// A node in an [OccurrenceTrie].
class _OccurrenceTrieNode<T extends Object> {
/// Descendants indexed by their address path component.
final Map<int, _OccurrenceTrieNode<T>> children = {};

/// The value stored at this node, if one has been assigned.
T? value;

/// Whether this node has neither a value nor descendants.
bool get isEmpty => value == null && children.isEmpty;
}
53 changes: 53 additions & 0 deletions packages/rohd_hierarchy/test/occurrence_trie_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (C) 2026 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// occurrence_trie_test.dart
// Tests for compact occurrence-address trie storage.
//
// 2026 August
// Author: Desmond Kirkpatrick <desmond.a.kirkpatrick@intel.com>

import 'package:rohd_hierarchy/rohd_hierarchy.dart';
import 'package:test/test.dart';

void main() {
test('stores values with shared occurrence-address prefixes', () {
final trie = OccurrenceTrie<String>();
const first = OccurrenceAddress([0, 2, 4]);
const second = OccurrenceAddress([0, 2, 5]);

trie[first] = 'first';
trie[OccurrenceAddress.root] = 'root';
trie[second] = 'second';

expect(trie[OccurrenceAddress.root], 'root');
expect(trie[first], 'first');
expect(trie[second], 'second');
expect(trie[const OccurrenceAddress([0, 2, 6])], isNull);
});

test('prunes an address branch after removing its final value', () {
final trie = OccurrenceTrie<String>();
const first = OccurrenceAddress([0, 2, 4]);
const second = OccurrenceAddress([0, 2, 5]);
trie[first] = 'first';
trie[second] = 'second';

expect(trie.remove(first), 'first');
expect(trie[first], isNull);
expect(trie[second], 'second');
expect(trie.remove(second), 'second');
expect(trie.isEmpty, isTrue);
});

test('accepts root addresses and rejects negative path indices', () {
final trie = OccurrenceTrie<String>();

trie[OccurrenceAddress.root] = 'root';
expect(trie[OccurrenceAddress.root], 'root');
expect(
() => trie[const OccurrenceAddress([0, -1])],
throwsArgumentError,
);
});
}
42 changes: 42 additions & 0 deletions rohd_devtools_extension/packages/rohd_devtools_widgets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,48 @@ across DevTools packages.
- ROHD extension client/status abstractions: `RohdExtensionClient`,
`NullExtensionClient`, `RohdModuleInfo`, and `RohdFormatInfo`.

## Widgets & Utilities

### UI Controls & Buttons

- **`MarkdownHelpButton`** — A help button that displays Markdown content from an asset file in a dialog. Supports tooltip text and rich formatting.

- **`ExportPngButton`** — A camera icon button for triggering PNG export functionality. Includes customizable tooltip text.

- **`CrossProbeButton`** — A toolbar button for toggling cross-probing between viewers. Shows a bidirectional arrows icon that reflects the active/inactive state.

### Overlays & Layout

- **`AppBarOverlay`** — An auto-hiding AppBar that slides in from the top edge when the mouse approaches. When disabled, behaves like a standard AppBar.

### Export & Capture

- **`captureBoundaryToPng`** — Captures a `RepaintBoundary` as PNG and saves or downloads it.

- **`showExportToast`** — Shows export feedback and status messages.

### Cross-Probing

- **`CrossProbeService`** — Service for managing cross-probe state between multiple viewers/debuggers. Handles bidirectional signal selection synchronization.

- **`buildGotoSourceMenuItems`** — Builds source-navigation menu items for ROHD DevTools surfaces.

### Signal & Bit Field Utilities

- **`expandLogicType`**, **`formatFieldValue`**, and **`formatTypeTooltip`** — Format ROHD logic types and values for display.

- **`BitFieldDef`**, **`showBitRangeDialog`**, and **`showDefineBitFieldsDialog`** — Define and edit bit-field ranges.

- **`buildBitExpansionMenuItems`** and **`resolveBitExpansionMenuValue`** — Build and resolve the "Expand Bits" and "Define Bit Fields" actions used across signal selection overlays and panels.

- **`SignalValueFormatRegistry`** — Shared registry for signal display-format preferences, allowing consistent formatting across multiple viewers.

### Extension Integration

- **`RohdExtensionClient`** — Abstract interface for querying the ROHD VS Code extension. Supports multiple implementations (DevTools, VS Code webview, offline mode).

- **`RohdSourceFormat`** and **`RohdFormatInfo`** — Describe source formats and their availability.

## Usage

Add this package as a path dependency from a ROHD DevTools package and import the shared widgets you need:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export 'src/bit_field_utils.dart';
// Shared "Expand Bits" / "Define Bit Fields" popup-menu helpers
export 'src/bit_expansion_menu.dart';

// Shared signal display-format preferences and value formatting
export 'src/signal_value_format_registry.dart';

// ROHD extension client
export 'src/rohd_extension_status.dart';
export 'src/rohd_extension_client.dart';
Loading
Loading