dart-modern-features — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited dart-modern-features (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill when:
such as records, extension types, class modifiers, null-aware collection elements, dot shorthands, and digit separators.
domain wrappers.
For pattern matching, switch expressions, and list/map/split destructuring, use [dart-use-pattern-matching]. For converting closed class hierarchies into exhaustive sealed types, use [dart-seal-type-hierarchies].
Do NOT apply modern features or refactor code when:
pubspec.yaml specifies an SDKconstraint that supports Dart 2.x (e.g., sdk: '>=2.19.0 <4.0.0'). Refactoring to Dart 3 features will introduce syntax errors for Dart 2 users.
values or internal tuples, but complex public API payloads are clearer and more extensible as dedicated classes or extension types.
To find candidates for modernization:
Search for collection if statements checking for null:
if\s*\(\w+\s*!=\s*null\)\s*\w+Search for long numbers without separators:
\b\d{6,}\b (Matches numbers with 6 or more digits).Use records as anonymous, immutable, aggregate structures to bundle multiple objects without defining a custom class. Prefer them for returning multiple values from a function or grouping related data temporarily.
Avoid: Creating a dedicated class for simple multiple-value returns.
class UserResult {
final String name;
final int age;
UserResult(this.name, this.age);
}
UserResult fetchUser() {
return UserResult('Alice', 42);
}Prefer: Using records to bundle types seamlessly on the fly.
(String, int) fetchUser() {
return ('Alice', 42);
}
void main() {
var user = fetchUser();
print(user.$1); // Alice
}Use class modifiers (final, base, interface, sealed) to restrict how classes can be subtyped outside their defining library:
interface class: External libraries may implement, but cannot extend.base class: External libraries may extend, but cannot implement(preserving private implementation invariants).
final class: External libraries can neither extend nor implement.sealed class: Closed family of subtypes within the same library enablingexhaustive switching (see [dart-seal-type-hierarchies]).
Avoid: Leaving internal implementation classes open to arbitrary external subclassing or interface implementation when invariants must be enforced.
class TokenStore {
void save(String token) {}
}Prefer: Declaring explicit subtyping capabilities with class modifiers.
final class TokenStore {
void save(String token) {}
}Use extension types for a zero-cost wrapper around an existing type. Use them to restrict operations or add custom behavior without runtime overhead.
Avoid: Allocating new wrapper objects just for domain-specific logic or type safety.
class Id {
final int value;
Id(this.value);
bool get isValid => value > 0;
}Prefer: Using extension types which compile down to the underlying type at runtime.
extension type Id(int value) {
bool get isValid => value > 0;
}Use underscores (_) in number literals strictly to improve visual readability of large numeric values.
Avoid: Long number literals that are difficult to read at a glance.
const int oneMillion = 1000000;Prefer: Using underscores to separate thousands or other groupings.
const int oneMillion = 1_000_000;Use wildcards (_) as non-binding variables or parameters to explicitly signal that a value is intentionally unused.
Avoid: Inventing clunky, distinct variable names to avoid "unused variable" warnings.
void handleEvent(String ignoredName, int status) {
print('Status: $status');
}Prefer: Explicitly dropping the binding with an underscore.
void handleEvent(String _, int status) {
print('Status: $status');
}Use null-aware elements (?) inside collection literals to conditionally include items only if they evaluate to a non-null value.
Avoid: Using collection if statements for simple null checks.
var names = [
'Alice',
if (optionalName != null) optionalName,
'Charlie'
];Prefer: Using the ? prefix inline.
var names = ['Alice', ?optionalName, 'Charlie'];Use dot shorthands to omit the explicit type name when it can be confidently inferred from context, such as with enums or static fields.
Avoid: Fully qualifying type names when the type is obvious from the context.
LogLevel currentLevel = LogLevel.info;Prefer: Reducing visual noise with inferred shorthand.
LogLevel currentLevel = .info;matching, switch expressions, and list/map/String.split() destructuring.
sealed types for exhaustive switching.
that predate or complement the modern syntax features.
[dart-use-pattern-matching]: https://github.com/dart-lang/skills/blob/main/skills/dart-use-pattern-matching/SKILL.md [dart-seal-type-hierarchies]: https://github.com/kevmoo/dash_skills/blob/main/skills/dart-seal-type-hierarchies/SKILL.md [dart-best-practices]: https://github.com/kevmoo/dash_skills/blob/main/skills/dart-best-practices/SKILL.md
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.