Skip to content

Commit 2a5f37d

Browse files
author
Dart CI
committed
Version 2.10.0-80.0.dev
Merge commit 'f5a0e185d20b46dbfe112070bb2128a99e93a400' into 'dev'
2 parents 6eab35f + f5a0e18 commit 2a5f37d

File tree

12 files changed

+284
-19
lines changed

12 files changed

+284
-19
lines changed

pkg/analyzer/lib/error/error.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ const List<ErrorCode> errorCodeValues = [
465465
FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS,
466466
FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS,
467467
FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH,
468+
HintCode.ASSIGNMENT_OF_DO_NOT_STORE,
468469
HintCode.CAN_BE_NULL_AFTER_NULL_AWARE,
469470
HintCode.DEAD_CODE,
470471
HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH,

pkg/analyzer/lib/src/dart/element/extensions.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@ import 'package:analyzer/dart/element/type.dart';
77
import 'package:analyzer/src/dart/element/element.dart';
88
import 'package:analyzer/src/generated/utilities_dart.dart';
99

10+
extension ElementExtension on Element {
11+
/// Return `true` if this element, the enclosing class (if there is one), or
12+
/// the enclosing library, has been annotated with the `@doNotStore`
13+
/// annotation.
14+
bool get hasOrInheritsDoNotStore {
15+
if (hasDoNotStore) {
16+
return true;
17+
}
18+
var ancestor = enclosingElement;
19+
if (ancestor is ClassElement || ancestor is ExtensionElement) {
20+
if (ancestor.hasDoNotStore) {
21+
return true;
22+
}
23+
ancestor = ancestor.enclosingElement;
24+
}
25+
return ancestor is CompilationUnitElement &&
26+
ancestor.enclosingElement.hasDoNotStore;
27+
}
28+
}
29+
1030
extension ParameterElementExtensions on ParameterElement {
1131
/// Return [ParameterElement] with the specified properties replaced.
1232
ParameterElement copyWith({DartType type, ParameterKind kind}) {

pkg/analyzer/lib/src/dart/error/hint_codes.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ import 'package:analyzer/src/error/analyzer_error_code.dart';
1414
* mentioned in the Dart Language Specification.
1515
*/
1616
class HintCode extends AnalyzerErrorCode {
17+
/**
18+
* Users should not assign values marked `@doNotStore`.
19+
*/
20+
static const HintCode ASSIGNMENT_OF_DO_NOT_STORE = HintCode(
21+
'ASSIGNMENT_OF_DO_NOT_STORE',
22+
"'{0}' is marked 'doNotStore' and shouldn't be assigned to a field.",
23+
correction: "Try removing the assignment.");
24+
1725
/**
1826
* When the target expression uses '?.' operator, it can be `null`, so all the
1927
* subsequent invocations should also use '?.' operator.

pkg/analyzer/lib/src/error/best_practices_verifier.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import 'package:analyzer/dart/element/type.dart';
1414
import 'package:analyzer/dart/element/type_provider.dart';
1515
import 'package:analyzer/error/listener.dart';
1616
import 'package:analyzer/src/dart/element/element.dart';
17+
import 'package:analyzer/src/dart/element/extensions.dart';
1718
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
1819
import 'package:analyzer/src/dart/element/member.dart' show ExecutableMember;
1920
import 'package:analyzer/src/dart/element/type.dart';
@@ -359,6 +360,37 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
359360
field.name,
360361
[field.name, overriddenElement.enclosingElement.name]);
361362
}
363+
364+
var expression = field.initializer;
365+
366+
Element element;
367+
if (expression is PropertyAccess) {
368+
element = expression.propertyName.staticElement;
369+
// Tear-off.
370+
if (element is FunctionElement || element is MethodElement) {
371+
element = null;
372+
}
373+
} else if (expression is MethodInvocation) {
374+
element = expression.methodName.staticElement;
375+
} else if (expression is Identifier) {
376+
element = expression.staticElement;
377+
// Tear-off.
378+
if (element is FunctionElement || element is MethodElement) {
379+
element = null;
380+
}
381+
}
382+
if (element != null) {
383+
if (element is PropertyAccessorElement && element.isSynthetic) {
384+
element = (element as PropertyAccessorElement).variable;
385+
}
386+
if (element.hasOrInheritsDoNotStore) {
387+
_errorReporter.reportErrorForNode(
388+
HintCode.ASSIGNMENT_OF_DO_NOT_STORE,
389+
expression,
390+
[element.name],
391+
);
392+
}
393+
}
362394
}
363395
} finally {
364396
_inDeprecatedMember = wasInDeprecatedMember;

pkg/analyzer/lib/src/test_utilities/mock_packages.dart

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class JS {
2525
library meta;
2626
2727
const _AlwaysThrows alwaysThrows = const _AlwaysThrows();
28+
const _DoNotStore doNotStore = _DoNotStore();
2829
const _Factory factory = const _Factory();
2930
const Immutable immutable = const Immutable();
3031
const _Literal literal = const _Literal();
@@ -36,16 +37,19 @@ const Required required = const Required();
3637
const _Sealed sealed = const _Sealed();
3738
const _VisibleForTesting visibleForTesting = const _VisibleForTesting();
3839
39-
class Immutable {
40-
final String reason;
41-
const Immutable([this.reason]);
42-
}
4340
class _AlwaysThrows {
4441
const _AlwaysThrows();
4542
}
43+
class _DoNotStore {
44+
const _DoNotStore();
45+
}
4646
class _Factory {
4747
const _Factory();
4848
}
49+
class Immutable {
50+
final String reason;
51+
const Immutable([this.reason]);
52+
}
4953
class _Literal {
5054
const _Literal();
5155
}
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
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 file.
4+
5+
import 'package:analyzer/src/error/codes.dart';
6+
import 'package:test_reflective_loader/test_reflective_loader.dart';
7+
8+
import '../dart/resolution/context_collection_resolution.dart';
9+
10+
main() {
11+
defineReflectiveSuite(() {
12+
defineReflectiveTests(AssignmentOfDoNotStoreTest);
13+
});
14+
}
15+
16+
@reflectiveTest
17+
class AssignmentOfDoNotStoreTest extends PubPackageResolutionTest {
18+
@override
19+
void setUp() {
20+
super.setUp();
21+
writeTestPackageConfigWithMeta();
22+
}
23+
24+
test_classMemberGetter() async {
25+
await assertErrorsInCode('''
26+
import 'package:meta/meta.dart';
27+
28+
class A {
29+
@doNotStore
30+
String get v => '';
31+
}
32+
33+
class B {
34+
String f = A().v;
35+
}
36+
''', [
37+
error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 106, 5),
38+
]);
39+
}
40+
41+
test_classMemberVariable() async {
42+
await assertErrorsInCode('''
43+
import 'package:meta/meta.dart';
44+
45+
class A{
46+
@doNotStore
47+
final f = '';
48+
}
49+
50+
class B {
51+
String f = A().f;
52+
}
53+
''', [
54+
error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 99, 5),
55+
]);
56+
}
57+
58+
test_classStaticGetter() async {
59+
await assertErrorsInCode('''
60+
import 'package:meta/meta.dart';
61+
62+
class A {
63+
@doNotStore
64+
static String get v => '';
65+
}
66+
67+
class B {
68+
String f = A.v;
69+
}
70+
''', [
71+
error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 113, 3),
72+
]);
73+
}
74+
75+
test_classStaticVariable() async {
76+
await assertErrorsInCode('''
77+
import 'package:meta/meta.dart';
78+
79+
class A{
80+
@doNotStore
81+
static final f = '';
82+
}
83+
84+
class B {
85+
String f = A.f;
86+
}
87+
''', [
88+
error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 106, 3),
89+
]);
90+
}
91+
92+
test_functionAssignment() async {
93+
await assertNoErrorsInCode('''
94+
import 'package:meta/meta.dart';
95+
96+
@doNotStore
97+
String g(int i) => '';
98+
99+
class C {
100+
String Function(int) f = g;
101+
}
102+
''');
103+
}
104+
105+
test_functionReturnValue() async {
106+
await assertErrorsInCode('''
107+
import 'package:meta/meta.dart';
108+
109+
@doNotStore
110+
String getV() => '';
111+
112+
class A {
113+
final f = getV();
114+
}
115+
''', [
116+
error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 90, 6),
117+
]);
118+
}
119+
120+
test_methodReturnValue() async {
121+
await assertErrorsInCode('''
122+
import 'package:meta/meta.dart';
123+
124+
class A {
125+
@doNotStore
126+
String getV() => '';
127+
}
128+
129+
class B {
130+
final f = A().getV();
131+
}
132+
''', [
133+
error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 106, 10),
134+
]);
135+
}
136+
137+
test_tearOff() async {
138+
await assertNoErrorsInCode('''
139+
import 'package:meta/meta.dart';
140+
141+
@doNotStore
142+
String getV() => '';
143+
144+
class A {
145+
final f = getV;
146+
}
147+
''');
148+
}
149+
150+
test_topLevelGetter() async {
151+
await assertErrorsInCode('''
152+
import 'package:meta/meta.dart';
153+
154+
@doNotStore
155+
String get v => '';
156+
157+
class A {
158+
final f = v;
159+
}
160+
''', [
161+
error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 89, 1),
162+
]);
163+
}
164+
165+
test_topLevelVariable() async {
166+
await assertErrorsInCode('''
167+
import 'package:meta/meta.dart';
168+
169+
@doNotStore
170+
final v = '';
171+
172+
class A {
173+
final f = v;
174+
}
175+
''', [
176+
error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 83, 1),
177+
]);
178+
}
179+
}

pkg/analyzer/test/src/diagnostics/test_all.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import 'annotation_with_non_class_test.dart' as annotation_with_non_class;
2222
import 'argument_type_not_assignable_test.dart' as argument_type_not_assignable;
2323
import 'assert_in_redirecting_constructor_test.dart'
2424
as assert_in_redirecting_constructor;
25+
import 'assignment_of_do_not_store_test.dart' as assignment_of_do_not_store;
2526
import 'assignment_to_const_test.dart' as assignment_to_const;
2627
import 'assignment_to_final_local_test.dart' as assignment_to_final_local;
2728
import 'assignment_to_final_no_setter_test.dart'
@@ -653,6 +654,7 @@ main() {
653654
annotation_with_non_class.main();
654655
argument_type_not_assignable.main();
655656
assert_in_redirecting_constructor.main();
657+
assignment_of_do_not_store.main();
656658
assignment_to_const.main();
657659
assignment_to_final_local.main();
658660
assignment_to_final_no_setter.main();

pkg/dartdev/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@ A command-line utility for Dart development.
66
Usage: dart [<vm-flags>] <command|dart-file> [<arguments>]
77
88
Global options:
9-
-h, --help Print this usage information.
10-
-v, --verbose Show additional command output.
11-
--version Print the Dart SDK version.
12-
--enable-analytics Enable anonymous analytics.
13-
--disable-analytics Disable anonymous analytics.
14-
--enable-experiment=<experiment> Enable one or more experimental features (see dart.dev/go/experiments).
9+
-h, --help Print this usage information.
10+
-v, --verbose Show additional command output.
11+
--version Print the Dart SDK version.
12+
--enable-analytics Enable anonymous analytics.
13+
--disable-analytics Disable anonymous analytics.
1514
1615
Available commands:
1716
analyze Analyze the project's Dart code.
1817
compile Compile Dart to various formats.
1918
create Create a new project.
20-
format Idiomatically formats Dart source code.
19+
format Idiomatically format Dart source code.
2120
pub Work with packages.
2221
run Run a Dart program.
2322
test Run tests in this package.
2423
2524
Run "dart help <command>" for more information about a command.
25+
See https://dart.dev/tools/dart-tool for detailed documentation.
2626
```
2727

2828
## Contributing

pkg/dartdev/lib/dartdev.dart

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,12 @@ class DartdevRunner<int> extends CommandRunner {
206206
// A hidden flag to disable analytics on this run, this constructor can be
207207
// called with this flag, but should be removed before run() is called as
208208
// the flag has not been added to all sub-commands.
209-
argParser.addFlag('disable-dartdev-analytics',
210-
negatable: false,
211-
help: 'Disable anonymous analytics for this `dart *` run',
212-
hide: true);
209+
argParser.addFlag(
210+
'disable-dartdev-analytics',
211+
negatable: false,
212+
help: 'Disable anonymous analytics for this `dart *` run',
213+
hide: true,
214+
);
213215

214216
// Another hidden flag used by the VM to indicate that DDS should be
215217
// launched. Should be removed for all commands other than `run`.
@@ -220,7 +222,7 @@ class DartdevRunner<int> extends CommandRunner {
220222
addCommand(CreateCommand(verbose: verbose));
221223
addCommand(CompileCommand());
222224
addCommand(FixCommand());
223-
addCommand(FormatCommand());
225+
addCommand(FormatCommand(verbose: verbose));
224226
addCommand(MigrateCommand(
225227
verbose: verbose,
226228
hidden: Runtime.runtime.stableChannel,
@@ -254,6 +256,7 @@ class DartdevRunner<int> extends CommandRunner {
254256
allowedHelp: verbose ? allowedHelp : null,
255257
help: 'Enable one or more experimental features '
256258
'(see dart.dev/go/experiments).',
259+
hide: !verbose,
257260
);
258261
}
259262

0 commit comments

Comments
 (0)