Skip to content
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

Evaluation HoverCard #2746

Merged
merged 9 commits into from
Mar 3, 2021
Merged

Evaluation HoverCard #2746

merged 9 commits into from
Mar 3, 2021

Conversation

grouma
Copy link
Member

@grouma grouma commented Feb 26, 2021

  • Create new HoverCard class to handle absolutely positioned overlays that automatically remove themself
  • Update CodeView to support hovering over source code and display an evaluation result

Screen Shot 2021-02-26 at 10 51 19 AM

@grouma grouma requested a review from jacob314 February 26, 2021 18:55
@kenzieschmoll
Copy link
Member

DBC: Is this the card placement we want? I would think we'd want the card to be centered above the mouse position or below. I think Chrome devtools places the hover card above. IntelliJ places it below like this:
Screen Shot 2021-02-26 at 12 54 18 PM

@grouma
Copy link
Member Author

grouma commented Feb 26, 2021

DBC: Is this the card placement we want? I would think we'd want the card to be centered above the mouse position or below. I think Chrome devtools places the hover card above. IntelliJ places it below like this:

I'm open to changing it. I was making this consistent with the current hover logic in the memory page. Let me know if you prefer consistency or the Chrome logic.

@kenzieschmoll
Copy link
Member

DBC: Is this the card placement we want? I would think we'd want the card to be centered above the mouse position or below. I think Chrome devtools places the hover card above. IntelliJ places it below like this:

I'm open to changing it. I was making this consistent with the current hover logic in the memory page. Let me know if you prefer consistency or the Chrome logic.

Yes let's be consistent with chrome devtools or with the IDEs for debugging purposes.

@grouma
Copy link
Member Author

grouma commented Feb 26, 2021

Yes let's be consistent with chrome devtools or with the IDEs for debugging purposes.

Done.

@grouma grouma requested a review from kenzieschmoll March 2, 2021 18:14
Comment on lines 50 to 52
_CodeViewState(this.debuggerController);

final DebuggerController debuggerController;
Copy link
Member

Choose a reason for hiding this comment

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

access controller via widget.controller instead of passing it into the state object

Copy link
Member

@kenzieschmoll kenzieschmoll Mar 2, 2021

Choose a reason for hiding this comment

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

And actually, since CodeViewState is a stateful widget, we can access the controller from Provider in didChangeDependencies, and we don't need to pass debuggerController into the widget constructor either. See

final newController = Provider.of<DebuggerController>(context);
for an example of that

Copy link
Contributor

Choose a reason for hiding this comment

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

why not just lookup the Provider in the build method?

const LineItem({
Key key,
@required this.lineContents,
@required this.debuggerController,
Copy link
Member

Choose a reason for hiding this comment

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

access debugger controller from didChangeDependencies instead of requiring it to be a parameter for this stateful widget (see above comment for example)

Copy link
Contributor

Choose a reason for hiding this comment

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

why didUpdateDependencies instead of the build method?

final theme = Theme.of(context);
_hoverCard?.remove();
final word = wordForHover(
event.localPosition.dx, widget.lineContents, theme.fixedFontStyle);
Copy link
Member

Choose a reason for hiding this comment

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

nit: trailing comma

contents: Material(
child: ExpandableVariable(
debuggerController: widget.debuggerController,
variable: ValueNotifier(variable))),
Copy link
Member

Choose a reason for hiding this comment

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

trailing commas

debuggerController: widget.debuggerController,
variable: ValueNotifier(variable))),
event: event,
width: 250,
Copy link
Member

Choose a reason for hiding this comment

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

put this into a const

event: event,
width: 250,
title: word,
context: context);
Copy link
Member

Choose a reason for hiding this comment

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

trailing comma

child:
RichText(text: truncateTextSpan(lineContents, column - 1)),
child: RichText(
text: truncateTextSpan(widget.lineContents, column - 1)),
Copy link
Member

Choose a reason for hiding this comment

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

trailing comma

widget.lineContents,
scrollPhysics: const NeverScrollableScrollPhysics(),
maxLines: 1,
)),
Copy link
Member

Choose a reason for hiding this comment

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

trailing comma

widget.lineContents,
scrollPhysics: const NeverScrollableScrollPhysics(),
maxLines: 1,
));
Copy link
Member

Choose a reason for hiding this comment

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

tc

