Skip to content

Span inspector #1296

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open

Conversation

QuentinLeeWeber
Copy link
Contributor

@QuentinLeeWeber QuentinLeeWeber commented Jun 24, 2025

This PR introduces a tool called span-inspector that helps analyze and visualize the spans of tokens generated from the input to a cxx-qt-bridge macro.

Details

  • Parses the input of a cxx-qt-bridge macro
  • Expands the macro
  • Highlights the spans of individual tokens for better inspection and debugging
  • Differentiates between synthesized and normal tokens

LeonMatthesKDAB and others added 12 commits March 27, 2025 09:05
This highlights all output tokens that share the same span
as the text cursor is hovering over.
Expansion erros are now shown directly in the output textfield.
- Fix incorrect calculation of target span
- Fix false highlighting caused by Pretty Please code manipulation
- Prevents issues with special characters like '<' and '>' breaking the output HTML
These tokens are now ignored during parsing because prettyplease
inserts them automatically in certain situations.
…fresh bug

- Make output text area scrollable
- Adjust text color to match the theme
- Fix edge case where text change did not trigger refresh if cursor position stayed the same
Copy link

codecov bot commented Jun 24, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (cb64b22) to head (791cb56).
Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #1296   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           75        75           
  Lines        12772     12772           
=========================================
  Hits         12772     12772           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Collaborator

@LeonMatthesKDAB LeonMatthesKDAB left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The app works nicely and the overall approach is fine.
There are still some improvements to the code necessary before we can merge though.

[dependencies]
cxx.workspace = true
cxx-qt.workspace = true
cxx-qt-lib = { workspace = true, features = ["full"] }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please take a look at which features of cxx-qt-lib you really need, as compiling cxx-qt-lib fully can take a lot of time.

@@ -24,7 +24,7 @@ members = [

"tests/basic_cxx_only/rust",
"tests/basic_cxx_qt/rust",
"tests/qt_types_standalone/rust",
"tests/qt_types_standalone/rust", "examples/span-inspector",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this line up to the other examples.


fn main() {
let qml_module: QmlModule<'static, &str, &str> = QmlModule {
uri: "com.kdab.cxx_qt.demo",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
uri: "com.kdab.cxx_qt.demo",
uri: "com.kdab.cxx_qt.span_inspector",

I copied this from our demos, but this could actually use a useful name (remember to update the according QML import).

Comment on lines +112 to +117
qt_thread
.queue(|this| {
unsafe { this.output_document() }
.set_html(&QString::from(String::from("expanding...")))
})
.ok();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this needs to use a qt_thread.
Can't this just call set_html directly?


let text = unsafe { Pin::new_unchecked(&mut *input.text_document()) }
.to_plain_text()
.to_string();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This last to_string() call does a UTF-16 to UTF-8 conversion.
Please move this conversion into the background thread as well.

Comment on lines +176 to +177
let string = token.to_string();
!matches!(string.as_str(), "," | "}" | "{")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is implemented twice in build_html, please factor it out into a common method.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, I think pretty-please can also insert , so that may need to be added to the list.

(
target_span
.map(|s| s.byte_range().eq(token.span().byte_range()))
.unwrap_or_else(|| false),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.unwrap_or_else(|| false),
.unwrap_or_default(),

}

// Expand input code as #[cxxqt_qt::bridge] would do
fn expand(input: &str, cursor_position: usize) -> Result<(String, Vec<(bool, bool)>), String> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is pretty unclear what the two bool instances in Vec<(bool, bool)> actually represent.
Please create a new struct with named fields for this.

Comment on lines +271 to +278
background-color: #ff00ff;
padding: 2px 6px;
border-radius: 6px;
}
.generated {
color: rgba(255, 255, 255, 100);
padding: 2px 6px;
border-radius: 6px;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These colors are hard-coded, and can be hard to read, depending on the color scheme (light/dark mode).
Ideally these would be chosen based on the current palette of the widget, but this may be hard to fix at the moment, so it's something to note for a follow-up PR.

};
qt_thread
.queue(move |this| {
unsafe { this.output_document() }.set_html(&QString::from(output))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do multiple subsequent edits to the input string, they all race to set their result as the output_string. If a later edit finishes faster, it will be overwritten by an edit that happened beforehand, leaving the app in an inconsistent state.

The easiest way to fix this is to add a request_token (just an i32) that is incremented every time a background thread is started.
Only the background thread with the matching request_token is then allowed to set its result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants