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

Side by Side Diff: pkg/analyzer/lib/src/dart/element/member.dart

Issue 1525663003: Move the remainder of generated/element.dart into better locations (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years 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
OLDNEW
(Empty)
1 // Copyright (c) 2014, 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.src.dart.element.member;
6
7 import 'package:analyzer/dart/element/element.dart';
8 import 'package:analyzer/dart/element/type.dart';
9 import 'package:analyzer/src/dart/element/element.dart';
10 import 'package:analyzer/src/dart/element/type.dart';
11 import 'package:analyzer/src/generated/ast.dart';
12 import 'package:analyzer/src/generated/constant.dart'
13 show DartObject, EvaluationResultImpl;
14 import 'package:analyzer/src/generated/engine.dart'
15 show AnalysisContext, AnalysisEngine, AnalysisException;
16 import 'package:analyzer/src/generated/java_core.dart';
17 import 'package:analyzer/src/generated/java_engine.dart';
18 import 'package:analyzer/src/generated/source.dart';
19 import 'package:analyzer/src/generated/utilities_dart.dart';
20
21 /**
22 * A constructor element defined in a parameterized type where the values of the
23 * type parameters are known.
24 */
25 class ConstructorMember extends ExecutableMember implements ConstructorElement {
26 /**
27 * Initialize a newly created element to represent a constructor, based on the
28 * [baseElement], defined by the [definingType]. If [type] is passed, it
29 * represents the full type of the member, and will take precedence over
30 * the [definingType].
31 */
32 ConstructorMember(ConstructorElement baseElement, InterfaceType definingType,
33 [FunctionType type])
34 : super(baseElement, definingType, type);
35
36 @override
37 ConstructorElement get baseElement => super.baseElement as ConstructorElement;
38
39 @override
40 InterfaceType get definingType => super.definingType as InterfaceType;
41
42 @override
43 ClassElement get enclosingElement => baseElement.enclosingElement;
44
45 @override
46 bool get isConst => baseElement.isConst;
47
48 @override
49 bool get isDefaultConstructor => baseElement.isDefaultConstructor;
50
51 @override
52 bool get isFactory => baseElement.isFactory;
53
54 @override
55 int get nameEnd => baseElement.nameEnd;
56
57 @override
58 int get periodOffset => baseElement.periodOffset;
59
60 @override
61 ConstructorElement get redirectedConstructor =>
62 from(baseElement.redirectedConstructor, definingType);
63
64 @override
65 accept(ElementVisitor visitor) => visitor.visitConstructorElement(this);
66
67 @override
68 ConstructorDeclaration computeNode() => baseElement.computeNode();
69
70 @override
71 String toString() {
72 ConstructorElement baseElement = this.baseElement;
73 List<ParameterElement> parameters = this.parameters;
74 FunctionType type = this.type;
75 StringBuffer buffer = new StringBuffer();
76 buffer.write(baseElement.enclosingElement.displayName);
77 String name = displayName;
78 if (name != null && !name.isEmpty) {
79 buffer.write(".");
80 buffer.write(name);
81 }
82 buffer.write("(");
83 int parameterCount = parameters.length;
84 for (int i = 0; i < parameterCount; i++) {
85 if (i > 0) {
86 buffer.write(", ");
87 }
88 buffer.write(parameters[i]);
89 }
90 buffer.write(")");
91 if (type != null) {
92 buffer.write(ElementImpl.RIGHT_ARROW);
93 buffer.write(type.returnType);
94 }
95 return buffer.toString();
96 }
97
98 /**
99 * If the given [constructor]'s type is different when any type parameters
100 * from the defining type's declaration are replaced with the actual type
101 * arguments from the [definingType], create a constructor member representing
102 * the given constructor. Return the member that was created, or the original
103 * constructor if no member was created.
104 */
105 static ConstructorElement from(
106 ConstructorElement constructor, InterfaceType definingType) {
107 if (constructor == null || definingType.typeArguments.length == 0) {
108 return constructor;
109 }
110 FunctionType baseType = constructor.type;
111 if (baseType == null) {
112 // TODO(brianwilkerson) We need to understand when this can happen.
113 return constructor;
114 }
115 List<DartType> argumentTypes = definingType.typeArguments;
116 List<DartType> parameterTypes = definingType.element.type.typeArguments;
117 FunctionType substitutedType =
118 baseType.substitute2(argumentTypes, parameterTypes);
119 if (baseType == substitutedType) {
120 return constructor;
121 }
122 return new ConstructorMember(constructor, definingType, substitutedType);
123 }
124 }
125
126 /**
127 * An executable element defined in a parameterized type where the values of the
128 * type parameters are known.
129 */
130 abstract class ExecutableMember extends Member implements ExecutableElement {
131 @override
132 final FunctionType type;
133
134 /**
135 * Initialize a newly created element to represent a callable element (like a
136 * method or function or property), based on the [baseElement], defined by the
137 * [definingType]. If [type] is passed, it represents the full type of the
138 * member, and will take precedence over the [definingType].
139 */
140 ExecutableMember(ExecutableElement baseElement, InterfaceType definingType,
141 [FunctionType type])
142 : type = type ??
143 baseElement.type.substitute2(definingType.typeArguments,
144 TypeParameterTypeImpl.getTypes(definingType.typeParameters)),
145 super(baseElement, definingType);
146
147 @override
148 ExecutableElement get baseElement => super.baseElement as ExecutableElement;
149
150 @override
151 List<FunctionElement> get functions {
152 //
153 // Elements within this element should have type parameters substituted,
154 // just like this element.
155 //
156 throw new UnsupportedOperationException();
157 // return getBaseElement().getFunctions();
158 }
159
160 @override
161 bool get hasImplicitReturnType => baseElement.hasImplicitReturnType;
162
163 @override
164 bool get isAbstract => baseElement.isAbstract;
165
166 @override
167 bool get isAsynchronous => baseElement.isAsynchronous;
168
169 @override
170 bool get isExternal => baseElement.isExternal;
171
172 @override
173 bool get isGenerator => baseElement.isGenerator;
174
175 @override
176 bool get isOperator => baseElement.isOperator;
177
178 @override
179 bool get isStatic => baseElement.isStatic;
180
181 @override
182 bool get isSynchronous => baseElement.isSynchronous;
183
184 @override
185 List<LabelElement> get labels => baseElement.labels;
186
187 @override
188 List<LocalVariableElement> get localVariables {
189 //
190 // Elements within this element should have type parameters substituted,
191 // just like this element.
192 //
193 throw new UnsupportedOperationException();
194 // return getBaseElement().getLocalVariables();
195 }
196
197 @override
198 List<ParameterElement> get parameters => type.parameters;
199
200 @override
201 DartType get returnType => type.returnType;
202
203 @override
204 List<TypeParameterElement> get typeParameters => baseElement.typeParameters;
205
206 @override
207 void visitChildren(ElementVisitor visitor) {
208 // TODO(brianwilkerson) We need to finish implementing the accessors used
209 // below so that we can safely invoke them.
210 super.visitChildren(visitor);
211 safelyVisitChildren(baseElement.functions, visitor);
212 safelyVisitChildren(labels, visitor);
213 safelyVisitChildren(baseElement.localVariables, visitor);
214 safelyVisitChildren(parameters, visitor);
215 }
216 }
217
218 /**
219 * A parameter element defined in a parameterized type where the values of the
220 * type parameters are known.
221 */
222 class FieldFormalParameterMember extends ParameterMember
223 implements FieldFormalParameterElement {
224 /**
225 * Initialize a newly created element to represent a field formal parameter,
226 * based on the [baseElement], defined by the [definingType]. If [type]
227 * is passed it will be used as the substituted type for this member.
228 */
229 FieldFormalParameterMember(
230 FieldFormalParameterElement baseElement, ParameterizedType definingType,
231 [DartType type])
232 : super(baseElement, definingType, type);
233
234 @override
235 FieldElement get field {
236 FieldElement field = (baseElement as FieldFormalParameterElement).field;
237 if (field is FieldElement) {
238 return FieldMember.from(
239 field, substituteFor(field.enclosingElement.type));
240 }
241 return field;
242 }
243
244 @override
245 accept(ElementVisitor visitor) =>
246 visitor.visitFieldFormalParameterElement(this);
247 }
248
249 /**
250 * A field element defined in a parameterized type where the values of the type
251 * parameters are known.
252 */
253 class FieldMember extends VariableMember implements FieldElement {
254 /**
255 * Initialize a newly created element to represent a field, based on the
256 * [baseElement], defined by the [definingType].
257 */
258 FieldMember(FieldElement baseElement, InterfaceType definingType)
259 : super(baseElement, definingType);
260
261 @override
262 FieldElement get baseElement => super.baseElement as FieldElement;
263
264 @override
265 ClassElement get enclosingElement => baseElement.enclosingElement;
266
267 @override
268 PropertyAccessorElement get getter =>
269 PropertyAccessorMember.from(baseElement.getter, definingType);
270
271 @override
272 bool get isEnumConstant => baseElement.isEnumConstant;
273
274 @override
275 DartType get propagatedType => substituteFor(baseElement.propagatedType);
276
277 @override
278 PropertyAccessorElement get setter =>
279 PropertyAccessorMember.from(baseElement.setter, definingType);
280
281 @override
282 accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
283
284 @override
285 VariableDeclaration computeNode() => baseElement.computeNode();
286
287 @override
288 String toString() => '$type $displayName';
289
290 /**
291 * If the given [field]'s type is different when any type parameters from the
292 * defining type's declaration are replaced with the actual type arguments
293 * from the [definingType], create a field member representing the given
294 * field. Return the member that was created, or the base field if no member
295 * was created.
296 */
297 static FieldElement from(FieldElement field, ParameterizedType definingType) {
298 if (!_isChangedByTypeSubstitution(field, definingType)) {
299 return field;
300 }
301 // TODO(brianwilkerson) Consider caching the substituted type in the
302 // instance. It would use more memory but speed up some operations.
303 // We need to see how often the type is being re-computed.
304 return new FieldMember(field, definingType);
305 }
306
307 /**
308 * Determine whether the given [field]'s type is changed when type parameters
309 * from the [definingType]'s declaration are replaced with the actual type
310 * arguments from the defining type.
311 */
312 static bool _isChangedByTypeSubstitution(
313 FieldElement field, ParameterizedType definingType) {
314 List<DartType> argumentTypes = definingType.typeArguments;
315 if (field != null && argumentTypes.length != 0) {
316 DartType baseType = field.type;
317 List<DartType> parameterTypes =
318 TypeParameterTypeImpl.getTypes(definingType.typeParameters);
319 if (baseType != null) {
320 DartType substitutedType =
321 baseType.substitute2(argumentTypes, parameterTypes);
322 if (baseType != substitutedType) {
323 return true;
324 }
325 }
326 // If the field has a propagated type, then we need to check whether the
327 // propagated type needs substitution.
328 DartType basePropagatedType = field.propagatedType;
329 if (basePropagatedType != null) {
330 DartType substitutedPropagatedType =
331 basePropagatedType.substitute2(argumentTypes, parameterTypes);
332 if (basePropagatedType != substitutedPropagatedType) {
333 return true;
334 }
335 }
336 }
337 return false;
338 }
339 }
340
341 /**
342 * An element of a generic function, where the type parameters are known.
343 */
344 // TODO(jmesserly): the term "function member" is a bit weird, but it allows
345 // a certain consistency.
346 class FunctionMember extends ExecutableMember implements FunctionElement {
347 /**
348 * Initialize a newly created element to represent a function, based on the
349 * [baseElement], with the corresponding function [type].
350 */
351 FunctionMember(FunctionElement baseElement, [DartType type])
352 : super(baseElement, null, type);
353
354 @override
355 FunctionElement get baseElement => super.baseElement as FunctionElement;
356
357 @override
358 Element get enclosingElement => baseElement.enclosingElement;
359
360 @override
361 bool get isEntryPoint => baseElement.isEntryPoint;
362
363 @override
364 SourceRange get visibleRange => baseElement.visibleRange;
365
366 @override
367 accept(ElementVisitor visitor) => visitor.visitFunctionElement(this);
368
369 @override
370 FunctionDeclaration computeNode() => baseElement.computeNode();
371
372 @override
373 String toString() {
374 StringBuffer buffer = new StringBuffer();
375 buffer.write(baseElement.displayName);
376 (type as FunctionTypeImpl).appendTo(buffer);
377 return buffer.toString();
378 }
379
380 /**
381 * If the given [method]'s type is different when any type parameters from the
382 * defining type's declaration are replaced with the actual type arguments
383 * from the [definingType], create a method member representing the given
384 * method. Return the member that was created, or the base method if no member
385 * was created.
386 */
387 static MethodElement from(
388 MethodElement method, ParameterizedType definingType) {
389 if (method == null || definingType.typeArguments.length == 0) {
390 return method;
391 }
392 FunctionType baseType = method.type;
393 List<DartType> argumentTypes = definingType.typeArguments;
394 List<DartType> parameterTypes =
395 TypeParameterTypeImpl.getTypes(definingType.typeParameters);
396 FunctionType substitutedType =
397 baseType.substitute2(argumentTypes, parameterTypes);
398 if (baseType == substitutedType) {
399 return method;
400 }
401 return new MethodMember(method, definingType, substitutedType);
402 }
403 }
404
405 /**
406 * An element defined in a parameterized type where the values of the type
407 * parameters are known.
408 */
409 abstract class Member implements Element {
410 /**
411 * The element on which the parameterized element was created.
412 */
413 final Element _baseElement;
414
415 /**
416 * The type in which the element is defined.
417 */
418 final ParameterizedType _definingType;
419
420 /**
421 * Initialize a newly created element to represent a member, based on the
422 * [baseElement], defined by the [definingType].
423 */
424 Member(this._baseElement, this._definingType);
425
426 /**
427 * Return the element on which the parameterized element was created.
428 */
429 Element get baseElement => _baseElement;
430
431 @override
432 AnalysisContext get context => _baseElement.context;
433
434 /**
435 * Return the type in which the element is defined.
436 */
437 ParameterizedType get definingType => _definingType;
438
439 @override
440 String get displayName => _baseElement.displayName;
441
442 @override
443 SourceRange get docRange => _baseElement.docRange;
444
445 int get id => _baseElement.id;
446
447 @override
448 bool get isDeprecated => _baseElement.isDeprecated;
449
450 @override
451 bool get isOverride => _baseElement.isOverride;
452
453 @override
454 bool get isPrivate => _baseElement.isPrivate;
455
456 @override
457 bool get isPublic => _baseElement.isPublic;
458
459 @override
460 bool get isSynthetic => _baseElement.isSynthetic;
461
462 @override
463 ElementKind get kind => _baseElement.kind;
464
465 @override
466 LibraryElement get library => _baseElement.library;
467
468 @override
469 ElementLocation get location => _baseElement.location;
470
471 @override
472 List<ElementAnnotation> get metadata => _baseElement.metadata;
473
474 @override
475 String get name => _baseElement.name;
476
477 @override
478 int get nameLength => _baseElement.nameLength;
479
480 @override
481 int get nameOffset => _baseElement.nameOffset;
482
483 @override
484 Source get source => _baseElement.source;
485
486 @override
487 CompilationUnit get unit => _baseElement.unit;
488
489 @override
490 String computeDocumentationComment() =>
491 _baseElement.computeDocumentationComment();
492
493 @override
494 AstNode computeNode() => _baseElement.computeNode();
495
496 @override
497 Element getAncestor(Predicate<Element> predicate) =>
498 baseElement.getAncestor(predicate);
499
500 @override
501 String getExtendedDisplayName(String shortName) =>
502 _baseElement.getExtendedDisplayName(shortName);
503
504 @override
505 bool isAccessibleIn(LibraryElement library) =>
506 _baseElement.isAccessibleIn(library);
507
508 /**
509 * If the given [child] is not `null`, use the given [visitor] to visit it.
510 */
511 void safelyVisitChild(Element child, ElementVisitor visitor) {
512 // TODO(brianwilkerson) Make this private
513 if (child != null) {
514 child.accept(visitor);
515 }
516 }
517
518 /**
519 * Use the given [visitor] to visit all of the [children].
520 */
521 void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
522 // TODO(brianwilkerson) Make this private
523 if (children != null) {
524 for (Element child in children) {
525 child.accept(visitor);
526 }
527 }
528 }
529
530 /**
531 * Return the type that results from replacing the type parameters in the
532 * given [type] with the type arguments associated with this member.
533 */
534 DartType substituteFor(DartType type) {
535 if (type == null) {
536 return null;
537 }
538 List<DartType> argumentTypes = _definingType.typeArguments;
539 List<DartType> parameterTypes =
540 TypeParameterTypeImpl.getTypes(_definingType.typeParameters);
541 return type.substitute2(argumentTypes, parameterTypes);
542 }
543
544 @override
545 void visitChildren(ElementVisitor visitor) {
546 // There are no children to visit
547 }
548 }
549
550 /**
551 * A method element defined in a parameterized type where the values of the type
552 * parameters are known.
553 */
554 class MethodMember extends ExecutableMember implements MethodElement {
555 /**
556 * Initialize a newly created element to represent a method, based on the
557 * [baseElement], defined by the [definingType]. If [type] is passed, it
558 * represents the full type of the member, and will take precedence over
559 * the [definingType].
560 */
561 MethodMember(MethodElement baseElement, InterfaceType definingType,
562 [DartType type])
563 : super(baseElement, definingType, type);
564
565 @override
566 MethodElement get baseElement => super.baseElement as MethodElement;
567
568 @override
569 ClassElement get enclosingElement => baseElement.enclosingElement;
570
571 @override
572 accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
573
574 @override
575 MethodDeclaration computeNode() => baseElement.computeNode();
576
577 @override
578 String toString() {
579 MethodElement baseElement = this.baseElement;
580 List<ParameterElement> parameters = this.parameters;
581 FunctionType type = this.type;
582 StringBuffer buffer = new StringBuffer();
583 buffer.write(baseElement.enclosingElement.displayName);
584 buffer.write(".");
585 buffer.write(baseElement.displayName);
586 buffer.write("(");
587 int parameterCount = parameters.length;
588 for (int i = 0; i < parameterCount; i++) {
589 if (i > 0) {
590 buffer.write(", ");
591 }
592 buffer.write(parameters[i]);
593 }
594 buffer.write(")");
595 if (type != null) {
596 buffer.write(ElementImpl.RIGHT_ARROW);
597 buffer.write(type.returnType);
598 }
599 return buffer.toString();
600 }
601
602 /**
603 * If the given [method]'s type is different when any type parameters from the
604 * defining type's declaration are replaced with the actual type arguments
605 * from the [definingType], create a method member representing the given
606 * method. Return the member that was created, or the base method if no member
607 * was created.
608 */
609 static MethodElement from(MethodElement method, InterfaceType definingType) {
610 if (method == null || definingType.typeArguments.length == 0) {
611 return method;
612 }
613 FunctionType baseType = method.type;
614 List<DartType> argumentTypes = definingType.typeArguments;
615 List<DartType> parameterTypes = definingType.element.type.typeArguments;
616 FunctionType substitutedType =
617 baseType.substitute2(argumentTypes, parameterTypes);
618 if (baseType == substitutedType) {
619 return method;
620 }
621 return new MethodMember(method, definingType, substitutedType);
622 }
623 }
624
625 /**
626 * A parameter element defined in a parameterized type where the values of the
627 * type parameters are known.
628 */
629 class ParameterMember extends VariableMember
630 with ParameterElementMixin
631 implements ParameterElement {
632 /**
633 * Initialize a newly created element to represent a parameter, based on the
634 * [baseElement], defined by the [definingType]. If [type] is passed it will
635 * represent the already substituted type.
636 */
637 ParameterMember(ParameterElement baseElement, ParameterizedType definingType,
638 [DartType type])
639 : super._(baseElement, definingType, type);
640
641 @override
642 ParameterElement get baseElement => super.baseElement as ParameterElement;
643
644 @override
645 String get defaultValueCode => baseElement.defaultValueCode;
646
647 @override
648 Element get enclosingElement => baseElement.enclosingElement;
649
650 @override
651 int get hashCode => baseElement.hashCode;
652
653 @override
654 bool get isInitializingFormal => baseElement.isInitializingFormal;
655
656 @override
657 ParameterKind get parameterKind => baseElement.parameterKind;
658
659 @override
660 List<ParameterElement> get parameters {
661 DartType type = this.type;
662 if (type is FunctionType) {
663 return type.parameters;
664 }
665 return ParameterElement.EMPTY_LIST;
666 }
667
668 @override
669 List<TypeParameterElement> get typeParameters => baseElement.typeParameters;
670
671 @override
672 SourceRange get visibleRange => baseElement.visibleRange;
673
674 // TODO(jmesserly): this equality is broken. It should consider the defining
675 // type as well, otherwise we're dropping the substitution.
676 @override
677 bool operator ==(Object object) =>
678 object is ParameterMember && baseElement == object.baseElement;
679
680 @override
681 accept(ElementVisitor visitor) => visitor.visitParameterElement(this);
682
683 @override
684 FormalParameter computeNode() => baseElement.computeNode();
685
686 @override
687 Element getAncestor(Predicate<Element> predicate) {
688 Element element = baseElement.getAncestor(predicate);
689 ParameterizedType definingType = this.definingType;
690 if (definingType is InterfaceType) {
691 InterfaceType definingInterfaceType = definingType;
692 if (element is ConstructorElement) {
693 return ConstructorMember.from(element, definingInterfaceType);
694 } else if (element is MethodElement) {
695 return MethodMember.from(element, definingInterfaceType);
696 } else if (element is PropertyAccessorElement) {
697 return PropertyAccessorMember.from(element, definingInterfaceType);
698 }
699 }
700 return element;
701 }
702
703 @override
704 String toString() {
705 ParameterElement baseElement = this.baseElement;
706 String left = "";
707 String right = "";
708 while (true) {
709 if (baseElement.parameterKind == ParameterKind.NAMED) {
710 left = "{";
711 right = "}";
712 } else if (baseElement.parameterKind == ParameterKind.POSITIONAL) {
713 left = "[";
714 right = "]";
715 } else if (baseElement.parameterKind == ParameterKind.REQUIRED) {}
716 break;
717 }
718 return '$left$type ${baseElement.displayName}$right';
719 }
720
721 @override
722 void visitChildren(ElementVisitor visitor) {
723 super.visitChildren(visitor);
724 safelyVisitChildren(parameters, visitor);
725 }
726
727 /**
728 * If the given [parameter]'s type is different when any type parameters from
729 * the defining type's declaration are replaced with the actual type
730 * arguments from the [definingType], create a parameter member representing
731 * the given parameter. Return the member that was created, or the base
732 * parameter if no member was created.
733 */
734 static ParameterElement from(
735 ParameterElement parameter, ParameterizedType definingType) {
736 if (parameter == null || definingType.typeArguments.length == 0) {
737 return parameter;
738 }
739 // Check if parameter type depends on defining type type arguments.
740 // It is possible that we did not resolve field formal parameter yet,
741 // so skip this check for it.
742 if (parameter is FieldFormalParameterElement) {
743 return new FieldFormalParameterMember(parameter, definingType);
744 } else {
745 DartType baseType = parameter.type;
746 List<DartType> argumentTypes = definingType.typeArguments;
747 List<DartType> parameterTypes =
748 TypeParameterTypeImpl.getTypes(definingType.typeParameters);
749 DartType substitutedType =
750 baseType.substitute2(argumentTypes, parameterTypes);
751 if (baseType == substitutedType) {
752 return parameter;
753 }
754 return new ParameterMember(parameter, definingType, substitutedType);
755 }
756 }
757 }
758
759 /**
760 * A property accessor element defined in a parameterized type where the values
761 * of the type parameters are known.
762 */
763 class PropertyAccessorMember extends ExecutableMember
764 implements PropertyAccessorElement {
765 /**
766 * Initialize a newly created element to represent a property, based on the
767 * [baseElement], defined by the [definingType].
768 */
769 PropertyAccessorMember(
770 PropertyAccessorElement baseElement, InterfaceType definingType)
771 : super(baseElement, definingType);
772
773 @override
774 PropertyAccessorElement get baseElement =>
775 super.baseElement as PropertyAccessorElement;
776
777 @override
778 PropertyAccessorElement get correspondingGetter =>
779 from(baseElement.correspondingGetter, definingType);
780
781 @override
782 PropertyAccessorElement get correspondingSetter =>
783 from(baseElement.correspondingSetter, definingType);
784
785 @override
786 InterfaceType get definingType => super.definingType as InterfaceType;
787
788 @override
789 Element get enclosingElement => baseElement.enclosingElement;
790
791 @override
792 bool get isGetter => baseElement.isGetter;
793
794 @override
795 bool get isSetter => baseElement.isSetter;
796
797 @override
798 PropertyInducingElement get variable {
799 PropertyInducingElement variable = baseElement.variable;
800 if (variable is FieldElement) {
801 return FieldMember.from(variable, definingType);
802 }
803 return variable;
804 }
805
806 @override
807 accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this);
808
809 @override
810 String toString() {
811 PropertyAccessorElement baseElement = this.baseElement;
812 List<ParameterElement> parameters = this.parameters;
813 FunctionType type = this.type;
814 StringBuffer builder = new StringBuffer();
815 if (isGetter) {
816 builder.write("get ");
817 } else {
818 builder.write("set ");
819 }
820 builder.write(baseElement.enclosingElement.displayName);
821 builder.write(".");
822 builder.write(baseElement.displayName);
823 builder.write("(");
824 int parameterCount = parameters.length;
825 for (int i = 0; i < parameterCount; i++) {
826 if (i > 0) {
827 builder.write(", ");
828 }
829 builder.write(parameters[i]);
830 }
831 builder.write(")");
832 if (type != null) {
833 builder.write(ElementImpl.RIGHT_ARROW);
834 builder.write(type.returnType);
835 }
836 return builder.toString();
837 }
838
839 /**
840 * If the given [accessor]'s type is different when any type parameters from
841 * the defining type's declaration are replaced with the actual type
842 * arguments from the [definingType], create an accessor member representing
843 * the given accessor. Return the member that was created, or the base
844 * accessor if no member was created.
845 */
846 static PropertyAccessorElement from(
847 PropertyAccessorElement accessor, InterfaceType definingType) {
848 if (!_isChangedByTypeSubstitution(accessor, definingType)) {
849 return accessor;
850 }
851 // TODO(brianwilkerson) Consider caching the substituted type in the
852 // instance. It would use more memory but speed up some operations.
853 // We need to see how often the type is being re-computed.
854 return new PropertyAccessorMember(accessor, definingType);
855 }
856
857 /**
858 * Determine whether the given property [accessor]'s type is changed when type
859 * parameters from the defining type's declaration are replaced with the
860 * actual type arguments from the [definingType].
861 */
862 static bool _isChangedByTypeSubstitution(
863 PropertyAccessorElement accessor, InterfaceType definingType) {
864 List<DartType> argumentTypes = definingType.typeArguments;
865 if (accessor != null && argumentTypes.length != 0) {
866 FunctionType baseType = accessor.type;
867 if (baseType == null) {
868 AnalysisEngine.instance.logger.logInformation(
869 'Type of $accessor is null in PropertyAccessorMember._isChangedByTyp eSubstitution');
870 return false;
871 }
872 List<DartType> parameterTypes = definingType.element.type.typeArguments;
873 FunctionType substitutedType =
874 baseType.substitute2(argumentTypes, parameterTypes);
875 if (baseType != substitutedType) {
876 return true;
877 }
878 // If this property accessor is based on a field, that field might have a
879 // propagated type. In which case we need to check whether the propagated
880 // type of the field needs substitution.
881 PropertyInducingElement field = accessor.variable;
882 if (!field.isSynthetic) {
883 DartType baseFieldType = field.propagatedType;
884 if (baseFieldType != null) {
885 DartType substitutedFieldType =
886 baseFieldType.substitute2(argumentTypes, parameterTypes);
887 if (baseFieldType != substitutedFieldType) {
888 return true;
889 }
890 }
891 }
892 }
893 return false;
894 }
895 }
896
897 /**
898 * A variable element defined in a parameterized type where the values of the
899 * type parameters are known.
900 */
901 abstract class VariableMember extends Member implements VariableElement {
902 @override
903 final DartType type;
904
905 /**
906 * Initialize a newly created element to represent a variable, based on the
907 * [baseElement], defined by the [definingType].
908 */
909 VariableMember(VariableElement baseElement, ParameterizedType definingType,
910 [DartType type])
911 : type = type ??
912 baseElement.type.substitute2(definingType.typeArguments,
913 TypeParameterTypeImpl.getTypes(definingType.typeParameters)),
914 super(baseElement, definingType);
915
916 // TODO(jmesserly): this is temporary to allow the ParameterMember subclass.
917 // Apparently mixins don't work with optional params.
918 VariableMember._(VariableElement baseElement, ParameterizedType definingType,
919 DartType type)
920 : this(baseElement, definingType, type);
921
922 @override
923 VariableElement get baseElement => super.baseElement as VariableElement;
924
925 @override
926 DartObject get constantValue => baseElement.constantValue;
927
928 @override
929 bool get hasImplicitType => baseElement.hasImplicitType;
930
931 @override
932 FunctionElement get initializer {
933 //
934 // Elements within this element should have type parameters substituted,
935 // just like this element.
936 //
937 throw new UnsupportedOperationException();
938 // return getBaseElement().getInitializer();
939 }
940
941 @override
942 bool get isConst => baseElement.isConst;
943
944 @override
945 bool get isFinal => baseElement.isFinal;
946
947 @override
948 bool get isPotentiallyMutatedInClosure =>
949 baseElement.isPotentiallyMutatedInClosure;
950
951 @override
952 bool get isPotentiallyMutatedInScope =>
953 baseElement.isPotentiallyMutatedInScope;
954
955 @override
956 bool get isStatic => baseElement.isStatic;
957
958 @override
959 void visitChildren(ElementVisitor visitor) {
960 // TODO(brianwilkerson) We need to finish implementing the accessors used
961 // below so that we can safely invoke them.
962 super.visitChildren(visitor);
963 safelyVisitChild(baseElement.initializer, visitor);
964 }
965 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/dart/element/element.dart ('k') | pkg/analyzer/lib/src/dart/element/type.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698