use-string-buffers

Same as use_string_buffers in Dart lints

Path
lint/performance/use-string-buffers
Default
On (recommended)
Origin
Dart lints
Rule
505 of 512
recommended

Prefers a StringBuffer to growing a String with + inside a loop.

Strings are immutable, so s += piece in a loop copies the whole string on every iteration; a StringBuffer appends in amortized constant time. The rule inspects the statements directly in the body of a for, while or do-while loop (and plain nested blocks). It reports s += ... when s is a String variable declared outside that body, and reports s in s = s + ... or s = '$s...' (parentheses aside), where the right-hand side starts with s and s is a local variable or parameter: for a field or top-level variable the analyzer compares the setter written with the getter read, which never match.

Invalid

example.dartdart
String concat(List<String> parts) {
  var result = '';
  for (final part in parts) {
    result += part;
  }
  return result;
}

String whileLoop(int n) {
  String text = '';
  var i = 0;
  while (i < n) {
    text = text + '$i';
    i++;
  }
  return text;
}

String doLoop(int n) {
  var text = '';
  do {
    text = '$text,';
    n--;
  } while (n > 0);
  return text;
}

String classic(int n) {
  var s = '';
  for (var i = 0; i < n; i++) {
    {
      s += 'x';
    }
  }
  return s;
}

String interpolatedBraces(List<int> values) {
  var s = '';
  for (final v in values) {
    s = '${s}x$v';
  }
  return s;
}

class Joiner {
  Joiner(this.prefix, this.label);
  final String prefix;
  final String? label;

  // The variables' types come from the enclosing class's fields.
  String join(List<String> parts) {
    var s = prefix;
    for (final part in parts) {
      s += part;
    }
    var t = label ?? '';
    for (final part in parts) {
      t += part;
    }
    return s + t;
  }
}
Use a string buffer rather than `+` to compose strings.
3 for (final part in parts) {
4 result += part;
Use a string buffer rather than `+` to compose strings.
12 while (i < n) {
13 text = text + '$i';
Use a string buffer rather than `+` to compose strings.
21 do {
22 text = '$text,';
Use a string buffer rather than `+` to compose strings.
31 {
32 s += 'x';
Use a string buffer rather than `+` to compose strings.
40 for (final v in values) {
41 s = '${s}x$v';
Use a string buffer rather than `+` to compose strings.
54 for (final part in parts) {
55 s += part;
Use a string buffer rather than `+` to compose strings.
58 for (final part in parts) {
59 t += part;

Valid

example.dartdart
String buffer(List<String> parts) {
  final buffer = StringBuffer();
  for (final part in parts) {
    buffer.write(part);
  }
  return buffer.toString();
}

String declaredInside(List<String> parts) {
  var last = '';
  for (final part in parts) {
    var s = '';
    s += part;
    last = s;
  }
  return last;
}

int numbers(List<int> values) {
  var total = 0;
  for (final v in values) {
    total += v;
  }
  return total;
}

String suffix(List<String> parts) {
  var s = '';
  for (final part in parts) {
    s = part + s;
  }
  return s;
}

String nested(List<String> parts) {
  var s = '';
  for (final part in parts) {
    if (part.isNotEmpty) {
      s += part;
    }
  }
  return s;
}

String outside(String s) {
  s += '!';
  return s;
}

String prefixText(List<String> parts) {
  var s = '';
  for (final part in parts) {
    s = 'x$s';
  }
  return s;
}

Configure use-string-buffers

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "performance": {
        "use-string-buffers": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/performance/use-string-buffers: <reason>