Skip to content

Commit 4f78ad9

Browse files
bwilkersoncommit-bot@chromium.org
authored andcommitted
An initial and partial implementation of an element model for extensions
Change-Id: Id780bc64104690389a5af18f8acac8fc44536201 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108001 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent 744bb47 commit 4f78ad9

6 files changed

Lines changed: 302 additions & 9 deletions

File tree

‎pkg/analysis_server/test/protocol_server_test.dart‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ class EnumTest {
180180
engine.ElementKind.DYNAMIC: ElementKind.UNKNOWN,
181181
engine.ElementKind.ERROR: ElementKind.UNKNOWN,
182182
engine.ElementKind.EXPORT: ElementKind.UNKNOWN,
183+
engine.ElementKind.EXTENSION: ElementKind.UNKNOWN,
183184
engine.ElementKind.GENERIC_FUNCTION_TYPE: ElementKind.FUNCTION_TYPE_ALIAS,
184185
engine.ElementKind.IMPORT: ElementKind.UNKNOWN,
185186
engine.ElementKind.NAME: ElementKind.UNKNOWN,

‎pkg/analyzer/lib/dart/element/element.dart‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ abstract class CompilationUnitElement implements Element, UriReferencedElement {
373373
/// unit.
374374
List<ClassElement> get enums;
375375

376+
/// Return a list containing all of the extensions contained in this
377+
/// compilation unit.
378+
List<ExtensionElement> get extensions;
379+
376380
/// Return a list containing all of the top-level functions contained in this
377381
/// compilation unit.
378382
List<FunctionElement> get functions;
@@ -818,6 +822,9 @@ class ElementKind implements Comparable<ElementKind> {
818822
static const ElementKind EXPORT =
819823
const ElementKind('EXPORT', 5, "export directive");
820824

825+
static const ElementKind EXTENSION =
826+
const ElementKind('EXTENSION', 24, "extension");
827+
821828
static const ElementKind FIELD = const ElementKind('FIELD', 6, "field");
822829

823830
static const ElementKind FUNCTION =
@@ -957,6 +964,8 @@ abstract class ElementVisitor<R> {
957964

958965
R visitExportElement(ExportElement element);
959966

967+
R visitExtensionElement(ExtensionElement element);
968+
960969
R visitFieldElement(FieldElement element);
961970

962971
R visitFieldFormalParameterElement(FieldFormalParameterElement element);

‎pkg/analyzer/lib/dart/element/visitor.dart‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ class GeneralizingElementVisitor<R> implements ElementVisitor<R> {
100100
@override
101101
R visitExportElement(ExportElement element) => visitElement(element);
102102

103+
@override
104+
R visitExtensionElement(ExtensionElement element) => visitElement(element);
105+
103106
@override
104107
R visitFieldElement(FieldElement element) =>
105108
visitPropertyInducingElement(element);
@@ -212,6 +215,12 @@ class RecursiveElementVisitor<R> implements ElementVisitor<R> {
212215
return null;
213216
}
214217

218+
@override
219+
R visitExtensionElement(ExtensionElement element) {
220+
element.visitChildren(this);
221+
return null;
222+
}
223+
215224
@override
216225
R visitFieldElement(FieldElement element) {
217226
element.visitChildren(this);
@@ -328,6 +337,9 @@ class SimpleElementVisitor<R> implements ElementVisitor<R> {
328337
@override
329338
R visitExportElement(ExportElement element) => null;
330339

340+
@override
341+
R visitExtensionElement(ExtensionElement element) => null;
342+
331343
@override
332344
R visitFieldElement(FieldElement element) => null;
333345

@@ -399,6 +411,9 @@ class ThrowingElementVisitor<R> implements ElementVisitor<R> {
399411
@override
400412
R visitExportElement(ExportElement element) => _throw(element);
401413

414+
@override
415+
R visitExtensionElement(ExtensionElement element) => _throw(element);
416+
402417
@override
403418
R visitFieldElement(FieldElement element) => _throw(element);
404419

‎pkg/analyzer/lib/src/dart/element/element.dart‎

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,10 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl
16121612
/// A list containing all of the enums contained in this compilation unit.
16131613
List<ClassElement> _enums;
16141614

1615+
/// A list containing all of the extensions contained in this compilation
1616+
/// unit.
1617+
List<ExtensionElement> _extensions;
1618+
16151619
/// A list containing all of the top-level functions contained in this
16161620
/// compilation unit.
16171621
List<FunctionElement> _functions;
@@ -1767,6 +1771,30 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl
17671771
this._enums = enums;
17681772
}
17691773

1774+
@override
1775+
List<ExtensionElement> get extensions {
1776+
if (_extensions != null) {
1777+
return _extensions;
1778+
}
1779+
1780+
if (linkedNode != null) {
1781+
// TODO(brianwilkerson) Implement this.
1782+
} else if (_unlinkedUnit != null) {
1783+
// TODO(brianwilkerson) Implement this.
1784+
}
1785+
1786+
return _extensions ?? const <ExtensionElement>[];
1787+
}
1788+
1789+
/// Set the extensions contained in this compilation unit to the given
1790+
/// [extensions].
1791+
void set extensions(List<ExtensionElement> extensions) {
1792+
for (ExtensionElement extension in extensions) {
1793+
(extension as ExtensionElementImpl).enclosingElement = this;
1794+
}
1795+
this._extensions = extensions;
1796+
}
1797+
17701798
@override
17711799
List<FunctionElement> get functions {
17721800
if (_functions != null) return _functions;
@@ -4895,6 +4923,239 @@ class ExportElementImpl extends UriReferencedElementImpl
48954923
}
48964924
}
48974925

4926+
/// A concrete implementation of an [ExtensionElement].
4927+
class ExtensionElementImpl extends ElementImpl implements ExtensionElement {
4928+
/// The unlinked representation of the extension in the summary.
4929+
final /* UnlinkedExtension */ _unlinkedExtension;
4930+
4931+
/// A list containing all of the type parameters declared by this extension.
4932+
List<TypeParameterElement> _typeParameters;
4933+
4934+
/// The type being extended.
4935+
DartType _extendedType;
4936+
4937+
/// A list containing all of the accessors (getters and setters) contained in
4938+
/// this extension.
4939+
List<PropertyAccessorElement> _accessors;
4940+
4941+
/// A list containing all of the methods contained in this extension.
4942+
List<MethodElement> _methods;
4943+
4944+
/// Initialize a newly created extension element to have the given [name] at
4945+
/// the given [offset] in the file that contains the declaration of this
4946+
/// element.
4947+
ExtensionElementImpl(String name, int nameOffset)
4948+
: _unlinkedExtension = null,
4949+
super(name, nameOffset);
4950+
4951+
/// Initialize a newly created extension element to have the given [name].
4952+
ExtensionElementImpl.forNode(Identifier name)
4953+
: _unlinkedExtension = null,
4954+
super.forNode(name);
4955+
4956+
@override
4957+
List<PropertyAccessorElement> get accessors {
4958+
if (_accessors != null) {
4959+
return _accessors;
4960+
}
4961+
4962+
if (linkedNode != null) {
4963+
if (linkedNode is ExtensionDeclaration) {
4964+
// TODO(brianwilkerson) Implement this.
4965+
// _createPropertiesAndAccessors();
4966+
// assert(_accessors != null);
4967+
// return _accessors;
4968+
} else {
4969+
return _accessors = const [];
4970+
}
4971+
} else if (_unlinkedExtension != null) {
4972+
// TODO(brianwilkerson) Implement this.
4973+
// _resynthesizePropertyAccessors();
4974+
}
4975+
4976+
return _accessors ??= const <PropertyAccessorElement>[];
4977+
}
4978+
4979+
void set accessors(List<PropertyAccessorElement> accessors) {
4980+
_assertNotResynthesized(_unlinkedExtension);
4981+
for (PropertyAccessorElement accessor in accessors) {
4982+
(accessor as PropertyAccessorElementImpl).enclosingElement = this;
4983+
}
4984+
_accessors = accessors;
4985+
}
4986+
4987+
@override
4988+
DartType get extendedType {
4989+
if (_extendedType != null) {
4990+
return _extendedType;
4991+
}
4992+
4993+
if (linkedNode != null) {
4994+
// TODO(brianwilkerson) Implement this.
4995+
// var context = enclosingUnit.linkedContext;
4996+
// return _extendedType = context.getExtendedType(linkedNode)?.type;
4997+
} else if (_unlinkedExtension != null) {
4998+
return _extendedType = enclosingUnit.resynthesizerContext
4999+
.resolveTypeRef(this, _unlinkedExtension.extendedType);
5000+
}
5001+
5002+
return _extendedType;
5003+
}
5004+
5005+
void set extendedType(DartType extendedType) {
5006+
_assertNotResynthesized(_unlinkedExtension);
5007+
_extendedType = extendedType;
5008+
}
5009+
5010+
@override
5011+
ElementKind get kind => ElementKind.EXTENSION;
5012+
5013+
@override
5014+
List<MethodElement> get methods {
5015+
if (_methods != null) {
5016+
return _methods;
5017+
}
5018+
5019+
if (linkedNode != null) {
5020+
// TODO(brianwilkerson) Implement this.
5021+
// var context = enclosingUnit.linkedContext;
5022+
// var containerRef = reference.getChild('@method');
5023+
// return _methods = context
5024+
// .getMethods(linkedNode)
5025+
// .where((node) => node.propertyKeyword == null)
5026+
// .map((node) {
5027+
// var name = node.name.name;
5028+
// var reference = containerRef.getChild(name);
5029+
// if (reference.hasElementFor(node)) {
5030+
// return reference.element as MethodElement;
5031+
// }
5032+
// return MethodElementImpl.forLinkedNode(this, reference, node);
5033+
// }).toList();
5034+
} else if (_unlinkedExtension != null) {
5035+
// TODO(brianwilkerson) Implement this.
5036+
// var unlinkedExecutables = _unlinkedExtension.executables;
5037+
//
5038+
// var length = unlinkedExecutables.length;
5039+
// if (length == 0) {
5040+
// return _methods = const <MethodElement>[];
5041+
// }
5042+
//
5043+
// var count = 0;
5044+
// for (var i = 0; i < length; i++) {
5045+
// var e = unlinkedExecutables[i];
5046+
// if (e.kind == UnlinkedExecutableKind.functionOrMethod) {
5047+
// count++;
5048+
// }
5049+
// }
5050+
// if (count == 0) {
5051+
// return _methods = const <MethodElement>[];
5052+
// }
5053+
//
5054+
// var methods = new List<MethodElement>(count);
5055+
// var index = 0;
5056+
// for (var i = 0; i < length; i++) {
5057+
// var e = unlinkedExecutables[i];
5058+
// if (e.kind == UnlinkedExecutableKind.functionOrMethod) {
5059+
// methods[index++] = new MethodElementImpl.forSerialized(e, this);
5060+
// }
5061+
// }
5062+
// return _methods = methods;
5063+
}
5064+
return _methods = const <MethodElement>[];
5065+
}
5066+
5067+
/// Set the methods contained in this extension to the given [methods].
5068+
void set methods(List<MethodElement> methods) {
5069+
_assertNotResynthesized(_unlinkedExtension);
5070+
for (MethodElement method in methods) {
5071+
(method as MethodElementImpl).enclosingElement = this;
5072+
}
5073+
_methods = methods;
5074+
}
5075+
5076+
@override
5077+
List<TypeParameterElement> get typeParameters {
5078+
if (_typeParameters != null) {
5079+
return _typeParameters;
5080+
}
5081+
5082+
if (linkedNode != null) {
5083+
var typeParameters = linkedContext.getTypeParameters2(linkedNode);
5084+
if (typeParameters == null) {
5085+
return _typeParameters = const [];
5086+
}
5087+
var containerRef = reference.getChild('@typeParameter');
5088+
return _typeParameters =
5089+
typeParameters.typeParameters.map<TypeParameterElement>((node) {
5090+
var reference = containerRef.getChild(node.name.name);
5091+
if (reference.hasElementFor(node)) {
5092+
return reference.element as TypeParameterElement;
5093+
}
5094+
return TypeParameterElementImpl.forLinkedNode(this, reference, node);
5095+
}).toList();
5096+
} else if (_unlinkedExtension != null) {
5097+
// TODO(brianwilkerson) Implement this.
5098+
// List<UnlinkedTypeParam> unlinkedParams =
5099+
// _unlinkedExtension?.typeParameters;
5100+
// if (unlinkedParams != null) {
5101+
// int numTypeParameters = unlinkedParams.length;
5102+
// _typeParameters = new List<TypeParameterElement>(numTypeParameters);
5103+
// for (int i = 0; i < numTypeParameters; i++) {
5104+
// _typeParameters[i] = new TypeParameterElementImpl.forSerialized(
5105+
// unlinkedParams[i], this);
5106+
// }
5107+
// }
5108+
}
5109+
5110+
return _typeParameters ?? const <TypeParameterElement>[];
5111+
}
5112+
5113+
/// Set the type parameters defined by this extension to the given
5114+
/// [typeParameters].
5115+
void set typeParameters(List<TypeParameterElement> typeParameters) {
5116+
_assertNotResynthesized(_unlinkedExtension);
5117+
for (TypeParameterElement typeParameter in typeParameters) {
5118+
(typeParameter as TypeParameterElementImpl).enclosingElement = this;
5119+
}
5120+
this._typeParameters = typeParameters;
5121+
}
5122+
5123+
@override
5124+
T accept<T>(ElementVisitor<T> visitor) {
5125+
return visitor.visitExtensionElement(this);
5126+
}
5127+
5128+
@override
5129+
PropertyAccessorElement getGetter(String getterName) {
5130+
int length = accessors.length;
5131+
for (int i = 0; i < length; i++) {
5132+
PropertyAccessorElement accessor = accessors[i];
5133+
if (accessor.isGetter && accessor.name == getterName) {
5134+
return accessor;
5135+
}
5136+
}
5137+
return null;
5138+
}
5139+
5140+
@override
5141+
MethodElement getMethod(String methodName) {
5142+
int length = methods.length;
5143+
for (int i = 0; i < length; i++) {
5144+
MethodElement method = methods[i];
5145+
if (method.name == methodName) {
5146+
return method;
5147+
}
5148+
}
5149+
return null;
5150+
}
5151+
5152+
@override
5153+
PropertyAccessorElement getSetter(String setterName) {
5154+
return AbstractClassElementImpl.getSetterFromAccessors(
5155+
setterName, accessors);
5156+
}
5157+
}
5158+
48985159
/// A concrete implementation of a [FieldElement].
48995160
class FieldElementImpl extends PropertyInducingElementImpl
49005161
implements FieldElement {

‎pkg/analyzer/lib/src/dart/element/handle.dart‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ class CompilationUnitElementHandle extends ElementHandle
213213
@override
214214
List<ClassElement> get enums => actualElement.enums;
215215

216+
@override
217+
List<ExtensionElement> get extensions => actualElement.extensions;
218+
216219
@override
217220
List<FunctionElement> get functions => actualElement.functions;
218221

@@ -893,9 +896,6 @@ class LibraryElementHandle extends ElementHandle implements LibraryElement {
893896
@override
894897
LibraryElement get actualElement => super.actualElement as LibraryElement;
895898

896-
@override
897-
bool get isNonNullableByDefault => actualElement.isNonNullableByDefault;
898-
899899
@override
900900
CompilationUnitElement get definingCompilationUnit =>
901901
actualElement.definingCompilationUnit;
@@ -939,6 +939,9 @@ class LibraryElementHandle extends ElementHandle implements LibraryElement {
939939
@override
940940
bool get isInSdk => actualElement.isInSdk;
941941

942+
@override
943+
bool get isNonNullableByDefault => actualElement.isNonNullableByDefault;
944+
942945
@override
943946
ElementKind get kind => ElementKind.LIBRARY;
944947

0 commit comments

Comments
 (0)