2424 * A legal name is:
2525 * 1. not empty.
2626 * 2. doesn't collide with other names.
27- * 3. Optional: begins with a letter .
27+ * 3. Optional: is a valid python identifier .
2828 */
29- export function makeLegalName ( proposedName : string , otherNames : string [ ] , mustBeginWithLetter : boolean ) : string {
29+ export function makeLegalName ( proposedName : string , otherNames : string [ ] , mustBeValidPythonIdentifier : boolean ) : string {
3030 const otherNamesLowerCase = otherNames . map ( n => n . toLowerCase ( ) ) ;
3131
3232 // Strip leading and trailing whitespace.
@@ -35,10 +35,27 @@ export function makeLegalName(proposedName: string, otherNames: string[], mustBe
3535 // Make the name non-empty.
3636 name = name || 'unnamed' ;
3737
38- if ( mustBeginWithLetter ) {
39- // If the name begins with a non-alphabetic character, insert the letter a at the beginning.
40- if ( ! name . match ( / ^ [ a - z A - Z ] .* $ / ) ) {
41- name = 'a' + name ;
38+ if ( mustBeValidPythonIdentifier ) {
39+ if ( ! name . match ( / ^ [ a - z A - Z _ ] [ a - z A - Z 0 - 9 _ ] * $ / ) ) {
40+ let identifier = '' ;
41+ const firstChar = name [ 0 ] ;
42+ if ( / [ a - z A - Z _ ] / . test ( firstChar ) ) {
43+ identifier += firstChar ;
44+ } else if ( / [ a - z A - Z 0 - 9 _ ] / . test ( firstChar ) ) {
45+ // If the first character would be valid as the second charactor, insert an underscore.
46+ identifier += '_' + firstChar ;
47+ } else {
48+ identifier += '_' ;
49+ }
50+ for ( let i = 1 ; i < name . length ; i ++ ) {
51+ const char = name [ i ] ;
52+ if ( / [ a - z A - Z 0 - 9 _ ] / . test ( char ) ) {
53+ identifier += char ;
54+ } else {
55+ identifier += '_' ;
56+ }
57+ }
58+ name = identifier ;
4259 }
4360 }
4461
0 commit comments