Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ function fromSdkClient(
methodParameterSegments: diagnostics.pipe(
getMethodParameterSegments(sdkContext, parameter),
),
isExactName: parameter.isExactName,
});
}
return diagnostics.wrap(parameters);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,7 @@ function fromQueryParameter(
crossLanguageDefinitionId: p.crossLanguageDefinitionId,
readOnly: isReadOnly(p),
methodParameterSegments: diagnostics.pipe(getMethodParameterSegments(sdkContext, p)),
isExactName: p.isExactName,
};

sdkContext.__typeCache.updateSdkOperationParameterReferences(p, retVar);
Expand Down Expand Up @@ -539,6 +540,7 @@ function fromPathParameter(
readOnly: isReadOnly(p),
crossLanguageDefinitionId: p.crossLanguageDefinitionId,
methodParameterSegments: diagnostics.pipe(getMethodParameterSegments(sdkContext, p)),
isExactName: p.isExactName,
};

sdkContext.__typeCache.updateSdkOperationParameterReferences(p, retVar);
Expand Down Expand Up @@ -574,6 +576,7 @@ function fromHeaderParameter(
crossLanguageDefinitionId: p.crossLanguageDefinitionId,
methodParameterSegments: diagnostics.pipe(getMethodParameterSegments(sdkContext, p)),
collectionHeaderPrefix: diagnostics.pipe(getCollectionHeaderPrefix(sdkContext, p)),
isExactName: p.isExactName,
};

sdkContext.__typeCache.updateSdkOperationParameterReferences(p, retVar);
Expand Down Expand Up @@ -604,6 +607,7 @@ function fromBodyParameter(
readOnly: isReadOnly(p),
crossLanguageDefinitionId: p.crossLanguageDefinitionId,
methodParameterSegments: diagnostics.pipe(getMethodParameterSegments(sdkContext, p)),
isExactName: p.isExactName,
};

sdkContext.__typeCache.updateSdkOperationParameterReferences(p, retVar);
Expand Down Expand Up @@ -645,6 +649,7 @@ export function fromMethodParameter(
access: p.access,
decorators: p.decorators,
paramAlias,
isExactName: p.isExactName,
};

sdkContext.__typeCache.updateSdkMethodParameterReferences(p, retVar);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ function fromSdkModelType(
decorators: decorators,
external: fromSdkExternalTypeInfo(modelType),
serializationOptions: modelType.serializationOptions,
isExactName: modelType.isExactName,
} as InputModelType;

sdkContext.__typeCache.updateSdkTypeReferences(modelType, inputModelType);
Expand Down Expand Up @@ -291,6 +292,7 @@ function fromSdkModelProperty(
// A property is defined to be metadata if it is marked `@header`, `@cookie`, `@query`, `@path`.
isHttpMetadata: isHttpMetadata(sdkContext, sdkProperty),
encode: sdkProperty.encode,
isExactName: sdkProperty.isExactName,
} as InputModelProperty;

if (property) {
Expand Down Expand Up @@ -342,6 +344,7 @@ function createEnumType(
usage: sdkType.kind === "enum" ? sdkType.usage : UsageFlags.None,
decorators: sdkType.decorators,
external: fromSdkExternalTypeInfo(sdkType),
isExactName: sdkType.isExactName,
};

sdkContext.__typeCache.updateSdkTypeReferences(sdkType, inputEnumType);
Expand Down Expand Up @@ -431,6 +434,7 @@ function fromUnionType(
namespace: union.namespace,
decorators: union.decorators,
external: fromSdkExternalTypeInfo(union),
isExactName: union.isExactName,
});
}

Expand All @@ -448,6 +452,7 @@ function fromSdkConstantType(
valueType: diagnostics.pipe(fromSdkType(sdkContext, constantType.valueType)),
value: constantType.value,
decorators: constantType.decorators,
isExactName: constantType.isExactName,
};

sdkContext.__typeCache.updateConstantCache(constantType, literalType);
Expand Down
10 changes: 10 additions & 0 deletions packages/http-client-csharp/emitter/src/type/input-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ export interface InputLiteralType extends InputTypeBase {
namespace: string;
valueType: InputPrimitiveType;
value: string | number | boolean | null;
/** Whether the name should be used exactly as-is, without casing transformations. */
isExactName?: boolean;
}

