Skip to content

Commit 5ca1176

Browse files
authored
Merge pull request #342 from microsoftgraph/po/0.9.1BugFixes
0.9.1 bug fixes
2 parents 10f8d30 + 157e204 commit 5ca1176

File tree

7 files changed

+129
-20
lines changed

7 files changed

+129
-20
lines changed

src/Financials/Financials/readme.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,32 @@ title: $(service-name)
3232
subject-prefix: ''
3333

3434
```
35+
36+
### Directives
37+
38+
> see https://github.com/Azure/autorest/blob/master/docs/powershell/directives.md
39+
40+
``` yaml
41+
directive:
42+
# Modify generated .dictionary.cs model classes in Financials module.
43+
- from: source-file-csharp
44+
where: $
45+
transform: >
46+
if (!$documentPath.match(/generated%5Capi%5CModels%5CMicrosoftGraph\w*\d*.dictionary.cs/gm))
47+
{
48+
return $;
49+
} else {
50+
// Rename additionalProperties indexer name in Financials module from Item to EntityItem to avoid property name conflict. salesOrderLine has a property named item.
51+
// See https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/indexers/using-indexers
52+
let indexerRegex = /(^\s*)(public\s*global::System.Object this\[global::System.String index\]\s*{\W.*}$)/gm
53+
$ = $.replace(indexerRegex, '$1[System.Runtime.CompilerServices.IndexerName("EntityItem")]\n$1$2');
54+
return $;
55+
}
56+
```
57+
3558
### Versioning
3659
3760
``` yaml
38-
module-version: 0.9.0
61+
module-version: 0.9.2
3962
release-notes: See https://aka.ms/GraphPowerShell-Release.
4063
```

src/Identity.Organization/Identity.Organization/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@ directive:
4444
### Versioning
4545
4646
``` yaml
47-
module-version: 0.9.0
47+
module-version: 0.9.2
4848
release-notes: See https://aka.ms/GraphPowerShell-Release.
4949
```

src/Teams.Team/Teams.Team/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,6 @@ directive:
4545
### Versioning
4646
4747
``` yaml
48-
module-version: 0.9.0
48+
module-version: 0.9.2
4949
release-notes: See https://aka.ms/GraphPowerShell-Release.
5050
```

src/readme.graph.md

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,20 +361,26 @@ directive:
361361
subject: (Application|ServicePrincipal)SynchronizationJobCredentials
362362
variant: Validate1|ValidateExpanded1|ValidateViaIdentity1|ValidateViaIdentityExpanded1
363363
remove: true
364-
# Add AfterToJson
364+
# Modify generated .json.cs model classes.
365365
- from: source-file-csharp
366366
where: $
367367
transform: >
368368
if (!$documentPath.match(/generated%5Capi%5CModels%5CMicrosoftGraph\w*\d*.json.cs/gm))
369369
{
370370
return $;
371371
} else {
372+
// Add AfterToJson
372373
let afterJsonDeclarationRegex = /(^\s*)(partial\s*void\s*AfterFromJson\s*\(Microsoft.Graph.PowerShell.Runtime.Json.JsonObject\s*json\s*\);$)/gm
373374
$ = $.replace(afterJsonDeclarationRegex, '$1$2\n$1partial void AfterToJson(ref Microsoft.Graph.PowerShell.Runtime.Json.JsonObject container, Microsoft.Graph.PowerShell.Runtime.SerializationMode serializationMode);\n');
374375
let afterJsonRegex = /(^\s*)(AfterToJson\(ref\s*container\s*\);$)/gm
375376
$ = $.replace(afterJsonRegex, '$1$2\n$1AfterToJson(ref container, serializationMode);\n');
377+
378+
// Pass exclusion properties to base classes during serialization.
379+
let baseClassInitializerRegex = /(new\s*Microsoft.Graph.PowerShell.Models.MicrosoftGraph\w*\(\s*json\s*,\s*new\s*global::System.Collections.Generic.HashSet<string>\()(\){\W.*}\);)/gm
380+
$ = $.replace(baseClassInitializerRegex, '$1(exclusions ?? new System.Collections.Generic.HashSet<string>())$2');
376381
return $;
377382
}
383+
# Modify generated .cs model classes.
378384
- from: source-file-csharp
379385
where: $
380386
transform: >
@@ -388,6 +394,24 @@ directive:
388394
$ = $.replace(valuesPropertiesRegex, '$1$2 new $3');
389395
}
390396
397+
// Add new modifier to 'additionalProperties' properties of classes that derive from an IAssociativeArray. See example https://regex101.com/r/hnX7xO/2.
398+
let additionalPropertiesRegex = /(SerializedName\s*=\s*@"additionalProperties".*\s*.*)(\s*)(.*AdditionalProperties\s*{\s*get;\s*set;\s*})/gmi
399+
if($.match(additionalPropertiesRegex)) {
400+
$ = $.replace(additionalPropertiesRegex, '$1$2 new $3');
401+
}
402+
403+
// Add new modifier to 'keys' properties of classes that derive from an IAssociativeArray. See example https://regex101.com/r/hnX7xO/2.
404+
let keysRegex = /(SerializedName\s*=\s*@"keys".*\s*.*)(\s*)(.*Keys\s*{\s*get;\s*set;\s*})/gmi
405+
if($.match(keysRegex)) {
406+
$ = $.replace(keysRegex, '$1$2 new $3');
407+
}
408+
409+
// Add new modifier to 'count' properties of classes that derive from an IAssociativeArray. See example https://regex101.com/r/hnX7xO/2.
410+
let countRegex = /(SerializedName\s*=\s*@"count".*\s*.*)(\s*)(.*Count\s*{\s*get;\s*set;\s*})/gmi
411+
if($.match(countRegex)) {
412+
$ = $.replace(countRegex, '$1$2 new $3');
413+
}
414+
391415
let regexPattern = /^\s*public\s*partial\s*class\s*MicrosoftGraph(?<EntityName>.*):$/gm;
392416
let regexArray;
393417
while ((regexArray = regexPattern.exec($)) !== null) {
@@ -404,29 +428,36 @@ directive:
404428
}
405429
return $;
406430
}
407-
# Override OnDefault to handle all success, 2xx responses, as success and not error.
431+
# Modify generated .cs cmdlets.
408432
- from: source-file-csharp
409433
where: $
410434
transform: >
411435
if (!$documentPath.match(/generated%2Fcmdlets%2F\w*\d*.cs/gm))
412436
{
413437
return $;
414438
} else {
439+
// Initialize AdditionalProperties prop to a new Hashtable by default.
440+
let additionalPropertiesPropRegex = /System.Collections.Hashtable\s*AdditionalProperties\s*{\s*get;\s*set;\s*}$/gmi
441+
let newAdditionalPropertiesProp = "System.Collections.Hashtable AdditionalProperties { get; set; } = new System.Collections.Hashtable();"
442+
$ = $.replace(additionalPropertiesPropRegex, newAdditionalPropertiesProp);
443+
444+
// Override OnDefault to handle all success, 2xx responses, as success and not error.
415445
let overrideOnDefaultRegex = /(\s*)(partial\s*void\s*overrideOnDefault)/gmi
416446
let overrideOnDefaultImplementation = "$1partial void overrideOnDefault(global::System.Net.Http.HttpResponseMessage responseMessage, global::System.Threading.Tasks.Task<Microsoft.Graph.PowerShell.Models.IOdataError> response, ref global::System.Threading.Tasks.Task<bool> returnNow) => this.OverrideOnDefault(responseMessage,ref returnNow);$1$2"
417447
$ = $.replace(overrideOnDefaultRegex, overrideOnDefaultImplementation);
418448
419449
return $;
420450
}
421451
422-
# Add custom -PageSize parameter to *_List cmdlets that support Odata next link.
452+
# Modify generated .cs list cmdlets.
423453
- from: source-file-csharp
424454
where: $
425455
transform: >
426456
if (!$documentPath.match(/generated%2Fcmdlets%2FGet\w*_List\d*.cs/gm))
427457
{
428458
return $;
429459
} else {
460+
// Add custom -PageSize parameter to *_List cmdlets that support Odata next link.
430461
let odataNextLinkRegex = /(^\s*)(if\s*\(\s*result.OdataNextLink\s*!=\s*null\s*\))/gmi
431462
if($.match(odataNextLinkRegex)) {
432463
$ = $.replace(odataNextLinkRegex, '$1if (result.OdataNextLink != null && this.ShouldIteratePages(this.InvocationInformation.BoundParameters, result.Value.Length))\n$1');
@@ -442,4 +473,21 @@ directive:
442473
}
443474
return $;
444475
}
476+
477+
# Modify generated runtime TypeConverterExtensions class.
478+
- from: source-file-csharp
479+
where: $
480+
transform: >
481+
if (!$documentPath.match(/generated%5Cruntime%5CTypeConverterExtensions.cs/gm))
482+
{
483+
return $;
484+
} else {
485+
// Use a case-insensitive contains search.
486+
let keyValueContainsRegex = /(exclusions|inclusions)(\?.Contains\(key\?.ToString\(\))(\)\))/gm
487+
$ = $.replace(keyValueContainsRegex, '$1$2, System.StringComparer.OrdinalIgnoreCase$3');
488+
489+
let propertyContainsRegex = /(exclusions|inclusions)(\?.Contains\(property.Name)(\)\))/gm
490+
$ = $.replace(propertyContainsRegex, '$1$2, System.StringComparer.OrdinalIgnoreCase$3');
491+
return $;
492+
}
445493
```

