blob: e6ddb8127f5cd22fffe6a8e8afceead9638570d7 [file] [log] [blame]
// Copyright (c) 2022, 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:_fe_analyzer_shared/src/type_inference/type_analysis_result.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart'
as shared;
import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
import 'package:analyzer/src/error/codes.dart';
typedef SharedPatternField
= shared.RecordPatternField<PatternFieldImpl, DartPatternImpl>;
/// Implementation of [shared.TypeAnalyzerErrors] that reports errors using the
/// analyzer's [ErrorReporter] class.
class SharedTypeAnalyzerErrors
implements
shared.TypeAnalyzerErrors<AstNode, Statement, Expression,
PromotableElement, SharedTypeView<DartType>, DartPattern, void> {
final ErrorReporter _errorReporter;
SharedTypeAnalyzerErrors(this._errorReporter);
@override
void assertInErrorRecovery() {}
@override
void caseExpressionTypeMismatch(
{required Expression scrutinee,
required Expression caseExpression,
required SharedTypeView<DartType> scrutineeType,
required SharedTypeView<DartType> caseExpressionType,
required bool nullSafetyEnabled}) {
_errorReporter.atNode(
caseExpression,
CompileTimeErrorCode
.CASE_EXPRESSION_TYPE_IS_NOT_SWITCH_EXPRESSION_SUBTYPE,
arguments: [caseExpressionType, scrutineeType],
);
}
@override
void duplicateAssignmentPatternVariable({
required covariant PromotableElement variable,
required covariant AssignedVariablePatternImpl original,
required covariant AssignedVariablePatternImpl duplicate,
}) {
_errorReporter.reportError(
DiagnosticFactory().duplicateAssignmentPatternVariable(
source: _errorReporter.source,
variable: variable,
original: original,
duplicate: duplicate,
),
);
}
@override
void duplicateRecordPatternField({
required DartPattern objectOrRecordPattern,
required String name,
required covariant SharedPatternField original,
required covariant SharedPatternField duplicate,
}) {
if (objectOrRecordPattern is RecordPatternImpl) {
objectOrRecordPattern.hasDuplicateNamedField = true;
}
_errorReporter.reportError(
DiagnosticFactory().duplicatePatternField(
source: _errorReporter.source,
name: name,
duplicateField: duplicate.node,
originalField: original.node,
),
);
}
@override
void duplicateRestPattern({
required DartPattern mapOrListPattern,
required covariant RestPatternElementImpl original,
required covariant RestPatternElementImpl duplicate,
}) {
_errorReporter.reportError(
DiagnosticFactory().duplicateRestElementInPattern(
source: _errorReporter.source,
originalElement: original,
duplicateElement: duplicate,
),
);
}
@override
void emptyMapPattern({
required DartPattern pattern,
}) {
_errorReporter.atNode(
pattern,
CompileTimeErrorCode.EMPTY_MAP_PATTERN,
);
}
@override
void inconsistentJoinedPatternVariable({
required PromotableElement variable,
required PromotableElement component,
}) {
_errorReporter.atElement(
component,
CompileTimeErrorCode.INCONSISTENT_PATTERN_VARIABLE_LOGICAL_OR,
arguments: [variable.name],
);
}
@override
void matchedTypeIsStrictlyNonNullable({
required DartPattern pattern,
required SharedTypeView<DartType> matchedType,
}) {
if (pattern is NullAssertPattern) {
_errorReporter.atToken(
pattern.operator,
StaticWarningCode.UNNECESSARY_NULL_ASSERT_PATTERN,
);
} else if (pattern is NullCheckPattern) {
_errorReporter.atToken(
pattern.operator,
StaticWarningCode.UNNECESSARY_NULL_CHECK_PATTERN,
);
} else {
throw UnimplementedError('(${pattern.runtimeType}) $pattern');
}
}
@override
void matchedTypeIsSubtypeOfRequired({
required covariant CastPatternImpl pattern,
required SharedTypeView<DartType> matchedType,
required SharedTypeView<DartType> requiredType,
}) {
_errorReporter.atToken(
pattern.asToken,
WarningCode.UNNECESSARY_CAST_PATTERN,
);
}
@override
void nonBooleanCondition({required Expression node}) {
_errorReporter.atNode(
node,
CompileTimeErrorCode.NON_BOOL_CONDITION,
);
}
@override
void patternForInExpressionIsNotIterable({
required AstNode node,
required Expression expression,
required SharedTypeView<DartType> expressionType,
}) {
_errorReporter.atNode(
expression,
CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE,
arguments: [expressionType, 'Iterable'],
);
}
@override
void patternTypeMismatchInIrrefutableContext({
required covariant DartPatternImpl pattern,
required AstNode context,
required SharedTypeView<DartType> matchedType,
required SharedTypeView<DartType> requiredType,
}) {
_errorReporter.atNode(
pattern,
CompileTimeErrorCode.PATTERN_TYPE_MISMATCH_IN_IRREFUTABLE_CONTEXT,
arguments: [matchedType, requiredType],
);
}
@override
void refutablePatternInIrrefutableContext(
{required AstNode pattern, required AstNode context}) {
_errorReporter.atNode(
pattern,
CompileTimeErrorCode.REFUTABLE_PATTERN_IN_IRREFUTABLE_CONTEXT,
);
}
@override
void relationalPatternOperandTypeNotAssignable({
required covariant RelationalPatternImpl pattern,
required SharedTypeView<DartType> operandType,
required SharedTypeView<DartType> parameterType,
}) {
_errorReporter.atNode(
pattern.operand,
CompileTimeErrorCode.RELATIONAL_PATTERN_OPERAND_TYPE_NOT_ASSIGNABLE,
arguments: [operandType, parameterType, pattern.operator.lexeme],
);
}
@override
void relationalPatternOperatorReturnTypeNotAssignableToBool({
required covariant RelationalPatternImpl pattern,
required SharedTypeView<DartType> returnType,
}) {
_errorReporter.atToken(
pattern.operator,
CompileTimeErrorCode
.RELATIONAL_PATTERN_OPERATOR_RETURN_TYPE_NOT_ASSIGNABLE_TO_BOOL,
);
}
@override
void restPatternInMap({
required covariant MapPatternImpl node,
required covariant RestPatternElementImpl element,
}) {
_errorReporter.atNode(
element,
CompileTimeErrorCode.REST_ELEMENT_IN_MAP_PATTERN,
);
}
@override
void switchCaseCompletesNormally(
{required covariant SwitchStatement node, required int caseIndex}) {
_errorReporter.atToken(
node.members[caseIndex].keyword,
CompileTimeErrorCode.SWITCH_CASE_COMPLETES_NORMALLY,
);
}
@override
void unnecessaryWildcardPattern({
required covariant WildcardPatternImpl pattern,
required UnnecessaryWildcardKind kind,
}) {
switch (kind) {
case UnnecessaryWildcardKind.logicalAndPatternOperand:
_errorReporter.atNode(
pattern,
WarningCode.UNNECESSARY_WILDCARD_PATTERN,
);
}
}
}