コード例 #1
0
 public static SyntaxNode FixLambda(SyntaxNode root, LambdaExpressionSyntax lambda, CSharpSyntaxNode newBody)
 {
     var simpleLambda = lambda as SimpleLambdaExpressionSyntax;
     var parenthesizedLambda = lambda as ParenthesizedLambdaExpressionSyntax;
     if (simpleLambda != null)
     {
         return root.ReplaceNode(lambda, simpleLambda
             .WithAsyncKeyword(Token(SyntaxKind.AsyncKeyword).WithTrailingTrivia(Space))
             .WithBody(newBody));
     }
     else
     {
         return root.ReplaceNode(lambda, parenthesizedLambda
             .WithAsyncKeyword(Token(SyntaxKind.AsyncKeyword).WithTrailingTrivia(Space))
             .WithBody(newBody));
     }
 }
コード例 #2
0
        private void AnalyzeLambda(SyntaxNodeAnalysisContext context)
        {
            LambdaExpressionSyntax lambdaExpressionSyntax = (LambdaExpressionSyntax)context.Node;

            if (lambdaExpressionSyntax.AsyncKeyword.Kind() != SyntaxKind.AsyncKeyword)
            {
                return;
            }

            var retValType = context.SemanticModel.GetSymbolInfo(lambdaExpressionSyntax);

            if (retValType.Symbol is null)
            {
                return;
            }

            if (retValType.Symbol is IMethodSymbol method && method.ReturnType.SpecialType == SpecialType.System_Void)
            {
                context.ReportDiagnostic(Diagnostic.Create(Rule, lambdaExpressionSyntax.GetLocation()));
            }
        }
コード例 #3
0
        public static Task <Document> RefactorAsync(
            Document document,
            LambdaExpressionSyntax lambdaExpressionSyntax,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            if (lambdaExpressionSyntax == null)
            {
                throw new ArgumentNullException(nameof(lambdaExpressionSyntax));
            }

            LambdaExpressionSyntax newLambda = Refactor(lambdaExpressionSyntax)
                                               .WithTriviaFrom(lambdaExpressionSyntax)
                                               .WithFormatterAnnotation();

            return(document.ReplaceNodeAsync(lambdaExpressionSyntax, newLambda, cancellationToken));
        }
コード例 #4
0
ファイル: WhereRewriter.cs プロジェクト: yitaom2/ravendb
        private static SyntaxNode HandleMethod(LambdaExpressionSyntax node, InvocationExpressionSyntax invocation, string method)
        {
            switch (method)
            {
            case "Any":
            case "All":
            case "First":
            case "FirstOrDefault":
            case "Last":
            case "LastOfDefault":
            case "Single":
            case "Where":
            case "Count":
            case "SingleOrDefault":
            case "TakeWhile":
            case "SkipWhile":
                return(ModifyLambdaForBools(node));
            }

            return(node);
        }
コード例 #5
0
ファイル: LocalBinderFactory.cs プロジェクト: shashinh/roslyn
        private void VisitLambdaExpression(LambdaExpressionSyntax node)
        {
            // Do not descend into a lambda unless it is a root node
            if (_root != node)
            {
                return;
            }

            CSharpSyntaxNode body = node.Body;

            if (body.Kind() == SyntaxKind.Block)
            {
                VisitBlock((BlockSyntax)body);
            }
            else
            {
                var binder = new PatternVariableBinder(body, _enclosing);
                AddToMap(body, binder);
                Visit(body, binder);
            }
        }
コード例 #6
0
        private static LambdaExpressionSyntax WithExpressionBody(LambdaExpressionSyntax declaration)
        {
            if (!TryConvertToExpressionBody(
                    declaration, declaration.SyntaxTree.Options, ExpressionBodyPreference.WhenPossible,
                    out var expressionBody, out _))
            {
                return(declaration);
            }

            var updatedDecl = declaration.WithBody(expressionBody);

            // If there will only be whitespace between the arrow and the body, then replace that
            // with a single space so that the lambda doesn't have superfluous newlines in it.
            if (declaration.ArrowToken.TrailingTrivia.All(t => t.IsWhitespaceOrEndOfLine()) &&
                expressionBody.GetLeadingTrivia().All(t => t.IsWhitespaceOrEndOfLine()))
            {
                updatedDecl = updatedDecl.WithArrowToken(updatedDecl.ArrowToken.WithTrailingTrivia(SyntaxFactory.ElasticSpace));
            }

            return(updatedDecl);
        }
        private static async Task <Document> ConvertAnonymousMethodToLambdaExpressionAsync(
            Document document,
            AnonymousMethodExpressionSyntax anonymousMethod,
            CancellationToken cancellationToken)
        {
            SyntaxNode oldRoot = await document.GetSyntaxRootAsync(cancellationToken);

            LambdaExpressionSyntax lambda = ParenthesizedLambdaExpression(
                anonymousMethod.AsyncKeyword,
                anonymousMethod.ParameterList,
                Token(SyntaxKind.EqualsGreaterThanToken),
                anonymousMethod.Block);

            lambda = SimplifyLambdaExpressionRefactoring.SimplifyLambdaExpression(lambda)
                     .WithTriviaFrom(anonymousMethod)
                     .WithAdditionalAnnotations(Formatter.Annotation);

            SyntaxNode newRoot = oldRoot.ReplaceNode(anonymousMethod, lambda);

            return(document.WithSyntaxRoot(newRoot));
        }
