GithubHelp home page GithubHelp logo

asyncgenerator's People

Contributors

eamonhetherton avatar gliljas avatar hazzik avatar maca88 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

asyncgenerator's Issues

Add better support for delegate arguments

Example:

public class MethodWithDelegate
{
    public void Test()
    {
        Read(() => SimpleFile.Read());
    }

    public void Read(Action action)
    {
        action();
        SimpleFile.Read();
    }
}

Expected result

public partial class MethodWithDelegate
{
    public Task TestAsync()
    {
        return ReadAsync(() => SimpleFile.Read());
    }

    public Task ReadAsync(Action action)
    {
        try
        {
            action();
            return SimpleFile.ReadAsync();
        }
        catch (Exception ex)
        {
            return Task.FromException<object>(ex);
        }
    }
}

Actual result

public partial class MethodWithDelegate
{

    public Task ReadAsync(Action action)
    {
        try
        {
            action();
            return SimpleFile.ReadAsync();
        }
        catch (Exception ex)
        {
            return Task.FromException<object>(ex);
        }
    }
}

Generate async counterparts for overriden methods that have an async counterpart

Example:

public abstract class ExternalClass
{
  public virtual bool Read()
  {
    SimpleFile.Read();
    return true;
  }

  public virtual async Task<bool> ReadAsync()
  {
    await SimpleFile.ReadAsync();
    return true;
  }
}

public class OverrideSyncMethod : ExternalClass
{
  public override bool Read()
  {
    base.Read();
    return false;
  }
}

Desired generated type:

public partial class OverrideSyncMethod : ExternalClass
{
  public override async Task<bool> ReadAsync()
  {
    await base.ReadAsync();
    return false;
  }
}

The only problem here is that in some cases the OverrideSyncMethod could intentionally override only the sync counterpart so the solution should support both scenarios.

Missing member used by copied methods with NewType generation

When generating Async code as new type, constants/fields used by copied methods are not copied.

public class Class1
{
    public void Do()
    {
        DbConnection c = GetConnection();
        c.Open();
    }

    private const string _connectionString = "blah";

    private SqlConnection GetConnection() => new SqlConnection(_connectionString);
}

Get generated as:

public class Class1Async
{
    public Task DoAsync(CancellationToken cancellationToken = default(CancellationToken))
    {
        try
        {
            DbConnection c = GetConnection();
            return c.OpenAsync(cancellationToken);
        }
        catch (System.Exception ex)
        {
            return Task.FromException<object>(ex);
        }
    }

    private static SqlConnection GetConnection() => new SqlConnection(_connectionString);
}

Workaround: declare the field or constant as a property.
For this example, changing it to private static string _connectionString => "blah"; dodge the trouble.

Add support for Parallel.For and Parallel.ForEach

The generator should convert

Parallel.ForEach(Enumerable.Range(1, 100), i =>
{
    File.ReadAllText("path" + i);
});

or

Parallel.For(1, 100, i =>
{
    File.ReadAllText("path" + i);
});

to:

Task.WhenAll(Enumerable.Range(1, 100).Select(async i =>
{
    await File.ReadAllTextAsync("path" + i);
}));

Add an option to ignore scanning for a method references

As we've seen in this issue, the method SymbolFinder.FindReferencesAsync can be quite expensive so we want to reduce its calls as far as possible. The idea here is to ignore the scanning for a method references even if the method conversion is set to Smart or ToAsync, this would be very useful for unit test methods as we know that they are not referenced by other methods.
By doing some local testing on the NHibernate test project I found out, that this will reduce the generation time by 20-25 seconds.

Allowing not generating "content" xml comment

Async generator generates partial classes with a "content" xml comment, like this:

/// <content>
/// Contains generated async methods
/// </content>
public partial interface ICollectionPersister

In some tools (JetBrains Rider) under some circumstances (when the original class has non standard xml comment, such as using <para /> for splitting paragraph instead of <para>someText</para>), the intellisens show the async content comment instead of the original class comment. Removing it allow to see the original comment again.

If there is no value in having this content comment as a xml comment, maybe switching it to a simple comment would be better. In its current form it may interfere with documentation tooling.

// Contains generated async methods
public partial interface ICollectionPersister

InvalidCastException while generating

Willing to check how much more tests would be generated for NHibernate Test project by flagging all fixture with [TestFixture] (which is a condition in its async generation configuration), I got a cast failure:

System.InvalidCastException: Impossible d'effectuer un cast d'un objet de type 'Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax' en type 'Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax'.

It seems to occur deep into Microsoft.CodeAnalysis, so it looks likely as an external bug... Maybe that is just some syntax to avoid in some test, but the error do not give much information about which source code file (from which async code should be generated) could trigger the bug.

This had occurred with this branch.

