mirror of
https://github.com/dart-lang/sdk
synced 2024-09-23 01:23:47 +00:00
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:
parent
ee0e4e8c56
commit
a707ae2282
|
@ -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)))
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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].
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue