| 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 | 9 |
| 9 import 'package:analyzer/src/generated/ast.dart'; | 10 import 'package:analyzer/src/generated/ast.dart'; |
| 10 import 'package:analyzer/src/generated/element.dart'; | 11 import 'package:analyzer/src/generated/element.dart'; |
| 11 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask; | 12 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask; |
| 12 import 'package:analyzer/src/generated/error.dart'; | 13 import 'package:analyzer/src/generated/error.dart'; |
| 13 import 'package:analyzer/src/generated/java_engine.dart'; | 14 import 'package:analyzer/src/generated/java_engine.dart'; |
| 14 import 'package:analyzer/src/generated/parser.dart'; | 15 import 'package:analyzer/src/generated/parser.dart'; |
| 15 import 'package:analyzer/src/generated/resolver.dart'; | 16 import 'package:analyzer/src/generated/resolver.dart'; |
| 16 import 'package:analyzer/src/generated/scanner.dart'; | 17 import 'package:analyzer/src/generated/scanner.dart'; |
| 17 import 'package:analyzer/src/generated/sdk.dart'; | 18 import 'package:analyzer/src/generated/sdk.dart'; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS, | 61 'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS, |
| 61 contributesTo: DART_ERRORS); | 62 contributesTo: DART_ERRORS); |
| 62 | 63 |
| 63 /** | 64 /** |
| 64 * The [ClassElement]s of a [LibraryUnitTarget]. | 65 * The [ClassElement]s of a [LibraryUnitTarget]. |
| 65 */ | 66 */ |
| 66 final ResultDescriptor<List<ClassElement>> CLASS_ELEMENTS = | 67 final ResultDescriptor<List<ClassElement>> CLASS_ELEMENTS = |
| 67 new ResultDescriptor<List<ClassElement>>('CLASS_ELEMENTS', null); | 68 new ResultDescriptor<List<ClassElement>>('CLASS_ELEMENTS', null); |
| 68 | 69 |
| 69 /** | 70 /** |
| 71 * The [ConstructorElement]s of a [ClassElement]. |
| 72 */ |
| 73 final ResultDescriptor<List<ConstructorElement>> CONSTRUCTORS = |
| 74 new ResultDescriptor<List<ConstructorElement>>('CONSTRUCTORS', null); |
| 75 |
| 76 /** |
| 77 * The errors produced while building a [ClassElement] constructors. |
| 78 * |
| 79 * The list will be empty if there were no errors, but will not be `null`. |
| 80 * |
| 81 * The result is only available for targets representing a [ClassElement]. |
| 82 */ |
| 83 final ResultDescriptor<List<AnalysisError>> CONSTRUCTORS_ERRORS = |
| 84 new ResultDescriptor<List<AnalysisError>>( |
| 85 'CONSTRUCTORS_ERRORS', AnalysisError.NO_ERRORS); |
| 86 |
| 87 /** |
| 70 * The sources representing the export closure of a library. | 88 * The sources representing the export closure of a library. |
| 71 * | 89 * |
| 72 * The result is only available for targets representing a Dart library. | 90 * The result is only available for targets representing a Dart library. |
| 73 */ | 91 */ |
| 74 final ResultDescriptor<List<Source>> EXPORT_SOURCE_CLOSURE = | 92 final ResultDescriptor<List<Source>> EXPORT_SOURCE_CLOSURE = |
| 75 new ResultDescriptor<List<Source>>('EXPORT_SOURCE_CLOSURE', null); | 93 new ResultDescriptor<List<Source>>('EXPORT_SOURCE_CLOSURE', null); |
| 76 | 94 |
| 77 /** | 95 /** |
| 78 * The partial [LibraryElement] associated with a library. | 96 * The partial [LibraryElement] associated with a library. |
| 79 * | 97 * |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT4 = | 200 final ResultDescriptor<CompilationUnit> RESOLVED_UNIT4 = |
| 183 new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT4', null); | 201 new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT4', null); |
| 184 | 202 |
| 185 /** | 203 /** |
| 186 * The [TypeProvider] of the context. | 204 * The [TypeProvider] of the context. |
| 187 */ | 205 */ |
| 188 final ResultDescriptor<TypeProvider> TYPE_PROVIDER = | 206 final ResultDescriptor<TypeProvider> TYPE_PROVIDER = |
| 189 new ResultDescriptor<TypeProvider>('TYPE_PROVIDER', null); | 207 new ResultDescriptor<TypeProvider>('TYPE_PROVIDER', null); |
| 190 | 208 |
| 191 /** | 209 /** |
| 210 * A task that builds implicit constructors for a [ClassElement], or keeps |
| 211 * the existing explicit constructors if the class has them. |
| 212 */ |
| 213 class BuildClassConstructorsTask extends SourceBasedAnalysisTask { |
| 214 /** |
| 215 * The name of the [CONSTRUCTORS] input for the superclass. |
| 216 */ |
| 217 static const String SUPER_CONSTRUCTORS = 'SUPER_CONSTRUCTORS'; |
| 218 |
| 219 /** |
| 220 * The task descriptor describing this kind of task. |
| 221 */ |
| 222 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( |
| 223 'BuildConstructorsForClassTask', createTask, buildInputs, |
| 224 <ResultDescriptor>[CONSTRUCTORS, CONSTRUCTORS_ERRORS]); |
| 225 |
| 226 BuildClassConstructorsTask( |
| 227 InternalAnalysisContext context, AnalysisTarget target) |
| 228 : super(context, target); |
| 229 |
| 230 @override |
| 231 TaskDescriptor get descriptor => DESCRIPTOR; |
| 232 |
| 233 @override |
| 234 void internalPerform() { |
| 235 List<AnalysisError> errors = <AnalysisError>[]; |
| 236 // |
| 237 // Prepare inputs. |
| 238 // |
| 239 ClassElementImpl classElement = this.target; |
| 240 List<ConstructorElement> superConstructors = inputs[SUPER_CONSTRUCTORS]; |
| 241 DartType superType = classElement.supertype; |
| 242 ClassElement superElement = superType.element; |
| 243 // |
| 244 // Shortcut for ClassElement(s) without implicit constructors. |
| 245 // |
| 246 if (superConstructors == null) { |
| 247 outputs[CONSTRUCTORS] = classElement.constructors; |
| 248 outputs[CONSTRUCTORS_ERRORS] = AnalysisError.NO_ERRORS; |
| 249 return; |
| 250 } |
| 251 // |
| 252 // ClassTypeAlias |
| 253 // |
| 254 if (classElement.isTypedef) { |
| 255 List<ConstructorElement> implicitConstructors = |
| 256 new List<ConstructorElement>(); |
| 257 void callback(ConstructorElement explicitConstructor, |
| 258 List<DartType> parameterTypes, List<DartType> argumentTypes) { |
| 259 implicitConstructors.add(_createImplicitContructor(classElement.type, |
| 260 explicitConstructor, parameterTypes, argumentTypes)); |
| 261 } |
| 262 if (_findForwardedConstructors(classElement, superType, callback)) { |
| 263 if (implicitConstructors.isEmpty) { |
| 264 errors.add(new AnalysisError.con2(classElement.source, |
| 265 classElement.nameOffset, classElement.name.length, |
| 266 CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS, |
| 267 [superElement.name])); |
| 268 } else { |
| 269 classElement.constructors = implicitConstructors; |
| 270 } |
| 271 } |
| 272 outputs[CONSTRUCTORS] = classElement.constructors; |
| 273 outputs[CONSTRUCTORS_ERRORS] = errors; |
| 274 } |
| 275 // |
| 276 // ClassDeclaration |
| 277 // |
| 278 if (!classElement.isTypedef) { |
| 279 bool constructorFound = false; |
| 280 void callback(ConstructorElement explicitConstructor, |
| 281 List<DartType> parameterTypes, List<DartType> argumentTypes) { |
| 282 constructorFound = true; |
| 283 } |
| 284 if (_findForwardedConstructors(classElement, superType, callback) && |
| 285 !constructorFound) { |
| 286 SourceRange withRange = classElement.withClauseRange; |
| 287 errors.add(new AnalysisError.con2(classElement.source, withRange.offset, |
| 288 withRange.length, CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS, |
| 289 [superElement.name])); |
| 290 classElement.mixinErrorsReported = true; |
| 291 } |
| 292 outputs[CONSTRUCTORS] = classElement.constructors; |
| 293 outputs[CONSTRUCTORS_ERRORS] = errors; |
| 294 } |
| 295 } |
| 296 |
| 297 /** |
| 298 * Return a map from the names of the inputs of this kind of task to the task |
| 299 * input descriptors describing those inputs for a task with the |
| 300 * given [classElement]. |
| 301 */ |
| 302 static Map<String, TaskInput> buildInputs(ClassElement classElement) { |
| 303 // TODO(scheglov) Here we implicitly depend on LIBRARY_ELEMENT5, i.e. that |
| 304 // "supertype" for the "classElement" is set. |
| 305 // We need to make it an explicit dependency. |
| 306 DartType superType = classElement.supertype; |
| 307 if (superType is InterfaceType) { |
| 308 if (classElement.isTypedef || classElement.mixins.isNotEmpty) { |
| 309 ClassElement superElement = superType.element; |
| 310 return <String, TaskInput>{ |
| 311 SUPER_CONSTRUCTORS: CONSTRUCTORS.inputFor(superElement) |
| 312 }; |
| 313 } |
| 314 } |
| 315 // No implicit constructors, no inputs required. |
| 316 return <String, TaskInput>{}; |
| 317 } |
| 318 |
| 319 /** |
| 320 * Create a [BuildClassConstructorsTask] based on the given |
| 321 * [target] in the given [context]. |
| 322 */ |
| 323 static BuildClassConstructorsTask createTask( |
| 324 AnalysisContext context, AnalysisTarget target) { |
| 325 return new BuildClassConstructorsTask(context, target); |
| 326 } |
| 327 |
| 328 /** |
| 329 * Create an implicit constructor that is copied from the given |
| 330 * [explicitConstructor], but that is in the given class. |
| 331 * |
| 332 * [classType] - the class in which the implicit constructor is defined. |
| 333 * [explicitConstructor] - the constructor on which the implicit constructor |
| 334 * is modeled. |
| 335 * [parameterTypes] - the types to be replaced when creating parameters. |
| 336 * [argumentTypes] - the types with which the parameters are to be replaced. |
| 337 */ |
| 338 static ConstructorElement _createImplicitContructor(InterfaceType classType, |
| 339 ConstructorElement explicitConstructor, List<DartType> parameterTypes, |
| 340 List<DartType> argumentTypes) { |
| 341 ConstructorElementImpl implicitConstructor = |
| 342 new ConstructorElementImpl(explicitConstructor.name, -1); |
| 343 implicitConstructor.synthetic = true; |
| 344 implicitConstructor.redirectedConstructor = explicitConstructor; |
| 345 implicitConstructor.const2 = explicitConstructor.isConst; |
| 346 implicitConstructor.returnType = classType; |
| 347 List<ParameterElement> explicitParameters = explicitConstructor.parameters; |
| 348 int count = explicitParameters.length; |
| 349 if (count > 0) { |
| 350 List<ParameterElement> implicitParameters = |
| 351 new List<ParameterElement>(count); |
| 352 for (int i = 0; i < count; i++) { |
| 353 ParameterElement explicitParameter = explicitParameters[i]; |
| 354 ParameterElementImpl implicitParameter = |
| 355 new ParameterElementImpl(explicitParameter.name, -1); |
| 356 implicitParameter.const3 = explicitParameter.isConst; |
| 357 implicitParameter.final2 = explicitParameter.isFinal; |
| 358 implicitParameter.parameterKind = explicitParameter.parameterKind; |
| 359 implicitParameter.synthetic = true; |
| 360 implicitParameter.type = |
| 361 explicitParameter.type.substitute2(argumentTypes, parameterTypes); |
| 362 implicitParameters[i] = implicitParameter; |
| 363 } |
| 364 implicitConstructor.parameters = implicitParameters; |
| 365 } |
| 366 FunctionTypeImpl type = new FunctionTypeImpl.con1(implicitConstructor); |
| 367 type.typeArguments = classType.typeArguments; |
| 368 implicitConstructor.type = type; |
| 369 return implicitConstructor; |
| 370 } |
| 371 |
| 372 /** |
| 373 * Find all the constructors that should be forwarded from the given |
| 374 * [superType], to the class or mixin application [classElement], |
| 375 * and pass information about them to [callback]. |
| 376 * |
| 377 * Return true if some constructors were considered. (A false return value |
| 378 * can only happen if the supeclass is a built-in type, in which case it |
| 379 * can't be used as a mixin anyway). |
| 380 */ |
| 381 static bool _findForwardedConstructors(ClassElementImpl classElement, |
| 382 InterfaceType superType, void callback( |
| 383 ConstructorElement explicitConstructor, List<DartType> parameterTypes, |
| 384 List<DartType> argumentTypes)) { |
| 385 ClassElement superclassElement = superType.element; |
| 386 List<ConstructorElement> constructors = superclassElement.constructors; |
| 387 int count = constructors.length; |
| 388 if (count == 0) { |
| 389 return false; |
| 390 } |
| 391 List<DartType> parameterTypes = |
| 392 TypeParameterTypeImpl.getTypes(superType.typeParameters); |
| 393 List<DartType> argumentTypes = _getArgumentTypes(superType, parameterTypes); |
| 394 for (int i = 0; i < count; i++) { |
| 395 ConstructorElement explicitConstructor = constructors[i]; |
| 396 if (!explicitConstructor.isFactory && |
| 397 classElement.isSuperConstructorAccessible(explicitConstructor)) { |
| 398 callback(explicitConstructor, parameterTypes, argumentTypes); |
| 399 } |
| 400 } |
| 401 return true; |
| 402 } |
| 403 |
| 404 /** |
| 405 * Return a list of argument types that corresponds to the [parameterTypes] |
| 406 * and that are derived from the type arguments of the given [superType]. |
| 407 */ |
| 408 static List<DartType> _getArgumentTypes( |
| 409 InterfaceType superType, List<DartType> parameterTypes) { |
| 410 DynamicTypeImpl dynamic = DynamicTypeImpl.instance; |
| 411 int parameterCount = parameterTypes.length; |
| 412 List<DartType> types = new List<DartType>(parameterCount); |
| 413 if (superType == null) { |
| 414 types = new List<DartType>.filled(parameterCount, dynamic); |
| 415 } else { |
| 416 List<DartType> typeArguments = superType.typeArguments; |
| 417 int argumentCount = math.min(typeArguments.length, parameterCount); |
| 418 for (int i = 0; i < argumentCount; i++) { |
| 419 types[i] = typeArguments[i]; |
| 420 } |
| 421 for (int i = argumentCount; i < parameterCount; i++) { |
| 422 types[i] = dynamic; |
| 423 } |
| 424 } |
| 425 return types; |
| 426 } |
| 427 } |
| 428 |
| 429 /** |
| 192 * A task that builds a compilation unit element for a single compilation unit. | 430 * A task that builds a compilation unit element for a single compilation unit. |
| 193 */ | 431 */ |
| 194 class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask { | 432 class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask { |
| 195 /** | 433 /** |
| 196 * The name of the input whose value is the line information for the | 434 * The name of the input whose value is the line information for the |
| 197 * compilation unit. | 435 * compilation unit. |
| 198 */ | 436 */ |
| 199 static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME'; | 437 static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME'; |
| 200 | 438 |
| 201 /** | 439 /** |
| (...skipping 1494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1696 } | 1934 } |
| 1697 | 1935 |
| 1698 /** | 1936 /** |
| 1699 * Create a [ScanDartTask] based on the given [target] in the given [context]. | 1937 * Create a [ScanDartTask] based on the given [target] in the given [context]. |
| 1700 */ | 1938 */ |
| 1701 static ScanDartTask createTask( | 1939 static ScanDartTask createTask( |
| 1702 AnalysisContext context, AnalysisTarget target) { | 1940 AnalysisContext context, AnalysisTarget target) { |
| 1703 return new ScanDartTask(context, target); | 1941 return new ScanDartTask(context, target); |
| 1704 } | 1942 } |
| 1705 } | 1943 } |
| OLD | NEW |