Chromium Code Reviews| 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) { | |
|
Paul Berry
2015/03/24 20:10:17
I think this is going to cause a problem in the lo
scheglov
2015/03/24 21:17:15
I will add TODO for now.
We need to discuss it whe
| |
| 303 DartType superType = classElement.supertype; | |
| 304 if (superType is InterfaceType) { | |
| 305 if (classElement.isTypedef || classElement.mixins.isNotEmpty) { | |
| 306 ClassElement superElement = superType.element; | |
| 307 return <String, TaskInput>{ | |
| 308 SUPER_CONSTRUCTORS: CONSTRUCTORS.inputFor(superElement) | |
| 309 }; | |
| 310 } | |
| 311 } | |
| 312 // No implicit constructors, no inputs required. | |
| 313 return <String, TaskInput>{}; | |
| 314 } | |
| 315 | |
| 316 /** | |
| 317 * Create a [BuildClassConstructorsTask] based on the given | |
| 318 * [target] in the given [context]. | |
| 319 */ | |
| 320 static BuildClassConstructorsTask createTask( | |
| 321 AnalysisContext context, AnalysisTarget target) { | |
| 322 return new BuildClassConstructorsTask(context, target); | |
| 323 } | |
| 324 | |
| 325 /** | |
| 326 * Create an implicit constructor that is copied from the given | |
| 327 * [explicitConstructor], but that is in the given class. | |
| 328 * | |
| 329 * [classType] - the class in which the implicit constructor is defined. | |
| 330 * [explicitConstructor] - the constructor on which the implicit constructor | |
| 331 * is modeled. | |
| 332 * [parameterTypes] - the types to be replaced when creating parameters. | |
| 333 * [argumentTypes] - the types with which the parameters are to be replaced. | |
| 334 */ | |
| 335 static ConstructorElement _createImplicitContructor(InterfaceType classType, | |
| 336 ConstructorElement explicitConstructor, List<DartType> parameterTypes, | |
| 337 List<DartType> argumentTypes) { | |
| 338 ConstructorElementImpl implicitConstructor = | |
| 339 new ConstructorElementImpl(explicitConstructor.name, -1); | |
| 340 implicitConstructor.synthetic = true; | |
| 341 implicitConstructor.redirectedConstructor = explicitConstructor; | |
| 342 implicitConstructor.const2 = explicitConstructor.isConst; | |
| 343 implicitConstructor.returnType = classType; | |
| 344 List<ParameterElement> explicitParameters = explicitConstructor.parameters; | |
| 345 int count = explicitParameters.length; | |
| 346 if (count > 0) { | |
| 347 List<ParameterElement> implicitParameters = | |
| 348 new List<ParameterElement>(count); | |
| 349 for (int i = 0; i < count; i++) { | |
| 350 ParameterElement explicitParameter = explicitParameters[i]; | |
| 351 ParameterElementImpl implicitParameter = | |
| 352 new ParameterElementImpl(explicitParameter.name, -1); | |
| 353 implicitParameter.const3 = explicitParameter.isConst; | |
| 354 implicitParameter.final2 = explicitParameter.isFinal; | |
| 355 implicitParameter.parameterKind = explicitParameter.parameterKind; | |
| 356 implicitParameter.synthetic = true; | |
| 357 implicitParameter.type = | |
| 358 explicitParameter.type.substitute2(argumentTypes, parameterTypes); | |
| 359 implicitParameters[i] = implicitParameter; | |
| 360 } | |
| 361 implicitConstructor.parameters = implicitParameters; | |
| 362 } | |
| 363 FunctionTypeImpl type = new FunctionTypeImpl.con1(implicitConstructor); | |
| 364 type.typeArguments = classType.typeArguments; | |
| 365 implicitConstructor.type = type; | |
| 366 return implicitConstructor; | |
| 367 } | |
| 368 | |
| 369 /** | |
| 370 * Find all the constructors that should be forwarded from the given | |
| 371 * [superType], to the class or mixin application [classElement], | |
| 372 * and pass information about them to [callback]. | |
| 373 * | |
| 374 * Return true if some constructors were considered. (A false return value | |
| 375 * can only happen if the supeclass is a built-in type, in which case it | |
| 376 * can't be used as a mixin anyway). | |
| 377 */ | |
| 378 static bool _findForwardedConstructors(ClassElementImpl classElement, | |
| 379 InterfaceType superType, void callback( | |
| 380 ConstructorElement explicitConstructor, List<DartType> parameterTypes, | |
| 381 List<DartType> argumentTypes)) { | |
| 382 ClassElement superclassElement = superType.element; | |
| 383 List<ConstructorElement> constructors = superclassElement.constructors; | |
| 384 int count = constructors.length; | |
| 385 if (count == 0) { | |
| 386 return false; | |
| 387 } | |
| 388 List<DartType> parameterTypes = | |
| 389 TypeParameterTypeImpl.getTypes(superType.typeParameters); | |
| 390 List<DartType> argumentTypes = _getArgumentTypes(superType, parameterTypes); | |
| 391 for (int i = 0; i < count; i++) { | |
| 392 ConstructorElement explicitConstructor = constructors[i]; | |
| 393 if (!explicitConstructor.isFactory && | |
| 394 classElement.isSuperConstructorAccessible(explicitConstructor)) { | |
| 395 callback(explicitConstructor, parameterTypes, argumentTypes); | |
| 396 } | |
| 397 } | |
| 398 return true; | |
| 399 } | |
| 400 | |
| 401 /** | |
| 402 * Return a list of argument types that corresponds to the [parameterTypes] | |
| 403 * and that are derived from the type arguments of the given [superType]. | |
| 404 */ | |
| 405 static List<DartType> _getArgumentTypes( | |
| 406 InterfaceType superType, List<DartType> parameterTypes) { | |
| 407 DynamicTypeImpl dynamic = DynamicTypeImpl.instance; | |
| 408 int parameterCount = parameterTypes.length; | |
| 409 List<DartType> types = new List<DartType>(parameterCount); | |
| 410 if (superType == null) { | |
| 411 types = new List<DartType>.filled(parameterCount, dynamic); | |
| 412 } else { | |
| 413 List<DartType> typeArguments = superType.typeArguments; | |
| 414 int argumentCount = math.min(typeArguments.length, parameterCount); | |
| 415 for (int i = 0; i < argumentCount; i++) { | |
| 416 types[i] = typeArguments[i]; | |
| 417 } | |
| 418 for (int i = argumentCount; i < parameterCount; i++) { | |
| 419 types[i] = dynamic; | |
| 420 } | |
| 421 } | |
| 422 return types; | |
| 423 } | |
| 424 } | |
| 425 | |
| 426 /** | |
| 192 * A task that builds a compilation unit element for a single compilation unit. | 427 * A task that builds a compilation unit element for a single compilation unit. |
| 193 */ | 428 */ |
| 194 class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask { | 429 class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask { |
| 195 /** | 430 /** |
| 196 * The name of the input whose value is the line information for the | 431 * The name of the input whose value is the line information for the |
| 197 * compilation unit. | 432 * compilation unit. |
| 198 */ | 433 */ |
| 199 static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME'; | 434 static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME'; |
| 200 | 435 |
| 201 /** | 436 /** |
| (...skipping 1494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1696 } | 1931 } |
| 1697 | 1932 |
| 1698 /** | 1933 /** |
| 1699 * Create a [ScanDartTask] based on the given [target] in the given [context]. | 1934 * Create a [ScanDartTask] based on the given [target] in the given [context]. |
| 1700 */ | 1935 */ |
| 1701 static ScanDartTask createTask( | 1936 static ScanDartTask createTask( |
| 1702 AnalysisContext context, AnalysisTarget target) { | 1937 AnalysisContext context, AnalysisTarget target) { |
| 1703 return new ScanDartTask(context, target); | 1938 return new ScanDartTask(context, target); |
| 1704 } | 1939 } |
| 1705 } | 1940 } |
| OLD | NEW |