Here is the log:

     [exec] 19:52:05,377 INFO  ProjectAnalyzer:0 - Post-analyzing documents completed
     [exec] 19:52:05,378 INFO  AsyncCodeGenerator:0 - Analyzing project 'NHibernate.Test' completed
     [exec] 19:52:05,378 INFO  AsyncCodeGenerator:0 - Transforming project 'NHibernate.Test' started
     [exec] 19:52:05,379 INFO  ProjectTransformer:0 - Generating documents started
     [exec] System.AggregateException: Une ou plusieurs erreurs se sont produites. ---> System.InvalidCastException: Impossible d'effectuer un cast d'un objet de type 'Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax' en type 'Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax'.
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SeparatedSyntaxList`1 list)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitArgumentList(ArgumentListSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitInvocationExpression(InvocationExpressionSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExpressionStatement(ExpressionStatementSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SyntaxList`1 list)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitBlock(BlockSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitSimpleLambdaExpression(SimpleLambdaExpressionSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitArgument(ArgumentSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SeparatedSyntaxList`1 list)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitArgumentList(ArgumentListSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitInvocationExpression(InvocationExpressionSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExpressionStatement(ExpressionStatementSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SyntaxList`1 list)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitBlock(BlockSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ConstructorDeclarationSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replace[TNode](SyntaxNode root, IEnumerable`1 nodes, Func`3 computeReplacementNode, IEnumerable`1 tokens, Func`3 computeReplacementToken, IEnumerable`1 trivia, Func`3 computeReplacementTrivia)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode.ReplaceCore[TNode](IEnumerable`1 nodes, Func`3 computeReplacementNode, IEnumerable`1 tokens, Func`3 computeReplacementToken, IEnumerable`1 trivia, Func`3 computeReplacementTrivia)
     [exec]    à Microsoft.CodeAnalysis.SyntaxNodeExtensions.ReplaceNode[TRoot](TRoot root, SyntaxNode oldNode, SyntaxNode newNode)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformFunction(IFunctionAnalyzationResult rootFuncResult, ITypeTransformationMetadata typeMetadata, INamespaceTransformationMetadata namespaceMetadata)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformSpecialMethod(FunctionTransformationResult methodTransform, TypeDeclarationSyntax newTypeNode, TypeTransformationResult transformResult, INamespaceTransformationMetadata namespaceMetadata, SyntaxTrivia memberWhitespace, Boolean onlyMissingMembers)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformMethodsAndProperties(TypeDeclarationSyntax newTypeNode, TypeTransformationResult transformResult, INamespaceTransformationMetadata namespaceMetadata, SyntaxTrivia memberWhitespace, Boolean onlyMissingMembers)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformType(ITypeAnalyzationResult rootTypeResult, INamespaceTransformationMetadata namespaceMetadata, Boolean onlyMissingMembers)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformType(ITypeAnalyzationResult rootTypeResult, INamespaceTransformationMetadata namespaceMetadata)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformNamespace(INamespaceAnalyzationResult rootResult)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformDocument(IDocumentAnalyzationResult documentResult)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.<>c__DisplayClass18_0.<Transform>g__TransfromDocument0(IDocumentAnalyzationResult document)
     [exec]    à System.Threading.Tasks.Parallel.<>c__DisplayClass42_0`2.<PartitionerForEachWorker>b__1()
     [exec]    à System.Threading.Tasks.Task.InnerInvoke()
     [exec]    à System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
     [exec]    à System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object )
     [exec]    --- Fin de la trace de la pile d'exception interne ---
     [exec]    à System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
     [exec]    à System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
     [exec]    à System.Threading.Tasks.Task.Wait()
     [exec]    à System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 simpleBody, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
     [exec]    à System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
     [exec]    à System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, Action`1 body)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.Transform(IProjectAnalyzationResult analyzationResult)
     [exec]    à AsyncGenerator.AsyncCodeGenerator.TransformProject(IProjectAnalyzationResult analyzationResult, ProjectTransformConfiguration configuration)
     [exec]    à AsyncGenerator.AsyncCodeGenerator.<GenerateProject>d__3.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.AsyncCodeGenerator.<GenerateAsync>d__1.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à AsyncGenerator.CommandLine.Program.Main(String[] args)
     [exec] ---> (Exception interne #0) System.InvalidCastException: Impossible d'effectuer un cast d'un objet de type 'Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax' en type 'Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax'.
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SeparatedSyntaxList`1 list)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitArgumentList(ArgumentListSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitInvocationExpression(InvocationExpressionSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExpressionStatement(ExpressionStatementSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SyntaxList`1 list)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitBlock(BlockSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitSimpleLambdaExpression(SimpleLambdaExpressionSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SimpleLambdaExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitArgument(ArgumentSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SeparatedSyntaxList`1 list)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitArgumentList(ArgumentListSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitInvocationExpression(InvocationExpressionSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitExpressionStatement(ExpressionStatementSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitListElement[TNode](TNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitList[TNode](SyntaxList`1 list)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitBlock(BlockSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.ConstructorDeclarationSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replacer`1.Visit(SyntaxNode node)
     [exec]    à Microsoft.CodeAnalysis.CSharp.Syntax.SyntaxReplacer.Replace[TNode](SyntaxNode root, IEnumerable`1 nodes, Func`3 computeReplacementNode, IEnumerable`1 tokens, Func`3 computeReplacementToken, IEnumerable`1 trivia, Func`3 computeReplacementTrivia)
     [exec]    à Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode.ReplaceCore[TNode](IEnumerable`1 nodes, Func`3 computeReplacementNode, IEnumerable`1 tokens, Func`3 computeReplacementToken, IEnumerable`1 trivia, Func`3 computeReplacementTrivia)
     [exec]    à Microsoft.CodeAnalysis.SyntaxNodeExtensions.ReplaceNode[TRoot](TRoot root, SyntaxNode oldNode, SyntaxNode newNode)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformFunction(IFunctionAnalyzationResult rootFuncResult, ITypeTransformationMetadata typeMetadata, INamespaceTransformationMetadata namespaceMetadata)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformSpecialMethod(FunctionTransformationResult methodTransform, TypeDeclarationSyntax newTypeNode, TypeTransformationResult transformResult, INamespaceTransformationMetadata namespaceMetadata, SyntaxTrivia memberWhitespace, Boolean onlyMissingMembers)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformMethodsAndProperties(TypeDeclarationSyntax newTypeNode, TypeTransformationResult transformResult, INamespaceTransformationMetadata namespaceMetadata, SyntaxTrivia memberWhitespace, Boolean onlyMissingMembers)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformType(ITypeAnalyzationResult rootTypeResult, INamespaceTransformationMetadata namespaceMetadata, Boolean onlyMissingMembers)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformType(ITypeAnalyzationResult rootTypeResult, INamespaceTransformationMetadata namespaceMetadata)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformNamespace(INamespaceAnalyzationResult rootResult)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.TransformDocument(IDocumentAnalyzationResult documentResult)
     [exec]    à AsyncGenerator.Transformation.Internal.ProjectTransformer.<>c__DisplayClass18_0.<Transform>g__TransfromDocument0(IDocumentAnalyzationResult document)
     [exec]    à System.Threading.Tasks.Parallel.<>c__DisplayClass42_0`2.<PartitionerForEachWorker>b__1()
     [exec]    à System.Threading.Tasks.Task.InnerInvoke()
     [exec]    à System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
     [exec]    à System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object )<---
     [exec]

BUILD FAILED

E:\Projets\nhibernate\nhibernate-core\default.build(33,4):
External Program Failed: E:\Projets\nhibernate\nhibernate-core\Tools\CSharpAsyncGenerator.CommandLine.0.3.8\tools\AsyncGenerator.CommandLine.exe (return code was -1)

Total time: 337.5 seconds.

Generalize NUnit support as a plugin

There is an NUnitAsyncCountepartFinder and various conversion methods for better tests generation. I think this can be generalized as a plugin.

Minor

Ability to convert properties to async methods

We, unfortunately, have some properties which can be detected as being convertible to async version. Yes, I know that it breaks the "semantic" of being a property, but anyway. Currently AsyncGenerator ignores all properties.

Here is a real life example from NHibernate:

//SessionImpl.cs
public override DbConnection Connection
{
	get { return connectionManager.GetConnection(); }
}

AsyncGenerator generates an async counterpart for connectionManager.GetConnection(), so the property itself becomes convertible to async method. Here is what I want to get:

public override DbConnection GetConnectionAsync()
{
	return connectionManager.GetConnectionAsync();
}

Lacking inherited type generation for newType conversion

Scenario: a base test fixture class defines some settings altering the way all its tests are run. A bunch of other classes inherits that base class and only alters its settings, not containing directly themselves any method to be converted to async. The base test fixture class has its async counterpart generated as a new type.

Expected result: new types are also generated for descendant classes, allowing to have their async counterparts.

But they are not generated.

Minimal example:

using System.Data.Common;
using System.Data.SqlClient;

namespace TestClass
{
    public class BaseClass
    {
        public virtual void Setup()
        {

        }
    }

    public class Class1 : BaseClass
    {
        public virtual bool SomeSetting => false;

        public override void Setup()
        {
            RunSetup();
        }

        public void RunSetup()
        {
            if (SomeSetting)
                using (var c = new SqlConnection(""))
                {
                    c.Open();
                }
        }

        public void Do()
        {
            DbConnection c = null;
            c.Open();
        }
    }

    public class Class2 : Class1
    {
        public override bool SomeSetting => true;
    }
}

With conf

projects:
- filePath: TestClass\TestClass.csproj
  concurrentRun: true
  applyChanges: true
  analyzation:
    methodConversion:
    - conversion: ToAsync
      name: Do
      containingTypeName: Class1
    typeConversion:
    - conversion: NewType
      name: Class1
    - conversion: NewType
      name: Class2
    - conversion: Ignore
      name: BaseClass
    scanMethodBody: true
    scanForMissingAsyncMembers:
    - all: true

Concrete NHibernate case here by example. (Note that adding [TextFixture] attribute on the class does not help. This is another trouble by the way, needing to be fixed on NHibernate side : TextFixture attribute is almost obsolete, NUnit does not need it anymore and many fixtures do not have it already. This causes current NHibernate.Test rules to not generate async tests for those fixtures, like for NH-4004 currently in master.)

NullReferenceException

For some reasons now I'm getting a NullReferenceException when run from console (I was getting it from tests as well, but it disappeared).

The exception:

     [exec] AsyncGenerator
     [exec]
     [exec] 10:50:59,166 INFO  AsyncCodeGenerator:0 - Generating async code started
     [exec] 10:50:59,181 INFO  AsyncCodeGenerator:0 - Configuring solution 'D:\Projects\nhibernate-core\src\NHibernate.s
ln' prior analyzation started
     [exec] 10:51:01,278 INFO  AsyncCodeGenerator:0 - Configuring solution 'D:\Projects\nhibernate-core\src\NHibernate.s
ln' prior analyzation completed
     [exec] 10:51:01,286 INFO  AsyncCodeGenerator:0 - Initializing registered plugins for project 'NHibernate' started
     [exec] 10:51:01,288 INFO  AsyncCodeGenerator:0 - Initializing registered plugins for project 'NHibernate' completed

     [exec] 10:51:01,292 INFO  AsyncCodeGenerator:0 - Analyzing project 'NHibernate' started
     [exec] 10:51:01,307 INFO  ProjectAnalyzer:0 - Parsing documents started
     [exec] 10:51:03,071 INFO  ProjectAnalyzer:0 - Parsing documents completed
     [exec] 10:51:03,073 INFO  ProjectAnalyzer:0 - Pre-analyzing documents started
     [exec] 10:51:05,976 INFO  ProjectAnalyzer:0 - Pre-analyzing documents completed
     [exec] 10:51:05,976 INFO  ProjectAnalyzer:0 - Scanning references started
     [exec] System.NullReferenceException: Object reference not set to an instance of an object.
     [exec]    at AsyncGenerator.Internal.ProjectData.GetFunctionData(IMethodSymbol methodSymbol)
     [exec]    at AsyncGenerator.Internal.ProjectData.GetMethodData(IMethodSymbol symbol)
     [exec]    at AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__33.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    at AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__28.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    at AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__33.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    at AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__28.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    at AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__33.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    at AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__28.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    at AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__33.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    at AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__28.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanDocumentData>d__23.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<Analyze>d__45.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    at AsyncGenerator.AsyncCodeGenerator.<GenerateAsync>d__1.MoveNext()
     [exec] --- End of stack trace from previous location where exception was thrown ---
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    at AsyncGenerator.CommandLine.Program.Main(String[] args)

NetStandard (or NetCore) version?

NHibernate is moving to the NetCore (or NetStandard) worlds, so it would be nice if the tooling would not require having the full .net framework.

I was trying to target netstandard1.6 and the only thing which prevents me to do so is lack of MSBuildWorkspace class.

Override Copy method conversion when type conversion is Partial

Example:

public class PartialCopy
{
    public void Read()
    {
        Copy();
        SimpleFile.Read();
    }

    public void Copy()
    {
        
    }
}

Expected result
The method Copy must not be copied, even if the user set the conversion to Copy.

public partial class PartialCopy
{
    public Task ReadAsync()
    {
        try
        {
            Copy();
            return SimpleFile.ReadAsync();
        }
        catch (Exception ex)
        {
            return Task.FromException<object>(ex);
        }
    }
}

Generalizing as a tool

Currently, the tool is not really useable without an explicit configuration. I was thinking that it is possible to implement some marking attributes.

Do not generate try-catch for "return <literal>;"

The following method has been generated with unnecessary try-catch

public object[] GetNaturalIdentifierSnapshot(object id, ISessionImplementor session)
{
	return null;
}

=>

public Task<object[]> GetNaturalIdentifierSnapshotAsync(object id, ISessionImplementor session, CancellationToken cancellationToken)
{
	try
	{
		return Task.FromResult<object[]>(null);
	}
	catch (Exception ex)
	{
		return Task.FromException<object[]>(ex);
	}
}

NUnitAsyncCounterpartsFinder does not handle ignored returned value

Assert.That(() => query.ToList(), Throws.Exception);

Is converted to:

Assert.That(() => query.ToListAsync(), Throws.Exception);

Instead of:

Assert.That(async () => await query.ToListAsync(), Throws.Exception);

While

List<Dog> list;
Assert.That(() => list = query.ToList(), Throws.Exception);

Is correctly converted to:

List<Dog> list;
Assert.That(async () => list = await query.ToListAsync(), Throws.Exception);

Found with this test. This causes the exception to not occur inside the assertion check and it gets caught by NUnit which report it as failure, instead of being swallowed as being expected.
(But well, the valid syntax still fails as uncaught, and the workaround too, weird... Maybe there is a NUnit bug on top of that. Confirmed : see this.)

No support of -= on events

It seems -= operator is not supported in some cases. When trying to generate async files on the second commit of this NHibernate PR, it fails with message Unknown node kind: SubtractAssignmentExpression.

There was one change concerning a -= in this commit, inside AdoNetWithDistributedTransactionFactory (renamed AdoNetWithSystemTransactionFactory): an event removal has been moved from a local delegate to a class method.

Here is the log for the error.

     [exec] 21:21:39,162 INFO  ProjectAnalyzer:0 - Analyzing documents started
     [exec] 21:21:39,210 WARN  ProjectAnalyzer:0 - Cannot attach an async method to an event (void async is not an option as cannot be awaited):
     [exec] connection.StateChange += Connection_StateChange
     [exec]
     [exec] System.AggregateException: Une ou plusieurs erreurs se sont produites. ---> System.NotSupportedException: Unknown node kind: SubtractAssignmentExpression
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeMethodReference(DocumentData documentData, BodyFunctionReferenceData refData)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeMethodData(DocumentData documentData, MethodOrAccessorData methodAccessorData)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeDocumentData(DocumentData documentData)
     [exec]    à System.Threading.Tasks.Parallel.<>c__DisplayClass30_0`2.<ForEachWorker>b__0(Int32 i)
     [exec]    à System.Threading.Tasks.Parallel.<>c__DisplayClass17_0`1.<ForWorker>b__1()
     [exec]    à System.Threading.Tasks.Task.InnerInvoke()
     [exec]    à System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
     [exec]    à System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object )
     [exec]    --- Fin de la trace de la pile d'exception interne ---
     [exec]    à System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
     [exec]    à System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
     [exec]    à System.Threading.Tasks.Task.Wait()
     [exec]    à System.Threading.Tasks.Parallel.ForWorker[TLocal](Int32 fromInclusive, Int32 toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
     [exec]    à System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](TSource[] array, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
     [exec]    à System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
     [exec]    à System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, Action`1 body)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<Analyze>d__55.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.AsyncCodeGenerator.<GenerateProject>d__3.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.AsyncCodeGenerator.<GenerateAsync>d__1.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à AsyncGenerator.CommandLine.Program.Main(String[] args)
     [exec] ---> (Exception interne #0) System.NotSupportedException: Unknown node kind: SubtractAssignmentExpression
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeMethodReference(DocumentData documentData, BodyFunctionReferenceData refData)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeMethodData(DocumentData documentData, MethodOrAccessorData methodAccessorData)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeDocumentData(DocumentData documentData)
     [exec]    à System.Threading.Tasks.Parallel.<>c__DisplayClass30_0`2.<ForEachWorker>b__0(Int32 i)
     [exec]    à System.Threading.Tasks.Parallel.<>c__DisplayClass17_0`1.<ForWorker>b__1()
     [exec]    à System.Threading.Tasks.Task.InnerInvoke()
     [exec]    à System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
     [exec]    à System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object )<---
     [exec]

BUILD FAILED

E:\Projets\nhibernate\nhibernate-core\default.build(33,4):
External Program Failed: E:\Projets\nhibernate\nhibernate-core\Tools\CSharpAsyncGenerator.CommandLine.0.3.6\tools\AsyncGenerator.CommandLine.exe (return code was -1)

Total time: 46.8 seconds.

Some subsequent commit removes completely that -=, and that generates NHibernate.csproj successfully from that other commit.

ToAsync method conversion of interfaces shall respect callForwarding option

I'm trying to add following to the methodConversion of NHibernate project:

      - conversion: ToAsync
        containingType: NHibernate.Cache.ICache
        name: Get
      - conversion: ToAsync
        containingType: NHibernate.Cache.ICache
        name: Put
      - conversion: ToAsync
        containingType: NHibernate.Cache.ICache
        name: Remove
      - conversion: ToAsync
        containingType: NHibernate.Cache.ICache
        name: Clear
      - conversion: ToAsync
        containingType: NHibernate.Cache.ICache
        name: Lock
      - conversion: ToAsync
        containingType: NHibernate.Cache.ICache
        name: Unlock

I expect it to respect callForwarding option. How do I do that?

Support System.Threading.Tasks.Task methods like GetAwaiter().GetResult()

Convert:

Task.Run(() => DoSomething()).Wait();
Task.Run(() => DoSomething2()).Result;
Task.Run(() => DoSomething3()).GetAwaiter().GetResult();

to

Task.Run(() => DoSomething()).Wait();
Task.Run(() => DoSomething2()).Result;
await Task.Run(() => DoSomething3());

.Wait() and .Result shouldn't be converted to async, because they will throw an AggregateException that contains the actual exception, when an exception occurs.

Support local variables

Convert:

Func<bool> func = DoSomething();
func();

to

Func<Task<bool>> func = DoSomethingAsync();
await func();

Support nameof keyword

The following example:

public class TestCase
{
  [DefaultValue(nameof(Write))]
  public void Write()
  {
    SimpleFile.Write(nameof(DoSomething));
  }

  private void DoSomething()
  {
  }
}

when transfromed into a new type should generate:

public class TestCaseAsync
{
  [DefaultValue(nameof(WriteAsync))]
  public Task WriteAsync()
  {
    return SimpleFile.WriteAsync(nameof(DoSomething));
  }

  private void DoSomething()
  {
  }
}

where nameof(Write) should be converted to nameof(WriteAsync) and DoSomething must be copied as it is referenced by the argument of WriteAsync method

Unknown node kind: MemberBindingExpression

The async generator fails generating NHibernate.Test.csproj with an error Unknown node kind: MemberBindingExpression, when trying to generate it for this PR.

It seems that commenting out NH2420 Fixture file and ResourceManagerFixture dodge the issue.

Partial log:

     [exec] 22:24:02,621 INFO  ProjectAnalyzer:0 - Scanning references completed
     [exec] 22:24:02,621 INFO  ProjectAnalyzer:0 - Analyzing documents started

... truncated for brevity 

     [exec] 22:24:02,729 INFO  ProjectAnalyzer:0 - Cannot await method that is either void or do not return a Task:
     [exec] NUnit.Framework.Assert.Throws<NHibernate.QueryException>(NUnit.Framework.TestDelegate)
     [exec]
     [exec] System.AggregateException: Une ou plusieurs erreurs se sont produites. ---> System.NotSupportedException: Unknown node kind: MemberBindingExpression
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeMethodReference(DocumentData documentData, BodyFunctionReferenceData refData)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeMethodData(DocumentData documentData, MethodOrAccessorData methodAccessorData)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeDocumentData(DocumentData documentData)
     [exec]    à System.Threading.Tasks.Parallel.<>c__DisplayClass30_0`2.<ForEachWorker>b__0(Int32 i)
     [exec]    à System.Threading.Tasks.Parallel.<>c__DisplayClass17_0`1.<ForWorker>b__1()
     [exec]    à System.Threading.Tasks.Task.InnerInvoke()
     [exec]    à System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
     [exec]    à System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object )
     [exec]    --- Fin de la trace de la pile d'exception interne ---
     [exec]    à System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
     [exec]    à System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
     [exec]    à System.Threading.Tasks.Task.Wait()
     [exec]    à System.Threading.Tasks.Parallel.ForWorker[TLocal](Int32 fromInclusive, Int32 toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 localInit, Action`1 localFinally)
     [exec]    à System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](TSource[] array, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
     [exec]    à System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
     [exec]    à System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, Action`1 body)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<Analyze>d__55.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.AsyncCodeGenerator.<GenerateProject>d__3.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.AsyncCodeGenerator.<GenerateAsync>d__1.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à AsyncGenerator.CommandLine.Program.Main(String[] args)
     [exec] ---> (Exception interne #0) System.NotSupportedException: Unknown node kind: MemberBindingExpression
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeMethodReference(DocumentData documentData, BodyFunctionReferenceData refData)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeMethodData(DocumentData documentData, MethodOrAccessorData methodAccessorData)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.AnalyzeDocumentData(DocumentData documentData)
     [exec]    à System.Threading.Tasks.Parallel.<>c__DisplayClass30_0`2.<ForEachWorker>b__0(Int32 i)
     [exec]    à System.Threading.Tasks.Parallel.<>c__DisplayClass17_0`1.<ForWorker>b__1()
     [exec]    à System.Threading.Tasks.Task.InnerInvoke()
     [exec]    à System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
     [exec]    à System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object )<---
     [exec]

BUILD FAILED

E:\Projets\nhibernate\nhibernate-core\default.build(33,4):
External Program Failed: E:\Projets\nhibernate\nhibernate-core\Tools\CSharpAsyncGenerator.CommandLine.0.3.6\tools\AsyncGenerator.CommandLine.exe (return code was -1)

Total time: 249.1 seconds.

Ambiguous candidates symbols not resolved

The syntax return new FutureValue<T>(List<T>, ... where List<T> is a class method seems unsupported if this class method has overloads.

In the tested failing case, the new FutureValue<T>() constructor has no overloads, only List<T> has one.

public IList<T> List<T>() // The one matching
public void List<T>(IList<T> results) // The added one, having triggered the failure

The syntax return new FutureValue<T>(() => List<T>(), ... still allows to dodge the trouble.

This was tested within NHibernate.Impl.CriteriaImpl class. (Local commit not published anywhere currently.)

Error log:

     [exec] 01:07:23,383 WARN  ProjectAnalyzer:0 - Function inside member NHibernate.Action.BulkOperationCleanupAction.AfterTransactionCompletionProcess.get cannot be async because of its kind LambdaMethod
     [exec] System.InvalidOperationException: Unable to find symbol for node List<T> inside function NHibernate.Impl.CriteriaImpl.FutureValue<T>()
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanAllMethodReferenceLocations>d__42.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanMethodData>d__36.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<ScanDocumentData>d__31.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à AsyncGenerator.Analyzation.Internal.ProjectAnalyzer.<Analyze>d__55.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.AsyncCodeGenerator.<GenerateProject>d__3.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
     [exec]    à AsyncGenerator.AsyncCodeGenerator.<GenerateAsync>d__1.MoveNext()
     [exec] --- Fin de la trace de la pile à partir de l'emplacement précédent au niveau duquel l'exception a été levée ---
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     [exec]    à System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     [exec]    à AsyncGenerator.CommandLine.Program.Main(String[] args)

BUILD FAILED

Upgrade Roslyn to 2.3.0 when released

With Roslyn 2.3.0 the static methods of SymbolFinder will be significant faster when calling them multiple times for the same project. As the generator is using those methods quite a lot, the upgrade should speedup the generation for larger projects.

Invalid code generated for newType conversion when ignoring a method

Scenario: a test fixture having its async version generated as a new type. It contains some utility methods for setup and tear-down, methods for which we have no interest in having async counterparts.

Not ignoring them causes the generated async class to contain both the sync and the async version, with the async version usually not used. (Minor nuisance.)
Ignoring them causes the generated async class to not contain the method at all, causing its setup and/or tear-down method to not compile due to missing the sync version of the utility method.

So there is an easy workaround, just not ignore them. Now if we were really needing to ignore a specific method in such case, we would have troubles.

Minimal example:

using System.Data.Common;
using System.Data.SqlClient;

namespace TestClass
{
    public class BaseClass
    {
        public virtual void Setup()
        {

        }
    }

    public class Class1 : BaseClass
    {
        public override void Setup()
        {
            RunSetup();
        }

        public void RunSetup()
        {
            using (var c = new SqlConnection(""))
            {
                c.Open();
            }
        }

        public void Do()
        {
            DbConnection c = null;
            c.Open();
        }
    }
}

With

projects:
- filePath: TestClass\TestClass.csproj
  concurrentRun: true
  applyChanges: true
  analyzation:
    methodConversion:
    - conversion: ToAsync
      name: Do
      containingTypeName: Class1
    - conversion: Ignore
      name: RunSetup
    typeConversion:
    - conversion: NewType
      name: Class1
    - conversion: Ignore
      name: BaseClass
    scanMethodBody: true
    scanForMissingAsyncMembers:
    - all: true

Don't generate un-used private methods

For the following example:

public class TestCase {
    public event Action Event = () => { };

    public void Read() {
        SimpleFile.Read();
        Event += ReadInternal;
    }

    private void ReadInternal() {
        SimpleFile.Read();
    }

    protected void TriggetEvent() {
        Event?.Invoke();
    }
}

the generator shall not generate ReadInternalAsync method as it won't be referenced anywhere.

Extract method body after guards into a separate method

The sync methods with guard exceptions/preconditions shall be split into two methods:

public int Divide(int a, int b) {
   if (b==0) throw new InvalidOperationException();
   return a/b;
}
public Task<int> DivideAsync(int a, int b) {
   if (b==0) throw new InvalidOperationException();
   return DivideInternalAsync(a, b);
}
// Not sure what shall be the order of "Internal" and "Async" postfixes
private async Task<int> DivideInternalAsync (int a, int b) {    
  return await Task.FromResult(a/b);
}

Reduce the usage of SymbolFinder.FindReferencesAsync for methods

By manual profiling, I came to the conclusion that the SymbolFinder.FindReferencesAsync can be called only once for a group of related methods.
Lets see an example by displaying the slowest executions of FindReferencesAsync for the NHibernate test project:

Time: 3596ms, Symbol: NHibernate.Test.TestCase.OnTearDown()
Time: 2294ms, Symbol: NHibernate.Test.TestCase.OnSetUp()
Time: 1675ms, Symbol: NHibernate.Test.NHSpecificTest.NH1642.TrafficRuleSetDAOTest.Scenario.Dispose()
Time: 1485ms, Symbol: NHibernate.Test.FilterTest.DynamicFilterTest.TestData.Dispose()
Time: 1468ms, Symbol: NHibernate.Test.NHSpecificTest.NH2488.Fixture.FetchJoinScenario.Dispose()
Time: 1452ms, Symbol: NHibernate.Test.NHSpecificTest.NH1323.CheckViability.FullInitializedRetrievedEntity.Dispose()
Time: 1434ms, Symbol: NHibernate.Test.NHSpecificTest.NH2489.Fixture.MapScenario.Dispose()
Time: 1431ms, Symbol: NHibernate.Test.NHSpecificTest.NH2565.Fixture.TaskSavedScenario.Dispose()
Time: 1427ms, Symbol: NHibernate.Test.NHSpecificTest.NH2488.Fixture.FetchSelectScenario.Dispose()
Time: 1413ms, Symbol: NHibernate.Test.NHSpecificTest.NH2587.CachingWithLinq.Scenario.Dispose()
Time: 1409ms, Symbol: NHibernate.Test.NHSpecificTest.NH2673.CachingWithTransformerTests.Scenario.Dispose()
Time: 1404ms, Symbol: NHibernate.Test.PolymorphicGetAndLoad.PolymorphicGetAndLoadTest.ScenarioWithA.Dispose()
Time: 1403ms, Symbol: NHibernate.Test.NHSpecificTest.NH2488.Fixture.JoinedSubclassScenario.Dispose()
Time: 1397ms, Symbol: NHibernate.Test.NHSpecificTest.NH2603.Fixture.MapScenario.Dispose()
Time: 1389ms, Symbol: NHibernate.Test.PolymorphicGetAndLoad.PolymorphicGetAndLoadTest.ScenarioWithB.Dispose()
Time: 1384ms, Symbol: NHibernate.Test.NHSpecificTest.NH2510.Fixture.Scenario.Dispose()
Time: 1382ms, Symbol: NHibernate.Test.NHSpecificTest.NH2228.Fixture.ParentWithTwoChildrenScenario.Dispose()
Time: 1372ms, Symbol: NHibernate.Test.NHSpecificTest.NH2489.Fixture.ListScenario.Dispose()
Time: 1370ms, Symbol: NHibernate.Test.NHSpecificTest.NH2324.BulkUpdateWithCustomCompositeType.Scenario.Dispose()
Time: 1369ms, Symbol: NHibernate.Test.NHSpecificTest.NH2603.Fixture.ListScenario.Dispose()
Time: 1364ms, Symbol: NHibernate.Test.NHSpecificTest.NH2632.Fixture.Scenario.Dispose()
Time: 1363ms, Symbol: NHibernate.Test.NHSpecificTest.NH2505.Fixture.Scenario.Dispose()
Time: 1030ms, Symbol: NHibernate.Test.TestCase.Configure(NHibernate.Cfg.Configuration)
Time: 861ms, Symbol: NHibernate.IQuery.UniqueResult<T>()
Time: 670ms, Symbol: NHibernate.Connection.IConnectionProvider.GetConnection()
Time: 334ms, Symbol: NHibernate.IStatelessSession.Insert(object)
Time: 286ms, Symbol: NHibernate.Type.TicksType.Seed(NHibernate.Engine.ISessionImplementor)
Time: 281ms, Symbol: NUnit.Framework.Assert.That(NUnit.Framework.TestDelegate, NUnit.Framework.Constraints.IResolveConstraint)
Time: 256ms, Symbol: NHibernate.Type.Int64Type.Seed(NHibernate.Engine.ISessionImplementor)
Time: 246ms, Symbol: NHibernate.Type.Int64Type.Next(object, NHibernate.Engine.ISessionImplementor)
Time: 235ms, Symbol: System.Data.Common.DbCommand.ExecuteNonQuery()
Time: 233ms, Symbol: NHibernate.Id.NativeGuidGenerator.Generate(NHibernate.Engine.ISessionImplementor, object)
Time: 231ms, Symbol: NHibernate.Id.IIdentifierGenerator.Generate(NHibernate.Engine.ISessionImplementor, object)
Time: 227ms, Symbol: NHibernate.Type.Int16Type.Next(object, NHibernate.Engine.ISessionImplementor)
Time: 226ms, Symbol: NHibernate.Type.DateTimeOffsetType.Next(object, NHibernate.Engine.ISessionImplementor)
Time: 223ms, Symbol: NHibernate.Type.DateTimeOffsetType.Seed(NHibernate.Engine.ISessionImplementor)
Time: 217ms, Symbol: NHibernate.Type.Int32Type.Seed(NHibernate.Engine.ISessionImplementor)
Time: 216ms, Symbol: NHibernate.Type.TimestampType.Next(object, NHibernate.Engine.ISessionImplementor)
Time: 214ms, Symbol: NHibernate.Type.TimeSpanType.Seed(NHibernate.Engine.ISessionImplementor)
Time: 212ms, Symbol: NHibernate.Type.Int16Type.Seed(NHibernate.Engine.ISessionImplementor)
Time: 211ms, Symbol: NHibernate.Type.TimeAsTimeSpanType.Seed(NHibernate.Engine.ISessionImplementor)
Time: 211ms, Symbol: NHibernate.Type.DateTimeType.Seed(NHibernate.Engine.ISessionImplementor)
Time: 208ms, Symbol: NHibernate.Type.DateTimeType.Next(object, NHibernate.Engine.ISessionImplementor)
Time: 207ms, Symbol: NHibernate.Type.TimeAsTimeSpanType.Next(object, NHibernate.Engine.ISessionImplementor)
Time: 207ms, Symbol: NHibernate.Type.TimestampType.Seed(NHibernate.Engine.ISessionImplementor)
Time: 206ms, Symbol: NHibernate.Type.TicksType.Next(object, NHibernate.Engine.ISessionImplementor)
Time: 202ms, Symbol: NHibernate.Type.TimeSpanType.Next(object, NHibernate.Engine.ISessionImplementor)
Time: 202ms, Symbol: NHibernate.Type.Int32Type.Next(object, NHibernate.Engine.ISessionImplementor)
Time: 200ms, Symbol: NHibernate.Type.IVersionType.Seed(NHibernate.Engine.ISessionImplementor)

In the above output we can see that for example getting references for Dispose method took approx. 1.4 seconds and the result (not displayed) contains not only the references of the passed method but also for the implemented interface IDisposable.Dispose. So the idea is to skip the call when we detect if any of the related method was already searched.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.