コード例 #8
0
        public static bool CanRefactor(LambdaExpressionSyntax lambda)
        {
            if (lambda == null)
            {
                throw new ArgumentNullException(nameof(lambda));
            }

            if (lambda.Body?.IsKind(SyntaxKind.Block) == true)
            {
                var block = (BlockSyntax)lambda.Body;

                if (block.Statements.Count == 1)
                {
                    StatementSyntax statement = block.Statements[0];

                    if (statement.IsKind(SyntaxKind.ReturnStatement, SyntaxKind.ExpressionStatement))
                    {
                        ExpressionSyntax expression = GetExpression(statement);

                        if (expression?.IsSingleLine() == true)
                        {
                            TextSpan span = TextSpan.FromBounds(lambda.ArrowToken.Span.End, expression.Span.Start);

                            if (lambda
                                .DescendantTrivia(span)
                                .All(f => f.IsWhitespaceOrEndOfLineTrivia()))
                            {
                                span = TextSpan.FromBounds(expression.Span.End, block.Span.End);

                                return(lambda
                                       .DescendantTrivia(span)
                                       .All(f => f.IsWhitespaceOrEndOfLineTrivia()));
                            }
                        }
                    }
                }
            }

            return(false);
        }
コード例 #9
0
        public static Task <Document> RefactorAsync(
            Document document,
            LambdaExpressionSyntax lambda,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var              block      = (BlockSyntax)lambda.Body;
            StatementSyntax  statement  = block.Statements[0];
            ExpressionSyntax expression = GetNewExpression(statement).WithoutTrivia();

            LambdaExpressionSyntax newLambda = GetNewLambda()
                                               .WithTriviaFrom(lambda)
                                               .WithFormatterAnnotation();

            return(document.ReplaceNodeAsync(lambda, newLambda, cancellationToken));

            LambdaExpressionSyntax GetNewLambda()
            {
                switch (lambda.Kind())
                {
                case SyntaxKind.SimpleLambdaExpression:
                {
                    return(((SimpleLambdaExpressionSyntax)lambda)
                           .WithArrowToken(lambda.ArrowToken.WithTrailingTrivia(TriviaList(Space)))
                           .WithBody(expression));
                }

                case SyntaxKind.ParenthesizedLambdaExpression:
                {
                    return(((ParenthesizedLambdaExpressionSyntax)lambda)
                           .WithArrowToken(lambda.ArrowToken.WithTrailingTrivia(TriviaList(Space)))
                           .WithBody(expression));
                }

                default:
                {
                    throw new InvalidOperationException();
                }
                }
            }
        }
コード例 #10
0
        private async Task <Document> RegenerateDefaultMappingsAsync(
            Document document,
            LambdaExpressionSyntax lambda,
            string automappableMembers,
            CancellationToken cancellationToken)
        {
            var parsedMappableMembers = automappableMembers
                                        .Split(';')
                                        .Where(x => string.IsNullOrWhiteSpace(x) == false)
                                        .ToArray();

            var sourceIdentifierName = lambda
                                       .ChildNodes().OfType <ParameterListSyntax>().Single()
                                       .ChildNodes().OfType <ParameterSyntax>().Single()
                                       .ChildTokens().Single().ToString().Trim();

            var preparedNames = parsedMappableMembers
                                .Select(x => $"{x}={sourceIdentifierName}.{x},\r\n")
                                .ToArray();

            var preparedJoinedNames = string.Join("", preparedNames);

            var newInitializerText =
                $@"new X{{
{preparedJoinedNames}}}";

            var newInitializer = ((ObjectCreationExpressionSyntax)SF.ParseExpression(newInitializerText))
                                 .ChildNodes().OfType <InitializerExpressionSyntax>().Single();

            var oldInitializer = lambda
                                 .ChildNodes().OfType <ObjectCreationExpressionSyntax>().Single()
                                 .ChildNodes().OfType <InitializerExpressionSyntax>().Single();

            var newRawLambda = lambda.ReplaceNode(oldInitializer, newInitializer);

            document = await ParseSyntaxTextAndReplaceNode(document, lambda, newRawLambda, cancellationToken);

            return(document);
        }
