| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library elements; |
| |
| import 'dart:uri'; |
| |
| import 'modelx.dart'; |
| import '../tree/tree.dart'; |
| import '../util/util.dart'; |
| import '../resolution/resolution.dart'; |
| |
| import '../dart2jslib.dart' show InterfaceType, |
| DartType, |
| TypeVariableType, |
| TypedefType, |
| MessageKind, |
| DiagnosticListener, |
| Script, |
| FunctionType, |
| SourceString, |
| Selector, |
| Constant, |
| Compiler; |
| |
| import '../dart_types.dart'; |
| |
| import '../scanner/scannerlib.dart' show Token, |
| isUserDefinableOperator, |
| isMinusOperator; |
| |
| const int STATE_NOT_STARTED = 0; |
| const int STATE_STARTED = 1; |
| const int STATE_DONE = 2; |
| |
| class ElementCategory { |
| /** |
| * Represents things that we don't expect to find when looking in a |
| * scope. |
| */ |
| static const int NONE = 0; |
| |
| /** Field, parameter, or variable. */ |
| static const int VARIABLE = 1; |
| |
| /** Function, method, or foreign function. */ |
| static const int FUNCTION = 2; |
| |
| static const int CLASS = 4; |
| |
| static const int PREFIX = 8; |
| |
| /** Constructor or factory. */ |
| static const int FACTORY = 16; |
| |
| static const int ALIAS = 32; |
| |
| static const int SUPER = 64; |
| |
| /** Type variable */ |
| static const int TYPE_VARIABLE = 128; |
| |
| static const int IMPLIES_TYPE = CLASS | ALIAS | TYPE_VARIABLE; |
| } |
| |
| class ElementKind { |
| final String id; |
| final int category; |
| |
| const ElementKind(String this.id, this.category); |
| |
| static const ElementKind VARIABLE = |
| const ElementKind('variable', ElementCategory.VARIABLE); |
| static const ElementKind PARAMETER = |
| const ElementKind('parameter', ElementCategory.VARIABLE); |
| // Parameters in constructors that directly initialize fields. For example: |
| // [:A(this.field):]. |
| static const ElementKind FIELD_PARAMETER = |
| const ElementKind('field_parameter', ElementCategory.VARIABLE); |
| static const ElementKind FUNCTION = |
| const ElementKind('function', ElementCategory.FUNCTION); |
| static const ElementKind CLASS = |
| const ElementKind('class', ElementCategory.CLASS); |
| static const ElementKind GENERATIVE_CONSTRUCTOR = |
| const ElementKind('generative_constructor', ElementCategory.FACTORY); |
| static const ElementKind FIELD = |
| const ElementKind('field', ElementCategory.VARIABLE); |
| static const ElementKind VARIABLE_LIST = |
| const ElementKind('variable_list', ElementCategory.NONE); |
| static const ElementKind FIELD_LIST = |
| const ElementKind('field_list', ElementCategory.NONE); |
| static const ElementKind GENERATIVE_CONSTRUCTOR_BODY = |
| const ElementKind('generative_constructor_body', ElementCategory.NONE); |
| static const ElementKind COMPILATION_UNIT = |
| const ElementKind('compilation_unit', ElementCategory.NONE); |
| static const ElementKind GETTER = |
| const ElementKind('getter', ElementCategory.NONE); |
| static const ElementKind SETTER = |
| const ElementKind('setter', ElementCategory.NONE); |
| static const ElementKind TYPE_VARIABLE = |
| const ElementKind('type_variable', ElementCategory.TYPE_VARIABLE); |
| static const ElementKind ABSTRACT_FIELD = |
| const ElementKind('abstract_field', ElementCategory.VARIABLE); |
| static const ElementKind LIBRARY = |
| const ElementKind('library', ElementCategory.NONE); |
| static const ElementKind PREFIX = |
| const ElementKind('prefix', ElementCategory.PREFIX); |
| static const ElementKind TYPEDEF = |
| const ElementKind('typedef', ElementCategory.ALIAS); |
| |
| static const ElementKind STATEMENT = |
| const ElementKind('statement', ElementCategory.NONE); |
| static const ElementKind LABEL = |
| const ElementKind('label', ElementCategory.NONE); |
| static const ElementKind VOID = |
| const ElementKind('void', ElementCategory.NONE); |
| |
| static const ElementKind AMBIGUOUS = |
| const ElementKind('ambiguous', ElementCategory.NONE); |
| static const ElementKind ERROR = |
| const ElementKind('error', ElementCategory.NONE); |
| static const ElementKind MALFORMED_TYPE = |
| const ElementKind('malformed', ElementCategory.NONE); |
| |
| toString() => id; |
| } |
| |
| /** |
| * A declared element of a program. |
| * |
| * The declared elements of a program include classes, methods, |
| * fields, variables, parameters, etc. |
| * |
| * Sometimes it makes sense to construct "synthetic" elements that |
| * have not been declared anywhere in a program, for example, there |
| * are elements corresponding to "dynamic", "null", and unresolved |
| * references. |
| * |
| * Elements are distinct from types ([DartType]). For example, there |
| * is one declaration of the class List, but several related types, |
| * for example, List, List<int>, List<String>, etc. |
| * |
| * Elements are distinct from AST nodes ([Node]), and there normally is a |
| * one-to-one correspondence between an AST node and an element |
| * (except that not all kinds of AST nodes have an associated |
| * element). |
| * |
| * AST nodes represent precisely what is written in source code, for |
| * example, when a user writes "class MyClass {}", the corresponding |
| * AST node does not have a superclass. On the other hand, the |
| * corresponding element (once fully resolved) will record the |
| * information about the implicit superclass as defined by the |
| * language semantics. |
| * |
| * Generally, the contents of a method are represented as AST nodes |
| * without additional elements, but things like local functions, local |
| * variables, and labels have a corresponding element. |
| * |
| * We generally say that scanning, parsing, resolution, and type |
| * checking comprise the "front-end" of the compiler. The "back-end" |
| * includes things like SSA graph construction, optimizations, and |
| * code generation. |
| * |
| * The front-end data structures are designed to be reusable by |
| * several back-ends. For example, we may want to support emitting |
| * minified Dart and JavaScript code in one go. Also, we're planning |
| * on adding an incremental compilation server that should be able to |
| * reuse elements between compilations. So to keep things simple, it |
| * is best if the backends avoid setting state directly in elements. |
| * It is better to keep such state in a table on the side. |
| */ |
| abstract class Element implements Spannable { |
| SourceString get name; |
| ElementKind get kind; |
| Modifiers get modifiers; |
| Element get enclosingElement; |
| Link<MetadataAnnotation> get metadata; |
| |
| Node parseNode(DiagnosticListener listener); |
| DartType computeType(Compiler compiler); |
| |
| bool isFunction(); |
| bool isConstructor(); |
| bool isClosure(); |
| bool isMember(); |
| bool isInstanceMember(); |
| |
| bool isFactoryConstructor(); |
| bool isGenerativeConstructor(); |
| bool isGenerativeConstructorBody(); |
| bool isCompilationUnit(); |
| bool isClass(); |
| bool isPrefix(); |
| bool isVariable(); |
| bool isParameter(); |
| bool isStatement(); |
| bool isTypedef(); |
| bool isTypeVariable(); |
| bool isField(); |
| bool isAbstractField(); |
| bool isGetter(); |
| bool isSetter(); |
| bool isAccessor(); |
| bool isLibrary(); |
| bool isErroneous(); |
| bool isAmbiguous(); |
| |
| bool isTopLevel(); |
| bool isAssignable(); |
| bool isNative(); |
| |
| bool impliesType(); |
| |
| Token position(); |
| |
| CompilationUnitElement getCompilationUnit(); |
| LibraryElement getLibrary(); |
| LibraryElement getImplementationLibrary(); |
| ClassElement getEnclosingClass(); |
| Element getEnclosingClassOrCompilationUnit(); |
| Element getEnclosingMember(); |
| Element getOutermostEnclosingMemberOrTopLevel(); |
| |
| FunctionElement asFunctionElement(); |
| |
| bool get isPatched; |
| bool get isPatch; |
| bool get isImplementation; |
| bool get isDeclaration; |
| bool get isSynthesized; |
| |
| Element get implementation; |
| Element get declaration; |
| Element get patch; |
| Element get origin; |
| |
| bool hasFixedBackendName(); |
| String fixedBackendName(); |
| |
| bool isAbstract(Compiler compiler); |
| bool isForeign(Compiler compiler); |
| |
| void addMetadata(MetadataAnnotation annotation); |
| void setNative(String name); |
| void setFixedBackendName(String name); |
| |
| Scope buildScope(); |
| } |
| |
| class Elements { |
| static bool isUnresolved(Element e) { |
| return e == null || e.isErroneous(); |
| } |
| static bool isErroneousElement(Element e) => e != null && e.isErroneous(); |
| |
| static bool isClass(Element e) => e != null && e.kind == ElementKind.CLASS; |
| static bool isTypedef(Element e) { |
| return e != null && e.kind == ElementKind.TYPEDEF; |
| } |
| |
| static bool isLocal(Element element) { |
| return !Elements.isUnresolved(element) |
| && !element.isInstanceMember() |
| && !isStaticOrTopLevelField(element) |
| && !isStaticOrTopLevelFunction(element) |
| && (identical(element.kind, ElementKind.VARIABLE) || |
| identical(element.kind, ElementKind.PARAMETER) || |
| identical(element.kind, ElementKind.FUNCTION)); |
| } |
| |
| static bool isInstanceField(Element element) { |
| return !Elements.isUnresolved(element) |
| && element.isInstanceMember() |
| && (identical(element.kind, ElementKind.FIELD) |
| || identical(element.kind, ElementKind.GETTER) |
| || identical(element.kind, ElementKind.SETTER)); |
| } |
| |
| static bool isStaticOrTopLevel(Element element) { |
| // TODO(ager): This should not be necessary when patch support has |
| // been reworked. |
| if (!Elements.isUnresolved(element) |
| && element.modifiers.isStatic()) { |
| return true; |
| } |
| return !Elements.isUnresolved(element) |
| && !element.isInstanceMember() |
| && !element.isPrefix() |
| && element.enclosingElement != null |
| && (element.enclosingElement.kind == ElementKind.CLASS || |
| element.enclosingElement.kind == ElementKind.COMPILATION_UNIT || |
| element.enclosingElement.kind == ElementKind.LIBRARY); |
| } |
| |
| static bool isInStaticContext(Element element) { |
| if (isUnresolved(element)) return true; |
| if (element.enclosingElement.isClosure()) { |
| var closureClass = element.enclosingElement; |
| element = closureClass.methodElement; |
| } |
| Element outer = element.getOutermostEnclosingMemberOrTopLevel(); |
| if (isUnresolved(outer)) return true; |
| if (outer.isTopLevel()) return true; |
| if (outer.isGenerativeConstructor()) return false; |
| if (outer.isInstanceMember()) return false; |
| return true; |
| } |
| |
| static bool isStaticOrTopLevelField(Element element) { |
| return isStaticOrTopLevel(element) |
| && (identical(element.kind, ElementKind.FIELD) |
| || identical(element.kind, ElementKind.GETTER) |
| || identical(element.kind, ElementKind.SETTER)); |
| } |
| |
| static bool isStaticOrTopLevelFunction(Element element) { |
| return isStaticOrTopLevel(element) |
| && (identical(element.kind, ElementKind.FUNCTION)); |
| } |
| |
| static bool isInstanceMethod(Element element) { |
| return !Elements.isUnresolved(element) |
| && element.isInstanceMember() |
| && (identical(element.kind, ElementKind.FUNCTION)); |
| } |
| |
| static bool isInstanceSend(Send send, TreeElements elements) { |
| Element element = elements[send]; |
| if (element == null) return !isClosureSend(send, element); |
| return isInstanceMethod(element) || isInstanceField(element); |
| } |
| |
| static bool isClosureSend(Send send, Element element) { |
| if (send.isPropertyAccess) return false; |
| if (send.receiver != null) return false; |
| Node selector = send.selector; |
| // this(). |
| if (selector.isThis()) return true; |
| // (o)() or foo()(). |
| if (element == null && selector.asIdentifier() == null) return true; |
| if (element == null) return false; |
| // foo() with foo a local or a parameter. |
| return isLocal(element); |
| } |
| |
| static SourceString constructConstructorName(SourceString receiver, |
| SourceString selector) { |
| String r = receiver.slowToString(); |
| String s = selector.slowToString(); |
| return new SourceString('$r\$$s'); |
| } |
| |
| static SourceString deconstructConstructorName(SourceString name, |
| ClassElement holder) { |
| String r = '${holder.name.slowToString()}\$'; |
| String s = name.slowToString(); |
| if (s.startsWith(r)) { |
| return new SourceString(s.substring(r.length)); |
| } |
| return null; |
| } |
| |
| /** |
| * Map an operator-name to a valid Dart identifier. |
| * |
| * For non-operator names, this metod just returns its input. |
| * |
| * The results returned from this method are guaranteed to be valid |
| * JavaScript identifers, except it may include reserved words for |
| * non-operator names. |
| */ |
| static SourceString operatorNameToIdentifier(SourceString name) { |
| if (name == null) return null; |
| String value = name.stringValue; |
| if (value == null) { |
| return name; |
| } else if (identical(value, '==')) { |
| return const SourceString(r'operator$eq'); |
| } else if (identical(value, '~')) { |
| return const SourceString(r'operator$not'); |
| } else if (identical(value, '[]')) { |
| return const SourceString(r'operator$index'); |
| } else if (identical(value, '[]=')) { |
| return const SourceString(r'operator$indexSet'); |
| } else if (identical(value, '*')) { |
| return const SourceString(r'operator$mul'); |
| } else if (identical(value, '/')) { |
| return const SourceString(r'operator$div'); |
| } else if (identical(value, '%')) { |
| return const SourceString(r'operator$mod'); |
| } else if (identical(value, '~/')) { |
| return const SourceString(r'operator$tdiv'); |
| } else if (identical(value, '+')) { |
| return const SourceString(r'operator$add'); |
| } else if (identical(value, '<<')) { |
| return const SourceString(r'operator$shl'); |
| } else if (identical(value, '>>')) { |
| return const SourceString(r'operator$shr'); |
| } else if (identical(value, '>=')) { |
| return const SourceString(r'operator$ge'); |
| } else if (identical(value, '>')) { |
| return const SourceString(r'operator$gt'); |
| } else if (identical(value, '<=')) { |
| return const SourceString(r'operator$le'); |
| } else if (identical(value, '<')) { |
| return const SourceString(r'operator$lt'); |
| } else if (identical(value, '&')) { |
| return const SourceString(r'operator$and'); |
| } else if (identical(value, '^')) { |
| return const SourceString(r'operator$xor'); |
| } else if (identical(value, '|')) { |
| return const SourceString(r'operator$or'); |
| } else if (identical(value, '-')) { |
| return const SourceString(r'operator$sub'); |
| } else if (identical(value, 'unary-')) { |
| return const SourceString(r'operator$negate'); |
| } else { |
| return name; |
| } |
| } |
| |
| static SourceString constructOperatorNameOrNull(SourceString op, |
| bool isUnary) { |
| String value = op.stringValue; |
| if (isMinusOperator(value)) { |
| return isUnary ? const SourceString('unary-') : op; |
| } else if (isUserDefinableOperator(value)) { |
| return op; |
| } else { |
| return null; |
| } |
| } |
| |
| static SourceString constructOperatorName(SourceString op, bool isUnary) { |
| SourceString operatorName = constructOperatorNameOrNull(op, isUnary); |
| if (operatorName == null) throw 'Unhandled operator: ${op.slowToString()}'; |
| else return operatorName; |
| } |
| |
| static SourceString mapToUserOperatorOrNull(SourceString op) { |
| String value = op.stringValue; |
| |
| if (identical(value, '!=')) return const SourceString('=='); |
| if (identical(value, '*=')) return const SourceString('*'); |
| if (identical(value, '/=')) return const SourceString('/'); |
| if (identical(value, '%=')) return const SourceString('%'); |
| if (identical(value, '~/=')) return const SourceString('~/'); |
| if (identical(value, '+=')) return const SourceString('+'); |
| if (identical(value, '-=')) return const SourceString('-'); |
| if (identical(value, '<<=')) return const SourceString('<<'); |
| if (identical(value, '>>=')) return const SourceString('>>'); |
| if (identical(value, '&=')) return const SourceString('&'); |
| if (identical(value, '^=')) return const SourceString('^'); |
| if (identical(value, '|=')) return const SourceString('|'); |
| |
| return null; |
| } |
| |
| static SourceString mapToUserOperator(SourceString op) { |
| SourceString userOperator = mapToUserOperatorOrNull(op); |
| if (userOperator == null) throw 'Unhandled operator: ${op.slowToString()}'; |
| else return userOperator; |
| } |
| |
| static bool isNumberOrStringSupertype(Element element, Compiler compiler) { |
| LibraryElement coreLibrary = compiler.coreLibrary; |
| return (element == coreLibrary.find(const SourceString('Comparable'))); |
| } |
| |
| static bool isStringOnlySupertype(Element element, Compiler compiler) { |
| LibraryElement coreLibrary = compiler.coreLibrary; |
| return element == coreLibrary.find(const SourceString('Pattern')); |
| } |
| |
| static bool isListSupertype(Element element, Compiler compiler) { |
| LibraryElement coreLibrary = compiler.coreLibrary; |
| return element == coreLibrary.find(const SourceString('Iterable')); |
| } |
| |
| /// A `compareTo` function that places [Element]s in a consistent order based |
| /// on the source code order. |
| static int compareByPosition(Element a, Element b) { |
| CompilationUnitElement unitA = a.getCompilationUnit(); |
| CompilationUnitElement unitB = b.getCompilationUnit(); |
| if (!identical(unitA, unitB)) { |
| int r = unitA.script.uri.path.compareTo(unitB.script.uri.path); |
| if (r != 0) return r; |
| } |
| Token positionA = a.position(); |
| Token positionB = b.position(); |
| int r = positionA.charOffset.compareTo(positionB.charOffset); |
| if (r != 0) return r; |
| r = a.name.slowToString().compareTo(b.name.slowToString()); |
| if (r != 0) return r; |
| // Same file, position and name. If this happens, we should find out why |
| // and make the order total and independent of hashCode. |
| return a.hashCode.compareTo(b.hashCode); |
| } |
| |
| static List<Element> sortedByPosition(Iterable<Element> elements) { |
| return elements.toList()..sort(compareByPosition); |
| } |
| |
| static bool isFixedListConstructorCall(Element element, |
| Send node, |
| Compiler compiler) { |
| return element == compiler.unnamedListConstructor |
| && node.isCall |
| && !node.arguments.isEmpty |
| && node.arguments.tail.isEmpty; |
| } |
| |
| static bool isGrowableListConstructorCall(Element element, |
| Send node, |
| Compiler compiler) { |
| return element == compiler.unnamedListConstructor |
| && node.isCall |
| && node.arguments.isEmpty; |
| } |
| } |
| |
| abstract class ErroneousElement extends Element implements FunctionElement { |
| MessageKind get messageKind; |
| Map get messageArguments; |
| } |
| |
| abstract class AmbiguousElement extends Element { |
| MessageKind get messageKind; |
| Map get messageArguments; |
| Element get existingElement; |
| Element get newElement; |
| } |
| |
| // TODO(kasperl): This probably shouldn't be called an element. It's |
| // just an interface shared by classes and libraries. |
| abstract class ScopeContainerElement { |
| Element localLookup(SourceString elementName); |
| |
| void forEachLocalMember(f(Element element)); |
| } |
| |
| abstract class CompilationUnitElement extends Element { |
| Script get script; |
| PartOf get partTag; |
| |
| void addMember(Element element, DiagnosticListener listener); |
| void setPartOf(PartOf tag, DiagnosticListener listener); |
| bool get hasMembers; |
| } |
| |
| abstract class LibraryElement extends Element implements ScopeContainerElement { |
| /** |
| * The canonical uri for this library. |
| * |
| * For user libraries the canonical uri is the script uri. For platform |
| * libraries the canonical uri is of the form [:dart:x:]. |
| */ |
| Uri get canonicalUri; |
| CompilationUnitElement get entryCompilationUnit; |
| Link<CompilationUnitElement> get compilationUnits; |
| Link<LibraryTag> get tags; |
| LibraryName get libraryTag; |
| Link<Element> get exports; |
| |
| /** |
| * [:true:] if this library is part of the platform, that is its canonical |
| * uri has the scheme 'dart'. |
| */ |
| bool get isPlatformLibrary; |
| |
| /** |
| * [:true:] if this library is a platform library whose path starts with |
| * an underscore. |
| */ |
| bool get isInternalLibrary; |
| bool get canUseNative; |
| bool get exportsHandled; |
| |
| // TODO(kasperl): We should try to get rid of these. |
| void set canUseNative(bool value); |
| void set libraryTag(LibraryName value); |
| |
| LibraryElement get implementation; |
| |
| void addCompilationUnit(CompilationUnitElement element); |
| void addTag(LibraryTag tag, DiagnosticListener listener); |
| void addImport(Element element, DiagnosticListener listener); |
| |
| /// Record which element an import or export tag resolved to. |
| /// (Belongs on builder object). |
| void recordResolvedTag(LibraryDependency tag, LibraryElement library); |
| |
| /// Return the library element corresponding to an import or export. |
| LibraryElement getLibraryFromTag(LibraryDependency tag); |
| |
| void addMember(Element element, DiagnosticListener listener); |
| void addToScope(Element element, DiagnosticListener listener); |
| |
| // TODO(kasperl): Get rid of this method. |
| Iterable<Element> getNonPrivateElementsInScope(); |
| |
| void setExports(Iterable<Element> exportedElements); |
| |
| Element find(SourceString elementName); |
| Element findLocal(SourceString elementName); |
| void forEachExport(f(Element element)); |
| |
| bool hasLibraryName(); |
| String getLibraryOrScriptName(); |
| } |
| |
| abstract class PrefixElement extends Element { |
| Map<SourceString, Element> get imported; |
| Element lookupLocalMember(SourceString memberName); |
| } |
| |
| abstract class TypedefElement extends Element |
| implements TypeDeclarationElement { |
| TypedefType get rawType; |
| DartType get alias; |
| FunctionSignature get functionSignature; |
| Link<DartType> get typeVariables; |
| |
| bool get isResolved; |
| |
| // TODO(kasperl): Try to get rid of these setters. |
| void set alias(DartType value); |
| void set functionSignature(FunctionSignature value); |
| } |
| |
| abstract class VariableElement extends Element { |
| VariableListElement get variables; |
| |
| // TODO(kasperl): Try to get rid of this. |
| Expression get cachedNode; |
| } |
| |
| abstract class FieldParameterElement extends VariableElement { |
| VariableElement get fieldElement; |
| } |
| |
| abstract class VariableListElement extends Element { |
| DartType get type; |
| FunctionSignature get functionSignature; |
| |
| // TODO(kasperl): Try to get rid of this. |
| void set type(DartType value); |
| } |
| |
| /** |
| * A synthetic element which holds a getter and/or a setter. |
| * |
| * This element unifies handling of fields and getters/setters. When |
| * looking at code like "foo.x", we don't have to look for both a |
| * field named "x", a getter named "x", and a setter named "x=". |
| */ |
| abstract class AbstractFieldElement extends Element { |
| FunctionElement get getter; |
| FunctionElement get setter; |
| } |
| |
| abstract class FunctionSignature { |
| DartType get returnType; |
| Link<Element> get requiredParameters; |
| Link<Element> get optionalParameters; |
| |
| int get requiredParameterCount; |
| int get optionalParameterCount; |
| bool get optionalParametersAreNamed; |
| Element get firstOptionalParameter; |
| |
| int get parameterCount; |
| List<Element> get orderedOptionalParameters; |
| |
| void forEachParameter(void function(Element parameter)); |
| void forEachRequiredParameter(void function(Element parameter)); |
| void forEachOptionalParameter(void function(Element parameter)); |
| |
| void orderedForEachParameter(void function(Element parameter)); |
| } |
| |
| abstract class FunctionElement extends Element { |
| FunctionExpression get cachedNode; |
| DartType get type; |
| FunctionSignature get functionSignature; |
| FunctionElement get redirectionTarget; |
| FunctionElement get defaultImplementation; |
| |
| FunctionElement get patch; |
| FunctionElement get origin; |
| |
| // TODO(kasperl): These are bit fishy. Do we really need them? |
| void set patch(FunctionElement value); |
| void set origin(FunctionElement value); |
| void set defaultImplementation(FunctionElement value); |
| |
| void setPatch(FunctionElement patchElement); |
| FunctionSignature computeSignature(Compiler compiler); |
| int requiredParameterCount(Compiler compiler); |
| int optionalParameterCount(Compiler compiler); |
| int parameterCount(Compiler compiler); |
| |
| FunctionExpression parseNode(DiagnosticListener listener); |
| } |
| |
| abstract class ConstructorBodyElement extends FunctionElement { |
| FunctionElement get constructor; |
| } |
| |
| /** |
| * [TypeDeclarationElement] defines the common interface for class/interface |
| * declarations and typedefs. |
| */ |
| abstract class TypeDeclarationElement extends Element { |
| GenericType get rawType; |
| |
| /** |
| * The type variables declared on this declaration. The type variables are not |
| * available until the type of the element has been computed through |
| * [computeType]. |
| */ |
| Link<DartType> get typeVariables; |
| } |
| |
| abstract class ClassElement extends TypeDeclarationElement |
| implements ScopeContainerElement { |
| int get id; |
| |
| InterfaceType get rawType; |
| InterfaceType get thisType; |
| |
| ClassElement get superclass; |
| |
| DartType get supertype; |
| Link<DartType> get allSupertypes; |
| Link<DartType> get interfaces; |
| |
| bool get hasConstructor; |
| Link<Element> get constructors; |
| |
| ClassElement get patch; |
| ClassElement get origin; |
| ClassElement get declaration; |
| ClassElement get implementation; |
| |
| int get supertypeLoadState; |
| int get resolutionState; |
| SourceString get nativeTagInfo; |
| |
| bool get isMixinApplication; |
| bool get hasBackendMembers; |
| bool get hasLocalScopeMembers; |
| |
| // TODO(kasperl): These are bit fishy. Do we really need them? |
| void set thisType(InterfaceType value); |
| void set supertype(DartType value); |
| void set allSupertypes(Link<DartType> value); |
| void set interfaces(Link<DartType> value); |
| void set patch(ClassElement value); |
| void set origin(ClassElement value); |
| void set supertypeLoadState(int value); |
| void set resolutionState(int value); |
| void set nativeTagInfo(SourceString value); |
| |
| // TODO(kasperl): These seem outdated. |
| bool isInterface(); |
| DartType get defaultClass; |
| void set defaultClass(DartType value); |
| |
| bool isObject(Compiler compiler); |
| bool isSubclassOf(ClassElement cls); |
| bool implementsInterface(ClassElement intrface); |
| bool isShadowedByField(Element fieldMember); |
| |
| ClassElement ensureResolved(Compiler compiler); |
| |
| void addMember(Element element, DiagnosticListener listener); |
| void addToScope(Element element, DiagnosticListener listener); |
| |
| /** |
| * Add a synthetic nullary constructor if there are no other |
| * constructors. |
| */ |
| void addDefaultConstructorIfNeeded(Compiler compiler); |
| |
| void addBackendMember(Element element); |
| void reverseBackendMembers(); |
| |
| Element lookupMember(SourceString memberName); |
| Element lookupSelector(Selector selector); |
| Element lookupSuperSelector(Selector selector); |
| |
| Element lookupLocalMember(SourceString memberName); |
| Element lookupBackendMember(SourceString memberName); |
| Element lookupSuperMember(SourceString memberName); |
| |
| Element lookupSuperMemberInLibrary(SourceString memberName, |
| LibraryElement library); |
| |
| Element lookupSuperInterfaceMember(SourceString memberName, |
| LibraryElement fromLibrary); |
| |
| Element validateConstructorLookupResults(Selector selector, |
| Element result, |
| Element noMatch(Element)); |
| |
| Element lookupConstructor(Selector selector, [Element noMatch(Element)]); |
| Element lookupFactoryConstructor(Selector selector, |
| [Element noMatch(Element)]); |
| |
| void forEachMember(void f(ClassElement enclosingClass, Element member), |
| {includeBackendMembers: false, |
| includeSuperMembers: false}); |
| |
| void forEachInstanceField(void f(ClassElement enclosingClass, Element field), |
| {includeBackendMembers: false, |
| includeSuperMembers: false}); |
| |
| void forEachBackendMember(void f(Element member)); |
| } |
| |
| abstract class MixinApplicationElement extends ClassElement { |
| ClassElement get mixin; |
| void set mixin(ClassElement value); |
| } |
| |
| abstract class LabelElement extends Element { |
| Label get label; |
| String get labelName; |
| TargetElement get target; |
| |
| bool get isTarget; |
| bool get isBreakTarget; |
| bool get isContinueTarget; |
| |
| void setBreakTarget(); |
| void setContinueTarget(); |
| } |
| |
| abstract class TargetElement extends Element { |
| Node get statement; |
| int get nestingLevel; |
| Link<LabelElement> get labels; |
| |
| bool get isTarget; |
| bool get isBreakTarget; |
| bool get isContinueTarget; |
| bool get isSwitch; |
| |
| // TODO(kasperl): Try to get rid of these. |
| void set isBreakTarget(bool value); |
| void set isContinueTarget(bool value); |
| |
| LabelElement addLabel(Label label, String labelName); |
| } |
| |
| abstract class TypeVariableElement extends Element { |
| TypeVariableType get type; |
| DartType get bound; |
| |
| // TODO(kasperl): Try to get rid of these. |
| void set type(TypeVariableType value); |
| void set bound(DartType value); |
| } |
| |
| abstract class MetadataAnnotation implements Spannable { |
| Constant get value; |
| Element get annotatedElement; |
| int get resolutionState; |
| Token get beginToken; |
| Token get endToken; |
| |
| // TODO(kasperl): Try to get rid of these. |
| void set annotatedElement(Element value); |
| void set resolutionState(int value); |
| |
| MetadataAnnotation ensureResolved(Compiler compiler); |
| } |