Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: pkg/analyzer/lib/src/task/dart.dart

Issue 1029953002: Task: BuildClassConstructorsTask. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: add TODO Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/analyzer/lib/src/generated/element.dart ('k') | pkg/analyzer/test/src/task/dart_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/element.dart ('k') | pkg/analyzer/test/src/task/dart_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698