コード例 #11
0
        private static LambdaExpressionSyntax WithBlockBody(
            SemanticModel semanticModel, LambdaExpressionSyntax originalDeclaration, LambdaExpressionSyntax currentDeclaration, ExpressionSyntax expressionBody)
        {
            var createReturnStatementForExpression = CreateReturnStatementForExpression(
                semanticModel, originalDeclaration);

            if (!expressionBody.TryConvertToStatement(
                    semicolonTokenOpt: null,
                    createReturnStatementForExpression,
                    out var statement))
            {
                return(currentDeclaration);
            }

            // If the user is converting to a block, it's likely they intend to add multiple
            // statements to it.  So make a multi-line block so that things are formatted properly
            // for them to do so.
            return(currentDeclaration.WithBody(SyntaxFactory.Block(
                                                   SyntaxFactory.Token(SyntaxKind.OpenBraceToken).WithAppendedTrailingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed),
                                                   SyntaxFactory.SingletonList(statement),
                                                   SyntaxFactory.Token(SyntaxKind.CloseBraceToken))));
        }
コード例 #12
0
        private LocalFunctionStatementSyntax CreateLocalFunctionStatement(
            LocalDeclarationStatementSyntax localDeclaration,
            LambdaExpressionSyntax lambda,
            INamedTypeSymbol delegateType,
            ParameterListSyntax parameterList,
            CancellationToken cancellationToken)
        {
            var modifiers = lambda.AsyncKeyword.IsKind(SyntaxKind.AsyncKeyword)
                ? new SyntaxTokenList(lambda.AsyncKeyword)
                : default;

            var invokeMethod = delegateType.DelegateInvokeMethod;

            // We add a space directly after the return-type, as the default presence of an elastic
            // trivia makes the formatting engine thing it can take a single-line local function and
            // wrap it over multiple lines.
            var returnType = invokeMethod.GenerateReturnTypeSyntax().WithTrailingTrivia(SyntaxFactory.Space);

            var identifier        = localDeclaration.Declaration.Variables[0].Identifier;
            var typeParameterList = default(TypeParameterListSyntax);

            var constraintClauses = default(SyntaxList <TypeParameterConstraintClauseSyntax>);

            var body = lambda.Body.IsKind(SyntaxKind.Block)
                ? (BlockSyntax)lambda.Body
                : null;

            var expressionBody = lambda.Body is ExpressionSyntax expression
                ? SyntaxFactory.ArrowExpressionClause(lambda.ArrowToken, expression)
                : null;

            var semicolonToken = lambda.Body is ExpressionSyntax
                ? localDeclaration.SemicolonToken
                : default;

            return(SyntaxFactory.LocalFunctionStatement(
                       modifiers, returnType, identifier, typeParameterList, parameterList,
                       constraintClauses, body, expressionBody, semicolonToken));
        }
コード例 #13
0
        private static SyntaxNode ModifyLambdaForSelect(LambdaExpressionSyntax node, InvocationExpressionSyntax currentInvocation)
        {
            var parentMethod = GetParentMethod(currentInvocation);

            switch (parentMethod)
            {
            case "GroupBy":
                return(SyntaxFactory.ParseExpression($"(Func<IGrouping<dynamic, dynamic>, dynamic>)({node})"));

            default:
            {
                if (node is SimpleLambdaExpressionSyntax)
                {
                    return(SyntaxFactory.ParseExpression($"(Func<dynamic, dynamic>)({node})"));
                }
                else
                {
                    return(SyntaxFactory.ParseExpression($"(Func<dynamic, int, dynamic>)({node})"));
                }
            }
            }
        }
コード例 #14
0
        private LocalFunctionStatementSyntax CreateLocalFunctionStatement(
            LocalDeclarationStatementSyntax localDeclaration,
            LambdaExpressionSyntax lambda,
            INamedTypeSymbol delegateType,
            ParameterListSyntax parameterList,
            CancellationToken cancellationToken)
        {
            var modifiers = lambda.AsyncKeyword.IsKind(SyntaxKind.AsyncKeyword)
                ? new SyntaxTokenList(lambda.AsyncKeyword)
                : default;

            var invokeMethod = delegateType.DelegateInvokeMethod;

            var returnType = invokeMethod.ReturnsVoid
                ? s_voidType
                : invokeMethod.ReturnType.GenerateTypeSyntax();

            var identifier        = localDeclaration.Declaration.Variables[0].Identifier;
            var typeParameterList = default(TypeParameterListSyntax);

            var constraintClauses = default(SyntaxList <TypeParameterConstraintClauseSyntax>);

            var body = lambda.Body.IsKind(SyntaxKind.Block)
                ? (BlockSyntax)lambda.Body
                : null;

            var expressionBody = lambda.Body is ExpressionSyntax expression
                ? SyntaxFactory.ArrowExpressionClause(lambda.ArrowToken, expression)
                : null;

            var semicolonToken = lambda.Body is ExpressionSyntax
                ? localDeclaration.SemicolonToken
                : default;

            return(SyntaxFactory.LocalFunctionStatement(
                       modifiers, returnType, identifier, typeParameterList, parameterList,
                       constraintClauses, body, expressionBody, semicolonToken));
        }
