Skip to content

Commit ab958be

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe,flutter] Make widget transformer location parameters optional
The location parameters added to Widgets was created as required and non-nullable when opting flutter in to null-safety. This leads to incremental compilation failing because already transformed constructors require parameters that cannot be passed by user code. Fixes flutter/flutter#60269 Change-Id: I91cbeaa455e67e82983ebb17f93da13b46376da2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153085 Reviewed-by: Jens Johansen <[email protected]> Reviewed-by: Jacob Richman <[email protected]> Commit-Queue: Johnni Winther <[email protected]>
1 parent a3d3777 commit ab958be

File tree

4 files changed

+201
-9
lines changed

4 files changed

+201
-9
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
# for details. All rights reserved. Use of this source code is governed by a
3+
# BSD-style license that can be found in the LICENSE.md file.
4+
5+
type: newworld
6+
target: DDC
7+
trackWidgetCreation: true
8+
worlds:
9+
- entry: main.dart
10+
experiments: non-nullable
11+
sources:
12+
main.dart: |
13+
import 'foo.dart';
14+
foo.dart:
15+
import 'package:flutter/src/widgets/framework.dart';
16+
import 'package:flutter/src/widgets/widget_inspector.dart';
17+
18+
class Foo extends Widget {
19+
const Foo();
20+
}
21+
flutter/lib/src/widgets/framework.dart: |
22+
abstract class Bar {
23+
const Bar();
24+
}
25+
26+
abstract class Widget extends Bar {
27+
const Widget();
28+
}
29+
flutter/lib/src/widgets/widget_inspector.dart: |
30+
abstract class _HasCreationLocation {
31+
_Location get _location;
32+
}
33+
34+
/// A tuple with file, line, and column number, for displaying human-readable
35+
/// file locations.
36+
class _Location {
37+
const _Location({
38+
required this.file,
39+
required this.line,
40+
required this.column,
41+
required this.name,
42+
required this.parameterLocations,
43+
});
44+
45+
/// File path of the location.
46+
final String file;
47+
48+
/// 1-based line number.
49+
final int line;
50+
51+
/// 1-based column number.
52+
final int column;
53+
54+
/// Optional name of the parameter or function at this location.
55+
final String name;
56+
57+
/// Optional locations of the parameters of the member at this location.
58+
final List<_Location> parameterLocations;
59+
}
60+
.dart_tool/package_config.json: |
61+
{
62+
"configVersion": 2,
63+
"packages": [
64+
{
65+
"name": "flutter",
66+
"rootUri": "../flutter",
67+
"packageUri": "lib/",
68+
"languageVersion": "2.9"
69+
}
70+
]
71+
}
72+
expectedLibraryCount: 4
73+
- entry: main.dart
74+
worldType: updated
75+
invalidate:
76+
- main.dart
77+
expectInitializeFromDill: false
78+
sources:
79+
main.dart: |
80+
import 'foo.dart';
81+
82+
Foo foo = const Foo();
83+
expectedLibraryCount: 4
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
main = <No Member>;
2+
library from "package:flutter/src/widgets/framework.dart" as fra {
3+
4+
abstract class Bar extends dart.core::Object /*hasConstConstructor*/ {
5+
const constructor •() → fra::Bar
6+
: super dart.core::Object::•()
7+
;
8+
}
9+
abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/ {
10+
final field wid::_Location? _location /*isNullableByDefault, from null */;
11+
const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → fra::Widget
12+
: super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4!
13+
;
14+
}
15+
}
16+
library from "package:flutter/src/widgets/widget_inspector.dart" as wid {
17+
18+
abstract class _HasCreationLocation extends dart.core::Object {
19+
synthetic constructor •() → wid::_HasCreationLocation
20+
: super dart.core::Object::•()
21+
;
22+
abstract get _location() → wid::_Location;
23+
}
24+
class _Location extends dart.core::Object /*hasConstConstructor*/ {
25+
final field dart.core::String file;
26+
final field dart.core::int line;
27+
final field dart.core::int column;
28+
final field dart.core::String name;
29+
final field dart.core::List<wid::_Location> parameterLocations;
30+
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
31+
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
32+
;
33+
}
34+
}
35+
library from "org-dartlang-test:///foo.dart" as foo {
36+
37+
import "package:flutter/src/widgets/framework.dart";
38+
import "package:flutter/src/widgets/widget_inspector.dart";
39+
40+
class Foo extends fra::Widget /*hasConstConstructor*/ {
41+
const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
42+
: super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
43+
;
44+
}
45+
}
46+
library from "org-dartlang-test:///main.dart" as main {
47+
48+
import "org-dartlang-test:///foo.dart";
49+
50+
}
51+
constants {
52+
#C1 = null
53+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
main = <No Member>;
2+
library from "package:flutter/src/widgets/framework.dart" as fra {
3+
4+
abstract class Bar extends dart.core::Object /*hasConstConstructor*/ {
5+
const constructor •() → fra::Bar
6+
: super dart.core::Object::•()
7+
;
8+
}
9+
abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/ {
10+
final field wid::_Location? _location /*isNullableByDefault, from null */;
11+
const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → fra::Widget
12+
: super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4!
13+
;
14+
}
15+
}
16+
library from "package:flutter/src/widgets/widget_inspector.dart" as wid {
17+
18+
abstract class _HasCreationLocation extends dart.core::Object {
19+
synthetic constructor •() → wid::_HasCreationLocation
20+
: super dart.core::Object::•()
21+
;
22+
abstract get _location() → wid::_Location;
23+
}
24+
class _Location extends dart.core::Object /*hasConstConstructor*/ {
25+
final field dart.core::String file;
26+
final field dart.core::int line;
27+
final field dart.core::int column;
28+
final field dart.core::String name;
29+
final field dart.core::List<wid::_Location> parameterLocations;
30+
const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
31+
: wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
32+
;
33+
}
34+
}
35+
library from "org-dartlang-test:///foo.dart" as foo {
36+
37+
import "package:flutter/src/widgets/framework.dart";
38+
import "package:flutter/src/widgets/widget_inspector.dart";
39+
40+
class Foo extends fra::Widget /*hasConstConstructor*/ {
41+
const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
42+
: super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
43+
;
44+
}
45+
}
46+
library from "org-dartlang-test:///main.dart" as main {
47+
48+
import "org-dartlang-test:///foo.dart";
49+
50+
static field foo::Foo foo = invalid-expression "Constant evaluation has no support for NullCheck!";
51+
}
52+
constants {
53+
#C1 = null
54+
}

pkg/kernel/lib/transformations/track_widget_constructor_locations.dart

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,8 @@ class WidgetCreatorTracker {
368368
_hasCreationLocationClass.enclosingLibrary,
369369
);
370370
final Field locationField = new Field(fieldName,
371-
type: new InterfaceType(
372-
_locationClass, clazz.enclosingLibrary.nonNullable),
371+
type:
372+
new InterfaceType(_locationClass, clazz.enclosingLibrary.nullable),
373373
isFinal: true,
374374
reference: clazz.reference.canonicalName
375375
?.getChildFromFieldWithName(fieldName)
@@ -389,8 +389,8 @@ class WidgetCreatorTracker {
389389
));
390390
final VariableDeclaration variable = new VariableDeclaration(
391391
_creationLocationParameterName,
392-
type: new InterfaceType(
393-
_locationClass, clazz.enclosingLibrary.nonNullable),
392+
type:
393+
new InterfaceType(_locationClass, clazz.enclosingLibrary.nullable),
394394
);
395395
if (!_maybeAddNamedParameter(constructor.function, variable)) {
396396
return;
@@ -418,7 +418,11 @@ class WidgetCreatorTracker {
418418
if (!hasRedirectingInitializer) {
419419
constructor.initializers.add(new FieldInitializer(
420420
locationField,
421-
new VariableGet(variable),
421+
clazz.enclosingLibrary.isNonNullableByDefault
422+
// The parameter is nullable so that it can be optional but the
423+
// field is non-nullable so we check it here.
424+
? new NullCheck(new VariableGet(variable))
425+
: new VariableGet(variable),
422426
));
423427
// TODO(jacobr): add an assert verifying the locationField is not
424428
// null. Currently, we cannot safely add this assert because we do not
@@ -535,8 +539,7 @@ class WidgetCreatorTracker {
535539
procedure.function,
536540
new VariableDeclaration(_creationLocationParameterName,
537541
type: new InterfaceType(
538-
_locationClass, clazz.enclosingLibrary.nonNullable),
539-
isRequired: clazz.enclosingLibrary.isNonNullableByDefault),
542+
_locationClass, clazz.enclosingLibrary.nullable)),
540543
);
541544
}
542545
}
@@ -559,8 +562,7 @@ class WidgetCreatorTracker {
559562
final VariableDeclaration variable = new VariableDeclaration(
560563
_creationLocationParameterName,
561564
type: new InterfaceType(
562-
_locationClass, clazz.enclosingLibrary.nonNullable),
563-
isRequired: clazz.enclosingLibrary.isNonNullableByDefault);
565+
_locationClass, clazz.enclosingLibrary.nullable));
564566
if (_hasNamedParameter(
565567
constructor.function, _creationLocationParameterName)) {
566568
// Constructor was already rewritten. TODO(jacobr): is this case actually hit?

0 commit comments

Comments
 (0)