From 787e9fcf7f11a8a0dcd8a7900a962cb24506cdc9 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Fri, 5 Jun 2015 11:29:04 -0700 Subject: [PATCH] Reanalyze after creating a referenced part. We need to finish linking CompilationUnitElement(s) to LibraryElement(s) even for not existing sources. Otherwise we get NPE later and leave model in the ERROR state. R=brianwilkerson@google.com BUG= Review URL: https://codereview.chromium.org//1168743002 --- pkg/analyzer/lib/src/context/cache.dart | 10 +++++ pkg/analyzer/lib/src/task/dart.dart | 38 ++++++++++--------- pkg/analyzer/lib/src/task/driver.dart | 1 + .../test/src/context/context_test.dart | 7 ++++ pkg/analyzer/test/src/task/dart_test.dart | 7 +++- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart index d9fada497b7..c8aa54d0c05 100644 --- a/pkg/analyzer/lib/src/context/cache.dart +++ b/pkg/analyzer/lib/src/context/cache.dart @@ -425,6 +425,15 @@ class CacheEntry { */ /**/ void setValue(ResultDescriptor /**/ descriptor, dynamic /*V*/ value, List dependedOn) { +// { +// String valueStr = '$value'; +// if (valueStr.length > 20) { +// valueStr = valueStr.substring(0, 20) + '...'; +// } +// valueStr = valueStr.replaceAll('\n', '\\n'); +// print( +// 'setValue $descriptor for $target value=$valueStr deps=$dependedOn'); +// } _validateStateChange(descriptor, CacheState.VALID); TargetedResult thisResult = new TargetedResult(target, descriptor); if (_partition != null) { @@ -464,6 +473,7 @@ class CacheEntry { * invalidation to other results that depend on it. */ void _invalidate(ResultDescriptor descriptor) { +// print('invalidate $descriptor for $target'); ResultData thisData = _resultMap.remove(descriptor); if (thisData == null) { return; diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart index 9aaa8c8c98b..f27614d9197 100644 --- a/pkg/analyzer/lib/src/task/dart.dart +++ b/pkg/analyzer/lib/src/task/dart.dart @@ -1331,7 +1331,7 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask { Source partSource = partDirective.source; hasPartDirective = true; CompilationUnit partUnit = partUnitMap[partSource]; - if (partUnit != null && context.exists(partSource)) { + if (partUnit != null) { CompilationUnitElementImpl partElement = partUnit.element; partElement.uriOffset = partUri.offset; partElement.uriEnd = partUri.end; @@ -1340,24 +1340,26 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask { // Validate that the part contains a part-of directive with the same // name as the library. // - String partLibraryName = - _getPartLibraryName(partSource, partUnit, directivesToResolve); - if (partLibraryName == null) { - errors.add(new AnalysisError(librarySource, partUri.offset, - partUri.length, CompileTimeErrorCode.PART_OF_NON_PART, - [partUri.toSource()])); - } else if (libraryNameNode == null) { - if (partsLibraryName == _UNKNOWN_LIBRARY_NAME) { - partsLibraryName = partLibraryName; - } else if (partsLibraryName != partLibraryName) { - partsLibraryName = null; + if (context.exists(partSource)) { + String partLibraryName = + _getPartLibraryName(partSource, partUnit, directivesToResolve); + if (partLibraryName == null) { + errors.add(new AnalysisError(librarySource, partUri.offset, + partUri.length, CompileTimeErrorCode.PART_OF_NON_PART, + [partUri.toSource()])); + } else if (libraryNameNode == null) { + if (partsLibraryName == _UNKNOWN_LIBRARY_NAME) { + partsLibraryName = partLibraryName; + } else if (partsLibraryName != partLibraryName) { + partsLibraryName = null; + } + } else if (libraryNameNode.name != partLibraryName) { + errors.add(new AnalysisError(librarySource, partUri.offset, + partUri.length, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [ + libraryNameNode.name, + partLibraryName + ])); } - } else if (libraryNameNode.name != partLibraryName) { - errors.add(new AnalysisError(librarySource, partUri.offset, - partUri.length, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [ - libraryNameNode.name, - partLibraryName - ])); } if (entryPoint == null) { entryPoint = _findEntryPoint(partElement); diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart index ad76d3dd2aa..36781f58b7e 100644 --- a/pkg/analyzer/lib/src/task/driver.dart +++ b/pkg/analyzer/lib/src/task/driver.dart @@ -126,6 +126,7 @@ class AnalysisDriver { } // Create a new WorkOrder. TargetedResult request = highestManager.getNextResult(); +// print('request: $request'); if (request != null) { WorkOrder workOrder = createWorkOrderForResult(request.target, request.result); diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart index 0f4ea1353c8..ddca9826228 100644 --- a/pkg/analyzer/test/src/context/context_test.dart +++ b/pkg/analyzer/test/src/context/context_test.dart @@ -473,6 +473,8 @@ library lib; part 'part.dart';'''); // run all tasks without part _analyzeAll_assertFinished(); + expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(libSource)), + isTrue, reason: "lib has errors"); // add part and run all tasks Source partSource = addSource("/part.dart", r''' part of lib; @@ -481,6 +483,11 @@ part of lib; // "libSource" should be here List librariesWithPart = context.getLibrariesContaining(partSource); expect(librariesWithPart, unorderedEquals([libSource])); + expect(_hasAnalysisErrorWithErrorSeverity(context.getErrors(libSource)), + isFalse, reason: "lib doesn't have errors"); + expect( + context.getResolvedCompilationUnit2(partSource, libSource), isNotNull, + reason: "part resolved"); } void test_performAnalysisTask_changeLibraryContents() { diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart index bd3ad5c753f..4036ee2f1e2 100644 --- a/pkg/analyzer/test/src/task/dart_test.dart +++ b/pkg/analyzer/test/src/task/dart_test.dart @@ -981,7 +981,12 @@ library lib; part 'no-such-file.dart'; ''' }); - expect(libraryElement.parts, isEmpty); + expect(libraryElement.parts, hasLength(1)); + CompilationUnitElement part = libraryElement.parts[0]; + expect(part, isNotNull); + expect(part.source, isNotNull); + expect(part.library, same(libraryElement)); + expect(context.exists(part.source), isFalse); } test_perform_patchTopLevelAccessors() {