Using Dart linter for cleaner code: from config to GitHub workflow

Alexey Inkin
Flutter Senior
Published in
5 min readJun 12, 2022

Dart and Flutter come with dart analyze command that points some possible errors and bad styling. It is also where tips and underlines in your editor come from.

Underlining and the tip in Android Studio coming from dart analyze.

If there are no analyzer complaints, then you can be informed when a new one emerges and prevent some possible errors. In this article we will add this check to your pipeline.

On the other hand, if there are complaints that you ignore, you can add more mess and never notice. This is why you should always know what each complaint means and deal with it quickly. You do this either by fixing the issue, or by deciding that it is OK for your project. In the latter case you configure the analyzer to ignore this issue or this class of issues. Either way you should always get back to having no issues reported by the analyzer.

To view a list of all issues in your code, run dart analyze in the root of your project.

The compilation errors

A compilation error is something that will not even build:

Android Studio signalling a compilation error.

These are the most obvious. Editors usually highlight them in red.

The lints

This is the interesting part. Lints are hints that do not prevent build, so beginners often ignore them. The first picture in this article shows a lint.

The word “lint” originally means a fuzz of tissue on clothes which looks nasty. To have a lint in your code means to have a rule triggered and flagged your code. Such rules are also called lints for short. The tool is called “linter”, it is a part of the analyzer.

While you never ignore compilation errors, lints are something you configure. There are over 200 different lints that the analyzer can report. Each one is described here.

Dart team had grouped the lints. You can choose a whole group of lints to be active on your project. Or you can choose individual lints. Or you can choose a group as your baseline, and then turn on or off individual lints.

Core

Some lints signal a hidden error almost certainly. Some signal no error but flag some styling that must be avoided, and most programmers in the world agree on that. The rating of your package suffers if you break any of these rules. These are grouped in core group and are listed here.

Recommended

Some other lints are more subtle but still very much desired. These are in recommended group and are listed here. This group also includes core lints.

Flutter

Flutter comes with its own catches, so there are lints specific to Flutter. Some of such lints are recommended by Flutter team and are enabled by default in each Flutter project. They form flutter group and are listed here. This group also includes recommended (and core).

Why not Enabling Them All?

A lint does not necessarily signal something bad. Some lints are used to enforce an opinionated code style so it is consistent for your project.

A good example are prefer_single_quotes and prefer_double_quotes which cannot be enabled together.

Another example are prefer_relative_imports and always_use_package_imports that also cannot be used together.

Some are highly subjective like prefer_final_parameters.

Enabling Lints for a Project

Dart has a great docs on this. Read this to enable a group or specific lints for a project: https://dart.dev/guides/language/analysis-options

The rest of the article assumes you have read that.

Analyzing without Mercy

You normally run dart analyze before each commit to see if there are any issues and do not commit if there are. It is good enough for a human eye, but not for an automated pipeline.

When you run dart analyze, it produces so called info issues for lints meaning these are not severe. With infos, the analyzer exits with zero code meaning any pipeline running it can continue.

So a better command is dart analyze --fatal-infos. It will return a non-zero code if any issue is found. You normally build this into your pipeline.

An Example GitHub Workflow

In addition to local checks on your machine, you can configure GitHub to run the same check on each or some of your commits. This is a must-have for teams when you cannot be sure everyone follows the rule to analyze before commit.

This is how one of my projects looks on GitHub. Commits with no lints are shown with green ticks. Commits with lints are shown with red crosses.

For each commit with lints, you can even see what exactly went wrong:

To fully understand this configuration, read about GitHub workflows: https://docs.github.com/en/actions/using-workflows

In short, in your code you can add workflow files that tell GitHub what to do with your commits. These are located in .github/workflows in the root of your repository. Each .yaml file there is processed by GitHub.

To configure this very same checkup, create .github/workflows/dart.yaml file in your repository with the following contents:

It runs on all branches on all pushes and all pull requests. It sets up a virtual instance of Ubuntu, installs Flutter and runs the commands we desire on it.

steps is where you list what to do. If a command at some step returns a non-zero exit code, the workflow breaks. We use this to break if dart analyze --fatal-infos fails.

Push this file into your repository, and from this commit on you will be somewhat protected.

--

--

Alexey Inkin
Flutter Senior

Google Developer Expert in Flutter. PHP, SQL, TS, Java, C++, professionally since 2003. Open for consulting & dev with my team. Telegram channel: @ainkin_com