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
b45088c0
Unverified
Commit
b45088c0
authored
Jan 21, 2021
by
Kenzie Schmoll
Committed by
GitHub
Jan 21, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Print DevTools inspector links in RenderFlex Overflow errors (#74251)
parent
eeb7c261
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
238 additions
and
7 deletions
+238
-7
binding.dart
packages/flutter/lib/src/foundation/binding.dart
+9
-0
debug.dart
packages/flutter/lib/src/foundation/debug.dart
+4
-0
widget_inspector.dart
packages/flutter/lib/src/widgets/widget_inspector.dart
+66
-3
service_extensions_test.dart
...ages/flutter/test/foundation/service_extensions_test.dart
+14
-1
widget_inspector_test.dart
packages/flutter/test/widgets/widget_inspector_test.dart
+10
-0
resident_runner.dart
packages/flutter_tools/lib/src/resident_runner.dart
+43
-0
run_cold.dart
packages/flutter_tools/lib/src/run_cold.dart
+8
-0
run_hot.dart
packages/flutter_tools/lib/src/run_hot.dart
+4
-0
flutter_attach_test.dart
...ter_tools/test/integration.shard/flutter_attach_test.dart
+26
-0
flutter_run_test.dart
...lutter_tools/test/integration.shard/flutter_run_test.dart
+15
-0
test_driver.dart
...ges/flutter_tools/test/integration.shard/test_driver.dart
+17
-2
test_utils.dart
...ages/flutter_tools/test/integration.shard/test_utils.dart
+21
-0
vmservice_integration_test.dart
...ls/test/integration.shard/vmservice_integration_test.dart
+1
-1
No files found.
packages/flutter/lib/src/foundation/binding.dart
View file @
b45088c0
...
...
@@ -245,6 +245,15 @@ abstract class BindingBase {
};
},
);
registerStringServiceExtension
(
name:
'activeDevToolsServerAddress'
,
getter:
()
async
=>
activeDevToolsServerAddress
??
''
,
setter:
(
String
serverAddress
)
async
{
activeDevToolsServerAddress
=
serverAddress
;
},
);
return
true
;
}());
assert
(()
{
...
...
packages/flutter/lib/src/foundation/debug.dart
View file @
b45088c0
...
...
@@ -109,3 +109,7 @@ String debugFormatDouble(double? value) {
/// * [WidgetsApp], which uses the [debugBrightnessOverride] setting in debug mode
/// to construct a [MediaQueryData].
ui
.
Brightness
?
debugBrightnessOverride
;
/// The address for the active DevTools server used for debugging this
/// application.
String
?
activeDevToolsServerAddress
;
packages/flutter/lib/src/widgets/widget_inspector.dart
View file @
b45088c0
...
...
@@ -713,6 +713,12 @@ mixin WidgetInspectorService {
_instance
=
instance
;
}
/// Information about the VM service protocol for the running application.
///
/// This information is necessary to provide Flutter DevTools deep links in
/// error messages.
developer
.
ServiceProtocolInfo
?
_serviceInfo
;
static
bool
_debugServiceExtensionsRegistered
=
false
;
/// Ground truth tracking what object(s) are currently selected used by both
...
...
@@ -976,6 +982,12 @@ mixin WidgetInspectorService {
/// * [BindingBase.initServiceExtensions], which explains when service
/// extensions can be used.
void
initServiceExtensions
(
_RegisterServiceExtensionCallback
registerServiceExtensionCallback
)
{
if
(!
kIsWeb
)
{
developer
.
Service
.
getInfo
().
then
((
developer
.
ServiceProtocolInfo
info
)
{
_serviceInfo
=
info
;
});
}
_structuredExceptionHandler
=
_reportError
;
if
(
isStructuredErrorsEnabled
())
{
FlutterError
.
onError
=
_structuredExceptionHandler
;
...
...
@@ -1385,6 +1397,46 @@ mixin WidgetInspectorService {
return
false
;
}
/// Returns a DevTools uri linking to a specific element on the inspector page.
String
?
_devToolsInspectorUriForElement
(
Object
?
object
)
{
if
(
activeDevToolsServerAddress
!=
null
&&
_serviceInfo
!=
null
)
{
final
Uri
?
vmServiceUri
=
_serviceInfo
!.
serverUri
;
if
(
vmServiceUri
!=
null
)
{
final
String
?
inspectorRef
=
toId
(
object
,
_consoleObjectGroup
);
if
(
inspectorRef
!=
null
)
{
return
devToolsInspectorUri
(
vmServiceUri
,
inspectorRef
);
}
}
}
return
null
;
}
/// Returns the DevTools inspector uri for the given vm service connection and
/// inspector reference.
@visibleForTesting
String
devToolsInspectorUri
(
Uri
vmServiceUri
,
String
inspectorRef
)
{
final
Uri
uri
=
Uri
.
parse
(
activeDevToolsServerAddress
!).
replace
(
queryParameters:
<
String
,
dynamic
>{
'uri'
:
'
$vmServiceUri
'
,
'inspectorRef'
:
inspectorRef
,
},
);
// We cannot add the '/#/inspector' path by means of
// [Uri.replace(path: '/#/inspector')] because the '#' character will be
// encoded when we try to print the url as a string. DevTools will not
// load properly if this character is encoded in the url.
// Related: https://github.com/flutter/devtools/issues/2475.
final
String
devToolsInspectorUri
=
uri
.
toString
();
final
int
startQueryParamIndex
=
devToolsInspectorUri
.
indexOf
(
'?'
);
// The query parameter character '?' should be present because we manually
// added query parameters above.
assert
(
startQueryParamIndex
!=
-
1
);
return
'
${devToolsInspectorUri.substring(0, startQueryParamIndex)}
'
'/#/inspector'
'
${devToolsInspectorUri.substring(startQueryParamIndex)}
'
;
}
/// Returns JSON representing the chain of [DiagnosticsNode] instances from
/// root of thee tree to the [Element] or [RenderObject] matching `id`.
///
...
...
@@ -2877,15 +2929,26 @@ Iterable<DiagnosticsNode> _describeRelevantUserCode(Element element) {
// TODO(chunhtai): should print out all the widgets that are about to cross
// package boundaries.
if
(
debugIsLocalCreationLocation
(
target
))
{
nodes
.
add
(
DiagnosticsNode
?
devToolsDiagnostic
;
final
String
?
devToolsInspectorUri
=
WidgetInspectorService
.
instance
.
_devToolsInspectorUriForElement
(
target
);
if
(
devToolsInspectorUri
!=
null
)
{
devToolsDiagnostic
=
DiagnosticsNode
.
message
(
'To inspect this widget in Flutter DevTools, visit:
$devToolsInspectorUri
'
,
);
}
nodes
.
addAll
(<
DiagnosticsNode
>[
DiagnosticsBlock
(
name:
'The relevant error-causing widget was'
,
children:
<
DiagnosticsNode
>[
ErrorDescription
(
'
${target.widget.toStringShort()}
${_describeCreationLocation(target)}
'
),
],
),
);
nodes
.
add
(
ErrorSpacer
());
ErrorSpacer
(),
if
(
devToolsDiagnostic
!=
null
)
...<
DiagnosticsNode
>[
devToolsDiagnostic
,
ErrorSpacer
()],
]);
return
false
;
}
return
true
;
...
...
packages/flutter/test/foundation/service_extensions_test.dart
View file @
b45088c0
...
...
@@ -167,7 +167,7 @@ void main() {
const
int
disabledExtensions
=
kIsWeb
?
2
:
0
;
// If you add a service extension... TEST IT! :-)
// ...then increment this number.
expect
(
binding
.
extensions
.
length
,
29
+
widgetInspectorExtensionCount
-
disabledExtensions
);
expect
(
binding
.
extensions
.
length
,
30
+
widgetInspectorExtensionCount
-
disabledExtensions
);
expect
(
console
,
isEmpty
);
debugPrint
=
debugPrintThrottled
;
...
...
@@ -758,4 +758,17 @@ void main() {
expect
(
brightnessValue
,
'Brightness.light'
);
});
test
(
'Service extensions - activeDevToolsServerAddress'
,
()
async
{
Map
<
String
,
dynamic
>
result
;
result
=
await
binding
.
testExtension
(
'activeDevToolsServerAddress'
,
<
String
,
String
>{});
String
serverAddress
=
result
[
'value'
]
as
String
;
expect
(
serverAddress
,
''
);
result
=
await
binding
.
testExtension
(
'activeDevToolsServerAddress'
,
<
String
,
String
>{
'value'
:
'http://127.0.0.1:9101'
});
serverAddress
=
result
[
'value'
]
as
String
;
expect
(
serverAddress
,
'http://127.0.0.1:9101'
);
result
=
await
binding
.
testExtension
(
'activeDevToolsServerAddress'
,
<
String
,
String
>{
'value'
:
'http://127.0.0.1:9102'
});
serverAddress
=
result
[
'value'
]
as
String
;
expect
(
serverAddress
,
'http://127.0.0.1:9102'
);
});
}
packages/flutter/test/widgets/widget_inspector_test.dart
View file @
b45088c0
...
...
@@ -2825,6 +2825,16 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect
(
debugIsLocalCreationLocation
(
paddingElement
.
widget
),
isFalse
);
},
skip:
!
WidgetInspectorService
.
instance
.
isWidgetCreationTracked
());
// Test requires --track-widget-creation flag.
test
(
'devToolsInspectorUri test'
,
()
{
activeDevToolsServerAddress
=
'http://127.0.0.1:9100'
;
expect
(
WidgetInspectorService
.
instance
.
devToolsInspectorUri
(
Uri
.
parse
(
'http://127.0.0.1:55269/798ay5al_FM=/'
),
'inspector-0'
,
),
equals
(
'http://127.0.0.1:9100/#/inspector?uri=http%3A%2F%2F127.0.0.1%3A55269%2F798ay5al_FM%3D%2F&inspectorRef=inspector-0'
),
);
});
}
}
...
...
packages/flutter_tools/lib/src/resident_runner.dart
View file @
b45088c0
...
...
@@ -1284,6 +1284,27 @@ abstract class ResidentRunner {
}
}
Future
<
void
>
maybeCallDevToolsUriServiceExtension
()
async
{
_devToolsLauncher
??=
DevtoolsLauncher
.
instance
;
if
(
_devToolsLauncher
.
activeDevToolsServer
!=
null
)
{
await
Future
.
wait
(<
Future
<
vm_service
.
Isolate
>>[
for
(
final
FlutterDevice
device
in
flutterDevices
)
waitForExtension
(
device
.
vmService
,
'ext.flutter.activeDevToolsServerAddress'
),
]);
try
{
unawaited
(
invokeFlutterExtensionRpcRawOnFirstIsolate
(
'ext.flutter.activeDevToolsServerAddress'
,
params:
<
String
,
dynamic
>{
'value'
:
_devToolsLauncher
.
activeDevToolsServer
.
uri
.
toString
(),
},
));
}
on
Exception
catch
(
e
)
{
globals
.
printError
(
e
.
toString
());
}
}
}
Future
<
void
>
shutdownDevTools
()
async
{
await
_devToolsLauncher
?.
close
();
_devToolsLauncher
=
null
;
...
...
@@ -1391,6 +1412,28 @@ abstract class ResidentRunner {
// Clears the screen.
void
clearScreen
()
=>
globals
.
logger
.
clear
();
Future
<
vm_service
.
Isolate
>
waitForExtension
(
vm_service
.
VmService
vmService
,
String
extension
)
async
{
final
Completer
<
void
>
completer
=
Completer
<
void
>();
try
{
await
vmService
.
streamListen
(
vm_service
.
EventStreams
.
kExtension
);
}
on
Exception
{
// do nothing
}
vmService
.
onExtensionEvent
.
listen
((
vm_service
.
Event
event
)
{
if
(
event
.
json
[
'extensionKind'
]
==
'Flutter.FrameworkInitialization'
)
{
completer
.
complete
();
}
});
final
vm_service
.
IsolateRef
isolateRef
=
(
await
vmService
.
getVM
()).
isolates
.
first
;
final
vm_service
.
Isolate
isolate
=
await
vmService
.
getIsolate
(
isolateRef
.
id
);
if
(
isolate
.
extensionRPCs
.
contains
(
extension
))
{
return
isolate
;
}
await
completer
.
future
;
return
isolate
;
}
}
class
OperationResult
{
...
...
packages/flutter_tools/lib/src/run_cold.dart
View file @
b45088c0
...
...
@@ -6,6 +6,7 @@ import 'dart:async';
import
'package:meta/meta.dart'
;
import
'base/common.dart'
;
import
'base/file_system.dart'
;
import
'build_info.dart'
;
import
'device.dart'
;
...
...
@@ -120,6 +121,10 @@ class ColdRunner extends ResidentRunner {
appFinished
();
}
if
(
debuggingEnabled
)
{
unawaited
(
maybeCallDevToolsUriServiceExtension
());
}
appStartedCompleter
?.
complete
();
writeVmServiceFile
();
...
...
@@ -161,6 +166,9 @@ class ColdRunner extends ResidentRunner {
globals
.
printTrace
(
'Connected to
$view
.'
);
}
}
unawaited
(
maybeCallDevToolsUriServiceExtension
());
appStartedCompleter
?.
complete
();
if
(
stayResident
)
{
return
waitForAppToFinish
();
...
...
packages/flutter_tools/lib/src/run_hot.dart
View file @
b45088c0
...
...
@@ -8,6 +8,7 @@ import 'package:vm_service/vm_service.dart' as vm_service;
import
'package:meta/meta.dart'
;
import
'package:pool/pool.dart'
;
import
'base/common.dart'
;
import
'base/context.dart'
;
import
'base/file_system.dart'
;
import
'base/logger.dart'
;
...
...
@@ -214,6 +215,9 @@ class HotRunner extends ResidentRunner {
globals
.
printError
(
'Error initializing DevFS:
$error
'
);
return
3
;
}
unawaited
(
maybeCallDevToolsUriServiceExtension
());
final
Stopwatch
initialUpdateDevFSsTimer
=
Stopwatch
()..
start
();
final
UpdateFSReport
devfsResult
=
await
_updateDevFS
(
fullRestart:
true
);
_addBenchmarkData
(
...
...
packages/flutter_tools/test/integration.shard/flutter_attach_test.dart
View file @
b45088c0
...
...
@@ -72,4 +72,30 @@ void main() {
await
_flutterAttach
.
attach
(
_flutterRun
.
vmServicePort
);
await
_flutterAttach
.
hotReload
();
});
testWithoutContext
(
'sets activeDevToolsServerAddress extension'
,
()
async
{
await
_flutterRun
.
run
(
startPaused:
true
,
withDebugger:
true
,
);
await
_flutterRun
.
resume
();
await
pollForServiceExtensionValue
(
testDriver:
_flutterRun
,
extension:
'ext.flutter.activeDevToolsServerAddress'
,
continuePollingValue:
''
,
expectedValue:
'http://127.0.0.1:9100'
,
);
// Attach with a different DevTools server address.
await
_flutterAttach
.
attach
(
_flutterRun
.
vmServicePort
,
additionalCommandArgs:
<
String
>[
'--devtools-server-address'
,
'http://127.0.0.1:9110'
],
);
await
pollForServiceExtensionValue
(
testDriver:
_flutterAttach
,
extension:
'ext.flutter.activeDevToolsServerAddress'
,
continuePollingValue:
''
,
expectedValue:
'http://127.0.0.1:9110'
,
);
});
}
packages/flutter_tools/test/integration.shard/flutter_run_test.dart
View file @
b45088c0
...
...
@@ -53,4 +53,19 @@ void main() {
await
_flutter
.
run
(
pidFile:
pidFile
);
expect
(
pidFile
.
existsSync
(),
isTrue
);
});
testWithoutContext
(
'sets activeDevToolsServerAddress extension'
,
()
async
{
await
_flutter
.
run
(
startPaused:
true
,
withDebugger:
true
,
additionalCommandArgs:
<
String
>[
'--devtools-server-address'
,
'http://127.0.0.1:9110'
],
);
await
_flutter
.
resume
();
await
pollForServiceExtensionValue
(
testDriver:
_flutter
,
extension:
'ext.flutter.activeDevToolsServerAddress'
,
continuePollingValue:
''
,
expectedValue:
'http://127.0.0.1:9110'
,
);
});
}
packages/flutter_tools/test/integration.shard/test_driver.dart
View file @
b45088c0
...
...
@@ -169,6 +169,19 @@ abstract class FlutterTestDriver {
}
}
Future
<
Response
>
callServiceExtension
(
String
extension
,
{
Map
<
String
,
dynamic
>
args
=
const
<
String
,
dynamic
>{},
})
async
{
final
VmService
vmService
=
await
vmServiceConnectUri
(
'ws://localhost:
$vmServicePort
/ws'
);
final
Isolate
isolate
=
await
waitForExtension
(
vmService
,
'ext.flutter.activeDevToolsServerAddress'
);
return
await
vmService
.
callServiceExtension
(
extension
,
isolateId:
isolate
.
id
,
args:
args
,
);
}
Future
<
int
>
quit
()
=>
_killGracefully
();
Future
<
int
>
_killGracefully
()
async
{
...
...
@@ -493,6 +506,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
bool
pauseOnExceptions
=
false
,
File
pidFile
,
bool
singleWidgetReloads
=
false
,
List
<
String
>
additionalCommandArgs
,
})
async
{
await
_setupProcess
(
<
String
>[
...
...
@@ -505,6 +519,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
'flutter-tester'
,
'--debug-port'
,
'
$port
'
,
...?
additionalCommandArgs
,
],
withDebugger:
withDebugger
,
startPaused:
startPaused
,
...
...
@@ -825,7 +840,7 @@ class SourcePosition {
final
int
column
;
}
Future
<
Isolate
>
waitForExtension
(
VmService
vmService
)
async
{
Future
<
Isolate
>
waitForExtension
(
VmService
vmService
,
String
extension
)
async
{
final
Completer
<
void
>
completer
=
Completer
<
void
>();
await
vmService
.
streamListen
(
EventStreams
.
kExtension
);
vmService
.
onExtensionEvent
.
listen
((
Event
event
)
{
...
...
@@ -835,7 +850,7 @@ Future<Isolate> waitForExtension(VmService vmService) async {
});
final
IsolateRef
isolateRef
=
(
await
vmService
.
getVM
()).
isolates
.
first
;
final
Isolate
isolate
=
await
vmService
.
getIsolate
(
isolateRef
.
id
);
if
(
isolate
.
extensionRPCs
.
contains
(
'ext.flutter.brightnessOverride'
))
{
if
(
isolate
.
extensionRPCs
.
contains
(
extension
))
{
return
isolate
;
}
await
completer
.
future
;
...
...
packages/flutter_tools/test/integration.shard/test_utils.dart
View file @
b45088c0
...
...
@@ -6,9 +6,12 @@ import 'package:file/file.dart';
import
'package:file/local.dart'
;
import
'package:flutter_tools/src/base/io.dart'
;
import
'package:flutter_tools/src/base/platform.dart'
;
import
'package:meta/meta.dart'
;
import
'package:process/process.dart'
;
import
'package:vm_service/vm_service.dart'
;
import
'../src/common.dart'
;
import
'test_driver.dart'
;
/// The [FileSystem] for the integration test environment.
const
FileSystem
fileSystem
=
LocalFileSystem
();
...
...
@@ -73,3 +76,21 @@ List<String> getLocalEngineArguments() {
'--local-engine-src-path=
${platform.environment[kLocalEngineLocation]}
'
,
];
}
Future
<
void
>
pollForServiceExtensionValue
<
T
>({
@required
FlutterTestDriver
testDriver
,
@required
String
extension
,
@required
T
continuePollingValue
,
@required
T
expectedValue
,
String
valueKey
=
'value'
,
})
async
{
for
(
int
i
=
10
;
i
<
10
;
i
++)
{
final
Response
response
=
await
testDriver
.
callServiceExtension
(
extension
);
if
(
response
.
json
[
valueKey
]
==
continuePollingValue
)
{
await
Future
<
void
>.
delayed
(
const
Duration
(
seconds:
1
));
}
else
{
expect
(
response
.
json
[
valueKey
],
equals
(
expectedValue
));
break
;
}
}
}
packages/flutter_tools/test/integration.shard/vmservice_integration_test.dart
View file @
b45088c0
...
...
@@ -96,7 +96,7 @@ void main() {
});
testWithoutContext
(
'ext.flutter.brightnessOverride can toggle window brightness'
,
()
async
{
final
Isolate
isolate
=
await
waitForExtension
(
vmService
);
final
Isolate
isolate
=
await
waitForExtension
(
vmService
,
'ext.flutter.brightnessOverride'
);
final
Response
response
=
await
vmService
.
callServiceExtension
(
'ext.flutter.brightnessOverride'
,
isolateId:
isolate
.
id
,
...
...
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