Skip to content
This repository was archived by the owner on Nov 20, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions lib/src/ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,10 @@ bool inPrivateMember(AstNode node) {
}

/// Returns `true` if the given [declaration] is annotated `@deprecated`.
bool isDeprecated(Declaration declaration) =>
declaration.declaredElement!.hasDeprecated;
bool isDeprecated(Declaration declaration) {
var declaredElement = declaration.declaredElement;
return declaredElement != null && declaredElement.hasDeprecated;
}

/// Returns `true` if this element is the `==` method declaration.
bool isEquals(ClassMember element) =>
Expand All @@ -121,7 +123,8 @@ bool isHashCode(ClassMember element) =>
/// [package]'s `lib/` directory tree.
bool isInLibDir(CompilationUnit node, WorkspacePackage? package) {
if (package == null) return false;
final cuPath = node.declaredElement!.library.source.fullName;
final cuPath = node.declaredElement?.library.source.fullName;
if (cuPath == null) return false;
final libDir = path.join(package.root, 'lib');
return path.isWithin(libDir, cuPath);
}
Expand All @@ -146,8 +149,10 @@ bool isProtected(Declaration declaration) =>
declaration.metadata.any((Annotation a) => a.name.name == 'protected');

/// Returns `true` if the given [ClassMember] is a public method.
bool isPublicMethod(ClassMember m) =>
isMethod(m) && m.declaredElement!.isPublic;
bool isPublicMethod(ClassMember m) {
var declaredElement = m.declaredElement;
return declaredElement != null && isMethod(m) && declaredElement.isPublic;
}

/// Returns `true` if the given method [declaration] is a "simple getter".
///
Expand Down Expand Up @@ -287,8 +292,8 @@ bool _checkForSimpleSetter(MethodDeclaration setter, Expression expression) {
return false;
}

