Skip to content

Commit ef0fcf2

Browse files
maca88hazzik
authored andcommitted
Added async future using System.Interactive.Async for ICriteria, QueryOver and Linq.
1 parent 667e9fd commit ef0fcf2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1463
-921
lines changed
181 KB
Binary file not shown.

lib/net/4.5/System.Interactive.Async.xml

Lines changed: 52 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/NHibernate.AsyncGenerator/DocumentTransformer.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ private MethodDeclarationSyntax TransformMethod(MethodInfo methodInfo)
169169
return methodInfo.Node
170170
.ReturnAsTask(methodInfo.Symbol, taskConflict)
171171
.WithIdentifier(Identifier(methodInfo.Node.Identifier.Value + "Async"))
172-
.RemoveLeadingRegions();
172+
.RemoveLeadingDirectives();
173173
}
174174

175175
var methodNode = methodInfo.Node.WithoutTrivia(); // references have spans without trivia
@@ -386,7 +386,7 @@ private MethodDeclarationSyntax TransformMethod(MethodInfo methodInfo)
386386

387387
return methodNode
388388
.WithLeadingTrivia(methodInfo.Node.GetLeadingTrivia())
389-
.RemoveLeadingRegions()
389+
.RemoveLeadingDirectives()
390390
.WithTrailingTrivia(methodInfo.Node.GetTrailingTrivia());
391391
}
392392

