avoid-missing-interpolation
- Group
- Correctness
- Path
lint/correctness/avoid-missing-interpolation- Default
- On (recommended)
- Origin
- Falcon
- Rule
- 88 of 512
Flags missing interpolation around visible String variables or member accesses and calls.
A plain string equal to an in-scope variable name may print the name instead
of its value. This check requires a positional argument of an unqualified call
and a local binding with a declared nonnullable dart:core String type.
Constructors, receiver methods, annotations, named arguments, raw/escaped/adjacent
strings, and calls whose arguments already read that variable are excluded.
Keys in maps, indexes, comparisons, and patterns are not positional arguments.
In '$object.property' and '$function(value)', only the identifier is
interpolated. The rule requires the receiver to have the named readable
member, or a known callable type, before suggesting ${...}. Unknown members,
dynamic receivers, filenames such as 'assets/$name.png', and string-valued
method names in logs are left alone. Raw and escaped dollars and braced
interpolations are never flagged. Reports the first incomplete interpolation
in each segment, rather than an entire multiline literal.
Invalid
class Label {
final String value;
const Label(this.value);
}
String render(String value) => value;
void example(Label label, String value) {
print('value: $label.value');
print("empty: $label.value.isEmpty");
print('$render(value)');
print('rendered: $render()');
print('''$label.value''');
print('prefix ' '$label.value');
print('$value.length and $label.value');
print('backslash: \\ $label.value');
print("${'$label.value'}");
print('''prefix
$label.value''');
print('value');
}
void localNames(String parameter) {
print('parameter');
final String title = 'Heading';
print('title');
String mutable = 'Current';
print("mutable");
const String constant = 'Fixed';
print('constant');
{
final String nested = 'Inner';
print('nested');
}
}void example(Label label, String value) { print('value: $label.value'); print('value: $label.value'); print("empty: $label.value.isEmpty"); print("empty: $label.value.isEmpty"); print('$render(value)'); print('$render(value)'); print('rendered: $render()'); print('rendered: $render()'); print('''$label.value'''); print('''$label.value'''); print('prefix ' '$label.value'); print('prefix ' '$label.value'); print('$value.length and $label.value'); print('$value.length and $label.value'); print('backslash: \\ $label.value'); print('backslash: \\ $label.value'); print("${'$label.value'}"); print('''prefix$label.value''');$label.value'''); print('value');void localNames(String parameter) { print('parameter'); final String title = 'Heading'; print('title'); String mutable = 'Current'; print("mutable"); const String constant = 'Fixed'; print('constant'); final String nested = 'Inner'; print('nested');Valid
class Label {
final String value;
const Label(this.value);
}
String render(String value) => value;
void example(Label label, String value) {
print('value: ${label.value}');
print('${render(value)}');
print(r'$label.value');
print(r'$render(value)');
print('\$label.value');
print('\$render(value)');
print('$label.');
print('$label...');
print('$value.42');
print('$label .value');
print('$render (value)');
print('${label}.value');
print('${render}(value)');
print('$value');
print('literal label');
print('''literal \$label.value''');
print('$label' '.value');
print(r'$label.value' '$value');
print("${'$label'}.value");
print('${{"closing": "}"}}.value');
print('$label\u002evalue');
print('$render\u0028value)');
final String name = 'avatar';
final String domain = 'example';
final String methodName = 'render';
print('assets/$name.png');
print('user@$domain.com');
print('logs $methodName()');
print(r'value');
print('\u0076alue');
print('value' ' suffix');
print('$label.unknown');
print('$value.png');
print('''
${label.value}.length
''');
}
void shadowing(String title, String? optional, dynamic unknown) {
{
final int title = 42;
print('title');
}
print('optional');
print('unknown');
print('notInScope');
}
class Key {
final String value;
const Key(this.value);
}
class Preferences {
void setString(String key, String value) {}
}
void named({required String key}) {}
void consume(Object first, Object second) {}
void keys(Preferences prefs, Map<String, String> json, String key) {
final String email = 'address';
final String token = 'secret';
final String name = 'person';
final fields = {'email': email};
prefs.setString('token', token);
print(json['name']);
print(key == 'name');
switch (key) {
case 'name':
break;
}
print(Key('email'));
print(const Key('email'));
named(key: 'email');
consume('email', email.length);
consume('email', '$email');
final String assignment = 'name';
print(fields);
print(assignment);
@Key('email')
void annotated() {}
}
String returnName(String name) => 'name';
class Cache {
String? get(String key) => null;
void remove(String key) {}
}
void storageKeys(Cache prefs, String token, String id) {
prefs.remove('token');
prefs.get('id');
}Configure avoid-missing-interpolation
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"correctness": {
"avoid-missing-interpolation": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/correctness/avoid-missing-interpolation: <reason>More correctness rules
- avoid-misused-hooksrecommendedflutter_hooks
Flags confirmed Flutter hooks called directly in non-hook Flutter widget builds.
- avoid-mounted-in-setstateflutter
Check mounted before invoking Flutter State.setState, never inside its callback.
- avoid-mutable-equatable-subclass-fieldsrecommendedequatable
Flags mutable instance fields on subclasses inheriting Equatable equality.
- avoid-mutable-global-variables
avoid_mutable_global_variablesDisallow mutable top-level variables.
- avoid-nested-futures
Avoid
Future<Future<T>>,FutureOr<Future<T>>, and other directly nested future wrappers. - avoid-nested-streams-and-futures
Avoid directly nesting SDK streams and futures:
Stream<Future<T>>andFuture<Stream<T>>complicate consumption. - avoid-read-inside-buildrecommendedprovider
Flags non-listening Provider reads directly inside Flutter widget builds.
- avoid-recursive-calls
Reports direct self-calls in functions and methods, including guarded recursion.