var parameters = setter.parameters!.parameters;
if (parameters.length == 1) {
var parameters = setter.parameters?.parameters;
if (parameters != null && parameters.length == 1) {
return rightElement == parameters[0].declaredElement;
}
}
Expand Down
13 changes: 7 additions & 6 deletions lib/src/formatter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Future writeBenchmarks(
final pedanticRuleset = await pedanticRules;
final stats = timings.keys.map((t) {
final details = pedanticRuleset.contains(t) ? ' [pedantic]' : '';
return _Stat('$t$details', timings[t]);
return _Stat('$t$details', timings[t] ?? 0);
}).toList();
_writeTimings(out, stats, 0);
}
Expand Down Expand Up @@ -95,7 +95,7 @@ void _writeTimings(IOSink out, List<_Stat> timings, int summaryLength) {

timings.sort();
for (var stat in timings) {
totalTime += stat.elapsed!;
totalTime += stat.elapsed;
// TODO: Shame timings slower than 100ms?
// TODO: Present both total times and time per count?
out.writeln(
Expand Down Expand Up @@ -266,8 +266,9 @@ class SimpleFormatter implements ReportFormatter {
}

void writeLints() {
var filter = this.filter;
errors.forEach((info) => (info.errors.toList()..sort(compare)).forEach((e) {
if (filter != null && filter!.filter(e)) {
if (filter != null && filter.filter(e)) {
filteredLintCount++;
} else {
++errorCount;
Expand Down Expand Up @@ -299,7 +300,7 @@ class SimpleFormatter implements ReportFormatter {
void writeTimings() {
final timers = lintRegistry.timers;
final timings = timers.keys
.map((t) => _Stat(t, timers[t]!.elapsedMilliseconds))
.map((t) => _Stat(t, timers[t]?.elapsedMilliseconds ?? 0))
.toList();
_writeTimings(out, timings, _summaryLength);
}
Expand All @@ -322,10 +323,10 @@ class SimpleFormatter implements ReportFormatter {

class _Stat implements Comparable<_Stat> {
final String name;
final int? elapsed;
final int elapsed;

_Stat(this.name, this.elapsed);

@override
int compareTo(_Stat other) => other.elapsed! - elapsed!;
int compareTo(_Stat other) => other.elapsed - elapsed;
}
4 changes: 2 additions & 2 deletions lib/src/rules/always_put_required_named_parameters_first.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ class _Visitor extends SimpleAstVisitor<void> {
void visitFormalParameterList(FormalParameterList node) {
var nonRequiredSeen = false;
for (var param in node.parameters.where((p) => p.isNamed)) {
var element = param.declaredElement!;
if (element.hasRequired || element.isRequiredNamed) {
var element = param.declaredElement;
if (element != null && (element.hasRequired || element.isRequiredNamed)) {
if (nonRequiredSeen) {
var identifier = param.identifier;
if (identifier != null) {
Expand Down
16 changes: 10 additions & 6 deletions lib/src/rules/always_require_non_null_named_parameters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,12 @@ class _Visitor extends SimpleAstVisitor<void> {
// Only named parameters
if (p.isNamed) {
final parameter = p as DefaultFormalParameter;
// Without a default value or marked @required
if (parameter.defaultValue == null &&
!parameter.declaredElement!.hasRequired) {
params.add(parameter);
// Without a default value or marked required
if (parameter.defaultValue == null) {
var declaredElement = parameter.declaredElement;
if (declaredElement != null && !declaredElement.hasRequired) {
params.add(parameter);
}
}
}
}
Expand All @@ -97,8 +99,10 @@ class _Visitor extends SimpleAstVisitor<void> {
void _checkAssert(
Expression assertExpression, List<DefaultFormalParameter> params) {
for (final param in params) {
if (_hasAssertNotNull(assertExpression, param.identifier!.name)) {
rule.reportLintForToken(param.identifier!.beginToken);
var identifier = param.identifier;
if (identifier != null &&
_hasAssertNotNull(assertExpression, identifier.name)) {
rule.reportLintForToken(identifier.beginToken);
params.remove(param);
return;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/src/rules/avoid_unnecessary_containers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ class _Visitor extends SimpleAstVisitor {
}
final parent = node.parent;
if (parent is NamedExpression && parent.name.label.name == 'child') {
final args = parent.thisOrAncestorOfType<ArgumentList>()!;
if (args.arguments.length == 1) {
final args = parent.thisOrAncestorOfType<ArgumentList>();
if (args?.arguments.length == 1) {
final parentCreation =
parent.thisOrAncestorOfType<InstanceCreationExpression>();
if (parentCreation != null) {
Expand Down
5 changes: 3 additions & 2 deletions lib/src/rules/cast_nullable_to_non_nullable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ class _Visitor extends SimpleAstVisitor<void> {

@override
void visitAsExpression(AsExpression node) {
final expressionType = node.expression.staticType!;
final expressionType = node.expression.staticType;
final type = node.type.type;
if (!expressionType.isDynamic &&
if (expressionType != null &&
!expressionType.isDynamic &&
context.typeSystem.isNullable(expressionType) &&
context.typeSystem.isNonNullable(type!)) {
rule.reportLint(node);
Expand Down
5 changes: 3 additions & 2 deletions lib/src/rules/deprecated_consistency.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ class _Visitor extends SimpleAstVisitor<void> {

@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
var constructorElement = node.declaredElement!;
if (constructorElement.enclosingElement.hasDeprecated &&
var constructorElement = node.declaredElement;
if (constructorElement != null &&
constructorElement.enclosingElement.hasDeprecated &&
!constructorElement.hasDeprecated) {
rule.reportLint(node);
}
Expand Down
15 changes: 9 additions & 6 deletions lib/src/rules/invariant_booleans.dart
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,12 @@ class _InvariantBooleansVisitor extends ConditionScopeVisitor {
@override
void visitCondition(Expression? node) {
// Right part discards reporting a subexpression already reported.
if (node?.staticType?.isDartCoreBool != true) {
if (node == null || node.staticType?.isDartCoreBool != true) {
return;
}

final testedNodes = _findPreviousTestedExpressions(node!);
testedNodes.evaluateInvariant()!.forEach((ContradictoryComparisons e) {
final testedNodes = _findPreviousTestedExpressions(node);
testedNodes?.evaluateInvariant()?.forEach((ContradictoryComparisons e) {
final reportRule = _ContradictionReportRule(e);
reportRule
..reporter = rule.reporter
Expand All @@ -166,10 +166,13 @@ class _InvariantBooleansVisitor extends ConditionScopeVisitor {
}
}

TestedExpressions _findPreviousTestedExpressions(Expression node) {
TestedExpressions? _findPreviousTestedExpressions(Expression node) {
final elements = _getElementsInExpression(node);
final conjunctions = getTrueExpressions(elements).toSet();
final negations = getFalseExpressions(elements).toSet();
final conjunctions = getTrueExpressions(elements)?.toSet();
final negations = getFalseExpressions(elements)?.toSet();
if (conjunctions == null || negations == null) {
return null;
}
return TestedExpressions(node, conjunctions, negations);
}
}
19 changes: 11 additions & 8 deletions lib/src/rules/lines_longer_than_80_chars.dart
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ class _AllowedLongLineVisitor extends RecursiveAstVisitor {
}

class _LineInfo {
final int? index;
final int? offset;
final int? end;
_LineInfo({this.index, this.offset, this.end});
int get length => end! - offset!;
final int index;
final int offset;
final int end;
_LineInfo({required this.index, required this.offset, required this.end});
int get length => end - offset;
}

class _Visitor extends SimpleAstVisitor {
Expand All @@ -175,7 +175,10 @@ class _Visitor extends SimpleAstVisitor {

@override
void visitCompilationUnit(CompilationUnit node) {
final lineInfo = node.lineInfo!;
final lineInfo = node.lineInfo;
if (lineInfo == null) {
return;
}
final lineCount = lineInfo.lineCount;
final longLines = <_LineInfo>[];
for (var i = 0; i < lineCount; i++) {
Expand Down Expand Up @@ -213,9 +216,9 @@ class _Visitor extends SimpleAstVisitor {
];

for (final line in longLines) {
if (allowedLines.contains(line.index! + 1)) continue;
if (allowedLines.contains(line.index + 1)) continue;
rule.reporter
.reportErrorForOffset(rule.lintCode, line.offset!, line.length);
.reportErrorForOffset(rule.lintCode, line.offset, line.length);
}
}
}
21 changes: 13 additions & 8 deletions lib/src/rules/prefer_asserts_in_initializer_lists.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class PreferAssertsInInitializerLists extends LintRule implements NodeLintRule {
}

class _AssertVisitor extends RecursiveAstVisitor {
final ConstructorElement? constructorElement;
final ConstructorElement constructorElement;
final _ClassAndSuperClasses? classAndSuperClasses;

bool needInstance = false;
Expand All @@ -71,7 +71,7 @@ class _AssertVisitor extends RecursiveAstVisitor {
element is PropertyAccessorElement &&
!element.isStatic &&
_hasAccessor(element) &&
!constructorElement!.parameters
!constructorElement.parameters
.whereType<FieldFormalParameterElement>()
.any((p) => p.field?.getter == element);
}
Expand All @@ -81,11 +81,15 @@ class _AssertVisitor extends RecursiveAstVisitor {
needInstance = true;
}

bool _hasAccessor(PropertyAccessorElement element) =>
classAndSuperClasses!.classes.contains(element.enclosingElement);
bool _hasAccessor(PropertyAccessorElement element) {
var classes = classAndSuperClasses?.classes;
return classes != null && classes.contains(element.enclosingElement);
}

bool _hasMethod(MethodElement element) =>
classAndSuperClasses!.classes.contains(element.enclosingElement);
bool _hasMethod(MethodElement element) {
var classes = classAndSuperClasses?.classes;
return classes != null && classes.contains(element.enclosingElement);
}
}

/// Lazy cache of elements.
Expand Down Expand Up @@ -126,15 +130,16 @@ class _Visitor extends SimpleAstVisitor<void> {

@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
if (node.declaredElement!.isFactory) return;
var declaredElement = node.declaredElement;
if (declaredElement == null || declaredElement.isFactory) return;

final body = node.body;
if (body is BlockFunctionBody) {
for (final statement in body.block.statements) {
if (statement is! AssertStatement) break;

final assertVisitor =
_AssertVisitor(node.declaredElement, _classAndSuperClasses);
_AssertVisitor(declaredElement, _classAndSuperClasses);
statement.visitChildren(assertVisitor);
if (!assertVisitor.needInstance) {
rule.reportLintForToken(statement.beginToken);
Expand Down
5 changes: 3 additions & 2 deletions lib/src/rules/prefer_bool_in_asserts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ class _Visitor extends SimpleAstVisitor<void> {

@override
void visitAssertStatement(AssertStatement node) {
var conditionType = _unbound(node.condition.staticType)!;
if (!typeSystem.isAssignableTo(conditionType, boolType)) {
var conditionType = _unbound(node.condition.staticType);
if (conditionType != null &&
!typeSystem.isAssignableTo(conditionType, boolType)) {
rule.reportLint(node.condition);
}
}
Expand Down
25 changes: 17 additions & 8 deletions lib/src/rules/prefer_const_constructors_in_immutables.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,17 @@ class _Visitor extends SimpleAstVisitor<void> {

@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
final element = node.declaredElement!;
final element = node.declaredElement;
if (element == null) {
return;
}
final isRedirected =
element.isFactory && element.redirectedConstructor != null;
if (node.body is EmptyFunctionBody &&
!element.isConst &&
!_hasMixin(element.enclosingElement) &&
_hasImmutableAnnotation(element.enclosingElement) &&
(isRedirected && element.redirectedConstructor!.isConst ||
(isRedirected && element.redirectedConstructor?.isConst == true ||
(!isRedirected &&
_hasConstConstructorInvocation(node) &&
context.canBeConstConstructor(node)))) {
Expand All @@ -91,23 +94,29 @@ class _Visitor extends SimpleAstVisitor<void> {
}

bool _hasConstConstructorInvocation(ConstructorDeclaration node) {
final clazz = node.declaredElement!.enclosingElement;
var declaredElement = node.declaredElement;
if (declaredElement == null) {
return false;
}
final clazz = declaredElement.enclosingElement;
// construct with super
final superInvocation = node.initializers
.firstWhereOrNull((e) => e is SuperConstructorInvocation)
as SuperConstructorInvocation?;
if (superInvocation != null) return superInvocation.staticElement!.isConst;
if (superInvocation != null) {
return superInvocation.staticElement?.isConst == true;
}
// construct with this
final redirectInvocation = node.initializers
.firstWhereOrNull((e) => e is RedirectingConstructorInvocation)
as RedirectingConstructorInvocation?;
if (redirectInvocation != null) {
return redirectInvocation.staticElement!.isConst;
return redirectInvocation.staticElement?.isConst == true;
}
// construct with implicit super()
return clazz.supertype!.constructors
.firstWhere((e) => e.name.isEmpty)
.isConst;
var supertype = clazz.supertype;
return supertype != null &&
supertype.constructors.firstWhere((e) => e.name.isEmpty).isConst;
}

bool _hasImmutableAnnotation(ClassElement clazz) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class _Visitor extends SimpleAstVisitor<void> {
node is SetOrMapLiteral ||
node is MapLiteralEntry ||
node is NamedExpression)) {
node = node!.parent;
node = node?.parent;
}
if (!(node is InstanceCreationExpression &&
_hasImmutableAnnotation(node.staticType))) {
Expand Down
Loading