Skip to content

Commit

Permalink
Merge branch 'main' into analyze-change-ts
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheeguerin authored Jul 26, 2024
2 parents cb949aa + 3aa2f5c commit 96c6ea4
Show file tree
Hide file tree
Showing 81 changed files with 5,920 additions and 572 deletions.
1 change: 1 addition & 0 deletions cspell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ ignorePaths:
- .github/CODEOWNERS
- packages/samples/test/output/**
- "**/BenchmarkDotNet.Artifacts/**"
- "**/tspCodeModel.json"
useGitignore: true
enableGlobDot: true
enableFiletypes:
Expand Down
1 change: 1 addition & 0 deletions eng/tsp-core/pipelines/pr-tools.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pr:
paths:
exclude:
- packages/http-client-csharp
- cspell.yaml

extends:
template: /eng/common/pipelines/templates/1es-redirect.yml
Expand Down
178 changes: 170 additions & 8 deletions packages/http-client-csharp/eng/scripts/Generate.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,178 @@

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

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

Invoke "npm run build:emitter"
# we don't want to build the entire solution because the test projects might not build until after regeneration
# generating Microsoft.Generator.CSharp.ClientModel.csproj is enough
Invoke "dotnet build $repoRoot/generator/Microsoft.Generator.CSharp.ClientModel/src"
Refresh-Build

$testProjectsLocalDir = Join-Path $repoRoot 'generator' 'TestProjects' 'Local'
Write-Host "Generating UnbrandedTypeSpec" -ForegroundColor Cyan
$testProjectsLocalDir = Join-Path $packageRoot 'generator' 'TestProjects' 'Local'

$unbrandedTypespecTestProject = Join-Path $testProjectsLocalDir "Unbranded-TypeSpec"
Invoke "npx tsp compile $unbrandedTypespecTestProject/Unbranded-TypeSpec.tsp --trace @typespec/http-client-csharp --emit @typespec/http-client-csharp --option @typespec/http-client-csharp.emitter-output-dir=$unbrandedTypespecTestProject --option @typespec/http-client-csharp.save-inputs=true"

Invoke "dotnet build $repoRoot/generator/TestProjects/Local/Unbranded-TypeSpec/src/UnbrandedTypeSpec.csproj"
Invoke (Get-TspCommand "$unbrandedTypespecTestProject/Unbranded-TypeSpec.tsp" $unbrandedTypespecTestProject)

# 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"

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

$specsDirectory = "$packageRoot/node_modules/@azure-tools/cadl-ranch-specs"
$cadlRanchRoot = Join-Path $packageRoot 'generator' 'TestProjects' 'CadlRanch'

function IsSpecDir {
param (
[string]$dir
)
$subdirs = Get-ChildItem -Path $dir -Directory
return -not ($subdirs) -and (Test-Path "$dir/main.tsp")
}

$failingSpecs = @(
Join-Path 'http' 'special-words'
Join-Path 'http' 'client' 'naming'
Join-Path 'http' 'client' 'structure' 'default'
Join-Path 'http' 'client' 'structure' 'multi-client'
Join-Path 'http' 'client' 'structure' 'renamed-operation'
Join-Path 'http' 'client' 'structure' 'two-operation-group'
Join-Path 'http' 'encode' 'bytes'
Join-Path 'http' 'encode' 'datetime'
Join-Path 'http' 'encode' 'duration'
Join-Path 'http' 'parameters' 'basic'
Join-Path 'http' 'parameters' 'body-optionality'
Join-Path 'http' 'parameters' 'collection-format'
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'
Join-Path 'http' 'serialization' 'encoded-name' 'json'
Join-Path 'http' 'server' 'endpoint' 'not-defined'
Join-Path 'http' 'server' 'path' 'multiple'
Join-Path 'http' 'server' 'path' 'single'
Join-Path 'http' 'server' 'versions' 'not-versioned'
Join-Path 'http' 'server' 'versions' 'versioned'
Join-Path 'http' 'special-headers' 'conditional-request'
Join-Path 'http' 'special-headers' 'repeatability'
Join-Path 'http' 'type' 'array'
Join-Path 'http' 'type' 'dictionary'
Join-Path 'http' 'type' 'scalar'
Join-Path 'http' 'type' 'union'
Join-Path 'http' 'type' 'enum' 'extensible'
Join-Path 'http' 'type' 'enum' 'fixed'
Join-Path 'http' 'type' 'model' 'empty'
Join-Path 'http' 'type' 'model' 'flatten'
Join-Path 'http' 'type' 'model' 'usage'
Join-Path 'http' 'type' 'model' 'visibility'
Join-Path 'http' 'type' 'model' 'inheritance' 'enum-discriminator'
Join-Path 'http' 'type' 'model' 'inheritance' 'nested-discriminator'
Join-Path 'http' 'type' 'model' 'inheritance' 'not-discriminated'
Join-Path 'http' 'type' 'model' 'inheritance' 'recursive'
Join-Path 'http' 'type' 'model' 'inheritance' 'single-discriminator'
Join-Path 'http' 'type' 'property' 'additional-properties'
Join-Path 'http' 'type' 'property' 'nullable'
Join-Path 'http' 'type' 'property' 'optionality'
Join-Path 'http' 'type' 'property' 'value-types'
)

