analyzer: Refactor how the mock 'dart:ui' library is discovered
Fixes https://github.com/dart-lang/sdk/issues/62234 by making the 'dart:ui' library discoverable in the same way that the real one is discoverable: by the sky_engine _embedder.yaml file. Coupled with this change is the motivation: the stubs are out-of-date, with `double width` and `double height` parameters on the Preview constructor. But this has been changed to use a `Size` object, and `Size` is written in 'dart:ui'. So to write a test that uses `Size`, the test now needs proper access to 'dart:ui', and we should not write 'package:ui/ui.dart' in our test cases. These changes are in `.../lib/mock_packages/package_content/flutter/lib/src/widget_previews/widget_previews.dart` and in `invalid_widget_preview_private_argument_test.dart`. Change-Id: I6f608eb3e1f431ad576ba8f3572454e42a39f9f1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/467680 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
committed by
Commit Queue
parent
68e2db8ce6
commit
25f0d80c15
@@ -148,6 +148,7 @@ abstract class AbstractAnalysisServerIntegrationTest extends IntegrationTest
|
||||
/// updates.
|
||||
bool _subscribedToServerStatus = false;
|
||||
|
||||
@override
|
||||
String dartSdkPath = path.dirname(path.dirname(Platform.resolvedExecutable));
|
||||
|
||||
StreamController<Request> serverToClientRequestsController =
|
||||
|
||||
@@ -56,6 +56,9 @@ class AbstractContextTest
|
||||
|
||||
List<String> get collectionIncludedPaths => [workspaceRootPath];
|
||||
|
||||
@override
|
||||
String get dartSdkPath => sdkRoot.path;
|
||||
|
||||
/// The line terminator being used for test files and to be expected in edits.
|
||||
String get eol => testEol;
|
||||
|
||||
|
||||
@@ -74,6 +74,8 @@ abstract class ContextResolutionTest with ResourceProviderMixin {
|
||||
|
||||
void Function(Notification)? notificationListener;
|
||||
|
||||
String get dartSdkPath => sdkRoot.path;
|
||||
|
||||
bool get retainDataForTesting => false;
|
||||
|
||||
Folder get sdkRoot => newFolder('/sdk');
|
||||
|
||||
@@ -21,7 +21,7 @@ void main() {
|
||||
class DocumentColorPresentationTest extends AbstractLspAnalysisServerTest {
|
||||
late TestCode code;
|
||||
late String testFilePath;
|
||||
final uiImportUri = 'package:ui/ui.dart';
|
||||
final uiImportUri = 'dart:ui';
|
||||
Range get colorRange => code.range.range;
|
||||
set content(String content) => code = TestCode.parse(content);
|
||||
Uri get testFileUri => pathContext.toUri(testFilePath);
|
||||
@@ -397,7 +397,7 @@ var white = [!Color.fromRGBO(191, 128, 64, 1)!];
|
||||
// allow a picker, but we want to ensure the generated code needs to add
|
||||
// an additional import to reference the `Color` class.
|
||||
content = '''
|
||||
import 'package:flutter/material.dart' show Colors;^
|
||||
^import 'package:flutter/material.dart' show Colors;
|
||||
|
||||
const white = [!Colors.white!];
|
||||
''';
|
||||
@@ -409,7 +409,7 @@ const white = [!Colors.white!];
|
||||
start: code.position.position,
|
||||
end: code.position.position,
|
||||
),
|
||||
newText: "${eol}import '$uiImportUri';",
|
||||
newText: "import '$uiImportUri';$eol$eol",
|
||||
),
|
||||
];
|
||||
|
||||
|
||||
@@ -76,6 +76,9 @@ abstract class AbstractLspAnalysisServerTest
|
||||
|
||||
DartFixPromptManager? get dartFixPromptManager => null;
|
||||
|
||||
@override
|
||||
String get dartSdkPath => sdkRoot.path;
|
||||
|
||||
@override
|
||||
LspClientCapabilities get editorClientCapabilities =>
|
||||
server.editorClientCapabilities!;
|
||||
@@ -91,6 +94,8 @@ abstract class AbstractLspAnalysisServerTest
|
||||
|
||||
bool get retainDataForTesting => false;
|
||||
|
||||
Folder get sdkRoot => newFolder('/sdk');
|
||||
|
||||
AnalysisServerOptions get serverOptions => AnalysisServerOptions();
|
||||
|
||||
@override
|
||||
@@ -269,8 +274,6 @@ abstract class AbstractLspAnalysisServerTest
|
||||
processRunner = MockProcessRunner();
|
||||
channel = MockLspServerChannel(debugPrintCommunication);
|
||||
|
||||
// Create an SDK in the mock file system.
|
||||
var sdkRoot = newFolder('/sdk');
|
||||
createMockSdk(resourceProvider: resourceProvider, root: sdkRoot);
|
||||
|
||||
errorNotifier = ErrorNotifier();
|
||||
|
||||
@@ -187,12 +187,12 @@ void f() {
|
||||
"kind": "ENUM",
|
||||
"enumItems": [
|
||||
{
|
||||
"libraryUri": "package:ui/ui.dart",
|
||||
"libraryUri": "dart:ui",
|
||||
"className": "FontStyle",
|
||||
"name": "normal"
|
||||
},
|
||||
{
|
||||
"libraryUri": "package:ui/ui.dart",
|
||||
"libraryUri": "dart:ui",
|
||||
"className": "FontStyle",
|
||||
"name": "italic"
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ mixin ConfigurationFilesMixin on MockPackagesMixin {
|
||||
/// This allows `package:vector_math/vector_math_64.dart` imports to resolve.
|
||||
bool get addVectorMathPackageDep => false;
|
||||
|
||||
String get dartSdkPath;
|
||||
|
||||
/// The Dart language version of the test package being used for testing.
|
||||
String get testPackageLanguageVersion => _latestLanguageVersion;
|
||||
|
||||
@@ -68,8 +70,8 @@ mixin ConfigurationFilesMixin on MockPackagesMixin {
|
||||
}
|
||||
|
||||
if (flutter) {
|
||||
var uiLibFolder = addUI();
|
||||
config.add(name: 'ui', rootPath: uiLibFolder.parent.path);
|
||||
var skyEnginePath = addSkyEngine(sdkPath: dartSdkPath).parent.path;
|
||||
config.add(name: 'sky_engine', rootPath: skyEnginePath);
|
||||
|
||||
var flutterLibFolder = addFlutter();
|
||||
config.add(name: 'flutter', rootPath: flutterLibFolder.parent.path);
|
||||
|
||||
@@ -403,8 +403,8 @@ class _VisibleOutsideTemplate {
|
||||
}
|
||||
|
||||
if (flutter) {
|
||||
var uiPath = addUI().parent.path;
|
||||
config.add(name: 'ui', rootPath: uiPath);
|
||||
var skyEnginePath = addSkyEngine(sdkPath: sdkRoot.path).parent.path;
|
||||
config.add(name: 'sky_engine', rootPath: skyEnginePath);
|
||||
|
||||
var flutterPath = addFlutter().parent.path;
|
||||
config.add(name: 'flutter', rootPath: flutterPath);
|
||||
|
||||
+39
-49
@@ -80,6 +80,33 @@ Widget extraPrivateName() => Text('Foo');
|
||||
);
|
||||
}
|
||||
|
||||
test_invalidPrivatePreviewArguments_inArgumentExpression() async {
|
||||
const String kPrivateTextScaleFactor = '_textScaleFactor';
|
||||
|
||||
await assertErrorsInCode(
|
||||
'''
|
||||
import 'package:flutter/widget_previews.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
const double $kPrivateTextScaleFactor = 2.0;
|
||||
|
||||
@Preview(textScaleFactor: $kPrivateTextScaleFactor + 1)
|
||||
Widget numericExpressionWithPrivateDouble() => Text('Foo');
|
||||
''',
|
||||
[
|
||||
error(
|
||||
diag.invalidWidgetPreviewPrivateArgument,
|
||||
134,
|
||||
37,
|
||||
correctionContains: correctionMessageBuilder(
|
||||
kPrivateTextScaleFactor,
|
||||
kPrivateTextScaleFactor.substring(1),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
test_invalidPrivatePreviewArguments_interpolatedInStringArgument() async {
|
||||
const String kPrivateName = '_privateName';
|
||||
|
||||
@@ -108,47 +135,37 @@ Widget privateNameStringInterp() => Text('Foo');
|
||||
}
|
||||
|
||||
test_invalidPrivatePreviewArguments_size() async {
|
||||
// TODO(srawlins): Update to the new Size argument.
|
||||
const String kPrivateWidth = '_privateWidth';
|
||||
const String kPrivateHeight = '_privateHeight';
|
||||
const String kPrivateSize = '_privateSize';
|
||||
const String kPrivateTextScaleFactor = '_textScaleFactor';
|
||||
|
||||
await assertErrorsInCode(
|
||||
'''
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/widget_previews.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
const double $kPrivateWidth = 42.0;
|
||||
const double $kPrivateHeight = 24.0;
|
||||
const Size $kPrivateSize = Size(42.0, 24.0);
|
||||
const double $kPrivateTextScaleFactor = 2.0;
|
||||
|
||||
@Preview(width: $kPrivateWidth,
|
||||
height: $kPrivateHeight,
|
||||
textScaleFactor: $kPrivateTextScaleFactor)
|
||||
@Preview(
|
||||
size: $kPrivateSize,
|
||||
textScaleFactor: $kPrivateTextScaleFactor,
|
||||
)
|
||||
Widget privateDoubles() => Text('Foo');
|
||||
''',
|
||||
[
|
||||
error(
|
||||
diag.invalidWidgetPreviewPrivateArgument,
|
||||
205,
|
||||
20,
|
||||
200,
|
||||
18,
|
||||
correctionContains: correctionMessageBuilder(
|
||||
kPrivateWidth,
|
||||
kPrivateWidth.substring(1),
|
||||
kPrivateSize,
|
||||
kPrivateSize.substring(1),
|
||||
),
|
||||
),
|
||||
error(
|
||||
diag.invalidWidgetPreviewPrivateArgument,
|
||||
235,
|
||||
22,
|
||||
correctionContains: correctionMessageBuilder(
|
||||
kPrivateHeight,
|
||||
kPrivateHeight.substring(1),
|
||||
),
|
||||
),
|
||||
error(
|
||||
diag.invalidWidgetPreviewPrivateArgument,
|
||||
267,
|
||||
222,
|
||||
33,
|
||||
correctionContains: correctionMessageBuilder(
|
||||
kPrivateTextScaleFactor,
|
||||
@@ -187,33 +204,6 @@ Widget privateThemeData() => Text('Foo');
|
||||
);
|
||||
}
|
||||
|
||||
test_invalidPrivatePreviewArguments_widthInArgument() async {
|
||||
const String kPrivateWidth = '_privateWidth';
|
||||
|
||||
await assertErrorsInCode(
|
||||
'''
|
||||
import 'package:flutter/widget_previews.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
const double $kPrivateWidth = 42.0;
|
||||
|
||||
@Preview(width: $kPrivateWidth + 10)
|
||||
Widget numericExpressionWithPrivateDouble() => Text('Foo');
|
||||
''',
|
||||
[
|
||||
error(
|
||||
diag.invalidWidgetPreviewPrivateArgument,
|
||||
132,
|
||||
25,
|
||||
correctionContains: correctionMessageBuilder(
|
||||
kPrivateWidth,
|
||||
kPrivateWidth.substring(1),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
test_invalidPrivatePreviewArguments_wrapper() async {
|
||||
const String kPrivateWrapper = '_privateWrapper';
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
## 0.1.9-dev
|
||||
- Deprecate `MockPackagesMixin.addUI`; This is replaced by `addSkyEngine`.
|
||||
|
||||
## 0.1.8
|
||||
|
||||
- Require version `10.0.0` of the `analyzer` package.
|
||||
|
||||
@@ -34,8 +34,9 @@ package:analyzer_testing/mock_packages/mock_packages.dart:
|
||||
addKernel (method: Folder Function(), deprecated)
|
||||
addMeta (method: Folder Function())
|
||||
addPedantic (method: Folder Function(), deprecated)
|
||||
addSkyEngine (method: Folder Function({required String sdkPath}))
|
||||
addTestReflectiveLoader (method: Folder Function())
|
||||
addUI (method: Folder Function())
|
||||
addUI (method: Folder Function(), deprecated)
|
||||
addVectorMath (method: Folder Function())
|
||||
package:analyzer_testing/package_root.dart:
|
||||
packageRoot (static getter: String)
|
||||
|
||||
@@ -184,11 +184,57 @@ mixin MockPackagesMixin {
|
||||
return packageFolder.getChildAssumingFolder('lib');
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"Use 'addSkyEngine' to include stubs (mocks) for the 'dart:ui' library",
|
||||
)
|
||||
Folder addUI() {
|
||||
var packageFolder = _addFiles2('ui', mock_ui.units);
|
||||
return packageFolder.getChildAssumingFolder('lib');
|
||||
}
|
||||
|
||||
/// Adds a mock sky_engine package with an `_embedder.yaml` file, and returns
|
||||
/// the [Folder] of the sky_engine package's 'lib' directory.
|
||||
Folder addSkyEngine({required String sdkPath}) {
|
||||
// Emulate sky engine by writing to disk:
|
||||
// * a `sky_engine/lib` directory,
|
||||
// * a `sky_engine/lib/_embedder.yaml` file which points to the Dart SDK
|
||||
// sources, and
|
||||
// * the `dart:ui` sources into `sky_engine/lib/ui`.
|
||||
var packageFolder = _addFiles2('ui', mock_ui.units);
|
||||
|
||||
var skyEngineFolder = resourceProvider.getFolder(
|
||||
resourceProvider.convertPath('$packagesRootPath/sky_engine'),
|
||||
)..create();
|
||||
var skyEngineLibFolder = skyEngineFolder.getChildAssumingFolder('lib')
|
||||
..create();
|
||||
var embedderFile = skyEngineLibFolder.getChildAssumingFile(
|
||||
'_embedder.yaml',
|
||||
);
|
||||
embedderFile.writeAsStringSync('''
|
||||
embedded_libs:
|
||||
"dart:ui": "${packageFolder.path}/lib/ui.dart"
|
||||
|
||||
"dart:async": "$sdkPath/lib/async/async.dart"
|
||||
"dart:collection": "$sdkPath/lib/collection/collection.dart"
|
||||
"dart:convert": "$sdkPath/lib/convert/convert.dart"
|
||||
"dart:core": "$sdkPath/lib/core/core.dart"
|
||||
"dart:developer": "$sdkPath/lib/developer/developer.dart"
|
||||
"dart:ffi": "$sdkPath/lib/ffi/ffi.dart"
|
||||
"dart:html": "$sdkPath/lib/html/dart2js/html_dart2js.dart"
|
||||
"dart:io": "$sdkPath/lib/io/io.dart"
|
||||
"dart:isolate": "$sdkPath/lib/isolate/isolate.dart"
|
||||
"dart:js": "$sdkPath/lib/js/js.dart"
|
||||
"dart:js_interop": "$sdkPath/lib/js/js_interop.dart"
|
||||
"dart:math": "$sdkPath/lib/math/math.dart"
|
||||
"dart:typed_data": "$sdkPath/lib/typed_data/typed_data.dart"
|
||||
|
||||
"dart:_interceptors": "$sdkPath/lib/_interceptors/interceptors.dart"
|
||||
"dart:_internal": "$sdkPath/lib/internal/internal.dart"
|
||||
''');
|
||||
|
||||
return skyEngineLibFolder;
|
||||
}
|
||||
|
||||
Folder addVectorMath() {
|
||||
var packageFolder = _addFiles2('vector_math', mock_vector_math.units);
|
||||
return packageFolder.getChildAssumingFolder('lib');
|
||||
|
||||
+2
-2
@@ -2,9 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:ui/ui.dart' show TextDirection;
|
||||
import 'dart:ui' show TextDirection;
|
||||
|
||||
export 'package:ui/ui.dart'
|
||||
export 'dart:ui'
|
||||
show
|
||||
BlendMode,
|
||||
Color,
|
||||
|
||||
+39
-11
@@ -5,24 +5,52 @@
|
||||
import 'package:flutter/material.dart' show Brightness;
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
typedef PreviewTheme = PreviewThemeData Function();
|
||||
|
||||
typedef WidgetWrapper = Widget Function(Widget);
|
||||
|
||||
typedef PreviewLocalizations = PreviewLocalizationsData Function();
|
||||
|
||||
base class Preview {
|
||||
const Preview({
|
||||
this.name,
|
||||
this.width,
|
||||
this.height,
|
||||
this.textScaleFactor,
|
||||
this.wrapper,
|
||||
this.theme,
|
||||
this.brightness,
|
||||
String group = 'Default',
|
||||
String? name,
|
||||
Size? size,
|
||||
double? textScaleFactor,
|
||||
WidgetWrapper? wrapper,
|
||||
PreviewTheme? theme,
|
||||
Brightness? brightness,
|
||||
PreviewLocalizations? localizations,
|
||||
}) : this._required(
|
||||
group: group,
|
||||
name: name,
|
||||
size: size,
|
||||
textScaleFactor: textScaleFactor,
|
||||
wrapper: wrapper,
|
||||
theme: theme,
|
||||
brightness: brightness,
|
||||
localizations: localizations,
|
||||
);
|
||||
|
||||
const Preview._required({
|
||||
required this.group,
|
||||
required this.name,
|
||||
required this.size,
|
||||
required this.textScaleFactor,
|
||||
required this.wrapper,
|
||||
required this.theme,
|
||||
required this.brightness,
|
||||
required this.localizations,
|
||||
});
|
||||
|
||||
final String group;
|
||||
final String? name;
|
||||
final double? width;
|
||||
final double? height;
|
||||
final Size? size;
|
||||
final double? textScaleFactor;
|
||||
final Widget Function(Widget)? wrapper;
|
||||
final PreviewThemeData Function()? theme;
|
||||
final WidgetWrapper? wrapper;
|
||||
final PreviewTheme? theme;
|
||||
final Brightness? brightness;
|
||||
final PreviewLocalizations? localizations;
|
||||
}
|
||||
|
||||
base class PreviewThemeData {}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/painting.dart';
|
||||
import 'package:ui/ui.dart';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'framework.dart';
|
||||
|
||||
|
||||
@@ -640,8 +640,8 @@ class PubPackageResolutionTest with MockPackagesMixin, ResourceProviderMixin {
|
||||
}
|
||||
|
||||
if (addFlutterPackageDep) {
|
||||
var uiPath = addUI().parent.path;
|
||||
configCopy.add(name: 'ui', rootPath: uiPath);
|
||||
var skyEnginePath = addSkyEngine(sdkPath: _sdkRoot.path).parent.path;
|
||||
configCopy.add(name: 'sky_engine', rootPath: skyEnginePath);
|
||||
|
||||
var flutterPath = addFlutter().parent.path;
|
||||
configCopy.add(name: 'flutter', rootPath: flutterPath);
|
||||
|
||||
@@ -22,6 +22,14 @@ class Radius {
|
||||
const Radius.elliptical(this.x, this.y);
|
||||
}
|
||||
|
||||
class Size {
|
||||
final double width;
|
||||
|
||||
final double height;
|
||||
|
||||
const Size(this.width, this.height);
|
||||
}
|
||||
|
||||
enum BlendMode {
|
||||
clear,
|
||||
src,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: analyzer_testing
|
||||
description: Testing utilities related to the analyzer and analysis_server_plugin packages.
|
||||
version: 0.1.8
|
||||
version: 0.1.9-dev
|
||||
repository: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer_testing
|
||||
|
||||
environment:
|
||||
|
||||
Reference in New Issue
Block a user