export function isInputLiteralType(type: InputType): type is InputLiteralType {
Expand Down Expand Up @@ -135,6 +137,8 @@ export interface InputUnionType extends InputTypeBase {
name: string;
variantTypes: InputType[];
namespace: string;
/** Whether the name should be used exactly as-is, without casing transformations. */
isExactName?: boolean;
}

export function isInputUnionType(type: InputType): type is InputUnionType {
Expand All @@ -159,6 +163,8 @@ export interface InputModelType extends InputTypeBase {
discriminatorProperty?: InputModelProperty;
baseModel?: InputModelType;
serializationOptions: SerializationOptions;
/** Whether the name should be used exactly as-is, without casing transformations. */
isExactName?: boolean;
}

export interface InputPropertyTypeBase extends DecoratedType {
Expand All @@ -172,6 +178,8 @@ export interface InputPropertyTypeBase extends DecoratedType {
crossLanguageDefinitionId: string;
readOnly: boolean;
access?: AccessFlags;
/** Whether the name should be used exactly as-is, without casing transformations. */
isExactName?: boolean;
}

export interface InputModelProperty extends InputPropertyTypeBase {
Expand Down Expand Up @@ -265,6 +273,8 @@ export interface InputEnumType extends InputTypeBase {
usage: UsageFlags;
access?: AccessFlags;
namespace: string;
/** Whether the name should be used exactly as-is, without casing transformations. */
isExactName?: boolean;
}

export interface InputEnumValueType extends InputTypeBase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1095,3 +1095,78 @@ describe("XML serialization options", () => {
strictEqual(itemsProperty.serializationOptions.xml.itemsName, "Item");
});
});

describe("Test isExactName propagation", () => {
let runner: TestHost;

beforeEach(async () => {
runner = await createEmitterTestHost();
});

it("propagates isExactName from @clientName decorator with exact() on property", async () => {
const program = await typeSpecCompile(
`
model Book {
@clientName(Azure.ClientGenerator.Core.exact("snake_case_name"), "csharp")
name: string;
}

op test(@body input: Book): Book;
`,
runner,
{ IsTCGCNeeded: true },
);
const context = createEmitterContext(program);
const sdkContext = await createCSharpSdkContext(context);
const [root] = createModel(sdkContext);
const bookModel = root.models.find((m) => m.name === "Book");
ok(bookModel);
const nameProp = bookModel.properties.find((p) => p.name === "snake_case_name");
ok(nameProp);
strictEqual(nameProp.isExactName, true);
});

it("propagates isExactName from @clientName decorator with exact() on model", async () => {
const program = await typeSpecCompile(
`
@clientName(Azure.ClientGenerator.Core.exact("my_exact_model"), "csharp")
model Book {
name: string;
}

op test(@body input: Book): Book;
`,
runner,
{ IsTCGCNeeded: true },
);
const context = createEmitterContext(program);
const sdkContext = await createCSharpSdkContext(context);
const [root] = createModel(sdkContext);
const bookModel = root.models.find((m) => m.name === "my_exact_model");
ok(bookModel);
strictEqual(bookModel.isExactName, true);
});

it("does not set isExactName when @clientName decorator does not use exact()", async () => {
const program = await typeSpecCompile(
`
model Book {
@clientName("regularName")
name: string;
}

op test(@body input: Book): Book;
`,
runner,
{ IsTCGCNeeded: true },
);
const context = createEmitterContext(program);
const sdkContext = await createCSharpSdkContext(context);
const [root] = createModel(sdkContext);
const bookModel = root.models.find((m) => m.name === "Book");
ok(bookModel);
const nameProp = bookModel.properties.find((p) => p.name === "regularName");
ok(nameProp);
strictEqual(nameProp.isExactName, false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,9 @@ protected InputProperty(string name, string? summary, string? doc, InputType typ
public InputModelType? EnclosingType { get; internal set; }
public bool IsApiVersion { get; internal set; }
public InputConstant? DefaultValue { get; internal set; }
/// <summary>
/// Whether the name should be used exactly as-is, without casing transformations.
/// </summary>
public bool IsExactName { get; internal set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ protected InputType(string name)
public string Name { get; internal set; }
public IReadOnlyList<InputDecoratorInfo> Decorators { get; internal set; } = new List<InputDecoratorInfo>();
public InputExternalTypeMetadata? External { get; internal set; }
/// <summary>
/// Whether the name should be used exactly as-is, without casing transformations.
/// </summary>
public bool IsExactName { get; internal set; }

internal InputType GetCollectionEquivalent(InputType inputType)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ internal static InputBodyParameter ReadInputBodyParameter(ref Utf8JsonReader rea
string? defaultContentType = null;
IReadOnlyList<InputDecoratorInfo>? decorators = null;
IReadOnlyList<InputMethodParameter>? methodParameterSegments = null;
bool isExactName = false;

while (reader.TokenType != JsonTokenType.EndObject)
{
Expand All @@ -81,7 +82,8 @@ internal static InputBodyParameter ReadInputBodyParameter(ref Utf8JsonReader rea
|| reader.TryReadComplexType("contentTypes",options, ref contentTypes)
|| reader.TryReadComplexType("defaultContentType", options, ref defaultContentType)
|| reader.TryReadComplexType("decorators", options, ref decorators)
|| reader.TryReadComplexType("methodParameterSegments", options, ref methodParameterSegments);
|| reader.TryReadComplexType("methodParameterSegments", options, ref methodParameterSegments)
|| reader.TryReadBoolean("isExactName", ref isExactName);

if (!isKnownProperty)
{
Expand All @@ -104,6 +106,7 @@ internal static InputBodyParameter ReadInputBodyParameter(ref Utf8JsonReader rea
parameter.ContentTypes = contentTypes ?? throw new JsonException($"{nameof(InputBodyParameter)} must have a contentTypes.");
parameter.DefaultContentType = defaultContentType ?? throw new JsonException($"{nameof(InputBodyParameter)} must have a defaultContentType.");
parameter.MethodParameterSegments = methodParameterSegments;
parameter.IsExactName = isExactName;

return parameter;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ internal static InputEndpointParameter ReadInputEndpointParameter(ref Utf8JsonRe
bool isEndpoint = false;
IReadOnlyList<InputDecoratorInfo>? decorators = null;
IReadOnlyList<InputMethodParameter>? methodParameterSegments = null;
bool isExactName = false;

while (reader.TokenType != JsonTokenType.EndObject)
{
Expand All @@ -84,7 +85,8 @@ internal static InputEndpointParameter ReadInputEndpointParameter(ref Utf8JsonRe
|| reader.TryReadBoolean("skipUrlEncoding", ref skipUrlEncoding)
|| reader.TryReadBoolean("isEndpoint", ref isEndpoint)
|| reader.TryReadComplexType("decorators", options, ref decorators)
|| reader.TryReadComplexType("methodParameterSegments", options, ref methodParameterSegments);
|| reader.TryReadComplexType("methodParameterSegments", options, ref methodParameterSegments)
|| reader.TryReadBoolean("isExactName", ref isExactName);

if (!isKnownProperty)
{
Expand All @@ -108,6 +110,7 @@ internal static InputEndpointParameter ReadInputEndpointParameter(ref Utf8JsonRe
parameter.Scope = InputParameter.ParseScope(type, name, scope);
parameter.SkipUrlEncoding = skipUrlEncoding;
parameter.MethodParameterSegments = methodParameterSegments;
parameter.IsExactName = isExactName;

return parameter;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public static InputEnumType CreateEnumType(ref Utf8JsonReader reader, string? id
IReadOnlyList<InputEnumTypeValue>? values = null;
IReadOnlyList<InputDecoratorInfo>? decorators = null;
InputExternalTypeMetadata? external = null;
bool isExactName = false;
while (reader.TokenType != JsonTokenType.EndObject)
{
var isKnownProperty = reader.TryReadString("name", ref name)
Expand All @@ -75,7 +76,8 @@ public static InputEnumType CreateEnumType(ref Utf8JsonReader reader, string? id
|| reader.TryReadComplexType("valueType", options, ref valueType)
|| reader.TryReadComplexType("values", options, ref values)
|| reader.TryReadComplexType("decorators", options, ref decorators)
|| reader.TryReadComplexType("external", options, ref external);
|| reader.TryReadComplexType("external", options, ref external)
|| reader.TryReadBoolean("isExactName", ref isExactName);

if (!isKnownProperty)
{
Expand All @@ -100,6 +102,7 @@ public static InputEnumType CreateEnumType(ref Utf8JsonReader reader, string? id
enumType.IsExtensible = !isFixed;
enumType.Decorators = decorators ?? [];
enumType.External = external;
enumType.IsExactName = isExactName;

return enumType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ internal static InputHeaderParameter ReadInputHeaderParameter(ref Utf8JsonReader
string? collectionFormat = null;
IReadOnlyList<InputDecoratorInfo>? decorators = null;
IReadOnlyList<InputMethodParameter>? methodParameterSegments = null;
bool isExactName = false;

while (reader.TokenType != JsonTokenType.EndObject)
{
Expand All @@ -87,7 +88,8 @@ internal static InputHeaderParameter ReadInputHeaderParameter(ref Utf8JsonReader
|| reader.TryReadBoolean("isContentType", ref isContentType)
|| reader.TryReadString("collectionHeaderPrefix", ref collectionHeaderPrefix)
|| reader.TryReadComplexType("decorators", options, ref decorators)
|| reader.TryReadComplexType("methodParameterSegments", options, ref methodParameterSegments);
|| reader.TryReadComplexType("methodParameterSegments", options, ref methodParameterSegments)
|| reader.TryReadBoolean("isExactName", ref isExactName);

if (!isKnownProperty)
{
Expand All @@ -112,6 +114,7 @@ internal static InputHeaderParameter ReadInputHeaderParameter(ref Utf8JsonReader
parameter.IsContentType = isContentType;
parameter.CollectionHeaderPrefix = collectionHeaderPrefix;
parameter.MethodParameterSegments = methodParameterSegments;
parameter.IsExactName = isExactName;

return parameter;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static InputLiteralType CreateInputLiteralType(ref Utf8JsonReader reader,
JsonElement? rawValue = null;
InputPrimitiveType? valueType = null;
IReadOnlyList<InputDecoratorInfo>? decorators = null;
bool isExactName = false;

while (reader.TokenType != JsonTokenType.EndObject)
{
Expand All @@ -36,7 +37,8 @@ public static InputLiteralType CreateInputLiteralType(ref Utf8JsonReader reader,
|| reader.TryReadString("namespace", ref ns)
|| reader.TryReadComplexType("value", options, ref rawValue)
|| reader.TryReadComplexType("valueType", options, ref valueType)
|| reader.TryReadComplexType("decorators", options, ref decorators);
|| reader.TryReadComplexType("decorators", options, ref decorators)
|| reader.TryReadBoolean("isExactName", ref isExactName);

if (!isKnownProperty)
{
Expand Down Expand Up @@ -65,7 +67,8 @@ public static InputLiteralType CreateInputLiteralType(ref Utf8JsonReader reader,

var literalType = new InputLiteralType(name, ns, valueType, value)
{
Decorators = decorators ?? []
Decorators = decorators ?? [],
IsExactName = isExactName
};

if (id != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ internal static InputMethodParameter ReadInputMethodParameter(ref Utf8JsonReader
IReadOnlyList<InputDecoratorInfo>? decorators = null;
string? location = null;
string? paramAlias = null;
bool isExactName = false;

while (reader.TokenType != JsonTokenType.EndObject)
{
Expand All @@ -82,7 +83,8 @@ internal static InputMethodParameter ReadInputMethodParameter(ref Utf8JsonReader
|| reader.TryReadComplexType("defaultContentType", options, ref defaultContentType)
|| reader.TryReadString("location", ref location)
|| reader.TryReadComplexType("decorators", options, ref decorators)
|| reader.TryReadString("paramAlias", ref paramAlias);
|| reader.TryReadString("paramAlias", ref paramAlias)
|| reader.TryReadBoolean("isExactName", ref isExactName);

if (!isKnownProperty)
{
Expand All @@ -102,6 +104,7 @@ internal static InputMethodParameter ReadInputMethodParameter(ref Utf8JsonReader
parameter.IsApiVersion = isApiVersion;
parameter.DefaultValue = defaultValue;
parameter.Scope = InputParameter.ParseScope(type, name, scope);;
parameter.IsExactName = isExactName;

if (location == null)
{
Expand Down
Loading
Loading