Resolve type hierarchies for all units of the library's import closure.

R=brianwilkerson@google.com
BUG=

Review URL: https://codereview.chromium.org//1052053002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@44846 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
scheglov@google.com 2015-04-01 22:18:32 +00:00
parent ee0e4e8c56
commit a707ae2282
4 changed files with 191 additions and 7 deletions

View file

@ -24,6 +24,7 @@ import 'package:analyzer/src/task/general.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/general.dart';
import 'package:analyzer/task/model.dart';
import 'package:analyzer/src/task/inputs.dart';
/**
* The errors produced while resolving a library directives.
@ -2011,8 +2012,11 @@ class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask {
static Map<String, TaskInput> buildInputs(Source libSource) {
return <String, TaskInput>{
LIBRARY_INPUT: LIBRARY_ELEMENT4.of(libSource),
'resolvedUnits': UNITS.of(libSource).toMap((Source source) =>
RESOLVED_UNIT4.of(new LibraryUnitTarget(libSource, source)))
'resolvedUnits': IMPORT_SOURCE_CLOSURE
.of(libSource)
.toMapOf(UNITS)
.toFlattenList((Source library, Source unit) =>
RESOLVED_UNIT4.of(new LibraryUnitTarget(library, unit)))
};
}

View file

@ -41,12 +41,12 @@ abstract class ListTaskInputMixin<E> implements ListTaskInput<E> {
return (this as ListTaskInputImpl<AnalysisTarget>).toList(valueResult.of);
}
TaskInput<Map<E, dynamic /*V*/ >> toMap(
MapTaskInput<E, dynamic /*V*/ > toMap(
UnaryFunction<E, dynamic /*<V>*/ > mapper) {
return new ListToMapTaskInput<E, dynamic /*V*/ >(this, mapper);
}
TaskInput<Map<AnalysisTarget, dynamic /*V*/ >> toMapOf(
MapTaskInput<AnalysisTarget, dynamic /*V*/ > toMapOf(
ResultDescriptor /*<V>*/ valueResult) {
return (this as ListTaskInputImpl<AnalysisTarget>).toMap(valueResult.of);
}
@ -113,7 +113,8 @@ class ListToListTaskInputBuilder<B, E>
* input to the task.
*/
class ListToMapTaskInput<B, E>
extends _ListToCollectionTaskInput<B, E, Map<B, E>> {
extends _ListToCollectionTaskInput<B, E, Map<B, E>>
with MapTaskInputMixin<B, E> {
/**
* Initialize a result accessor to use the given [baseAccessor] to access a
* list of values that can be passed to the given [generateTaskInputs] to
@ -156,6 +157,125 @@ class ListToMapTaskInputBuilder<B, E>
}
}
/**
* A mixin-ready implementation of [MapTaskInput].
*/
abstract class MapTaskInputMixin<K, V> implements MapTaskInput<K, V> {
TaskInput<List /*<E>*/ > toFlattenList(
BinaryFunction<K, dynamic /*element of V*/, dynamic /*<E>*/ > mapper) {
return new MapToFlattenListTaskInput<K, dynamic /*element of V*/, dynamic /*E*/ >(
this as MapTaskInput<K, List /*<element of V>*/ >, mapper);
}
}
/**
* A [TaskInput] that is computed by the following steps.
*
* First the [base] task input is used to compute a [Map]-valued result.
* The values of the [Map] must be [List]s.
*
* The given [mapper] is used to transform each key / value pair of the [Map]
* into task inputs.
*
* Finally, each of the task inputs are used to access analysis results,
* and the list of the results is used as the input.
*/
class MapToFlattenListTaskInput<K, V, E> implements TaskInput<List<E>> {
final MapTaskInput<K, List<V>> base;
final BinaryFunction<K, V, E> mapper;
MapToFlattenListTaskInput(this.base, this.mapper);
@override
TaskInputBuilder<List> createBuilder() {
return new MapToFlattenListTaskInputBuilder<K, V, E>(base, mapper);
}
}
/**
* The [TaskInputBuilder] for [MapToFlattenListTaskInput].
*/
class MapToFlattenListTaskInputBuilder<K, V, E>
implements TaskInputBuilder<List<E>> {
final MapTaskInput<K, List<V>> base;
final BinaryFunction<K, V, E> mapper;
TaskInputBuilder currentBuilder;
Map<K, List<V>> baseMap;
Iterator<K> keyIterator;
Iterator<V> valueIterator;
final List<E> inputValue = <E>[];
MapToFlattenListTaskInputBuilder(this.base, this.mapper) {
currentBuilder = base.createBuilder();
}
@override
ResultDescriptor get currentResult {
if (currentBuilder == null) {
return null;
}
return currentBuilder.currentResult;
}
AnalysisTarget get currentTarget {
if (currentBuilder == null) {
return null;
}
return currentBuilder.currentTarget;
}
@override
void set currentValue(Object value) {
if (currentBuilder == null) {
throw new StateError(
'Cannot set the result value when there is no current result');
}
currentBuilder.currentValue = value;
}
@override
bool moveNext() {
// Prepare base Map.
if (baseMap == null) {
if (currentBuilder.moveNext()) {
return true;
}
baseMap = currentBuilder.inputValue;
keyIterator = baseMap.keys.iterator;
// Done with this builder.
currentBuilder = null;
}
// Prepare the next result value.
if (currentBuilder != null) {
if (currentBuilder.moveNext()) {
return true;
}
// Add the result value for the current Map key/value.
E resultValue = currentBuilder.inputValue;
inputValue.add(resultValue);
// Done with this builder.
currentBuilder = null;
}
// Move to the next Map value.
if (valueIterator != null && valueIterator.moveNext()) {
K key = keyIterator.current;
V value = valueIterator.current;
currentBuilder = mapper(key, value).createBuilder();
return moveNext();
}
// Move to the next Map key.
if (keyIterator.moveNext()) {
K key = keyIterator.current;
valueIterator = baseMap[key].iterator;
return moveNext();
}
// No more Map values/keys to transform.
return false;
}
}
/**
* An input to an [AnalysisTask] that is computed by accessing a single result
* defined on a single target.

View file

@ -11,6 +11,11 @@ import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/task/model.dart';
/**
* A function that converts the given [key] and [value] into a [TaskInput].
*/
typedef TaskInput<E> BinaryFunction<K, V, E>(K key, V value);
/**
* A function that takes an analysis [context] and an analysis [target] and
* returns an analysis task. Such functions are passed to a [TaskDescriptor] to
@ -292,7 +297,7 @@ abstract class ListTaskInput<E> extends TaskInput<List<E>> {
* elements of this input and whose values are the result of passing the
* corresponding key to the [mapper] function.
*/
TaskInput<Map<E, dynamic /*V*/ >> toMap(
MapTaskInput<E, dynamic /*V*/ > toMap(
UnaryFunction<E, dynamic /*<V>*/ > mapper);
/**
@ -300,10 +305,26 @@ abstract class ListTaskInput<E> extends TaskInput<List<E>> {
* elements of this input and whose values are the [valueResult]'s associated
* with those elements.
*/
TaskInput<Map<AnalysisTarget, dynamic /*V*/ >> toMapOf(
MapTaskInput<AnalysisTarget, dynamic /*V*/ > toMapOf(
ResultDescriptor /*<V>*/ valueResult);
}
/**
* A description of an input with a [Map] based values.
*
* Clients are not expected to subtype this class.
*/
abstract class MapTaskInput<K, V> extends TaskInput<Map<K, V>> {
/**
* [V] must be a [List].
* Return a task input that can be used to compute a list whose elements are
* the result of passing keys [K] and the corresponding elements of [V] to
* the [mapper] function.
*/
TaskInput<List /*<E>*/ > toFlattenList(
BinaryFunction<K, dynamic /*element of V*/, dynamic /*<E>*/ > mapper);
}
/**
* A description of an analysis result that can be computed by an [AnalysisTask].
*

View file

@ -1326,6 +1326,45 @@ class C extends A {}
expect(classC.supertype.displayName, 'A');
}
}
test_perform_deep() {
Source sourceA = _newSource('/a.dart', '''
library a;
import 'b.dart';
class A extends B {}
''');
_newSource('/b.dart', '''
library b;
import 'c.dart';
part 'b2.dart';
class B extends B2 {}
''');
_newSource('/b2.dart', '''
part of b;
class B2 extends C {}
''');
_newSource('/c.dart', '''
library c;
class C {}
''');
_computeResult(sourceA, LIBRARY_ELEMENT5);
expect(task, new isInstanceOf<ResolveLibraryTypeNamesTask>());
// validate
LibraryElement library = outputs[LIBRARY_ELEMENT5];
{
ClassElement clazz = library.getType('A');
expect(clazz.displayName, 'A');
clazz = clazz.supertype.element;
expect(clazz.displayName, 'B');
clazz = clazz.supertype.element;
expect(clazz.displayName, 'B2');
clazz = clazz.supertype.element;
expect(clazz.displayName, 'C');
clazz = clazz.supertype.element;
expect(clazz.displayName, 'Object');
expect(clazz.supertype, isNull);
}
}
}
@reflectiveTest