| // Copyright (c) 2022, 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 _lowerCaseRegex = RegExp(r'([_\$]||[_\$]+[0-9])*[a-z]'); | |
| bool get firstLetterIsLowercase => startsWith(_lowerCaseRegex); | |
| /// Returns this string if not empty, otherwise null. | |
| String? get nullIfEmpty => isEmpty ? null : this; | |
| /// Computes a filename for a given symbol name (convert from PascalCase to | |
| /// snake_case and append '.dart'). | |
| /// | |
| /// It is assumed that this String is a valid identifier and does not contain | |
| /// characters that are invalid in file names. | |
| String get toFileName { | |
| var fileName = replaceAllMapped( | |
| RegExp('[A-Z]'), | |
| (match) => match.start == 0 ? match[0]! : '_${match[0]}', | |
| ).toLowerCase(); | |
| return '$fileName.dart'; | |
| } | |
| /// Returns a lowerCamelCase version of the receiver. | |
| /// | |
| /// No checks are made that the receiver is a valid identifier, other than | |
| /// the requirement that the receiver must contain at least one underscore | |
| /// (but neither at the beginning nor the end), and must not have two adjacent | |
| /// underscores. | |
| /// | |
| /// The resulting identifier is one in which only the letters following the | |
| /// underscores are capitalized. | |
| String? get toLowerCamelCase { | |
| var words = split('_'); | |
| if (words.length < 2) { | |
| return null; | |
| } | |
| var firstWord = words.first; | |
| if (firstWord.isEmpty) { | |
| return null; | |
| } | |
| var buffer = StringBuffer(); | |
| buffer.write(firstWord.toLowerCase()); | |
| for (var i = 1; i < words.length; i++) { | |
| var word = words[i]; | |
| if (word.isEmpty) { | |
| return null; | |
| } | |
| buffer.write(word._capitalized); | |
| } | |
| return buffer.toString(); | |
| } | |
| /// Returns an UpperCamelCase version of the receiver. | |
| /// | |
| /// No checks are made that the receiver is a valid identifier, other than | |
| /// the requirement that the receiver must contain at least one underscore | |
| /// (but neither at the beginning nor the end), and must not have two adjacent | |
| /// underscores. | |
| /// | |
| /// The resulting identifier is one in which only the first letter and the | |
| /// letters following the underscores are capitalized. | |
| String? get toUpperCamelCase { | |
| var words = split('_'); | |
| if (words.length < 2) { | |
| var first = words.firstOrNull; | |
| if (first != null && first.isNotEmpty) { | |
| return first._capitalized; | |
| } | |
| return null; | |
| } | |
| var buffer = StringBuffer(); | |
| for (var i = 0; i < words.length; i++) { | |
| var word = words[i]; | |
| if (word.isEmpty) { | |
| return null; | |
| } | |
| buffer.write(word._capitalized); | |
| } | |
| return buffer.toString(); | |
| } | |
| /// Returns the string after removing the '^' in the string, if present, | |
| /// along with the index of the caret, or null if not present. | |
| (String, int?) get withoutCaret { | |
| var caretIndex = indexOf('^'); | |
| if (caretIndex < 0) { | |
| return (this, null); | |
| } else { | |
| var rawText = substring(0, caretIndex) + substring(caretIndex + 1); | |
| return (rawText, caretIndex); | |
| } | |
| } | |
| /// Return a version of this string in which the first character is upper case | |
| /// and all remaining characters are lower case. | |
| String get _capitalized { | |
| if (length <= 1) { | |
| return toUpperCase(); | |
| } | |
| return substring(0, 1).toUpperCase() + substring(1).toLowerCase(); | |
| } | |
| /// Returns `null` if this string is the same as [other], otherwise `this`. | |
| String? orNullIfSameAs(String other) => this == other ? null : this; | |
| } |