Linter Demo Errors: 1Warnings: 5File: /home/fstrocco/Dart/dart/benchmark/compiler/lib/src/elements/elements.dart // 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 '../constants/expressions.dart'; import '../tree/tree.dart'; import '../util/util.dart'; import '../resolution/resolution.dart'; import '../dart2jslib.dart' show InterfaceType, DartType, TypeVariableType, TypedefType, DualKind, MessageKind, DiagnosticListener, Script, FunctionType, Selector, Constant, Compiler, Backend, isPrivateName; import '../dart_types.dart'; import '../helpers/helpers.dart'; import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator, isMinusOperator; import '../ordered_typeset.dart' show OrderedTypeSet; import 'visitor.dart' show ElementVisitor; part 'names.dart'; 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 INITIALIZING_FORMAL = const ElementKind('initializing_formal', 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 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 AMBIGUOUS = const ElementKind('ambiguous', ElementCategory.NONE); static const ElementKind WARN_ON_USE = const ElementKind('warn_on_use', ElementCategory.NONE); static const ElementKind ERROR = const ElementKind('error', ElementCategory.NONE); toString() => id; } /// Abstract interface for entities. /// /// Implement this directly if the entity is not a Dart language entity. /// Entities defined within the Dart language should implement [Element]. /// /// For instance, the JavaScript backend need to create synthetic variables for /// calling intercepted classes and such variables do not correspond to an /// entity in the Dart source code nor in the terminology of the Dart language /// and should therefore implement [Entity] directly. abstract class Entity implements Spannable { String get name; } /** * 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, List, 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 Entity { String get name; ElementKind get kind; Element get enclosingElement; Link get metadata; /// Do not use [computeType] outside of the resolver; instead retrieve the /// type from the corresponding field: /// - `type` for fields, variables, type variable, and function elements. /// - `thisType` or `rawType` for [TypeDeclarationElement]s (classes and /// typedefs), depending on the use case. /// Trying to access a type that has not been computed in resolution is an /// error and calling [computeType] covers that error. /// This method will go away! @deprecated DartType computeType(Compiler compiler); /// `true` if this element is a library. bool get isLibrary => kind == ElementKind.LIBRARY; /// `true` if this element is a compilation unit. bool get isCompilationUnit => kind == ElementKind.COMPILATION_UNIT; /// `true` if this element is defines the scope of prefix used by one or /// more import declarations. bool get isPrefix => kind == ElementKind.PREFIX; /// `true` if this element is a class declaration or a mixin application. bool get isClass => kind == ElementKind.CLASS; /// `true` if this element is a type variable declaration. bool get isTypeVariable => kind == ElementKind.TYPE_VARIABLE; /// `true` if this element is a typedef declaration. bool get isTypedef => kind == ElementKind.TYPEDEF; /// `true` if this element is a top level function, static or instance /// method, local function or closure defined by a function expression. /// /// This property is `true` for operator methods and factory constructors but /// `false` for getter and setter methods, and generative constructors. /// /// See also [isConstructor], [isGenerativeConstructor], and /// [isFactoryConstructor] for constructor properties, and [isAccessor], /// [isGetter] and [isSetter] for getter/setter properties. bool get isFunction => kind == ElementKind.FUNCTION; /// `true` if this element is an operator method. bool get isOperator; /// `true` if this element is an accessor, that is either an explicit /// getter or an explicit setter. bool get isAccessor => isGetter || isSetter; /// `true` if this element is an explicit getter method. bool get isGetter => kind == ElementKind.GETTER; /// `true` if this element is an explicit setter method. bool get isSetter => kind == ElementKind.SETTER; /// `true` if this element is a generative or factory constructor. bool get isConstructor => isGenerativeConstructor || isFactoryConstructor; /// `true` if this element is a generative constructor, potentially /// redirecting. bool get isGenerativeConstructor => kind == ElementKind.GENERATIVE_CONSTRUCTOR; /// `true` if this element is the body of a generative constructor. /// /// This is a synthetic element kind used only be the JavaScript backend. bool get isGenerativeConstructorBody => kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY; /// `true` if this element is a factory constructor, /// potentially redirecting. bool get isFactoryConstructor; /// `true` if this element is a local variable. bool get isVariable => kind == ElementKind.VARIABLE; /// `true` if this element is a top level variable, static or instance field. bool get isField => kind == ElementKind.FIELD; /// `true` if this element is the abstract field implicitly defined by an /// explicit getter and/or setter. bool get isAbstractField => kind == ElementKind.ABSTRACT_FIELD; /// `true` if this element is formal parameter either from a constructor, /// method, or typedef declaration or from an inlined function typed /// parameter. /// /// This property is `false` if this element is an initializing formal. /// See [isInitializingFormal]. bool get isParameter => kind == ElementKind.PARAMETER; /// `true` if this element is an initializing formal of constructor, that /// is a formal of the form `this.foo`. bool get isInitializingFormal => kind == ElementKind.INITIALIZING_FORMAL; /// `true` if this element represents a resolution error. bool get isErroneous => kind == ElementKind.ERROR; /// `true` if this element represents an ambiguous name. /// /// Ambiguous names occur when two imports/exports contain different entities /// by the same name. If an ambiguous name is resolved an warning or error /// is produced. bool get isAmbiguous => kind == ElementKind.AMBIGUOUS; /// `true` if this element represents an entity whose access causes one or /// more warnings. bool get isWarnOnUse => kind == ElementKind.WARN_ON_USE; bool get isClosure; /// `true` if the element is a (static or instance) member of a class. /// /// Members are constructors, methods and fields. bool get isClassMember; /// `true` if the element is a nonstatic member of a class. /// /// Instance members are methods and fields but not constructors. bool get isInstanceMember; /// Returns true if this [Element] is a top level element. /// That is, if it is not defined within the scope of a class. /// /// This means whether the enclosing element is a compilation unit. /// With the exception of [ClosureClassElement] that is considered top level /// as all other classes. bool get isTopLevel; bool get isAssignable; bool get isNative; bool get isDeferredLoaderGetter; /// True if the element is declared in a patch library but has no /// corresponding declaration in the origin library. bool get isInjected; /// `true` if this element is a constructor, top level or local variable, /// or static field that is declared `const`. bool get isConst; /// `true` if this element is a top level or local variable, static or /// instance field, or parameter that is declared `final`. bool get isFinal; /// `true` if this element is a method, getter, setter or field that /// is declared `static`. bool get isStatic; /// `true` if this element is local element, that is, a local variable, /// local function or parameter. bool get isLocal; bool get impliesType; Token get position; CompilationUnitElement get compilationUnit; LibraryElement get library; LibraryElement get implementationLibrary; ClassElement get enclosingClass; Element get enclosingClassOrCompilationUnit; Element get outermostEnclosingMemberOrTopLevel; // TODO(johnniwinther): Replace uses of this with [enclosingClass] when // [ClosureClassElement] has been removed. /// The enclosing class that defines the type environment for this element. ClassElement get contextClass; FunctionElement asFunctionElement(); /// Is [:true:] if this element has a corresponding patch. /// /// If [:true:] this element has a non-null [patch] field. /// /// See [:patch_parser.dart:] for a description of the terminology. bool get isPatched; /// Is [:true:] if this element is a patch. /// /// If [:true:] this element has a non-null [origin] field. /// /// See [:patch_parser.dart:] for a description of the terminology. bool get isPatch; /// Is [:true:] if this element defines the implementation for the entity of /// this element. /// /// See [:patch_parser.dart:] for a description of the terminology. bool get isImplementation; /// Is [:true:] if this element introduces the entity of this element. /// /// See [:patch_parser.dart:] for a description of the terminology. bool get isDeclaration; /// Returns the element which defines the implementation for the entity of /// this element. /// /// See [:patch_parser.dart:] for a description of the terminology. Element get implementation; /// Returns the element which introduces the entity of this element. /// /// See [:patch_parser.dart:] for a description of the terminology. Element get declaration; /// Returns the patch for this element if this element is patched. /// /// See [:patch_parser.dart:] for a description of the terminology. Element get patch; /// Returns the origin for this element if this element is a patch. /// /// See [:patch_parser.dart:] for a description of the terminology. Element get origin; bool get isSynthesized; bool get isMixinApplication; bool get hasFixedBackendName; String get fixedBackendName; bool get isAbstract; bool isForeign(Backend backend); void addMetadata(MetadataAnnotation annotation); void setNative(String name); Scope buildScope(); void diagnose(Element context, DiagnosticListener listener); // TODO(johnniwinther): Move this to [AstElement]. /// Returns the [Element] that holds the [TreeElements] for this element. AnalyzableElement get analyzableElement; accept(ElementVisitor visitor); } class Elements { static bool isUnresolved(Element e) { return e == null || e.isErroneous; } static bool isErroneous(Element e) => e != null && e.isErroneous; /// Unwraps [element] reporting any warnings attached to it, if any. static Element unwrap(Element element, DiagnosticListener listener, Spannable spannable) { if (element != null && element.isWarnOnUse) { WarnOnUseElement wrappedElement = element; element = wrappedElement.unwrap(listener, spannable); } return element; } 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.isLocal; } 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(johnniwinther): Clean this up. This currently returns true for a // PartialConstructorElement, SynthesizedConstructorElementX, and // TypeVariableElementX though neither `element.isStatic` nor // `element.isTopLevel` is true. if (Elements.isUnresolved(element)) return false; if (element.isStatic || element.isTopLevel) return true; return !element.isAmbiguous && !element.isInstanceMember && !element.isPrefix && element.enclosingElement != null && (element.enclosingElement.kind == ElementKind.CLASS || element.enclosingElement.kind == ElementKind.COMPILATION_UNIT || element.enclosingElement.kind == ElementKind.LIBRARY || element.enclosingElement.kind == ElementKind.PREFIX); } static bool isInStaticContext(Element element) { if (isUnresolved(element)) return true; if (element.enclosingElement.isClosure) { var closureClass = element.enclosingElement; element = closureClass.methodElement; } Element outer = element.outermostEnclosingMemberOrTopLevel; 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)); } /// Also returns true for [ConstructorBodyElement]s and getters/setters. static bool isNonAbstractInstanceMember(Element element) { // The generative constructor body is not a function. We therefore treat // it specially. if (element.isGenerativeConstructorBody) return true; return !Elements.isUnresolved(element) && !element.isAbstract && element.isInstanceMember && (element.isFunction || element.isAccessor); } static bool isNativeOrExtendsNative(ClassElement element) { if (element == null) return false; if (element.isNative) return true; assert(element.resolutionState == STATE_DONE); return isNativeOrExtendsNative(element.superclass); } 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 String reconstructConstructorNameSourceString(Element element) { if (element.name == '') { return element.enclosingClass.name; } else { return reconstructConstructorName(element); } } // TODO(johnniwinther): Remove this method. static String reconstructConstructorName(Element element) { String className = element.enclosingClass.name; if (element.name == '') { return className; } else { return '$className\$${element.name}'; } } static String constructorNameForDiagnostics(String className, String constructorName) { String classNameString = className; String constructorNameString = constructorName; return (constructorName == '') ? classNameString : "$classNameString.$constructorNameString"; } /// Returns `true` if [name] is the name of an operator method. static bool isOperatorName(String name) { return name == 'unary-' || isUserDefinableOperator(name); } /** * Map an operator-name to a valid JavaScript identifier. * * For non-operator names, this method 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 String operatorNameToIdentifier(String name) { if (name == null) { return name; } else if (identical(name, '==')) { return r'operator$eq'; } else if (identical(name, '~')) { return r'operator$not'; } else if (identical(name, '[]')) { return r'operator$index'; } else if (identical(name, '[]=')) { return r'operator$indexSet'; } else if (identical(name, '*')) { return r'operator$mul'; } else if (identical(name, '/')) { return r'operator$div'; } else if (identical(name, '%')) { return r'operator$mod'; } else if (identical(name, '~/')) { return r'operator$tdiv'; } else if (identical(name, '+')) { return r'operator$add'; } else if (identical(name, '<<')) { return r'operator$shl'; } else if (identical(name, '>>')) { return r'operator$shr'; } else if (identical(name, '>=')) { return r'operator$ge'; } else if (identical(name, '>')) { return r'operator$gt'; } else if (identical(name, '<=')) { return r'operator$le'; } else if (identical(name, '<')) { return r'operator$lt'; } else if (identical(name, '&')) { return r'operator$and'; } else if (identical(name, '^')) { return r'operator$xor'; } else if (identical(name, '|')) { return r'operator$or'; } else if (identical(name, '-')) { return r'operator$sub'; } else if (identical(name, 'unary-')) { return r'operator$negate'; } else { return name; } } static String constructOperatorNameOrNull(String op, bool isUnary) { if (isMinusOperator(op)) { return isUnary ? 'unary-' : op; } else if (isUserDefinableOperator(op)) { return op; } else { return null; } } static String constructOperatorName(String op, bool isUnary) { String operatorName = constructOperatorNameOrNull(op, isUnary); if (operatorName == null) throw 'Unhandled operator: $op'; else return operatorName; } static String mapToUserOperatorOrNull(String op) { if (identical(op, '!=')) return '=='; if (identical(op, '*=')) return '*'; if (identical(op, '/=')) return '/'; if (identical(op, '%=')) return '%'; if (identical(op, '~/=')) return '~/'; if (identical(op, '+=')) return '+'; if (identical(op, '-=')) return '-'; if (identical(op, '<<=')) return '<<'; if (identical(op, '>>=')) return '>>'; if (identical(op, '&=')) return '&'; if (identical(op, '^=')) return '^'; if (identical(op, '|=')) return '|'; return null; } static String mapToUserOperator(String op) { String userOperator = mapToUserOperatorOrNull(op); if (userOperator == null) throw 'Unhandled operator: $op'; else return userOperator; } static bool isNumberOrStringSupertype(Element element, Compiler compiler) { LibraryElement coreLibrary = compiler.coreLibrary; return (element == coreLibrary.find('Comparable')); } static bool isStringOnlySupertype(Element element, Compiler compiler) { LibraryElement coreLibrary = compiler.coreLibrary; return element == coreLibrary.find('Pattern'); } static bool isListSupertype(Element element, Compiler compiler) { LibraryElement coreLibrary = compiler.coreLibrary; return element == coreLibrary.find('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) { if (identical(a, b)) return 0; int r = a.library.compareTo(b.library); if (r != 0) return r; r = a.compilationUnit.compareTo(b.compilationUnit); if (r != 0) return r; Token positionA = a.position; Token positionB = b.position; int offsetA = positionA == null ? -1 : positionA.charOffset; int offsetB = positionB == null ? -1 : positionB.charOffset; r = offsetA.compareTo(offsetB); if (r != 0) return r; r = a.name.compareTo(b.name); 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 sortedByPosition(Iterable 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; } static bool isFilledListConstructorCall(Element element, Send node, Compiler compiler) { return element == compiler.filledListConstructor && node.isCall && !node.arguments.isEmpty && !node.arguments.tail.isEmpty && node.arguments.tail.tail.isEmpty; } static bool isConstructorOfTypedArraySubclass(Element element, Compiler compiler) { if (compiler.typedDataLibrary == null) return false; if (!element.isConstructor) return false; ConstructorElement constructor = element.implementation; constructor = constructor.effectiveTarget; ClassElement cls = constructor.enclosingClass; return cls.library == compiler.typedDataLibrary && cls.isNative && compiler.world.isSubtypeOf(cls, compiler.typedDataClass) && compiler.world.isSubtypeOf(cls, compiler.listClass) && constructor.name == ''; } static bool switchStatementHasContinue(SwitchStatement node, TreeElements elements) { for (SwitchCase switchCase in node.cases) { for (Node labelOrCase in switchCase.labelsAndCases) { Node label = labelOrCase.asLabel(); if (label != null) { LabelDefinition labelElement = elements.getLabelDefinition(label); if (labelElement != null && labelElement.isContinueTarget) { return true; } } } } return false; } static bool isUnusedLabel(LabeledStatement node, TreeElements elements) { Node body = node.statement; JumpTarget element = elements.getTargetDefinition(body); // Labeled statements with no element on the body have no breaks. // A different target statement only happens if the body is itself // a break or continue for a different target. In that case, this // label is also always unused. return element == null || element.statement != body; } } /// An element representing an erroneous resolution. /// /// An [ErroneousElement] is used instead of `null` to provide additional /// information about the error that caused the element to be unresolvable /// or otherwise invalid. /// /// Accessing any field or calling any method defined on [ErroneousElement] /// except [isErroneous] will currently throw an exception. (This might /// change when we actually want more information on the erroneous element, /// e.g., the name of the element we were trying to resolve.) /// /// Code that cannot not handle an [ErroneousElement] should use /// `Element.isUnresolved(element)` to check for unresolvable elements instead /// of `element == null`. abstract class ErroneousElement extends Element implements ConstructorElement { MessageKind get messageKind; Map get messageArguments; String get message; } /// An [Element] whose usage should cause one or more warnings. abstract class WarnOnUseElement extends Element { /// The element whose usage cause a warning. Element get wrappedElement; /// Reports the attached warning and returns the wrapped element. /// [usageSpannable] is used to report messages on the reference of /// [wrappedElement]. Element unwrap(DiagnosticListener listener, Spannable usageSpannable); } /// An ambiguous element represents multiple elements accessible by the same /// name. /// /// Ambiguous elements are created during handling of import/export scopes. If /// an ambiguous element is encountered during resolution a warning/error is /// reported. 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 implements Element { Element localLookup(String elementName); void forEachLocalMember(f(Element element)); } abstract class CompilationUnitElement extends Element { Script get script; PartOf get partTag; void forEachLocalMember(f(Element element)); void addMember(Element element, DiagnosticListener listener); void setPartOf(PartOf tag, DiagnosticListener listener); bool get hasMembers; int compareTo(CompilationUnitElement other); } abstract class LibraryElement extends Element implements ScopeContainerElement, AnalyzableElement { /** * 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; /// Returns `true` if this library is 'dart:core'. bool get isDartCore; CompilationUnitElement get entryCompilationUnit; Link get compilationUnits; Iterable get tags; LibraryName get libraryTag; Link 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 from a package, that is, its canonical uri has * the scheme 'package'. */ bool get isPackageLibrary; /** * [: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 libraryTag(LibraryName value); LibraryElement get implementation; void addCompilationUnit(CompilationUnitElement element); void addTag(LibraryTag tag, DiagnosticListener listener); void addImport(Element element, Import import, 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 getNonPrivateElementsInScope(); void setExports(Iterable exportedElements); Element find(String elementName); Element findLocal(String elementName); Element findExported(String elementName); void forEachExport(f(Element element)); /// Returns the imports that import element into this library. Link getImportsFor(Element element); bool hasLibraryName(); String getLibraryName(); String getLibraryOrScriptName(); int compareTo(LibraryElement other); } /// The implicit scope defined by a import declaration with a prefix clause. abstract class PrefixElement extends Element { void addImport(Element element, Import import, DiagnosticListener listener); Element lookupLocalMember(String memberName); /// Is true if this prefix belongs to a deferred import. bool get isDeferred; void markAsDeferred(Import import); Import get deferredImport; } /// A type alias definition. abstract class TypedefElement extends Element implements AstElement, TypeDeclarationElement, FunctionTypedElement { /// The type defined by this typedef with the type variables as its type /// arguments. /// /// For instance `F` for `typedef void F(T t)`. TypedefType get thisType; /// The type defined by this typedef with `dynamic` as its type arguments. /// /// For instance `F` for `typedef void F(T t)`. TypedefType get rawType; /// The type, function type if well-defined, for which this typedef is an /// alias. /// /// For instance `(int)->void` for `typedef void F(int)`. DartType get alias; void checkCyclicReference(Compiler compiler); } /// An executable element is an element that can hold code. /// /// These elements variables (fields, parameters and locals), which can hold /// code in their initializer, and functions (including methods and /// constructors), which can hold code in their body. abstract class ExecutableElement extends Element implements TypedElement, AstElement { /// The outermost member that contains this element. /// /// For top level, static or instance members, the member context is the /// element itself. For parameters, local variables and nested closures, the /// member context is the top level, static or instance member in which it is /// defined. MemberElement get memberContext; } /// A top-level, static or instance field or method, or a constructor. /// /// A [MemberElement] is the outermost executable element for any executable /// context. abstract class MemberElement extends Element implements ExecutableElement { /// The local functions defined within this member. List get nestedClosures; /// The name of this member taking privacy into account. Name get memberName; } /// A function, variable or parameter defined in an executable context. abstract class LocalElement extends Element implements TypedElement, Local { } /// A top level, static or instance field, a formal parameter or local variable. abstract class VariableElement extends ExecutableElement { Expression get initializer; } /// An entity that defines a local entity (memory slot) in generated code. /// /// Parameters, local variables and local functions (can) define local entity /// and thus implement [Local] through [LocalElement]. For non-element locals, /// like `this` and boxes, specialized [Local] classes are created. /// /// Type variables can introduce locals in factories and constructors /// but since one type variable can introduce different locals in different /// factories and constructors it is not itself a [Local] but instead /// a non-element [Local] is created through a specialized class. // TODO(johnniwinther): Should [Local] have `isAssignable` or `type`? abstract class Local extends Entity { /// The context in which this local is defined. ExecutableElement get executableContext; } /// A variable or parameter that is local to an executable context. /// /// The executable context is the [ExecutableElement] in which this variable /// is defined. abstract class LocalVariableElement extends VariableElement implements LocalElement { } /// A top-level, static or instance field. abstract class FieldElement extends VariableElement implements MemberElement { } /// A parameter-like element of a function signature. /// /// If the function signature comes from a typedef or an inline function-typed /// parameter (e.g. the parameter 'f' in `method(void f())`), then its /// parameters are not real parameters in that they can take no argument and /// hold no value. Such parameter-like elements are modeled by [FormalElement]. /// /// If the function signature comes from a function or constructor, its /// parameters are real parameters and are modeled by [ParameterElement]. abstract class FormalElement extends Element implements FunctionTypedElement, TypedElement, AstElement { /// Use [functionDeclaration] instead. @deprecated get enclosingElement; /// The function, typedef or inline function-typed parameter on which /// this parameter is declared. FunctionTypedElement get functionDeclaration; VariableDefinitions get node; } /// A formal parameter of a function or constructor. /// /// Normal parameter that introduce a local variable are modeled by /// [LocalParameterElement] whereas initializing formals, that is parameter of /// the form `this.x`, are modeled by [InitializingFormalParameter]. abstract class ParameterElement extends Element implements VariableElement, FormalElement, LocalElement { /// Use [functionDeclaration] instead. @deprecated get enclosingElement; /// The function on which this parameter is declared. FunctionElement get functionDeclaration; /// `true` if this parameter is named. bool get isNamed; /// `true` if this parameter is optional. bool get isOptional; } /// A formal parameter on a function or constructor that introduces a local /// variable in the scope of the function or constructor. abstract class LocalParameterElement extends ParameterElement implements LocalVariableElement { } /// A formal parameter in a constructor that directly initializes a field. /// /// For example: `A(this.field)`. abstract class InitializingFormalElement extends ParameterElement { /// The field initialized by this initializing formal. FieldElement get fieldElement; /// The function on which this parameter is declared. ConstructorElement get functionDeclaration; } /** * 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 { FunctionType get type; Link get requiredParameters; Link get optionalParameters; int get requiredParameterCount; int get optionalParameterCount; bool get optionalParametersAreNamed; FormalElement get firstOptionalParameter; bool get hasOptionalParameters; int get parameterCount; List get orderedOptionalParameters; void forEachParameter(void function(FormalElement parameter)); void forEachRequiredParameter(void function(FormalElement parameter)); void forEachOptionalParameter(void function(FormalElement parameter)); void orderedForEachParameter(void function(FormalElement parameter)); bool isCompatibleWith(FunctionSignature constructorSignature); } /// A top level, static or instance method, constructor, local function, or /// closure (anonymous local function). abstract class FunctionElement extends Element implements AstElement, TypedElement, FunctionTypedElement, ExecutableElement { FunctionExpression get node; FunctionElement get patch; FunctionElement get origin; /// Used to retrieve a link to the abstract field element representing this /// element. AbstractFieldElement get abstractField; /// Do not use [computeSignature] outside of the resolver; instead retrieve /// the signature through the [functionSignature] field. /// Trying to access a function signature that has not been computed in /// resolution is an error and calling [computeSignature] covers that error. /// This method will go away! // TODO(johnniwinther): Rename to `ensureFunctionSignature`. @deprecated FunctionSignature computeSignature(Compiler compiler); bool get hasFunctionSignature; /// The parameters of this functions. List get parameters; /// The type of this function. FunctionType get type; /// The synchronous/asynchronous marker on this function. AsyncMarker get asyncMarker; /// `true` if this function is external. bool get isExternal; } /// Enum for the synchronous/asynchronous function body modifiers. class AsyncMarker { /// The default function body marker. static const AsyncMarker SYNC = const AsyncMarker._(); /// The `sync*` function body marker. static const AsyncMarker SYNC_STAR = const AsyncMarker._(isYielding: true); /// The `async` function body marker. static const AsyncMarker ASYNC = const AsyncMarker._(isAsync: true); /// The `async*` function body marker. static const AsyncMarker ASYNC_STAR = const AsyncMarker._(isAsync: true, isYielding: true); /// Is `true` if this marker defines the function body to have an /// asynchronous result, that is, either a [Future] or a [Stream]. final bool isAsync; /// Is `true` if this marker defines the function body to have a plural /// result, that is, either an [Iterable] or a [Stream]. final bool isYielding; const AsyncMarker._({this.isAsync: false, this.isYielding: false}); String toString() { return '${isAsync ? 'async' : 'sync'}${isYielding ? '*' : ''}'; } } /// A top level, static or instance function. abstract class MethodElement extends FunctionElement implements MemberElement { } /// A local function or closure (anonymous local function). abstract class LocalFunctionElement extends FunctionElement implements LocalElement { } /// A constructor. abstract class ConstructorElement extends FunctionElement implements MemberElement { /// The effective target of this constructor, that is the non-redirecting /// constructor that is called on invocation of this constructor. /// /// Consider for instance this hierachy: /// /// class C { factory C.c() = D.d; } /// class D { factory D.d() = E.e2; } /// class E { E.e1(); /// E.e2() : this.e1(); } /// /// The effective target of both `C.c`, `D.d`, and `E.e2` is `E.e2`, and the /// effective target of `E.e1` is `E.e1` itself. ConstructorElement get effectiveTarget; /// The immediate redirection target of a redirecting factory constructor. /// /// Consider for instance this hierachy: /// /// class C { factory C() = D; } /// class D { factory D() = E; } /// class E { E(); } /// /// The immediate redirection target of `C` is `D` and the immediate /// redirection target of `D` is `E`. `E` is not a redirecting factory /// constructor so its immediate redirection target is `null`. ConstructorElement get immediateRedirectionTarget; /// Is `true` if this constructor is a redirecting generative constructor. bool get isRedirectingGenerative; /// Is `true` if this constructor is a redirecting factory constructor. bool get isRedirectingFactory; /// Compute the type of the effective target of this constructor for an /// instantiation site with type [:newType:]. InterfaceType computeEffectiveTargetType(InterfaceType newType); /// If this is a synthesized constructor [definingConstructor] points to /// the generative constructor from which this constructor was created. /// Otherwise [definingConstructor] is `null`. /// /// Consider for instance this hierarchy: /// /// class C { C.c(a, {b}); /// class D {} /// class E = C with D; /// /// Class `E` has a synthesized constructor, `E.c`, whose defining constructor /// is `C.c`. ConstructorElement get definingConstructor; /// Use [enclosingClass] instead. @deprecated get enclosingElement; } /// JavaScript backend specific element for the body of constructor. // TODO(johnniwinther): Remove this class from the element model. abstract class ConstructorBodyElement extends MethodElement { FunctionElement get constructor; } /// [TypeDeclarationElement] defines the common interface for class/interface /// declarations and typedefs. abstract class TypeDeclarationElement extends Element implements AstElement { /** * The `this type` for this type declaration. * * The type of [:this:] is the generic type based on this element in which * the type arguments are the declared type variables. For instance, * [:List:] for [:List:] and [:Map:] for [:Map:]. * * For a class declaration this is the type of [:this:]. */ GenericType get thisType; /** * The raw type for this type declaration. * * The raw type is the generic type base on this element in which the type * arguments are all [dynamic]. For instance [:List:] for [:List:] * and [:Map:] for [:Map:]. For non-generic classes [rawType] * is the same as [thisType]. * * The [rawType] field is a canonicalization of the raw type and should be * used to distinguish explicit and implicit uses of the [dynamic] * type arguments. For instance should [:List:] be the [rawType] of the * [:List:] class element whereas [:List:] should be its own * instantiation of [InterfaceType] with [:dynamic:] as type argument. Using * this distinction, we can print the raw type with type arguments only when * the input source has used explicit type arguments. */ 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]. */ List get typeVariables; bool get isResolved; int get resolutionState; void ensureResolved(Compiler compiler); } abstract class ClassElement extends TypeDeclarationElement implements ScopeContainerElement { int get id; /// The length of the longest inheritance path from [:Object:]. int get hierarchyDepth; InterfaceType get rawType; InterfaceType get thisType; ClassElement get superclass; /// The direct supertype of this class. DartType get supertype; /// Ordered set of all supertypes of this class including the class itself. OrderedTypeSet get allSupertypesAndSelf; /// A list of all supertypes of this class excluding the class itself. Link get allSupertypes; /// Returns the this type of this class as an instance of [cls]. InterfaceType asInstanceOf(ClassElement cls); /// A list of all direct superinterfaces of this class. Link get interfaces; bool get hasConstructor; Link get constructors; ClassElement get patch; ClassElement get origin; ClassElement get declaration; ClassElement get implementation; int get supertypeLoadState; String get nativeTagInfo; /// `true` if this class is an enum declaration. bool get isEnumClass; bool get isMixinApplication; bool get isUnnamedMixinApplication; bool get hasBackendMembers; bool get hasLocalScopeMembers; /// Returns `true` if this class is `Object` from dart:core. bool get isObject; /// Returns `true` if this class implements [Function] either by directly /// implementing the interface or by providing a [call] method. bool implementsFunction(Compiler compiler); bool isSubclassOf(ClassElement cls); /// Returns true if `this` explicitly/nominally implements [intrface]. /// /// Note that, if [intrface] is the `Function` class, this method returns /// false for a class that has a `call` method but does not explicitly /// implement `Function`. bool implementsInterface(ClassElement intrface); bool hasFieldShadowedBy(Element fieldMember); /// Returns `true` if this class has a @proxy annotation. bool get isProxy; /// Returns `true` if the class hierarchy for this class contains errors. bool get hasIncompleteHierarchy; void addMember(Element element, DiagnosticListener listener); void addToScope(Element element, DiagnosticListener listener); void addBackendMember(Element element); void reverseBackendMembers(); Element lookupMember(String memberName); Element lookupSelector(Selector selector); Element lookupSuperSelector(Selector selector); Element lookupLocalMember(String memberName); Element lookupBackendMember(String memberName); Element lookupSuperMember(String memberName); Element lookupSuperMemberInLibrary(String memberName, LibraryElement library); ConstructorElement lookupDefaultConstructor(); ConstructorElement lookupConstructor(String name); void forEachMember(void f(ClassElement enclosingClass, Element member), {bool includeBackendMembers: false, bool includeSuperAndInjectedMembers: false}); void forEachInstanceField(void f(ClassElement enclosingClass, FieldElement field), {bool includeSuperAndInjectedMembers: false}); /// Similar to [forEachInstanceField] but visits static fields. void forEachStaticField(void f(ClassElement enclosingClass, Element field)); void forEachBackendMember(void f(Element member)); List computeTypeParameters(Compiler compiler); /// Looks up the member [name] in this class. Member lookupClassMember(Name name); /// Calls [f] with each member of this class. void forEachClassMember(f(Member member)); /// Looks up the member [name] in the interface of this class. MemberSignature lookupInterfaceMember(Name name); /// Calls [f] with each member of the interface of this class. void forEachInterfaceMember(f(MemberSignature member)); /// Returns the type of the 'call' method in the interface of this class, or /// `null` if the interface has no 'call' method. FunctionType get callType; } abstract class MixinApplicationElement extends ClassElement { ClassElement get mixin; InterfaceType get mixinType; void set mixinType(InterfaceType value); void addConstructor(FunctionElement constructor); } /// Enum declaration. abstract class EnumClassElement extends ClassElement { /// The static fields implied by the enum values. List get enumValues; } /// The label entity defined by a labeled statement. abstract class LabelDefinition extends Entity { Label get label; String get labelName; JumpTarget get target; bool get isTarget; bool get isBreakTarget; bool get isContinueTarget; void setBreakTarget(); void setContinueTarget(); } /// A jump target is the reference point of a statement or switch-case, /// either by label or as the default target of a break or continue. abstract class JumpTarget extends Local { Node get statement; int get nestingLevel; Link 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); LabelDefinition addLabel(Label label, String labelName); } /// The [Element] for a type variable declaration on a generic class or typedef. abstract class TypeVariableElement extends Element implements AstElement, TypedElement { /// Use [typeDeclaration] instead. @deprecated get enclosingElement; /// The class or typedef on which this type variable is defined. TypeDeclarationElement get typeDeclaration; /// The [type] defined by the type variable. TypeVariableType get type; /// The upper bound on the type variable. If not explicitly declared, this is /// `Object`. DartType get bound; } abstract class MetadataAnnotation implements Spannable { /// The front-end constant of this metadata annotation. ConstantExpression get constant; Element get annotatedElement; int get resolutionState; Token get beginToken; Token get endToken; bool get hasNode; Node get node; MetadataAnnotation ensureResolved(Compiler compiler); } /// An [Element] that has a type. abstract class TypedElement extends Element { DartType get type; } /// An [Element] that can define a function type. abstract class FunctionTypedElement extends Element { /// The function signature for the function type defined by this element, /// if any. FunctionSignature get functionSignature; } /// An [Element] that holds a [TreeElements] mapping. abstract class AnalyzableElement extends Element { /// Return `true` if [treeElements] have been (partially) computed for this /// element. bool get hasTreeElements; /// Returns the [TreeElements] that hold the resolution information for the /// AST nodes of this element. TreeElements get treeElements; } /// An [Element] that (potentially) has a node. /// /// Synthesized elements may return `null` from [node]. abstract class AstElement extends AnalyzableElement { /// `true` if [node] is available and non-null. bool get hasNode; /// The AST node of this element. Node get node; /// `true` if [resolvedAst] is available. bool get hasResolvedAst; /// The defining AST node of this element with is corresponding /// [TreeElements]. This is not available if [hasResolvedAst] is `false`. ResolvedAst get resolvedAst; } class ResolvedAst { final Element element; final Node node; final TreeElements elements; ResolvedAst(this.element, this.node, this.elements); } /// A [MemberSignature] is a member of an interface. /// /// A signature is either a method or a getter or setter, possibly implicitly /// defined by a field declarations. Fields themselves are not members of an /// interface. /// /// A [MemberSignature] may be defined by a member declaration or may be /// synthetized from a set of declarations. abstract class MemberSignature { /// The name of this member. Name get name; /// The type of the member when accessed. For getters and setters this is the /// return type and argument type, respectively. For methods the type is the /// [functionType] defined by the return type and parameters. DartType get type; /// The function type of the member. For a getter `Foo get foo` this is /// `() -> Foo`, for a setter `void set foo(Foo _)` this is `(Foo) -> void`. /// For methods the function type is defined by the return type and /// parameters. FunctionType get functionType; /// Returns `true` if this member is a getter, possibly implictly defined by a /// field declaration. bool get isGetter; /// Returns `true` if this member is a setter, possibly implictly defined by a /// field declaration. bool get isSetter; /// Returns `true` if this member is a method, that is neither a getter nor /// setter. bool get isMethod; /// Returns an iterable of the declarations that define this member. Iterable get declarations; } /// A [Member] is a member of a class, that is either a method or a getter or /// setter, possibly implicitly defined by a field declarations. Fields /// themselves are not members of a class. /// /// A [Member] of a class also defines a signature which is a member of the /// corresponding interface type. /// /// A [Member] is implicitly concrete. An abstract declaration only declares /// a signature in the interface of its class. /// /// A [Member] is always declared by an [Element] which is accessibly through /// the [element] getter. abstract class Member extends MemberSignature { /// The [Element] that declared this member, possibly implicitly in case of /// a getter or setter defined by a field. Element get element; /// The instance of the class that declared this member. /// /// For instance: /// class A { T m() {} } /// class B extends A {} /// The declarer of `m` in `A` is `A` whereas the declarer of `m` in `B` is /// `A`. InterfaceType get declarer; /// Returns `true` if this member is static. bool get isStatic; /// Returns `true` if this member is a getter or setter implicitly declared /// by a field. bool get isDeclaredByField; /// Returns `true` if this member is abstract. bool get isAbstract; /// If abstract, [implementation] points to the overridden concrete member, /// if any. Otherwise [implementation] points to the member itself. Member get implementation; }