Skip to content

Commit

Permalink
chore(rust): Strongly type Rust NamingStyles (#2602)
Browse files Browse the repository at this point in the history
* 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

* ♻️
  • Loading branch information
inferrinizzard authored May 18, 2024
1 parent 3ddcadf commit ed1ffa4
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 20 deletions.
2 changes: 1 addition & 1 deletion packages/quicktype-core/src/language/CJSON/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { type RenderContext } from "../../Renderer";
import { EnumOption, type Option, StringOption, getOptionValues } from "../../RendererOptions";
import { type NamingStyle } from "../../support/Strings";
import { TargetLanguage } from "../../TargetLanguage";
import { type FixMeOptionsType, type FixMeOptionsAnyType } from "../../types";
import { type FixMeOptionsAnyType, type FixMeOptionsType } from "../../types";

import { CJSONRenderer } from "./CJSONRenderer";

Expand Down
15 changes: 8 additions & 7 deletions packages/quicktype-core/src/language/Rust/RustRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ import { keywords } from "./constants";
import { type rustOptions } from "./language";
import {
Density,
type NamingStyleKey,
Visibility,
camelNamingFunction,
getPreferedNamingStyle,
getPreferredNamingStyle,
listMatchingNamingStyles,
nameToNamingStyle,
nameWithNamingStyle,
namingStyles,
rustStringEscape,
snakeNamingFunction
Expand Down Expand Up @@ -121,12 +122,12 @@ export class RustRenderer extends ConvenienceRenderer {
private emitRenameAttribute(
propName: Name,
jsonName: string,
defaultNamingStyle: string,
preferedNamingStyle: string
defaultNamingStyle: NamingStyleKey,
preferedNamingStyle: NamingStyleKey
): void {
const escapedName = rustStringEscape(jsonName);
const name = namingStyles[defaultNamingStyle].fromParts(this.sourcelikeToString(propName).split(" "));
const styledName = nameToNamingStyle(name, preferedNamingStyle);
const styledName = nameWithNamingStyle(name, preferedNamingStyle);
const namesDiffer = escapedName !== styledName;
if (namesDiffer) {
this.emitLine('#[serde(rename = "', escapedName, '")]');
Expand Down Expand Up @@ -168,7 +169,7 @@ export class RustRenderer extends ConvenienceRenderer {

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

// Set the default naming style on the enum
const defaultStyle = "PascalCase";
const preferedNamingStyle = getPreferedNamingStyle(Object.values(enumCasesNamingStyles).flat(), defaultStyle);
const preferedNamingStyle = getPreferredNamingStyle(Object.values(enumCasesNamingStyles).flat(), defaultStyle);
if (preferedNamingStyle !== defaultStyle) {
this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`);
}
Expand Down
26 changes: 15 additions & 11 deletions packages/quicktype-core/src/language/Rust/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface NamingStyle {
toParts: NameToParts;
}

export const namingStyles: Record<string, NamingStyle> = {
export const namingStyles = {
snake_case: {
regex: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/,
toParts: (name: string): string[] => name.split("_"),
Expand Down Expand Up @@ -80,7 +80,11 @@ export const namingStyles: Record<string, NamingStyle> = {
toParts: (name: string): string[] => [name],
fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("")
}
};
} as const;

namingStyles satisfies Record<string, NamingStyle>;

export type NamingStyleKey = keyof typeof namingStyles;

const isAsciiLetterOrUnderscoreOrDigit = (codePoint: number): boolean => {
if (!isAscii(codePoint)) {
Expand Down Expand Up @@ -132,27 +136,27 @@ const standardUnicodeRustEscape = (codePoint: number): string => {

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

export function getPreferedNamingStyle(namingStyleOccurences: string[], defaultStyle: string): string {
export function getPreferredNamingStyle(namingStyleOccurences: string[], defaultStyle: NamingStyleKey): NamingStyleKey {
const occurrences = Object.fromEntries(Object.keys(namingStyles).map(key => [key, 0]));
namingStyleOccurences.forEach(style => ++occurrences[style]);
const max = Math.max(...Object.values(occurrences));
const preferedStyles = Object.entries(occurrences)
.filter(([_style, num]) => num === max)
.map(([style, _num]) => style);
const preferedStyles = Object.entries(occurrences).flatMap(([style, num]) =>
num === max ? [style] : []
) as NamingStyleKey[];
if (preferedStyles.includes(defaultStyle)) {
return defaultStyle;
}

return preferedStyles[0];
}

export function listMatchingNamingStyles(name: string): string[] {
return Object.entries(namingStyles)
.filter(([_, { regex }]) => regex.test(name))
.map(([namingStyle, _]) => namingStyle);
export function listMatchingNamingStyles(name: string): NamingStyleKey[] {
return Object.entries(namingStyles).flatMap(([namingStyleKey, { regex }]) =>
regex.test(name) ? [namingStyleKey] : []
) as NamingStyleKey[];
}

export function nameToNamingStyle(name: string, style: string): string {
export function nameWithNamingStyle(name: string, style: NamingStyleKey): string {
if (namingStyles[style].regex.test(name)) {
return name;
}
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"outDir": "dist",
"baseUrl": "src"
"baseUrl": "src",
"resolveJsonModule": true
},
"include": ["src"]
}

0 comments on commit ed1ffa4

Please sign in to comment.