コード例 #15
0
        private LocalFunctionStatementSyntax ConvertLambda(LambdaExpressionSyntax node)
        {
            LambdaExpressionSyntax visited;
            ParameterListSyntax    parameterList;

            switch (node)
            {
            case ParenthesizedLambdaExpressionSyntax parLambda: {
                var v = (ParenthesizedLambdaExpressionSyntax)base.VisitParenthesizedLambdaExpression(parLambda);
                parameterList = v.ParameterList;
                visited       = v;
                break;
            }

            case SimpleLambdaExpressionSyntax simpleLambda: {
                var v = (SimpleLambdaExpressionSyntax)base.VisitSimpleLambdaExpression(simpleLambda);
                parameterList = SyntaxFactory.ParameterList(
                    SyntaxFactory.SingletonSeparatedList(v.Parameter)
                    );
                visited = v;
                break;
            }

            default:
                throw new NotImplementedException();
            }
            if (_lambdaNumbersDict.TryGetValue(node, out var index))
            {
                return(SyntaxFactory.LocalFunctionStatement(GetDummyMethodReturnType(), $"lambda__{index}")
                       .NormalizeWhitespace()
                       .WithParameterList(parameterList)
                       .WithBody((BlockSyntax)visited.Body));
            }
            else
            {
                throw new Exception();
            }
        }
コード例 #16
0
        private SyntaxNode HandleMethod(LambdaExpressionSyntax node, InvocationExpressionSyntax invocation, string method)
        {
            switch (method)
            {
            case "Select":
            case "ToDictionary":
            case "GroupBy":
            case "OrderBy":
            case "OrderByDescending":
            case "Recurse":
                return(Visit(ModifyLambdaForSelect(node, invocation)));

            case "SelectMany":
                return(ModifyLambdaForSelectMany(node, invocation));

            case "Sum":
            case "Average":
                return(Visit(ModifyLambdaForNumerics(node)));

            case "Max":
            case "Min":
                return(Visit(ModifyLambdaForMinMax(node)));

            case "Any":
            case "All":
            case "First":
            case "FirstOrDefault":
            case "Last":
            case "LastOfDefault":
            case "Single":
            case "Where":
            case "Count":
            case "SingleOrDefault":
                return(Visit(ModifyLambdaForBools(node)));
            }

            return(node);
        }
コード例 #17
0
        private static bool CreateReturnStatementForExpression(
            SemanticModel semanticModel,
            LambdaExpressionSyntax declaration
            )
        {
            var lambdaType = (INamedTypeSymbol)semanticModel.GetTypeInfo(declaration).ConvertedType;

            if (lambdaType.DelegateInvokeMethod.ReturnsVoid)
            {
                return(false);
            }

            // 'async Task' is effectively a void-returning lambda.  we do not want to create
            // 'return statements' when converting.
            if (declaration.AsyncKeyword != default)
            {
                var returnType = lambdaType.DelegateInvokeMethod.ReturnType;
                if (returnType.IsErrorType())
                {
                    // "async Goo" where 'Goo' failed to bind.  If 'Goo' is 'Task' then it's
                    // reasonable to assume this is just a missing 'using' and that this is a true
                    // "async Task" lambda.  If the name isn't 'Task', then this looks like a
                    // real return type, and we should use return statements.
                    return(returnType.Name != nameof(Task));
                }

                var taskType = semanticModel.Compilation.GetTypeByMetadataName(
                    typeof(Task).FullName
                    );
                if (returnType.Equals(taskType))
                {
                    // 'async Task'.  definitely do not create a 'return' statement;
                    return(false);
                }
            }

            return(true);
        }
        private static bool CanOfferUseExpressionBody(
            ExpressionBodyPreference preference, LambdaExpressionSyntax declaration, LanguageVersion languageVersion)
        {
            var userPrefersExpressionBodies = preference != ExpressionBodyPreference.Never;

            if (!userPrefersExpressionBodies)
            {
                // If the user doesn't even want expression bodies, then certainly do not offer.
                return(false);
            }

            var expressionBody = GetBodyAsExpression(declaration);

            if (expressionBody != null)
            {
                // they already have an expression body.  so nothing to do here.
                return(false);
            }

            // They don't have an expression body.  See if we could convert the block they
            // have into one.
            return(TryConvertToExpressionBody(declaration, languageVersion, preference, out _, out _));
        }
