Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2796)

Unified Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 898513002: Fix async/await type checking in analyzer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Reformat and sort methods Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/generated/resolver.dart
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 0576ed003700018153bfa5afe32eace3d6dd7b8b..079b177b86450a877c1d1eb552614163ec2afbd5 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -61,11 +61,19 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> {
final ErrorReporter _errorReporter;
/**
+ * The type Future<Null>, which is needed for determining whether it is safe
+ * to have a bare "return;" in an async method.
+ */
+ final InterfaceType _futureNullType;
+
+ /**
* Create a new instance of the [BestPracticesVerifier].
*
* @param errorReporter the error reporter
*/
- BestPracticesVerifier(this._errorReporter);
+ BestPracticesVerifier(this._errorReporter, TypeProvider typeProvider)
+ : _futureNullType = typeProvider.futureType.substitute4(
Brian Wilkerson 2015/02/02 19:41:48 Should we make Future<Null> directly accessible th
Paul Berry 2015/02/02 20:55:38 That's a good idea. I need to do more work in thi
+ <DartType>[typeProvider.nullType]);
@override
Object visitArgumentList(ArgumentList node) {
@@ -558,6 +566,9 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> {
* statement on all branches. At the end of blocks with no return, Dart implicitly returns
* `null`, avoiding these implicit returns is considered a best practice.
*
+ * Note: for async functions/methods, this hint only applies when the
+ * function has a return type that Future<Null> is not assignable to.
+ *
* @param node the binary expression to check
* @param body the function body
* @return `true` if and only if a hint code is generated on the passed node
@@ -577,6 +588,11 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> {
if (returnTypeType == null || returnTypeType.isVoid) {
return false;
}
+ // For async, give no hint if Future<Null> is assignable to the return
+ // type.
+ if (body.isAsynchronous && _futureNullType.isAssignableTo(returnTypeType)) {
+ return false;
+ }
// Check the block for a return statement, if not, create the hint
BlockFunctionBody blockFunctionBody = body as BlockFunctionBody;
if (!blockFunctionBody.accept(new ExitDetector())) {
@@ -4393,7 +4409,7 @@ class FunctionTypeScope extends EnclosedScope {
class HintGenerator {
final List<CompilationUnit> _compilationUnits;
- final AnalysisContext _context;
+ final InternalAnalysisContext _context;
final AnalysisErrorListener _errorListener;
@@ -4458,7 +4474,8 @@ class HintGenerator {
unit.accept(new Dart2JSVerifier(errorReporter));
}
// Dart best practices
- unit.accept(new BestPracticesVerifier(errorReporter));
+ unit.accept(
+ new BestPracticesVerifier(errorReporter, _context.typeProvider));
unit.accept(new OverrideVerifier(_manager, errorReporter));
// Find to-do comments
new ToDoFinder(errorReporter).findIn(unit);
@@ -7690,11 +7707,21 @@ class LibraryResolver {
Source _coreLibrarySource;
/**
+ * A Source object representing the async library (dart:async).
+ */
+ Source _asyncLibrarySource;
+
+ /**
* The object representing the core library.
*/
Library _coreLibrary;
/**
+ * The object representing the async library.
+ */
+ Library _asyncLibrary;
+
+ /**
* The object used to access the types from the core library.
*/
TypeProvider _typeProvider;
@@ -7718,6 +7745,8 @@ class LibraryResolver {
this._errorListener = new RecordingErrorListener();
_coreLibrarySource =
analysisContext.sourceFactory.forUri(DartSdk.DART_CORE);
+ _asyncLibrarySource =
+ analysisContext.sourceFactory.forUri(DartSdk.DART_ASYNC);
}
/**
@@ -7769,7 +7798,7 @@ class LibraryResolver {
Library targetLibrary = _createLibraryWithUnit(librarySource, unit);
_coreLibrary = _libraryMap[_coreLibrarySource];
if (_coreLibrary == null) {
- // This will be true unless the library being analyzed is the core
+ // This will only happen if the library being analyzed is the core
// library.
_coreLibrary = createLibrary(_coreLibrarySource);
if (_coreLibrary == null) {
@@ -7778,6 +7807,17 @@ class LibraryResolver {
_coreLibrarySource);
}
}
+ _asyncLibrary = _libraryMap[_asyncLibrarySource];
+ if (_asyncLibrary == null) {
+ // This will only happen if the library being analyzed is the async
+ // library.
+ _asyncLibrary = createLibrary(_asyncLibrarySource);
+ if (_asyncLibrary == null) {
+ LibraryResolver2.missingAsyncLibrary(
+ analysisContext,
+ _asyncLibrarySource);
+ }
+ }
//
// Compute the set of libraries that need to be resolved together.
//
@@ -7804,8 +7844,12 @@ class LibraryResolver {
if (coreElement == null) {
throw new AnalysisException("Could not resolve dart:core");
}
+ LibraryElement asyncElement = _asyncLibrary.libraryElement;
+ if (asyncElement == null) {
+ throw new AnalysisException("Could not resolve dart:async");
+ }
_buildDirectiveModels();
- _typeProvider = new TypeProviderImpl(coreElement);
+ _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
_buildTypeAliases();
_buildTypeHierarchies();
//
@@ -7849,7 +7893,7 @@ class LibraryResolver {
Library targetLibrary = createLibrary(librarySource);
_coreLibrary = _libraryMap[_coreLibrarySource];
if (_coreLibrary == null) {
- // This will be true unless the library being analyzed is the core
+ // This should only happen if the library being analyzed is the core
// library.
_coreLibrary = _createLibraryOrNull(_coreLibrarySource);
if (_coreLibrary == null) {
@@ -7858,6 +7902,17 @@ class LibraryResolver {
_coreLibrarySource);
}
}
+ _asyncLibrary = _libraryMap[_asyncLibrarySource];
+ if (_asyncLibrary == null) {
+ // This should only happen if the library being analyzed is the async
+ // library.
+ _asyncLibrary = _createLibraryOrNull(_asyncLibrarySource);
+ if (_asyncLibrary == null) {
+ LibraryResolver2.missingAsyncLibrary(
+ analysisContext,
+ _asyncLibrarySource);
+ }
+ }
//
// Compute the set of libraries that need to be resolved together.
//
@@ -7886,8 +7941,12 @@ class LibraryResolver {
if (coreElement == null) {
throw new AnalysisException("Could not resolve dart:core");
}
+ LibraryElement asyncElement = _asyncLibrary.libraryElement;
+ if (asyncElement == null) {
+ throw new AnalysisException("Coulb not resolve dart:async");
+ }
_buildDirectiveModels();
- _typeProvider = new TypeProviderImpl(coreElement);
+ _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
_buildEnumMembers();
_buildTypeAliases();
_buildTypeHierarchies();
@@ -7966,13 +8025,21 @@ class LibraryResolver {
void _addToDependencyMap(Library library, HashMap<Library,
List<Library>> dependencyMap, Set<Library> visitedLibraries) {
if (visitedLibraries.add(library)) {
+ bool asyncFound = false;
for (Library referencedLibrary in library.importsAndExports) {
_addDependencyToMap(dependencyMap, library, referencedLibrary);
_addToDependencyMap(referencedLibrary, dependencyMap, visitedLibraries);
+ if (identical(referencedLibrary, _asyncLibrary)) {
+ asyncFound = true;
+ }
}
if (!library.explicitlyImportsCore && !identical(library, _coreLibrary)) {
_addDependencyToMap(dependencyMap, library, _coreLibrary);
}
+ if (!asyncFound && !identical(library, _asyncLibrary)) {
+ _addDependencyToMap(dependencyMap, library, _asyncLibrary);
+ _addToDependencyMap(_asyncLibrary, dependencyMap, visitedLibraries);
+ }
}
}
@@ -8339,10 +8406,14 @@ class LibraryResolver {
List<Source> importedSources, List<Source> exportedSources) {
List<Library> importedLibraries = new List<Library>();
bool explicitlyImportsCore = false;
+ bool importsAsync = false;
for (Source importedSource in importedSources) {
if (importedSource == _coreLibrarySource) {
explicitlyImportsCore = true;
}
+ if (importedSource == _asyncLibrarySource) {
+ importsAsync = true;
+ }
Library importedLibrary = _libraryMap[importedSource];
if (importedLibrary == null) {
importedLibrary = _createLibraryOrNull(importedSource);
@@ -8379,6 +8450,15 @@ class LibraryResolver {
}
}
}
+ if (!importsAsync && _asyncLibrarySource != library.librarySource) {
+ Library importedLibrary = _libraryMap[_asyncLibrarySource];
+ if (importedLibrary == null) {
+ importedLibrary = _createLibraryOrNull(_asyncLibrarySource);
+ if (importedLibrary != null) {
+ _computeLibraryDependencies(importedLibrary);
+ }
+ }
+ }
}
/**
@@ -8560,11 +8640,21 @@ class LibraryResolver2 {
Source _coreLibrarySource;
/**
+ * A source object representing the async library (dart:async).
+ */
+ Source _asyncLibrarySource;
+
+ /**
* The object representing the core library.
*/
ResolvableLibrary _coreLibrary;
/**
+ * The object representing the async library.
+ */
+ ResolvableLibrary _asyncLibrary;
+
+ /**
* The object used to access the types from the core library.
*/
TypeProvider _typeProvider;
@@ -8589,6 +8679,8 @@ class LibraryResolver2 {
this._errorListener = new RecordingErrorListener();
_coreLibrarySource =
analysisContext.sourceFactory.forUri(DartSdk.DART_CORE);
+ _asyncLibrarySource =
+ analysisContext.sourceFactory.forUri(DartSdk.DART_ASYNC);
}
/**
@@ -8627,6 +8719,7 @@ class LibraryResolver2 {
_libraryMap = _buildLibraryMap();
ResolvableLibrary targetLibrary = _libraryMap[librarySource];
_coreLibrary = _libraryMap[_coreLibrarySource];
+ _asyncLibrary = _libraryMap[_asyncLibrarySource];
//
// Build the element models representing the libraries being resolved.
// This is done in three steps:
@@ -8650,8 +8743,12 @@ class LibraryResolver2 {
if (coreElement == null) {
missingCoreLibrary(analysisContext, _coreLibrarySource);
}
+ LibraryElement asyncElement = _asyncLibrary.libraryElement;
+ if (asyncElement == null) {
+ missingAsyncLibrary(analysisContext, _asyncLibrarySource);
+ }
_buildDirectiveModels();
- _typeProvider = new TypeProviderImpl(coreElement);
+ _typeProvider = new TypeProviderImpl(coreElement, asyncElement);
_buildEnumMembers();
_buildTypeAliases();
_buildTypeHierarchies();
@@ -9068,6 +9165,16 @@ class LibraryResolver2 {
}
/**
+ * Report that the async library could not be resolved in the given
+ * [analysisContext] and throw an exception. [asyncLibrarySource] is the source
+ * representing the async library.
+ */
+ static void missingAsyncLibrary(AnalysisContext analysisContext,
+ Source asyncLibrarySource) {
+ throw new AnalysisException("Could not resolve dart:async");
+ }
+
+ /**
* Report that the core library could not be resolved in the given analysis context and throw an
* exception.
*
@@ -13300,6 +13407,11 @@ abstract class TypeProvider {
InterfaceType get functionType;
/**
+ * Return the type representing the built-in type 'Future'.
+ */
+ InterfaceType get futureType;
+
+ /**
* Return the type representing the built-in type 'int'.
*
* @return the type representing the built-in type 'int'
@@ -13411,6 +13523,11 @@ class TypeProviderImpl implements TypeProvider {
InterfaceType _functionType;
/**
+ * The type representing the built-in type 'Future'.
+ */
+ InterfaceType _futureType;
+
+ /**
* The type representing the built-in type 'int'.
*/
InterfaceType _intType;
@@ -13470,8 +13587,8 @@ class TypeProviderImpl implements TypeProvider {
*
* @param coreLibrary the element representing the core library (dart:core).
*/
- TypeProviderImpl(LibraryElement coreLibrary) {
- _initializeFrom(coreLibrary);
+ TypeProviderImpl(LibraryElement coreLibrary, LibraryElement asyncLibrary) {
+ _initializeFrom(coreLibrary, asyncLibrary);
}
@override
@@ -13493,6 +13610,9 @@ class TypeProviderImpl implements TypeProvider {
InterfaceType get functionType => _functionType;
@override
+ InterfaceType get futureType => _futureType;
+
+ @override
InterfaceType get intType => _intType;
@override
@@ -13548,25 +13668,29 @@ class TypeProviderImpl implements TypeProvider {
*
* @param library the library containing the definitions of the core types
*/
- void _initializeFrom(LibraryElement library) {
- Namespace namespace =
- new NamespaceBuilder().createPublicNamespaceForLibrary(library);
- _boolType = _getType(namespace, "bool");
+ void _initializeFrom(LibraryElement coreLibrary,
+ LibraryElement asyncLibrary) {
+ Namespace coreNamespace =
+ new NamespaceBuilder().createPublicNamespaceForLibrary(coreLibrary);
+ Namespace asyncNamespace =
+ new NamespaceBuilder().createPublicNamespaceForLibrary(asyncLibrary);
+ _boolType = _getType(coreNamespace, "bool");
_bottomType = BottomTypeImpl.instance;
- _deprecatedType = _getType(namespace, "Deprecated");
- _doubleType = _getType(namespace, "double");
+ _deprecatedType = _getType(coreNamespace, "Deprecated");
+ _doubleType = _getType(coreNamespace, "double");
_dynamicType = DynamicTypeImpl.instance;
- _functionType = _getType(namespace, "Function");
- _intType = _getType(namespace, "int");
- _listType = _getType(namespace, "List");
- _mapType = _getType(namespace, "Map");
- _nullType = _getType(namespace, "Null");
- _numType = _getType(namespace, "num");
- _objectType = _getType(namespace, "Object");
- _stackTraceType = _getType(namespace, "StackTrace");
- _stringType = _getType(namespace, "String");
- _symbolType = _getType(namespace, "Symbol");
- _typeType = _getType(namespace, "Type");
+ _functionType = _getType(coreNamespace, "Function");
+ _futureType = _getType(asyncNamespace, "Future");
+ _intType = _getType(coreNamespace, "int");
+ _listType = _getType(coreNamespace, "List");
+ _mapType = _getType(coreNamespace, "Map");
+ _nullType = _getType(coreNamespace, "Null");
+ _numType = _getType(coreNamespace, "num");
+ _objectType = _getType(coreNamespace, "Object");
+ _stackTraceType = _getType(coreNamespace, "StackTrace");
+ _stringType = _getType(coreNamespace, "String");
+ _symbolType = _getType(coreNamespace, "Symbol");
+ _typeType = _getType(coreNamespace, "Type");
_undefinedType = UndefinedTypeImpl.instance;
}
}

Powered by Google App Engine
This is Rietveld 408576698