@@ -97,13 +97,15 @@ extension String {
9797
9898 // 1. Leave leading underscores as-are
9999 // 2. In the middle: word separators: ["_", "-", <space>] -> remove and capitalize next word
100- // 3. In the middle: period: ["."] -> replace with "_"
100+ // 3. In the middle: period: [".", "/"] -> replace with "_"
101+ // 4. In the middle: drop ["{", "}"] -> replace with ""
101102
102103 var buffer : [ Character ] = [ ]
103104 buffer. reserveCapacity ( count)
104105
105106 enum State {
106107 case modifying
108+ case fallback
107109 case preFirstWord
108110 case accumulatingWord
109111 case waitingForWordStarter
@@ -129,7 +131,7 @@ extension String {
129131 state = . accumulatingWord
130132 } else {
131133 // Illegal character, fall back to the defensive strategy.
132- return safeForSwiftCode_defensive ( options : options )
134+ state = . fallback
133135 }
134136 case . accumulatingWord:
135137 if char. isLetter || char. isNumber {
@@ -139,22 +141,25 @@ extension String {
139141 buffer. append ( char)
140142 }
141143 state = . accumulatingWord
142- } else if char == " _ " || char == " - " || char == " " {
144+ } else if [ " _ " , " - " , " " ] . contains ( char ) {
143145 // In the middle of an identifier, dashes, underscores, and spaces are considered
144146 // word separators, so we remove the character and end the current word.
145147 state = . waitingForWordStarter
146- } else if char == " . " {
147- // In the middle of an identifier, a period gets replaced with an underscore, but continues
148- // the current word.
148+ } else if [ " . " , " / " ] . contains ( char ) {
149+ // In the middle of an identifier, a period or a slash gets replaced with
150+ // an underscore, but continues the current word.
149151 buffer. append ( " _ " )
150152 state = . accumulatingWord
153+ } else if [ " { " , " } " ] . contains ( char) {
154+ // In the middle of an identifier, curly braces are dropped.
155+ state = . accumulatingWord
151156 } else {
152157 // Illegal character, fall back to the defensive strategy.
153- return safeForSwiftCode_defensive ( options : options )
158+ state = . fallback
154159 }
155160 case . waitingForWordStarter:
156- if char == " _ " || char == " - " {
157- // Between words, just drop dashes, underscores, and spaces , since
161+ if [ " _ " , " - " , " . " , " / " , " { " , " } " ] . contains ( char ) {
162+ // Between words, just drop allowed special characters , since
158163 // we're already between words anyway.
159164 state = . waitingForWordStarter
160165 } else if char. isLetter || char. isNumber {
@@ -163,12 +168,15 @@ extension String {
163168 state = . accumulatingWord
164169 } else {
165170 // Illegal character, fall back to the defensive strategy.
166- return safeForSwiftCode_defensive ( options : options )
171+ state = . fallback
167172 }
168- case . modifying:
173+ case . modifying, . fallback :
169174 preconditionFailure ( " Logic error in \( #function) , string: ' \( self ) ' " )
170175 }
171176 precondition ( state != . modifying, " Logic error in \( #function) , string: ' \( self ) ' " )
177+ if case . fallback = state {
178+ return safeForSwiftCode_defensive ( options: options)
179+ }
172180 }
173181 if buffer. isEmpty || state == . preFirstWord {
174182 return safeForSwiftCode_defensive ( options: options)
0 commit comments