Skip to content

avoid_todo_comments

v1.1.0WarningConfigurableCode Quality

Warns when a comment marks work that was never done — TODO, FIXME, HACK or XXX — without naming a tracked issue.

A TODO marks a known missing case that ships anyway. require_reference is on by default, so a marker naming an issue passes and a bare one does not: that turns “I will get to it” into something a person who is not you can find.

The default reference pattern accepts an issue number (#42), a URL, or a tracker key (PROJ-118).

This rule is in the opinionated preset and works with its defaults.

Future<void> upload(String path) async {
// TODO: handle the 409 conflict case
await _put(path);
}
Future<void> _put(String path) async {}

Name the issue that tracks it:

Future<void> upload(String path) async {
// TODO(#42): handle the 409 conflict case
await _put(path);
}
Future<void> _put(String path) async {}

Any of these forms satisfy the default pattern:

// TODO(#42): handle the 409 conflict case
// TODO: handle this, https://github.com/example/repo/issues/42
// TODO(PROJ-118): handle the 409 conflict case

TODO(dominik): says who has context, not that anyone will act. The default pattern does not accept it, so it is still reported:

// Reported.
// TODO(dominik): handle the 409 conflict case

This is where the rule differs from the SDK’s flutter_style_todos, which enforces the shape TODO(username): message and has no opinion on whether the work is tracked. The two compose: // TODO(#42): ... satisfies both.

All four defaults are recognised, and all four take a reference:

// Reported — no tracked issue.
// FIXME: this retries forever
// HACK: works around the broken header
// XXX: do not ship this
// Accepted.
// FIXME(#77): this retries forever
// HACK(#78): works around the broken header

Narrow the set if you only care about some of them, or add your own:

many_lints.yaml
rules:
avoid_todo_comments:
markers:
- TODO
- FIXME
many_lints.yaml
rules:
avoid_todo_comments:
additional_markers:
- REVISIT

markers replaces the default list; additional_markers adds to whichever list won.

Set require_reference: false for a codebase that wants none at all — every marker is then reported, referenced or not:

many_lints.yaml
rules:
avoid_todo_comments:
require_reference: false
// Reported with `require_reference: false`, despite the issue number.
// TODO(#42): handle the 409 conflict case

reference_pattern is a regular expression. A shop that only uses Jira keys can insist on them:

many_lints.yaml
rules:
avoid_todo_comments:
reference_pattern: '[A-Z]{2,}-\d+'
// Accepted.
// TODO(PROJ-118): handle the 409 conflict case
// Reported — `#42` no longer counts.
// TODO(#42): handle the 409 conflict case

A marker is only recognised at the start of the comment body, so prose that mentions one (“the TODO above explains why”) is not reported, and neither is a word that merely begins with one (TODOS.md, HACKATHON).

Doc comments (///) and block comments (/* */) are examined too — a /// TODO: document this is reported like any other.

The reference pattern is matched against the whole comment, not just the part after the marker, so a line mentioning an issue anywhere in it passes.

analysis_options.yaml
many_lints:
rules:
avoid_todo_comments:
markers:
- TODO
- FIXME
require_reference: true
reference_pattern: '#\d+'
exclude:
- 'test/**'
Option Type Default Description
markers list of strings ['TODO', 'FIXME', 'HACK', 'XXX'] Which words open a marker comment. Replaces the default
additional_markers list of strings [] Adds to whichever list won, without restating the default
require_reference bool true Accept a marker that names a tracked issue; report only bare ones
reference_pattern regex #\d+|https?://\S+|[A-Z]+-\d+ What counts as a reference: an issue number, a URL, or a tracker key

This rule is in the opinionated preset, so it is on with preset: opinionated or preset: pedantic. Add it to a lower preset with avoid_todo_comments: true.

To turn it off:

many_lints.yaml
rules:
avoid_todo_comments: false

To keep the rule on but skip certain paths, use per-rule exclude.