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

* ♻️
This commit is contained in:
inferrinizzard
2024-05-18 13:39:15 -07:00
committed by GitHub
parent 3ddcadf332
commit ed1ffa43e9
4 changed files with 26 additions and 20 deletions

View File

@ -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";

View File

@ -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
@ -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, '")]');
@ -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}")]`);
}
@ -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}")]`);
}

View File

@ -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("_"),
@ -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)) {
@ -132,13 +136,13 @@ 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;
}
@ -146,13 +150,13 @@ export function getPreferedNamingStyle(namingStyleOccurences: string[], defaultS
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;
}

View File

@ -10,7 +10,8 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"outDir": "dist",
"baseUrl": "src"
"baseUrl": "src",
"resolveJsonModule": true
},
"include": ["src"]
}