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

Inspector Implementation #120

Merged
merged 10 commits into from Jan 17, 2019
Merged

Inspector Implementation #120

merged 10 commits into from Jan 17, 2019

Conversation

jacob314
Copy link
Contributor

Sorry about the large size. Good news is a few of the files are just additional clones from flutter and there are tests.

@jacob314
Copy link
Contributor Author

High level notes:
The important files to review are InspectorController, InspectorTree, and InspectorTreeCanvas.

InspectorController is a port of the InspectorPanel class from the Java code base with refactors to make it a true controller. InspectorController tests can be run with a regular dart vm.

InspectorTree holds most of the functionality for a very inspector specific tree renderer.
InspectorTreeCanvas holds the most important implementation that renders to Canvas
InspectorTreeHtml holds a prototype implementation that renders to HTML. It is generally there to ensure the code is abstracted plausible. In the future we will have and InspectorTreeStatefulWidget as well.

Renamed DiagnosticsNode to RemoteDiagnosticsNode as I wanted to pull in the real local DiagnosticsNode class from Flutter as it is really handy for ascii art string dumps for tests.

@devoncarew
Copy link
Member

I may take a few passes through this PR, but will defer to @kenzieschmoll for a full review. Can you post some screenshots of the UI in the meantime?

@jacob314
Copy link
Contributor Author

Clicking around in the tree also works with scrolling behavior matching intellij. Expand and collapse also works.
jan-15-2019 09-51-59

Auto-collapse toolbar:
auto-collapse

Known issues:
Need to suppress line art for the single child + zero property case.
Need to make tooltips hovering over the "Default icon work"
Need to calculate tree width correctly

Screenshot showing the HTML renderer which allows multiline property values. The html renderer is off by default but will be used for displaying errors in the logging panel at minimum.
screen shot 2019-01-14 at 8 48 46 am

@devoncarew
Copy link
Member

👍 screenshots look great


/// Reference the actual Dart DiagnosticsNode object this object is referencing.
InspectorInstanceRef getDartDiagnosticRef() {
InspectorInstanceRef get dartDiagnosticRef {
return InspectorInstanceRef(json['objectId']);
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 inline this?

InspectorInstanceRef get dartDiagnosticRef => InspectorInstanceRef(json['objectId']);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to but the line length is above 80 and => blocks shouldn't wrap.

Copy link
Member

@devoncarew devoncarew left a comment

Choose a reason for hiding this comment

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

This is really, really fantastic! I made a quick pass through; comments in-line.

@@ -725,12 +657,12 @@ class InspectorSourceLocation {
final Map<String, Object> json;
final InspectorSourceLocation parent;

String getPath() {
String get path {
Copy link
Member

Choose a reason for hiding this comment

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

use =>?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

: super(
name: 'Inspector',
id: 'inspector',
iconClass: 'octicon-device-mobile',
Copy link
Member

Choose a reason for hiding this comment

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

no trailing comma may make this particular instance format better?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Without the trailing comma, dartfmt generates

  InspectorScreen()
      : super(
            name: 'Inspector',
            id: 'inspector',
            iconClass: 'octicon-device-mobile');

which I feel makes the end paren less obvious.
As an aside, I would personally be a fan of setting the line length to 100 for this code base
in case this line would just be a natural one liner.

div()..flex(),
div(c: 'btn-group collapsible')
..add(<CoreElement>[
ServiceExtensionButton(extensions.performanceOverlay).button,
Copy link
Member

Choose a reason for hiding this comment

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

possibly put these into ~2 separate button groups, instead of having 7 buttons in a row?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done. Split into 3 groups and got a little clever about having the overflow buttons shrink down to just icons before the more important icons
double-collapse

inspectorContainer.add(elements);
splitterSubscription = flexSplitBidirectional(elements);

// TODO(jacobr): update visibility based on whether the screen is visible.
Copy link
Member

Choose a reason for hiding this comment

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

When you do get ready to do this, we have entering() and exiting() calls you can override for Screens.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

great!

await group.dispose();
return null;
}
// TODO(jacobr): use the list of loaded scripts to determine the appropriate
Copy link
Member

Choose a reason for hiding this comment

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

I think Isolate.rootLib is what you want - I don't think you'll need the full list of scripts (it's also available now however, as part of the new getScripts() call).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've updated the todo to use Isolate.rootLib. TLDR; I need to cleanup the --track-widget-creation transformer to stop using absolute paths.
@terrylucas maybe you are interested in helping fix that in the transformer as you need to tweak the transformer code for some memory tracking items.

// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

library inspector_tree_canvas;
Copy link
Member

Choose a reason for hiding this comment

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

I'm curious if we need library directives? I normally only add them if I need someplace to hang dartdoc comments off of.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no idea. I've been adding them out of habit. Removed the low value ones.

web/index.html Outdated
@@ -21,7 +21,7 @@
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="packages/devtools/debugger/debugger.css">
<link rel="stylesheet" href="packages/devtools/logging/logging.css">

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
Copy link
Member

Choose a reason for hiding this comment

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

Note that all the rest of our deps are in-lined into the package - that they could be served w/o an internet connection (including the octicons icons). Perhaps open an issue to in-line the material icons font?

Copy link
Member

Choose a reason for hiding this comment

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

I can't seem to make a comment down there, but right after <!-- add the known pages -->, can you add a place for the Inspector page, and remove the one for the Device page? We have an approximation of the final UI in static html so that there's less flashing and re-layout when the app launches.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch. I'd thought that part of static HTML was cruft to cleanup rather than server side rendering./

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Loaded the flutter icons locally.

web/styles.css Outdated
@@ -232,6 +232,35 @@ input:disabled+label {
opacity: 0.5;
}

.inspector-tree {
Copy link
Member

Choose a reason for hiding this comment

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

I'd create an inspector specific style sheet, lib/inspector/inspector.css, and move things into there that won't be shared. We do this for the debugging and logging pages, just so this css file doesn't grow unbounded.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -651,6 +680,26 @@ nav.menu li {
color: #ccc;
}

/*
We have to do something with the scrollbars as they flicker due to DOM
Copy link
Member

Choose a reason for hiding this comment

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

Do we want this for all of our scrollbars or just the inspector ones?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this impacts the infinite scrolling table as well so yes.
We can tweak this style so we still fade in and out on hover but I think this is at least a non-flickery default.

web/styles.css Outdated
@@ -686,3 +735,23 @@ nav.menu li {
bottom: 30px;
z-index: 10;
}

@media all and (max-width: 1280px) {
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 great

Copy link
Member

@devoncarew devoncarew left a comment

Choose a reason for hiding this comment

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

More comments (around testing)!

@@ -1041,6 +1041,7 @@ class BreakpointsView {

Stream<Breakpoint> get onDoubleClick => _items.onDoubleClick;

@override
Copy link
Member

Choose a reason for hiding this comment

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

👍 ; there are ~4 more places in this file I believe where we could make the same change

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great. I've updated them all to implement the CoreElementView interface.

expect(
detailsTree.toStringDeep(),
equalsIgnoringHashCodes(
'▼[S] Scaffold <-- selected\n'
Copy link
Member

Choose a reason for hiding this comment

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

Should we keep this golden output in a txt file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm torn about this. On one hand a text file makes rebaselining easy but on the other hand inline makes the intent of the test much clearer. As a middle ground I plan to fixup the output here so most of these tests are truncated output only highlighting the relevant details so rebaselining won't be needed much or at all and the forest is easier to see from the trees.
note that there are a number of inline golden style text output tests in flutter proper and they rarely break.

expect(
detailsTree.toStringDeep(),
equalsIgnoringHashCodes('▼[S] Scaffold \n'
'│ ▼state: ScaffoldState#00000(tickers: tracking 1 ticker)\n'
Copy link
Member

Choose a reason for hiding this comment

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

perhaps this output as well (in a separate file), given the size?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this dump will be made a pleasant size by the tweaks alluded to above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

correction. added reasonably nice golden file and rebaseline goldens functionality and used it i all the details cases. ended up adding a more verbose golden format that include styles as well and used it to catch a bug where we were emitting some pointless styled empty blocks.

@@ -0,0 +1,438 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

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

For some of these files, are there cooresponding Java file in the flutter-intellij repo (or dart files in the flutter repo) that we should be keeping them up-to-date with? If so, we should call that out in comments in order to help future maintainers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

import 'dart:async';
import 'dart:io';

import 'package:devtools/inspector/diagnostics_node.dart';
Copy link
Member

Choose a reason for hiding this comment

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

organize imports?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

import 'dart:async';
import 'dart:io';

import 'package:devtools/inspector/flutter_widget.dart';
Copy link
Member

Choose a reason for hiding this comment

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

organize imports?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

expect(
treeToDebugString(nodeInDetailsTree),
equalsIgnoringHashCodes('MaterialApp\n'
' │ state: _MaterialAppState#00000\n'
Copy link
Member

Choose a reason for hiding this comment

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

have a separate golden master file for this test expectation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

import 'package:devtools/inspector/flutter_widget.dart';
import 'package:test/test.dart';

import 'package:devtools/globals.dart';
Copy link
Member

Choose a reason for hiding this comment

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

It looks like some portion of the devtools codebase will need to run in the VM (not an issue, just noting it). I expect that the tests on travis will keep us honest, if we start referencing dart:html code from portions of the app that need to be able to run on the cli.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes. these tests along with the one @kenzieschmoll already added keep us honest about not adding dart:html imports to our business logic code which is a great thing. When I'd first added the inspector code but let a few dart:html tests sneak in, @kenzieschmoll's tests started failing locally with complains about my deart:html deps.

detailsInspectorTree.element.element
];
inspectorContainer.add(elements);
splitterSubscription = flexSplitBidirectional(elements);
Copy link
Member

Choose a reason for hiding this comment

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

I would use defaultSplitterWidth for the splitter width. I see that this version of the method doesn't take preferred ratios for the child sizes, but if we can add it you may try out a 40/60 or 33/66 split (see if giving more weight to the RHS looks good).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added default size options for the bidirectional splitter which is a bit tricky as it can be both horizontal and vertical depending on the window size.
Agreed that a 60/40 split looks much better. Use 65/35 split in the other direction in the vertical layout case as in that case the details panel should be smaller not larger.

lib/inspector/inspector.dart Outdated Show resolved Hide resolved
lib/inspector/inspector_controller.dart Outdated Show resolved Hide resolved
lib/inspector/inspector_controller.dart Outdated Show resolved Hide resolved
lib/inspector/inspector_controller.dart Outdated Show resolved Hide resolved
lib/inspector/inspector_controller.dart Outdated Show resolved Hide resolved
lib/inspector/inspector_tree_canvas.dart Outdated Show resolved Hide resolved
lib/ui/fake_flutter/diagnosticable.dart Show resolved Hide resolved
case DiagnosticsTreeStyle.truncateChildren:
return null;
}
return null;
Copy link
Member

Choose a reason for hiding this comment

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

Could put this in a default case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this code isn't for review here. it is just forked from package flutter so ignoring your valid comments :)

_debugPrintBuffer.isNotEmpty) {
final String line = _debugPrintBuffer.removeFirst();
_debugPrintedCharacters +=
line.length; // TODO(ianh): Use the UTF-8 byte length instead
Copy link
Member

Choose a reason for hiding this comment

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

Probably remove this todo for ianh@?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think there is value for us just porting files wholesale instead of trying to cleanup as these files will be ported more cleanly at some later point for hummingbird. all we want for them now is that we can reasonably bring in new versions from package:flutter without odd diffs.

test/inspector_controller_test.dart Outdated Show resolved Hide resolved
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.

LGTM

this matches intellij ui and solves problem where render objects in tests had
different dimensions than on the bots.
@jacob314 jacob314 merged commit e7f6f36 into flutter:master Jan 17, 2019
@jacob314 jacob314 deleted the inspector_review branch January 17, 2019 17:17
@DanTup
Copy link
Contributor

DanTup commented Jan 21, 2019

@fureweb-com
Copy link

wow!

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.

None yet

5 participants