/// <summary> /// Returns a string that will be valid for constructing a symbol by replacing all invalid characters /// with a valid one /// </summary> /// <remarks> /// Invalid characters are replaced by '$'. Invalid start characters are preserved if possible by shifting /// them to occur after a '$'. /// </remarks> public static string SanitizeStringForSymbol(string aString) { // The case of an empty value for a property is preserved as is // Other cases (project full path or property key) should never be empty if (String.IsNullOrEmpty(aString)) { return(String.Empty); } var builder = new StringBuilder(aString.Length); var allAtoms = aString.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); for (int j = 0; j < allAtoms.Length; j++) { var atom = allAtoms[j]; char firstChar = atom[0]; builder.Append(!SymbolAtom.IsValidIdentifierAtomStartChar(firstChar) ? '_' : firstChar); // If the character is not valid as a first character, but valid as a second one, we add it as well // This is useful for things like package.1.2, so we don't drop the version numbers completely if (!SymbolAtom.IsValidIdentifierAtomStartChar(firstChar) && SymbolAtom.IsValidIdentifierAtomChar(firstChar)) { builder.Append(firstChar); } for (int i = 1; i < atom.Length; i++) { var aChar = atom[i]; builder.Append(!SymbolAtom.IsValidIdentifierAtomChar(aChar) ? '_' : aChar); } if (j != allAtoms.Length - 1) { builder.Append('.'); } } return(builder.ToString()); }