Example #1
0
        /// <summary>
        /// Construct a new <see cref="Snippet"/> from a string containing a C# expression.
        /// </summary>
        /// <param name="text">String containing a C# expression, possibly with wildcards (single-character variables).</param>
        public Snippet(string?text)
        {
            // TODO: try parsing as statement first?
            Expression = SyntaxFactory.ParseExpression(text);

            // TODO: make this error! just not sure . . . how.

            if (!Expression.DescendantNodes().Any())
            {
                throw new UnknownExpressionException();
            }

            var lc = new Regex(@"^\p{Ll}$");

            var replacementNodes = Expression.DescendantNodes()
                                   .OfType <IdentifierNameSyntax>()
                                   .Where(nameSyntax => lc.IsMatch(nameSyntax.Identifier.ValueText))
                                   .GroupBy(nameSyntax => nameSyntax.Identifier.ValueText);

            SubexpressionIdentifiers = replacementNodes
                                       .Select(g => g.Key)
                                       .ToList();

            if (replacementNodes.Any(g => g.Count() > 1))
            {
                throw  new NotImplementedException("Matching the same subexpression is not yet supported: https://github.com/rainersigwald/bumblebee/issues/4");
            }
        }
Example #2
0
        public void LexicalTokenMatching_Usage()
        {
            var compiler = new RoslynCompiler();
            var lexical  = compiler.Lexical();

            lexical
            .match()
            .any('(', '=', ',')
            .token("function", named: "fn")
            .enclosed('(', ')')
            .token('{', named: "brace")
            .then(compiler.Lexical().transform()
                  .remove("fn")
                  .insert("=>", before: "brace"))
            .match()
            .any(new[] { '(', '=', ',' }, named: "start")
            .enclosed('[', ']', start: "open", end: "close")
            .then(compiler.Lexical().transform()
                  .insert("new []", after: "start")
                  .replace("open", "{")
                  .replace("close", "}"));

            ExpressionSyntax exprFunction = compiler.CompileExpression("call(10, function(x, y) {})");

            Assert.IsTrue(exprFunction.DescendantNodes()
                          .OfType <ParenthesizedLambdaExpressionSyntax>()
                          .Any());

            ExpressionSyntax exprArray = compiler.CompileExpression("call([1, 2, 3], 4, [5, 6, 7])");

            Assert.IsTrue(exprArray.DescendantNodes()
                          .OfType <ImplicitArrayCreationExpressionSyntax>()
                          .Count() == 2);
        }
        private FieldDeclarationSyntax GetStaticField(string name, List <ParameterSyntax> parameterList, TypeSyntax returType, ExpressionSyntax bodyExpression, SemanticModel sm, ITypeSymbol type)
        {
            GenericNameSyntax expressionType = GetExpressionTypeSyntax(parameterList, returType);

            ExpressionSyntax newBody = bodyExpression;

            if (parameterList.Count > 0 & parameterList[0].Identifier.ToString() == "@this")
            {
                newBody = AddImplicitThis(newBody, sm, type);

                newBody = newBody.ReplaceNodes(newBody.DescendantNodes().OfType <ThisExpressionSyntax>().ToList(),
                                               (thisExp, _) => SyntaxFactory.IdentifierName(parameterList[0].Identifier));
            }

            if (newBody.Span.Length > 80)
            {
                newBody = newBody.WithLeadingTrivia(SyntaxFactory.CarriageReturnLineFeed);
            }

            var parameters = parameterList.Select(p => SyntaxFactory.Parameter(p.Identifier)).ToArray();

            var lambda = parameters.Length == 1 ?
                         (LambdaExpressionSyntax)SyntaxFactory.SimpleLambdaExpression(parameters.Single(), newBody) :
                         (LambdaExpressionSyntax)SyntaxFactory.ParenthesizedLambdaExpression(SyntaxFactory.ParameterList().AddParameters(parameters), newBody);

            var variable = SyntaxFactory.VariableDeclaration(expressionType).AddVariables(
                SyntaxFactory.VariableDeclarator(name).WithInitializer(
                    SyntaxFactory.EqualsValueClause(lambda)));

            return(SyntaxFactory.FieldDeclaration(variable).WithModifiers(SyntaxTokenList.Create(SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
                   .NormalizeWhitespace()
                   .WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed));
        }
Example #4
0
 public IdentifierNameSyntax GetMethodIdentifier(ExpressionSyntax invocation, string methodName)
 {
     return(invocation
            .DescendantNodes()
            .OfType <IdentifierNameSyntax>()
            .FirstOrDefault(i => i.WithoutTrivia().ToString() == methodName));
 }
Example #5
0
        public static bool ContainsOutArgumentWithLocal(
            ExpressionSyntax expression,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            foreach (SyntaxNode node in expression.DescendantNodes())
            {
                if (node.Kind() == SyntaxKind.Argument)
                {
                    var argument = (ArgumentSyntax)node;

                    if (argument.RefOrOutKeyword.Kind() == SyntaxKind.OutKeyword)
                    {
                        ExpressionSyntax argumentExpression = argument.Expression;

                        if (argumentExpression?.IsMissing == false &&
                            semanticModel.GetSymbol(argumentExpression, cancellationToken)?.Kind == SymbolKind.Local)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Example #6
0
        public void FunctionUsage()
        {
            RoslynCompiler compiler = new RoslynCompiler();

            Functions.Apply(compiler);
            //XSModule.Apply(compiler);

            //as lambda
            ExpressionSyntax exprFunction = compiler.CompileExpression("call(10, function(x, y) {})");

            Assert.IsTrue(exprFunction.DescendantNodes()
                          .OfType <ParenthesizedLambdaExpressionSyntax>()
                          .Any());

            //as typed method
            string result = compiler.ApplyLexicalPass("class foo { public int function bar(int x) {}}");

            Assert.IsTrue(result == "class foo { public int bar(int x) {}}");

            SyntaxTree tree = null;
            string     text = null;

            //as untyped method
            tree = compiler.ApplySemanticalPass("class foo { public function bar() {}}", out text);
            Assert.IsTrue(tree.GetRoot()
                          .DescendantNodes()
                          .OfType <MethodDeclarationSyntax>()
                          .First()
                          .ReturnType
                          .ToString() == "void"); //must have added a return type


            //as code function
            tree = compiler.ApplySemanticalPass("class foo { public function bar() { function foobar(int x) {return 3;}}}", out text);
            Assert.IsTrue(tree.GetRoot()
                          .DescendantNodes()
                          .OfType <ParenthesizedLambdaExpressionSyntax>()
                          .Any()); //code functions replaced by a lambda declaration

            //as type, without return type
            tree = compiler.ApplySemanticalPass("class foo { void bar() { function<void, string> foobar; }}", out text);
            Assert.IsTrue(tree.GetRoot()
                          .DescendantNodes()
                          .OfType <LocalDeclarationStatementSyntax>()
                          .First()
                          .Declaration
                          .Type
                          .ToString() == "Action<string>"); //must have changed the function type into an action (because of the void)

            //as type, with return type
            tree = compiler.ApplySemanticalPass("class foo { void bar() { function<int, string> foobar; }}", out text);
            Assert.IsTrue(tree.GetRoot()
                          .DescendantNodes()
                          .OfType <LocalDeclarationStatementSyntax>()
                          .First()
                          .Declaration
                          .Type
                          .ToString() == "Func<string,int>"); //must have changed the function type, moving the return type to the end
        }
Example #7
0
        protected ExpressionSyntax RenameIdentifier(ExpressionSyntax expression, string oldName, string newName)
        {
            var identifierNode = expression.DescendantNodes()
                                 .OfType <IdentifierNameSyntax>()
                                 .First(node => node.Identifier.Text == oldName);

            return(expression.ReplaceNode(identifierNode, identifierNode.WithIdentifier(SyntaxFactory.Identifier(newName).WithTriviaFrom(identifierNode.Identifier))));
        }
Example #8
0
        public IdentifierNameSyntax GetMethodIdentifier(ExpressionSyntax invocation)
        {
            var nodes = invocation
                        .DescendantNodes()
                        .OfType <IdentifierNameSyntax>().ToList();

            return(nodes.ElementAtOrDefault(1) ?? nodes.ElementAtOrDefault(0) ?? null);
        }
Example #9
0
        private InvocationExpressionSyntax ReplaceIdentifier(MemberAccessExpressionSyntax mockedObjectIdentifier,
                                                             ParameterSyntax param, ExpressionSyntax lambdaBody)
        {
            var nameToken = lambdaBody.DescendantNodes().OfType <IdentifierNameSyntax>()
                            .First(x => x.Identifier.ValueText == param.Identifier.ValueText);

            return(lambdaBody.ReplaceNode(nameToken, mockedObjectIdentifier) as InvocationExpressionSyntax);
        }
Example #10
0
        public static void AnalyzeNamedType(SymbolAnalysisContext context, INamedTypeSymbol flagsAttribute)
        {
            var enumSymbol = (INamedTypeSymbol)context.Symbol;

            if (enumSymbol.IsEnum() &&
                enumSymbol.HasAttribute(flagsAttribute))
            {
                var infos = default(ImmutableArray <EnumFieldInfo>);

                foreach (ISymbol member in enumSymbol.GetMembers())
                {
                    if (member.IsField())
                    {
                        var fieldSymbol = (IFieldSymbol)member;

                        if (!fieldSymbol.HasConstantValue)
                        {
                            break;
                        }

                        var info = new EnumFieldInfo(fieldSymbol);

                        if (info.IsComposite())
                        {
                            var declaration = (EnumMemberDeclarationSyntax)info.Symbol.GetSyntax(context.CancellationToken);

                            ExpressionSyntax valueExpression = declaration.EqualsValue?.Value;

                            if (valueExpression != null &&
                                (valueExpression.IsKind(SyntaxKind.NumericLiteralExpression) ||
                                 valueExpression
                                 .DescendantNodes()
                                 .Any(f => f.IsKind(SyntaxKind.NumericLiteralExpression))))
                            {
                                if (infos.IsDefault)
                                {
                                    infos = EnumFieldInfo.CreateRange(enumSymbol);

                                    if (infos.IsDefault)
                                    {
                                        break;
                                    }
                                }

                                List <EnumFieldInfo> values = info.Decompose(infos);

                                if (values?.Count > 1)
                                {
                                    context.ReportDiagnostic(
                                        DiagnosticDescriptors.DeclareEnumValueAsCombinationOfNames,
                                        valueExpression);
                                }
                            }
                        }
                    }
                }
            }
        }
Example #11
0
        private (ExpressionSyntax fullInvocation, string identifierToken) PrepandCallToInvocation(IdentifierNameSyntax mockedObjectIdentifier, string prepandCall, ExpressionSyntax lambdaBody)
        {
            var prependInvocation = SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                                                            mockedObjectIdentifier, SyntaxFactory.IdentifierName(prepandCall)));
            var nameToken = lambdaBody.DescendantNodes().First(x => x.Kind() == mockedObjectIdentifier.Kind() && ((IdentifierNameSyntax)x).Identifier.ValueText == mockedObjectIdentifier.Identifier.ValueText);

            var fullInvocation = lambdaBody.ReplaceNode(nameToken, prependInvocation);

            return(fullInvocation, mockedObjectIdentifier.Identifier.ValueText);
        }
Example #12
0
        private BoundExpression BindAggregate(ExpressionSyntax aggregate, BoundAggregateExpression boundAggregate)
        {
            var affectedQueryScopes = aggregate.DescendantNodes()
                                      .Select(GetBoundNode <BoundColumnExpression>)
                                      .Where(n => n != null)
                                      .Select(b => b.Symbol)
                                      .OfType <TableColumnInstanceSymbol>()
                                      .Select(c => FindQueryState(c.TableInstance))
                                      .Distinct()
                                      .Take(2)
                                      .ToImmutableArray();

            if (affectedQueryScopes.Length > 1)
            {
                Diagnostics.ReportAggregateContainsColumnsFromDifferentQueries(aggregate.Span);
            }

            var queryState = affectedQueryScopes.DefaultIfEmpty(QueryState)
                             .First();

            if (queryState == null)
            {
                Diagnostics.ReportAggregateInvalidInCurrentContext(aggregate.Span);
            }
            else
            {
                var existingSlot = FindComputedValue(aggregate, queryState.ComputedAggregates);
                if (existingSlot == null)
                {
                    var slot = ValueSlotFactory.CreateTemporary(boundAggregate.Type);
                    queryState.ComputedAggregates.Add(new BoundComputedValueWithSyntax(aggregate, boundAggregate, slot));
                }
            }

            var aggregateBelongsToCurrentQuery = QueryState == queryState;

            if (InOnClause && aggregateBelongsToCurrentQuery)
            {
                Diagnostics.ReportAggregateInOn(aggregate.Span);
            }
            else if (InWhereClause && aggregateBelongsToCurrentQuery)
            {
                Diagnostics.ReportAggregateInWhere(aggregate.Span);
            }
            else if (InGroupByClause && aggregateBelongsToCurrentQuery)
            {
                Diagnostics.ReportAggregateInGroupBy(aggregate.Span);
            }
            else if (InAggregateArgument)
            {
                Diagnostics.ReportAggregateInAggregateArgument(aggregate.Span);
            }

            return(boundAggregate);
        }
Example #13
0
        private static bool IsNullableTypeInPointerExpression(ExpressionSyntax expression, ExpressionSyntax simplifiedNode)
        {
            // Note: nullable type syntax is not allowed in pointer type syntax
            if (simplifiedNode.Kind() == SyntaxKind.NullableType &&
                simplifiedNode.DescendantNodes().Any(n => n is PointerTypeSyntax))
            {
                return(true);
            }

            return(false);
        }
Example #14
0
        public void Arrays()
        {
            RoslynCompiler compiler = new RoslynCompiler();

            XSLang.Apply(compiler);

            ExpressionSyntax exprArray = compiler.CompileExpression("x = [[1, 2, 3], [4, 5, 6]]");

            Assert.IsTrue(exprArray.DescendantNodes()
                          .OfType <ImplicitArrayCreationExpressionSyntax>()
                          .Count() == 3);
        }
Example #15
0
        private bool MethodContainsUserInputMethod(ExpressionSyntax invocationExpressionSyntax, SemanticModel semanticModel)
        {
            bool methodContainsUserInputMethod = false;

            foreach (InvocationExpressionSyntax childInvocation in invocationExpressionSyntax.DescendantNodes().OfType <InvocationExpressionSyntax>())
            {
                IMethodSymbol methodSymbol = semanticModel.GetSymbolInfo(childInvocation).Symbol as IMethodSymbol;
                if (IsPotentialUserInputMethod(methodSymbol))
                {
                    methodContainsUserInputMethod = true;
                }
            }
            return(methodContainsUserInputMethod);
        }
        private string GetBuilderSetterMethod(ExpressionSyntax assigment)
        {
            var nodes = assigment.DescendantNodes <IdentifierNameSyntax>();

            if (assigment is IdentifierNameSyntax)
            {
                nodes = nodes.Prepend(assigment.As <IdentifierNameSyntax>());
            }

            var parameter = nodes
                            .Select(p => p.Identifier.Text)
                            .Select(p => _parameters.FirstOrDefault(q => q.Identifier.Text == p))
                            .FirstOrDefault(p => p != null);

            return(GetAssigmentMethodName(parameter));
        }
        private StatementSyntax GetNewTaskVariable()
        {
            var varType = "var".ToIdentifierName();

            var taskLambda = _expr.F(ParenthesizedLambdaExpression);

            if (_expr.DescendantNodes <AwaitExpressionSyntax>().Any())
            {
                taskLambda = taskLambda.WithAsyncKeyword(AsyncKeyword.ToToken());
            }

            var newTaskExpr = "Task".AccessTo("Run").ToInvocation(taskLambda);

            return(GetTaskVariableName()
                   .ToVariableDeclaration(varType, newTaskExpr)
                   .ToLocalDeclaration());
        }
Example #18
0
        private InvocationExpressionSyntax ReplaceIdentifier(MemberAccessExpressionSyntax mockedObjectIdentifier,
                                                             ParameterSyntax param, ExpressionSyntax lambdaBody)
        {
            try
            {
                //var prependInvocation = SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                //                                                               mockedObjectIdentifier,SyntaxFactory.IdentifierName(prepandCall)));
                //var nameToken = lambdaBody.DescendantNodes().First(x => x.Kind() == mockedObjectIdentifier.Kind() && ((IdentifierNameSyntax)x).Identifier.ValueText == mockedObjectIdentifier.Identifier.ValueText);
                var nameToken = lambdaBody.DescendantNodes().OfType <IdentifierNameSyntax>()
                                .First(x => x.Identifier.ValueText == param.Identifier.ValueText);

                return(lambdaBody.ReplaceNode(nameToken, mockedObjectIdentifier) as InvocationExpressionSyntax);
            }
            catch (Exception e)
            {
                throw new Exception();
            }
        }
Example #19
0
    public SyntaxTemplate(string source)
    {
        Syntax = SyntaxFactory.ParseExpression(source);
        var identifiers = ImmutableDictionary <string, ImmutableList <IdentifierNameSyntax> .Builder> .Empty.ToBuilder();

        foreach (var node in Syntax.DescendantNodes().OfType <IdentifierNameSyntax>())
        {
            ImmutableList <IdentifierNameSyntax> .Builder list;
            if (!identifiers.TryGetValue(node.Identifier.Text, out list))
            {
                list = identifiers[node.Identifier.Text] =
                    ImmutableList <IdentifierNameSyntax> .Empty.ToBuilder();
            }
            list.Add(node);
        }
        _identifiers = identifiers.ToImmutableDictionary(
            p => p.Key, p => p.Value.ToImmutableList());
    }
        private static bool ContainsInterpolatedString(SeparatedSyntaxList <VariableDeclaratorSyntax> variables)
        {
            foreach (VariableDeclaratorSyntax declarator in variables)
            {
                ExpressionSyntax value = declarator.Initializer.Value.WalkDownParentheses();

                if (value is not LiteralExpressionSyntax)
                {
                    foreach (SyntaxNode node in value.DescendantNodes())
                    {
                        if (node.IsKind(SyntaxKind.InterpolatedStringExpression))
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Example #21
0
        private static void AnalyzeNamedType(SymbolAnalysisContext context)
        {
            var typeSymbol = (INamedTypeSymbol)context.Symbol;

            if (typeSymbol.IsImplicitlyDeclared)
            {
                return;
            }

            if (typeSymbol.TypeKind != TypeKind.Enum)
            {
                return;
            }

            bool hasFlagsAttribute = typeSymbol.HasAttribute(MetadataNames.System_FlagsAttribute);

            ImmutableArray <ISymbol> members = default;

            if (hasFlagsAttribute &&
                DiagnosticRules.DeclareEnumMemberWithZeroValue.IsEffective(context))
            {
                members = typeSymbol.GetMembers();

                if (!ContainsFieldWithZeroValue(members))
                {
                    var enumDeclaration = (EnumDeclarationSyntax)typeSymbol.GetSyntax(context.CancellationToken);

                    DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.DeclareEnumMemberWithZeroValue, enumDeclaration.Identifier);
                }
            }

            EnumSymbolInfo enumInfo = default;

            if (hasFlagsAttribute &&
                DiagnosticRules.CompositeEnumValueContainsUndefinedFlag.IsEffective(context))
            {
                enumInfo = EnumSymbolInfo.Create(typeSymbol);

                foreach (EnumFieldSymbolInfo field in enumInfo.Fields)
                {
                    if (field.HasValue &&
                        ConvertHelpers.CanConvertFromUInt64(field.Value, typeSymbol.EnumUnderlyingType.SpecialType) &&
                        !IsMaxValue(field.Value, typeSymbol.EnumUnderlyingType.SpecialType) &&
                        field.HasCompositeValue())
                    {
                        foreach (ulong value in (field.GetFlags()))
                        {
                            if (!enumInfo.Contains(value))
                            {
                                ReportUndefinedFlag(context, field.Symbol, value.ToString());
                            }
                        }
                    }
                }
            }

            if (hasFlagsAttribute &&
                DiagnosticRules.DeclareEnumValueAsCombinationOfNames.IsEffective(context))
            {
                if (members.IsDefault)
                {
                    members = typeSymbol.GetMembers();
                }

                foreach (ISymbol member in members)
                {
                    if (!(member is IFieldSymbol fieldSymbol))
                    {
                        continue;
                    }

                    if (!fieldSymbol.HasConstantValue)
                    {
                        break;
                    }

                    EnumFieldSymbolInfo fieldInfo = EnumFieldSymbolInfo.Create(fieldSymbol);

                    if (!fieldInfo.HasCompositeValue())
                    {
                        continue;
                    }

                    var declaration = (EnumMemberDeclarationSyntax)fieldInfo.Symbol.GetSyntax(context.CancellationToken);

                    ExpressionSyntax expression = declaration.EqualsValue?.Value.WalkDownParentheses();

                    if (expression != null &&
                        (expression.IsKind(SyntaxKind.NumericLiteralExpression) ||
                         expression
                         .DescendantNodes()
                         .Any(f => f.IsKind(SyntaxKind.NumericLiteralExpression))))
                    {
                        if (enumInfo.IsDefault)
                        {
                            enumInfo = EnumSymbolInfo.Create(typeSymbol);

                            if (enumInfo.Fields.Any(f => !f.HasValue))
                            {
                                break;
                            }
                        }

                        List <EnumFieldSymbolInfo> values = enumInfo.Decompose(fieldInfo);

                        if (values?.Count > 1)
                        {
                            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.DeclareEnumValueAsCombinationOfNames, expression);
                        }
                    }
                }
            }

            if (hasFlagsAttribute &&
                DiagnosticRules.UseBitShiftOperator.IsEffective(context))
            {
                if (members.IsDefault)
                {
                    members = typeSymbol.GetMembers();
                }

                foreach (ISymbol member in members)
                {
                    if (!(member is IFieldSymbol fieldSymbol))
                    {
                        continue;
                    }

                    if (!fieldSymbol.HasConstantValue)
                    {
                        continue;
                    }

                    EnumFieldSymbolInfo fieldInfo = EnumFieldSymbolInfo.Create(fieldSymbol);

                    if (fieldInfo.Value <= 1)
                    {
                        continue;
                    }

                    if (fieldInfo.HasCompositeValue())
                    {
                        continue;
                    }

                    var declaration = (EnumMemberDeclarationSyntax)fieldInfo.Symbol.GetSyntax(context.CancellationToken);

                    ExpressionSyntax expression = declaration.EqualsValue?.Value.WalkDownParentheses();

                    if (expression.IsKind(SyntaxKind.NumericLiteralExpression))
                    {
                        var enumDeclaration = (EnumDeclarationSyntax)typeSymbol.GetSyntax(context.CancellationToken);

                        DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UseBitShiftOperator, enumDeclaration.Identifier);
                        break;
                    }
                }
            }

            if (DiagnosticRules.DuplicateEnumValue.IsEffective(context))
            {
                if (enumInfo.IsDefault)
                {
                    enumInfo = EnumSymbolInfo.Create(typeSymbol);
                }

                ImmutableArray <EnumFieldSymbolInfo> fields = enumInfo.Fields;

                if (fields.Length > 1)
                {
                    EnumFieldSymbolInfo symbolInfo1 = fields[0];
                    EnumFieldSymbolInfo symbolInfo2 = default;

                    for (int i = 1; i < fields.Length; i++, symbolInfo1 = symbolInfo2)
                    {
                        symbolInfo2 = fields[i];

                        if (!symbolInfo1.HasValue ||
                            !symbolInfo2.HasValue ||
                            symbolInfo1.Value != symbolInfo2.Value)
                        {
                            continue;
                        }

                        var enumMember1 = (EnumMemberDeclarationSyntax)symbolInfo1.Symbol.GetSyntax(context.CancellationToken);

                        if (enumMember1 == null)
                        {
                            continue;
                        }

                        var enumMember2 = (EnumMemberDeclarationSyntax)symbolInfo2.Symbol.GetSyntax(context.CancellationToken);

                        if (enumMember2 == null)
                        {
                            continue;
                        }

                        ExpressionSyntax value1 = enumMember1.EqualsValue?.Value?.WalkDownParentheses();
                        ExpressionSyntax value2 = enumMember2.EqualsValue?.Value?.WalkDownParentheses();

                        if (value1 == null)
                        {
                            if (value2 != null)
                            {
                                ReportDuplicateValue(context, enumMember1, value2);
                            }
                        }
                        else if (value2 == null)
                        {
                            ReportDuplicateValue(context, enumMember2, value1);
                        }
                        else
                        {
                            SyntaxKind kind1 = value1.Kind();
                            SyntaxKind kind2 = value2.Kind();

                            if (kind1 == SyntaxKind.NumericLiteralExpression)
                            {
                                if (kind2 == SyntaxKind.NumericLiteralExpression)
                                {
                                    var enumDeclaration = (EnumDeclarationSyntax)enumMember1.Parent;
                                    SeparatedSyntaxList <EnumMemberDeclarationSyntax> enumMembers = enumDeclaration.Members;

                                    if (enumMembers.IndexOf(enumMember1) < enumMembers.IndexOf(enumMember2))
                                    {
                                        ReportDuplicateValue(context, value2);
                                    }
                                    else
                                    {
                                        ReportDuplicateValue(context, value1);
                                    }
                                }
                                else if (!string.Equals((value2 as IdentifierNameSyntax)?.Identifier.ValueText, enumMember1.Identifier.ValueText, StringComparison.Ordinal))
                                {
                                    ReportDuplicateValue(context, value1);
                                }
                            }
                            else if (kind2 == SyntaxKind.NumericLiteralExpression &&
                                     !string.Equals((value1 as IdentifierNameSyntax)?.Identifier.ValueText, enumMember2.Identifier.ValueText, StringComparison.Ordinal))
                            {
                                ReportDuplicateValue(context, value2);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Determines whether an expression has an initializer syntax.
        /// </summary>
        /// <param name="syntax">The syntax.</param>
        /// <returns>
        ///   <see langword="true"/> if the specified expression has an initializer; otherwise, <see langword="false"/>.
        /// </returns>
        public static bool HasInitializer(this ExpressionSyntax syntax)
        {
            var i = syntax?.DescendantNodes().OfType <InitializerExpressionSyntax>().FirstOrDefault();

            return(i != null);
        }
Example #23
0
 // does the expression contain declaration?
 public static bool ContainsDeclarations(this ExpressionSyntax node)
 {
     return(node.DescendantNodes().Any(x =>
                                       x.IsKind(SyntaxKind.DeclarationExpression) || x.IsKind(SyntaxKind.DeclarationPattern)));
 }
        private static bool IsNullableTypeInPointerExpression(ExpressionSyntax expression, ExpressionSyntax simplifiedNode)
        {
            // Note: nullable type syntax is not allowed in pointer type syntax
            if (simplifiedNode.Kind() == SyntaxKind.NullableType &&
                simplifiedNode.DescendantNodes().Any(n => n is PointerTypeSyntax))
            {
                return true;
            }

            return false;
        }
Example #25
0
        private static void AnalyzeParenthesizedExpression(SyntaxNodeAnalysisContext context)
        {
            var parenthesizedExpression = (ParenthesizedExpressionSyntax)context.Node;

            ExpressionSyntax expression = parenthesizedExpression.Expression;

            if (expression?.IsMissing != false)
            {
                return;
            }

            SyntaxToken openParen = parenthesizedExpression.OpenParenToken;

            if (openParen.IsMissing)
            {
                return;
            }

            SyntaxToken closeParen = parenthesizedExpression.CloseParenToken;

            if (closeParen.IsMissing)
            {
                return;
            }

            SyntaxNode parent = parenthesizedExpression.Parent;

            SyntaxKind parentKind = parent.Kind();

            switch (parentKind)
            {
            case SyntaxKind.ParenthesizedExpression:
            case SyntaxKind.ArrowExpressionClause:
            case SyntaxKind.AttributeArgument:
            case SyntaxKind.Argument:
            case SyntaxKind.ExpressionStatement:
            case SyntaxKind.ReturnStatement:
            case SyntaxKind.YieldReturnStatement:
            case SyntaxKind.WhileStatement:
            case SyntaxKind.DoStatement:
            case SyntaxKind.UsingStatement:
            case SyntaxKind.LockStatement:
            case SyntaxKind.IfStatement:
            case SyntaxKind.SwitchStatement:
            case SyntaxKind.ArrayRankSpecifier:
            {
                ReportDiagnostic();
                break;
            }

            case SyntaxKind.LessThanExpression:
            case SyntaxKind.GreaterThanExpression:
            case SyntaxKind.LessThanOrEqualExpression:
            case SyntaxKind.GreaterThanOrEqualExpression:
            case SyntaxKind.EqualsExpression:
            case SyntaxKind.NotEqualsExpression:
            {
                if (expression.IsKind(SyntaxKind.IdentifierName) ||
                    expression is LiteralExpressionSyntax)
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.MultiplyExpression:
            case SyntaxKind.DivideExpression:
            case SyntaxKind.ModuloExpression:
            case SyntaxKind.AddExpression:
            case SyntaxKind.SubtractExpression:
            case SyntaxKind.LeftShiftExpression:
            case SyntaxKind.RightShiftExpression:
            case SyntaxKind.BitwiseAndExpression:
            case SyntaxKind.ExclusiveOrExpression:
            case SyntaxKind.BitwiseOrExpression:
            case SyntaxKind.LogicalAndExpression:
            case SyntaxKind.LogicalOrExpression:
            {
                SyntaxKind kind = expression.Kind();

                if (kind == SyntaxKind.IdentifierName ||
                    expression is LiteralExpressionSyntax)
                {
                    ReportDiagnostic();
                }
                else if (kind == parentKind &&
                         ((BinaryExpressionSyntax)parent).Left == parenthesizedExpression)
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.LogicalNotExpression:
            {
                switch (expression.Kind())
                {
                case SyntaxKind.IdentifierName:
                case SyntaxKind.GenericName:
                case SyntaxKind.InvocationExpression:
                case SyntaxKind.SimpleMemberAccessExpression:
                case SyntaxKind.ElementAccessExpression:
                case SyntaxKind.ConditionalAccessExpression:
                {
                    ReportDiagnostic();
                    break;
                }
                }

                break;
            }

            case SyntaxKind.SimpleAssignmentExpression:
            case SyntaxKind.AddAssignmentExpression:
            case SyntaxKind.SubtractAssignmentExpression:
            case SyntaxKind.MultiplyAssignmentExpression:
            case SyntaxKind.DivideAssignmentExpression:
            case SyntaxKind.ModuloAssignmentExpression:
            case SyntaxKind.AndAssignmentExpression:
            case SyntaxKind.ExclusiveOrAssignmentExpression:
            case SyntaxKind.OrAssignmentExpression:
            case SyntaxKind.LeftShiftAssignmentExpression:
            case SyntaxKind.RightShiftAssignmentExpression:
            {
                if (((AssignmentExpressionSyntax)parent).Left == parenthesizedExpression)
                {
                    ReportDiagnostic();
                }
                else if (expression.IsKind(SyntaxKind.IdentifierName) ||
                         expression is LiteralExpressionSyntax)
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.Interpolation:
            {
                if (!expression.IsKind(SyntaxKind.ConditionalExpression) &&
                    !expression.DescendantNodes().Any(f => f.IsKind(SyntaxKind.AliasQualifiedName)) &&
                    ((InterpolationSyntax)parent).Expression == parenthesizedExpression)
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.AwaitExpression:
            {
                if (parenthesizedExpression.Expression.IsKind(SyntaxKind.SwitchExpression))
                {
                    return;
                }

                if (CSharpFacts.GetOperatorPrecedence(expression.Kind()) <= CSharpFacts.GetOperatorPrecedence(SyntaxKind.AwaitExpression))
                {
                    ReportDiagnostic();
                }

                break;
            }

            case SyntaxKind.ArrayInitializerExpression:
            case SyntaxKind.CollectionInitializerExpression:
            {
                if (!(expression is AssignmentExpressionSyntax))
                {
                    ReportDiagnostic();
                }

                break;
            }
            }

            void ReportDiagnostic()
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.RemoveRedundantParentheses,
                    openParen.GetLocation(),
                    additionalLocations: ImmutableArray.Create(closeParen.GetLocation()));

                DiagnosticHelpers.ReportToken(context, DiagnosticRules.RemoveRedundantParenthesesFadeOut, openParen);
                DiagnosticHelpers.ReportToken(context, DiagnosticRules.RemoveRedundantParenthesesFadeOut, closeParen);
            }
        }