コード例 #19
0
        private static ExpressionSyntax RemoveAsyncKeywordFromLambdaExpression(LambdaExpressionSyntax lambdaExpression,
                                                                               AwaitExpressionSyntax awaitExpression)
        {
            var simpleLambdaExpression = lambdaExpression as SimpleLambdaExpressionSyntax;

            if (simpleLambdaExpression != null)
            {
                return(simpleLambdaExpression.ReplaceNode(awaitExpression, awaitExpression.Expression)
                       .WithAsyncKeyword(default(SyntaxToken))
                       .WithLeadingTrivia(simpleLambdaExpression.AsyncKeyword.LeadingTrivia));
            }

            var parenthesizedLambdaExpression = lambdaExpression as ParenthesizedLambdaExpressionSyntax;

            if (parenthesizedLambdaExpression != null)
            {
                return(parenthesizedLambdaExpression.ReplaceNode(awaitExpression, awaitExpression.Expression)
                       .WithAsyncKeyword(default(SyntaxToken))
                       .WithLeadingTrivia(parenthesizedLambdaExpression.AsyncKeyword.LeadingTrivia));
            }

            return(lambdaExpression);
        }
コード例 #20
0
            private void LambdaExpressionHandler(LambdaExpressionSyntax node)
            {
                LambdaMetricsResults.LambdaCount++;

                IEnumerable <IdentifierNameSyntax> variablesUsed = node
                                                                   .DescendantNodes()
                                                                   .OfType <IdentifierNameSyntax>();

                foreach (IdentifierNameSyntax variableUsed in variablesUsed)
                {
                    var symbol = _semanticModel.GetSymbolInfo(variableUsed);

                    if (symbol.Symbol is null)
                    {
                        continue;
                    }

                    switch (symbol.Symbol.Kind)
                    {
                    case SymbolKind.Local when !((ILocalSymbol)symbol.Symbol).HasConstantValue:
                        LambdaMetricsResults.LocalVariableUsageCount++;
                        break;

                    case SymbolKind.Field when !((IFieldSymbol)symbol.Symbol).HasConstantValue:
                        LambdaMetricsResults.FieldVariableUsageCount++;
                        break;

                    default:
                        continue;
                    }

                    if (IsMutated(variableUsed))
                    {
                        LambdaMetricsResults.SideEffects++;
                    }
                }
            }