$cadlRanchLaunchProjects = @{}

# Loop through all directories and subdirectories of the cadl ranch specs
$directories = Get-ChildItem -Path "$specsDirectory/http" -Directory -Recurse
foreach ($directory in $directories) {
if (-not (IsSpecDir $directory.FullName)) {
continue
}

$specFile = Join-Path $directory.FullName "main.tsp"
$subPath = $directory.FullName.Substring($specsDirectory.Length + 1)
$folders = $subPath.Split([System.IO.Path]::DirectorySeparatorChar)

if ($folders.Contains("azure")) {
continue
}

if ($folders.Contains("versioning")) {
continue # TODO: adopt versioning cadl ranch specs https://github.com/microsoft/typespec/issues/3965
}

if ($failingSpecs.Contains($subPath)) {
Write-Host "Skipping $subPath" -ForegroundColor Yellow
continue
}

$generationDir = $cadlRanchRoot
foreach ($folder in $folders) {
$generationDir = Join-Path $generationDir $folder
}

#create the directory if it doesn't exist
if (-not (Test-Path $generationDir)) {
New-Item -ItemType Directory -Path $generationDir | Out-Null
}

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

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

# TODO need to build but depends on https://github.com/Azure/autorest.csharp/issues/4463
}

Write-Host "Writing new launch settings" -ForegroundColor Cyan
$mgcExe = "`$(SolutionDir)/../dist/generator/Microsoft.Generator.CSharp.exe"
$sampleExe = "`$(SolutionDir)/../generator/artifacts/bin/SamplePlugin/Debug/net8.0/Microsoft.Generator.CSharp.exe"
$unbrandedSpec = "TestProjects/Local/Unbranded-TypeSpec"

$launchSettings = @{}
$launchSettings.Add("profiles", @{})
$launchSettings["profiles"].Add("Unbranded-TypeSpec", @{})
$launchSettings["profiles"]["Unbranded-TypeSpec"].Add("commandLineArgs", "`$(SolutionDir)/$unbrandedSpec -p ClientModelPlugin")
$launchSettings["profiles"]["Unbranded-TypeSpec"].Add("commandName", "Executable")
$launchSettings["profiles"]["Unbranded-TypeSpec"].Add("executablePath", $mgcExe)
$launchSettings["profiles"].Add("Debug-Plugin-Test-TypeSpec", @{})
$launchSettings["profiles"]["Debug-Plugin-Test-TypeSpec"].Add("commandLineArgs", "`$(SolutionDir)/$unbrandedSpec -p SampleCodeModelPlugin")
$launchSettings["profiles"]["Debug-Plugin-Test-TypeSpec"].Add("commandName", "Executable")
$launchSettings["profiles"]["Debug-Plugin-Test-TypeSpec"].Add("executablePath", $sampleExe)

foreach ($kvp in $cadlRanchLaunchProjects.GetEnumerator()) {
$launchSettings["profiles"].Add($kvp.Key, @{})
$launchSettings["profiles"][$kvp.Key].Add("commandLineArgs", "`$(SolutionDir)/$($kvp.Value) -p StubLibraryPlugin")
$launchSettings["profiles"][$kvp.Key].Add("commandName", "Executable")
$launchSettings["profiles"][$kvp.Key].Add("executablePath", $mgcExe)
}

$sortedLaunchSettings = @{}
$sortedLaunchSettings.Add("profiles", [ordered]@{})
$launchSettings["profiles"].Keys | Sort-Object | ForEach-Object {
$profileKey = $_
$originalProfile = $launchSettings["profiles"][$profileKey]

# Sort the keys inside each profile
# This is needed due to non deterministic ordering of json elements in powershell
$sortedProfile = [ordered]@{}
$originalProfile.GetEnumerator() | Sort-Object Key | ForEach-Object {
$sortedProfile[$_.Key] = $_.Value
}

$sortedLaunchSettings["profiles"][$profileKey] = $sortedProfile
}

# Write the launch settings to the launchSettings.json file
$launchSettingsPath = Join-Path $solutionDir "Microsoft.Generator.CSharp" "src" "Properties" "launchSettings.json"
$sortedLaunchSettings | ConvertTo-Json | Set-Content $launchSettingsPath
37 changes: 37 additions & 0 deletions packages/http-client-csharp/eng/scripts/Generation.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,41 @@ function Invoke($command, $executePath=$repoRoot)
Write-Error "Command failed to execute: $command"
}
}

function Get-TspCommand {
param (
[string]$specFile,
[string]$generationDir,
[bool]$generateStub = $false
)
$command = "npx tsp compile $specFile"
$command += " --trace @typespec/http-client-csharp"
$command += " --emit @typespec/http-client-csharp"
$command += " --option @typespec/http-client-csharp.emitter-output-dir=$generationDir"
$command += " --option @typespec/http-client-csharp.save-inputs=true"
if ($generateStub) {
$command += " --option @typespec/http-client-csharp.plugin-name=StubLibraryPlugin"
}
return $command
}

