Skip to content

Commit 1483450

Browse files
authored
Merge pull request #142 from microsoft/bugfix/main-graph-gen-tests
bugfix/main graph gen tests
2 parents 1a59893 + f6f7832 commit 1483450

32 files changed

+665
-442
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.0.4] - 2021-04-28
11+
12+
### Changed
13+
14+
- Multiple performance improvements for large descriptions
15+
- Deterministic ordering of properties/methods/indexers/subclasses
16+
- Deterministic import of sub path request builders
17+
- Stopped generating phantom indexer methods for TypeScript and Java
18+
1019
## [0.0.3] - 2021-04-25
1120

1221
### Added

abstractions/dotnet/src/RequestInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ public class RequestInfo
99
{
1010
public Uri URI { get; set; }
1111
public HttpMethod HttpMethod { get; set; }
12-
public IDictionary<string, object> QueryParameters { get; set; } = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
13-
public IDictionary<string, string> Headers { get; set; } = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
12+
public IDictionary<string, object> QueryParameters { get; set; } = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
13+
public IDictionary<string, string> Headers { get; set; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
1414
public Stream Content { get; set; }
1515
private const string jsonContentType = "application/json";
1616
private const string binaryContentType = "application/octet-stream";

core/dotnet/src/HttpCore.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ private HttpRequestMessage GetRequestMessageFromRequestInfo(RequestInfo requestI
131131

132132
};
133133
if(requestInfo.Headers?.Any() ?? false)
134-
requestInfo.Headers.Where(x => !contentTypeHeaderName.Equals(x.Key, StringComparison.InvariantCultureIgnoreCase)).ToList().ForEach(x => message.Headers.Add(x.Key, x.Value));
134+
requestInfo.Headers.Where(x => !contentTypeHeaderName.Equals(x.Key, StringComparison.OrdinalIgnoreCase)).ToList().ForEach(x => message.Headers.Add(x.Key, x.Value));
135135
if(requestInfo.Content != null) {
136136
message.Content = new StreamContent(requestInfo.Content);
137137
if(requestInfo?.Headers?.ContainsKey(contentTypeHeaderName) ?? false)

core/dotnet/src/serialization/JsonParseNodeFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public IParseNode GetRootParseNode(string contentType, Stream content)
1111
{
1212
if(string.IsNullOrEmpty(contentType))
1313
throw new ArgumentNullException(nameof(contentType));
14-
else if(!validContentType.Equals(contentType, StringComparison.InvariantCultureIgnoreCase))
14+
else if(!validContentType.Equals(contentType, StringComparison.OrdinalIgnoreCase))
1515
throw new ArgumentOutOfRangeException($"expected a {validContentType} content type");
1616

1717
_ = content ?? throw new ArgumentNullException(nameof(content));

core/dotnet/src/serialization/JsonSerializationWriterFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public class JsonSerializationWriterFactory : ISerializationWriterFactory {
77
public ISerializationWriter GetSerializationWriter(string contentType) {
88
if(string.IsNullOrEmpty(contentType))
99
throw new ArgumentNullException(nameof(contentType));
10-
else if(!validContentType.Equals(contentType, StringComparison.InvariantCultureIgnoreCase))
10+
else if(!validContentType.Equals(contentType, StringComparison.OrdinalIgnoreCase))
1111
throw new ArgumentOutOfRangeException($"expected a {validContentType} content type");
1212

1313
return new JsonSerializationWriter();

docs/kiotaabstractions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public class RequestInfo
2323
{
2424
public Uri URI { get; set; }
2525
public HttpMethod HttpMethod { get; set; }
26-
public IDictionary<string, object> QueryParameters { get; set; } = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
27-
public IDictionary<string, string> Headers { get; set; } = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
26+
public IDictionary<string, object> QueryParameters { get; set; } = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
27+
public IDictionary<string, string> Headers { get; set; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
2828
public Stream Content { get; set; }
2929
}
3030
```

samples

Submodule samples updated 221 files

src/Kiota.Builder/CodeDOM/CodeBlock.cs

Lines changed: 80 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
4+
using System.Diagnostics;
35
using System.Linq;
46

57
namespace Kiota.Builder
@@ -11,20 +13,27 @@ namespace Kiota.Builder
1113
public class CodeBlock : CodeElement
1214
{
1315
public BlockDeclaration StartBlock {get; set;}
14-
public List<CodeElement> InnerChildElements {get; set;} = new List<CodeElement>();
16+
protected IDictionary<string, CodeElement> InnerChildElements {get; private set;} = new ConcurrentDictionary<string, CodeElement>(StringComparer.OrdinalIgnoreCase);
1517
public BlockEnd EndBlock {get; set;}
1618
public CodeBlock(CodeElement parent):base(parent)
1719
{
1820
StartBlock = new BlockDeclaration(this);
1921
EndBlock = new BlockEnd(this);
2022
}
2123

22-
public override IList<CodeElement> GetChildElements()
24+
public override IEnumerable<CodeElement> GetChildElements(bool innerOnly = false)
2325
{
24-
var elements = new List<CodeElement>(InnerChildElements);
25-
elements.Insert(0, StartBlock);
26-
elements.Add(EndBlock);
27-
return elements;
26+
if(innerOnly)
27+
return InnerChildElements.Values;
28+
else
29+
return new CodeElement[] { StartBlock, EndBlock }.Union(InnerChildElements.Values);
30+
}
31+
public void RemoveChildElement<T>(params T[] elements) where T: CodeElement {
32+
if(elements == null) return;
33+
34+
foreach(var element in elements) {
35+
InnerChildElements.Remove(element.Name);
36+
}
2837
}
2938
public void AddUsing(params CodeUsing[] codeUsings)
3039
{
@@ -33,24 +42,72 @@ public void AddUsing(params CodeUsing[] codeUsings)
3342
AddMissingParent(codeUsings);
3443
StartBlock.Usings.AddRange(codeUsings);
3544
}
36-
public T GetChildElementOfType<T>(Func<T,bool> predicate) where T : CodeElement {
37-
if(predicate == null)
38-
throw new ArgumentNullException(nameof(predicate));
39-
else if(this is T thisT && predicate(thisT))
40-
return thisT;
41-
else if(this is CodeBlock currentBlock) {
42-
if (currentBlock.InnerChildElements.OfType<T>().Any(predicate))
43-
return currentBlock.InnerChildElements.OfType<T>().First(predicate);
44-
else if(currentBlock.InnerChildElements.OfType<CodeBlock>().Any())
45-
return currentBlock.InnerChildElements.OfType<CodeBlock>()
46-
.Select(x => x.GetChildElementOfType<T>(predicate))
47-
.OfType<T>()
48-
.FirstOrDefault();
49-
else
50-
return null;
45+
protected IEnumerable<T> AddRange<T>(params T[] elements) where T : CodeElement {
46+
if(elements == null) return Enumerable.Empty<T>();
47+
AddMissingParent(elements);
48+
var innerChildElements = InnerChildElements as ConcurrentDictionary<string, CodeElement>; // to avoid calling the non thread-safe extension method
49+
var result = new T[elements.Length]; // not using yield return as they'll only get called if the result is assigned
50+
51+
for(var i = 0; i < elements.Length; i++) {
52+
var element = elements[i];
53+
var returnedValue = innerChildElements.GetOrAdd(element.Name, element);
54+
result[i] = (T)HandleDuplicatedExceptions(innerChildElements, element, returnedValue);
5155
}
52-
else
53-
return null;
56+
return result;
57+
}
58+
private static CodeElement HandleDuplicatedExceptions(ConcurrentDictionary<string, CodeElement> innerChildElements, CodeElement element, CodeElement returnedValue) {
59+
var added = returnedValue == element;
60+
if(!added && element is CodeMethod currentMethod)
61+
if(currentMethod.MethodKind == CodeMethodKind.IndexerBackwardCompatibility &&
62+
returnedValue is CodeProperty cProp &&
63+
cProp.PropertyKind == CodePropertyKind.RequestBuilder) {
64+
// indexer retrofited to method in the parent request builder on the path and conflicting with the collection request builder propeerty
65+
returnedValue = innerChildElements.GetOrAdd($"{element.Name}-indexerbackcompat", element);
66+
added = true;
67+
} else if(currentMethod.MethodKind == CodeMethodKind.RequestExecutor ||
68+
currentMethod.MethodKind == CodeMethodKind.RequestGenerator) {
69+
// allows for methods overload
70+
var methodOverloadNameSuffix = currentMethod.Parameters.Any() ? currentMethod.Parameters.Select(x => x.Name).OrderBy(x => x).Aggregate((x, y) => x + y) : "1";
71+
returnedValue = innerChildElements.GetOrAdd($"{element.Name}-{methodOverloadNameSuffix}", element);
72+
added = true;
73+
}
74+
75+
if(!added && returnedValue.GetType() != element.GetType())
76+
throw new InvalidOperationException($"the current dom node already contains a child with name {returnedValue.Name} and of type {returnedValue.GetType().Name}");
77+
78+
return returnedValue;
79+
}
80+
public IEnumerable<T> FindChildrenByName<T>(string childName) where T: ICodeElement {
81+
if(string.IsNullOrEmpty(childName))
82+
throw new ArgumentNullException(nameof(childName));
83+
84+
if(InnerChildElements.Any()) {
85+
var result = new List<T>();
86+
var immediateResult = this.FindChildByName<T>(childName, false);
87+
if(immediateResult != null)
88+
result.Add(immediateResult);
89+
foreach(var childElement in InnerChildElements.Values.OfType<CodeBlock>())
90+
result.AddRange(childElement.FindChildrenByName<T>(childName));
91+
return result;
92+
} else
93+
return Enumerable.Empty<T>();
94+
}
95+
public T FindChildByName<T>(string childName, bool findInChildElements = true) where T: ICodeElement {
96+
if(string.IsNullOrEmpty(childName))
97+
throw new ArgumentNullException(nameof(childName));
98+
99+
if(!InnerChildElements.Any())
100+
return default(T);
101+
102+
if(InnerChildElements.TryGetValue(childName, out var result) && result is T)
103+
return (T)(object)result;
104+
else if(findInChildElements)
105+
foreach(var childElement in InnerChildElements.Values.OfType<CodeBlock>()) {
106+
var childResult = childElement.FindChildByName<T>(childName, true);
107+
if(childResult != null)
108+
return childResult;
109+
}
110+
return default(T);
54111
}
55112
public class BlockDeclaration : CodeTerminal
56113
{

src/Kiota.Builder/CodeDOM/CodeClass.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public enum CodeClassKind {
1313
/// <summary>
1414
/// CodeClass represents an instance of a Class to be generated in source code
1515
/// </summary>
16-
public class CodeClass : CodeBlock, IDocumentedElement
16+
public class CodeClass : CodeBlock, IDocumentedElement, ITypeDefinition
1717
{
1818
private string name;
1919

@@ -40,36 +40,33 @@ public override string Name
4040

4141
public void SetIndexer(CodeIndexer indexer)
4242
{
43-
this.InnerChildElements.Add(indexer);
43+
AddRange(indexer);
4444
}
4545

46-
public void AddProperty(params CodeProperty[] properties)
46+
public IEnumerable<CodeProperty> AddProperty(params CodeProperty[] properties)
4747
{
4848
if(!properties.Any() || properties.Any(x => x == null))
4949
throw new ArgumentNullException(nameof(properties));
50-
AddMissingParent(properties);
51-
this.InnerChildElements.AddRange(properties);
50+
return AddRange(properties);
5251
}
5352

5453
public bool ContainsMember(string name)
5554
{
56-
return this.InnerChildElements.Any(e => e.Name == name);
55+
return this.InnerChildElements.ContainsKey(name);
5756
}
5857

59-
public void AddMethod(params CodeMethod[] methods)
58+
public IEnumerable<CodeMethod> AddMethod(params CodeMethod[] methods)
6059
{
6160
if(!methods.Any() || methods.Any(x => x == null))
6261
throw new ArgumentOutOfRangeException(nameof(methods));
63-
AddMissingParent(methods);
64-
this.InnerChildElements.AddRange(methods);
62+
return AddRange(methods);
6563
}
6664

67-
public void AddInnerClass(params CodeClass[] codeClasses)
65+
public IEnumerable<CodeClass> AddInnerClass(params CodeClass[] codeClasses)
6866
{
6967
if(!codeClasses.Any() || codeClasses.Any(x => x == null))
7068
throw new ArgumentOutOfRangeException(nameof(codeClasses));
71-
AddMissingParent(codeClasses);
72-
this.InnerChildElements.AddRange(codeClasses);
69+
return AddRange(codeClasses);
7370
}
7471
public CodeClass GetParentClass() {
7572
if(StartBlock is Declaration declaration)

src/Kiota.Builder/CodeDOM/CodeElement.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ namespace Kiota.Builder
77
/// <summary>
88
/// Abstract element of some piece of source code to be generated
99
/// </summary>
10-
public abstract class CodeElement
10+
public abstract class CodeElement : ICodeElement
1111
{
12-
public Dictionary<string, object> GenerationProperties { get; set; } = new Dictionary<string, object>();
12+
public Dictionary<string, object> GenerationProperties { get; set; } = new(StringComparer.OrdinalIgnoreCase);
1313
protected CodeElement(CodeElement parent)
1414
{
1515
if(parent == null && !(this is CodeNamespace))
1616
throw new ArgumentNullException(nameof(parent));
1717
Parent = parent;
1818
}
1919
public CodeElement Parent { get; set; }
20-
public abstract IList<CodeElement> GetChildElements();
20+
public virtual IEnumerable<CodeElement> GetChildElements(bool innerOnly = false) => Enumerable.Empty<CodeElement>();
2121

2222
public virtual string Name
2323
{

0 commit comments

Comments
 (0)