From 307987339edeff16d6a8cc5ac66331a717bac090 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Wed, 2 Nov 2022 17:07:58 +0000 Subject: [PATCH] [flutter_tools/dap] Map org-dartlang-sdk URIs to the location of the source files found by the analyzer (#114369) --- .../src/debug_adapters/flutter_adapter.dart | 11 ++++- .../debug_adapters/flutter_test_adapter.dart | 11 ++++- .../lib/src/debug_adapters/mixins.dart | 36 ++++++++++++++ .../dap/flutter_adapter_test.dart | 49 +++++++++++++++++-- 4 files changed, 100 insertions(+), 7 deletions(-) diff --git a/packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart b/packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart index 3d058580959..b26f2a98f64 100644 --- a/packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart +++ b/packages/flutter_tools/lib/src/debug_adapters/flutter_adapter.dart @@ -19,7 +19,7 @@ import 'mixins.dart'; /// A DAP Debug Adapter for running and debugging Flutter applications. class FlutterDebugAdapter extends DartDebugAdapter - with PidTracker { + with PidTracker, FlutterAdapter { FlutterDebugAdapter( super.channel, { required this.fileSystem, @@ -30,14 +30,21 @@ class FlutterDebugAdapter extends DartDebugAdapter - with PidTracker, TestAdapter { + with PidTracker, FlutterAdapter, TestAdapter { FlutterTestDebugAdapter( super.channel, { required this.fileSystem, @@ -30,14 +30,21 @@ class FlutterTestDebugAdapter extends DartDebugAdapter get orgDartlangSdkMappings; + String get flutterSdkRoot; + FileSystem get fileSystem; + + void configureOrgDartlangSdkMappings() { + /// When a user navigates into 'dart:xxx' sources in their editor (via the + /// analysis server) they will land in flutter_sdk/bin/cache/pkg/sky_engine. + /// + /// The running VM knows nothing about these paths and will resolve these + /// libraries to 'org-dartlang-sdk://' URIs. We need to map between these + /// to ensure that if a user puts a breakpoint inside sky_engine the VM can + /// apply it to the correct place and once hit, we can navigate the user + /// back to the correct file on their disk. + /// + /// The mapping is handled by the base adapter but we need to override the + /// paths to match the layout used by Flutter. + /// + /// In future this might become unnecessary if + /// https://github.com/dart-lang/sdk/issues/48435 is implemented. Until + /// then, providing these mappings improves the debugging experience. + + // Clear original Dart SDK mappings because they're not valid here. + orgDartlangSdkMappings.clear(); + + // 'dart:ui' maps to /flutter/lib/ui + final String flutterRoot = fileSystem.path.join(flutterSdkRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'ui'); + orgDartlangSdkMappings[flutterRoot] = Uri.parse('org-dartlang-sdk:///flutter/lib/ui'); + + // The rest of the Dart SDK maps to /third_party/dart/sdk + final String dartRoot = fileSystem.path.join(flutterSdkRoot, 'bin', 'cache', 'pkg', 'sky_engine'); + orgDartlangSdkMappings[dartRoot] = Uri.parse('org-dartlang-sdk:///third_party/dart/sdk'); + } +} diff --git a/packages/flutter_tools/test/general.shard/dap/flutter_adapter_test.dart b/packages/flutter_tools/test/general.shard/dap/flutter_adapter_test.dart index 4f6ae0ef3bb..8a7d44a31ac 100644 --- a/packages/flutter_tools/test/general.shard/dap/flutter_adapter_test.dart +++ b/packages/flutter_tools/test/general.shard/dap/flutter_adapter_test.dart @@ -6,8 +6,10 @@ import 'dart:async'; import 'package:dds/dap.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/cache.dart'; +import 'package:flutter_tools/src/debug_adapters/flutter_adapter.dart'; import 'package:flutter_tools/src/debug_adapters/flutter_adapter_args.dart'; import 'package:flutter_tools/src/globals.dart' as globals show platform; import 'package:test/fake.dart'; @@ -20,6 +22,9 @@ void main() { // Use the real platform as a base so that Windows bots test paths. final FakePlatform platform = FakePlatform.fromPlatform(globals.platform); final FileSystemStyle fsStyle = platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix; + final String flutterRoot = platform.isWindows + ? r'C:\fake\flutter' + : '/fake/flutter'; group('flutter adapter', () { final String expectedFlutterExecutable = platform.isWindows @@ -27,9 +32,7 @@ void main() { : '/fake/flutter/bin/flutter'; setUpAll(() { - Cache.flutterRoot = platform.isWindows - ? r'C:\fake\flutter' - : '/fake/flutter'; + Cache.flutterRoot = flutterRoot; }); group('launchRequest', () { @@ -314,6 +317,46 @@ void main() { expect(adapter.processArgs, contains('tool_arg')); }); + group('maps org-dartlang-sdk paths', () { + late FileSystem fs; + late FlutterDebugAdapter adapter; + setUp(() { + fs = MemoryFileSystem.test(style: fsStyle); + adapter = MockFlutterDebugAdapter( + fileSystem: fs, + platform: platform, + ); + }); + + test('dart:ui URI to file path', () async { + expect( + adapter.convertOrgDartlangSdkToPath(Uri.parse('org-dartlang-sdk:///flutter/lib/ui/ui.dart')), + fs.path.join(flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'ui', 'ui.dart'), + ); + }); + + test('dart:ui file path to URI', () async { + expect( + adapter.convertPathToOrgDartlangSdk(fs.path.join(flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'ui', 'ui.dart')), + Uri.parse('org-dartlang-sdk:///flutter/lib/ui/ui.dart'), + ); + }); + + test('dart:core URI to file path', () async { + expect( + adapter.convertOrgDartlangSdkToPath(Uri.parse('org-dartlang-sdk:///third_party/dart/sdk/lib/core/core.dart')), + fs.path.join(flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'core', 'core.dart'), + ); + }); + + test('dart:core file path to URI', () async { + expect( + adapter.convertPathToOrgDartlangSdk(fs.path.join(flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'core', 'core.dart')), + Uri.parse('org-dartlang-sdk:///third_party/dart/sdk/lib/core/core.dart'), + ); + }); + }); + group('includes customTool', () { test('with no args replaced', () async { final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(