0742604758
See: https://github.com/dart-lang/linter/issues/4754 Change-Id: Ib875e1640dd15f321362f2dba76b3d5d8524497c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/328183 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Phil Quitslund <pquitslund@google.com> Reviewed-by: Samuel Rawlins <srawlins@google.com>
191 lines
4.0 KiB
Dart
191 lines
4.0 KiB
Dart
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'dart:core';
|
|
import 'dart:core' as core_top_level_prefix_as;
|
|
|
|
void explicitDynamicType(dynamic object) {
|
|
object.foo(); // LINT
|
|
object.bar; // LINT
|
|
}
|
|
|
|
void implicitDynamicType(object) {
|
|
object.foo(); // LINT
|
|
object.bar; // LINT
|
|
}
|
|
|
|
// This would likely not pass at runtime, but we're using it for inference only.
|
|
T genericType<T>() => null as T;
|
|
|
|
void inferredDynamicType() {
|
|
var object = genericType();
|
|
object.foo(); // LINT
|
|
object.bar; // LINT
|
|
}
|
|
|
|
class Wrapper<T> {
|
|
final T field;
|
|
Wrapper(this.field);
|
|
}
|
|
|
|
void fieldDynamicType(Wrapper<dynamic> wrapper) {
|
|
wrapper.field.foo(); // LINT
|
|
wrapper.field.bar; // LINT
|
|
wrapper.field(); // LINT
|
|
(wrapper.field)(); // LINT
|
|
}
|
|
|
|
void cascadeExpressions(dynamic a, Wrapper<dynamic> b) {
|
|
a..b; // LINT
|
|
b..field; // OK
|
|
b
|
|
..toString
|
|
..field.a() // LINT
|
|
..field.b; // LINT
|
|
}
|
|
|
|
class TearOffFunction {
|
|
static int staticDoThing() => 0;
|
|
|
|
int doThing() => 0;
|
|
}
|
|
|
|
void otherPropertyAccessOrCalls(dynamic a) {
|
|
a(); // LINT
|
|
a?.b; // LINT
|
|
a!.b; // LINT
|
|
a?.b(); // LINT
|
|
a!.b(); // LINT
|
|
(a).b; // LINT
|
|
}
|
|
|
|
void tearOffFunctions(TearOffFunction a) {
|
|
var p = core_top_level_prefix_as.print; // OK
|
|
core_top_level_prefix_as.print('Hello'); // OK
|
|
p('Hello'); // OK
|
|
var doThing = a.doThing; // OK
|
|
doThing(); // OK
|
|
var staticDoThing = TearOffFunction.staticDoThing; // OK
|
|
staticDoThing(); // OK
|
|
identical(true, false); // OK
|
|
var alsoIdentical = identical;
|
|
alsoIdentical(true, false); // OK
|
|
}
|
|
|
|
typedef F = void Function();
|
|
|
|
void functionExpressionInvocations(
|
|
dynamic a(),
|
|
Function b(),
|
|
void Function() c,
|
|
d(),
|
|
F f,
|
|
F? fn,
|
|
) {
|
|
a(); // OK
|
|
a()(); // LINT
|
|
b(); // OK
|
|
b()(); // LINT
|
|
c(); // OK
|
|
d(); // OK
|
|
f.call; // OK
|
|
f.call(); // OK
|
|
fn?.call; // OK
|
|
fn?.call(); // OK
|
|
}
|
|
|
|
void typedFunctionButBasicallyDynamic(Function a, Wrapper<Function> b) {
|
|
a(); // LINT
|
|
b.field(); // LINT
|
|
(b.field)(); // LINT
|
|
a.call; // OK
|
|
a.call(); // LINT
|
|
}
|
|
|
|
void binaryExpressions(dynamic a, int b, bool c) {
|
|
a + a; // LINT
|
|
a + b; // LINT
|
|
a > b; // LINT
|
|
a < b; // LINT
|
|
a >= b; // LINT
|
|
a <= b; // LINT
|
|
a ^ b; // LINT
|
|
a | b; // LINT
|
|
a & b; // LINT
|
|
a % b; // LINT
|
|
a / b; // LINT
|
|
a ~/ b; // LINT
|
|
a >> b; // LINT
|
|
a << b; // LINT
|
|
a || c; // OK; this is an implicit downcast, not a dynamic call
|
|
a && c; // OK; this is an implicit downcast, not a dynamic call
|
|
b + a; // OK; this is an implicit downcast, not a dynamic call
|
|
a ?? b; // OK; this is a null comparison, not a dynamic call.
|
|
a is int; // OK
|
|
a is! int; // OK
|
|
a as int; // OK
|
|
}
|
|
|
|
void equalityExpressions(dynamic a, dynamic b) {
|
|
a == b; // OK, see lint description for details.
|
|
a == null; // OK.
|
|
a != b; // OK
|
|
a != null; // OK.
|
|
}
|
|
|
|
void membersThatExistOnObject(dynamic a, Invocation b) {
|
|
a.hashCode; // OK
|
|
a.runtimeType; // OK
|
|
a.noSuchMethod(); // LINT
|
|
a.noSuchMethod(b); // OK
|
|
a.noSuchMethod(b, 1); // LINT
|
|
a.noSuchMethod(b, name: 1); // LINT
|
|
a.toString(); // OK
|
|
a.toString(1); // LINT
|
|
a.toString(name: 1); // LINT
|
|
'$a'; // OK
|
|
'${a}'; // OK
|
|
}
|
|
|
|
void memberTearOffsOnObject(dynamic a, Invocation b) {
|
|
var tearOffNoSuchMethod = a.noSuchMethod; // OK
|
|
tearOffNoSuchMethod(b); // OK
|
|
var tearOffToString = a.toString; // OK
|
|
tearOffToString(); // OK
|
|
}
|
|
|
|
void assignmentExpressions(dynamic a) {
|
|
a += 1; // LINT
|
|
a -= 1; // LINT
|
|
a *= 1; // LINT
|
|
a ^= 1; // LINT
|
|
a /= 1; // LINT
|
|
a &= 1; // LINT
|
|
a |= 1; // LINT
|
|
a ??= 1; // OK
|
|
}
|
|
|
|
void prefixExpressions(dynamic a, int b) {
|
|
!a; // LINT
|
|
-a; // LINT
|
|
++a; // LINT
|
|
--a; // LINT
|
|
++b; // OK
|
|
--b; // OK
|
|
}
|
|
|
|
void postfixExpressions(dynamic a, int b) {
|
|
a!; // OK; this is not a dynamic call.
|
|
a++; // LINT
|
|
a--; // LINT
|
|
b++; // OK
|
|
b--; // OK
|
|
}
|
|
|
|
void indexExpressions(dynamic a) {
|
|
a[1]; // LINT
|
|
a[1] = 1; // LINT
|
|
a = a[1]; // LINT
|
|
}
|