47e988b781
Change-Id: Iee3110f92ab0f24312ddd1eff407d2229f895321 Reviewed-on: https://dart-review.googlesource.com/c/89101 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
216 lines
6.4 KiB
Dart
216 lines
6.4 KiB
Dart
// Copyright (c) 2014, 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 'dart:mirrors';
|
|
|
|
import 'package:analysis_server/src/protocol_server.dart';
|
|
import 'package:analysis_server/src/services/search/search_engine.dart';
|
|
import 'package:analyzer/dart/ast/ast.dart' as engine;
|
|
import 'package:analyzer/dart/element/element.dart' as engine;
|
|
import 'package:analyzer/dart/element/type.dart' as engine;
|
|
import 'package:analyzer/error/error.dart' as engine;
|
|
import 'package:analyzer/src/error/codes.dart' as engine;
|
|
import 'package:analyzer/src/generated/source.dart' as engine;
|
|
import 'package:analyzer_plugin/protocol/protocol_common.dart';
|
|
import 'package:test/test.dart';
|
|
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
|
|
|
import 'constants.dart';
|
|
import 'mocks.dart';
|
|
|
|
main() {
|
|
defineReflectiveSuite(() {
|
|
defineReflectiveTests(AnalysisErrorTest);
|
|
defineReflectiveTests(EnumTest);
|
|
});
|
|
}
|
|
|
|
@reflectiveTest
|
|
class AnalysisErrorTest {
|
|
MockSource source = new MockSource();
|
|
engine.LineInfo lineInfo;
|
|
MockAnalysisError engineError;
|
|
|
|
void setUp() {
|
|
// prepare Source
|
|
source.fullName = 'foo.dart';
|
|
// prepare LineInfo
|
|
lineInfo = new engine.LineInfo([0, 5, 9, 20]);
|
|
// prepare AnalysisError
|
|
engineError = new MockAnalysisError(source,
|
|
engine.CompileTimeErrorCode.AMBIGUOUS_EXPORT, 10, 20, 'my message');
|
|
}
|
|
|
|
void tearDown() {
|
|
source = null;
|
|
engineError = null;
|
|
}
|
|
|
|
void test_fromEngine_hasCorrection() {
|
|
engineError.correction = 'my correction';
|
|
AnalysisError error = newAnalysisError_fromEngine(lineInfo, engineError);
|
|
expect(error.toJson(), {
|
|
SEVERITY: 'ERROR',
|
|
TYPE: 'COMPILE_TIME_ERROR',
|
|
LOCATION: {
|
|
FILE: 'foo.dart',
|
|
OFFSET: 10,
|
|
LENGTH: 20,
|
|
START_LINE: 3,
|
|
START_COLUMN: 2
|
|
},
|
|
MESSAGE: 'my message',
|
|
CORRECTION: 'my correction',
|
|
CODE: 'ambiguous_export',
|
|
HAS_FIX: false
|
|
});
|
|
}
|
|
|
|
void test_fromEngine_noCorrection() {
|
|
engineError.correction = null;
|
|
AnalysisError error = newAnalysisError_fromEngine(lineInfo, engineError);
|
|
expect(error.toJson(), {
|
|
SEVERITY: 'ERROR',
|
|
TYPE: 'COMPILE_TIME_ERROR',
|
|
LOCATION: {
|
|
FILE: 'foo.dart',
|
|
OFFSET: 10,
|
|
LENGTH: 20,
|
|
START_LINE: 3,
|
|
START_COLUMN: 2
|
|
},
|
|
MESSAGE: 'my message',
|
|
CODE: 'ambiguous_export',
|
|
HAS_FIX: false
|
|
});
|
|
}
|
|
|
|
void test_fromEngine_noLineInfo() {
|
|
engineError.correction = null;
|
|
AnalysisError error = newAnalysisError_fromEngine(null, engineError);
|
|
expect(error.toJson(), {
|
|
SEVERITY: 'ERROR',
|
|
TYPE: 'COMPILE_TIME_ERROR',
|
|
LOCATION: {
|
|
FILE: 'foo.dart',
|
|
OFFSET: 10,
|
|
LENGTH: 20,
|
|
START_LINE: -1,
|
|
START_COLUMN: -1
|
|
},
|
|
MESSAGE: 'my message',
|
|
CODE: 'ambiguous_export',
|
|
HAS_FIX: false
|
|
});
|
|
}
|
|
}
|
|
|
|
@reflectiveTest
|
|
class EnumTest {
|
|
void test_AnalysisErrorSeverity() {
|
|
new EnumTester<engine.ErrorSeverity, AnalysisErrorSeverity>().run(
|
|
(engine.ErrorSeverity engineErrorSeverity) =>
|
|
new AnalysisErrorSeverity(engineErrorSeverity.name),
|
|
exceptions: {engine.ErrorSeverity.NONE: null});
|
|
}
|
|
|
|
void test_AnalysisErrorType() {
|
|
new EnumTester<engine.ErrorType, AnalysisErrorType>().run(
|
|
(engine.ErrorType engineErrorType) =>
|
|
new AnalysisErrorType(engineErrorType.name));
|
|
}
|
|
|
|
void test_ElementKind() {
|
|
new EnumTester<engine.ElementKind, ElementKind>()
|
|
.run(convertElementKind, exceptions: {
|
|
// TODO(paulberry): do any of the exceptions below constitute bugs?
|
|
engine.ElementKind.DYNAMIC: ElementKind.UNKNOWN,
|
|
engine.ElementKind.ERROR: ElementKind.UNKNOWN,
|
|
engine.ElementKind.EXPORT: ElementKind.UNKNOWN,
|
|
engine.ElementKind.GENERIC_FUNCTION_TYPE: ElementKind.FUNCTION_TYPE_ALIAS,
|
|
engine.ElementKind.IMPORT: ElementKind.UNKNOWN,
|
|
engine.ElementKind.NAME: ElementKind.UNKNOWN,
|
|
engine.ElementKind.UNIVERSE: ElementKind.UNKNOWN
|
|
});
|
|
}
|
|
|
|
void test_SearchResultKind() {
|
|
// TODO(paulberry): why does the MatchKind class exist at all? Can't we
|
|
// use SearchResultKind inside the analysis server?
|
|
new EnumTester<MatchKind, SearchResultKind>()
|
|
.run(newSearchResultKind_fromEngine);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper class for testing the correspondence between an analysis engine enum
|
|
* and an analysis server API enum.
|
|
*/
|
|
class EnumTester<EngineEnum, ApiEnum> {
|
|
/**
|
|
* Test that the function [convert] properly converts all possible values of
|
|
* [EngineEnum] to an [ApiEnum] with the same name, with the exceptions noted
|
|
* in [exceptions]. For each key in [exceptions], if the corresponding value
|
|
* is null, then we check that converting the given key results in an error.
|
|
* If the corresponding value is an [ApiEnum], then we check that converting
|
|
* the given key results in the given value.
|
|
*/
|
|
void run(ApiEnum convert(EngineEnum value),
|
|
{Map<EngineEnum, ApiEnum> exceptions: const {}}) {
|
|
ClassMirror engineClass = reflectClass(EngineEnum);
|
|
engineClass.staticMembers.forEach((Symbol symbol, MethodMirror method) {
|
|
if (symbol == #values) {
|
|
return;
|
|
}
|
|
if (!method.isGetter) {
|
|
return;
|
|
}
|
|
String enumName = MirrorSystem.getName(symbol);
|
|
EngineEnum engineValue =
|
|
engineClass.getField(symbol).reflectee as EngineEnum;
|
|
expect(engineValue, new TypeMatcher<EngineEnum>());
|
|
if (exceptions.containsKey(engineValue)) {
|
|
ApiEnum expectedResult = exceptions[engineValue];
|
|
if (expectedResult == null) {
|
|
expect(() {
|
|
convert(engineValue);
|
|
}, throwsException);
|
|
} else {
|
|
ApiEnum apiValue = convert(engineValue);
|
|
expect(apiValue, equals(expectedResult));
|
|
}
|
|
} else {
|
|
ApiEnum apiValue = convert(engineValue);
|
|
expect((apiValue as dynamic).name, equals(enumName));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
class MockAnalysisError implements engine.AnalysisError {
|
|
@override
|
|
MockSource source;
|
|
|
|
@override
|
|
engine.ErrorCode errorCode;
|
|
|
|
@override
|
|
int offset;
|
|
|
|
@override
|
|
String message;
|
|
|
|
@override
|
|
String correction = null;
|
|
|
|
@override
|
|
bool isStaticOnly;
|
|
|
|
@override
|
|
int length;
|
|
|
|
MockAnalysisError(
|
|
this.source, this.errorCode, this.offset, this.length, this.message);
|
|
}
|