Skip to content

Commit ed1ffa4

Browse files
chore(rust): Strongly type Rust NamingStyles (#2602)
* standardise json formatting * add file association for schema files * install eslint packages * add eslint config * remove tslint * eslint autofix * update eslint rules, eslintignore * add lint:fix script * update eslint rules, eslintignore * add lint:fix script * add import rules * add import rules * update import rules * reduce excess style rules * downgrade remaining to warnings * fix enum values fixup! fix enum values * add all missing accessibility modifiers fixup! add all missing accessibility modifiers fixup! add all missing accessibility modifiers * fix nullish errors * update import rules * fix all require imports * fix all imports * reduce excess style rules * fix any types fixup! fix any types fixup! fix any types * fix misc errors * downgrade remaining to warnings * return types * fix types errors * fix json import for test tsconfig * auto lint fix * fix lint errors in extension * fix lint errors in Elixir * make ref.pushElement public * fix misc * fix accidental public in CSharp raw text get * fix new lint errors * Merge branch 'refactor/imports/languages' * strongly type Rust naming styles * fix typo * unify emitDeriveHeader for Rust * ♻️
1 parent 3ddcadf commit ed1ffa4

File tree

4 files changed

+26
-20
lines changed

4 files changed

+26
-20
lines changed

packages/quicktype-core/src/language/CJSON/language.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { type RenderContext } from "../../Renderer";
2525
import { EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions";
2626
import { type NamingStyle } from "../../support/Strings";
2727
import { TargetLanguage } from "../../TargetLanguage";
28-
import { type FixMeOptionsType, type FixMeOptionsAnyType } from "../../types";
28+
import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types";
2929

3030
import { CJSONRenderer } from "./CJSONRenderer";
3131

packages/quicktype-core/src/language/Rust/RustRenderer.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ import { keywords } from "./constants";
1616
import { type rustOptions } from "./language";
1717
import {
1818
Density,
19+
type NamingStyleKey,
1920
Visibility,
2021
camelNamingFunction,
21-
getPreferedNamingStyle,
22+
getPreferredNamingStyle,
2223
listMatchingNamingStyles,
23-
nameToNamingStyle,
24+
nameWithNamingStyle,
2425
namingStyles,
2526
rustStringEscape,
2627
snakeNamingFunction
@@ -121,12 +122,12 @@ export class RustRenderer extends ConvenienceRenderer {
121122
private emitRenameAttribute(
122123
propName: Name,
123124
jsonName: string,
124-
defaultNamingStyle: string,
125-
preferedNamingStyle: string
125+
defaultNamingStyle: NamingStyleKey,
126+
preferedNamingStyle: NamingStyleKey
126127
): void {
127128
const escapedName = rustStringEscape(jsonName);
128129
const name = namingStyles[defaultNamingStyle].fromParts(this.sourcelikeToString(propName).split(" "));
129-
const styledName = nameToNamingStyle(name, preferedNamingStyle);
130+
const styledName = nameWithNamingStyle(name, preferedNamingStyle);
130131
const namesDiffer = escapedName !== styledName;
131132
if (namesDiffer) {
132133
this.emitLine('#[serde(rename = "', escapedName, '")]');
@@ -168,7 +169,7 @@ export class RustRenderer extends ConvenienceRenderer {
168169

169170
// Set the default naming style on the struct
170171
const defaultStyle = "snake_case";
171-
const preferedNamingStyle = getPreferedNamingStyle(Object.values(propertiesNamingStyles).flat(), defaultStyle);
172+
const preferedNamingStyle = getPreferredNamingStyle(Object.values(propertiesNamingStyles).flat(), defaultStyle);
172173
if (preferedNamingStyle !== defaultStyle) {
173174
this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`);
174175
}
@@ -240,7 +241,7 @@ export class RustRenderer extends ConvenienceRenderer {
240241

241242
// Set the default naming style on the enum
242243
const defaultStyle = "PascalCase";
243-
const preferedNamingStyle = getPreferedNamingStyle(Object.values(enumCasesNamingStyles).flat(), defaultStyle);
244+
const preferedNamingStyle = getPreferredNamingStyle(Object.values(enumCasesNamingStyles).flat(), defaultStyle);
244245
if (preferedNamingStyle !== defaultStyle) {
245246
this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`);
246247
}

packages/quicktype-core/src/language/Rust/utils.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ interface NamingStyle {
3333
toParts: NameToParts;
3434
}
3535

36-
export const namingStyles: Record<string, NamingStyle> = {
36+
export const namingStyles = {
3737
snake_case: {
3838
regex: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,
3939
toParts: (name: string): string[] => name.split("_"),
@@ -80,7 +80,11 @@ export const namingStyles: Record<string, NamingStyle> = {
8080
toParts: (name: string): string[] => [name],
8181
fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("")
8282
}
83-
};
83+
} as const;
84+
85+
namingStyles satisfies Record<string, NamingStyle>;
86+
87+
export type NamingStyleKey = keyof typeof namingStyles;
8488

8589
const isAsciiLetterOrUnderscoreOrDigit = (codePoint: number): boolean => {
8690
if (!isAscii(codePoint)) {
@@ -132,27 +136,27 @@ const standardUnicodeRustEscape = (codePoint: number): string => {
132136

133137
export const rustStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeRustEscape));
134138

135-
export function getPreferedNamingStyle(namingStyleOccurences: string[], defaultStyle: string): string {
139+
export function getPreferredNamingStyle(namingStyleOccurences: string[], defaultStyle: NamingStyleKey): NamingStyleKey {
136140
const occurrences = Object.fromEntries(Object.keys(namingStyles).map(key => [key, 0]));
137141
namingStyleOccurences.forEach(style => ++occurrences[style]);
138142
const max = Math.max(...Object.values(occurrences));
139-
const preferedStyles = Object.entries(occurrences)
140-
.filter(([_style, num]) => num === max)
141-
.map(([style, _num]) => style);
143+
const preferedStyles = Object.entries(occurrences).flatMap(([style, num]) =>
144+
num === max ? [style] : []
145+
) as NamingStyleKey[];
142146
if (preferedStyles.includes(defaultStyle)) {
143147
return defaultStyle;
144148
}
145149

146150
return preferedStyles[0];
147151
}
148152

149-
export function listMatchingNamingStyles(name: string): string[] {
150-
return Object.entries(namingStyles)
151-
.filter(([_, { regex }]) => regex.test(name))
152-
.map(([namingStyle, _]) => namingStyle);
153+
export function listMatchingNamingStyles(name: string): NamingStyleKey[] {
154+
return Object.entries(namingStyles).flatMap(([namingStyleKey, { regex }]) =>
155+
regex.test(name) ? [namingStyleKey] : []
156+
) as NamingStyleKey[];
153157
}
154158

155-
export function nameToNamingStyle(name: string, style: string): string {
159+
export function nameWithNamingStyle(name: string, style: NamingStyleKey): string {
156160
if (namingStyles[style].regex.test(name)) {
157161
return name;
158162
}

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"noUnusedParameters": true,
1111
"noFallthroughCasesInSwitch": true,
1212
"outDir": "dist",
13-
"baseUrl": "src"
13+
"baseUrl": "src",
14+
"resolveJsonModule": true
1415
},
1516
"include": ["src"]
1617
}

0 commit comments

Comments
 (0)