blob: 1be252313f1e9ffb3e9cd02bada61fa7790f0c9f [file] [log] [blame]
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
extension StringExtension on String {
static final _toSnakeCaseRegExp = RegExp('_?[A-Z]');
static final _startsWithLowerCaseRegExp = RegExp('^[a-z]');
static final _startsWithUpperCaseRegExp = RegExp('^[A-Z]');
/// Returns `true` if the string is a `camelCase` string.
bool get isCamelCase {
if (contains('_')) return false;
if (_startsWithLowerCaseRegExp.matchAsPrefix(this) == null) return false;
return true;
}
/// Returns `true` if the string is a `PascalCase` string.
bool get isPascalCase {
if (contains('_')) return false;
if (_startsWithUpperCaseRegExp.matchAsPrefix(this) == null) return false;
return true;
}
/// Converts `SCREAMING_SNAKE_CASE` or `snake_case` to `camelCase`.
String toCamelCase() {
var parts = toLowerCase().split('_');
var buffer = StringBuffer();
var i = 0;
// Preserve initial '_'s
while (i < parts.length - 1 && parts[i].isEmpty) {
buffer.write('_');
++i;
}
if (i < parts.length) {
// Convert first word to lower case
buffer.write(parts[i].toLowerCase());
++i;
// Convert remaining words to initial upper case
while (i < parts.length) {
var part = parts[i];
if (part.isNotEmpty) {
buffer.write(part[0].toUpperCase());
buffer.write(part.substring(1));
}
++i;
}
}
return buffer.toString();
}
/// Converts `SCREAMING_SNAKE_CASE` or `snake_case` to `PascalCase`.
String toPascalCase() {
var parts = toLowerCase().split('_');
var buffer = StringBuffer();
var i = 0;
// Preserve initial '_'s
while (i < parts.length - 1 && parts[i].isEmpty) {
buffer.write('_');
++i;
}
// Convert words to initial upper case
while (i < parts.length) {
var part = parts[i];
if (part.isNotEmpty) {
buffer.write(part[0].toUpperCase());
buffer.write(part.substring(1));
}
++i;
}
return buffer.toString();
}
/// Converts `camelCase` or `PascalCase` to `snake_case`
String toSnakeCase() {
var parts = <String>[];
var i = 0;
var wordStarts = _toSnakeCaseRegExp.allMatches(this);
for (var RegExpMatch(:start) in wordStarts) {
if (i < start) {
parts.add(substring(i, start).toLowerCase());
i = start;
}
if (this[i] == '_' && parts.isNotEmpty) {
// Avoid doubling up the `_`. This handles strings that are already in
// snake case like `foo_Bar` (which translates to `foo_bar`).
i++;
}
}
if (i < length) {
parts.add(substring(i).toLowerCase());
}
return parts.join('_');
}
}