@@ -525,7 +525,7 @@ private TransformTypeResult TransformType(TypeInfo rootTypeInfo, bool onlyMissin
525525
var typeNode = rootTypeNode.GetAnnotatedNodes(metadata.NodeAnnotation).OfType<TypeDeclarationSyntax>().First();
526526
// TODO: we should not include all members, we need to skip the methods that are not required
527527
rootTypeNode = rootTypeNode.ReplaceNode(typeNode, typeNode.WithMembers(
528-
typeNode.Members.Select(o => o.RemoveLeadingRegions()).ToSyntaxList()
528+
typeNode.Members.Select(o => o.RemoveLeadingDirectives()).ToSyntaxList()
529529
.AddRange(
530530
metadata.TransformedNodes
531531
.OrderBy(o => o.Original.SpanStart)
@@ -596,7 +596,7 @@ private TransformTypeResult TransformType(TypeInfo rootTypeInfo, bool onlyMissin
596596
newTypeNode.DescendantNodes(descendIntoTrivia: true).OfType<DirectiveTriviaSyntax>(), SyntaxRemoveOptions.KeepNoTrivia); // remove invalid #endregion
597597
*/
598598
rootTypeNode = rootTypeNode
599-
.ReplaceNode(typeNode, newTypeNode.RemoveLeadingRegions());
599+
.ReplaceNode(typeNode, newTypeNode.RemoveLeadingDirectives());
600600
}
601601
}
602602

@@ -611,7 +611,7 @@ private TransformTypeResult TransformType(TypeInfo rootTypeInfo, bool onlyMissin
611611

612612
// remove all regions as not all methods will be written in the type
613613
result.Node = rootTypeNode != null
614-
? rootTypeNode.RemoveLeadingRegions()
614+
? rootTypeNode.RemoveLeadingDirectives()
615615
: null;
616616
/*.WithTriviaFrom(rootTypeInfo.Node)*/;
617617
return result;

src/NHibernate.AsyncGenerator/Extensions/SymbolExtensions.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,28 @@ public static bool IsNullable(this ITypeSymbol symbol)
355355
return symbol?.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T;
356356
}
357357

358+
/// <summary>
359+
/// Searches for an async counterpart within method containing type and its bases without checking the return type
360+
/// </summary>
361+
/// <param name="methodSymbol"></param>
362+
/// <param name="inherit"></param>
363+
/// <returns></returns>
364+
public static IMethodSymbol GetAsyncCounterpart(this IMethodSymbol methodSymbol, bool inherit = false)
365+
{
366+
if (inherit)
367+
{
368+
return methodSymbol.ContainingType.EnumerateBaseTypesAndSelf()
369+
.SelectMany(o => o.GetMembers(methodSymbol.Name + "Async"))
370+
.OfType<IMethodSymbol>()
371+
.Where(o => o.TypeParameters.Length == methodSymbol.TypeParameters.Length)
372+
.FirstOrDefault(o => o.HaveSameParameters(methodSymbol));
373+
}
374+
return methodSymbol.ContainingType.GetMembers(methodSymbol.Name + "Async")
375+
.OfType<IMethodSymbol>()
376+
.Where(o => o.TypeParameters.Length == methodSymbol.TypeParameters.Length)
377+
.FirstOrDefault(o => o.HaveSameParameters(methodSymbol));
378+
}
379+
358380
public static bool HaveSameParameters(this IMethodSymbol m1, IMethodSymbol m2, Func<IParameterSymbol, IParameterSymbol, bool> paramCompareFunc = null)
359381
{
360382
if (m1.Parameters.Length != m2.Parameters.Length)

src/NHibernate.AsyncGenerator/Extensions/SyntaxExtensions.Trivia.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ namespace NHibernate.AsyncGenerator.Extensions
1010
{
1111
internal static partial class SyntaxExtensions
1212
{
13+
private static readonly HashSet<SyntaxKind> DirectiveKinds;
14+
15+
static SyntaxExtensions()
16+
{
17+
DirectiveKinds = new HashSet<SyntaxKind>
18+
{
19+
SyntaxKind.RegionDirectiveTrivia,
20+
SyntaxKind.EndRegionDirectiveTrivia,
21+
SyntaxKind.EndIfDirectiveTrivia,
22+
SyntaxKind.IfDirectiveTrivia,
23+
SyntaxKind.ElseDirectiveTrivia,
24+
SyntaxKind.ElifDirectiveTrivia
25+
};
26+
}
27+
1328
public static T WithPrependedLeadingTrivia<T>(
1429
this T node,
1530
params SyntaxTrivia[] trivia) where T : SyntaxNode
@@ -19,7 +34,7 @@ public static T WithPrependedLeadingTrivia<T>(
1934
return node;
2035
}
2136

22-
return node.WithPrependedLeadingTrivia((IEnumerable<SyntaxTrivia>)trivia);
37+
return node.WithPrependedLeadingTrivia((IEnumerable<SyntaxTrivia>) trivia);
2338
}
2439

2540
public static T WithPrependedLeadingTrivia<T>(
@@ -50,7 +65,7 @@ public static T WithAppendedTrailingTrivia<T>(
5065
return node;
5166
}
5267

53-
return node.WithAppendedTrailingTrivia((IEnumerable<SyntaxTrivia>)trivia);
68+
return node.WithAppendedTrailingTrivia((IEnumerable<SyntaxTrivia>) trivia);
5469
}
5570

5671
public static T WithAppendedTrailingTrivia<T>(
@@ -80,13 +95,13 @@ public static T With<T>(
8095
return node.WithLeadingTrivia(leadingTrivia).WithTrailingTrivia(trailingTrivia);
8196
}
8297

83-
public static SyntaxTriviaList RemoveRegions(this SyntaxTriviaList list)
98+
public static SyntaxTriviaList RemoveDirectives(this SyntaxTriviaList list)
8499
{
85100
var toRemove = new List<int>();
86101
for (var i = list.Count - 1; i >= 0; i--)
87102
{
88103
var trivia = list[i];
89-
if (trivia.IsKind(SyntaxKind.RegionDirectiveTrivia) || trivia.IsKind(SyntaxKind.EndRegionDirectiveTrivia))
104+
if (DirectiveKinds.Contains((SyntaxKind) trivia.RawKind))
90105
{
91106
toRemove.Add(i);
92107
}
@@ -99,4 +114,4 @@ public static SyntaxTriviaList RemoveRegions(this SyntaxTriviaList list)
99114
return list;
100115
}
101116
}
102-
}
117+
}

src/NHibernate.AsyncGenerator/Extensions/SyntaxNodeExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ public static IEnumerable<TNode> GetAncestors<TNode>(this SyntaxNode node)
2727
}
2828
}
2929

30-
public static T RemoveLeadingRegions<T>(this T memberNode) where T : MemberDeclarationSyntax
30+
public static T RemoveLeadingDirectives<T>(this T memberNode) where T : MemberDeclarationSyntax
3131
{
3232
// remove all regions as not all methods will be written in the type
3333
var leadingTrivia = memberNode.GetLeadingTrivia();
34-
memberNode = memberNode.WithLeadingTrivia(leadingTrivia.RemoveRegions());
34+
memberNode = memberNode.WithLeadingTrivia(leadingTrivia.RemoveDirectives());
3535

3636
var baseTypeNode = memberNode as BaseTypeDeclarationSyntax;
3737
if (baseTypeNode == null)
@@ -42,7 +42,7 @@ public static T RemoveLeadingRegions<T>(this T memberNode) where T : MemberDecla
4242
.ReplaceToken(
4343
baseTypeNode.CloseBraceToken,
4444
baseTypeNode.CloseBraceToken
45-
.WithLeadingTrivia(baseTypeNode.CloseBraceToken.LeadingTrivia.RemoveRegions()));
45+
.WithLeadingTrivia(baseTypeNode.CloseBraceToken.LeadingTrivia.RemoveDirectives()));
4646
}
4747
}
4848
}