tools/Custom/ListCmdlet.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,12 @@ public void InitializePaging(ref global::System.Management.Automation.Invocation
9898
{
9999
currentPageSize = limit;
100100
}
101-
// Explicitly set `-Top` parameter to currentPageSize in order for the generated cmdlets to construct a URL with a `$top` query parameter.
102-
invocationInfo.BoundParameters["Top"] = currentPageSize;
103-
top = currentPageSize;
101+
102+
if (invocationInfo.BoundParameters.ContainsKey("PageSize") || invocationInfo.BoundParameters.ContainsKey("Top") || invocationInfo.BoundParameters.ContainsKey("All")){
103+
// Explicitly set `-Top` parameter to currentPageSize in order for the generated cmdlets to construct a URL with a `$top` query parameter.
104+
invocationInfo.BoundParameters["Top"] = currentPageSize;
105+
top = currentPageSize;
106+
}
104107

105108
if (limit != default)
106109
{

tools/Custom/Module.cs

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,25 @@ partial void CustomInit()
5656
/// </returns>
5757
public async Task EventHandler(string id, CancellationToken cancellationToken, Func<EventArgs> getEventData, Func<string, CancellationToken, Func<EventArgs>, Task> signal, InvocationInfo invocationInfo, string parameterSetName, System.Exception exception)
5858
{
59-
switch (id)
59+
if (invocationInfo.BoundParameters.ContainsKey("Debug"))
6060
{
61-
case Events.Finally:
62-
await Finally(id, cancellationToken, getEventData, signal);
63-
break;
64-
default:
65-
getEventData.Print(signal, cancellationToken, Events.Information, id);
66-
break;
61+
switch (id)
62+
{
63+
case Events.BeforeCall:
64+
await BeforeCall(id, cancellationToken, getEventData, signal);
65+
break;
66+
case Events.Finally:
67+
await Finally(id, cancellationToken, getEventData, signal);
68+
break;
69+
default:
70+
getEventData.Print(signal, cancellationToken, Events.Information, id);
71+
break;
72+
}
6773
}
6874
}
6975

7076
/// <summary>
71-
/// Handles the Finally event, which is called just before Request and Response are disposed.
77+
/// Handles the Finally event, which is called just after a response is received.
7278
/// </summary>
7379
/// <param name="id">The ID of the event</param>
7480
/// <param name="cancellationToken">The cancellation token for the event</param>
@@ -82,15 +88,35 @@ private async Task Finally(string id, CancellationToken cancellationToken, Func<
8288
using (Extensions.NoSynchronizationContext)
8389
{
8490
var eventData = EventDataConverter.ConvertFrom(getEventData());
85-
using (var requestFormatter = new HttpMessageFormatter(eventData.RequestMessage as HttpRequestMessage))
8691
using (var responseFormatter = new HttpMessageFormatter(eventData.ResponseMessage as HttpResponseMessage))
8792
{
88-
var requestString = await requestFormatter.ReadAsStringAsync();
8993
var responseString = await responseFormatter.ReadAsStringAsync();
90-
await signal(Events.Debug, cancellationToken, () => EventFactory.CreateLogEvent(requestString));
9194
await signal(Events.Debug, cancellationToken, () => EventFactory.CreateLogEvent(responseString));
9295
}
9396
}
9497
}
98+
99+
/// <summary>
100+
/// Handles the BeforeCall event, which is called just before Request is sent.
101+
/// </summary>
102+
/// <param name="id">The ID of the event</param>
103+
/// <param name="cancellationToken">The cancellation token for the event</param>
104+
/// <param name="getEventData">A delegate to get the detailed event data</param>
105+
/// <param name="signal">The callback for the event dispatcher</param>
106+
/// <returns>
107+
/// A <see cref="global::System.Threading.Tasks.Task" /> that will be complete when handling of the event is completed.
108+
/// </returns>
109+
private async Task BeforeCall(string id, CancellationToken cancellationToken, Func<EventArgs> getEventData, Func<string, CancellationToken, Func<EventArgs>, Task> signal)
110+
{
111+
using (Extensions.NoSynchronizationContext)
112+
{
113+
var eventData = EventDataConverter.ConvertFrom(getEventData());
114+
using (var requestFormatter = new HttpMessageFormatter(eventData.RequestMessage as HttpRequestMessage))
115+
{
116+
var requestString = await requestFormatter.ReadAsStringAsync();
117+
await signal(Events.Debug, cancellationToken, () => EventFactory.CreateLogEvent(requestString));
118+
}
119+
}
120+
}
95121
}
96122
}

tools/GenerateModules.ps1

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ $ModuleMapping.Keys | ForEach-Object -Begin { $RequestCount = 0 } -End { Write-H
136136
}
137137
} | Set-Content $ModulePsm1
138138

139+
# Address AutoREST bug where it looks for exports in the wrong directory.
140+
$InternalModulePsm1 = Join-Path $ModuleProjectDir "/internal/$ModulePrefix.$ModuleName.internal.psm1"
141+
(Get-Content -Path $InternalModulePsm1) | ForEach-Object{
142+
$_
143+
if ($_ -match '\$exportsPath = \$PSScriptRoot') {
144+
' $exportsPath = Join-Path $PSScriptRoot "../exports"'
145+
}
146+
} | Set-Content $InternalModulePsm1
147+
139148
if ($LASTEXITCODE) {
140149
Write-Error "Failed to build '$ModuleName' module."
141150
}

0 commit comments

Comments
 (0)