blob: f751c352585ec415a6999e5416bd73da4872038a [file] [log] [blame]
// Copyright (c) 2015, 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 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:linter/src/analyzer.dart';
const _desc = r'Avoid using `as`.';
const _details = r'''
From the [flutter style guide](https://github.com/flutter/engine/blob/master/sky/specs/style-guide.md):
**AVOID** using `as`.
If you know the type is correct, use an assertion or assign to a more
narrowly-typed variable (this avoids the type check in release mode; `as` is not
compiled out in release mode). If you don't know whether the type is
correct, check using `is` (this avoids the exception that `as` raises).
**BAD:**
```
(pm as Person).firstName = 'Seth';
```
**GOOD:**
```
Person person = pm;
person.firstName = 'Seth';
```
or
**GOOD:**
```
if (pm is Person)
pm.firstName = 'Seth';
```
but certainly not
**BAD:**
```
try {
(pm as Person).firstName = 'Seth';
} on CastError { }
```
Note that an exception is made in the case of `dynamic` since the cast has no
performance impact.
**OK:**
```
HasScrollDirection scrollable = renderObject as dynamic;
```
''';
class AvoidAs extends LintRule implements NodeLintRule {
AvoidAs()
: super(
name: 'avoid_as',
description: _desc,
details: _details,
group: Group.style);
@override
void registerNodeProcessors(NodeLintRegistry registry,
[LinterContext context]) {
final visitor = new _Visitor(this);
registry.addAsExpression(this, visitor);
}
}
class _Visitor extends SimpleAstVisitor<void> {
final LintRule rule;
_Visitor(this.rule);
@override
void visitAsExpression(AsExpression node) {
// TODO(brianwilkerson) Use TypeAnnotation rather than AstNode below.
AstNode typeAnnotation = node.type;
if (typeAnnotation is NamedType && typeAnnotation.name.name != 'dynamic') {
rule.reportLint(node);
}
}
}