Version 1.13.0-dev.7.1
Cherry-pick d2b1edb695e35455ca0f5735385c66e4c3e397db to dev
Cherry-pick a30bcd7b97c5d4704b27c99ba9cf8d85b527bb83 to dev
Cherry-pick a8e3eb4e101e914a47ac3a188fbbc214cc206595 to dev
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
index 7f58ad7..a4971ce 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
@@ -58,8 +58,7 @@
if (element.location == null) {
return;
}
- protocol.ElementKind kind =
- protocol.convertElementKind(element.kind);
+ protocol.ElementKind kind = protocol.convertElementKind(element.kind);
protocol.Location location = protocol.newLocation_fromElement(element);
if (location == null) {
return;
@@ -326,9 +325,11 @@
return;
}
// The node starts or ends in the range.
- if (isInRange(node.offset) || isInRange(node.end)) {
- node.accept(visitor);
- return;
+ if (node is! CompilationUnit) {
+ if (isInRange(node.offset) || isInRange(node.end) || node is Directive) {
+ node.accept(visitor);
+ return;
+ }
}
// Go deeper.
super.visitNode(node);
diff --git a/pkg/analysis_server/test/analysis/get_navigation_test.dart b/pkg/analysis_server/test/analysis/get_navigation_test.dart
index 34a8010..fb49169 100644
--- a/pkg/analysis_server/test/analysis/get_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/get_navigation_test.dart
@@ -58,6 +58,48 @@
return _checkInvalid(file, -1, -1);
}
+ test_issue24599_importDirective() async {
+ addTestFile('''
+import 'dart:math';
+
+main() {
+}''');
+ await waitForTasksFinished();
+ await _getNavigation(testFile, 0, 17);
+ expect(regions, hasLength(1));
+ assertHasRegionString("'dart:math'");
+ expect(testTargets, hasLength(1));
+ expect(testTargets[0].kind, ElementKind.LIBRARY);
+ }
+
+ test_issue24599_importKeyword() async {
+ addTestFile('''
+import 'dart:math';
+
+main() {
+}''');
+ await waitForTasksFinished();
+ await _getNavigation(testFile, 0, 1);
+ expect(regions, hasLength(1));
+ assertHasRegionString("'dart:math'");
+ expect(testTargets, hasLength(1));
+ expect(testTargets[0].kind, ElementKind.LIBRARY);
+ }
+
+ test_issue24599_importUri() async {
+ addTestFile('''
+import 'dart:math';
+
+main() {
+}''');
+ await waitForTasksFinished();
+ await _getNavigation(testFile, 7, 11);
+ expect(regions, hasLength(1));
+ assertHasRegionString("'dart:math'");
+ expect(testTargets, hasLength(1));
+ expect(testTargets[0].kind, ElementKind.LIBRARY);
+ }
+
test_multipleRegions() async {
addTestFile('''
main() {
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index 4accf97..5e66eca 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -26,6 +26,7 @@
NavigationRegion testRegion;
List<int> testTargetIndexes;
+ List<NavigationTarget> testTargets;
NavigationTarget testTarget;
/**
@@ -33,8 +34,6 @@
* at [offset] and with the given [length].
*/
void assertHasFileTarget(String file, int offset, int length) {
- List<NavigationTarget> testTargets =
- testTargetIndexes.map((int index) => targets[index]).toList();
for (NavigationTarget target in testTargets) {
if (targetFiles[target.fileIndex] == file &&
target.offset == offset &&
@@ -167,6 +166,7 @@
}
testRegion = region;
testTargetIndexes = region.targets;
+ testTargets = testTargetIndexes.map((i) => targets[i]).toList();
return;
}
}
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index ab8fe91..ffe623b 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -974,10 +974,18 @@
return null;
}
//
- // We ignore identifiers that have already been resolved, such as
- // identifiers representing the name in a declaration.
+ // Ignore nodes that should have been resolved before getting here.
//
- if (node.staticElement != null) {
+ if (node.inDeclarationContext()) {
+ return null;
+ }
+ AstNode parent = node.parent;
+ if (parent is FieldFormalParameter) {
+ return null;
+ } else if (parent is ConstructorFieldInitializer &&
+ parent.fieldName == node) {
+ return null;
+ } else if (parent is Annotation && parent.constructorName == node) {
return null;
}
//
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 6ed3964..dc484ed 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -29,9 +29,9 @@
import 'package:analyzer/src/task/html.dart';
import 'package:analyzer/src/task/inputs.dart';
import 'package:analyzer/src/task/model.dart';
-import 'package:analyzer/src/task/strong_mode.dart';
import 'package:analyzer/src/task/strong/checker.dart';
import 'package:analyzer/src/task/strong/rules.dart';
+import 'package:analyzer/src/task/strong_mode.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/general.dart';
import 'package:analyzer/task/model.dart';
@@ -162,43 +162,6 @@
new ListResultDescriptor<Source>('IMPORT_EXPORT_SOURCE_CLOSURE', null);
/**
- * A list of the [LibraryElement]s that make up the strongly connected
- * component in the import/export graph in which the target resides.
- *
- * Only non-empty in strongMode
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<LibraryElement> LIBRARY_CYCLE =
- new ListResultDescriptor<LibraryElement>('LIBRARY_CYCLE', null);
-
-/**
- * A list of the [CompilationUnitElement]s (including all parts) that make up
- * the strongly connected component in the import/export graph in which the
- * target resides.
- *
- * Only non-empty in strongMode
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<CompilationUnitElement> LIBRARY_CYCLE_UNITS =
- new ListResultDescriptor<CompilationUnitElement>(
- 'LIBRARY_CYCLE_UNITS', null);
-
-/**
- * A list of the [CompilationUnitElement]s that comprise all of the parts and
- * libraries in the direct import/export dependencies of the library cycle
- * of the target, with the intra-component dependencies excluded.
- *
- * Only non-empty in strongMode
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<CompilationUnitElement> LIBRARY_CYCLE_DEPENDENCIES =
- new ListResultDescriptor<CompilationUnitElement>(
- 'LIBRARY_CYCLE_DEPENDENCIES', null);
-
-/**
* A list of the [VariableElement]s whose type should be inferred that another
* inferable static variable (the target) depends on.
*
@@ -234,6 +197,43 @@
cachingPolicy: ELEMENT_CACHING_POLICY);
/**
+ * A list of the [LibraryElement]s that make up the strongly connected
+ * component in the import/export graph in which the target resides.
+ *
+ * Only non-empty in strongMode.
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ListResultDescriptor<LibraryElement> LIBRARY_CYCLE =
+ new ListResultDescriptor<LibraryElement>('LIBRARY_CYCLE', null);
+
+/**
+ * A list of the [CompilationUnitElement]s that comprise all of the parts and
+ * libraries in the direct import/export dependencies of the library cycle
+ * of the target, with the intra-component dependencies excluded.
+ *
+ * Only non-empty in strongMode.
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ListResultDescriptor<CompilationUnitElement> LIBRARY_CYCLE_DEPENDENCIES =
+ new ListResultDescriptor<CompilationUnitElement>(
+ 'LIBRARY_CYCLE_DEPENDENCIES', null);
+
+/**
+ * A list of the [CompilationUnitElement]s (including all parts) that make up
+ * the strongly connected component in the import/export graph in which the
+ * target resides.
+ *
+ * Only non-empty in strongMode.
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ListResultDescriptor<CompilationUnitElement> LIBRARY_CYCLE_UNITS =
+ new ListResultDescriptor<CompilationUnitElement>(
+ 'LIBRARY_CYCLE_UNITS', null);
+
+/**
* The partial [LibraryElement] associated with a library.
*
* The [LibraryElement] and its [CompilationUnitElement]s are attached to each
@@ -343,17 +343,6 @@
new ResultDescriptor<ReferencedNames>('REFERENCED_NAMES', null);
/**
- * The errors produced while resolving a full compilation unit.
- *
- * The list will be empty if there were no errors, but will not be `null`.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ListResultDescriptor<AnalysisError> RESOLVE_UNIT_ERRORS =
- new ListResultDescriptor<AnalysisError>(
- 'RESOLVE_UNIT_ERRORS', AnalysisError.NO_ERRORS);
-
-/**
* The errors produced while resolving type names.
*
* The list will be empty if there were no errors, but will not be `null`.
@@ -365,6 +354,17 @@
'RESOLVE_TYPE_NAMES_ERRORS', AnalysisError.NO_ERRORS);
/**
+ * The errors produced while resolving a full compilation unit.
+ *
+ * The list will be empty if there were no errors, but will not be `null`.
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ListResultDescriptor<AnalysisError> RESOLVE_UNIT_ERRORS =
+ new ListResultDescriptor<AnalysisError>(
+ 'RESOLVE_UNIT_ERRORS', AnalysisError.NO_ERRORS);
+
+/**
* The partially resolved [CompilationUnit] associated with a compilation unit.
*
* Tasks that use this value as an input can assume that the [SimpleIdentifier]s
@@ -378,11 +378,21 @@
cachingPolicy: AST_CACHING_POLICY);
/**
+ * The resolved [CompilationUnit] associated with a compilation unit, with
+ * constants resolved.
+ *
+ * The result is only available for [LibrarySpecificUnit]s.
+ */
+final ResultDescriptor<CompilationUnit> RESOLVED_UNIT10 =
+ new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT10', null,
+ cachingPolicy: AST_CACHING_POLICY);
+
+/**
* The partially resolved [CompilationUnit] associated with a compilation unit.
*
* Tasks that use this value as an input can assume that the [SimpleIdentifier]s
* at all declaration sites have been bound to the element defined by the
- * declaration, including for the constants defined in an 'enum' declaration.
+ * declaration, including the constants defined in an 'enum' declaration.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
@@ -421,8 +431,9 @@
* The partially resolved [CompilationUnit] associated with a compilation unit.
*
* In addition to what is true of a [RESOLVED_UNIT4], tasks that use this value
- * as an input can assume that elements and types have been initially resolved
- * outside of method bodies.
+ * as an input can assume that elements and types associated with expressions
+ * outside of method bodies (essentially initializers) have been initially
+ * resolved.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
@@ -443,9 +454,11 @@
cachingPolicy: AST_CACHING_POLICY);
/**
- * The resolved [CompilationUnit] associated with a compilation unit in which
- * the right hand sides of instance variables have been re-resolved in addition
- * to everything that is true of a [RESOLVED_UNIT6].
+ * The partially resolved [CompilationUnit] associated with a compilation unit.
+ *
+ * In addition to what is true of a [RESOLVED_UNIT6], tasks that use this value
+ * as an input can assume that the initializers of instance variables have been
+ * re-resolved.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
@@ -475,16 +488,6 @@
cachingPolicy: AST_CACHING_POLICY);
/**
- * The resolved [CompilationUnit] associated with a compilation unit, with
- * constants resolved.
- *
- * The result is only available for [LibrarySpecificUnit]s.
- */
-final ResultDescriptor<CompilationUnit> RESOLVED_UNIT10 =
- new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT10', null,
- cachingPolicy: AST_CACHING_POLICY);
-
-/**
* The errors produced while scanning a compilation unit.
*
* The list will be empty if there were no errors, but will not be `null`.
@@ -2733,122 +2736,6 @@
}
/**
- * A task that ensures that all of the inferrable instance members in a
- * compilation unit have had their right hand sides re-resolved
- */
-class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask {
- /**
- * The name of the [LIBRARY_ELEMENT5] input.
- */
- static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
-
- /**
- * The name of the [TYPE_PROVIDER] input.
- */
- static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
-
- /**
- * The name of the input whose value is the [RESOLVED_UNIT6] for the
- * compilation unit.
- */
- static const String UNIT_INPUT = 'UNIT_INPUT';
-
- /**
- * The task descriptor describing this kind of task.
- */
- static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveInstanceFieldsInUnitTask',
- createTask,
- buildInputs,
- <ResultDescriptor>[RESOLVED_UNIT7]);
-
- /**
- * Initialize a newly created task to build a library element for the given
- * [unit] in the given [context].
- */
- ResolveInstanceFieldsInUnitTask(
- InternalAnalysisContext context, LibrarySpecificUnit unit)
- : super(context, unit);
-
- @override
- TaskDescriptor get descriptor => DESCRIPTOR;
-
- @override
- void internalPerform() {
- //
- // Prepare inputs.
- //
- LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
- CompilationUnit unit = getRequiredInput(UNIT_INPUT);
- TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
-
- CompilationUnitElement unitElement = unit.element;
- if (context.analysisOptions.strongMode) {
- //
- // Resolve references.
- //
- // TODO(leafp): This code only needs to re-resolve the right hand sides of
- // instance fields. We could do incremental resolution on each field
- // only using the incremental resolver. However, this caused a massive
- // performance degredation on the large_class_declaration_test.dart test.
- // I would hypothesize that incremental resolution of field is linear in
- // the size of the enclosing class, and hence incrementally resolving each
- // field was quadratic. We may wish to revisit this if we can resolve
- // this performance issue.
- InheritanceManager inheritanceManager =
- new InheritanceManager(libraryElement);
- PartialResolverVisitor visitor = new PartialResolverVisitor(
- libraryElement,
- unitElement.source,
- typeProvider,
- AnalysisErrorListener.NULL_LISTENER,
- inheritanceManager: inheritanceManager);
- unit.accept(visitor);
- }
- //
- // Record outputs.
- //
- outputs[RESOLVED_UNIT7] = unit;
- }
-
- /**
- * Return a map from the names of the inputs of this kind of task to the task
- * input descriptors describing those inputs for a task with the given
- * [libSource].
- */
- static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
- LibrarySpecificUnit unit = target;
- return <String, TaskInput>{
- UNIT_INPUT: RESOLVED_UNIT6.of(unit),
- LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
- TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
- // In strong mode, add additional dependencies to enforce inference
- // ordering.
-
- // Require that static variable inference be complete for all units in
- // the current library cycle.
- 'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
- (CompilationUnitElementImpl unit) => RESOLVED_UNIT6
- .of(new LibrarySpecificUnit(unit.librarySource, unit.source))),
- // Require that full inference be complete for all dependencies of the
- // current library cycle.
- 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
- (CompilationUnitElementImpl unit) => RESOLVED_UNIT8
- .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
- };
- }
-
- /**
- * Create a [ResolveInstanceFieldsInUnitTask] based on the given [target] in
- * the given [context].
- */
- static ResolveInstanceFieldsInUnitTask createTask(
- AnalysisContext context, AnalysisTarget target) {
- return new ResolveInstanceFieldsInUnitTask(context, target);
- }
-}
-
-/**
* An abstract class that defines utility methods that are useful for tasks
* operating on static variables.
*/
@@ -3691,12 +3578,12 @@
}
/**
- * A task that resolves the bodies of top-level functions, constructors, and
- * methods within a single compilation unit.
+ * A task that ensures that all of the inferrable instance members in a
+ * compilation unit have had their right hand sides re-resolved
*/
-class ResolveUnitTask extends SourceBasedAnalysisTask {
+class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask {
/**
- * The name of the input whose value is the defining [LIBRARY_ELEMENT5].
+ * The name of the [LIBRARY_ELEMENT5] input.
*/
static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
@@ -3706,19 +3593,27 @@
static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
/**
- * The name of the [RESOLVED_UNIT8] input.
+ * The name of the input whose value is the [RESOLVED_UNIT6] for the
+ * compilation unit.
*/
static const String UNIT_INPUT = 'UNIT_INPUT';
+ /**
+ * The task descriptor describing this kind of task.
+ */
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
- 'ResolveUnitTask',
+ 'ResolveInstanceFieldsInUnitTask',
createTask,
buildInputs,
- <ResultDescriptor>[RESOLVE_UNIT_ERRORS, RESOLVED_UNIT9]);
+ <ResultDescriptor>[RESOLVED_UNIT7]);
- ResolveUnitTask(
- InternalAnalysisContext context, LibrarySpecificUnit compilationUnit)
- : super(context, compilationUnit);
+ /**
+ * Initialize a newly created task to build a library element for the given
+ * [unit] in the given [context].
+ */
+ ResolveInstanceFieldsInUnitTask(
+ InternalAnalysisContext context, LibrarySpecificUnit unit)
+ : super(context, unit);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@@ -3731,50 +3626,70 @@
LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
CompilationUnit unit = getRequiredInput(UNIT_INPUT);
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
- //
- // Resolve everything
- //
+
CompilationUnitElement unitElement = unit.element;
- RecordingErrorListener errorListener = new RecordingErrorListener();
- ResolverVisitor visitor = new ResolverVisitor(
- libraryElement, unitElement.source, typeProvider, errorListener);
- unit.accept(visitor);
+ if (context.analysisOptions.strongMode) {
+ //
+ // Resolve references.
+ //
+ // TODO(leafp): This code only needs to re-resolve the right hand sides of
+ // instance fields. We could do incremental resolution on each field
+ // only using the incremental resolver. However, this caused a massive
+ // performance degredation on the large_class_declaration_test.dart test.
+ // I would hypothesize that incremental resolution of field is linear in
+ // the size of the enclosing class, and hence incrementally resolving each
+ // field was quadratic. We may wish to revisit this if we can resolve
+ // this performance issue.
+ InheritanceManager inheritanceManager =
+ new InheritanceManager(libraryElement);
+ PartialResolverVisitor visitor = new PartialResolverVisitor(
+ libraryElement,
+ unitElement.source,
+ typeProvider,
+ AnalysisErrorListener.NULL_LISTENER,
+ inheritanceManager: inheritanceManager);
+ unit.accept(visitor);
+ }
//
// Record outputs.
//
- outputs[RESOLVE_UNIT_ERRORS] = errorListener.errors;
- outputs[RESOLVED_UNIT9] = unit;
+ outputs[RESOLVED_UNIT7] = unit;
}
/**
* Return a map from the names of the inputs of this kind of task to the task
* input descriptors describing those inputs for a task with the given
- * [target].
+ * [libSource].
*/
static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
LibrarySpecificUnit unit = target;
return <String, TaskInput>{
+ UNIT_INPUT: RESOLVED_UNIT6.of(unit),
LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
- UNIT_INPUT: RESOLVED_UNIT8.of(unit),
// In strong mode, add additional dependencies to enforce inference
// ordering.
- // Require that inference be complete for all units in the
- // current library cycle.
+ // Require that static variable inference be complete for all units in
+ // the current library cycle.
'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
+ (CompilationUnitElementImpl unit) => RESOLVED_UNIT6
+ .of(new LibrarySpecificUnit(unit.librarySource, unit.source))),
+ // Require that full inference be complete for all dependencies of the
+ // current library cycle.
+ 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList(
(CompilationUnitElementImpl unit) => RESOLVED_UNIT8
.of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
};
}
/**
- * Create a [ResolveUnitTask] based on the given [target] in
+ * Create a [ResolveInstanceFieldsInUnitTask] based on the given [target] in
* the given [context].
*/
- static ResolveUnitTask createTask(
+ static ResolveInstanceFieldsInUnitTask createTask(
AnalysisContext context, AnalysisTarget target) {
- return new ResolveUnitTask(context, target);
+ return new ResolveInstanceFieldsInUnitTask(context, target);
}
}
@@ -3914,6 +3829,94 @@
}
/**
+ * A task that resolves the bodies of top-level functions, constructors, and
+ * methods within a single compilation unit.
+ */
+class ResolveUnitTask extends SourceBasedAnalysisTask {
+ /**
+ * The name of the input whose value is the defining [LIBRARY_ELEMENT5].
+ */
+ static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
+
+ /**
+ * The name of the [TYPE_PROVIDER] input.
+ */
+ static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
+
+ /**
+ * The name of the [RESOLVED_UNIT8] input.
+ */
+ static const String UNIT_INPUT = 'UNIT_INPUT';
+
+ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+ 'ResolveUnitTask',
+ createTask,
+ buildInputs,
+ <ResultDescriptor>[RESOLVE_UNIT_ERRORS, RESOLVED_UNIT9]);
+
+ ResolveUnitTask(
+ InternalAnalysisContext context, LibrarySpecificUnit compilationUnit)
+ : super(context, compilationUnit);
+
+ @override
+ TaskDescriptor get descriptor => DESCRIPTOR;
+
+ @override
+ void internalPerform() {
+ //
+ // Prepare inputs.
+ //
+ LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
+ CompilationUnit unit = getRequiredInput(UNIT_INPUT);
+ TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
+ //
+ // Resolve everything.
+ //
+ CompilationUnitElement unitElement = unit.element;
+ RecordingErrorListener errorListener = new RecordingErrorListener();
+ ResolverVisitor visitor = new ResolverVisitor(
+ libraryElement, unitElement.source, typeProvider, errorListener);
+ unit.accept(visitor);
+ //
+ // Record outputs.
+ //
+ outputs[RESOLVE_UNIT_ERRORS] = errorListener.errors;
+ outputs[RESOLVED_UNIT9] = unit;
+ }
+
+ /**
+ * Return a map from the names of the inputs of this kind of task to the task
+ * input descriptors describing those inputs for a task with the given
+ * [target].
+ */
+ static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+ LibrarySpecificUnit unit = target;
+ return <String, TaskInput>{
+ LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
+ TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
+ UNIT_INPUT: RESOLVED_UNIT8.of(unit),
+ // In strong mode, add additional dependencies to enforce inference
+ // ordering.
+
+ // Require that inference be complete for all units in the
+ // current library cycle.
+ 'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList(
+ (CompilationUnitElementImpl unit) => RESOLVED_UNIT8
+ .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
+ };
+ }
+
+ /**
+ * Create a [ResolveUnitTask] based on the given [target] in
+ * the given [context].
+ */
+ static ResolveUnitTask createTask(
+ AnalysisContext context, AnalysisTarget target) {
+ return new ResolveUnitTask(context, target);
+ }
+}
+
+/**
* A task that builds [RESOLVED_UNIT3] for a unit.
*/
class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 0142fcb..e3615fe 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -1912,7 +1912,7 @@
UsedLocalElements usedElements;
Set<String> usedElementNames;
- fail_perform_forPart_afterLibraryUpdate() {
+ test_perform_forPart_afterLibraryUpdate() {
Source libSource = newSource(
'/my_lib.dart',
'''
@@ -3982,25 +3982,6 @@
enableStrongMode();
}
- void test_perform_verifyError() {
- enableStrongMode();
- AnalysisTarget source = newSource(
- '/test.dart',
- '''
-int topLevel = 3;
-class C {
- String field = topLevel;
-}
-''');
- computeResult(new LibrarySpecificUnit(source, source), STRONG_MODE_ERRORS);
- // validate
- _fillErrorListener(STRONG_MODE_ERRORS);
-
- var errors = errorListener.errors;
- expect(errors.length, 1);
- expect(errors[0].errorCode.name, "dev_compiler.StaticTypeError");
- }
-
void test_perform_recordDynamicInvoke() {
enableStrongMode();
AnalysisTarget source = newSource(
@@ -4025,6 +4006,25 @@
expect(DynamicInvoke.get(idx.target), isNotNull);
expect(DynamicInvoke.get(idx.target), isTrue);
}
+
+ void test_perform_verifyError() {
+ enableStrongMode();
+ AnalysisTarget source = newSource(
+ '/test.dart',
+ '''
+int topLevel = 3;
+class C {
+ String field = topLevel;
+}
+''');
+ computeResult(new LibrarySpecificUnit(source, source), STRONG_MODE_ERRORS);
+ // validate
+ _fillErrorListener(STRONG_MODE_ERRORS);
+
+ var errors = errorListener.errors;
+ expect(errors.length, 1);
+ expect(errors[0].errorCode.name, "dev_compiler.StaticTypeError");
+ }
}
@reflectiveTest
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index 78f42de..2cd5f8a 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -16,18 +16,8 @@
* [libtour]: http://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html
*/
class Uri {
- // The host name of the URI.
- // Set to `null` if there is no authority in a URI.
- final String _host;
- // The port. Set to null if there is no port. Normalized to null if
- // the port is the default port for the scheme.
- // Set to the value of the default port if an empty port was supplied.
- int _port;
- // The path. Always non-null.
- String _path;
-
/**
- * Returns the scheme component.
+ * The scheme component of the URI.
*
* Returns the empty string if there is no scheme component.
*
@@ -39,6 +29,213 @@
final String scheme;
/**
+ * The user-info part of the authority.
+ *
+ * Does not distinguish between an empty user-info and an absent one.
+ * The value is always non-null.
+ * Is considered absent if [_host] is `null`.
+ */
+ final String _userInfo;
+
+ /**
+ * The host name of the URI.
+ *
+ * Set to `null` if there is no authority in the URI.
+ * The host name is the only mandatory part of an authority, so we use
+ * it to mark whether an authority part was present or not.
+ */
+ final String _host;
+
+ /**
+ * The port number part of the authority.
+ *
+ * The port. Set to null if there is no port. Normalized to null if
+ * the port is the default port for the scheme.
+ */
+ int _port;
+
+ /**
+ * The path of the URI.
+ *
+ * Always non-null.
+ */
+ String _path;
+
+ // The query content, or null if there is no query.
+ final String _query;
+
+ // The fragment content, or null if there is no fragment.
+ final String _fragment;
+
+ /**
+ * Cache the computed return value of [pathSegements].
+ */
+ List<String> _pathSegments;
+
+ /**
+ * Cache the computed return value of [queryParameters].
+ */
+ Map<String, String> _queryParameters;
+
+ /// Internal non-verifying constructor. Only call with validated arguments.
+ Uri._internal(this.scheme,
+ this._userInfo,
+ this._host,
+ this._port,
+ this._path,
+ this._query,
+ this._fragment);
+
+ /**
+ * Creates a new URI from its components.
+ *
+ * Each component is set through a named argument. Any number of
+ * components can be provided. The [path] and [query] components can be set
+ * using either of two different named arguments.
+ *
+ * The scheme component is set through [scheme]. The scheme is
+ * normalized to all lowercase letters. If the scheme is omitted or empty,
+ * the URI will not have a scheme part.
+ *
+ * The user info part of the authority component is set through
+ * [userInfo]. It defaults to the empty string, which will be omitted
+ * from the string representation of the URI.
+ *
+ * The host part of the authority component is set through
+ * [host]. The host can either be a hostname, an IPv4 address or an
+ * IPv6 address, contained in '[' and ']'. If the host contains a
+ * ':' character, the '[' and ']' are added if not already provided.
+ * The host is normalized to all lowercase letters.
+ *
+ * The port part of the authority component is set through
+ * [port].
+ * If [port] is omitted or `null`, it implies the default port for
+ * the URI's scheme, and is equivalent to passing that port explicitly.
+ * The recognized schemes, and their default ports, are "http" (80) and
+ * "https" (443). All other schemes are considered as having zero as the
+ * default port.
+ *
+ * If any of `userInfo`, `host` or `port` are provided,
+ * the URI will have an autority according to [hasAuthority].
+ *
+ * The path component is set through either [path] or
+ * [pathSegments]. When [path] is used, it should be a valid URI path,
+ * but invalid characters, except the general delimiters ':/@[]?#',
+ * will be escaped if necessary.
+ * When [pathSegments] is used, each of the provided segments
+ * is first percent-encoded and then joined using the forward slash
+ * separator. The percent-encoding of the path segments encodes all
+ * characters except for the unreserved characters and the following
+ * list of characters: `!$&'()*+,;=:@`. If the other components
+ * calls for an absolute path a leading slash `/` is prepended if
+ * not already there.
+ *
+ * The query component is set through either [query] or
+ * [queryParameters]. When [query] is used the provided string should
+ * be a valid URI query, but invalid characters other than general delimiters,
+ * will be escaped if necessary.
+ * When [queryParameters] is used the query is built from the
+ * provided map. Each key and value in the map is percent-encoded
+ * and joined using equal and ampersand characters. The
+ * percent-encoding of the keys and values encodes all characters
+ * except for the unreserved characters.
+ * If `query` is the empty string, it is equivalent to omitting it.
+ * To have an actual empty query part,
+ * use an empty list for `queryParameters`.
+ * If both `query` and `queryParameters` are omitted or `null`, the
+ * URI will have no query part.
+ *
+ * The fragment component is set through [fragment].
+ * It should be a valid URI fragment, but invalid characters other than
+ * general delimiters, will be escaped if necessary.
+ * If `fragment` is omitted or `null`, the URI will have no fragment part.
+ */
+ factory Uri({String scheme : "",
+ String userInfo : "",
+ String host,
+ int port,
+ String path,
+ Iterable<String> pathSegments,
+ String query,
+ Map<String, String> queryParameters,
+ String fragment}) {
+ scheme = _makeScheme(scheme, 0, _stringOrNullLength(scheme));
+ userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo));
+ host = _makeHost(host, 0, _stringOrNullLength(host), false);
+ // Special case this constructor for backwards compatibility.
+ if (query == "") query = null;
+ query = _makeQuery(query, 0, _stringOrNullLength(query), queryParameters);
+ fragment = _makeFragment(fragment, 0, _stringOrNullLength(fragment));
+ port = _makePort(port, scheme);
+ bool isFile = (scheme == "file");
+ if (host == null &&
+ (userInfo.isNotEmpty || port != null || isFile)) {
+ host = "";
+ }
+ bool hasAuthority = (host != null);
+ path = _makePath(path, 0, _stringOrNullLength(path), pathSegments,
+ scheme, hasAuthority);
+ if (scheme.isEmpty && host == null && !path.startsWith('/')) {
+ path = _normalizeRelativePath(path);
+ } else {
+ path = _removeDotSegments(path);
+ }
+ return new Uri._internal(scheme, userInfo, host, port,
+ path, query, fragment);
+ }
+
+ /**
+ * Creates a new `http` URI from authority, path and query.
+ *
+ * Examples:
+ *
+ * ```
+ * // http://example.org/path?q=dart.
+ * new Uri.http("google.com", "/search", { "q" : "dart" });
+ *
+ * // http://user:pass@localhost:8080
+ * new Uri.http("user:pass@localhost:8080", "");
+ *
+ * // http://example.org/a%20b
+ * new Uri.http("example.org", "a b");
+ *
+ * // http://example.org/a%252F
+ * new Uri.http("example.org", "/a%2F");
+ * ```
+ *
+ * The `scheme` is always set to `http`.
+ *
+ * The `userInfo`, `host` and `port` components are set from the
+ * [authority] argument. If `authority` is `null` or empty,
+ * the created `Uri` will have no authority, and will not be directly usable
+ * as an HTTP URL, which must have a non-empty host.
+ *
+ * The `path` component is set from the [unencodedPath]
+ * argument. The path passed must not be encoded as this constructor
+ * encodes the path.
+ *
+ * The `query` component is set from the optional [queryParameters]
+ * argument.
+ */
+ factory Uri.http(String authority,
+ String unencodedPath,
+ [Map<String, String> queryParameters]) {
+ return _makeHttpUri("http", authority, unencodedPath, queryParameters);
+ }
+
+ /**
+ * Creates a new `https` URI from authority, path and query.
+ *
+ * This constructor is the same as [Uri.http] except for the scheme
+ * which is set to `https`.
+ */
+ factory Uri.https(String authority,
+ String unencodedPath,
+ [Map<String, String> queryParameters]) {
+ return _makeHttpUri("https", authority, unencodedPath, queryParameters);
+ }
+
+ /**
* Returns the authority component.
*
* The authority is formatted from the [userInfo], [host] and [port]
@@ -54,14 +251,6 @@
}
/**
- * The user-info part of the authority.
- *
- * Does not distinguish between an empty user-info and an absent one.
- * The value is always non-null.
- */
- final String _userInfo;
-
- /**
* Returns the user info part of the authority component.
*
* Returns the empty string if there is no user info in the
@@ -118,9 +307,6 @@
*/
String get path => _path;
- // The query content, or null if there is no query.
- final String _query;
-
/**
* Returns the query component. The returned query is encoded. To get
* direct access to the decoded query use [queryParameters].
@@ -129,9 +315,6 @@
*/
String get query => (_query == null) ? "" : _query;
- // The fragment content, or null if there is no fragment.
- final String _fragment;
-
/**
* Returns the fragment identifier component.
*
@@ -141,16 +324,6 @@
String get fragment => (_fragment == null) ? "" : _fragment;
/**
- * Cache the computed return value of [pathSegements].
- */
- List<String> _pathSegments;
-
- /**
- * Cache the computed return value of [queryParameters].
- */
- Map<String, String> _queryParameters;
-
- /**
* Creates a new `Uri` object by parsing a URI string.
*
* If [start] and [end] are provided, only the substring from `start`
@@ -415,164 +588,6 @@
throw new FormatException(message, uri, index);
}
- /// Internal non-verifying constructor. Only call with validated arguments.
- Uri._internal(this.scheme,
- this._userInfo,
- this._host,
- this._port,
- this._path,
- this._query,
- this._fragment);
-
- /**
- * Creates a new URI from its components.
- *
- * Each component is set through a named argument. Any number of
- * components can be provided. The [path] and [query] components can be set
- * using either of two different named arguments.
- *
- * The scheme component is set through [scheme]. The scheme is
- * normalized to all lowercase letters. If the scheme is omitted or empty,
- * the URI will not have a scheme part.
- *
- * The user info part of the authority component is set through
- * [userInfo]. It defaults to the empty string, which will be omitted
- * from the string representation of the URI.
- *
- * The host part of the authority component is set through
- * [host]. The host can either be a hostname, an IPv4 address or an
- * IPv6 address, contained in '[' and ']'. If the host contains a
- * ':' character, the '[' and ']' are added if not already provided.
- * The host is normalized to all lowercase letters.
- *
- * The port part of the authority component is set through
- * [port].
- * If [port] is omitted or `null`, it implies the default port for
- * the URI's scheme, and is equivalent to passing that port explicitly.
- * The recognized schemes, and their default ports, are "http" (80) and
- * "https" (443). All other schemes are considered as having zero as the
- * default port.
- *
- * If any of `userInfo`, `host` or `port` are provided,
- * the URI will have an autority according to [hasAuthority].
- *
- * The path component is set through either [path] or
- * [pathSegments]. When [path] is used, it should be a valid URI path,
- * but invalid characters, except the general delimiters ':/@[]?#',
- * will be escaped if necessary.
- * When [pathSegments] is used, each of the provided segments
- * is first percent-encoded and then joined using the forward slash
- * separator. The percent-encoding of the path segments encodes all
- * characters except for the unreserved characters and the following
- * list of characters: `!$&'()*+,;=:@`. If the other components
- * calls for an absolute path a leading slash `/` is prepended if
- * not already there.
- *
- * The query component is set through either [query] or
- * [queryParameters]. When [query] is used the provided string should
- * be a valid URI query, but invalid characters other than general delimiters,
- * will be escaped if necessary.
- * When [queryParameters] is used the query is built from the
- * provided map. Each key and value in the map is percent-encoded
- * and joined using equal and ampersand characters. The
- * percent-encoding of the keys and values encodes all characters
- * except for the unreserved characters.
- * If `query` is the empty string, it is equivalent to omitting it.
- * To have an actual empty query part,
- * use an empty list for `queryParameters`.
- * If both `query` and `queryParameters` are omitted or `null`, the
- * URI will have no query part.
- *
- * The fragment component is set through [fragment].
- * It should be a valid URI fragment, but invalid characters other than
- * general delimiters, will be escaped if necessary.
- * If `fragment` is omitted or `null`, the URI will have no fragment part.
- */
- factory Uri({String scheme : "",
- String userInfo : "",
- String host,
- int port,
- String path,
- Iterable<String> pathSegments,
- String query,
- Map<String, String> queryParameters,
- String fragment}) {
- scheme = _makeScheme(scheme, 0, _stringOrNullLength(scheme));
- userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo));
- host = _makeHost(host, 0, _stringOrNullLength(host), false);
- // Special case this constructor for backwards compatibility.
- if (query == "") query = null;
- query = _makeQuery(query, 0, _stringOrNullLength(query), queryParameters);
- fragment = _makeFragment(fragment, 0, _stringOrNullLength(fragment));
- port = _makePort(port, scheme);
- bool isFile = (scheme == "file");
- if (host == null &&
- (userInfo.isNotEmpty || port != null || isFile)) {
- host = "";
- }
- bool hasAuthority = (host != null);
- path = _makePath(path, 0, _stringOrNullLength(path), pathSegments,
- scheme, hasAuthority);
- if (scheme.isEmpty && host == null && !path.startsWith('/')) {
- path = _normalizeRelativePath(path);
- } else {
- path = _removeDotSegments(path);
- }
- return new Uri._internal(scheme, userInfo, host, port,
- path, query, fragment);
- }
-
- /**
- * Creates a new `http` URI from authority, path and query.
- *
- * Examples:
- *
- * ```
- * // http://example.org/path?q=dart.
- * new Uri.http("google.com", "/search", { "q" : "dart" });
- *
- * // http://user:pass@localhost:8080
- * new Uri.http("user:pass@localhost:8080", "");
- *
- * // http://example.org/a%20b
- * new Uri.http("example.org", "a b");
- *
- * // http://example.org/a%252F
- * new Uri.http("example.org", "/a%2F");
- * ```
- *
- * The `scheme` is always set to `http`.
- *
- * The `userInfo`, `host` and `port` components are set from the
- * [authority] argument. If `authority` is `null` or empty,
- * the created `Uri` will have no authority, and will not be directly usable
- * as an HTTP URL, which must have a non-empty host.
- *
- * The `path` component is set from the [unencodedPath]
- * argument. The path passed must not be encoded as this constructor
- * encodes the path.
- *
- * The `query` component is set from the optional [queryParameters]
- * argument.
- */
- factory Uri.http(String authority,
- String unencodedPath,
- [Map<String, String> queryParameters]) {
- return _makeHttpUri("http", authority, unencodedPath, queryParameters);
- }
-
- /**
- * Creates a new `https` URI from authority, path and query.
- *
- * This constructor is the same as [Uri.http] except for the scheme
- * which is set to `https`.
- */
- factory Uri.https(String authority,
- String unencodedPath,
- [Map<String, String> queryParameters]) {
- return _makeHttpUri("https", authority, unencodedPath, queryParameters);
- }
-
static Uri _makeHttpUri(String scheme,
String authority,
String unencodedPath,
@@ -938,7 +953,7 @@
if (userInfo != null) {
userInfo = _makeUserInfo(userInfo, 0, userInfo.length);
} else {
- userInfo = this.userInfo;
+ userInfo = this._userInfo;
}
if (port != null) {
port = _makePort(port, scheme);
@@ -952,7 +967,7 @@
if (host != null) {
host = _makeHost(host, 0, host.length, false);
} else if (this.hasAuthority) {
- host = this.host;
+ host = this._host;
} else if (userInfo.isNotEmpty || port != null || isFile) {
host = "";
}
@@ -962,7 +977,7 @@
path = _makePath(path, 0, _stringOrNullLength(path), pathSegments,
scheme, hasAuthority);
} else {
- path = this.path;
+ path = this._path;
if ((isFile || (hasAuthority && !path.isEmpty)) &&
!path.startsWith('/')) {
path = "/" + path;
@@ -971,14 +986,14 @@
if (query != null || queryParameters != null) {
query = _makeQuery(query, 0, _stringOrNullLength(query), queryParameters);
- } else if (this.hasQuery) {
- query = this.query;
+ } else {
+ query = this._query;
}
if (fragment != null) {
fragment = _makeFragment(fragment, 0, fragment.length);
- } else if (this.hasFragment) {
- fragment = this.fragment;
+ } else {
+ fragment = this._fragment;
}
return new Uri._internal(
@@ -992,7 +1007,8 @@
*/
Uri removeFragment() {
if (!this.hasFragment) return this;
- return new Uri._internal(scheme, userInfo, host, port, path, query, null);
+ return new Uri._internal(scheme, _userInfo, _host, _port,
+ _path, _query, null);
}
/**
diff --git a/tests/corelib/uri_test.dart b/tests/corelib/uri_test.dart
index 834cadc..fd281c5 100644
--- a/tests/corelib/uri_test.dart
+++ b/tests/corelib/uri_test.dart
@@ -7,13 +7,25 @@
import "package:expect/expect.dart";
import 'dart:convert';
-testUri(String uri, bool isAbsolute) {
- Expect.equals(isAbsolute, Uri.parse(uri).isAbsolute);
- Expect.stringEquals(uri, Uri.parse(uri).toString());
+testUri(String uriText, bool isAbsolute) {
+ var uri = Uri.parse(uriText);
+
+ Expect.equals(isAbsolute, uri.isAbsolute);
+ Expect.stringEquals(uriText, uri.toString());
// Test equals and hashCode members.
- Expect.equals(Uri.parse(uri), Uri.parse(uri));
- Expect.equals(Uri.parse(uri).hashCode, Uri.parse(uri).hashCode);
+ var uri2 = Uri.parse(uriText);
+ Expect.equals(uri, uri2);
+ Expect.equals(uri.hashCode, uri2.hashCode);
+
+ // Test that removeFragment doesn't change anything else.
+ if (uri.hasFragment) {
+ Expect.equals(Uri.parse(uriText.substring(0, uriText.indexOf('#'))),
+ uri.removeFragment());
+ } else {
+ Expect.equals(uri,
+ Uri.parse(uriText + "#fragment").removeFragment());
+ }
}
testEncodeDecode(String orig, String encoded) {
diff --git a/tools/VERSION b/tools/VERSION
index 2e0ad90..fb4794f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 13
PATCH 0
PRERELEASE 7
-PRERELEASE_PATCH 0
+PRERELEASE_PATCH 1