STRING_TRIM_IS_EMPTY
Summary
- Rule ID:
STRING_TRIM_IS_EMPTY - Name: String trim followed by isEmpty
- Description: Reports direct
String.trim().isEmpty()chains because blank-check intent is ambiguous andString.isBlank()(Java 11+) is clearer. - Annotation policy:
@Suppress/@SuppressWarningsare not supported; only JSpecify annotations are recognized for annotation-driven semantics, and non-JSpecify annotations do not change behavior.
Motivation
trim().isEmpty() is often used to express blank-string checks, but its behavior can be misunderstood for Unicode whitespace and the intent is less explicit. isBlank() communicates intent directly and aligns better with modern Java APIs.
What it detects
- Direct call chains where
java.lang.String.trim()is immediately followed byjava.lang.String.isEmpty()on the returned string value. - One finding per matching chain.
What it does NOT detect
- Standalone
String.isEmpty()calls. - Standalone
String.trim()calls. - Non-adjacent or alternative forms such as
trim().length() == 0. - Suppression via annotations (
@Suppress,@SuppressWarnings). - Behavior changes based on non-JSpecify annotations.
Examples (TP/TN/Edge)
TP (reported)
TN (not reported)
Edge (only direct chain is reported)
class ClassC {
boolean methodZ(String varOne, String varTwo) {
boolean varThree = varOne.trim().isEmpty();
boolean varFour = varTwo.isEmpty();
return varThree || varFour;
}
}
Output
- Message should be actionable and include method context, for example:
String blank check in <class>.<method><descriptor> uses trim().isEmpty(); replace with isBlank() (Java 11+) for clearer Unicode-aware whitespace handling. - Location should point to the call site line when line metadata is available.
Performance considerations
- Analysis should be linear in the number of discovered call sites.
- No whole-program dataflow is required.
- Result order should be deterministic across runs.
Acceptance criteria
- Reports each direct
String.trim().isEmpty()chain. - Does not report
String.isBlank()calls. - Does not report standalone
String.isEmpty()calls without a preceding directtrim()chain. - Covers TP, TN, and edge scenarios in tests.
- Produces deterministic finding count and ordering.
- Keeps
@Suppress-style suppression unsupported and does not add non-JSpecify annotation semantics.