blob: b20716a4a5ee7188865e21218365450499d60aba [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.
library analyzer.source.error_processor;
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:yaml/yaml.dart';
/// 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(Object codeMap) {
_processMap(codeMap);
}
void _process(String code, Object action) {
action = toLowerCase(action);
code = toUpperCase(code);
if (AnalyzerOptions.ignoreSynonyms.contains(action)) {
processors.add(new ErrorProcessor.ignore(code));
} else {
ErrorSeverity severity = _toSeverity(action);
if (severity != null) {
processors.add(new ErrorProcessor(code, severity));
}
}
}
void _processMap(Object codes) {
if (codes is YamlMap) {
// TODO(pq): stop traversing nodes and unify w/ standard map handling
codes.nodes.forEach((k, v) {
if (k is YamlScalar && v is YamlScalar) {
_process(k.value, v.value);
}
});
} else if (codes is Map) {
codes.forEach((k, v) {
if (k is String) {
_process(k, v);
}
});
}
}
ErrorSeverity _toSeverity(String severity) {
switch (severity) {
case 'error':
return ErrorSeverity.ERROR;
case 'info':
return ErrorSeverity.INFO;
case 'warning':
return ErrorSeverity.WARNING;
}
return null;
}
}
/// 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) => new ErrorProcessor(code);
/// Check if this processor applies to the given [error].
bool appliesTo(AnalysisError error) => code == error.errorCode.name;
/// Return an error processor associated with this [context] for the given
/// [error], or `null` if none is found.
static ErrorProcessor getProcessor(
AnalysisContext context, AnalysisError error) {
if (context == null) {
return null;
}
List<ErrorProcessor> processors =
context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS);
return processors.firstWhere((ErrorProcessor p) => p.appliesTo(error),
orElse: () => null);
}
}