# The Element Model

The element model, together with the [type][type] model, describes the semantic
(as opposed to syntactic) structure of Dart code. The syntactic structure of the
code is modeled by the [AST][ast].

Generally speaking, an element represents something that is declared in the
code, such as a class, method, or variable. Elements can be explicitly declared,
such as the class defined by a class declaration, or implicitly declared, such
as the default constructor defined for classes that do not have any explicit
constructor declarations. Elements that are implicitly declared are referred to
as _synthetic_ elements.

There are a few elements that represent entities that are not declared. For
example, there is an element representing a compilation unit (`.dart` file) and
another representing a library.

## The Structure of the Element Model

Elements are organized in a tree structure in which the children of an element
are the elements that are logically (and often syntactically) part of the
declaration of the parent. For example, the elements representing the methods
and fields in a class are children of the element representing the class.

Every complete element structure is rooted by an instance of the class
`LibraryElement`. A library element represents a single Dart library. Every
library is defined by one or more compilation units (the library and all of its
parts). The compilation units are represented by the class
`CompilationUnitElement` and are children of the library that is defined by
them. Each compilation unit can contain zero or more top-level declarations,
such as classes, functions, and variables. Each of these is in turn
represented as an element that is a child of the compilation unit. Classes
contain methods and fields, methods can contain local variables, etc.

The element model does not contain everything in the code, only those things
that are declared by the code. For example, it does not include any
representation of the statements in a method body, but if one of those
statements declares a local variable then the local variable will be represented
by an element.

## Getting a Compilation Unit Element

If you have followed the steps in [Performing Analysis][analysis], and you want
to get the compilation unit element for a file at a known `path`, then you can
ask the analysis session for the compilation unit representing that file.

```dart
void analyzeSingleFile(AnalysisSession session, String path) async {
  var result = await session.getUnitElement(path);
  if (result is UnitElementResult) {
    LibraryFragment element = result.fragment;
  }
}
```

(If you also need the resolved AST for the file, you can ask the session to
`getResolvedAst`, and the returned result will have the library element for the
library containing the compilation unit.)

## Traversing the Structure

There are two ways to traverse the structure of an AST: getters and visitors.

### Getters

Every element defines getters for accessing the parent and the children of that
element. Those getters can be used to traverse the structure, and are often the
most efficient way of doing so. For example, if you wanted to write a utility to
print the names of all of the members of each class in a given library,
it might look something like this:

```dart
void printMembers(LibraryElement libraryElement) {
  for (ClassElement classElement in libraryElement.classes) {
    print(classElement.name);
    for (ConstructorElement constructorElement in classElement.constructors) {
      if (!constructorElement.isSynthetic) {
        print('  ${constructorElement.displayName}');
      }
    }
    for (FieldElement fieldElement in classElement.fields) {
      if (!fieldElement.isSynthetic) {
        print('  ${fieldElement.name}');
      }
    }
    for (GetterElement getterElement in classElement.getters) {
      if (!getterElement.isSynthetic) {
        print('  ${getterElement.name}');
      }
    }
    for (SetterElement setterElement in classElement.setters) {
      if (!setterElement.isSynthetic) {
        print('  ${setterElement.name}');
      }
    }
    for (MethodElement methodElement in classElement.methods) {
      if (!methodElement.isSynthetic) {
        print('  ${methodElement.name}');
      }
    }
  }
}
```

### Visitors

Getters work well for most uses, but there might be times when it is easier to
use a visitor pattern.

Getters work well for cases like the above because compilation units cannot be
nested inside other compilation units, classes cannot be nested inside other
classes, etc. But when you're dealing with a structure that can be nested inside
similar structures (such as functions), then nested loops don't work as well.
For those cases, the analyzer package provides a visitor pattern.

There is a single visitor API, defined by the abstract class `ElementVisitor`.
It defines a separate visit method for each class of element. For example, the
method `visitClassElement` is used to visit a `ClassElement`. If you ask an
element to accept a visitor, it will invoke the corresponding method on the
visitor interface.

If you want to define a visitor, you'll probably want to subclass one of the
concrete implementations of `ElementVisitor`. The concrete subclasses are
defined in `package:analyzer/dart/element/visitor.dart`. A couple of the most
useful include
- `SimpleElementVisitor` which implements every visit method by doing nothing,
- `RecursiveElementVisitor` which will cause every element in a structure to be
  visited, and
- `GeneralizingElementVisitor` which makes it easy to visit kinds of nodes, such
  as visiting any executable element (method, function, accessor, or
  constructor).

As an example, let's assume you want to write some code to compute the largest
number of parameters defined for any function or method in a given structure.
You need to visit every element because functions can be nested inside
functions. But because methods and functions are represented by different
classes of elements, it would be useful to use a visitor that will generalize
both to allow you to just visit executable elements (those that have
parameters). Hence, you'd want to create a subclass of
`GeneralizingElementVisitor`.

```dart
class ParameterCounter extends GeneralizingElementVisitor2<void> {
  int maxParameterCount = 0;

  @override
  void visitExecutableElement(ExecutableElement element) {
    maxParameterCount = math.max(maxParameterCount, element.formalParameters.length);
    super.visitExecutableElement(element);
  }
}
```

[analysis]: analysis.md
[ast]: ast.md
[type]: type.md