コード例 #21
0
        public static void Write(LambdaExpressionSyntax syntax, IIndentedTextWriterWrapper textWriter, IContext context)
        {
            var symbol = GetSymbolForParentUsingTheLambda(syntax, context);

            context.TypeReferenceWriter.WriteInteractionElementReference(symbol, textWriter);
            textWriter.Write("._C_0_16704"); // Lua.Function as argument
            textWriter.Write("(function(");

            if (syntax is SimpleLambdaExpressionSyntax)
            {
                ((SimpleLambdaExpressionSyntax)syntax).Parameter.Write(textWriter, context);
            }
            else
            {
                ((ParenthesizedLambdaExpressionSyntax)syntax).ParameterList.Write(textWriter, context);
            }

            textWriter.Write(")");

            if (syntax.Body is BlockSyntax)
            {
                textWriter.WriteLine("");
                ((BlockSyntax)syntax.Body).Write(textWriter, context);
            }
            else
            {
                if (!(syntax.Body is AssignmentExpressionSyntax))
                {
                    textWriter.Write(" return ");
                }

                syntax.Body.Write(textWriter, context);
                textWriter.Write(" ");
            }

            textWriter.Write("end)");
        }
        private static bool ShouldIncludeReturnStatement(
            SemanticDocument document,
            LambdaExpressionSyntax oldLambda,
            CancellationToken cancellationToken)
        {
            if (document.SemanticModel.GetTypeInfo(oldLambda, cancellationToken).ConvertedType is INamedTypeSymbol delegateType &&
                delegateType.DelegateInvokeMethod != null)
            {
                if (delegateType.DelegateInvokeMethod.ReturnsVoid)
                {
                    return(false);
                }

                // Async lambdas with a Task or ValueTask return type don't need a return statement.
                // e.g.:
                //     Func<int, Task> f = async x => await M2();
                //
                // After refactoring:
                //     Func<int, Task> f = async x =>
                //     {
                //         Task task = M2();
                //         await task;
                //     };
                var compilation        = document.SemanticModel.Compilation;
                var delegateReturnType = delegateType.DelegateInvokeMethod.ReturnType;
                if (oldLambda.AsyncKeyword != default && delegateReturnType != null)
                {
                    if ((compilation.TaskType() != null && delegateReturnType.Equals(compilation.TaskType())) ||
                        (compilation.ValueTaskType() != null && delegateReturnType.Equals(compilation.ValueTaskType())))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
コード例 #23
0
 private static SyntaxNode ModifyLambdaForPredicates(LambdaExpressionSyntax node)
 {
     return(SyntaxFactory.ParseExpression($"(Predicate<dynamic>)({node})"));
 }
コード例 #24
0
        // Shared code needed by all parts of the style provider for this feature.

        private static ExpressionSyntax GetBodyAsExpression(LambdaExpressionSyntax declaration)
        => declaration.Body as ExpressionSyntax;
コード例 #25
0
ファイル: SyntaxInfo.cs プロジェクト: tinoji/Roslynator
 /// <summary>
 /// Creates a new <see cref="Syntax.SingleParameterLambdaExpressionInfo"/> from the specified lambda expression.
 /// </summary>
 /// <param name="lambdaExpression"></param>
 /// <param name="allowMissing"></param>
 /// <returns></returns>
 public static SingleParameterLambdaExpressionInfo SingleParameterLambdaExpressionInfo(
     LambdaExpressionSyntax lambdaExpression,
     bool allowMissing = false)
 {
     return(Syntax.SingleParameterLambdaExpressionInfo.Create(lambdaExpression, allowMissing));
 }
コード例 #26
0
        private static void AnalyzeLambdaInLinqExpression(SyntaxNodeAnalysisContext context, EFUsageContext efContext, LambdaExpressionSyntax lambda)
        {
            var lambdaAssign = lambda.Parent as EqualsValueClauseSyntax;
            var arg = lambda.Parent as ArgumentSyntax;
            if (arg != null) //The lambda in question is being passed as an argument
            {
                var parent = arg.Parent;
                while (parent != null && !(parent is ArgumentListSyntax))
                {
                    parent = parent.Parent;
                }

                if (parent != null) //Which should be part of an ArgumentList
                {
                    var argList = parent;
                    var invoc = argList?.Parent as InvocationExpressionSyntax;
                    if (invoc != null) //Which should be part of an invocation
                    {
                        var memberExpr = invoc.Expression as MemberAccessExpressionSyntax;
                        if (memberExpr != null)
                        {
                            if (CanonicalMethodNames.IsLinqOperator(memberExpr?.Name?.Identifier.ValueText))
                            {
                                var si = context.SemanticModel.GetSymbolInfo(memberExpr.Expression);

                                var lts = si.Symbol as ILocalSymbol;
                                var pts = si.Symbol as IPropertySymbol;
                                //Is this method called on a property?
                                if (pts != null)
                                {
                                    var nts = pts.Type as INamedTypeSymbol;
                                    if (nts != null)
                                    {
                                        //Like a DbSet<T>?
                                        if (nts.IsDbSet())
                                        {
                                            //That is part of a class derived from DbContext?
                                            if (pts?.ContainingType?.BaseType?.Name == EFSpecialIdentifiers.DbContext)
                                            {
                                                var typeArg = nts.TypeArguments[0];
                                                //Let's give our method some assistance, by checking what T actually is
                                                var clsInfo = efContext.GetClassInfo(typeArg);
                                                if (clsInfo != null)
                                                {
                                                    //Okay now let's see if this lambda is valid in the EF context
                                                    LinqExpressionValidator.ValidateLinqToEntitiesExpression(lambda, clsInfo, context, efContext);
                                                }
                                            }
                                        }
                                    }
                                }
                                else if (lts != null) //The linq method was called on a local variable
                                {
                                    var nts = lts.Type as INamedTypeSymbol;
                                    if (nts != null && nts.TypeArguments.Length == 1)
                                    {
                                        //This is some generic type with one type argument
                                        var typeArg = nts.TypeArguments[0];
                                        var clsInfo = efContext.GetClassInfo(typeArg);
                                        if (clsInfo != null)
                                        {
                                            if (nts.IsDbSet())
                                            {
                                                //TODO: Should still actually check that it is ultimately assigned
                                                //from a DbSet<T> property of a DbContext derived class

                                                LinqExpressionValidator.ValidateLinqToEntitiesExpression(lambda, clsInfo, context, efContext);
                                            }
                                            else if (nts.IsQueryable())
                                            {
                                                bool treatAsWarning = !LinqExpressionValidator.SymbolCanBeTracedBackToDbContext(lts, context, efContext, clsInfo);
                                                LinqExpressionValidator.ValidateLinqToEntitiesExpression(lambda, clsInfo, context, efContext, treatAsWarning);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else if (lambdaAssign != null) //The lambda in question is being assigned
            {
                var localLambdaDecl = lambdaAssign?.Parent?.Parent?.Parent as LocalDeclarationStatementSyntax;
                if (localLambdaDecl != null)
                {
                    var declType = localLambdaDecl?.Declaration?.Type as GenericNameSyntax;
                    if (declType != null)
                    {
                        //Is Expression<T>
                        if (declType.Identifier.ValueText == EFSpecialIdentifiers.Expression && declType.TypeArgumentList.Arguments.Count == 1)
                        {
                            //The T is Func<TInput, TOutput>
                            var exprTypeArg = declType.TypeArgumentList.Arguments[0] as GenericNameSyntax;
                            if (exprTypeArg != null &&
                                exprTypeArg.Identifier.ValueText == EFSpecialIdentifiers.Func &&
                                exprTypeArg.TypeArgumentList.Arguments.Count == 2)
                            {
                                var inputType = exprTypeArg.TypeArgumentList.Arguments[0] as IdentifierNameSyntax;
                                var outputType = exprTypeArg.TypeArgumentList.Arguments[1] as PredefinedTypeSyntax;
                                //The TOutput in Func<TInput, TOutput> is bool
                                if (inputType != null && outputType != null && outputType.Keyword.ValueText == EFSpecialIdentifiers.BooleanShort)
                                {
                                    var si = context.SemanticModel.GetSymbolInfo(inputType);
                                    var ts = efContext.EntityTypes.FirstOrDefault(t => t == si.Symbol);
                                    if (ts != null)
                                    {
                                        var clsInfo = efContext.GetClassInfo(ts);
                                        if (clsInfo != null)
                                        {
                                            LinqExpressionValidator.ValidateLinqToEntitiesExpression(lambda, clsInfo, context, efContext);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #27
0
 private static Location GetDiagnosticLocation(LambdaExpressionSyntax declaration)
 => Location.Create(declaration.SyntaxTree,
                    TextSpan.FromBounds(declaration.SpanStart, declaration.ArrowToken.Span.End));
コード例 #28
0
 /// <summary>
 /// Validates the given lambda to see if it is a valid LINQ to Entities expression
 /// </summary>
 /// <param name="lambda">The lambda syntax node</param>
 /// <param name="rootQueryableType">The type of the IQueryable instance where a known LINQ operator is invoked on with this lambda</param>
 /// <param name="context">The analysis context</param>
 /// <param name="efContext">The EF-specific view of the semantic model</param>
 /// <param name="treatAsWarning">If true, instructs any diagnostic reports to be flagged as warnings instead of errors. This is normally true when the analyzer cannot fully determine that the LINQ expression is made against an actual DbSet</param>
 public static void ValidateLinqToEntitiesExpression(LambdaExpressionSyntax lambda, EFCodeFirstClassInfo rootQueryableType, SyntaxNodeAnalysisContext context, EFUsageContext efContext, bool treatAsWarning = false)
 {
     var descendants = lambda.DescendantNodes();
     var parameterNodes = ContextualLinqParameter.BuildContext(descendants.OfType<ParameterSyntax>(), context, efContext);
     ValidateLinqToEntitiesUsageInSyntaxNodes(descendants, rootQueryableType, context, efContext, parameterNodes, treatAsWarning);
 }
コード例 #29
0
ファイル: Rewriter.cs プロジェクト: VitalyTVA/MetaSharp
        LiteralExpressionSyntax VisitLambdaExpression(LambdaExpressionSyntax lambda)
        {
            //TODO check parents and semantic of parents
            //var parents = lambda.GetParents();
            //var argument = lambda.Parent;
            //var symbol = model.GetSymbolInfo(argument.Parent.Parent).Symbol as IMethodSymbol;

            //TODO check lambda expression parameters (1 parameter, type is same as method's generic parameter)
            //TODO custom args order (named parameters)
            //TODO works only for 'Property' methods
            //TODO semantic model checks

            var body = (MemberAccessExpressionSyntax)lambda.Body;
            var property = body.Name.Identifier.Text;
            var literal = SyntaxFactory.Literal(property);
            return SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, literal);
        }
コード例 #30
0
 internal static SingleParameterLambdaExpressionInfo Create(
     LambdaExpressionSyntax lambdaExpression,
     bool allowMissing = false)
 {
     return(CreateImpl(lambdaExpression, allowMissing));
 }
コード例 #31
0
            private bool TryGetLambdaExpressionBodyWithCast(LambdaExpressionSyntax lambdaExpression, LambdaExpressionSyntax newLambdaExpression, out ExpressionSyntax newLambdaExpressionBodyWithCast)
            {
                if (newLambdaExpression.Body is ExpressionSyntax)
                {
                    var body = (ExpressionSyntax)lambdaExpression.Body;
                    var newBody = (ExpressionSyntax)newLambdaExpression.Body;

                    var returnType = (_semanticModel.GetSymbolInfo(lambdaExpression).Symbol as IMethodSymbol)?.ReturnType;
                    if (returnType != null)
                    {
                        return TryCastTo(returnType, body, newBody, out newLambdaExpressionBodyWithCast);
                    }
                }

                newLambdaExpressionBodyWithCast = null;
                return false;
            }
コード例 #32
0
        private static ITypeSymbol GetSymbolForParentUsingTheLambda(LambdaExpressionSyntax syntax, IContext context)
        {
            var argListSyntax = syntax.Ancestors().OfType <ArgumentListSyntax>().FirstOrDefault();

            if (argListSyntax != null)
            {
                var argument = syntax.Ancestors().OfType <ArgumentSyntax>().First();
                var argNum   = argListSyntax.ChildNodes().ToList().IndexOf(argument);

                if (argListSyntax.Parent is InvocationExpressionSyntax)
                {
                    var symbol =
                        (IMethodSymbol)
                        ModelExtensions.GetSymbolInfo(
                            context.SemanticModel,
                            (InvocationExpressionSyntax)argListSyntax.Parent).Symbol;
                    return(symbol.Parameters[argNum].Type);
                }
                else if (argListSyntax.Parent is ObjectCreationExpressionSyntax)
                {
                    var symbol = (IMethodSymbol)context.SemanticModel.GetSymbolInfo(argListSyntax.Parent).Symbol;

                    if (symbol != null)
                    {
                        return(symbol.Parameters[argNum].Type);
                    }

                    var namedTypeSymbol =
                        (INamedTypeSymbol)
                        ModelExtensions.GetSymbolInfo(
                            context.SemanticModel,
                            ((ObjectCreationExpressionSyntax)argListSyntax.Parent).Type).Symbol;

                    if (namedTypeSymbol.TypeKind == TypeKind.Delegate)
                    {
                        return(namedTypeSymbol);
                    }

                    throw new Exception($"Could not guess constructor for {namedTypeSymbol}.");
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            else
            {
                var assignment = syntax.Parent as AssignmentExpressionSyntax;
                if (assignment != null)
                {
                    var s = context.SemanticModel.GetSymbolInfo(assignment.Left).Symbol;
                    var propertySymbol = s as IPropertySymbol;
                    if (propertySymbol != null)
                    {
                        return(propertySymbol.Type);
                    }

                    var fieldSymbol = s as IFieldSymbol;
                    if (fieldSymbol != null)
                    {
                        return(fieldSymbol.Type);
                    }

                    throw new NotImplementedException();
                }
                throw new NotImplementedException();
            }
        }
コード例 #33
0
        private void VisitLambdaExpression(LambdaExpressionSyntax node)
        {
            // Do not descend into a lambda unless it is a root node
            if (_root != node)
            {
                return;
            }

            CSharpSyntaxNode body = node.Body;
            if (body.Kind() == SyntaxKind.Block)
            {
                VisitBlock((BlockSyntax)body);
            }
            else
            {
                var binder = new ExpressionVariableBinder(body, _enclosing);
                AddToMap(body, binder);
                Visit(body, binder);
            }
        }
コード例 #34
0
 private List<LinqStep> InsertExpandedShortcutMethod(List<LinqStep> chain, string methodFullName, LambdaExpressionSyntax lambda)
 {
     var ch = chain.ToList();
     //    var baseExpression = ((MemberAccessExpressionSyntax)chain.First().Expression).Expression;
     ch.Insert(1, new LinqStep(methodFullName, new[] { lambda }));
     return ch;
 }
コード例 #35
0
        private static SyntaxNode ModifyLambdaForAggregate(LambdaExpressionSyntax node)
        {
            var cast = node is SimpleLambdaExpressionSyntax ? "Func<dynamic, dynamic>" : "Func<dynamic, dynamic, dynamic>";

            return(SyntaxFactory.ParseExpression($"({cast})({node})"));
        }
コード例 #36
0
 private static SyntaxNode ModifyLambdaForZip(LambdaExpressionSyntax node)
 {
     return(SyntaxFactory.ParseExpression($"(Func<dynamic, dynamic, dynamic>)({node})"));
 }
コード例 #37
0
            private ITypeSymbol InferTypeForFirstParameterOfLambda(
                LambdaExpressionSyntax lambdaExpression)
            {
                if (lambdaExpression is ParenthesizedLambdaExpressionSyntax)
                {
                    return InferTypeForFirstParameterOfParenthesizedLambda(
                        (ParenthesizedLambdaExpressionSyntax)lambdaExpression);
                }
                else if (lambdaExpression is SimpleLambdaExpressionSyntax)
                {
                    return InferTypeForFirstParameterOfSimpleLambda(
                        (SimpleLambdaExpressionSyntax)lambdaExpression);
                }

                return null;
            }
コード例 #38
0
        private static SyntaxNode ModifyLambdaForTakeSkipWhile(LambdaExpressionSyntax node)
        {
            var cast = node is SimpleLambdaExpressionSyntax ? "Func<dynamic, bool>" : "Func<dynamic, int, bool>";

            return(SyntaxFactory.ParseExpression($"({cast})({node})"));
        }
コード例 #39
0
 private ITypeSymbol InferTypeForFirstParameterOfLambda(
     LambdaExpressionSyntax lambdaExpression, ParameterSyntax parameter)
 {
     return InferTypeForFirstParameterOfLambda(
         parameter.Identifier.ValueText, lambdaExpression.Body);
 }