Avoid a crash during summary linking when there are inheritance errors.

R=brianwilkerson@google.com, scheglov@google.com

Review URL: https://codereview.chromium.org/2531333006 .
This commit is contained in:
Paul Berry 2016-11-29 11:04:29 -08:00
parent 22f85df76e
commit 636e7b559b
3 changed files with 37 additions and 10 deletions

View file

@ -53,13 +53,23 @@ class InheritanceManager {
Map<ClassElement, Set<AnalysisError>> _errorsInClassElement =
new HashMap<ClassElement, Set<AnalysisError>>();
/**
* Indicates whether errors should be ignored.
*
* When this bool is `true`, we skip the logic that figures out which error
* to report; this avoids a crash when the inheritance manager is used in the
* context of summary linking (where there is not enough information available
* to determine error locations).
*/
final bool ignoreErrors;
/**
* Initialize a newly created inheritance manager.
*
* @param library the library element context that the inheritance mappings are being generated
*/
InheritanceManager(LibraryElement library,
{bool includeAbstractFromSuperclasses: false}) {
{bool includeAbstractFromSuperclasses: false, this.ignoreErrors: false}) {
this._library = library;
_includeAbstractFromSuperclasses = includeAbstractFromSuperclasses;
_classLookup = new HashMap<ClassElement, Map<String, ExecutableElement>>();
@ -654,15 +664,18 @@ class InheritanceManager {
* @param errorCode the error code to be associated with this error
* @param arguments the arguments used to build the error message
*/
void _reportError(ClassElement classElt, int offset, int length,
ErrorCode errorCode, List<Object> arguments) {
void _reportError(
ClassElement classElt, ErrorCode errorCode, List<Object> arguments) {
if (ignoreErrors) {
return;
}
HashSet<AnalysisError> errorSet = _errorsInClassElement[classElt];
if (errorSet == null) {
errorSet = new HashSet<AnalysisError>();
_errorsInClassElement[classElt] = errorSet;
}
errorSet.add(new AnalysisError(
classElt.source, offset, length, errorCode, arguments));
errorSet.add(new AnalysisError(classElt.source, classElt.nameOffset,
classElt.nameLength, errorCode, arguments));
}
/**
@ -793,8 +806,6 @@ class InheritanceManager {
"${executableElementTypes[0]}, ${executableElementTypes[1]}";
_reportError(
classElt,
classElt.nameOffset,
classElt.nameLength,
StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE,
[key, firstTwoFuntionTypesStr]);
}
@ -823,8 +834,6 @@ class InheritanceManager {
} else {
_reportError(
classElt,
classElt.nameOffset,
classElt.nameLength,
StaticWarningCode
.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD,
[key]);

View file

@ -3529,7 +3529,7 @@ class LibraryElementInBuildUnit
* Get the inheritance manager for this library (creating it if necessary).
*/
InheritanceManager get inheritanceManager =>
_inheritanceManager ??= new InheritanceManager(this);
_inheritanceManager ??= new InheritanceManager(this, ignoreErrors: true);
@override
LibraryCycleForLink get libraryCycleForLink {

View file

@ -3625,6 +3625,24 @@ var v = [f, g];
''');
}
test_inheritance_errors() {
checkLibrary('''
abstract class A {
int m();
}
abstract class B {
String m();
}
abstract class C implements A, B {}
abstract class D extends C {
var f;
}
''');
}
test_initializer_executable_with_return_type_from_closure() {
checkLibrary('var v = () => 0;');
}