Motivation

Sometimes there is a need to access the names of programming language entities, such as methods, properties, constructors, etc. Unfortunately, Flutter does not have a reflection mechanism designed for this purpose. But there is code generation! It is all you need for access to names of code entities with this package.

Index

How to use

Install

To use Nameof, you will need your typical build_runner code-generator setup.
First, install build_runner and Nameof by adding them to your pubspec.yaml file:

If you are using creating a Flutter project:

$ flutter pub add nameof_annotation
$ flutter pub add --dev build_runner
$ flutter pub add --dev nameof

If you are using creating a Dart project:

$ dart pub add nameof_annotation
$ dart pub add --dev build_runner
$ dart pub add --dev nameof

This installs three packages:

Run the generator

To run the code generator, execute the following command:

dart run build_runner build

For Flutter projects, you can also run:

flutter pub run build_runner build

Note that like most code-generators, nameof will need you to both import the annotation (nameof_annotation) and use the part keyword on the top of your files.

As such, a file that wants to use nameof will start with:

import 'package:nameof_annotation/nameof_annotation.dart';

part 'my_file.nameof.dart';

Using Nameof

Simple usage

For example we have a class Car. For names generation of this class you need to tell generator some instructions with nameof annotation:

@nameof
class Car {
  final double price;
  final double weigth;

  final int year;
  final String model;

  Car(this.price, this.weigth, this.year, this.model);

  Car.sedan(double price, double weigth, int year)
      : this(price, weigth, year, 'Sedan');
}

Then you need to run generator Run the generator

It will generate next code:

/// Container for names of elements belonging to the [Car] class
abstract class NameofCar {
  static const String className = 'Car';

  static const String constructor = '';
  static const String constructorSedan = 'sedan';

  static const String fieldPrice = 'price';
  static const String fieldWeigth = 'weigth';
  static const String fieldYear = 'year';
  static const String fieldModel = 'model';
}

Then use it in your code:

print(NameofCar.fieldPrice);

It is simple!

Also you may to use nameof annotation for abstract classes and mixins.

Models coverage

You can have very precision setting of coverage of model's members with use coverage settings and @NameofIgnore annotation. For example two next configurations will lead to one output.

  • First configuration:
@Nameof(coverage: Coverage.excludeImplicit)
class Itinerary {
  final double longStart;
  final double latStart;

  final double longEnd;
  final double latEnd;

  @nameofKey
  final String name;

  @nameofKey
  final double length;

  Itinerary(this.longStart, this.latStart, this.longEnd, this.latEnd, this.name,
      this.length);
}
  • Second configuration:
@Nameof(coverage: Coverage.includeImplicit)
class Itinerary {
  @nameofIgnore
  final double longStart;
  
  @nameofIgnore
  final double latStart;

  @nameofIgnore
  final double longEnd;
  
  @nameofIgnore
  final double latEnd;

  final String name;
  final double length;

  @nameofIgnore
  Itinerary(this.longStart, this.latStart, this.longEnd, this.latEnd, this.name,
      this.length);
}

Output:

/// Container for names of elements belonging to the [Itinerary] class
abstract class NameofItinerary {
  static const String className = 'Itinerary';

  static const String fieldName = 'name';
  static const String fieldLength = 'length';
}

Take an attention for coverage setting, @nameofKey and @nameofIgnore annotations. If you do not set coverage, generator will use includeImplicit setting by default.

Override names

If you want override name of element you can do it! Code:

@nameof
class Ephemeral {
  @NameofKey(name: 'AbRaCadabra')
  String get flushLight => 'Purple';
}

Generator output:

/// Container for names of elements belonging to the [Ephemeral] class
abstract class NameofEphemeral {
  static const String className = 'Ephemeral';

  static const String constructor = '';

  static const String propertyGetFlushLight = 'AbRaCadabra';
}

As can you see property was renamed. Output has AbRaCadabra not flushLight.

NameofKey targets

@NameofKey annotatition applyed for public fields, methods, properties and constructors.

Configurations

Nameof offers various options to customize the generated code. For example, you may want to change coverage behaviour of model.

To do so, there are two possibilities:

Changing the behavior for a specific model

If you want to customize the generated code for only one specific class, you can do so by using annotation setting:

@Nameof(coverage: Coverage.excludeImplicit)
class Empoyee {...}

Changing the behavior for the entire project

Instead of applying your modification to a single class, you may want to apply it to all Nameof models at the same time.

You can do so by customizing a file called build.yaml
This file is an optional configuration file that should be placed next to your pubspec.yaml:

project_folder/
  pubspec.yaml
  build.yaml
  lib/

There, you will be able to change the same options as the options found in @Nameof (see above) by writing:

targets:
  $default:
    builders:
      nameof:
        options:
          coverage: includeImplicit
          

Two settings for coverage is available: includeImplicit (default) and excludeImplicit

Libraries

nameof
Support for doing something awesome.