Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 elements.modelx; | 5 library elements.modelx; |
| 6 | 6 |
| 7 import 'dart:uri'; | 7 import 'dart:uri'; |
| 8 import 'dart:collection' show LinkedHashMap; | 8 import 'dart:collection' show LinkedHashMap; |
| 9 | 9 |
| 10 import 'elements.dart'; | 10 import 'elements.dart'; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 125 | 125 |
| 126 /** | 126 /** |
| 127 * Is [:true:] if this element introduces the entity of this element. | 127 * Is [:true:] if this element introduces the entity of this element. |
| 128 * | 128 * |
| 129 * See [:patch_parser.dart:] for a description of the terminology. | 129 * See [:patch_parser.dart:] for a description of the terminology. |
| 130 */ | 130 */ |
| 131 bool get isDeclaration => !isPatch; | 131 bool get isDeclaration => !isPatch; |
| 132 | 132 |
| 133 bool get isSynthesized => false; | 133 bool get isSynthesized => false; |
| 134 | 134 |
| 135 bool get isForwardingConstructor => false; | |
| 136 | |
| 135 /** | 137 /** |
| 136 * Returns the element which defines the implementation for the entity of this | 138 * Returns the element which defines the implementation for the entity of this |
| 137 * element. | 139 * element. |
| 138 * | 140 * |
| 139 * See [:patch_parser.dart:] for a description of the terminology. | 141 * See [:patch_parser.dart:] for a description of the terminology. |
| 140 */ | 142 */ |
| 141 Element get implementation => isPatched ? patch : this; | 143 Element get implementation => isPatched ? patch : this; |
| 142 | 144 |
| 143 /** | 145 /** |
| 144 * Returns the element which introduces the entity of this element. | 146 * Returns the element which introduces the entity of this element. |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 263 void setFixedBackendName(String name) { | 265 void setFixedBackendName(String name) { |
| 264 _fixedBackendName = name; | 266 _fixedBackendName = name; |
| 265 } | 267 } |
| 266 | 268 |
| 267 FunctionElement asFunctionElement() => null; | 269 FunctionElement asFunctionElement() => null; |
| 268 | 270 |
| 269 static bool isInvalid(Element e) => e == null || e.isErroneous(); | 271 static bool isInvalid(Element e) => e == null || e.isErroneous(); |
| 270 | 272 |
| 271 bool isAbstract(Compiler compiler) => modifiers.isAbstract(); | 273 bool isAbstract(Compiler compiler) => modifiers.isAbstract(); |
| 272 bool isForeign(Compiler compiler) => getLibrary() == compiler.foreignLibrary; | 274 bool isForeign(Compiler compiler) => getLibrary() == compiler.foreignLibrary; |
| 275 | |
| 276 FunctionElement get targetConstructor => null; | |
| 273 } | 277 } |
| 274 | 278 |
| 275 /** | 279 /** |
| 276 * Represents an unresolvable or duplicated element. | 280 * Represents an unresolvable or duplicated element. |
| 277 * | 281 * |
| 278 * An [ErroneousElement] is used instead of [null] to provide additional | 282 * An [ErroneousElement] is used instead of [null] to provide additional |
| 279 * information about the error that caused the element to be unresolvable | 283 * information about the error that caused the element to be unresolvable |
| 280 * or otherwise invalid. | 284 * or otherwise invalid. |
| 281 * | 285 * |
| 282 * Accessing any field or calling any method defined on [ErroneousElement] | 286 * Accessing any field or calling any method defined on [ErroneousElement] |
| (...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1256 Node parseNode(DiagnosticListener listener) { | 1260 Node parseNode(DiagnosticListener listener) { |
| 1257 if (cachedNode != null) return cachedNode; | 1261 if (cachedNode != null) return cachedNode; |
| 1258 cachedNode = constructor.parseNode(listener); | 1262 cachedNode = constructor.parseNode(listener); |
| 1259 assert(cachedNode != null); | 1263 assert(cachedNode != null); |
| 1260 return cachedNode; | 1264 return cachedNode; |
| 1261 } | 1265 } |
| 1262 | 1266 |
| 1263 Token position() => constructor.position(); | 1267 Token position() => constructor.position(); |
| 1264 } | 1268 } |
| 1265 | 1269 |
| 1270 /** | |
| 1271 * A constructor that is not defined in the source code but rather implied by | |
| 1272 * the language semantics. | |
| 1273 * | |
| 1274 * This class is used to represent default constructors and forwarding | |
| 1275 * constructors for mixin applications. | |
| 1276 */ | |
| 1266 class SynthesizedConstructorElementX extends FunctionElementX { | 1277 class SynthesizedConstructorElementX extends FunctionElementX { |
| 1278 /// The target constructor if this synthetic constructor is a forwarding | |
| 1279 /// constructor in a mixin application. | |
| 1280 final FunctionElement target; | |
| 1281 | |
| 1267 SynthesizedConstructorElementX(Element enclosing) | 1282 SynthesizedConstructorElementX(Element enclosing) |
| 1268 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR, | 1283 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR, |
| 1269 Modifiers.EMPTY, enclosing); | 1284 Modifiers.EMPTY, enclosing), |
| 1285 target = null; | |
| 1270 | 1286 |
| 1271 SynthesizedConstructorElementX.forDefault(Element enclosing, | 1287 SynthesizedConstructorElementX.forDefault(Element enclosing, |
| 1272 Compiler compiler) | 1288 Compiler compiler) |
| 1273 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR, | 1289 : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR, |
| 1274 Modifiers.EMPTY, enclosing) { | 1290 Modifiers.EMPTY, enclosing), |
| 1291 target = null { | |
| 1292 // TODO(karlklose): get rid of the fake AST. | |
| 1275 type = new FunctionType(this, | 1293 type = new FunctionType(this, |
| 1276 compiler.types.voidType, | 1294 compiler.types.voidType, |
| 1277 const Link<DartType>(), | 1295 const Link<DartType>(), |
| 1278 const Link<DartType>(), | 1296 const Link<DartType>(), |
| 1279 const Link<SourceString>(), | 1297 const Link<SourceString>(), |
| 1280 const Link<DartType>()); | 1298 const Link<DartType>()); |
| 1281 cachedNode = new FunctionExpression( | 1299 cachedNode = new FunctionExpression( |
| 1282 new Identifier(enclosing.position()), | 1300 new Identifier(enclosing.position()), |
| 1283 new NodeList.empty(), | 1301 new NodeList.empty(), |
| 1284 new Block(new NodeList.empty()), | 1302 new Block(new NodeList.empty()), |
| 1285 null, Modifiers.EMPTY, null, null); | 1303 null, Modifiers.EMPTY, null, null); |
| 1286 } | 1304 } |
| 1287 | 1305 |
| 1306 /** | |
| 1307 * Create synthetic constructor that directly forwards to a constructor in the | |
| 1308 * super class of a mixin application. | |
| 1309 * | |
| 1310 * In a mixin application `Base with M`, any constructor defined in `Base` is | |
| 1311 * available as if they were a constructor defined in the mixin application | |
| 1312 * with the same formal parameters that calls the constructor in the super | |
| 1313 * class via a `super` initializer (see Ch. 9.1 in the specification). | |
| 1314 */ | |
| 1315 SynthesizedConstructorElementX.forwarding(SourceString name, this.target, | |
| 1316 Element enclosing) | |
| 1317 : super(name, ElementKind.GENERATIVE_CONSTRUCTOR, Modifiers.EMPTY, | |
| 1318 enclosing); | |
| 1319 | |
| 1320 Token position() => enclosingElement.position(); | |
| 1321 | |
| 1288 bool get isSynthesized => true; | 1322 bool get isSynthesized => true; |
| 1289 | 1323 |
| 1290 Token position() => enclosingElement.position(); | 1324 bool get isForwardingConstructor => target != null; |
| 1325 | |
| 1326 FunctionElement get targetConstructor => target; | |
| 1327 | |
| 1328 FunctionSignature computeSignature(compiler) { | |
| 1329 if (target != null) { | |
| 1330 return target.computeSignature(compiler); | |
| 1331 } else { | |
| 1332 assert(cachedNode != null); | |
| 1333 return super.computeSignature(compiler); | |
| 1334 } | |
| 1335 } | |
| 1336 | |
| 1337 get declaration => this; | |
| 1338 get implementation => this; | |
| 1339 get defaultImplementation => this; | |
| 1291 } | 1340 } |
| 1292 | 1341 |
| 1293 class VoidElementX extends ElementX { | 1342 class VoidElementX extends ElementX { |
| 1294 VoidElementX(Element enclosing) | 1343 VoidElementX(Element enclosing) |
| 1295 : super(const SourceString('void'), ElementKind.VOID, enclosing); | 1344 : super(const SourceString('void'), ElementKind.VOID, enclosing); |
| 1296 DartType computeType(compiler) => compiler.types.voidType; | 1345 DartType computeType(compiler) => compiler.types.voidType; |
| 1297 Node parseNode(_) { | 1346 Node parseNode(_) { |
| 1298 throw 'internal error: parseNode on void'; | 1347 throw 'internal error: parseNode on void'; |
| 1299 } | 1348 } |
| 1300 bool impliesType() => true; | 1349 bool impliesType() => true; |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1832 return super.toString(); | 1881 return super.toString(); |
| 1833 } | 1882 } |
| 1834 } | 1883 } |
| 1835 } | 1884 } |
| 1836 | 1885 |
| 1837 class MixinApplicationElementX extends BaseClassElementX | 1886 class MixinApplicationElementX extends BaseClassElementX |
| 1838 implements MixinApplicationElement { | 1887 implements MixinApplicationElement { |
| 1839 final Node node; | 1888 final Node node; |
| 1840 final Modifiers modifiers; | 1889 final Modifiers modifiers; |
| 1841 | 1890 |
| 1842 FunctionElement constructor; | 1891 Link<FunctionElement> constructors = new Link<FunctionElement>(); |
| 1892 | |
| 1843 ClassElement mixin; | 1893 ClassElement mixin; |
| 1844 | 1894 |
| 1845 // TODO(kasperl): The analyzer complains when I don't have these two | 1895 // TODO(kasperl): The analyzer complains when I don't have these two |
| 1846 // fields. This is pretty weird. I cannot replace them with getters. | 1896 // fields. This is pretty weird. I cannot replace them with getters. |
| 1847 final ClassElement patch = null; | 1897 final ClassElement patch = null; |
| 1848 final ClassElement origin = null; | 1898 final ClassElement origin = null; |
| 1849 | 1899 |
| 1850 MixinApplicationElementX(SourceString name, Element enclosing, int id, | 1900 MixinApplicationElementX(SourceString name, Element enclosing, int id, |
| 1851 this.node, this.modifiers) | 1901 this.node, this.modifiers) |
| 1852 : super(name, enclosing, id, STATE_NOT_STARTED); | 1902 : super(name, enclosing, id, STATE_NOT_STARTED); |
| 1853 | 1903 |
| 1854 bool get isMixinApplication => true; | 1904 bool get isMixinApplication => true; |
| 1855 bool get hasConstructor => constructor != null; | 1905 bool get hasConstructor => !constructors.isEmpty; |
| 1856 bool get hasLocalScopeMembers => false; | 1906 bool get hasLocalScopeMembers => constructors.isEmpty; |
|
kasperl
2013/04/25 12:13:12
So it has local scope members when there are no co
karlklose
2013/05/03 09:35:45
Done.
| |
| 1857 | 1907 |
| 1858 Token position() => node.getBeginToken(); | 1908 Token position() => node.getBeginToken(); |
| 1859 | 1909 |
| 1860 Node parseNode(DiagnosticListener listener) => node; | 1910 Node parseNode(DiagnosticListener listener) => node; |
| 1861 | 1911 |
| 1862 Element localLookup(SourceString name) { | 1912 Element localLookup(SourceString name) { |
| 1863 if (this.name == name) return constructor; | 1913 for (Link<Element> link = constructors; |
|
kasperl
2013/04/25 12:13:12
Maybe add a lookup constructor for this and call i
karlklose
2013/05/03 09:35:45
Done.
| |
| 1914 !link.isEmpty; | |
| 1915 link = link.tail) { | |
| 1916 if (link.head.name == name) return link.head; | |
| 1917 } | |
| 1864 if (mixin == null) return null; | 1918 if (mixin == null) return null; |
| 1865 Element mixedInElement = mixin.localLookup(name); | 1919 Element mixedInElement = mixin.localLookup(name); |
| 1866 if (mixedInElement == null) return null; | 1920 if (mixedInElement == null) return null; |
| 1867 return mixedInElement.isInstanceMember() ? mixedInElement : null; | 1921 return mixedInElement.isInstanceMember() ? mixedInElement : null; |
| 1868 } | 1922 } |
| 1869 | 1923 |
| 1870 void forEachLocalMember(void f(Element member)) { | 1924 void forEachLocalMember(void f(Element member)) { |
| 1871 if (mixin != null) mixin.forEachLocalMember((Element mixedInElement) { | 1925 if (mixin != null) mixin.forEachLocalMember((Element mixedInElement) { |
| 1872 if (mixedInElement.isInstanceMember()) f(mixedInElement); | 1926 if (mixedInElement.isInstanceMember()) f(mixedInElement); |
| 1873 }); | 1927 }); |
| 1874 } | 1928 } |
| 1875 | 1929 |
| 1876 void addMember(Element element, DiagnosticListener listener) { | 1930 void addMember(Element element, DiagnosticListener listener) { |
| 1877 throw new UnsupportedError("cannot add member to $this"); | 1931 throw new UnsupportedError("cannot add member to $this"); |
| 1878 } | 1932 } |
| 1879 | 1933 |
| 1880 void addToScope(Element element, DiagnosticListener listener) { | 1934 void addToScope(Element element, DiagnosticListener listener) { |
| 1881 throw new UnsupportedError("cannot add to scope of $this"); | 1935 if (!element.isConstructor()) { |
|
kasperl
2013/04/25 12:13:12
Why not keep this as is and always throw?
karlklose
2013/05/03 09:35:45
Done.
| |
| 1936 listener.internalError('can only add constructors to mixin application ' | |
| 1937 'scope, but got $element', element: this); | |
| 1938 } | |
| 1939 constructors = constructors.prepend(element); | |
| 1882 } | 1940 } |
| 1883 | 1941 |
| 1884 void setDefaultConstructor(FunctionElement constructor, Compiler compiler) { | 1942 void setDefaultConstructor(FunctionElement constructor, Compiler compiler) { |
| 1885 assert(!hasConstructor); | 1943 assert(!hasConstructor); |
| 1886 this.constructor = constructor; | 1944 addToScope(constructor, compiler); |
| 1887 } | 1945 } |
| 1888 | 1946 |
|
kasperl
2013/04/25 12:13:12
I'd add a new method for adding a constructor and
karlklose
2013/05/03 09:35:45
Done.
| |
| 1889 Link<DartType> computeTypeParameters(Compiler compiler) { | 1947 Link<DartType> computeTypeParameters(Compiler compiler) { |
| 1890 NamedMixinApplication named = node.asNamedMixinApplication(); | 1948 NamedMixinApplication named = node.asNamedMixinApplication(); |
| 1891 if (named == null) return const Link<DartType>(); | 1949 if (named == null) return const Link<DartType>(); |
| 1892 return TypeDeclarationElementX.createTypeVariables( | 1950 return TypeDeclarationElementX.createTypeVariables( |
| 1893 this, named.typeParameters); | 1951 this, named.typeParameters); |
| 1894 } | 1952 } |
| 1895 } | 1953 } |
| 1896 | 1954 |
| 1897 class LabelElementX extends ElementX implements LabelElement { | 1955 class LabelElementX extends ElementX implements LabelElement { |
| 1898 | 1956 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2018 | 2076 |
| 2019 MetadataAnnotation ensureResolved(Compiler compiler) { | 2077 MetadataAnnotation ensureResolved(Compiler compiler) { |
| 2020 if (resolutionState == STATE_NOT_STARTED) { | 2078 if (resolutionState == STATE_NOT_STARTED) { |
| 2021 compiler.resolver.resolveMetadataAnnotation(this); | 2079 compiler.resolver.resolveMetadataAnnotation(this); |
| 2022 } | 2080 } |
| 2023 return this; | 2081 return this; |
| 2024 } | 2082 } |
| 2025 | 2083 |
| 2026 String toString() => 'MetadataAnnotation($value, $resolutionState)'; | 2084 String toString() => 'MetadataAnnotation($value, $resolutionState)'; |
| 2027 } | 2085 } |
| OLD | NEW |