Files
sdk/pkg/analyzer/lib/source/error_processor.dart
T
Sam Rawlins 105efd85b6 [analyzer] Add a valueOrThrow extension similar to our oft-used typeOrThrow
This really helps in complying with strict-casts. YamlNode.value returns
a `dynamic`, which is then often passed somewhere which accepts Object
(and then does some type tests). To avoid the implicit cast from
`dynamic`, we can use `.valueOrThrow` (or basically just
`.value as Object`).

The extension getter improves readability and avoids a lot of
as-expressions inside conditional expressions etc.

Change-Id: I50d2eebd51d6fc3eccf1c930652dd5ce70dd9eb1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/277582
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
2023-01-03 18:53:39 +00:00

110 lines
3.6 KiB
Dart

// 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/error/error.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:analyzer/src/util/yaml.dart';
import 'package:yaml/yaml.dart';
/// String identifiers mapped to associated severities.
const Map<String, ErrorSeverity> severityMap = {
'error': ErrorSeverity.ERROR,
'info': ErrorSeverity.INFO,
'warning': ErrorSeverity.WARNING
};
/// Error processor configuration derived from analysis (or embedder) options.
class ErrorConfig {
/// The processors in this config.
final List<ErrorProcessor> processors = <ErrorProcessor>[];
/// Create an error config for the given error code map.
/// For example:
/// new ErrorConfig({'missing_return' : 'error'});
/// will create a processor config that turns `missing_return` hints into
/// errors.
ErrorConfig(YamlNode? codeMap) {
_processMap(codeMap);
}
void _process(String? code, Object action) {
code = toUpperCase(code);
var actionStr = toLowerCase(action);
if (AnalyzerOptions.ignoreSynonyms.contains(actionStr)) {
processors.add(ErrorProcessor.ignore(code!));
} else {
var severity = _toSeverity(actionStr);
if (severity != null) {
processors.add(ErrorProcessor(code!, severity));
}
}
}
void _processMap(YamlNode? codes) {
if (codes is YamlMap) {
codes.nodes.forEach((k, v) {
if (k is YamlScalar && v is YamlScalar) {
_process(k.value as String?, v.valueOrThrow);
}
});
}
}
ErrorSeverity? _toSeverity(String? severity) => severityMap[severity];
}
/// Process errors by filtering or changing associated [ErrorSeverity].
class ErrorProcessor {
/// The code name of the associated error.
final String code;
/// The desired severity of the processed error.
///
/// If `null`, this processor will "filter" the associated error code.
final ErrorSeverity? severity;
/// Create an error processor that assigns errors with this [code] the
/// given [severity].
///
/// If [severity] is `null`, matching errors will be filtered.
ErrorProcessor(this.code, [this.severity]);
/// Create an error processor that ignores the given error by [code].
factory ErrorProcessor.ignore(String code) => ErrorProcessor(code);
/// The string that unique describes the processor.
String get description => '$code -> ${severity?.name}';
/// Check if this processor applies to the given [error].
///
/// Note: [code] is normalized to uppercase; `errorCode.name` for regular
/// analysis issues uses uppercase; `errorCode.name` for lints uses lowercase.
bool appliesTo(AnalysisError error) =>
code == error.errorCode.name ||
code == error.errorCode.name.toUpperCase();
/// Return an error processor associated in the [analysisOptions] for the
/// given [error], or `null` if none is found.
static ErrorProcessor? getProcessor(
AnalysisOptions? analysisOptions, AnalysisError error) {
if (analysisOptions == null) {
return null;
}
// Let the user configure how specific errors are processed.
List<ErrorProcessor> processors = analysisOptions.errorProcessors;
// Add the strong mode processor.
processors = processors.toList();
for (var processor in processors) {
if (processor.appliesTo(error)) {
return processor;
}
}
return null;
}
}