http-client-java, remove unused namer module (#4328)

History: we originally intend to use m4 prenamer (opt-in via
flag/option) to keep names in SDK same as from Swagger (mostly for
brownfield).

But later we decided to just use `@clientName` in client.tsp to
explicitly do the naming, if backward-compatibility is an issue.

This flag/option is not used by any service.
This commit is contained in:
Weidong Xu 2024-09-05 07:12:53 +08:00 коммит произвёл GitHub
Родитель 1dcd5c4c36
Коммит b645fb3d6d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 0 добавлений и 956 удалений

Просмотреть файл

@ -27,7 +27,6 @@ words:
- cobertura
- codehaus
- codeql
- collisons
- Contoso
- CORGE
- createsorreplacesresource

Просмотреть файл

@ -143,7 +143,6 @@ import {
operationIsMultipart,
operationIsMultipleContentTypes,
} from "./operation-utils.js";
import { PreNamer } from "./prenamer/prenamer.js";
import {
ProcessingCache,
getAccess,
@ -265,10 +264,6 @@ export class CodeModelBuilder {
this.processSchemaUsage();
if (this.options.namer) {
this.codeModel = new PreNamer(this.codeModel).init().process();
}
this.deduplicateSchemaName();
return this.codeModel;

Просмотреть файл

@ -25,8 +25,6 @@ export interface EmitterOptions {
"skip-special-headers"?: string[];
namer?: boolean;
"generate-samples"?: boolean;
"generate-tests"?: boolean;
@ -73,9 +71,6 @@ const EmitterOptionsSchema: JSONSchemaType<EmitterOptions> = {
// header
"skip-special-headers": { type: "array", items: { type: "string" }, nullable: true },
// namer
namer: { type: "boolean", nullable: true, default: false },
// sample and test
"generate-samples": { type: "boolean", nullable: true, default: true },
"generate-tests": { type: "boolean", nullable: true, default: true },

Просмотреть файл

@ -1,251 +0,0 @@
import { fixLeadingNumber, removeSequentialDuplicates } from "@azure-tools/codegen";
export type Styler = (
identifier: string | Array<string>,
removeDuplicates: boolean | undefined,
overrides: Record<string, string> | undefined
) => string;
type StylerWithUppercasePreservation = (
identifier: string | Array<string>,
removeDuplicates: boolean | undefined,
overrides: Record<string, string> | undefined,
maxUppercasePreserve: number | undefined
) => string;
function capitalize(s: string): string {
return s ? `${s.charAt(0).toUpperCase()}${s.slice(1)}` : s;
}
function uncapitalize(s: string): string {
return s ? `${s.charAt(0).toLowerCase()}${s.slice(1)}` : s;
}
function IsFullyUpperCase(identifier: string, maxUppercasePreserve: number) {
const len = identifier.length;
if (len > 1) {
if (len <= maxUppercasePreserve && identifier === identifier.toUpperCase()) {
return true;
}
if (len <= maxUppercasePreserve + 1 && identifier.endsWith("s")) {
const i = identifier.substring(0, len - 1);
if (i.toUpperCase() === i) {
return true;
}
}
}
return false;
}
function deconstruct(
identifier: string | Array<string>,
maxUppercasePreserve: number
): Array<string> {
if (Array.isArray(identifier)) {
return [...identifier.flatMap((each) => deconstruct(each, maxUppercasePreserve))];
}
return `${identifier}`
.replace(/([a-z]+)([A-Z])/g, "$1 $2") // Add a space in between camelCase words(e.g. fooBar => foo Bar)
.replace(/(\d+)/g, " $1 ") // Adds a space after numbers(e.g. foo123 => foo123 bar)
.replace(/\b([A-Z]+)([A-Z])s([^a-z])(.*)/g, "$1$2« $3$4") // Add a space after a plural upper cased word(e.g. MBsFoo => MBs Foo)
.replace(/\b([A-Z]+)([A-Z])([a-z]+)/g, "$1 $2$3") // Add a space between an upper case word(2 char+) and the last capital case.(e.g. SQLConnection -> SQL Connection)
.replace(/«/g, "s")
.trim()
.split(/[\W|_]+/)
.map((each) => (IsFullyUpperCase(each, maxUppercasePreserve) ? each : each.toLowerCase()));
}
function wrap(
prefix: string,
postfix: string,
style: StylerWithUppercasePreservation,
maxUppercasePreserve: number
): Styler {
if (postfix || prefix) {
return (i, r, o) =>
typeof i === "string" && typeof o === "object"
? o[i.toLowerCase()] || `${prefix}${style(i, r, o, maxUppercasePreserve)}${postfix}`
: `${prefix}${style(i, r, o, maxUppercasePreserve)}${postfix}`;
}
return (i, r, o) => style(i, r, o, maxUppercasePreserve);
}
function applyFormat(
normalizedContent: Array<string>,
overrides: Record<string, string> = {},
separator = "",
formatter: (s: string, i: number) => string = (s, i) => s
) {
return normalizedContent
.map((each, index) => {
if (Object.keys(overrides).includes(each.toLowerCase())) {
const override = overrides[each.toLowerCase()];
if (override) {
return override;
}
}
return formatter(each, index);
})
.join(separator);
}
function normalize(
identifier: string | Array<string>,
removeDuplicates = true,
overrides: Record<string, string> = {},
maxUppercasePreserve = 0
): Array<string> {
if (!identifier || identifier.length === 0) {
return [""];
}
return typeof identifier === "string"
? normalize(
fixLeadingNumber(deconstruct(identifier, maxUppercasePreserve)),
removeDuplicates,
overrides,
maxUppercasePreserve
)
: removeDuplicates
? removeSequentialDuplicates(identifier)
: identifier;
}
export class Style {
static select(style: any, fallback: Styler, maxUppercasePreserve: number): Styler {
if (style) {
const styles = /^([a-zA-Z0-9_]*?\+?)([a-zA-Z]+)(\+?[a-zA-Z0-9_]*)$/g.exec(
style.replace(/\s*/g, "")
);
if (styles) {
const prefix = styles[1] ? styles[1].substring(0, styles[1].length - 1) : "";
const postfix = styles[3] ? styles[3].substring(1) : "";
switch (styles[2]) {
case "camelcase":
case "camel":
return wrap(prefix, postfix, Style.camel, maxUppercasePreserve);
case "pascalcase":
case "pascal":
return wrap(prefix, postfix, Style.pascal, maxUppercasePreserve);
case "snakecase":
case "snake":
return wrap(prefix, postfix, Style.snake, maxUppercasePreserve);
case "uppercase":
case "upper":
return wrap(prefix, postfix, Style.upper, maxUppercasePreserve);
case "kebabcase":
case "kebab":
return wrap(prefix, postfix, Style.kebab, maxUppercasePreserve);
case "spacecase":
case "space":
return wrap(prefix, postfix, Style.space, maxUppercasePreserve);
}
}
}
return wrap("", "", fallback, maxUppercasePreserve);
}
static kebab(
identifier: string | Array<string>,
removeDuplicates = true,
overrides: Record<string, string> = {},
maxUppercasePreserve = 0
): string {
return (
(Object.keys(overrides).includes(<string>identifier) && overrides[<string>identifier]) ||
applyFormat(
normalize(identifier, removeDuplicates, overrides, maxUppercasePreserve),
overrides,
"-"
).replace(/([^\d])-(\d+)/g, "$1$2")
);
}
static space(
identifier: string | Array<string>,
removeDuplicates = true,
overrides: Record<string, string> = {},
maxUppercasePreserve = 0
): string {
return (
(Object.keys(overrides).includes(<string>identifier) && overrides[<string>identifier]) ||
applyFormat(
normalize(identifier, removeDuplicates, overrides, maxUppercasePreserve),
overrides,
" "
).replace(/([^\d]) (\d+)/g, "$1$2")
);
}
static snake(
identifier: string | Array<string>,
removeDuplicates = true,
overrides: Record<string, string> = {},
maxUppercasePreserve = 0
): string {
return (
(Object.keys(overrides).includes(<string>identifier) && overrides[<string>identifier]) ||
applyFormat(
normalize(identifier, removeDuplicates, overrides, maxUppercasePreserve),
overrides,
"_"
).replace(/([^\d])_(\d+)/g, "$1$2")
);
}
static upper(
identifier: string | Array<string>,
removeDuplicates = true,
overrides: Record<string, string> = {},
maxUppercasePreserve = 0
): string {
return (
(Object.keys(overrides).includes(<string>identifier) && overrides[<string>identifier]) ||
applyFormat(
normalize(identifier, removeDuplicates, overrides, maxUppercasePreserve),
overrides,
"_",
(each) => each.toUpperCase()
).replace(/([^\d])_(\d+)/g, "$1$2")
);
}
static pascal(
identifier: string | Array<string>,
removeDuplicates = true,
overrides: Record<string, string> = {},
maxUppercasePreserve = 0
): string {
return (
(Object.keys(overrides).includes(<string>identifier) && overrides[<string>identifier]) ||
applyFormat(
normalize(identifier, removeDuplicates, overrides, maxUppercasePreserve),
overrides,
"",
(each) => capitalize(each)
)
);
}
static camel(
identifier: string | Array<string>,
removeDuplicates = true,
overrides: Record<string, string> = {},
maxUppercasePreserve = 0
): string {
return (
(Object.keys(overrides).includes(<string>identifier) && overrides[<string>identifier]) ||
applyFormat(
normalize(identifier, removeDuplicates, overrides, maxUppercasePreserve),
overrides,
"",
(each, index) =>
index
? capitalize(each)
: IsFullyUpperCase(each, maxUppercasePreserve)
? each
: uncapitalize(each)
)
);
}
}

Просмотреть файл

@ -1,219 +0,0 @@
import { Languages } from "@autorest/codemodel";
import { deconstruct, fixLeadingNumber, removeSequentialDuplicates } from "@azure-tools/codegen";
import pkg from "lodash";
import { Style, Styler } from "./formatter.js";
const { last } = pkg;
export function getNameOptions(typeName: string, components: Array<string>) {
const result = new Set<string>();
// add a variant for each incrementally inclusive parent naming scheme.
for (let i = 0; i < components.length; i++) {
const subset = Style.pascal([
...removeSequentialDuplicates(components.slice(-1 * i, components.length)),
]);
result.add(subset);
}
// add a second-to-last-ditch option as <typename>.<name>
result.add(
Style.pascal([
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
...removeSequentialDuplicates([
...fixLeadingNumber(deconstruct(typeName)),
...deconstruct(last(components)!),
]),
])
);
return [...result.values()];
}
interface SetNameOptions {
/**
* Remove consecutive duplicate words in the name.
* @example "FooBarBarSomething" -> "FooBarSomething"
*/
removeDuplicates?: boolean;
/**
* Error message if a name is empty.
*/
nameEmptyErrorMessage?: string;
}
const setNameDefaultOptions = Object.freeze({
removeDuplicates: true,
});
export interface Nameable {
language: Languages;
}
export class NamingService {
public constructor() {}
public setName(
thing: Nameable,
styler: Styler,
defaultValue: string,
overrides: Record<string, string>,
options?: SetNameOptions
) {
this.setNameAllowEmpty(thing, styler, defaultValue, overrides, options);
// if (!thing.language.default.name) {
// this.session.error(options?.nameEmptyErrorMessage ?? getNameEmptyError(thing), ["Prenamer", "NameEmpty"], thing);
// }
}
public setNameAllowEmpty(
thing: Nameable,
styler: Styler,
defaultValue: string,
overrides: Record<string, string>,
options?: SetNameOptions
) {
options = { ...setNameDefaultOptions, ...options };
thing.language.default.name = styler(
defaultValue && isUnassigned(thing.language.default.name)
? defaultValue
: thing.language.default.name,
options.removeDuplicates,
overrides
);
}
}
export function isUnassigned(value: string) {
return !value || value.indexOf("·") > -1;
}
export interface ScopeNamerOptions {
deduplicateNames?: boolean;
overrides?: Record<string, string>;
}
interface NamerEntry {
entity: Nameable;
styler: Styler;
initialName: string;
}
/**
* Class that will style and resolve unique names for entities in the same scope.
*/
export class ScopeNamer {
private names = new Map<string, NamerEntry[]>();
public constructor(private options: ScopeNamerOptions) {}
/**
* Add a nameable entity to be styled and named.
* @param entity Nameable entity.
* @param styler Styler to use to render name.
* @param defaultName Default name in case entity doesn't have any specified.
*/
public add(entity: Nameable, styler: Styler, defaultName?: string) {
const initialName =
defaultName && isUnassigned(entity.language.default.name)
? defaultName
: entity.language.default.name;
const name = styler(initialName, false, this.options.overrides);
const list = this.names.get(name);
const entry = { entity, styler, initialName };
if (list) {
list.push(entry);
} else {
this.names.set(name, [entry]);
}
}
/**
* Returns true if the name is already used in this scope.
* @param name Name to check
* @returns Boolean
*/
public isUsed(name: string): boolean {
return this.names.has(name);
}
/**
* Trigger the renaming process.
* Will go over all the entity and find best possible names.
*/
public process() {
const state = this.processSimplifyNames();
if (this.options.deduplicateNames) {
this.deduplicateNames(state);
}
}
/**
* 1st pass of the name resolving where it tries to simplify names with duplicate consecutive words.
*/
private processSimplifyNames(): Map<string, Nameable[]> {
const processedNames = new Map<string, Nameable[]>();
for (const [name, entities] of this.names.entries()) {
for (const { entity, styler, initialName } of entities) {
let selectedName = name;
const noDupName = styler(initialName, true, this.options.overrides);
if (noDupName !== name) {
if (!this.names.has(noDupName) && !processedNames.has(noDupName)) {
selectedName = noDupName;
}
}
entity.language.default.name = selectedName;
const entries = processedNames.get(selectedName);
if (entries) {
entries.push(entity);
} else {
processedNames.set(selectedName, [entity]);
}
}
}
return processedNames;
}
/**
* 2nd pass of the name resolving where it will deduplicate names used twice.
*/
private deduplicateNames(names: Map<string, Nameable[]>) {
const entityNames = new Set(names.keys());
for (const [_, entries] of names.entries()) {
if (entries.length > 1) {
for (const entity of entries.slice(1)) {
this.deduplicateSchemaName(entity, entityNames);
}
}
}
}
/**
* Tries to find a new compatible name for the given schema.
*/
private deduplicateSchemaName(schema: Nameable, entityNames: Set<string>): void {
const schemaName = schema.language.default.name;
const maxDedupes = 1000;
if (entityNames.has(schemaName)) {
for (let i = 1; i <= maxDedupes; i++) {
const newName = `${schemaName}AutoGenerated${i === 1 ? "" : i}`;
if (!entityNames.has(newName)) {
schema.language.default.name = newName;
entityNames.add(newName);
// this.session.warning(`Deduplicating schema name: '${schemaName}' -> '${newName}'`, [
// "PreNamer/DeduplicateName",
// ]);
return;
}
}
// this.session.error(
// `Attempted to deduplicate schema name '${schema.language.default.name}' more than ${maxDedupes} times and failed.`,
// ["PreNamer/DeduplicateName"],
// );
}
entityNames.add(schemaName);
}
}

Просмотреть файл

@ -1,475 +0,0 @@
import {
getAllParentProperties,
ImplementationLocation,
isObjectSchema,
isVirtualParameter,
Languages,
ObjectSchema,
Parameter,
Response,
SchemaType,
} from "@autorest/codemodel";
import { selectName } from "@azure-tools/codegen";
import pkg from "lodash";
import { CodeModel } from "../common/code-model.js";
import { Operation, Request } from "../common/operation.js";
import { ChoiceSchema, SealedChoiceSchema } from "../common/schemas/choice.js";
import { Style } from "./formatter.js";
import { getNameOptions, isUnassigned, NamingService, ScopeNamer } from "./naming-utils.js";
const { partition } = pkg;
export class PreNamer {
codeModel: CodeModel;
options: any = {};
format = {
parameter: Style.camel,
property: Style.camel,
operation: Style.camel,
operationGroup: Style.pascal,
responseHeader: Style.camel,
choice: Style.pascal,
choiceValue: Style.upper,
constant: Style.pascal,
constantParameter: Style.camel,
type: Style.pascal,
client: Style.pascal,
local: Style.camel,
global: Style.pascal,
override: <Record<string, string>>{},
};
enum = 0;
constant = 0;
private namingService: NamingService;
constructor(codeModel: CodeModel) {
this.codeModel = codeModel;
this.namingService = new NamingService();
}
init() {
// get our configuration for this run.
this.options = {
prenamer: true,
naming: {
parameter: "camel",
property: "camel",
operation: "camel",
operationGroup: "pascal",
choice: "pascal",
choiceValue: "upper",
constant: "pascal",
constantParameter: "camel",
client: "pascal",
type: "pascal",
local: "camel",
global: "camel",
"preserve-uppercase-max-length": 1,
},
};
const naming = this.options.naming || {};
const maxPreserve = Number(naming["preserve-uppercase-max-length"]) || 3;
this.format = {
parameter: Style.select(naming.parameter, Style.camel, maxPreserve),
property: Style.select(naming.property, Style.camel, maxPreserve),
operation: Style.select(naming.operation, Style.camel, maxPreserve),
operationGroup: Style.select(naming.operationGroup, Style.pascal, maxPreserve),
responseHeader: Style.select(naming.header, Style.camel, maxPreserve),
choice: Style.select(naming.choice, Style.pascal, maxPreserve),
choiceValue: Style.select(naming.choiceValue, Style.upper, maxPreserve),
constant: Style.select(naming.constant, Style.pascal, maxPreserve),
constantParameter: Style.select(naming.constantParameter, Style.camel, maxPreserve),
client: Style.select(naming.client, Style.pascal, maxPreserve),
type: Style.select(naming.type, Style.pascal, maxPreserve),
local: Style.select(naming.local, Style.camel, maxPreserve),
global: Style.select(naming.global, Style.pascal, maxPreserve),
override: naming.override || {},
};
return this;
}
process() {
if (this.options["prenamer"] === false) {
return this.codeModel;
}
const deduplicateSchemaNames =
!!this.options["lenient-model-deduplication"] ||
!!this.options["resolve-schema-name-collisons"];
const scopeNamer = new ScopeNamer({
deduplicateNames: deduplicateSchemaNames,
overrides: this.format.override,
});
// choice
this.processChoiceNames(this.codeModel.schemas.choices, scopeNamer);
// sealed choice
this.processChoiceNames(this.codeModel.schemas.sealedChoices, scopeNamer);
// constant
for (const schema of values(this.codeModel.schemas.constants)) {
this.namingService.setName(
schema,
this.format.constant,
`Constant${this.enum++}`,
this.format.override
);
}
// ors
for (const schema of values(this.codeModel.schemas.ors)) {
this.namingService.setName(
schema,
this.format.type,
`Union${this.enum++}`,
this.format.override
);
}
// strings
for (const schema of values(this.codeModel.schemas.strings)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
// number
for (const schema of values(this.codeModel.schemas.numbers)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
for (const schema of values(this.codeModel.schemas.dates)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
for (const schema of values(this.codeModel.schemas.dateTimes)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
for (const schema of values(this.codeModel.schemas.durations)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
for (const schema of values(this.codeModel.schemas.uuids)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
for (const schema of values(this.codeModel.schemas.uris)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
for (const schema of values(this.codeModel.schemas.unixtimes)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
if (isUnassigned(schema.language.default.description)) {
schema.language.default.description = "date in seconds since 1970-01-01T00:00:00Z.";
}
}
for (const schema of values(this.codeModel.schemas.byteArrays)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
for (const schema of values(this.codeModel.schemas.chars)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
for (const schema of values(this.codeModel.schemas.booleans)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
for (const schema of values(this.codeModel.schemas.flags)) {
this.namingService.setName(schema, this.format.type, schema.type, this.format.override);
}
// dictionary
for (const schema of values(this.codeModel.schemas.dictionaries)) {
this.namingService.setName(
schema,
this.format.type,
`DictionaryOf${schema.elementType.language.default.name}`,
this.format.override
);
if (isUnassigned(schema.language.default.description)) {
schema.language.default.description = `Dictionary of ${schema.elementType.language.default.name}`;
}
}
for (const schema of values(this.codeModel.schemas.arrays)) {
this.namingService.setName(
schema,
this.format.type,
`ArrayOf${schema.elementType.language.default.name}`,
this.format.override
);
if (isUnassigned(schema.language.default.description)) {
schema.language.default.description = `Array of ${schema.elementType.language.default.name}`;
}
}
for (const schema of values(this.codeModel.schemas.objects)) {
scopeNamer.add(schema, this.format.type, "");
const propertyScopeName = new ScopeNamer({
deduplicateNames: false,
overrides: this.format.override,
});
for (const property of values(schema.properties)) {
propertyScopeName.add(property, this.format.property, "");
}
propertyScopeName.process();
}
for (const schema of values(this.codeModel.schemas.groups)) {
scopeNamer.add(schema, this.format.type, "");
for (const property of values(schema.properties)) {
this.namingService.setName(property, this.format.property, "", this.format.override);
}
}
for (const parameter of values(this.codeModel.globalParameters)) {
if (parameter.schema.type === SchemaType.Constant) {
this.namingService.setName(
parameter,
this.format.constantParameter,
"",
this.format.override
);
} else {
this.namingService.setName(parameter, this.format.parameter, "", this.format.override);
}
}
for (const operationGroup of this.codeModel.operationGroups) {
this.namingService.setNameAllowEmpty(
operationGroup,
this.format.operationGroup,
operationGroup.$key,
this.format.override,
{
removeDuplicates: false,
}
);
const operationScopeNamer = new ScopeNamer({
overrides: this.format.override,
});
for (const operation of operationGroup.operations) {
operationScopeNamer.add(operation, this.format.operation, "");
this.setParameterNames(operation);
for (const request of values(operation.requests)) {
this.setParameterNames(request);
}
for (const response of values(operation.responses)) {
this.setResponseHeaderNames(response);
}
for (const response of values(operation.exceptions)) {
this.setResponseHeaderNames(response);
}
const convenienceApi = (operation as Operation).convenienceApi;
if (convenienceApi) {
this.namingService.setName(
convenienceApi,
this.format.operation,
"",
this.format.override
);
}
const p = operation.language.default.paging;
if (p) {
p.group = p.group
? this.format.operationGroup(p.group, true, this.format.override)
: undefined;
p.member = p.member
? this.format.operation(p.member, true, this.format.override)
: undefined;
}
}
operationScopeNamer.process();
}
scopeNamer.process();
// set a styled client name
this.namingService.setName(
this.codeModel,
this.format.client,
this.codeModel.info.title,
this.format.override
);
if (this.codeModel.clients) {
// client
for (const client of this.codeModel.clients) {
this.namingService.setName(client, this.format.client, "", this.format.override);
// operation group
for (const operationGroup of client.operationGroups) {
this.namingService.setNameAllowEmpty(
operationGroup,
this.format.operationGroup,
operationGroup.$key,
this.format.override,
{
removeDuplicates: false,
}
);
}
}
}
// fix collisions from flattening on ObjectSchemas
this.fixPropertyCollisions();
// fix collisions from flattening on VirtualParameters
this.fixParameterCollisions();
return this.codeModel;
}
private processChoiceNames(
choices: Array<ChoiceSchema | SealedChoiceSchema> | undefined,
scopeNamer: ScopeNamer
) {
for (const schema of values(choices)) {
scopeNamer.add(schema, this.format.choice, `Enum${this.enum++}`);
for (const choice of values(schema.choices)) {
this.namingService.setName(choice, this.format.choiceValue, "", this.format.override, {
removeDuplicates: false,
nameEmptyErrorMessage: `Enum '${schema.language.default.name}' cannot have a value '${choice.value}' that result in an empty name. Use x-ms-enum.values to specify the name of the values.`,
});
}
}
}
private setParameterNames(parameterContainer: Operation | Request) {
for (const parameter of values(parameterContainer.signatureParameters)) {
if (parameter.schema.type === SchemaType.Constant) {
this.namingService.setName(
parameter,
this.format.constantParameter,
"",
this.format.override
);
} else {
this.namingService.setName(parameter, this.format.parameter, "", this.format.override);
}
}
for (const parameter of values(parameterContainer.parameters)) {
if ((parameterContainer.signatureParameters ?? []).indexOf(parameter) === -1) {
if (parameter.schema.type === SchemaType.Constant) {
this.namingService.setName(
parameter,
this.format.constantParameter,
"",
this.format.override
);
} else {
if (parameter.implementation === ImplementationLocation.Client) {
this.namingService.setName(parameter, this.format.global, "", this.format.override);
} else {
this.namingService.setName(parameter, this.format.local, "", this.format.override);
}
}
}
}
}
private setResponseHeaderNames(response: Response) {
if (response.protocol.http) {
for (const header of Object.values(response.protocol.http.headers ?? {})) {
this.namingService.setName(
header as { language: Languages },
this.format.responseHeader,
"",
this.format.override
);
}
}
}
fixParameterCollisions() {
for (const operation of values(this.codeModel.operationGroups).flatMap(
(each) => each.operations
)) {
for (const request of values(operation.requests)) {
const parameters = values(operation.signatureParameters).concat(
values(request.signatureParameters)
);
const usedNames = new Set<string>();
const collisions = new Set<Parameter>();
// we need to make sure we avoid name collisions. operation parameters get first crack.
for (const each of values(parameters)) {
const name = this.format.parameter(each.language.default.name);
if (usedNames.has(name)) {
collisions.add(each);
} else {
usedNames.add(name);
}
}
// handle operation parameters
for (const parameter of collisions) {
let options = [parameter.language.default.name];
if (isVirtualParameter(parameter)) {
options = getNameOptions(parameter.schema.language.default.name, [
parameter.language.default.name,
...parameter.pathToProperty.map((each) => each.language.default.name),
]).map((each) => this.format.parameter(each));
}
parameter.language.default.name = this.format.parameter(selectName(options, usedNames));
}
}
}
}
fixCollisions(schema: ObjectSchema) {
for (const each of values(schema.parents?.immediate).filter((each) => isObjectSchema(each))) {
this.fixCollisions(<ObjectSchema>each);
}
const [owned, flattened] = partition(
schema.properties ?? [],
(each) => each.flattenedNames === undefined || each.flattenedNames.length === 0
);
const inherited = [...getAllParentProperties(schema)];
const all = [...owned, ...inherited, ...flattened];
const inlined = new Map<string, number>();
for (const each of all) {
const name = this.format.property(each.language.default.name);
// track number of instances of a given name.
inlined.set(name, (inlined.get(name) || 0) + 1);
}
const usedNames = new Set(inlined.keys());
for (const each of flattened /*.sort((a, b) => length(a.nameOptions) - length(b.nameOptions)) */) {
const ct = inlined.get(this.format.property(each.language.default.name));
if (ct && ct > 1) {
const options = getNameOptions(each.schema.language.default.name, [
each.language.default.name,
...values(each.flattenedNames),
]);
each.language.default.name = this.format.property(selectName(options, usedNames));
}
}
}
fixPropertyCollisions() {
for (const schema of values(this.codeModel.schemas.objects)) {
this.fixCollisions(schema);
}
}
}
function values<T>(item: T[] | undefined): T[] {
return Object.values(item ?? []);
}