5d17e0aa92
Use FileSource backed by analyzer_testing resources instead of the test-only Source implementations in analyzer tests. Update the lightweight TestAnalysisContext to receive a ResourceProviderMixin and install a URI resolver that produces real FileSource instances for the dart: and package: URIs used by mock SDK elements. Convert scanner, diagnostic, options, constant, type system, and workspace tests to create sources from in-memory files. Remove the remaining Source mock helpers, including TestSource, TestSourceWithUri, local Source mocks, and the unused TestTypeProvider. This keeps test sources closer to production Source behavior and avoids partial mock implementations that rely on noSuchMethod stubs. Change-Id: Iad600fb7f5ea00d2c015191df548e0d66a424940 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/499422 Reviewed-by: Paul Berry <paulberry@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
228 lines
6.7 KiB
Dart
228 lines
6.7 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/dart/analysis/analysis_options.dart';
|
|
import 'package:analyzer/diagnostic/diagnostic.dart';
|
|
import 'package:analyzer/error/error.dart';
|
|
import 'package:analyzer/source/error_processor.dart';
|
|
import 'package:analyzer/source/file_source.dart';
|
|
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
|
|
import 'package:analyzer/src/context/source.dart';
|
|
import 'package:analyzer/src/dart/analysis/analysis_options.dart';
|
|
import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag;
|
|
import 'package:analyzer_testing/resource_provider_mixin.dart';
|
|
import 'package:collection/collection.dart';
|
|
import 'package:test/test.dart';
|
|
import 'package:yaml/yaml.dart';
|
|
|
|
import '../src/util/yaml_test.dart';
|
|
|
|
main() {
|
|
var testSources = _TestSources();
|
|
|
|
Diagnostic invalid_assignment = Diagnostic.tmp(
|
|
source: testSources.source(),
|
|
offset: 0,
|
|
length: 1,
|
|
diagnosticCode: diag.invalidAssignment,
|
|
arguments: [
|
|
['x'],
|
|
['y'],
|
|
],
|
|
);
|
|
|
|
Diagnostic assignment_of_do_not_store = Diagnostic.tmp(
|
|
source: testSources.source(),
|
|
offset: 0,
|
|
length: 1,
|
|
diagnosticCode: diag.assignmentOfDoNotStore,
|
|
arguments: [
|
|
['x'],
|
|
],
|
|
);
|
|
|
|
Diagnostic unused_local_variable = Diagnostic.tmp(
|
|
source: testSources.source(),
|
|
offset: 0,
|
|
length: 1,
|
|
diagnosticCode: diag.unusedLocalVariable,
|
|
arguments: [
|
|
['x'],
|
|
],
|
|
);
|
|
|
|
Diagnostic use_of_void_result = Diagnostic.tmp(
|
|
source: testSources.source(),
|
|
offset: 0,
|
|
length: 1,
|
|
diagnosticCode: diag.useOfVoidResult,
|
|
);
|
|
|
|
// We in-line a lint code here in order to avoid adding a dependency on the
|
|
// linter package.
|
|
Diagnostic annotate_overrides = Diagnostic.tmp(
|
|
source: testSources.source(),
|
|
offset: 0,
|
|
length: 1,
|
|
diagnosticCode: LintCode(
|
|
'annotate_overrides',
|
|
'',
|
|
uniqueName: 'LintCode.annotate_overrides',
|
|
),
|
|
);
|
|
|
|
group('ErrorProcessor', () {
|
|
late _TestContext context;
|
|
|
|
setUp(() {
|
|
context = _TestContext();
|
|
});
|
|
|
|
test('configureOptions', () {
|
|
context.configureOptions('''
|
|
analyzer:
|
|
errors:
|
|
invalid_assignment: error # severity ERROR
|
|
assignment_of_do_not_store: false # ignore
|
|
unused_local_variable: true # skipped
|
|
use_of_void_result: unsupported_action # skipped
|
|
''');
|
|
expect(
|
|
context.getProcessor(invalid_assignment)!.severity,
|
|
DiagnosticSeverity.ERROR,
|
|
);
|
|
expect(
|
|
context.getProcessor(assignment_of_do_not_store)!.severity,
|
|
isNull,
|
|
);
|
|
expect(context.getProcessor(unused_local_variable), isNull);
|
|
expect(context.getProcessor(use_of_void_result), isNull);
|
|
});
|
|
|
|
test('does not upgrade other warnings to errors in strong mode', () {
|
|
context.configureOptions('''
|
|
analyzer:
|
|
strong-mode: true
|
|
''');
|
|
expect(context.getProcessor(unused_local_variable), isNull);
|
|
});
|
|
|
|
test('applies to analyzer warning even if lower case', () {
|
|
var errorProcessor = ErrorProcessor('cast_from_null_always_fails');
|
|
expect(
|
|
errorProcessor.appliesTo(
|
|
Diagnostic.tmp(
|
|
source: testSources.source(),
|
|
offset: 0,
|
|
length: 1,
|
|
diagnosticCode: diag.castFromNullAlwaysFails,
|
|
),
|
|
),
|
|
true,
|
|
);
|
|
});
|
|
});
|
|
|
|
group('ErrorConfig', () {
|
|
var config = '''
|
|
analyzer:
|
|
errors:
|
|
invalid_assignment: unsupported_action # should be skipped
|
|
assignment_of_do_not_store: false
|
|
unused_local_variable: error
|
|
''';
|
|
|
|
group('processing', () {
|
|
test('yaml map', () {
|
|
var options = AnalysisOptionsProvider(
|
|
SourceFactoryImpl([]),
|
|
).getOptionsFromString(config);
|
|
var errorConfig = ErrorConfig(
|
|
(options['analyzer'] as YamlMap)['errors'] as YamlNode?,
|
|
);
|
|
expect(errorConfig.processors, hasLength(2));
|
|
|
|
// ignore
|
|
var missingReturnProcessor = errorConfig.processors.firstWhere(
|
|
(p) => p.appliesTo(assignment_of_do_not_store),
|
|
);
|
|
expect(missingReturnProcessor.severity, isNull);
|
|
|
|
// error
|
|
var unusedLocalProcessor = errorConfig.processors.firstWhere(
|
|
(p) => p.appliesTo(unused_local_variable),
|
|
);
|
|
expect(unusedLocalProcessor.severity, DiagnosticSeverity.ERROR);
|
|
|
|
// skip
|
|
var invalidAssignmentProcessor = errorConfig.processors
|
|
.firstWhereOrNull((p) => p.appliesTo(invalid_assignment));
|
|
expect(invalidAssignmentProcessor, isNull);
|
|
});
|
|
|
|
test('string map', () {
|
|
var options = wrap({
|
|
'invalid_assignment': 'unsupported_action', // should be skipped
|
|
'assignment_of_do_not_store': 'false',
|
|
'unused_local_variable': 'error',
|
|
});
|
|
var errorConfig = ErrorConfig(options);
|
|
expect(errorConfig.processors, hasLength(2));
|
|
|
|
// ignore
|
|
var missingReturnProcessor = errorConfig.processors.firstWhere(
|
|
(p) => p.appliesTo(assignment_of_do_not_store),
|
|
);
|
|
expect(missingReturnProcessor.severity, isNull);
|
|
|
|
// error
|
|
var unusedLocalProcessor = errorConfig.processors.firstWhere(
|
|
(p) => p.appliesTo(unused_local_variable),
|
|
);
|
|
expect(unusedLocalProcessor.severity, DiagnosticSeverity.ERROR);
|
|
|
|
// skip
|
|
var invalidAssignmentProcessor = errorConfig.processors
|
|
.firstWhereOrNull((p) => p.appliesTo(invalid_assignment));
|
|
expect(invalidAssignmentProcessor, isNull);
|
|
});
|
|
});
|
|
|
|
test('configure lints', () {
|
|
var options = AnalysisOptionsProvider(SourceFactoryImpl([]))
|
|
.getOptionsFromString(
|
|
'analyzer:\n errors:\n annotate_overrides: warning\n',
|
|
);
|
|
var errorConfig = ErrorConfig(
|
|
(options['analyzer'] as YamlMap)['errors'] as YamlNode?,
|
|
);
|
|
expect(errorConfig.processors, hasLength(1));
|
|
|
|
ErrorProcessor processor = errorConfig.processors.first;
|
|
expect(processor.appliesTo(annotate_overrides), true);
|
|
expect(processor.severity, DiagnosticSeverity.WARNING);
|
|
});
|
|
});
|
|
}
|
|
|
|
class _TestContext {
|
|
late AnalysisOptions analysisOptions;
|
|
|
|
void configureOptions(String options) {
|
|
analysisOptions = AnalysisOptionsImpl.fromYaml(
|
|
optionsMap: AnalysisOptionsProvider(
|
|
SourceFactoryImpl([]),
|
|
).getOptionsFromString(options),
|
|
);
|
|
}
|
|
|
|
ErrorProcessor? getProcessor(Diagnostic diagnostic) {
|
|
return ErrorProcessor.getProcessor(analysisOptions, diagnostic);
|
|
}
|
|
}
|
|
|
|
class _TestSources with ResourceProviderMixin {
|
|
FileSource source() => FileSource(newFile('/test.dart', ''));
|
|
}
|