function Refresh-Build {
Write-Host "Building emitter and generator" -ForegroundColor Cyan
Invoke "npm run build:emitter"
# exit if the generation failed
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}

# we don't want to build the entire solution because the test projects might not build until after regeneration
# generating Microsoft.Generator.CSharp.ClientModel.csproj is enough
Invoke "dotnet build $repoRoot/../generator/Microsoft.Generator.CSharp.ClientModel.StubLibrary/src"
# exit if the generation failed
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
}

Export-ModuleMember -Function "Invoke"
Export-ModuleMember -Function "Get-TspCommand"
Export-ModuleMember -Function "Refresh-Build"
104 changes: 104 additions & 0 deletions packages/http-client-csharp/eng/scripts/Test-CadlRanch.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# cspell:ignore cadlranch

#Requires -Version 7.0

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

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

Refresh-Build

$specsDirectory = "$packageRoot/node_modules/@azure-tools/cadl-ranch-specs"
$cadlRanchRoot = Join-Path $packageRoot 'generator' 'TestProjects' 'CadlRanch'
$directories = Get-ChildItem -Path "$cadlRanchRoot" -Directory -Recurse
$cadlRanchCsproj = Join-Path $packageRoot 'generator' 'TestProjects' 'CadlRanch.Tests' 'TestProjects.CadlRanch.Tests.csproj'
$runSettings = Join-Path $packageRoot 'eng' 'test-configurations' 'cadlranch.runsettings'

function IsGenerated {
param (
[string]$dir
)

if (-not ($dir.EndsWith("Generated"))) {
return $false
}

$csFiles = Get-ChildItem -Path $directory -Filter *.cs -File
return $csFiles.Count -gt 0
}

function Capitalize-FirstLetter {
param (
[string]$inputString
)

if ([string]::IsNullOrEmpty($inputString)) {
return $inputString
}

$firstChar = $inputString[0].ToString().ToUpper()
$restOfString = $inputString.Substring(1)

return $firstChar + $restOfString
}

function Get-Namespace {
param (
[string]$dir
)

$words = $dir.Split('-')
$namespace = ""
foreach ($word in $words) {
$namespace += Capitalize-FirstLetter $word
}
return $namespace
}

foreach ($directory in $directories) {
if (-not (IsGenerated $directory.FullName)) {
continue
}

$outputDir = $directory.FullName.Substring(0, $directory.FullName.IndexOf("src") - 1)
$subPath = $outputDir.Substring($cadlRanchRoot.Length + 1)
$folders = $subPath.Split([System.IO.Path]::DirectorySeparatorChar)

$testFilter = "TestProjects.CadlRanch.Tests"
foreach ($folder in $folders) {
$testFilter += ".$(Get-Namespace $folder)"
}

Write-Host "Regenerating $subPath" -ForegroundColor Cyan

$specFile = Join-Path $specsDirectory $subPath "main.tsp"

$command = Get-TspCommand $specFile $outputDir
Invoke $command
# exit if the generation failed
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}

Write-Host "Testing $subPath" -ForegroundColor Cyan
$command = "dotnet test $cadlRanchCsproj --filter `"FullyQualifiedName~$testFilter`" --settings $runSettings"
Invoke $command
# exit if the generation failed
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}

Write-Host "Restoring $subPath" -ForegroundColor Cyan
$command = "git clean -xfd $outputDir"
Invoke $command
# exit if the generation failed
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
$command = "git restore $outputDir"
Invoke $command
# exit if the generation failed
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
}
4 changes: 3 additions & 1 deletion packages/http-client-csharp/eng/scripts/Test-Packages.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ try {
try {
# test the emitter
Invoke-LoggedCommand "npm run build" -GroupOutput
Invoke-LoggedCommand "npm run test" -GroupOutput
Invoke-LoggedCommand "npm run test:emitter" -GroupOutput

# test the generator
Invoke-LoggedCommand "dotnet test ./generator" -GroupOutput

Invoke-LoggedCommand "./eng/scripts/Test-CadlRanch.ps1" -GroupOutput
}
finally {
Pop-Location
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<RunSettings>
<TestRunParameters>
<Parameter name="RunCadlRanch" value="true" />
</TestRunParameters>
</RunSettings>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<PackageId>StubPlugin</PackageId>
<Version>1.0.0-beta.1</Version>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.ClientModel" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Microsoft.Generator.CSharp.ClientModel\src\Microsoft.Generator.CSharp.ClientModel.csproj" />
</ItemGroup>

<!-- Copy output to package dist path for local execution and -->
<Target Name="CopyForNpmPackage" AfterTargets="Build">
<Message Text="Copying output to dist path" Importance="high" />
<ItemGroup>
<SourceDir Include="$(OutputPath)**\*Stub*.*" />
</ItemGroup>
<Copy SourceFiles="@(SourceDir)" DestinationFolder="$(MSBuildThisFileDirectory)..\..\..\dist\generator\%(RecursiveDir)" />
</Target>

</Project>
Loading

0 comments on commit 96c6ea4

Please sign in to comment.