src/NHibernate.AsyncGenerator/MethodInfo.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ public void CalculateIgnore(int deep = 0, HashSet<MethodInfo> processedMethodInf
180180
_ignoreCalculated = true;
181181
}
182182

183+
public void SetIgnore(bool value)
184+
{
185+
_ignoreCalculated = true;
186+
Ignore = value;
187+
}
188+
183189
public bool HasReferences
184190
{
185191
get
@@ -540,15 +546,11 @@ public async Task<List<AsyncCounterpartMethod>> FindAsyncCounterpartMethodsWhiti
540546
var config = projectInfo.Configuration;
541547
if (config.FindAsyncCounterpart != null)
542548
{
543-
asyncMethodSymbol = await config.FindAsyncCounterpart.Invoke(projectInfo.Project, methodSymbol.OriginalDefinition).ConfigureAwait(false);
549+
asyncMethodSymbol = await config.FindAsyncCounterpart.Invoke(projectInfo.Project, methodSymbol.OriginalDefinition, true).ConfigureAwait(false);
544550
}
545551
else
546552
{
547-
asyncMethodSymbol = methodSymbol.ContainingType.EnumerateBaseTypesAndSelf()
548-
.SelectMany(o => o.GetMembers(methodSymbol.Name + "Async"))
549-
.OfType<IMethodSymbol>()
550-
.Where(o => o.TypeParameters.Length == methodSymbol.TypeParameters.Length)
551-
.FirstOrDefault(o => o.HaveSameParameters(methodSymbol));
553+
asyncMethodSymbol = methodSymbol.GetAsyncCounterpart(true);
552554
}
553555
methodAsyncConterparts?.Add(methodSymbol.OriginalDefinition, asyncMethodSymbol?.OriginalDefinition);
554556
}

src/NHibernate.AsyncGenerator/Program.cs

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static void Main(string[] args)
2828
var currentPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
2929
var basePath = Path.GetFullPath(Path.Combine(currentPath, @"..\..\..\"));
3030

31-
Func<Project, IMethodSymbol, Task<IMethodSymbol>> findAsyncFn = async (project, symbol) =>
31+
Func<Project, IMethodSymbol, bool, Task<IMethodSymbol>> findAsyncFn = async (project, symbol, inherit) =>
3232
{
3333
var ns = symbol.ContainingNamespace?.ToString() ?? "";
3434
var isToList = project.Name != "NHibernate" && symbol.ContainingType.Name == "Enumerable" && symbol.Name == "ToList";
@@ -93,11 +93,19 @@ static void Main(string[] args)
9393
paramCompareFunc = (p1, p2) => p1.Type.Equals(p2.Type) ||
9494
(delegateNames.Contains(p1.Type.Name) && delegateNames.Contains(p2.Type.Name));
9595
}
96-
return symbol.ContainingType.EnumerateBaseTypesAndSelf()
97-
.SelectMany(o => o.GetMembers(symbol.Name + "Async"))
98-
.OfType<IMethodSymbol>()
99-
.Where(o => o.TypeParameters.Length == symbol.TypeParameters.Length)
100-
.FirstOrDefault(o => o.HaveSameParameters(symbol, paramCompareFunc));
96+
97+
if (inherit)
98+
{
99+
return symbol.ContainingType.EnumerateBaseTypesAndSelf()
100+
.SelectMany(o => o.GetMembers(symbol.Name + "Async"))
101+
.OfType<IMethodSymbol>()
102+
.Where(o => o.TypeParameters.Length == symbol.TypeParameters.Length)
103+
.FirstOrDefault(o => o.HaveSameParameters(symbol, paramCompareFunc));
104+
}
105+
return symbol.ContainingType.GetMembers(symbol.Name + "Async")
106+
.OfType<IMethodSymbol>()
107+
.Where(o => o.TypeParameters.Length == symbol.TypeParameters.Length)
108+
.FirstOrDefault(o => o.HaveSameParameters(symbol, paramCompareFunc));
101109
};
102110

103111
var solutionConfig = new SolutionConfiguration(Path.Combine(basePath, @"NHibernate.sln"))
@@ -178,22 +186,6 @@ static void Main(string[] args)
178186
// if "await Task.Yield();" is added after DoLinqInSeparateSessionAsync then the test runs successfully (TODO: discover why)
179187
return !doc.FilePath.EndsWith(@"Linq\MathTests.cs") &&
180188
!doc.FilePath.EndsWith(@"Linq\ExpressionSessionLeakTest.cs");
181-
182-
//return
183-
// doc.FilePath.EndsWith(@"NH2322\PostUpdateEventListener.cs") /*||
184-
// doc.FilePath.EndsWith(@"\TestCaseMappingByCode.cs") ||
185-
// doc.FilePath.EndsWith(@"\TestCase.cs")*/
186-
// ;
187-
188-
//return doc.FilePath.EndsWith(@"Linq\JoinTests.cs") ||
189-
//doc.FilePath.EndsWith(@"Linq\LinqTestCase.cs") ||
190-
//doc.FilePath.EndsWith(@"Linq\ReadonlyTestCase.cs") ||
191-
//doc.FilePath.EndsWith(@"\TestCase.cs");
192-
193-
//return
194-
//doc.FilePath.EndsWith(@"NHSpecificTest\BasicClassFixture.cs") ||
195-
//doc.FilePath.EndsWith(@"\ObjectAssertion.cs") ||
196-
//doc.FilePath.EndsWith(@"\TestCase.cs");
197189
},
198190
FindAsyncCounterpart = findAsyncFn,
199191
TypeTransformationFunc = type =>

src/NHibernate.AsyncGenerator/ProjectConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public ProjectConfiguration(string name)
4040
/// <summary>
4141
/// A custom method that will be called when for a method there is not an async counterpart with same parameters
4242
/// </summary>
43-
public Func<Project, IMethodSymbol, Task<IMethodSymbol>> FindAsyncCounterpart { get; set; } = null;
43+
public Func<Project, IMethodSymbol, bool, Task<IMethodSymbol>> FindAsyncCounterpart { get; set; } = null;
4444

4545
/// <summary>
4646
/// When enabled it will search all invocation expressions inside a method body and tries to find a async counterpart

src/NHibernate.AsyncGenerator/ProjectInfo.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,15 @@ private async Task<DocumentInfo> AnalyzeDocument(Document document)
229229
{
230230
continue;
231231
}
232-
var symbolInfo = AnalyzeMethodSymbol(memberSymbol, true, conversion);
232+
var symbolInfo = await AnalyzeMethodSymbol(memberSymbol, true, conversion).ConfigureAwait(false);
233233
if (!symbolInfo.IsValid)
234234
{
235+
// For new types we need to register all method infos in order to copy only methods that are not ignored
236+
if (symbolInfo == MethodSymbolInfo.Ignore && typeInfo.TypeTransformation == TypeTransformation.NewType)
237+
{
238+
docInfo.GetOrCreateMethodInfo(memberSymbol)?.SetIgnore(true);
239+
}
240+
235241
continue;
236242
}
237243
if (conversion == MethodAsyncConversion.Smart && !await SmartAnalyzeMethod(docInfo, typeInfo, memberSymbol, symbolInfo).ConfigureAwait(false))
@@ -463,6 +469,8 @@ private class MethodSymbolInfo
463469
{
464470
public static readonly MethodSymbolInfo Invalid = new MethodSymbolInfo();
465471

472+
public static readonly MethodSymbolInfo Ignore = new MethodSymbolInfo();
473+
466474
public HashSet<IMethodSymbol> InterfaceMethods { get; set; }
467475

468476
public HashSet<IMethodSymbol> AsyncInterfaceMethods { get; set; }
@@ -559,7 +567,7 @@ private bool CanProcessDocument(Document doc)
559567

560568
private readonly Dictionary<IMethodSymbol, MethodSymbolInfo> _cachedMethodSymbolInfos = new Dictionary<IMethodSymbol, MethodSymbolInfo>();
561569

562-
private MethodSymbolInfo AnalyzeMethodSymbol(IMethodSymbol methodSymbol, bool memorize = true, MethodAsyncConversion? conversion = null)
570+
private async Task<MethodSymbolInfo> AnalyzeMethodSymbol(IMethodSymbol methodSymbol, bool memorize = true, MethodAsyncConversion? conversion = null)
563571
{
564572
if (_cachedMethodSymbolInfos.ContainsKey(methodSymbol.OriginalDefinition))
565573
{
@@ -575,7 +583,7 @@ private MethodSymbolInfo AnalyzeMethodSymbol(IMethodSymbol methodSymbol, bool me
575583
{
576584
Logger.Debug($"Symbol {methodSymbol} is already async");
577585
}
578-
return MethodSymbolInfo.Invalid;
586+
return MethodSymbolInfo.Ignore;
579587
}
580588
if (methodSymbol.MethodKind != MethodKind.Ordinary && methodSymbol.MethodKind != MethodKind.ExplicitInterfaceImplementation)
581589
{
@@ -728,6 +736,23 @@ private MethodSymbolInfo AnalyzeMethodSymbol(IMethodSymbol methodSymbol, bool me
728736
interfaceMethods.Add(interfaceMember.OriginalDefinition);
729737
}
730738

739+
// Verify if there is already an async counterpart for this method
740+
IMethodSymbol asyncCounterpart;
741+
if (Configuration.FindAsyncCounterpart != null)
742+
{
743+
asyncCounterpart = await Configuration.FindAsyncCounterpart.Invoke(Project, methodSymbol.OriginalDefinition, false).ConfigureAwait(false);
744+
}
745+
else
746+
{
747+
asyncCounterpart = methodSymbol.GetAsyncCounterpart();
748+
}
749+
if (asyncCounterpart != null)
750+
{
751+
Logger.Debug($"Method {methodSymbol} has already an async counterpart {asyncCounterpart}");
752+
_cachedMethodSymbolInfos.Add(methodSymbol.OriginalDefinition, MethodSymbolInfo.Ignore);
753+
return MethodSymbolInfo.Ignore;
754+
}
755+
731756
var isSymbolValidFunc = SolutionInfo.Configuration.IsSymbolValidFunc;
732757
if (isSymbolValidFunc != null && !isSymbolValidFunc(this, methodSymbol))
733758
{
@@ -955,7 +980,7 @@ private async Task ScanAllMethodReferenceLocations(IMethodSymbol methodSymbol, i
955980
continue;
956981
}
957982
// dont check if the method was already analyzed as there can be many references inside one method
958-
var symbolInfo = AnalyzeMethodSymbol(refMethodSymbol, false);
983+
var symbolInfo = await AnalyzeMethodSymbol(refMethodSymbol, false).ConfigureAwait(false);
959984
if (!symbolInfo.IsValid)
960985
{
961986
IgnoredReferenceLocation.Add(refLocation);

0 commit comments

Comments
 (0)