blob: ad422cafca68cc8fa486eaf6e260ba904f514629 [file] [log] [blame]
// 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.
library analyzer.src.summary.summary_sdk;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/context/cache.dart' show CacheEntry;
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart'
show DartUriResolver, Source, SourceFactory, SourceKind;
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/resynthesize.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/model.dart'
show AnalysisTarget, ResultDescriptor, TargetedResult;
class SdkSummaryResultProvider implements SummaryResultProvider {
final InternalAnalysisContext context;
final PackageBundle bundle;
final SummaryTypeProvider typeProvider = new SummaryTypeProvider();
@override
SummaryResynthesizer resynthesizer;
SdkSummaryResultProvider(this.context, this.bundle) {
resynthesizer = new SdkSummaryResynthesizer(
context, typeProvider, context.sourceFactory, bundle);
_buildCoreLibrary();
_buildAsyncLibrary();
resynthesizer.finalizeCoreAsyncLibraries();
context.typeProvider = typeProvider;
}
@override
bool compute(CacheEntry entry, ResultDescriptor result) {
if (result == TYPE_PROVIDER) {
entry.setValue(result, typeProvider, TargetedResult.EMPTY_LIST);
return true;
}
AnalysisTarget target = entry.target;
// Only SDK sources after this point.
if (target.source == null || !target.source.isInSystemLibrary) {
return false;
}
// Constant expressions are always resolved in summaries.
if (result == CONSTANT_EXPRESSION_RESOLVED &&
target is ConstantEvaluationTarget) {
entry.setValue(result, true, TargetedResult.EMPTY_LIST);
return true;
}
if (target is Source) {
if (result == LIBRARY_ELEMENT1 ||
result == LIBRARY_ELEMENT2 ||
result == LIBRARY_ELEMENT3 ||
result == LIBRARY_ELEMENT4 ||
result == LIBRARY_ELEMENT5 ||
result == LIBRARY_ELEMENT6 ||
result == LIBRARY_ELEMENT7 ||
result == LIBRARY_ELEMENT8 ||
result == LIBRARY_ELEMENT) {
// TODO(scheglov) try to find a way to avoid listing every result
// e.g. "result.whenComplete == LIBRARY_ELEMENT"
String uri = target.uri.toString();
LibraryElement libraryElement = resynthesizer.getLibraryElement(uri);
entry.setValue(result, libraryElement, TargetedResult.EMPTY_LIST);
return true;
} else if (result == READY_LIBRARY_ELEMENT2 ||
result == READY_LIBRARY_ELEMENT5 ||
result == READY_LIBRARY_ELEMENT6) {
entry.setValue(result, true, TargetedResult.EMPTY_LIST);
return true;
} else if (result == SOURCE_KIND) {
String uri = target.uri.toString();
SourceKind kind = _getSourceKind(uri);
if (kind != null) {
entry.setValue(result, kind, TargetedResult.EMPTY_LIST);
return true;
}
return false;
} else {
// throw new UnimplementedError('$result of $target');
}
}
if (target is LibrarySpecificUnit) {
if (target.library == null || !target.library.isInSystemLibrary) {
return false;
}
if (result == COMPILATION_UNIT_ELEMENT) {
String libraryUri = target.library.uri.toString();
String unitUri = target.unit.uri.toString();
CompilationUnitElement unit = resynthesizer.getElement(
new ElementLocationImpl.con3(<String>[libraryUri, unitUri]));
if (unit != null) {
entry.setValue(result, unit, TargetedResult.EMPTY_LIST);
return true;
}
}
}
return false;
}
void _buildAsyncLibrary() {
LibraryElement library = resynthesizer.getLibraryElement('dart:async');
typeProvider.initializeAsync(library);
}
void _buildCoreLibrary() {
LibraryElement library = resynthesizer.getLibraryElement('dart:core');
typeProvider.initializeCore(library);
}
/**
* Return the [SourceKind] of the given [uri] or `null` if it is unknown.
*/
SourceKind _getSourceKind(String uri) {
if (bundle.linkedLibraryUris.contains(uri)) {
return SourceKind.LIBRARY;
}
if (bundle.unlinkedUnitUris.contains(uri)) {
return SourceKind.PART;
}
return null;
}
}
/**
* The implementation of [SummaryResynthesizer] for Dart SDK.
*/
class SdkSummaryResynthesizer extends SummaryResynthesizer {
final PackageBundle bundle;
final Map<String, UnlinkedUnit> unlinkedSummaries = <String, UnlinkedUnit>{};
final Map<String, LinkedLibrary> linkedSummaries = <String, LinkedLibrary>{};
SdkSummaryResynthesizer(AnalysisContext context, TypeProvider typeProvider,
SourceFactory sourceFactory, this.bundle)
: super(null, context, typeProvider, sourceFactory, false) {
// TODO(paulberry): we always resynthesize the summary in weak mode. Is
// this ok?
for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
unlinkedSummaries[bundle.unlinkedUnitUris[i]] = bundle.unlinkedUnits[i];
}
for (int i = 0; i < bundle.linkedLibraryUris.length; i++) {
linkedSummaries[bundle.linkedLibraryUris[i]] = bundle.linkedLibraries[i];
}
}
@override
LinkedLibrary getLinkedSummary(String uri) {
return linkedSummaries[uri];
}
@override
UnlinkedUnit getUnlinkedSummary(String uri) {
return unlinkedSummaries[uri];
}
@override
bool hasLibrarySummary(String uri) {
return uri.startsWith('dart:');
}
}
/**
* Provider for analysis results.
*/
abstract class SummaryResultProvider extends ResultProvider {
/**
* The [SummaryResynthesizer] of this context, maybe `null`.
*/
SummaryResynthesizer get resynthesizer;
}
/**
* Implementation of [TypeProvider] which can be initialized separately with
* `dart:core` and `dart:async` libraries.
*/
class SummaryTypeProvider implements TypeProvider {
bool _isCoreInitialized = false;
bool _isAsyncInitialized = false;
InterfaceType _boolType;
InterfaceType _deprecatedType;
InterfaceType _doubleType;
InterfaceType _functionType;
InterfaceType _futureDynamicType;
InterfaceType _futureNullType;
InterfaceType _futureType;
InterfaceType _intType;
InterfaceType _iterableDynamicType;
InterfaceType _iterableType;
InterfaceType _listType;
InterfaceType _mapType;
DartObjectImpl _nullObject;
InterfaceType _nullType;
InterfaceType _numType;
InterfaceType _objectType;
InterfaceType _stackTraceType;
InterfaceType _streamDynamicType;
InterfaceType _streamType;
InterfaceType _stringType;
InterfaceType _symbolType;
InterfaceType _typeType;
@override
InterfaceType get boolType {
assert(_isCoreInitialized);
return _boolType;
}
@override
DartType get bottomType => BottomTypeImpl.instance;
@override
InterfaceType get deprecatedType {
assert(_isCoreInitialized);
return _deprecatedType;
}
@override
InterfaceType get doubleType {
assert(_isCoreInitialized);
return _doubleType;
}
@override
DartType get dynamicType => DynamicTypeImpl.instance;
@override
InterfaceType get functionType {
assert(_isCoreInitialized);
return _functionType;
}
@override
InterfaceType get futureDynamicType {
assert(_isAsyncInitialized);
return _futureDynamicType;
}
@override
InterfaceType get futureNullType {
assert(_isAsyncInitialized);
return _futureNullType;
}
@override
InterfaceType get futureType {
assert(_isAsyncInitialized);
return _futureType;
}
@override
InterfaceType get intType {
assert(_isCoreInitialized);
return _intType;
}
@override
InterfaceType get iterableDynamicType {
assert(_isCoreInitialized);
return _iterableDynamicType;
}
@override
InterfaceType get iterableType {
assert(_isCoreInitialized);
return _iterableType;
}
@override
InterfaceType get listType {
assert(_isCoreInitialized);
return _listType;
}
@override
InterfaceType get mapType {
assert(_isCoreInitialized);
return _mapType;
}
@override
List<InterfaceType> get nonSubtypableTypes => <InterfaceType>[
nullType,
numType,
intType,
doubleType,
boolType,
stringType
];
@override
DartObjectImpl get nullObject {
if (_nullObject == null) {
_nullObject = new DartObjectImpl(nullType, NullState.NULL_STATE);
}
return _nullObject;
}
@override
InterfaceType get nullType {
assert(_isCoreInitialized);
return _nullType;
}
@override
InterfaceType get numType {
assert(_isCoreInitialized);
return _numType;
}
@override
InterfaceType get objectType {
assert(_isCoreInitialized);
return _objectType;
}
@override
InterfaceType get stackTraceType {
assert(_isCoreInitialized);
return _stackTraceType;
}
@override
InterfaceType get streamDynamicType {
assert(_isAsyncInitialized);
return _streamDynamicType;
}
@override
InterfaceType get streamType {
assert(_isAsyncInitialized);
return _streamType;
}
@override
InterfaceType get stringType {
assert(_isCoreInitialized);
return _stringType;
}
@override
InterfaceType get symbolType {
assert(_isCoreInitialized);
return _symbolType;
}
@override
InterfaceType get typeType {
assert(_isCoreInitialized);
return _typeType;
}
@override
DartType get undefinedType => UndefinedTypeImpl.instance;
/**
* Initialize the `dart:async` types provided by this type provider.
*/
void initializeAsync(LibraryElement library) {
assert(_isCoreInitialized);
assert(!_isAsyncInitialized);
_isAsyncInitialized = true;
_futureType = _getType(library, "Future");
_streamType = _getType(library, "Stream");
_futureDynamicType = _futureType.substitute4(<DartType>[dynamicType]);
_futureNullType = _futureType.substitute4(<DartType>[_nullType]);
_streamDynamicType = _streamType.substitute4(<DartType>[dynamicType]);
}
/**
* Initialize the `dart:core` types provided by this type provider.
*/
void initializeCore(LibraryElement library) {
assert(!_isCoreInitialized);
assert(!_isAsyncInitialized);
_isCoreInitialized = true;
_boolType = _getType(library, "bool");
_deprecatedType = _getType(library, "Deprecated");
_doubleType = _getType(library, "double");
_functionType = _getType(library, "Function");
_intType = _getType(library, "int");
_iterableType = _getType(library, "Iterable");
_listType = _getType(library, "List");
_mapType = _getType(library, "Map");
_nullType = _getType(library, "Null");
_numType = _getType(library, "num");
_objectType = _getType(library, "Object");
_stackTraceType = _getType(library, "StackTrace");
_stringType = _getType(library, "String");
_symbolType = _getType(library, "Symbol");
_typeType = _getType(library, "Type");
_iterableDynamicType = _iterableType.substitute4(<DartType>[dynamicType]);
}
/**
* Return the type with the given [name] from the given [library], or
* throw a [StateError] if there is no class with the given name.
*/
InterfaceType _getType(LibraryElement library, String name) {
Element element = library.getType(name);
if (element == null) {
throw new StateError("No definition of type $name");
}
return (element as ClassElement).type;
}
}