Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
8f62e342
Unverified
Commit
8f62e342
authored
Mar 28, 2023
by
Loïc Sharma
Committed by
GitHub
Mar 28, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Focus] Add run key command to dump the focus tree (#123473)
[Focus] Add run key command to dump the focus tree
parent
89da0468
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
160 additions
and
2 deletions
+160
-2
smoke_test.dart
dev/integration_tests/flutter_gallery/test/smoke_test.dart
+1
-0
service_extensions.dart
packages/flutter/lib/src/rendering/service_extensions.dart
+0
-1
binding.dart
packages/flutter/lib/src/widgets/binding.dart
+10
-0
service_extensions.dart
packages/flutter/lib/src/widgets/service_extensions.dart
+9
-0
service_extensions_test.dart
...ages/flutter/test/foundation/service_extensions_test.dart
+14
-1
command_help.dart
packages/flutter_tools/lib/src/base/command_help.dart
+6
-0
resident_runner.dart
packages/flutter_tools/lib/src/resident_runner.dart
+19
-0
vmservice.dart
packages/flutter_tools/lib/src/vmservice.dart
+10
-0
command_help_test.dart
...tter_tools/test/general.shard/base/command_help_test.dart
+3
-0
resident_runner_test.dart
...lutter_tools/test/general.shard/resident_runner_test.dart
+1
-0
terminal_handler_test.dart
...utter_tools/test/general.shard/terminal_handler_test.dart
+46
-0
vmservice_test.dart
...ages/flutter_tools/test/general.shard/vmservice_test.dart
+40
-0
overall_experience_test.dart
...tools/test/integration.shard/overall_experience_test.dart
+1
-0
No files found.
dev/integration_tests/flutter_gallery/test/smoke_test.dart
View file @
8f62e342
...
...
@@ -81,6 +81,7 @@ Future<void> smokeDemo(WidgetTester tester, GalleryDemo demo) async {
verifyToStringOutput
(
'debugDumpApp'
,
routeName
,
WidgetsBinding
.
instance
.
rootElement
!.
toStringDeep
());
verifyToStringOutput
(
'debugDumpRenderTree'
,
routeName
,
RendererBinding
.
instance
.
renderView
.
toStringDeep
());
verifyToStringOutput
(
'debugDumpLayerTree'
,
routeName
,
RendererBinding
.
instance
.
renderView
.
debugLayer
?.
toStringDeep
()
??
''
);
verifyToStringOutput
(
'debugDumpFocusTree'
,
routeName
,
WidgetsBinding
.
instance
.
focusManager
.
toStringDeep
());
// Scroll the demo around a bit more.
await
tester
.
flingFrom
(
const
Offset
(
400.0
,
300.0
),
const
Offset
(
0.0
,
400.0
),
1000.0
);
...
...
packages/flutter/lib/src/rendering/service_extensions.dart
View file @
8f62e342
...
...
@@ -68,7 +68,6 @@ enum RenderingServiceExtensions {
/// registered.
debugDumpLayerTree
,
/// Name of service extension that, when called, will toggle whether all
/// clipping effects from the layer tree will be ignored.
///
...
...
packages/flutter/lib/src/widgets/binding.dart
View file @
8f62e342
...
...
@@ -386,6 +386,16 @@ mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureB
},
);
registerServiceExtension
(
name:
WidgetsServiceExtensions
.
debugDumpFocusTree
.
name
,
callback:
(
Map
<
String
,
String
>
parameters
)
async
{
final
String
data
=
focusManager
.
toStringDeep
();
return
<
String
,
Object
>{
'data'
:
data
,
};
},
);
if
(!
kIsWeb
)
{
registerBoolServiceExtension
(
name:
WidgetsServiceExtensions
.
showPerformanceOverlay
.
name
,
...
...
packages/flutter/lib/src/widgets/service_extensions.dart
View file @
8f62e342
...
...
@@ -20,6 +20,15 @@ enum WidgetsServiceExtensions {
/// registered.
debugDumpApp
,
/// Name of service extension that, when called, will output a string
/// representation of the focus tree to the console.
///
/// See also:
///
/// * [WidgetsBinding.initServiceExtensions], where the service extension is
/// registered.
debugDumpFocusTree
,
/// Name of service extension that, when called, will overlay a performance
/// graph on top of this app.
///
...
...
packages/flutter/test/foundation/service_extensions_test.dart
View file @
8f62e342
...
...
@@ -177,7 +177,7 @@ void main() {
// framework, excluding any that are for the widget inspector
// (see widget_inspector_test.dart for tests of the ext.flutter.inspector
// service extensions).
const
int
serviceExtensionCount
=
3
7
;
const
int
serviceExtensionCount
=
3
8
;
expect
(
binding
.
extensions
.
length
,
serviceExtensionCount
+
widgetInspectorExtensionCount
-
disabledExtensions
);
...
...
@@ -218,6 +218,19 @@ void main() {
});
});
test
(
'Service extensions - debugDumpFocusTree'
,
()
async
{
final
Map
<
String
,
dynamic
>
result
=
await
binding
.
testExtension
(
WidgetsServiceExtensions
.
debugDumpFocusTree
.
name
,
<
String
,
String
>{});
expect
(
result
,
<
String
,
dynamic
>{
'data'
:
matches
(
r'^'
r'FocusManager#[0-9a-f]{5}\n'
r' └─rootScope: FocusScopeNode#[0-9a-f]{5}\(Root Focus Scope\)\n'
r'$'
,
),
});
});
test
(
'Service extensions - debugDumpRenderTree'
,
()
async
{
await
binding
.
doFrame
();
final
Map
<
String
,
dynamic
>
result
=
await
binding
.
testExtension
(
RenderingServiceExtensions
.
debugDumpRenderTree
.
name
,
<
String
,
String
>{});
...
...
packages/flutter_tools/lib/src/base/command_help.dart
View file @
8f62e342
...
...
@@ -97,6 +97,12 @@ class CommandHelp {
'Detach (terminate "flutter run" but leave application running).'
,
);
late
final
CommandHelpOption
f
=
_makeOption
(
'f'
,
'Dump focus tree to the console.'
,
'debugDumpFocusTree'
,
);
late
final
CommandHelpOption
g
=
_makeOption
(
'g'
,
'Run source code generators.'
...
...
packages/flutter_tools/lib/src/resident_runner.dart
View file @
8f62e342
...
...
@@ -752,6 +752,22 @@ abstract class ResidentHandlers {
return
true
;
}
Future
<
bool
>
debugDumpFocusTree
()
async
{
if
(!
supportsServiceProtocol
||
!
isRunningDebug
)
{
return
false
;
}
for
(
final
FlutterDevice
?
device
in
flutterDevices
)
{
final
List
<
FlutterView
>
views
=
await
device
!.
vmService
!.
getFlutterViews
();
for
(
final
FlutterView
view
in
views
)
{
final
String
data
=
await
device
.
vmService
!.
flutterDebugDumpFocusTree
(
isolateId:
view
.
uiIsolate
!.
id
!,
);
logger
.
printStatus
(
data
);
}
}
return
true
;
}
/// Dump the application's current semantics tree to the terminal.
///
/// If semantics are not enabled, nothing is returned.
...
...
@@ -1521,6 +1537,7 @@ abstract class ResidentRunner extends ResidentHandlers {
commandHelp
.
t
.
print
();
if
(
isRunningDebug
)
{
commandHelp
.
L
.
print
();
commandHelp
.
f
.
print
();
commandHelp
.
S
.
print
();
commandHelp
.
U
.
print
();
commandHelp
.
i
.
print
();
...
...
@@ -1706,6 +1723,8 @@ class TerminalHandler {
case
'D'
:
await
residentRunner
.
detach
();
return
true
;
case
'f'
:
return
residentRunner
.
debugDumpFocusTree
();
case
'g'
:
await
residentRunner
.
runSourceGenerators
();
return
true
;
...
...
packages/flutter_tools/lib/src/vmservice.dart
View file @
8f62e342
...
...
@@ -643,6 +643,16 @@ class FlutterVmService {
return
response
?[
'data'
]?.
toString
()
??
''
;
}
Future
<
String
>
flutterDebugDumpFocusTree
({
required
String
isolateId
,
})
async
{
final
Map
<
String
,
Object
?>?
response
=
await
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpFocusTree'
,
isolateId:
isolateId
,
);
return
response
?[
'data'
]?.
toString
()
??
''
;
}
Future
<
String
>
flutterDebugDumpSemanticsTreeInTraversalOrder
({
required
String
isolateId
,
})
async
{
...
...
packages/flutter_tools/test/general.shard/base/command_help_test.dart
View file @
8f62e342
...
...
@@ -60,6 +60,7 @@ void _testMessageLength({
expect
(
commandHelp
.
b
.
toString
().
length
,
lessThanOrEqualTo
(
expectedWidth
));
expect
(
commandHelp
.
c
.
toString
().
length
,
lessThanOrEqualTo
(
expectedWidth
));
expect
(
commandHelp
.
d
.
toString
().
length
,
lessThanOrEqualTo
(
expectedWidth
));
expect
(
commandHelp
.
f
.
toString
().
length
,
lessThanOrEqualTo
(
expectedWidth
));
expect
(
commandHelp
.
g
.
toString
().
length
,
lessThanOrEqualTo
(
expectedWidth
));
expect
(
commandHelp
.
hWithDetails
.
toString
().
length
,
lessThanOrEqualTo
(
expectedWidth
));
expect
(
commandHelp
.
hWithoutDetails
.
toString
().
length
,
lessThanOrEqualTo
(
expectedWidth
));
...
...
@@ -137,6 +138,7 @@ void main() {
expect
(
commandHelp
.
U
.
toString
(),
endsWith
(
'
\
x1B[90m(debugDumpSemantics)
\
x1B[39m
\
x1B[22m'
));
expect
(
commandHelp
.
a
.
toString
(),
endsWith
(
'
\
x1B[90m(debugProfileWidgetBuilds)
\
x1B[39m
\
x1B[22m'
));
expect
(
commandHelp
.
b
.
toString
(),
endsWith
(
'
\
x1B[90m(debugBrightnessOverride)
\
x1B[39m
\
x1B[22m'
));
expect
(
commandHelp
.
f
.
toString
(),
endsWith
(
'
\
x1B[90m(debugDumpFocusTree)
\
x1B[39m
\
x1B[22m'
));
expect
(
commandHelp
.
i
.
toString
(),
endsWith
(
'
\
x1B[90m(WidgetsApp.showWidgetInspectorOverride)
\
x1B[39m
\
x1B[22m'
));
expect
(
commandHelp
.
o
.
toString
(),
endsWith
(
'
\
x1B[90m(defaultTargetPlatform)
\
x1B[39m
\
x1B[22m'
));
expect
(
commandHelp
.
p
.
toString
(),
endsWith
(
'
\
x1B[90m(debugPaintSizeEnabled)
\
x1B[39m
\
x1B[22m'
));
...
...
@@ -193,6 +195,7 @@ void main() {
expect
(
commandHelp
.
b
.
toString
(),
equals
(
'
\
x1B[1mb
\
x1B[22m Toggle platform brightness (dark and light mode).
\
x1B[90m(debugBrightnessOverride)
\
x1B[39m
\
x1B[22m'
));
expect
(
commandHelp
.
c
.
toString
(),
equals
(
'
\
x1B[1mc
\
x1B[22m Clear the screen'
));
expect
(
commandHelp
.
d
.
toString
(),
equals
(
'
\
x1B[1md
\
x1B[22m Detach (terminate "flutter run" but leave application running).'
));
expect
(
commandHelp
.
f
.
toString
(),
equals
(
'
\
x1B[1mf
\
x1B[22m Dump focus tree to the console.
\
x1B[90m(debugDumpFocusTree)
\
x1B[39m
\
x1B[22m'
));
expect
(
commandHelp
.
g
.
toString
(),
equals
(
'
\
x1B[1mg
\
x1B[22m Run source code generators.'
));
expect
(
commandHelp
.
hWithDetails
.
toString
(),
equals
(
'
\
x1B[1mh
\
x1B[22m Repeat this help message.'
));
expect
(
commandHelp
.
hWithoutDetails
.
toString
(),
equals
(
'
\
x1B[1mh
\
x1B[22m List all available interactive commands.'
));
...
...
packages/flutter_tools/test/general.shard/resident_runner_test.dart
View file @
8f62e342
...
...
@@ -1455,6 +1455,7 @@ flutter:
commandHelp
.
w
,
commandHelp
.
t
,
commandHelp
.
L
,
commandHelp
.
f
,
commandHelp
.
S
,
commandHelp
.
U
,
commandHelp
.
i
,
...
...
packages/flutter_tools/test/general.shard/terminal_handler_test.dart
View file @
8f62e342
...
...
@@ -400,6 +400,52 @@ void main() {
await
terminalHandler
.
processTerminalInput
(
'L'
);
});
testWithoutContext
(
'f - debugDumpFocusTree'
,
()
async
{
final
TerminalHandler
terminalHandler
=
setUpTerminalHandler
(<
FakeVmServiceRequest
>[
listViews
,
const
FakeVmServiceRequest
(
method:
'ext.flutter.debugDumpFocusTree'
,
args:
<
String
,
Object
>{
'isolateId'
:
'1'
,
},
jsonResponse:
<
String
,
Object
>{
'data'
:
'FOCUS TREE'
,
}
),
]);
await
terminalHandler
.
processTerminalInput
(
'f'
);
expect
(
terminalHandler
.
logger
.
statusText
,
contains
(
'FOCUS TREE'
));
});
testWithoutContext
(
'f - debugDumpLayerTree with web target'
,
()
async
{
final
TerminalHandler
terminalHandler
=
setUpTerminalHandler
(<
FakeVmServiceRequest
>[
listViews
,
const
FakeVmServiceRequest
(
method:
'ext.flutter.debugDumpFocusTree'
,
args:
<
String
,
Object
>{
'isolateId'
:
'1'
,
},
jsonResponse:
<
String
,
Object
>{
'data'
:
'FOCUS TREE'
,
}
),
],
web:
true
);
await
terminalHandler
.
processTerminalInput
(
'f'
);
expect
(
terminalHandler
.
logger
.
statusText
,
contains
(
'FOCUS TREE'
));
});
testWithoutContext
(
'f - debugDumpFocusTree with service protocol and profile mode is skipped'
,
()
async
{
final
TerminalHandler
terminalHandler
=
setUpTerminalHandler
(<
FakeVmServiceRequest
>[],
buildMode:
BuildMode
.
profile
);
await
terminalHandler
.
processTerminalInput
(
'f'
);
});
testWithoutContext
(
'f - debugDumpFocusTree without service protocol is skipped'
,
()
async
{
final
TerminalHandler
terminalHandler
=
setUpTerminalHandler
(<
FakeVmServiceRequest
>[],
supportsServiceProtocol:
false
);
await
terminalHandler
.
processTerminalInput
(
'f'
);
});
testWithoutContext
(
'o,O - debugTogglePlatform'
,
()
async
{
final
TerminalHandler
terminalHandler
=
setUpTerminalHandler
(<
FakeVmServiceRequest
>[
// Request 1.
...
...
packages/flutter_tools/test/general.shard/vmservice_test.dart
View file @
8f62e342
...
...
@@ -447,6 +447,46 @@ void main() {
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
});
testWithoutContext
(
'flutterDebugDumpFocusTree handles missing method'
,
()
async
{
final
FakeVmServiceHost
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
method:
'ext.flutter.debugDumpFocusTree'
,
args:
<
String
,
Object
>{
'isolateId'
:
'1'
,
},
errorCode:
RPCErrorCodes
.
kMethodNotFound
,
),
]
);
expect
(
await
fakeVmServiceHost
.
vmService
.
flutterDebugDumpFocusTree
(
isolateId:
'1'
,
),
''
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
});
testWithoutContext
(
'flutterDebugDumpFocusTree returns data'
,
()
async
{
final
FakeVmServiceHost
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
method:
'ext.flutter.debugDumpFocusTree'
,
args:
<
String
,
Object
>{
'isolateId'
:
'1'
,
},
jsonResponse:
<
String
,
Object
>
{
'data'
:
'Hello world'
,
},
),
]
);
expect
(
await
fakeVmServiceHost
.
vmService
.
flutterDebugDumpFocusTree
(
isolateId:
'1'
,
),
'Hello world'
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
});
testWithoutContext
(
'Framework service extension invocations return null if service disappears '
,
()
async
{
final
FakeVmServiceHost
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
...
packages/flutter_tools/test/integration.shard/overall_experience_test.dart
View file @
8f62e342
...
...
@@ -604,6 +604,7 @@ void main() {
'w Dump widget hierarchy to the console. (debugDumpApp)'
,
't Dump rendering tree to the console. (debugDumpRenderTree)'
,
'L Dump layer tree to the console. (debugDumpLayerTree)'
,
'f Dump focus tree to the console. (debugDumpFocusTree)'
,
'S Dump accessibility tree in traversal order. (debugDumpSemantics)'
,
'U Dump accessibility tree in inverse hit test order. (debugDumpSemantics)'
,
'i Toggle widget inspector. (WidgetsApp.showWidgetInspectorOverride)'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment