Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
m-nash committed Aug 20, 2024
2 parents efc80e1 + 2d4f55f commit 68a4a8f
Show file tree
Hide file tree
Showing 30 changed files with 1,490 additions and 43 deletions.
41 changes: 23 additions & 18 deletions packages/http-client-csharp/eng/scripts/Generate.ps1
Original file line number Diff line number Diff line change
@@ -1,36 +1,39 @@
#Requires -Version 7.0
param(
$filter,
[bool]$Stubbed = $true
[bool]$Stubbed = $true,
[bool]$LaunchOnly = $false
)

Import-Module "$PSScriptRoot\Generation.psm1" -DisableNameChecking -Force;

$packageRoot = Resolve-Path (Join-Path $PSScriptRoot '..' '..')
$solutionDir = Join-Path $packageRoot 'generator'

Refresh-Build
if (-not $LaunchOnly) {
Refresh-Build

if ($null -eq $filter -or $filter -eq "Unbranded-TypeSpec") {
Write-Host "Generating UnbrandedTypeSpec" -ForegroundColor Cyan
$testProjectsLocalDir = Join-Path $packageRoot 'generator' 'TestProjects' 'Local'
if ($null -eq $filter -or $filter -eq "Unbranded-TypeSpec") {
Write-Host "Generating UnbrandedTypeSpec" -ForegroundColor Cyan
$testProjectsLocalDir = Join-Path $packageRoot 'generator' 'TestProjects' 'Local'

$unbrandedTypespecTestProject = Join-Path $testProjectsLocalDir "Unbranded-TypeSpec"
$unbrandedTypespecTestProject = $unbrandedTypespecTestProject
$unbrandedTypespecTestProject = Join-Path $testProjectsLocalDir "Unbranded-TypeSpec"
$unbrandedTypespecTestProject = $unbrandedTypespecTestProject

Invoke (Get-TspCommand "$unbrandedTypespecTestProject/Unbranded-TypeSpec.tsp" $unbrandedTypespecTestProject)
Invoke (Get-TspCommand "$unbrandedTypespecTestProject/Unbranded-TypeSpec.tsp" $unbrandedTypespecTestProject)

# exit if the generation failed
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
# exit if the generation failed
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}

Write-Host "Building UnbrandedTypeSpec" -ForegroundColor Cyan
Invoke "dotnet build $packageRoot/generator/TestProjects/Local/Unbranded-TypeSpec/src/UnbrandedTypeSpec.csproj"
Write-Host "Building UnbrandedTypeSpec" -ForegroundColor Cyan
Invoke "dotnet build $packageRoot/generator/TestProjects/Local/Unbranded-TypeSpec/src/UnbrandedTypeSpec.csproj"

# exit if the generation failed
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
# exit if the generation failed
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
}
}

