Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library analyzer.task.model; | |
| 6 | |
| 7 import 'dart:collection'; | |
| 8 | |
| 9 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask; | |
| 10 import 'package:analyzer/src/generated/java_engine.dart'; | |
| 11 import 'package:analyzer/src/generated/source.dart'; | |
| 12 import 'package:analyzer/src/task/model.dart'; | |
| 13 | |
| 14 /** | |
| 15 * A function that takes an analysis [context] and an analysis [target] and | |
| 16 * returns an analysis task. Such functions are passed to a [TaskDescriptor] to | |
| 17 * be used to create the described task. | |
| 18 */ | |
| 19 typedef AnalysisTask BuildTask(AnalysisContext context, AnalysisTarget target); | |
|
Paul Berry
2015/01/20 23:34:53
Consider renaming to "TaskBuilder" so that the typ
| |
| 20 | |
| 21 /** | |
| 22 * A function that takes the target for which a task will produce results and | |
| 23 * returns a map from input names to descriptions of the analysis results needed | |
| 24 * by the task in order for the task to be performed. Such functions are passed | |
| 25 * to a [TaskDescriptor] to be used to determine the inputs needed by the task. | |
| 26 */ | |
| 27 typedef Map<String, TaskInput> CreateTaskInputs(AnalysisTarget target); | |
|
Paul Berry
2015/01/20 23:34:53
Similarly, consider renaming to "InputBuilder".
| |
| 28 | |
| 29 /** | |
| 30 * An object with which an analysis result can be associated. | |
| 31 * | |
| 32 * Clients are allowed to subtype this class when creating new kinds of targets. | |
| 33 * Instances of this type are used in hashed data structures, so subtypes are | |
| 34 * required to correctly implement [==] and [hashCode]. | |
| 35 */ | |
| 36 abstract class AnalysisTarget { | |
| 37 /** | |
| 38 * Return the source associated with this target, or `null` if this target is | |
| 39 * not associated with a source. | |
| 40 */ | |
| 41 Source get source; | |
| 42 } | |
| 43 | |
| 44 /** | |
| 45 * An object used to compute one or more analysis results associated with a | |
| 46 * single target. | |
| 47 * | |
| 48 * Clients are expected to extend this class when creating new tasks. | |
| 49 */ | |
| 50 abstract class AnalysisTask { | |
| 51 /** | |
| 52 * A table mapping the types of analysis tasks to stopwatches used to compute | |
| 53 * how much time was spent executing each kind of task. | |
| 54 */ | |
| 55 static final Map<Type, Stopwatch> stopwatchMap = | |
| 56 new HashMap<Type, Stopwatch>(); | |
| 57 | |
| 58 /** | |
| 59 * The context in which the task is to be performed. | |
| 60 */ | |
| 61 final AnalysisContext context; | |
| 62 | |
| 63 /** | |
| 64 * The target for which result values are being produced. | |
| 65 */ | |
| 66 final AnalysisTarget target; | |
| 67 | |
| 68 /** | |
| 69 * A table mapping input names to input values. | |
| 70 */ | |
| 71 Map<String, dynamic> inputs; | |
| 72 | |
| 73 /** | |
| 74 * A table mapping result descriptors whose values are produced by this task | |
| 75 * to the values that were produced. | |
| 76 */ | |
| 77 Map<ResultDescriptor, dynamic> outputs = | |
| 78 new HashMap<ResultDescriptor, dynamic>(); | |
| 79 | |
| 80 /** | |
| 81 * The exception that was thrown while performing this task, or `null` if the | |
| 82 * task completed successfully. | |
| 83 */ | |
| 84 CaughtException thrownException; | |
|
Paul Berry
2015/01/20 23:34:53
I'm not sure the word "thrown" adds any meaning he
Brian Wilkerson
2015/01/26 04:54:51
Done
| |
| 85 | |
| 86 /** | |
| 87 * Initialize a newly created task to perform analysis within the given | |
| 88 * [context] in order to produce results for the given [target]. | |
| 89 */ | |
| 90 AnalysisTask(this.context, this.target); | |
| 91 | |
| 92 /** | |
| 93 * Return a textual description of this task. | |
| 94 */ | |
| 95 String get description; | |
| 96 | |
| 97 /** | |
| 98 * Return the source associated with this task's target, or `null` if the | |
| 99 * target is not associated with a source. | |
| 100 */ | |
| 101 Source get source => target.source; | |
|
Paul Berry
2015/01/20 23:34:53
Consider removing this getter. It doesn't add a h
Brian Wilkerson
2015/01/26 04:54:51
Done
| |
| 102 | |
| 103 /** | |
| 104 * Perform this analysis task, protected by an exception handler. | |
| 105 * | |
| 106 * This method should throw an [AnalysisException] if an exception occurs | |
| 107 * while performing the task. If other kinds of exceptions are thrown they | |
| 108 * will be wrapped in an [AnalysisException]. | |
| 109 * | |
| 110 * If no exception is thrown, this method must fully populate the [outputs] | |
| 111 * map (have a key/value pair for each result that this task is expected to | |
| 112 * produce). | |
| 113 */ | |
| 114 void internalPerform(); | |
| 115 | |
| 116 /** | |
| 117 * Perform this analysis task. When this method returns, either the [outputs] | |
| 118 * map should be fully populated (have a key/value pair for each result that | |
| 119 * this task is expected to produce) or the [thrownException] should be set. | |
| 120 * | |
| 121 * Clients should not override this method. | |
| 122 */ | |
| 123 void perform() { | |
| 124 try { | |
| 125 safelyPerform(); | |
| 126 } on AnalysisException catch (exception, stackTrace) { | |
| 127 thrownException = new CaughtException(exception, stackTrace); | |
| 128 AnalysisEngine.instance.logger.logInformation( | |
| 129 "Task failed: ${description}", | |
| 130 thrownException); | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 /** | |
| 135 * Perform this analysis task, ensuring that all exceptions are wrapped in an | |
| 136 * [AnalysisException]. | |
| 137 * | |
| 138 * Clients should not override this method. | |
| 139 */ | |
| 140 void safelyPerform() { | |
|
Paul Berry
2015/01/20 23:34:53
Is this method ever meant to be called by clients,
Brian Wilkerson
2015/01/26 04:54:51
It also changes what is being measures by the stop
| |
| 141 try { | |
| 142 Stopwatch stopwatch = stopwatchMap[runtimeType]; | |
| 143 if (stopwatch == null) { | |
| 144 stopwatch = new Stopwatch(); | |
| 145 stopwatchMap[runtimeType] = stopwatch; | |
| 146 } | |
| 147 stopwatch.start(); | |
| 148 try { | |
| 149 internalPerform(); | |
| 150 } finally { | |
| 151 stopwatch.stop(); | |
| 152 } | |
| 153 } on AnalysisException catch (exception) { | |
| 154 rethrow; | |
| 155 } catch (exception, stackTrace) { | |
| 156 throw new AnalysisException( | |
| 157 'Unexpected exception while performing $description', | |
| 158 new CaughtException(exception, stackTrace)); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 @override | |
| 163 String toString() => description; | |
| 164 } | |
| 165 | |
| 166 /** | |
| 167 * A [ResultDescriptor] that denotes an analysis result that is a union of | |
| 168 * one or more other results. | |
| 169 * | |
| 170 * Clients are not expected to subtype this class. | |
| 171 */ | |
| 172 abstract class ContributionPoint<V> extends ResultDescriptor<V> { | |
|
Paul Berry
2015/01/20 23:34:53
As discussed in person, consider making Contributi
Brian Wilkerson
2015/01/26 04:54:51
I like the idea, but it leads to a type warning th
| |
| 173 /** | |
| 174 * Initialize a newly created contribution point to have the given [name]. | |
| 175 */ | |
| 176 factory ContributionPoint(String name) = ContributionPointImpl; | |
| 177 | |
| 178 /** | |
| 179 * Return a list containing the descriptors of the results that are unioned | |
| 180 * together to comprise the value of this result. | |
| 181 * | |
| 182 * Clients must not modify the returned list. | |
| 183 */ | |
| 184 List<ResultDescriptor<V>> get contributors; | |
| 185 } | |
| 186 | |
| 187 /** | |
| 188 * A description of an analysis result that can be computed by an [AnalysisTask] . | |
| 189 * | |
| 190 * Clients are not expected to subtype this class. | |
| 191 */ | |
| 192 abstract class ResultDescriptor<V> { | |
| 193 /** | |
| 194 * Initialize a newly created analysis result to have the given [name]. If a | |
| 195 * contribution point is specified, then this result will contribute to it. | |
| 196 */ | |
| 197 factory ResultDescriptor(String name, {ContributionPoint contributesTo}) = | |
| 198 ResultDescriptorImpl; | |
| 199 | |
| 200 /** | |
| 201 * Return a task input that can be used to compute this result for the given | |
| 202 * [target]. | |
| 203 */ | |
| 204 TaskInput<V> inputFor(AnalysisTarget target); | |
| 205 } | |
| 206 | |
| 207 /** | |
| 208 * A description of an [AnalysisTask]. | |
| 209 */ | |
| 210 abstract class TaskDescriptor { | |
| 211 /** | |
| 212 * Initialize a newly created task descriptor to have the given [name] and to | |
| 213 * describe a task that takes the inputs built using the given [inputBuilder], | |
| 214 * and produces the given [results]. The [buildTask] will be used to create | |
| 215 * the instance of [AnalysisTask] thusly described. | |
| 216 */ | |
| 217 factory TaskDescriptor(String name, BuildTask buildTask, | |
| 218 CreateTaskInputs inputBuilder, List<ResultDescriptor> results) = | |
| 219 TaskDescriptorImpl; | |
| 220 | |
| 221 /** | |
| 222 * Return the builder used to build the inputs to the task. | |
| 223 */ | |
| 224 CreateTaskInputs get createTaskInputs; | |
| 225 | |
| 226 /** | |
| 227 * Return a list of the analysis results that will be computed by this task. | |
| 228 */ | |
| 229 List<ResultDescriptor> get results; | |
| 230 | |
| 231 /** | |
| 232 * Create and return a task that is described by this descriptor that can be | |
| 233 * used to compute results based on the given [inputs]. | |
| 234 */ | |
| 235 AnalysisTask createTask(AnalysisContext context, AnalysisTarget target, | |
| 236 Map<String, dynamic> inputs); | |
| 237 } | |
| 238 | |
| 239 /** | |
| 240 * A description of an input to an [AnalysisTask] that can be used to compute | |
| 241 * that input. | |
| 242 * | |
| 243 * Clients are not expected to subtype this class. | |
| 244 */ | |
| 245 abstract class TaskInput<V> { | |
| 246 /** | |
| 247 * Create and return a builder that can be used to build this task input. | |
| 248 */ | |
| 249 TaskInputBuilder<V> createBuilder(); | |
| 250 } | |
| 251 | |
| 252 /** | |
| 253 * An object used to build the value associated with a single [TaskInput]. | |
| 254 * | |
| 255 * All builders work by requesting one or more results (each result being | |
| 256 * associated with a target). The interaction pattern is modeled after the class | |
| 257 * [Iterator], in which the method [moveNext] is invoked to move from one result | |
| 258 * request to the next. The getters [currentResult] and [currentTarget] are used | |
| 259 * to get the result and target of the current request. The value of the result | |
| 260 * must be supplied using the [currentValue] setter before [moveNext] can be | |
| 261 * invoked to move to the next request. When [moveNext] returns `false`, | |
| 262 * indicating that there are no more requests, the method [inputValue] can be | |
| 263 * used to access the value of the input that was built. | |
| 264 * | |
| 265 * Clients are not expected to subtype this class. | |
| 266 */ | |
| 267 abstract class TaskInputBuilder<V> { | |
| 268 /** | |
| 269 * Return the result that needs to be computed, or `null` if [moveNext] has | |
| 270 * not been invoked or if the last invocation of [moveNext] returned `false`. | |
| 271 */ | |
| 272 ResultDescriptor get currentResult; | |
| 273 | |
| 274 /** | |
| 275 * Return the target for which the result needs to be computed, or `null` if | |
| 276 * [moveNext] has not been invoked or if the last invocation of [moveNext] | |
| 277 * returned `false`. | |
| 278 */ | |
| 279 AnalysisTarget get currentTarget; | |
| 280 | |
| 281 /** | |
| 282 * Set the [value] that was computed for the current result. | |
| 283 * | |
| 284 * Throws a [StateError] if [moveNext] has not been invoked or if the last | |
| 285 * invocation of [moveNext] returned `false`. | |
| 286 */ | |
| 287 void set currentValue(Object value); | |
| 288 | |
| 289 /** | |
| 290 * Return the [value] that was computed by this builder. | |
| 291 * | |
| 292 * Throws a [StateError] if [moveNext] has not been invoked or if the last | |
| 293 * invocation of [moveNext] returned `true`. | |
| 294 */ | |
| 295 V get inputValue; | |
| 296 | |
| 297 /** | |
| 298 * Move to the next result that needs to be computed in order to build the | |
| 299 * inputs for a task. Return `true` if there is another result that needs to | |
| 300 * be computed, or `false` if the inputs have been computed. | |
| 301 * | |
| 302 * It is safe to invoke [moveNext] after it has returned `false`. In this case | |
| 303 * [moveNext] has no effect and will again return `false`. | |
| 304 * | |
| 305 * Throws a [StateError] if the value of the current result has not been | |
| 306 * provided using [currentValue]. | |
| 307 */ | |
| 308 bool moveNext(); | |
| 309 } | |
| OLD | NEW |