OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library analyzer.src.task.dart; | 5 library analyzer.src.task.dart; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 import 'dart:math' as math; | 8 import 'dart:math' as math; |
9 | 9 |
10 import 'package:analyzer/src/context/cache.dart'; | 10 import 'package:analyzer/src/context/cache.dart'; |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 * | 275 * |
276 * The list will be empty if there were no errors, but will not be `null`. | 276 * The list will be empty if there were no errors, but will not be `null`. |
277 * | 277 * |
278 * The result is only available for [Source]s representing a compilation unit. | 278 * The result is only available for [Source]s representing a compilation unit. |
279 */ | 279 */ |
280 final ListResultDescriptor<AnalysisError> PARSE_ERRORS = | 280 final ListResultDescriptor<AnalysisError> PARSE_ERRORS = |
281 new ListResultDescriptor<AnalysisError>( | 281 new ListResultDescriptor<AnalysisError>( |
282 'PARSE_ERRORS', AnalysisError.NO_ERRORS); | 282 'PARSE_ERRORS', AnalysisError.NO_ERRORS); |
283 | 283 |
284 /** | 284 /** |
| 285 * The names (resolved and not) referenced by a unit. |
| 286 * |
| 287 * The result is only available for [Source]s representing a compilation unit. |
| 288 */ |
| 289 final ResultDescriptor<ReferencedNames> REFERENCED_NAMES = |
| 290 new ResultDescriptor<ReferencedNames>('REFERENCED_NAMES', null); |
| 291 |
| 292 /** |
285 * The errors produced while resolving references. | 293 * The errors produced while resolving references. |
286 * | 294 * |
287 * The list will be empty if there were no errors, but will not be `null`. | 295 * The list will be empty if there were no errors, but will not be `null`. |
288 * | 296 * |
289 * The result is only available for [LibrarySpecificUnit]s. | 297 * The result is only available for [LibrarySpecificUnit]s. |
290 */ | 298 */ |
291 final ListResultDescriptor<AnalysisError> RESOLVE_REFERENCES_ERRORS = | 299 final ListResultDescriptor<AnalysisError> RESOLVE_REFERENCES_ERRORS = |
292 new ListResultDescriptor<AnalysisError>( | 300 new ListResultDescriptor<AnalysisError>( |
293 'RESOLVE_REFERENCES_ERRORS', AnalysisError.NO_ERRORS); | 301 'RESOLVE_REFERENCES_ERRORS', AnalysisError.NO_ERRORS); |
294 | 302 |
(...skipping 1613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1908 * Create a [ContainingLibrariesTask] based on the given [target] in the given | 1916 * Create a [ContainingLibrariesTask] based on the given [target] in the given |
1909 * [context]. | 1917 * [context]. |
1910 */ | 1918 */ |
1911 static ContainingLibrariesTask createTask( | 1919 static ContainingLibrariesTask createTask( |
1912 AnalysisContext context, AnalysisTarget target) { | 1920 AnalysisContext context, AnalysisTarget target) { |
1913 return new ContainingLibrariesTask(context, target); | 1921 return new ContainingLibrariesTask(context, target); |
1914 } | 1922 } |
1915 } | 1923 } |
1916 | 1924 |
1917 /** | 1925 /** |
| 1926 * The description for a change in a Dart source. |
| 1927 */ |
| 1928 class DartDelta extends Delta { |
| 1929 bool hasDirectiveChange = false; |
| 1930 |
| 1931 final Set<String> addedNames = new Set<String>(); |
| 1932 final Set<String> changedNames = new Set<String>(); |
| 1933 final Set<String> removedNames = new Set<String>(); |
| 1934 |
| 1935 final Set<Source> invalidatedSources = new Set<Source>(); |
| 1936 |
| 1937 DartDelta(Source source) : super(source) { |
| 1938 invalidatedSources.add(source); |
| 1939 } |
| 1940 |
| 1941 @override |
| 1942 bool affects(InternalAnalysisContext context, AnalysisTarget target, |
| 1943 ResultDescriptor descriptor) { |
| 1944 if (hasDirectiveChange) { |
| 1945 return true; |
| 1946 } |
| 1947 Source targetSource = null; |
| 1948 if (target is Source) { |
| 1949 targetSource = target; |
| 1950 } |
| 1951 if (target is LibrarySpecificUnit) { |
| 1952 targetSource = target.library; |
| 1953 } |
| 1954 if (target is Element) { |
| 1955 targetSource = target.source; |
| 1956 } |
| 1957 if (targetSource == source) { |
| 1958 return true; |
| 1959 } |
| 1960 if (targetSource != null) { |
| 1961 List<Source> librarySources = |
| 1962 context.getLibrariesContaining(targetSource); |
| 1963 for (Source librarySource in librarySources) { |
| 1964 AnalysisCache cache = context.analysisCache; |
| 1965 ReferencedNames referencedNames = |
| 1966 cache.getValue(librarySource, REFERENCED_NAMES); |
| 1967 if (referencedNames == null) { |
| 1968 return true; |
| 1969 } |
| 1970 referencedNames.addChangedElements(this); |
| 1971 if (referencedNames.isAffectedBy(this)) { |
| 1972 return true; |
| 1973 } |
| 1974 } |
| 1975 return false; |
| 1976 } |
| 1977 return true; |
| 1978 } |
| 1979 |
| 1980 void elementAdded(Element element) { |
| 1981 addedNames.add(element.name); |
| 1982 } |
| 1983 |
| 1984 void elementChanged(Element element) { |
| 1985 changedNames.add(element.name); |
| 1986 } |
| 1987 |
| 1988 void elementRemoved(Element element) { |
| 1989 removedNames.add(element.name); |
| 1990 } |
| 1991 |
| 1992 bool isNameAffected(String name) { |
| 1993 return addedNames.contains(name) || |
| 1994 changedNames.contains(name) || |
| 1995 removedNames.contains(name); |
| 1996 } |
| 1997 |
| 1998 bool nameChanged(String name) { |
| 1999 return changedNames.add(name); |
| 2000 } |
| 2001 } |
| 2002 |
| 2003 /** |
1918 * A task that merges all of the errors for a single source into a single list | 2004 * A task that merges all of the errors for a single source into a single list |
1919 * of errors. | 2005 * of errors. |
1920 */ | 2006 */ |
1921 class DartErrorsTask extends SourceBasedAnalysisTask { | 2007 class DartErrorsTask extends SourceBasedAnalysisTask { |
1922 /** | 2008 /** |
1923 * The name of the [BUILD_DIRECTIVES_ERRORS] input. | 2009 * The name of the [BUILD_DIRECTIVES_ERRORS] input. |
1924 */ | 2010 */ |
1925 static const String BUILD_DIRECTIVES_ERRORS_INPUT = 'BUILD_DIRECTIVES_ERRORS'; | 2011 static const String BUILD_DIRECTIVES_ERRORS_INPUT = 'BUILD_DIRECTIVES_ERRORS'; |
1926 | 2012 |
1927 /** | 2013 /** |
(...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2784 void _addPublicNames(CompilationUnitElement compilationUnit) { | 2870 void _addPublicNames(CompilationUnitElement compilationUnit) { |
2785 compilationUnit.accessors.forEach(_addIfPublic); | 2871 compilationUnit.accessors.forEach(_addIfPublic); |
2786 compilationUnit.enums.forEach(_addIfPublic); | 2872 compilationUnit.enums.forEach(_addIfPublic); |
2787 compilationUnit.functions.forEach(_addIfPublic); | 2873 compilationUnit.functions.forEach(_addIfPublic); |
2788 compilationUnit.functionTypeAliases.forEach(_addIfPublic); | 2874 compilationUnit.functionTypeAliases.forEach(_addIfPublic); |
2789 compilationUnit.types.forEach(_addIfPublic); | 2875 compilationUnit.types.forEach(_addIfPublic); |
2790 } | 2876 } |
2791 } | 2877 } |
2792 | 2878 |
2793 /** | 2879 /** |
| 2880 * Information about a library - which names it uses, which names it defines |
| 2881 * with their externally visible dependencies. |
| 2882 */ |
| 2883 class ReferencedNames { |
| 2884 final Set<String> names = new Set<String>(); |
| 2885 final Map<String, Set<String>> userToDependsOn = <String, Set<String>>{}; |
| 2886 |
| 2887 /** |
| 2888 * Updates [delta] by adding names that are changed in this library. |
| 2889 */ |
| 2890 void addChangedElements(DartDelta delta) { |
| 2891 bool hasProgress = true; |
| 2892 while (hasProgress) { |
| 2893 hasProgress = false; |
| 2894 userToDependsOn.forEach((user, dependencies) { |
| 2895 for (String dependency in dependencies) { |
| 2896 if (delta.isNameAffected(dependency)) { |
| 2897 if (delta.nameChanged(user)) { |
| 2898 hasProgress = true; |
| 2899 } |
| 2900 } |
| 2901 } |
| 2902 }); |
| 2903 } |
| 2904 } |
| 2905 |
| 2906 /** |
| 2907 * Returns `true` if the library described by this object is affected by |
| 2908 * the given [delta]. |
| 2909 */ |
| 2910 bool isAffectedBy(DartDelta delta) { |
| 2911 for (String name in names) { |
| 2912 if (delta.isNameAffected(name)) { |
| 2913 return true; |
| 2914 } |
| 2915 } |
| 2916 return false; |
| 2917 } |
| 2918 } |
| 2919 |
| 2920 /** |
| 2921 * A builder for creating [ReferencedNames]. |
| 2922 * |
| 2923 * TODO(scheglov) Record dependencies for all other top-level declarations. |
| 2924 */ |
| 2925 class ReferencedNamesBuilder extends RecursiveAstVisitor { |
| 2926 final ReferencedNames names; |
| 2927 int bodyLevel = 0; |
| 2928 Set<String> dependsOn; |
| 2929 |
| 2930 ReferencedNamesBuilder(this.names); |
| 2931 |
| 2932 ReferencedNames build(CompilationUnit unit) { |
| 2933 unit.accept(this); |
| 2934 return names; |
| 2935 } |
| 2936 |
| 2937 @override |
| 2938 visitBlockFunctionBody(BlockFunctionBody node) { |
| 2939 try { |
| 2940 bodyLevel++; |
| 2941 super.visitBlockFunctionBody(node); |
| 2942 } finally { |
| 2943 bodyLevel--; |
| 2944 } |
| 2945 } |
| 2946 |
| 2947 @override |
| 2948 visitClassDeclaration(ClassDeclaration node) { |
| 2949 dependsOn = new Set<String>(); |
| 2950 super.visitClassDeclaration(node); |
| 2951 names.userToDependsOn[node.name.name] = dependsOn; |
| 2952 dependsOn = null; |
| 2953 } |
| 2954 |
| 2955 @override |
| 2956 visitExpressionFunctionBody(ExpressionFunctionBody node) { |
| 2957 try { |
| 2958 bodyLevel++; |
| 2959 super.visitExpressionFunctionBody(node); |
| 2960 } finally { |
| 2961 bodyLevel--; |
| 2962 } |
| 2963 } |
| 2964 |
| 2965 @override |
| 2966 visitSimpleIdentifier(SimpleIdentifier node) { |
| 2967 if (!node.inDeclarationContext()) { |
| 2968 String name = node.name; |
| 2969 names.names.add(name); |
| 2970 if (dependsOn != null && bodyLevel == 0) { |
| 2971 dependsOn.add(name); |
| 2972 } |
| 2973 } |
| 2974 } |
| 2975 } |
| 2976 |
| 2977 /** |
2794 * A task that finishes resolution by requesting [RESOLVED_UNIT_NO_CONSTANTS] fo
r every | 2978 * A task that finishes resolution by requesting [RESOLVED_UNIT_NO_CONSTANTS] fo
r every |
2795 * unit in the libraries closure and produces [LIBRARY_ELEMENT]. | 2979 * unit in the libraries closure and produces [LIBRARY_ELEMENT]. |
2796 */ | 2980 */ |
2797 class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask { | 2981 class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask { |
2798 /** | 2982 /** |
2799 * The name of the [LIBRARY_ELEMENT6] input. | 2983 * The name of the [LIBRARY_ELEMENT6] input. |
2800 */ | 2984 */ |
2801 static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; | 2985 static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; |
2802 | 2986 |
2803 /** | 2987 /** |
| 2988 * The name of the [RESOLVED_UNIT6] input. |
| 2989 */ |
| 2990 static const String UNITS_INPUT = 'UNITS_INPUT'; |
| 2991 |
| 2992 /** |
2804 * The task descriptor describing this kind of task. | 2993 * The task descriptor describing this kind of task. |
2805 */ | 2994 */ |
2806 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( | 2995 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( |
2807 'ResolveLibraryReferencesTask', createTask, buildInputs, | 2996 'ResolveLibraryReferencesTask', createTask, buildInputs, |
2808 <ResultDescriptor>[LIBRARY_ELEMENT]); | 2997 <ResultDescriptor>[LIBRARY_ELEMENT, REFERENCED_NAMES]); |
2809 | 2998 |
2810 ResolveLibraryReferencesTask( | 2999 ResolveLibraryReferencesTask( |
2811 InternalAnalysisContext context, AnalysisTarget target) | 3000 InternalAnalysisContext context, AnalysisTarget target) |
2812 : super(context, target); | 3001 : super(context, target); |
2813 | 3002 |
2814 @override | 3003 @override |
2815 TaskDescriptor get descriptor => DESCRIPTOR; | 3004 TaskDescriptor get descriptor => DESCRIPTOR; |
2816 | 3005 |
2817 @override | 3006 @override |
2818 void internalPerform() { | 3007 void internalPerform() { |
| 3008 // |
| 3009 // Prepare inputs. |
| 3010 // |
2819 LibraryElement library = getRequiredInput(LIBRARY_INPUT); | 3011 LibraryElement library = getRequiredInput(LIBRARY_INPUT); |
| 3012 List<CompilationUnit> units = getRequiredInput(UNITS_INPUT); |
| 3013 // Compute referenced names. |
| 3014 ReferencedNames referencedNames = new ReferencedNames(); |
| 3015 for (CompilationUnit unit in units) { |
| 3016 new ReferencedNamesBuilder(referencedNames).build(unit); |
| 3017 } |
| 3018 // |
| 3019 // Record outputs. |
| 3020 // |
2820 outputs[LIBRARY_ELEMENT] = library; | 3021 outputs[LIBRARY_ELEMENT] = library; |
| 3022 outputs[REFERENCED_NAMES] = referencedNames; |
2821 } | 3023 } |
2822 | 3024 |
2823 /** | 3025 /** |
2824 * Return a map from the names of the inputs of this kind of task to the task | 3026 * Return a map from the names of the inputs of this kind of task to the task |
2825 * input descriptors describing those inputs for a task with the | 3027 * input descriptors describing those inputs for a task with the |
2826 * given [target]. | 3028 * given [target]. |
2827 */ | 3029 */ |
2828 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { | 3030 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
2829 Source source = target; | 3031 Source source = target; |
2830 return <String, TaskInput>{ | 3032 return <String, TaskInput>{ |
2831 LIBRARY_INPUT: LIBRARY_ELEMENT6.of(source), | 3033 LIBRARY_INPUT: LIBRARY_ELEMENT6.of(source), |
| 3034 UNITS_INPUT: UNITS.of(source).toList((Source unit) => |
| 3035 RESOLVED_UNIT6.of(new LibrarySpecificUnit(source, unit))), |
2832 'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE | 3036 'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE |
2833 .of(source) | 3037 .of(source) |
2834 .toMapOf(UNITS) | 3038 .toMapOf(UNITS) |
2835 .toFlattenList((Source library, Source unit) => | 3039 .toFlattenList((Source library, Source unit) => |
2836 RESOLVED_UNIT6.of(new LibrarySpecificUnit(library, unit))), | 3040 RESOLVED_UNIT6.of(new LibrarySpecificUnit(library, unit))), |
2837 }; | 3041 }; |
2838 } | 3042 } |
2839 | 3043 |
2840 /** | 3044 /** |
2841 * Create a [ResolveLibraryReferencesTask] based on the given [target] in | 3045 * Create a [ResolveLibraryReferencesTask] based on the given [target] in |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3050 | 3254 |
3051 /** | 3255 /** |
3052 * Return a map from the names of the inputs of this kind of task to the task | 3256 * Return a map from the names of the inputs of this kind of task to the task |
3053 * input descriptors describing those inputs for a task with the | 3257 * input descriptors describing those inputs for a task with the |
3054 * given [target]. | 3258 * given [target]. |
3055 */ | 3259 */ |
3056 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { | 3260 static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
3057 LibrarySpecificUnit unit = target; | 3261 LibrarySpecificUnit unit = target; |
3058 return <String, TaskInput>{ | 3262 return <String, TaskInput>{ |
3059 'importsExportNamespace': | 3263 'importsExportNamespace': |
3060 IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4), | 3264 IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4), |
3061 LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library), | 3265 LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library), |
3062 UNIT_INPUT: RESOLVED_UNIT2.of(unit), | 3266 UNIT_INPUT: RESOLVED_UNIT2.of(unit), |
3063 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request) | 3267 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request) |
3064 }; | 3268 }; |
3065 } | 3269 } |
3066 | 3270 |
3067 /** | 3271 /** |
3068 * Create a [ResolveUnitTypeNamesTask] based on the given [target] in | 3272 * Create a [ResolveUnitTypeNamesTask] based on the given [target] in |
3069 * the given [context]. | 3273 * the given [context]. |
3070 */ | 3274 */ |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3485 | 3689 |
3486 @override | 3690 @override |
3487 bool moveNext() { | 3691 bool moveNext() { |
3488 if (_newSources.isEmpty) { | 3692 if (_newSources.isEmpty) { |
3489 return false; | 3693 return false; |
3490 } | 3694 } |
3491 currentTarget = _newSources.removeLast(); | 3695 currentTarget = _newSources.removeLast(); |
3492 return true; | 3696 return true; |
3493 } | 3697 } |
3494 } | 3698 } |
OLD | NEW |