Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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'); | 5 #library('elements'); |
| 6 | 6 |
| 7 #import('../tree/tree.dart'); | 7 #import('../tree/tree.dart'); |
| 8 #import('../scanner/scannerlib.dart'); | 8 #import('../scanner/scannerlib.dart'); |
| 9 #import('../leg.dart'); // TODO(karlklose): we only need type. | 9 #import('../leg.dart'); // TODO(karlklose): we only need type. |
| 10 #import('../util/util.dart'); | 10 #import('../util/util.dart'); |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 } | 240 } |
| 241 | 241 |
| 242 bool _isNative = false; | 242 bool _isNative = false; |
| 243 void setNative() { _isNative = true; } | 243 void setNative() { _isNative = true; } |
| 244 bool isNative() => _isNative; | 244 bool isNative() => _isNative; |
| 245 | 245 |
| 246 FunctionElement asFunctionElement() => null; | 246 FunctionElement asFunctionElement() => null; |
| 247 } | 247 } |
| 248 | 248 |
| 249 class ContainerElement extends Element { | 249 class ContainerElement extends Element { |
| 250 ContainerElement(name, kind, enclosingElement) : | 250 ContainerElement(name, kind, enclosingElement) |
| 251 super(name, kind, enclosingElement); | 251 : super(name, kind, enclosingElement); |
| 252 | 252 |
| 253 abstract void addMember(Element element, DiagnosticListener listener); | 253 abstract void addMember(Element element, DiagnosticListener listener); |
| 254 | 254 |
| 255 void addGetterOrSetter(Element element, | 255 /** |
| 256 Element existing, | 256 * Adds a definition for an accessor (getter or setter) to a container. |
|
ahe
2012/08/10 11:21:46
Please use the [] notation to refer to the argumen
Lasse Reichstein Nielsen
2012/08/13 13:37:51
Done.
| |
| 257 DiagnosticListener listener) { | 257 * The definition binds to an abstract field that can hold both a getter |
| 258 * and a setter. | |
| 259 * | |
| 260 * The abstract field is added once, for the first getter or setter, and | |
| 261 * reused if the other one is also added. | |
| 262 * The abstract field should not be treated as a proper member of the | |
| 263 * container, it's simply a way to return two results for one lookup. | |
| 264 * I.e., the getter or setter does not have the abstract field as enclosing | |
|
ahe
2012/08/10 11:21:46
Use English, not Latin. That is, use "that is", no
Lasse Reichstein Nielsen
2012/08/13 13:37:51
Done.
| |
| 265 * element, they are enclosed by the class, as is the abstract field. | |
| 266 */ | |
| 267 void defineAccessor(Element element, | |
| 268 Element existing, | |
| 269 DiagnosticListener listener) { | |
| 258 void reportError(Element other) { | 270 void reportError(Element other) { |
| 259 listener.cancel('duplicate definition of ${element.name.slowToString()}', | 271 listener.cancel('duplicate definition of ${element.name.slowToString()}', |
| 260 element: element); | 272 element: element); |
| 261 listener.cancel('existing definition', element: other); | 273 listener.cancel('existing definition', element: other); |
| 262 } | 274 } |
| 263 | 275 |
| 264 if (existing != null) { | 276 if (existing != null) { |
| 265 if (existing.kind !== ElementKind.ABSTRACT_FIELD) { | 277 if (existing.kind !== ElementKind.ABSTRACT_FIELD) { |
| 266 reportError(existing); | 278 reportError(existing); |
| 267 } else { | 279 } else { |
| 268 AbstractFieldElement field = existing; | 280 AbstractFieldElement field = existing; |
| 269 if (element.kind == ElementKind.GETTER) { | 281 if (element.kind == ElementKind.GETTER) { |
| 270 if (field.getter != null && field.getter != element) { | 282 if (field.getter != null && field.getter != element) { |
| 271 reportError(field.getter); | 283 reportError(field.getter); |
| 272 } | 284 } |
| 273 field.getter = element; | 285 field.getter = element; |
| 274 } else { | 286 } else { |
| 287 assert(element.kind == ElementKind.SETTER); | |
|
ahe
2012/08/10 11:21:46
This assertion does not hold if I write:
class Fo
Lasse Reichstein Nielsen
2012/08/13 13:37:51
I don't see how. Either element is a getter or it'
| |
| 275 if (field.setter != null && field.setter != element) { | 288 if (field.setter != null && field.setter != element) { |
| 276 reportError(field.setter); | 289 reportError(field.setter); |
| 277 } | 290 } |
| 278 field.setter = element; | 291 field.setter = element; |
| 279 } | 292 } |
| 280 } | 293 } |
| 281 } else { | 294 } else { |
| 282 AbstractFieldElement field = new AbstractFieldElement(element.name, this); | 295 AbstractFieldElement field = new AbstractFieldElement(element.name, this); |
| 283 if (element.kind == ElementKind.GETTER) { | 296 if (element.kind == ElementKind.GETTER) { |
| 284 field.getter = element; | 297 field.getter = element; |
| 285 } else { | 298 } else { |
| 286 field.setter = element; | 299 field.setter = element; |
| 287 } | 300 } |
| 288 addMember(field, listener); | 301 define(field, listener); |
| 289 } | 302 } |
| 290 } | 303 } |
| 304 | |
| 305 abstract void define(Element element, DiagnosticListener listener); | |
|
Anders Johnsen
2012/08/07 13:02:30
Could you add a short description to this member?
Lasse Reichstein Nielsen
2012/08/13 13:37:51
Done.
| |
| 291 } | 306 } |
| 292 | 307 |
| 293 class CompilationUnitElement extends ContainerElement { | 308 class CompilationUnitElement extends ContainerElement { |
| 294 final Script script; | 309 final Script script; |
| 295 Link<Element> topLevelElements = const EmptyLink<Element>(); | 310 Link<Element> topLevelElements = const EmptyLink<Element>(); |
| 296 | 311 |
| 297 CompilationUnitElement(Script script, Element enclosing) | 312 CompilationUnitElement(Script script, Element enclosing) |
| 298 : this.script = script, | 313 : this.script = script, |
| 299 super(new SourceString(script.name), | 314 super(new SourceString(script.name), |
| 300 ElementKind.COMPILATION_UNIT, | 315 ElementKind.COMPILATION_UNIT, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 void addTag(ScriptTag tag, DiagnosticListener listener) { | 360 void addTag(ScriptTag tag, DiagnosticListener listener) { |
| 346 tags = tags.prepend(tag); | 361 tags = tags.prepend(tag); |
| 347 } | 362 } |
| 348 | 363 |
| 349 void addMember(Element element, DiagnosticListener listener) { | 364 void addMember(Element element, DiagnosticListener listener) { |
| 350 topLevelElements = topLevelElements.prepend(element); | 365 topLevelElements = topLevelElements.prepend(element); |
| 351 define(element, listener); | 366 define(element, listener); |
| 352 } | 367 } |
| 353 | 368 |
| 354 void define(Element element, DiagnosticListener listener) { | 369 void define(Element element, DiagnosticListener listener) { |
| 355 if (element.kind == ElementKind.GETTER | 370 if (element.isAccessor()) { |
| 356 || element.kind == ElementKind.SETTER) { | 371 defineAccessor(element, find(element.name), listener); |
| 357 addGetterOrSetter(element, elements[element.name], listener); | 372 return; |
| 358 } else { | 373 } |
| 359 Element existing = elements.putIfAbsent(element.name, () => element); | 374 Element existing = elements.putIfAbsent(element.name, () => element); |
| 360 if (existing !== element) { | 375 if (existing !== element) { |
| 361 listener.cancel('duplicate definition', token: element.position()); | 376 listener.cancel('duplicate definition', token: element.position()); |
| 362 listener.cancel('existing definition', token: existing.position()); | 377 listener.cancel('existing definition', token: existing.position()); |
| 363 } | |
| 364 } | 378 } |
| 365 } | 379 } |
| 366 | 380 |
| 367 /** Look up a top-level element in this library. The element could | 381 /** Look up a top-level element in this library. The element could |
| 368 * potentially have been imported from another library. Returns | 382 * potentially have been imported from another library. Returns |
| 369 * null if no such element exist. */ | 383 * null if no such element exist. */ |
| 370 Element find(SourceString elementName) { | 384 Element find(SourceString elementName) { |
| 371 return elements[elementName]; | 385 return elements[elementName]; |
| 372 } | 386 } |
| 373 | 387 |
| (...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 890 Link<Type> allSupertypes; | 904 Link<Type> allSupertypes; |
| 891 ClassElement patch = null; | 905 ClassElement patch = null; |
| 892 | 906 |
| 893 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) | 907 ClassElement(SourceString name, CompilationUnitElement enclosing, this.id) |
| 894 : localMembers = new Map<SourceString, Element>(), | 908 : localMembers = new Map<SourceString, Element>(), |
| 895 constructors = new Map<SourceString, Element>(), | 909 constructors = new Map<SourceString, Element>(), |
| 896 super(name, ElementKind.CLASS, enclosing); | 910 super(name, ElementKind.CLASS, enclosing); |
| 897 | 911 |
| 898 void addMember(Element element, DiagnosticListener listener) { | 912 void addMember(Element element, DiagnosticListener listener) { |
| 899 members = members.prepend(element); | 913 members = members.prepend(element); |
| 914 define(element, listener); | |
| 915 } | |
| 916 | |
| 917 void define(Element element, DiagnosticListener listener) { | |
| 918 if (element.isAccessor()) { | |
| 919 defineAccessor(element, localMembers[element.name], listener); | |
| 920 return; | |
| 921 } | |
| 900 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || | 922 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR || |
| 901 element.modifiers.isFactory()) { | 923 element.modifiers.isFactory()) { |
| 902 constructors[element.name] = element; | 924 constructors[element.name] = element; |
| 903 } else if (element.kind == ElementKind.GETTER | |
| 904 || element.kind == ElementKind.SETTER) { | |
| 905 addGetterOrSetter(element, localMembers[element.name], listener); | |
| 906 } else { | 925 } else { |
| 907 localMembers[element.name] = element; | 926 localMembers[element.name] = element; |
| 908 } | 927 } |
| 909 } | 928 } |
| 910 | 929 |
| 911 InterfaceType computeType(compiler) { | 930 InterfaceType computeType(compiler) { |
| 912 if (type == null) { | 931 if (type == null) { |
| 913 ClassNode node = parseNode(compiler); | 932 ClassNode node = parseNode(compiler); |
| 914 Link<Type> parameters = | 933 Link<Type> parameters = |
| 915 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); | 934 TypeDeclarationElement.createTypeVariables(this, node.typeParameters); |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1248 TypeVariableElement(name, Element enclosing, this.cachedNode, | 1267 TypeVariableElement(name, Element enclosing, this.cachedNode, |
| 1249 [this.type, this.bound]) | 1268 [this.type, this.bound]) |
| 1250 : super(name, ElementKind.TYPE_VARIABLE, enclosing); | 1269 : super(name, ElementKind.TYPE_VARIABLE, enclosing); |
| 1251 | 1270 |
| 1252 TypeVariableType computeType(compiler) => type; | 1271 TypeVariableType computeType(compiler) => type; |
| 1253 | 1272 |
| 1254 Node parseNode(compiler) => cachedNode; | 1273 Node parseNode(compiler) => cachedNode; |
| 1255 | 1274 |
| 1256 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; | 1275 String toString() => "${enclosingElement.toString()}.${name.slowToString()}"; |
| 1257 } | 1276 } |
| OLD | NEW |