Expand Down Expand Up @@ -59,7 +62,6 @@ $failingSpecs = @(
Join-Path 'http' 'parameters' 'spread'
Join-Path 'http' 'payload' 'content-negotiation'
Join-Path 'http' 'payload' 'json-merge-patch'
Join-Path 'http' 'payload' 'media-type'
Join-Path 'http' 'payload' 'multipart'
Join-Path 'http' 'payload' 'pageable'
Join-Path 'http' 'resiliency' 'srv-driven'
Expand Down Expand Up @@ -135,6 +137,9 @@ foreach ($directory in $directories) {
}

$cadlRanchLaunchProjects.Add(($folders -join "-"), ("TestProjects/CadlRanch/$($subPath.Replace([System.IO.Path]::DirectorySeparatorChar, '/'))"))
if ($LaunchOnly) {
continue
}
Write-Host "Generating $subPath" -ForegroundColor Cyan
Invoke (Get-TspCommand $specFile $generationDir $stubbed)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,15 @@ public static ParameterProvider ClientOptions(CSharpType clientOptionsType)
public static readonly ParameterProvider MatchConditionsParameter = new("matchConditions", $"The content to send as the request conditions of the request.", ClientModelPlugin.Instance.TypeFactory.MatchConditionsType(), DefaultOf(ClientModelPlugin.Instance.TypeFactory.MatchConditionsType()));
public static readonly ParameterProvider RequestOptions = new("options", $"The request options, which can override default behaviors of the client pipeline on a per-call basis.", typeof(RequestOptions));
public static readonly ParameterProvider BinaryContent = new("content", $"The content to send as the body of the request.", typeof(BinaryContent)) { Validation = ParameterValidationType.AssertNotNull };

// Known header parameters
public static readonly ParameterProvider RepeatabilityRequestId = new("repeatabilityRequestId", FormattableStringHelpers.Empty, typeof(Guid))
{
DefaultValue = Static(typeof(Guid)).Invoke(nameof(Guid.NewGuid)).Invoke(nameof(string.ToString))
};
public static readonly ParameterProvider RepeatabilityFirstSent = new("repeatabilityFirstSent", FormattableStringHelpers.Empty, typeof(DateTimeOffset))
{
DefaultValue = Static(typeof(DateTimeOffset)).Property(nameof(DateTimeOffset.Now))
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.ClientModel;
using System.Collections.Generic;
using System.IO;
using Microsoft.Generator.CSharp.ClientModel.Snippets;
using Microsoft.Generator.CSharp.Expressions;
using Microsoft.Generator.CSharp.Primitives;
using Microsoft.Generator.CSharp.Providers;
using Microsoft.Generator.CSharp.Snippets;
using Microsoft.Generator.CSharp.Statements;
using static Microsoft.Generator.CSharp.Snippets.Snippet;

namespace Microsoft.Generator.CSharp.ClientModel.Providers
{
internal class BinaryContentHelperDefinition : TypeProvider
{
private const string _fromEnumerableName = "FromEnumerable";
private const string _fromDictionaryName = "FromDictionary";
private const string _fromObjectName = "FromObject";

private readonly CSharpType _requestBodyType = typeof(BinaryContent);

private readonly MethodSignatureModifiers _methodModifiers = MethodSignatureModifiers.Public | MethodSignatureModifiers.Static;

protected override string BuildName() => "BinaryContentHelper";

protected override TypeSignatureModifiers GetDeclarationModifiers()
=> TypeSignatureModifiers.Internal | TypeSignatureModifiers.Static | TypeSignatureModifiers.Partial | TypeSignatureModifiers.Class;

protected override string BuildRelativeFilePath() => Path.Combine("src", "Generated", "Internal", $"{Name}.cs");

protected override MethodProvider[] BuildMethods()
{
return
[
BuildFromEnumerableTMethod(),
BuildFromEnumerableBinaryDataMethod(),
BuildFromReadOnlySpanMethod(),
BuildFromDictionaryTMethod(),
BuildFromDictionaryBinaryDataMethod(),
BuildFromObjectMethod(),
BuildFromBinaryDataMethod()
];
}

private MethodProvider BuildFromEnumerableTMethod()
{
var enumerableTType = typeof(IEnumerable<>);
CSharpType tType = enumerableTType.GetGenericArguments()[0];
var enumerableParameter = new ParameterProvider("enumerable", FormattableStringHelpers.Empty, enumerableTType);
var signature = new MethodSignature(
Name: _fromEnumerableName,
Modifiers: _methodModifiers,
Parameters: [enumerableParameter],
ReturnType: _requestBodyType,
GenericArguments: [tType],
GenericParameterConstraints: [Where.NotNull(tType)],
Description: null,
ReturnDescription: null);

var body = new List<MethodBodyStatement>
{
Declare("content", New.Instance<Utf8JsonBinaryContentDefinition>(), out var content)
};
var writer = content.JsonWriter();
body.AddRange(
[
writer.WriteStartArray(),
new ForeachStatement("item", enumerableParameter.As(enumerableParameter.Type), out var item)
{
writer.WriteObjectValue(item.As(tType), ModelSerializationExtensionsSnippets.Wire)
},
writer.WriteEndArray(),
MethodBodyStatement.EmptyLine,
Return(content)
]);

return new MethodProvider(signature, body, this);
}

private MethodProvider BuildFromEnumerableBinaryDataMethod()
{
var enumerableParameter = new ParameterProvider("enumerable", FormattableStringHelpers.Empty, typeof(IEnumerable<BinaryData>));
var signature = new MethodSignature(
Name: _fromEnumerableName,
Modifiers: _methodModifiers,
Parameters: [enumerableParameter],
ReturnType: _requestBodyType,
Description: null,
ReturnDescription: null);

var body = new List<MethodBodyStatement>
{
Declare("content", New.Instance<Utf8JsonBinaryContentDefinition>(), out var content)
};
var writer = content.JsonWriter();
body.AddRange(
[
writer.WriteStartArray(),
new ForeachStatement("item", enumerableParameter.As<IEnumerable<BinaryData>>(), out var item)
{
new IfElseStatement(
item.InvokeEquals(Null),
writer.WriteNullValue(),
writer.WriteBinaryData(item))
},
writer.WriteEndArray(),
MethodBodyStatement.EmptyLine,
Return(content)
]);

return new MethodProvider(signature, body, this);
}

private MethodProvider BuildFromReadOnlySpanMethod()
{
var spanType = typeof(ReadOnlySpan<>);
CSharpType tType = spanType.GetGenericArguments()[0];
var spanParameter = new ParameterProvider("span", FormattableStringHelpers.Empty, spanType);
var signature = new MethodSignature(
Name: _fromEnumerableName,
Modifiers: _methodModifiers,
Parameters: [spanParameter],
ReturnType: _requestBodyType,
GenericArguments: [tType],
GenericParameterConstraints: [Where.NotNull(tType)],
Description: null,
ReturnDescription: null);

var body = new List<MethodBodyStatement>
{
Declare("content", New.Instance<Utf8JsonBinaryContentDefinition>(), out var content)
};
var writer = content.JsonWriter();
body.AddRange(
[
writer.WriteStartArray(),
Declare<int>("i", Int(0), out var i),
new ForStatement(null, i.LessThan(spanParameter.Property(nameof(ReadOnlySpan<byte>.Length))), i.Increment())
{
writer.WriteObjectValue(new IndexerExpression(spanParameter, i).As(tType), ModelSerializationExtensionsSnippets.Wire)
},
writer.WriteEndArray(),
MethodBodyStatement.EmptyLine,
Return(content)
]);

return new MethodProvider(signature, body, this);
}

private MethodProvider BuildFromDictionaryTMethod()
{
var dictionaryTType = typeof(IDictionary<,>);
CSharpType valueType = dictionaryTType.GetGenericArguments()[1];
var dictionaryParameter = new ParameterProvider("dictionary", FormattableStringHelpers.Empty, new CSharpType(dictionaryTType, typeof(string), valueType));
var signature = new MethodSignature(
Name: _fromDictionaryName,
Modifiers: _methodModifiers,
Parameters: [dictionaryParameter],
ReturnType: _requestBodyType,
GenericArguments: [valueType],
GenericParameterConstraints: [Where.NotNull(valueType)],
Description: null,
ReturnDescription: null);

var body = new List<MethodBodyStatement>
{
Declare("content", New.Instance<Utf8JsonBinaryContentDefinition>(), out var content)
};
var writer = content.JsonWriter();
body.AddRange(
[
writer.WriteStartObject(),
new ForeachStatement("item", dictionaryParameter.As(dictionaryParameter.Type), out var item)
{
writer.WritePropertyName(item.Property("Key")),
writer.WriteObjectValue(item.Property("Value").As(valueType), ModelSerializationExtensionsSnippets.Wire)
},
writer.WriteEndObject(),
MethodBodyStatement.EmptyLine,
Return(content)
]);

return new MethodProvider(signature, body, this);
}

private MethodProvider BuildFromDictionaryBinaryDataMethod()
{
var dictionaryParameter = new ParameterProvider("dictionary", FormattableStringHelpers.Empty, typeof(IDictionary<string, BinaryData>));
var signature = new MethodSignature(
Name: _fromDictionaryName,
Modifiers: _methodModifiers,
Parameters: [dictionaryParameter],
ReturnType: _requestBodyType,
Description: null,
ReturnDescription: null);

var body = new List<MethodBodyStatement>
{
Declare("content", New.Instance<Utf8JsonBinaryContentDefinition>(), out var content)
};
var writer = content.JsonWriter();
body.AddRange(
[
writer.WriteStartObject(),
new ForeachStatement("item", dictionaryParameter.As(dictionaryParameter.Type), out var item)
{
writer.WritePropertyName(item.Property("Key")),
new IfElseStatement(
item.Property("Value").InvokeEquals(Null),
writer.WriteNullValue(),
writer.WriteBinaryData(item.Property("Value")))
},
writer.WriteEndObject(),
MethodBodyStatement.EmptyLine,
Return(content)
]);

return new MethodProvider(signature, body, this);
}

private MethodProvider BuildFromObjectMethod()
{
var valueParameter = new ParameterProvider("value", FormattableStringHelpers.Empty, typeof(object));
var signature = new MethodSignature(
Name: _fromObjectName,
Modifiers: _methodModifiers,
Parameters: [valueParameter],
ReturnType: _requestBodyType,
Description: null,
ReturnDescription: null);

MethodBodyStatement[] body =
[
Declare("content", New.Instance<Utf8JsonBinaryContentDefinition>(), out var content),
content.JsonWriter().WriteObjectValue(valueParameter.As<object>(), ModelSerializationExtensionsSnippets.Wire),
Return(content)
];

return new MethodProvider(signature, body, this);
}

private MethodProvider BuildFromBinaryDataMethod()
{
var valueParameter = new ParameterProvider("value", FormattableStringHelpers.Empty, typeof(BinaryData));
var signature = new MethodSignature(
Name: _fromObjectName,
Modifiers: _methodModifiers,
Parameters: [valueParameter],
ReturnType: _requestBodyType,
Description: null,
ReturnDescription: null);

var body = new List<MethodBodyStatement>
{
Declare("content", New.Instance<Utf8JsonBinaryContentDefinition>(), out var content)
};
var writer = content.JsonWriter();
body.AddRange(
[
writer.WriteBinaryData(valueParameter),
Return(content)
]);

return new MethodProvider(signature, body, this);
}
}
}
Loading

0 comments on commit 68a4a8f

Please sign in to comment.