| 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 toString() => id; | 85 toString() => id; |
| 86 } | 86 } |
| 87 | 87 |
| 88 class Element implements Hashable { | 88 class Element implements Hashable { |
| 89 final SourceString name; | 89 final SourceString name; |
| 90 final ElementKind kind; | 90 final ElementKind kind; |
| 91 final Element enclosingElement; | 91 final Element enclosingElement; |
| 92 Modifiers get modifiers() => null; | 92 Modifiers get modifiers() => null; |
| 93 | 93 |
| 94 Node parseNode(DiagnosticListener listener) { | 94 Node parseNode(DiagnosticListener listener) { |
| 95 listener.cancel("Internal Error: Element.parseNode"); | 95 listener.cancel("Internal Error: $this.parseNode", token: position()); |
| 96 } | 96 } |
| 97 | 97 |
| 98 Type computeType(Compiler compiler) { | 98 Type computeType(Compiler compiler) { |
| 99 compiler.internalError("Element.computeType."); | 99 compiler.internalError("$this.computeType.", token: position()); |
| 100 } | 100 } |
| 101 | 101 |
| 102 bool isFunction() => kind === ElementKind.FUNCTION; | 102 bool isFunction() => kind === ElementKind.FUNCTION; |
| 103 bool isMember() => | 103 bool isMember() => |
| 104 enclosingElement !== null && enclosingElement.kind === ElementKind.CLASS; | 104 enclosingElement !== null && enclosingElement.kind === ElementKind.CLASS; |
| 105 bool isInstanceMember() => false; | 105 bool isInstanceMember() => false; |
| 106 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory(); | 106 bool isFactoryConstructor() => modifiers !== null && modifiers.isFactory(); |
| 107 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR; | 107 bool isGenerativeConstructor() => kind === ElementKind.GENERATIVE_CONSTRUCTOR; |
| 108 bool isCompilationUnit() { | 108 bool isCompilationUnit() { |
| 109 return kind === ElementKind.COMPILATION_UNIT || | 109 return kind === ElementKind.COMPILATION_UNIT || |
| 110 kind === ElementKind.LIBRARY; | 110 kind === ElementKind.LIBRARY; |
| 111 } | 111 } |
| 112 bool isClass() => kind === ElementKind.CLASS; | 112 bool isClass() => kind === ElementKind.CLASS; |
| 113 bool isVariable() => kind === ElementKind.VARIABLE; | 113 bool isVariable() => kind === ElementKind.VARIABLE; |
| 114 bool isParameter() => kind === ElementKind.PARAMETER; | 114 bool isParameter() => kind === ElementKind.PARAMETER; |
| 115 bool isStatement() => kind === ElementKind.STATEMENT; | 115 bool isStatement() => kind === ElementKind.STATEMENT; |
| 116 bool isTypedef() => kind === ElementKind.TYPEDEF; | 116 bool isTypedef() => kind === ElementKind.TYPEDEF; |
| 117 bool isGetter() => kind === ElementKind.GETTER; | 117 bool isGetter() => kind === ElementKind.GETTER; |
| 118 bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0; | 118 bool impliesType() => (kind.category & ElementCategory.IMPLIES_TYPE) != 0; |
| 119 | 119 |
| 120 bool isAssignable() { | 120 bool isAssignable() { |
| 121 if (modifiers != null && modifiers.isFinal()) return false; | 121 if (modifiers != null && modifiers.isFinal()) return false; |
| 122 if (isFunction() || isGenerativeConstructor()) return false; | 122 if (isFunction() || isGenerativeConstructor()) return false; |
| 123 return true; | 123 return true; |
| 124 } | 124 } |
| 125 | 125 |
| 126 Token position() => null; | 126 Token position() => null; |
| 127 | 127 |
| 128 Token findMyName(Token token) { |
| 129 for (Token t = token; t !== EOF_TOKEN; t = t.next) { |
| 130 if (t.value == name) return t; |
| 131 } |
| 132 return token; |
| 133 } |
| 134 |
| 128 const Element(this.name, this.kind, this.enclosingElement); | 135 const Element(this.name, this.kind, this.enclosingElement); |
| 129 | 136 |
| 130 // TODO(kasperl): This is a very bad hash code for the element and | 137 // TODO(kasperl): This is a very bad hash code for the element and |
| 131 // there's no reason why two elements with the same name should have | 138 // there's no reason why two elements with the same name should have |
| 132 // the same hash code. Replace this with a simple id in the element? | 139 // the same hash code. Replace this with a simple id in the element? |
| 133 int hashCode() => name.hashCode(); | 140 int hashCode() => name.hashCode(); |
| 134 | 141 |
| 135 CompilationUnitElement getCompilationUnit() { | 142 CompilationUnitElement getCompilationUnit() { |
| 136 Element element = this; | 143 Element element = this; |
| 137 while (element !== null && !element.isCompilationUnit()) { | 144 while (element !== null && !element.isCompilationUnit()) { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 listener.cancel('duplicate definition', token: element.position()); | 270 listener.cancel('duplicate definition', token: element.position()); |
| 264 listener.cancel('existing definition', token: existing.position()); | 271 listener.cancel('existing definition', token: existing.position()); |
| 265 } | 272 } |
| 266 } | 273 } |
| 267 } | 274 } |
| 268 | 275 |
| 269 Element find(SourceString name) { | 276 Element find(SourceString name) { |
| 270 return elements[name]; | 277 return elements[name]; |
| 271 } | 278 } |
| 272 | 279 |
| 273 Element lookupLocalMember(SourceString name) { | |
| 274 Element element = find(name); | |
| 275 if (element === null) return null; | |
| 276 return (this === element.getLibrary()) ? element : null; | |
| 277 } | |
| 278 | |
| 279 void forEachExport(f(Element element)) { | 280 void forEachExport(f(Element element)) { |
| 280 elements.forEach((SourceString _, Element e) { | 281 elements.forEach((SourceString _, Element e) { |
| 281 if (this === e.getLibrary() | 282 if (this === e.getLibrary() |
| 282 && e.kind !== ElementKind.PREFIX | 283 && e.kind !== ElementKind.PREFIX |
| 283 && e.kind !== ElementKind.FOREIGN) { | 284 && e.kind !== ElementKind.FOREIGN) { |
| 284 f(e); | 285 f(e); |
| 285 } | 286 } |
| 286 }); | 287 }); |
| 287 } | 288 } |
| 288 } | 289 } |
| 289 | 290 |
| 290 class PrefixElement extends Element { | 291 class PrefixElement extends Element { |
| 291 final LiteralString prefix; | 292 Map<SourceString, Element> imported; |
| 292 final LibraryElement library; | |
| 293 | 293 |
| 294 PrefixElement(LiteralString prefix, | 294 PrefixElement(SourceString prefix, Element enclosing) |
| 295 LibraryElement this.library, | 295 : imported = new Map<SourceString, Element>(), |
| 296 Element enclosing) | 296 super(prefix, ElementKind.PREFIX, enclosing); |
| 297 : this.prefix = prefix, | |
| 298 super(prefix.dartString.source, ElementKind.PREFIX, enclosing); | |
| 299 | 297 |
| 300 lookupLocalMember(SourceString name) => library.lookupLocalMember(name); | 298 lookupLocalMember(SourceString name) => imported[name]; |
| 299 |
| 300 Type computeType(Compiler compiler) => compiler.types.dynamicType; |
| 301 } | 301 } |
| 302 | 302 |
| 303 class TypedefElement extends Element { | 303 class TypedefElement extends Element { |
| 304 TypedefElement(SourceString name, Element enclosing) | 304 TypedefElement(SourceString name, Element enclosing) |
| 305 : super(name, ElementKind.TYPEDEF, enclosing); | 305 : super(name, ElementKind.TYPEDEF, enclosing); |
| 306 } | 306 } |
| 307 | 307 |
| 308 class VariableElement extends Element { | 308 class VariableElement extends Element { |
| 309 final VariableListElement variables; | 309 final VariableListElement variables; |
| 310 Expression cachedNode; // The send or the identifier in the variables list. | 310 Expression cachedNode; // The send or the identifier in the variables list. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 339 Type computeType(Compiler compiler) { | 339 Type computeType(Compiler compiler) { |
| 340 return variables.computeType(compiler); | 340 return variables.computeType(compiler); |
| 341 } | 341 } |
| 342 | 342 |
| 343 Type get type() => variables.type; | 343 Type get type() => variables.type; |
| 344 | 344 |
| 345 bool isInstanceMember() { | 345 bool isInstanceMember() { |
| 346 return isMember() && !modifiers.isStatic(); | 346 return isMember() && !modifiers.isStatic(); |
| 347 } | 347 } |
| 348 | 348 |
| 349 Token position() { | 349 // Note: cachedNode.getBeginToken() will not be correct in all |
| 350 // TODO(ahe): Record the token corresponding to name instead of | 350 // cases, for example, for function typed parameters. |
| 351 // returning different values at different points in time. | 351 Token position() => findMyName(variables.position()); |
| 352 return (cachedNode !== null) | |
| 353 ? cachedNode.getBeginToken() : variables.position(); | |
| 354 } | |
| 355 } | 352 } |
| 356 | 353 |
| 357 // This element represents a list of variable or field declaration. | 354 // This element represents a list of variable or field declaration. |
| 358 // It contains the node, and the type. A [VariableElement] always | 355 // It contains the node, and the type. A [VariableElement] always |
| 359 // references its [VariableListElement]. It forwards its | 356 // references its [VariableListElement]. It forwards its |
| 360 // [computeType] and [parseNode] methods to this element. | 357 // [computeType] and [parseNode] methods to this element. |
| 361 class VariableListElement extends Element { | 358 class VariableListElement extends Element { |
| 362 VariableDefinitions cachedNode; | 359 VariableDefinitions cachedNode; |
| 363 Type type; | 360 Type type; |
| 364 final Modifiers modifiers; | 361 final Modifiers modifiers; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 : super(name, ElementKind.ABSTRACT_FIELD, enclosing), | 407 : super(name, ElementKind.ABSTRACT_FIELD, enclosing), |
| 411 modifiers = new Modifiers.empty(); | 408 modifiers = new Modifiers.empty(); |
| 412 | 409 |
| 413 Type computeType(Compiler compiler) { | 410 Type computeType(Compiler compiler) { |
| 414 throw "internal error: AbstractFieldElement has no type"; | 411 throw "internal error: AbstractFieldElement has no type"; |
| 415 } | 412 } |
| 416 | 413 |
| 417 Node parseNode(DiagnosticListener listener) { | 414 Node parseNode(DiagnosticListener listener) { |
| 418 throw "internal error: AbstractFieldElement has no node"; | 415 throw "internal error: AbstractFieldElement has no node"; |
| 419 } | 416 } |
| 417 |
| 418 position() { |
| 419 // The getter and setter may be defined in two different |
| 420 // compilation units. However, we know that one of them is |
| 421 // non-null and defined in the same compilation unit as the |
| 422 // abstract element. |
| 423 // |
| 424 // We need to make sure that the position returned is relative to |
| 425 // the compilation unit of the abstract element. |
| 426 if (getter !== null && getter.enclosingElement === enclosingElement) { |
| 427 return getter.position(); |
| 428 } else { |
| 429 return setter.position(); |
| 430 } |
| 431 } |
| 420 } | 432 } |
| 421 | 433 |
| 422 /** DEPRECATED. */ | 434 /** DEPRECATED. */ |
| 423 Type getType(TypeAnnotation typeAnnotation, | 435 Type getType(TypeAnnotation typeAnnotation, |
| 424 Compiler compiler, | 436 Compiler compiler, |
| 425 LibraryElement library) { | 437 LibraryElement library) { |
| 426 // TODO(karlklose,ngeoffray): This method should be removed and the | 438 // TODO(karlklose,ngeoffray): This method should be removed and the |
| 427 // information should be computed by the resolver. | 439 // information should be computed by the resolver. |
| 428 | 440 |
| 429 if (typeAnnotation == null || typeAnnotation.typeName == null) { | 441 if (typeAnnotation == null || typeAnnotation.typeName == null) { |
| 430 return compiler.types.dynamicType; | 442 return compiler.types.dynamicType; |
| 431 } | 443 } |
| 432 Identifier identifier = typeAnnotation.typeName.asIdentifier(); | 444 Identifier identifier = typeAnnotation.typeName.asIdentifier(); |
| 433 if (identifier === null) { | 445 if (identifier === null) { |
| 434 compiler.cancel('library prefixes not handled', | 446 compiler.reportWarning(typeAnnotation.typeName, |
| 435 node: typeAnnotation.typeName); | 447 'library prefixes not handled'); |
| 448 return compiler.types.dynamicType; |
| 436 } | 449 } |
| 437 SourceString name = identifier.source; | 450 SourceString name = identifier.source; |
| 438 Element element = library.find(name); | 451 Element element = library.find(name); |
| 439 if (element !== null) { | 452 if (element !== null) { |
| 440 if (element.isTypedef()) { | 453 if (element.isTypedef()) { |
| 441 // TODO(ngeoffray): This is a hack to help us get support for the | 454 // TODO(ngeoffray): This is a hack to help us get support for the |
| 442 // DOM library. | 455 // DOM library. |
| 443 // TODO(ngeoffray): The list of types for the argument is wrong. | 456 // TODO(ngeoffray): The list of types for the argument is wrong. |
| 444 return new FunctionType(compiler.types.dynamicType, | 457 return new FunctionType(compiler.types.dynamicType, |
| 445 const EmptyLink<Type>(), | 458 const EmptyLink<Type>(), |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 | 863 |
| 851 LabelElement addLabel(Identifier label, String labelName) { | 864 LabelElement addLabel(Identifier label, String labelName) { |
| 852 LabelElement result = new LabelElement(label, labelName, this, | 865 LabelElement result = new LabelElement(label, labelName, this, |
| 853 enclosingElement); | 866 enclosingElement); |
| 854 labels = labels.prepend(result); | 867 labels = labels.prepend(result); |
| 855 return result; | 868 return result; |
| 856 } | 869 } |
| 857 | 870 |
| 858 Node parseNode(DiagnosticListener l) => statement; | 871 Node parseNode(DiagnosticListener l) => statement; |
| 859 } | 872 } |
| OLD | NEW |