scrollPhysics: const NeverScrollableScrollPhysics(),
maxLines: 1,
);
child = MouseRegion(
Copy link
Member

Choose a reason for hiding this comment

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

this is duplicated code. Can you pull out into a local var and use in both places?


@override
Widget build(BuildContext context) {
return ValueListenableBuilder<Variable>(
valueListenable: variable,
builder: (context, variable, _) {
final controller = Provider.of<DebuggerController>(context);
final controller =
debuggerController ?? Provider.of<DebuggerController>(context);
Copy link
Member

Choose a reason for hiding this comment

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

Is this because we don't have a debugger controller available in the context of the hover card overlay?

Copy link
Contributor

Choose a reason for hiding this comment

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

correct. Overlay doesn't play great with provider. We might be able to resolve if we moved our providers to the absolute root of the tree but that would cause problems for the snapshot app case.

/// Merges words linked by a `.`.
///
/// For example, hovering over `bar` in `foo.bar.baz` would return
/// `foo.bar.baz`.
Copy link
Member

Choose a reason for hiding this comment

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

nit: should this be foo.bar instead of foo.bar.baz?

Copy link
Member Author

@grouma grouma Mar 2, 2021

Choose a reason for hiding this comment

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

No this is correct.

Copy link
Member

Choose a reason for hiding this comment

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

can you explain that rationale to me? If a user hovers over bar, wouldn't they want to look at the value of bar, not baz?

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought Chrome's behavior was to treat all things linked by a . as a single "block".

I just tested and that doesn't seem to be the case:
Screen Shot 2021-03-02 at 3 16 52 PM

I'll update the logic.

/// For example, hovering over `bar` in `foo.bar.baz` would return
/// `foo.bar.baz`.
String _mergedLinkedWords(String word, int index, TextSpan line) {
var left = index - 1;
Copy link
Member

@kenzieschmoll kenzieschmoll Mar 2, 2021

Choose a reason for hiding this comment

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

how is the index = 1 case handled? If we are hovering over bar in foo.bar, don't we want to evaluate foo.bar? This looks like we only merge the words if there are two previous values. We should be able to change this to chain previous values one at a time instead of 2 at a time.

same comment for the right case

Copy link
Member Author

Choose a reason for hiding this comment

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

We want to evaluate all words linked by a .. This is consistent with Chrome's behavior.

index in this case would point to bar and foo would be merged. There are test cases covering this.

Copy link
Member Author

Choose a reason for hiding this comment

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

I updated the logic and the tests. If we hover over bar in foo.bar.baz we want to evaluate foo.bar to be consistent with Chrome. There will always be at least two items because one of the items will be .. Otherwise it won't be linked.

_hasMouseEntered = true;
},
child: Container(
padding: const EdgeInsets.fromLTRB(8, 8, 8, 8),
Copy link
Member

Choose a reason for hiding this comment

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

use const EdgeInsets.all(denseSpacing);

color: focusColor,
width: _hoverCardBorderWidth,
),
borderRadius: BorderRadius.circular(10.0),
Copy link
Member

Choose a reason for hiding this comment

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

put this into a const or use the defaultBorderRadius used elsewhere in devtools

child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
Copy link
Member

Choose a reason for hiding this comment

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

use SizedBox instead since width is the only property

Container(
width: width,
child: Text(
title,
Copy link
Member

Choose a reason for hiding this comment

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

what if the title is long? should this ellipsize?

contents,
],
),
)));
Copy link
Member

Choose a reason for hiding this comment

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

trailing commas

Copy link
Member

@kenzieschmoll kenzieschmoll left a comment

Choose a reason for hiding this comment

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

Done with first round of comments

@@ -39,10 +43,14 @@ class CodeView extends StatefulWidget {
final void Function(ScriptRef scriptRef, int line) onSelected;

@override
_CodeViewState createState() => _CodeViewState();
_CodeViewState createState() => _CodeViewState(controller);
Copy link
Contributor

Choose a reason for hiding this comment

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

https://dart-lang.github.io/linter/lints/no_logic_in_create_state.html
will avoid this issue without code review. lets add the lint to devtools.

final prev = line.children[left].toPlainText();
final prevprev = line.children[left - 1].toPlainText();
if (prev == '.') {
word = '$prevprev$prev$word';
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: one way to write this logic a little bit more simply is to create a
List that is the components of the line.
Then you can just track the the start and end indexes and use String.join to get the output string when you are done.

@grouma
Copy link
Member Author

grouma commented Mar 2, 2021

This should be ready to review again. PTAL.

@kenzieschmoll
Copy link
Member

lgtm_orangatang

@grouma grouma merged commit f8e219a into master Mar 3, 2021
@grouma grouma deleted the hover-card branch March 3, 2021 16:41
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.

3 participants