String built by concatenation inside a loop

ID

dart.performance.use_string_buffers

Severity

info

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

low

Resource

Idiom

Language

Dart

Description

Reports a variable initialised to the empty string and then extended inside a for, for-in, while or do-while loop with += or s = s + x. The empty-string initialiser is what identifies the accumulator as a String, so a numeric accumulator is not reported.

Rationale

Dart strings are immutable, so s += x cannot extend the existing string - it allocates a new one and copies both operands into it. Repeating that per iteration copies the prefix again every time, which makes building an n-element string quadratic in the total length and leaves n-1 intermediate strings for the collector to reclaim. On a few short parts this is invisible; on a report, a serialised payload or a log line assembled from a large collection it is the dominant cost of the method. A StringBuffer appends into a growable buffer and produces the result once, so the same loop becomes linear.

The following code illustrates the pattern detected by this rule:

class Renderer {
  String csv(List<List<String>> rows) {
    // FLAGGED: String built by concatenation inside a loop
    var out = '';
    for (final row in rows) {
      out += row.join(',');
      out += '\n';
    }
    return out;
  }
}

Remediation

Accumulate into a StringBuffer with write, writeln or writeAll and call toString() once after the loop. Where the loop only joins elements with a separator, Iterable.join does the whole job in one call.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved