Skip to content

Commit 8f0dceb

Browse files
maca88hazzik
authored andcommitted
bug fixing
1 parent 85e7319 commit 8f0dceb

File tree

312 files changed

+718
-7787
lines changed

Some content is hidden

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

312 files changed

+718
-7787
lines changed

src/NHibernate.AsyncGenerator/DocumentWriter.cs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ private BlockSyntax AsyncLockBlock(BlockSyntax block)
103103
private MethodDeclarationSyntax RewiteMethod(MethodInfo methodInfo)
104104
{
105105
// TODO: if a method cannot be converted to async we should not convert dependencies too
106-
if (!methodInfo.CanBeAsnyc && !methodInfo.Dependencies.Any() && !methodInfo.Missing)
106+
if (!methodInfo.CanBeAsnyc && !methodInfo.RelatedMethods.Any() && !methodInfo.Missing)
107107
{
108108
if (methodInfo.TypeInfo.TypeTransformation == TypeTransformation.Partial)
109109
{
@@ -115,10 +115,11 @@ private MethodDeclarationSyntax RewiteMethod(MethodInfo methodInfo)
115115
var taskConflict = !DocumentInfo.ProjectInfo.IsNameUniqueInsideNamespace(methodInfo.TypeInfo.NamespaceInfo.Symbol, "Task");
116116
if (!methodInfo.HasBody)
117117
{
118-
return methodInfo.Node
119-
.WithoutAttribute("Async")
120-
.ReturnAsTask(methodInfo.Symbol, taskConflict)
121-
.WithIdentifier(Identifier(methodInfo.Node.Identifier.Value + "Async"));
118+
return RemoveLeadingRegions(
119+
methodInfo.Node
120+
.WithoutAttribute("Async")
121+
.ReturnAsTask(methodInfo.Symbol, taskConflict)
122+
.WithIdentifier(Identifier(methodInfo.Node.Identifier.Value + "Async")));
122123
}
123124

124125
var methodNode = methodInfo.Node.WithoutTrivia(); // references have spans without trivia
@@ -473,15 +474,6 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
473474

474475
var removeNode = methodInfo.Ignore;
475476

476-
//TODO: REMOVE THIS
477-
/*
478-
if (typeInfo.TypeTransformation == TypeTransformation.NewType &&
479-
methodInfo.ReferenceResults.Any(o => !o.CanBeAsync && o.DeclaredWithinSameType))
480-
{
481-
//TODO: handle dependencies and methods from other types
482-
removeNode = true;
483-
}*/
484-
485477
metadata.TaskUsed |= methodInfo.CanSkipAsync || methodInfo.IsEmpty || methodInfo.HasYields || !methodInfo.CanBeAsnyc;
486478
result.TaskUsed |= metadata.TaskUsed;
487479
metadata.AsyncLockUsed |= methodInfo.MustRunSynchronized;
@@ -619,7 +611,9 @@ private RewriteTypeResult RewriteType(TypeInfo rootTypeInfo, bool onlyMissingMem
619611
}
620612

621613
// remove all regions as not all methods will be written in the type
622-
result.Node = RemoveLeadingRegions(rootTypeNode);
614+
result.Node = rootTypeNode != null
615+
? RemoveLeadingRegions(rootTypeNode)
616+
: null;
623617
/*.WithTriviaFrom(rootTypeInfo.Node)*/;
624618
return result;
625619
}

src/NHibernate.AsyncGenerator/MethodInfo.cs

Lines changed: 115 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,25 @@ public MethodInfo(TypeInfo typeInfo, IMethodSymbol symbol, MethodDeclarationSynt
3434

3535
public bool Missing { get; set; }
3636

37-
public Dictionary<ReferenceLocation, MethodInfo> InvokedBy { get; } = new Dictionary<ReferenceLocation, MethodInfo>();
37+
public HashSet<MethodInfo> InvokedBy { get; } = new HashSet<MethodInfo>();
3838

39-
public HashSet<MethodInfo> Dependencies { get; } = new HashSet<MethodInfo>();
39+
/// <summary>
40+
/// Implementation/derived/base/interface methods
41+
/// </summary>
42+
public HashSet<MethodInfo> RelatedMethods { get; } = new HashSet<MethodInfo>();
43+
44+
/// <summary>
45+
/// Related and invoked by methods
46+
/// </summary>
47+
public IEnumerable<MethodInfo> Dependencies
48+
{
49+
get { return InvokedBy.Union(RelatedMethods); }
50+
}
4051

41-
public HashSet<IMethodSymbol> ExternalDependencies { get; } = new HashSet<IMethodSymbol>();
52+
/// <summary>
53+
/// External Base/derivered or interface/implementation methods
54+
/// </summary>
55+
public HashSet<IMethodSymbol> ExternalRelatedMethods { get; } = new HashSet<IMethodSymbol>();
4256

4357
// async methods that have the same parameters and name and are external
4458
public HashSet<IMethodSymbol> ExternalAsyncMethods { get; } = new HashSet<IMethodSymbol>();
@@ -47,6 +61,13 @@ public MethodInfo(TypeInfo typeInfo, IMethodSymbol symbol, MethodDeclarationSynt
4761
/// When true the method will not be generated. Example would be a test method (never invoked in code) that does not have any async calls
4862
/// or a method that is only called by that test method. If there are some references (methods invoked) we need to check them as they can be
4963
///
64+
/// Steps:
65+
/// 1. Check if the method is missing or implements an abstract method
66+
/// a) If true then we cannot ignore this method
67+
/// 3. Calculate the Ignore property for all dependant methods
68+
/// a) If there is a method that is not ignored then this wont be too
69+
/// i) Calculate ignore property for all current references
70+
/// 2. Calculate the Ignore property for all current references
5071
/// </summary>
5172
public void CalculateIgnore(int deep = 0, HashSet<MethodInfo> processedMethodInfos = null)
5273
{
@@ -59,75 +80,78 @@ public void CalculateIgnore(int deep = 0, HashSet<MethodInfo> processedMethodInf
5980
throw new Exception("_ignoreCalculating");
6081
}
6182
_ignoreCalculating = true;
62-
63-
83+
84+
6485
if (processedMethodInfos == null)
6586
{
6687
processedMethodInfos = new HashSet<MethodInfo> {this};
6788
}
68-
69-
deep++;
70-
if (deep > 20)
89+
else
7190
{
72-
Ignore = false;
73-
_ignoreCalculating = false;
74-
_ignoreCalculated = true;
75-
return;
91+
processedMethodInfos.Add(this);
7692
}
77-
/*
78-
foreach (var refResult in ReferenceResults)
79-
{
80-
refResult.CalculateIgnore(deep, processedMethodInfos);
81-
}*/
8293

83-
if (Missing || IsRequired)
94+
deep++;
95+
if (deep > 100)
8496
{
85-
Ignore = false;
97+
foreach (var refResult in ReferenceResults)
98+
{
99+
refResult.CalculateIgnore(deep, processedMethodInfos);
100+
}
86101
_ignoreCalculating = false;
87102
_ignoreCalculated = true;
88103
return;
89104
}
90-
var config = TypeInfo.NamespaceInfo.DocumentInfo.ProjectInfo.Configuration;
91-
92-
//if (TypeInfo.TypeTransformation == TypeTransformation.NewType)
93-
//{
94-
95-
//}
96105

97-
// If method is used elsewhere then we should generante the method (TODO: check if methods that invoke this one are ignored... problem with circular calls)
98-
if (InvokedBy.Any())
106+
if (Missing || ImplementsAbstractMethod)
99107
{
100-
Ignore = false;
108+
foreach (var refResult in ReferenceResults)
109+
{
110+
refResult.CalculateIgnore(deep, processedMethodInfos);
111+
}
101112
_ignoreCalculating = false;
102113
_ignoreCalculated = true;
103114
return;
104115
}
105116

106-
/*
107-
foreach (var methodInfo in InvokedBy.Values)
117+
// Calculate the ignore property for all dependent methods.
118+
// If any of above methods is required then this will be too
119+
foreach (var methodInfo in Dependencies)
108120
{
109121
if (methodInfo == this)
110122
{
111123
continue;
112124
}
125+
// If we detect a circular dependency we assume that the method is required
126+
if (methodInfo._ignoreCalculating)
127+
{
128+
foreach (var refResult in ReferenceResults)
129+
{
130+
refResult.CalculateIgnore(deep, processedMethodInfos);
131+
}
132+
_ignoreCalculating = false;
133+
_ignoreCalculated = true;
134+
return;
135+
}
113136

114137
methodInfo.CalculateIgnore(deep, processedMethodInfos);
115138
if (methodInfo.Ignore)
116139
{
117140
continue;
118141
}
119-
Ignore = false;
142+
foreach (var refResult in ReferenceResults)
143+
{
144+
refResult.CalculateIgnore(deep, processedMethodInfos);
145+
}
146+
_ignoreCalculating = false;
147+
_ignoreCalculated = true;
120148
return;
121-
}*/
149+
}
122150

123151
var dependencies = ReferenceResults
124-
.Union(GetAllDependencies().ToList().SelectMany(o => o.ReferenceResults))
125-
.ToList();/*
126-
if (!dependencies.Any() && config.CanGenerateMethod != null)
127-
{
128-
return !config.CanGenerateMethod(this);
129-
}
130-
*/
152+
.Union(GetAllRelatedMethods().ToList().SelectMany(o => o.ReferenceResults))
153+
.ToList();
154+
131155
foreach (var refResult in dependencies)
132156
{
133157
// if the reference cannot be async we should preserve the original method. TODO: what if the method has dependecies that are async
@@ -136,23 +160,6 @@ public void CalculateIgnore(int deep = 0, HashSet<MethodInfo> processedMethodInf
136160
refResult.MethodInfo.CanBeAsnyc = false;
137161
}
138162
refResult.CalculateIgnore(deep, processedMethodInfos);
139-
140-
/*
141-
var ignore = false;
142-
if (refResult.MethodInfo != null)
143-
{
144-
if (processedMethodInfos.Contains(refResult.MethodInfo))
145-
{
146-
continue;
147-
}
148-
processedMethodInfos.Add(refResult.MethodInfo);
149-
ignore |= refResult.MethodInfo.CanIgnore(deep, processedMethodInfos);
150-
}
151-
ignore |= refResult.UserIgnore;
152-
if (!ignore)
153-
{
154-
return false;
155-
}*/
156163
}
157164
Ignore = dependencies.All(o => o.Ignore);
158165
_ignoreCalculating = false;
@@ -163,7 +170,7 @@ public bool HasReferences
163170
{
164171
get
165172
{
166-
return References.Any() || GetAllDependencies().Any(o => o.References.Any());
173+
return References.Any() || GetAllRelatedMethods().Any(o => o.References.Any());
167174
}
168175
}
169176

@@ -179,13 +186,13 @@ public bool HasRequiredExternalMethods(int deep = 0, HashSet<MethodInfo> process
179186
processedMethodInfos = new HashSet<MethodInfo> { this };
180187
}
181188

182-
if (ExternalDependencies.Select(o => o.ContainingType.GetFullName())
189+
if (ExternalRelatedMethods.Select(o => o.ContainingType.GetFullName())
183190
.Except(ExternalAsyncMethods.Select(o => o.ContainingType.GetFullName()))
184191
.Any())
185192
{
186193
return true;
187194
}
188-
foreach (var depednency in GetAllDependencies())
195+
foreach (var depednency in GetAllRelatedMethods())
189196
{
190197
if (processedMethodInfos.Contains(depednency))
191198
{
@@ -200,15 +207,15 @@ public bool HasRequiredExternalMethods(int deep = 0, HashSet<MethodInfo> process
200207
return false;
201208
}
202209

203-
public bool IsRequired
210+
public bool ImplementsAbstractMethod
204211
{
205212
get { return OverridenMethod != null && OverridenMethod.IsAbstract; }
206213
}
207214

208215
public IMethodSymbol OverridenMethod { get; set; }
209216

210217
/// <summary>
211-
/// references that are candidates to be async
218+
/// References to other methods that are invoked inside this method and are candidates to be async
212219
/// </summary>
213220
internal HashSet<ReferenceLocation> References { get; } = new HashSet<ReferenceLocation>();
214221

@@ -217,6 +224,29 @@ public bool IsRequired
217224
/// </summary>
218225
public HashSet<ReferenceLocation> TypeReferences { get; } = new HashSet<ReferenceLocation>();
219226

227+
public IEnumerable<MethodInfo> GetAllRelatedMethods()
228+
{
229+
var deps = new HashSet<MethodInfo>();
230+
var depsQueue = new Queue<MethodInfo>(RelatedMethods);
231+
while (depsQueue.Count > 0)
232+
{
233+
var dependency = depsQueue.Dequeue();
234+
if (deps.Contains(dependency))
235+
{
236+
continue;
237+
}
238+
deps.Add(dependency);
239+
foreach (var subDependency in dependency.RelatedMethods)
240+
{
241+
if (!deps.Contains(subDependency))
242+
{
243+
depsQueue.Enqueue(subDependency);
244+
}
245+
}
246+
yield return dependency;
247+
}
248+
}
249+
220250
public IEnumerable<MethodInfo> GetAllDependencies()
221251
{
222252
var deps = new HashSet<MethodInfo>();
@@ -231,11 +261,10 @@ public IEnumerable<MethodInfo> GetAllDependencies()
231261
deps.Add(dependency);
232262
foreach (var subDependency in dependency.Dependencies)
233263
{
234-
if (deps.Contains(subDependency))
264+
if (!deps.Contains(subDependency))
235265
{
236-
continue;
266+
depsQueue.Enqueue(subDependency);
237267
}
238-
depsQueue.Enqueue(subDependency);
239268
}
240269
yield return dependency;
241270
}
@@ -559,17 +588,39 @@ public void PostAnalyze()
559588
{
560589
TypeInfo.MethodInfos.Remove(Node);
561590
}
591+
592+
// Remove all references as the method wont be transformed to asnyc
593+
if (!CanBeAsnyc && !RelatedMethods.Any() && !Missing)
594+
{
595+
foreach (var invoked in InvokedBy)
596+
{
597+
var toRemove = invoked.ReferenceResults.Where(o => o.MethodInfo == this).ToList();
598+
while (toRemove.Count > 0)
599+
{
600+
invoked.ReferenceResults.Remove(toRemove[0]);
601+
toRemove.RemoveAt(0);
602+
}
603+
}
604+
}
562605
}
563606

564607
// check if all the references can be converted to async
565608
public void Analyze()
566609
{
610+
var solutionConfig = TypeInfo.NamespaceInfo.DocumentInfo.ProjectInfo.SolutionInfo.Configuration;
611+
567612
foreach (var reference in References)
568613
{
569614
ReferenceResults.Add(AnalyzeReference(reference));
570615
}
571616
CanBeAsnyc = ReferenceResults.Any(o => o.CanBeAsync);
572617

618+
// TODO: check if this is correct
619+
if (TypeInfo.TypeTransformation == TypeTransformation.Partial && GetAllRelatedMethods().ToList().Any(o => o.InvokedBy.Any()))
620+
{
621+
Missing = true;
622+
}
623+
573624
var counter = new MethodStatementsCounterVisitior();
574625
counter.Visit(Node.Body);
575626

@@ -582,7 +633,6 @@ public void Analyze()
582633
IsEmpty = true;
583634
}
584635

585-
var solutionConfig = TypeInfo.NamespaceInfo.DocumentInfo.ProjectInfo.SolutionInfo.Configuration;
586636
if (Node.AttributeLists
587637
.SelectMany(o => o.Attributes.Where(a => a.Name.ToString() == "MethodImpl"))
588638
.Any(o => o.ArgumentList.Arguments.Any(a => a.Expression.ToString() == "MethodImplOptions.Synchronized")))

0 commit comments

Comments
 (0)