/// <summary>
		///   Normalizes the <paramref name="assignment" />.
		/// </summary>
		public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax assignment)
		{
			if (!IsFormulaType(assignment.Left) || IsFormulaType(assignment.Right))
				return base.VisitAssignmentExpression(assignment);

			return assignment.WithRight(CreateInvocation(assignment.Right));
		}
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the assignment expression.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="assignment">AssignmentExpressionSyntax</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        protected override void AnalyzeOwnershipInAssignment(GivenUpOwnershipSymbol givenUpSymbol,
            AssignmentExpressionSyntax assignment, Statement statement, StateMachine machine,
            SemanticModel model, TraceInfo trace)
        {
            var leftIdentifier = base.AnalysisContext.GetRootIdentifier(assignment.Left);
            ISymbol leftSymbol = model.GetSymbolInfo(leftIdentifier).Symbol;

            if (assignment.Right is IdentifierNameSyntax)
            {
                var rightIdentifier = base.AnalysisContext.GetRootIdentifier(assignment.Right);
                ISymbol rightSymbol = model.GetSymbolInfo(rightIdentifier).Symbol;

                if (statement.Summary.DataFlowAnalysis.FlowsIntoSymbol(rightSymbol,
                    givenUpSymbol.ContainingSymbol, statement, givenUpSymbol.Statement))
                {
                    var type = model.GetTypeInfo(assignment.Right).Type;
                    if (leftSymbol != null && leftSymbol.Kind == SymbolKind.Field &&
                        base.IsFieldAccessedInSuccessor(leftSymbol as IFieldSymbol, statement.Summary, machine) &&
                        !base.AnalysisContext.IsTypePassedByValueOrImmutable(type))
                    {
                        TraceInfo newTrace = new TraceInfo();
                        newTrace.Merge(trace);
                        newTrace.AddErrorTrace(statement.SyntaxNode);

                        AnalysisErrorReporter.ReportGivenUpOwnershipFieldAssignment(newTrace, leftSymbol);
                    }

                    return;
                }
            }
            else if (assignment.Right is MemberAccessExpressionSyntax)
            {
                this.AnalyzeOwnershipInExpression(givenUpSymbol, assignment.Right, statement,
                    machine, model, trace);
            }
            else if (assignment.Right is InvocationExpressionSyntax ||
                assignment.Right is ObjectCreationExpressionSyntax)
            {
                trace.InsertCall(statement.Summary.Method, assignment.Right);
                base.AnalyzeOwnershipInCall(givenUpSymbol, assignment.Right, statement,
                    machine, model, trace);
            }

            if (assignment.Left is MemberAccessExpressionSyntax)
            {
                ISymbol outerLeftMemberSymbol = model.GetSymbolInfo(assignment.Left).Symbol;
                if (!outerLeftMemberSymbol.Equals(leftSymbol) &&
                    statement.Summary.DataFlowAnalysis.FlowsIntoSymbol(givenUpSymbol.ContainingSymbol,
                    leftSymbol, givenUpSymbol.Statement, statement))
                {
                    TraceInfo newTrace = new TraceInfo();
                    newTrace.Merge(trace);
                    newTrace.AddErrorTrace(statement.SyntaxNode);

                    AnalysisErrorReporter.ReportGivenUpOwnershipAccess(newTrace);
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Only handles assignment-only or declaration-only deconstructions at this point.
        /// Issue https://github.com/dotnet/roslyn/issues/15050 tracks allowing mixed deconstructions
        /// </summary>
        private BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, DiagnosticBag diagnostics)
        {
            var left = node.Left;
            var right = node.Right;

            bool isDeclaration = node.IsDeconstructionDeclaration();
            Debug.Assert(isDeclaration || !ContainsDeclarations(left));
            return BindDeconstruction(node, left, right, diagnostics, isDeclaration);
        }
        private BoundExpression BindDeconstructionAssignment(AssignmentExpressionSyntax node, DiagnosticBag diagnostics)
        {
            var left = (TupleExpressionSyntax)node.Left;
            ArrayBuilder<DeconstructionVariable> checkedVariables = BindDeconstructionAssignmentVariables(left.Arguments, left, diagnostics);

            var result = BindDeconstructionAssignment(node, node.Right, checkedVariables, diagnostics, isDeclaration: false);
            FreeDeconstructionVariables(checkedVariables);

            return result;
        }
 private static SyntaxNode ReplaceAddExpressionByStringBuilderAppendExpression(AssignmentExpressionSyntax assignmentExpression, SyntaxNode expressionStatement, SyntaxNode expressionStatementParent, string builderName)
 {
     var appendExpressionOnLoop = assignmentExpression.IsKind(SyntaxKind.SimpleAssignmentExpression)
         ? SyntaxFactory.ParseStatement($"{builderName}.Append({((BinaryExpressionSyntax)assignmentExpression.Right).Right.ToString()});\r\n")
         : SyntaxFactory.ParseStatement($"{builderName}.Append({assignmentExpression.Right.ToString()});\r\n");
     appendExpressionOnLoop = appendExpressionOnLoop
         .WithLeadingTrivia(expressionStatement.GetLeadingTrivia())
         .WithTrailingTrivia(expressionStatement.GetTrailingTrivia());
     var newExpressionStatementParent = expressionStatementParent.ReplaceNode(expressionStatement, appendExpressionOnLoop);
     return newExpressionStatementParent;
 }
        internal static bool ParseIfStatement(IfStatementSyntax node, out ExpressionSyntax condition, out ExpressionSyntax target, out AssignmentExpressionSyntax whenTrue, out AssignmentExpressionSyntax whenFalse)
        {
            condition = null;
            target = null;
            whenTrue = null;
            whenFalse = null;

            if (node == null || node.Else == null || node.Parent is IfStatementSyntax || node.Else.Statement is IfStatementSyntax)
                return false;

            condition = node.Condition;
            //make sure to check for multiple statements
            ExpressionStatementSyntax whenTrueExprStatement, whenFalseExprStatement;
            var embeddedBlock = node.Statement as BlockSyntax;
            if (embeddedBlock != null)
            {
                if (embeddedBlock.Statements.Count > 1)
                    return false;
                var childNodes = embeddedBlock.ChildNodes();
                if (childNodes.Count() > 1)
                    return false;
                whenTrueExprStatement = childNodes.OfType<ExpressionStatementSyntax>().FirstOrDefault();
            }
            else
            {
                whenTrueExprStatement = node.Statement as ExpressionStatementSyntax;
            }

            var elseBlock = node.Else.Statement as BlockSyntax;
            if (elseBlock != null)
            {
                if (elseBlock.Statements.Count > 1)
                    return false;
                var childNodes = elseBlock.ChildNodes();
                if (childNodes.Count() > 1)
                    return false;
                whenFalseExprStatement = childNodes.OfType<ExpressionStatementSyntax>().FirstOrDefault();
            }
            else
            {
                whenFalseExprStatement = node.Else.Statement as ExpressionStatementSyntax;
            }

            if (whenTrueExprStatement == null || whenFalseExprStatement == null)
                return false;

            whenTrue = whenTrueExprStatement.Expression as AssignmentExpressionSyntax;
            whenFalse = whenFalseExprStatement.Expression as AssignmentExpressionSyntax;
            if (whenTrue == null || whenFalse == null || whenTrue.Kind() != whenFalse.Kind() ||
                !SyntaxFactory.AreEquivalent(whenTrue.Left, whenFalse.Left))
                return false;

            return true;
        }
        public override void VisitAssignmentExpression(AssignmentExpressionSyntax node)
        {
            cb.AppendIndent();
              Visit(node.Left);

              cb.Append(" = ");

              Visit(node.Right);

              cb.AppendLine(";");
        }
        /// <summary>
        /// Analyzes the ownership of the given-up symbol
        /// in the assignment expression.
        /// </summary>
        /// <param name="givenUpSymbol">GivenUpOwnershipSymbol</param>
        /// <param name="assignment">AssignmentExpressionSyntax</param>
        /// <param name="statement">Statement</param>
        /// <param name="machine">StateMachine</param>
        /// <param name="model">SemanticModel</param>
        /// <param name="trace">TraceInfo</param>
        protected override void AnalyzeOwnershipInAssignment(GivenUpOwnershipSymbol givenUpSymbol,
            AssignmentExpressionSyntax assignment, Statement statement, StateMachine machine,
            SemanticModel model, TraceInfo trace)
        {
            IdentifierNameSyntax leftIdentifier = base.AnalysisContext.GetRootIdentifier(assignment.Left);
            ISymbol leftSymbol = model.GetSymbolInfo(leftIdentifier).Symbol;

            this.AnalyzeGivingUpFieldOwnership(givenUpSymbol, leftSymbol, statement, machine, trace);
            this.AnalyzeOwnershipInExpression(givenUpSymbol, assignment.Right,
                statement, machine, model, trace);
        }
 private static bool IsAssignmentOutsideConstructor(AssignmentExpressionSyntax assignment, ISymbol fieldSymbol, SemanticModel model)
 {
     var assignedSymbol = model.GetSymbolInfo(assignment.Left);
     if (assignedSymbol.Symbol != fieldSymbol)
     {
         return false;
     }
     // Method (or whatever) enclosing the assignment
     var enclosingSymbol = model.GetEnclosingSymbol(assignment.SpanStart) as IMethodSymbol;
     var isCtor = enclosingSymbol?.MethodKind == MethodKind.Constructor;
     return !isCtor;
 }
        static bool CheckConditionAndAssignment(SyntaxNodeAnalysisContext nodeContext, AssignmentExpressionSyntax assignment, BinaryExpressionSyntax condition)
        {
            if (assignment == null)
                return false;

            var assignmentTarget = nodeContext.SemanticModel.GetSymbolInfo(assignment.Left).Symbol;
            if (assignmentTarget == null)
                return false;

            var condLeftSymbol = nodeContext.SemanticModel.GetSymbolInfo(condition.Left).Symbol;
            var condRightSymbol = nodeContext.SemanticModel.GetSymbolInfo(condition.Right).Symbol;

            var assignmentValue = nodeContext.SemanticModel.GetSymbolInfo(assignment.Right).Symbol;
            var constant = nodeContext.SemanticModel.GetConstantValue(assignment.Right);

            bool constantAssignment = assignmentValue == null && constant.HasValue;

            if (assignmentTarget.Equals(condLeftSymbol))
            {
                if (constantAssignment)
                {
                    var condRightValue = nodeContext.SemanticModel.GetConstantValue(condition.Right);
                    if (condRightValue.HasValue)
                        return condRightValue.Value == constant.Value;
                }
                else
                {
                    if ((assignmentValue == null) || !assignmentValue.Equals(condRightSymbol))
                        return false;
                }
                return true;
            }

            // flipped operands
            if (assignmentTarget.Equals(condRightSymbol))
            {
                if (constantAssignment)
                {
                    var condLeftValue = nodeContext.SemanticModel.GetConstantValue(condition.Left);
                    if (condLeftValue.HasValue)
                        return condLeftValue.Value == constant.Value;
                }
                else
                {
                    if ((assignmentValue == null) || !assignmentValue.Equals(condLeftSymbol))
                        return false;
                }
                return true;
            }

            return false;
        }
 private static MemberAccessExpressionSyntax GetMemberAccessExpressionFromAssignment(SemanticModel semanticModel, AssignmentExpressionSyntax assignmentExpression, AssignmentExpressionSyntax nullLiteralAssignment)
 {
     if (assignmentExpression == null || nullLiteralAssignment == null
         || !assignmentExpression.IsKind(SyntaxKind.SimpleAssignmentExpression)
         || !assignmentExpression.IsKind(SyntaxKind.SimpleAssignmentExpression))
         return null;
     if (!nullLiteralAssignment.Right.IsKind(SyntaxKind.NullLiteralExpression)) return null;
     if (!nullLiteralAssignment.Left.IsKind(SyntaxKind.IdentifierName)) return null;
     if (!assignmentExpression.Left.IsKind(SyntaxKind.IdentifierName)) return null;
     var assignmentIdentifier = semanticModel.GetSymbolInfo(assignmentExpression.Left);
     var nullLiteralAssignmentIdentifier = semanticModel.GetSymbolInfo(nullLiteralAssignment.Left);
     if ((assignmentIdentifier.Symbol ?? nullLiteralAssignmentIdentifier.Symbol) == null) return null;
     if (!assignmentIdentifier.Equals(nullLiteralAssignmentIdentifier)) return null;
     var memberAccessExpression = assignmentExpression.Right as MemberAccessExpressionSyntax;
     return memberAccessExpression;
 }
        private static void AddVariableThatWasSkippedBeforeBecauseItLackedAInitializer(Dictionary<IFieldSymbol, VariableDeclaratorSyntax> variablesToMakeReadonly, IFieldSymbol fieldSymbol, AssignmentExpressionSyntax assignment)
        {
            var parent = assignment.Parent;
            while (parent != null)
            {
                if (parent is AnonymousFunctionExpressionSyntax)
                    return;
                if (parent is ConstructorDeclarationSyntax)
                    break;
                parent = parent.Parent;
            }

            if (!fieldSymbol.IsReadOnly && !variablesToMakeReadonly.Keys.Contains(fieldSymbol))
                foreach (var variable in fieldSymbol.DeclaringSyntaxReferences)
                    variablesToMakeReadonly.Add(fieldSymbol, (VariableDeclaratorSyntax)variable.GetSyntax());
        }
		/// <summary>
		///   Normalizes the <paramref name="assignment" />.
		/// </summary>
		public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax assignment)
		{
			var objectCreation = assignment.Right as ObjectCreationExpressionSyntax;
			if (objectCreation == null)
				return assignment;

			var fault = SemanticModel.GetTypeSymbol<Fault>();
			if (SemanticModel.GetTypeInfo(objectCreation).Type?.IsDerivedFrom(fault) == false)
				return assignment;

			var targetSymbol = SemanticModel.GetSymbolInfo(assignment.Left).Symbol;
			if (targetSymbol == null || (targetSymbol.Kind != SymbolKind.Field && targetSymbol.Kind != SymbolKind.Property))
				return assignment;

			return assignment.WithRight(AddNameInitializer(fault, objectCreation, targetSymbol.Name));
		}
		/// <summary>
		///     Normalizes the <paramref name="expression" /> if it represents a compound assignment.
		/// </summary>
		public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax expression)
		{
			expression = (AssignmentExpressionSyntax)base.VisitAssignmentExpression(expression);

			SyntaxKind expressionKind;
			switch (expression.Kind())
			{
				case SyntaxKind.AddAssignmentExpression:
					expressionKind = SyntaxKind.AddExpression;
					break;
				case SyntaxKind.SubtractAssignmentExpression:
					expressionKind = SyntaxKind.SubtractExpression;
					break;
				case SyntaxKind.MultiplyAssignmentExpression:
					expressionKind = SyntaxKind.MultiplyExpression;
					break;
				case SyntaxKind.DivideAssignmentExpression:
					expressionKind = SyntaxKind.DivideExpression;
					break;
				case SyntaxKind.ModuloAssignmentExpression:
					expressionKind = SyntaxKind.ModuloExpression;
					break;
				case SyntaxKind.AndAssignmentExpression:
					expressionKind = SyntaxKind.LogicalAndExpression;
					break;
				case SyntaxKind.ExclusiveOrAssignmentExpression:
					expressionKind = SyntaxKind.ExclusiveOrExpression;
					break;
				case SyntaxKind.OrAssignmentExpression:
					expressionKind = SyntaxKind.LogicalOrExpression;
					break;
				case SyntaxKind.LeftShiftAssignmentExpression:
					expressionKind = SyntaxKind.LeftShiftExpression;
					break;
				case SyntaxKind.RightShiftAssignmentExpression:
					expressionKind = SyntaxKind.RightShiftExpression;
					break;
				default:
					return expression;
			}

			var originalRightHand = (ExpressionSyntax)Visit(expression.Right);
			var parenthesizedExpression = SyntaxFactory.ParenthesizedExpression(originalRightHand).WithLeadingSpace();
			var rightHandExpression = SyntaxFactory.BinaryExpression(expressionKind, expression.Left.WithLeadingSpace(), parenthesizedExpression);
			var simpleAssignment = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, expression.Left, rightHandExpression);
			return simpleAssignment.WithTrivia(expression);
		}
        internal static AssignmentExpressionSyntax CreateAssignment(AssignmentExpressionSyntax node)
        {
            var bop = node.Right as BinaryExpressionSyntax;
            if (bop == null)
                return null;
            var outerLeft = GetOuterLeft(bop);
			var outerLeftId = outerLeft as IdentifierNameSyntax;
			var leftId = node.Left as IdentifierNameSyntax;
			if (outerLeftId == null || leftId == null)
				return null;
			if (!outerLeftId.Identifier.Value.Equals (leftId.Identifier.Value))
                return null;
            var op = GetAssignmentOperator(bop.OperatorToken);
            if (op == SyntaxKind.None)
                return null;
            return SyntaxFactory.AssignmentExpression(op, node.Left, SplitIfWithAndConditionInTwoCodeRefactoringProvider.GetRightSide(outerLeft.Parent as BinaryExpressionSyntax));
        }
		/// <summary>
		///   Normalizes the <paramref name="expression" />.
		/// </summary>
		public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax expression)
		{
			if (!_inConstructor)
				return expression;

			var propertySymbol = SemanticModel.GetSymbolInfo(expression.Left).Symbol as IPropertySymbol;
			expression = (AssignmentExpressionSyntax)base.VisitAssignmentExpression(expression);

			if (propertySymbol == null || !propertySymbol.IsAutoProperty())
				return expression;

			if (propertySymbol.GetMethod != null && !propertySymbol.GetMethod.CanBeAffectedByFaults(SemanticModel))
				return expression;

			var fieldExpression = (ExpressionSyntax)Syntax.IdentifierName(GetBackingFieldName(propertySymbol)).WithTrivia(expression.Left);
			return expression.WithLeft(fieldExpression);
		}
        /// <summary>
        /// Only handles assignment-only or declaration-only deconstructions at this point.
        /// Issue https://github.com/dotnet/roslyn/issues/15050 tracks allowing mixed deconstructions
        /// </summary>
        private BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, DiagnosticBag diagnostics)
        {
            var left = node.Left;
            var right = node.Right;

            if (node.IsDeconstructionDeclaration())
            {
                return BindDeconstructionDeclaration(node, left, right, diagnostics);
            }

            AssertDeconstructionIsAssignment(left);

            var tuple = (TupleExpressionSyntax)left;
            ArrayBuilder<DeconstructionVariable> checkedVariables = BindDeconstructionAssignmentVariables(tuple.Arguments, tuple, diagnostics);
            var result = BindDeconstructionAssignment(node, node.Right, checkedVariables, diagnostics, isDeclaration: false);
            FreeDeconstructionVariables(checkedVariables);
            return result;
        }
        private BoundExpression BindDeconstruction(AssignmentExpressionSyntax node, DiagnosticBag diagnostics)
        {
            var left = node.Left;
            var right = node.Right;
            DeclarationExpressionSyntax declaration = null;
            ExpressionSyntax expression = null;
            var result = BindDeconstruction(node, left, right, diagnostics, ref declaration, ref expression);
            if (declaration != null)
            {
                // only allowed at the top level, or in a for loop
                switch (node.Parent?.Kind())
                {
                    case null:
                    case SyntaxKind.ExpressionStatement:
                        if (expression != null)
                        {
                            // We only allow assignment-only or declaration-only deconstructions at this point.
                            // Issue https://github.com/dotnet/roslyn/issues/15050 tracks allowing mixed deconstructions.
                            // For now we give an error when you mix.
                            Error(diagnostics, ErrorCode.ERR_MixedDeconstructionUnsupported, left);
                        }
                        break;
                    case SyntaxKind.ForStatement:
                        if (((ForStatementSyntax)node.Parent).Initializers.Contains(node))
                        {
                            if (expression != null)
                            {
                                Error(diagnostics, ErrorCode.ERR_MixedDeconstructionUnsupported, left);
                            }
                        }
                        else
                        {
                            Error(diagnostics, ErrorCode.ERR_DeclarationExpressionNotPermitted, declaration);
                        }
                        break;
                    default:
                        Error(diagnostics, ErrorCode.ERR_DeclarationExpressionNotPermitted, declaration);
                        break;
                }
            }

            return result;
        }
        void AnalyzeAssignment(SyntaxNodeAnalysisContext context, AssignmentExpressionSyntax assignment)
        {
            var containingMethod = assignment.GetContainingMethod();
            if (containingMethod.HasConstAttribute(context.SemanticModel)) {
                if (context.SemanticModel.GetSymbolInfo(assignment.Left).Symbol?.Kind == SymbolKind.Local) {
                    return;
                }

                var left = assignment.Left as MemberAccessExpressionSyntax;
                if (left != null) {
                    var walker = new Walker(context);
                    containingMethod.Accept(walker);
                    var exprSymbol = context.SemanticModel.GetSymbolInfo(left.Expression).Symbol;
                    if (exprSymbol != null && exprSymbol.Kind == SymbolKind.Local && !walker.UnsafeLocals.Contains(exprSymbol.Name)) {
                        return;
                    }
                }
                context.ReportDiagnostic(Diagnostic.Create(Rule, assignment.GetLocation(), context.SemanticModel.GetDeclaredSymbol(containingMethod)?.Name));
            }
        }
        private static SyntaxNode CalculateNewRoot(SyntaxNode root, Diagnostic diagnostic,
            StatementSyntax currentAsStatement, AssignmentExpressionSyntax currentAsAssignment,
            BinaryExpressionSyntax currentAsBinary)
        {
            if (currentAsStatement != null)
            {
                return root.RemoveNode(currentAsStatement, SyntaxRemoveOptions.KeepNoTrivia);
            }

            if (currentAsAssignment != null)
            {
                return root.ReplaceNode(
                    currentAsAssignment,
                    currentAsAssignment.Left.WithAdditionalAnnotations(Formatter.Annotation));
            }

            var isReportingOnLeft = bool.Parse(diagnostic.Properties[SillyBitwiseOperation.IsReportingOnLeftKey]);
            return root.ReplaceNode(
                currentAsBinary,
                (isReportingOnLeft ? currentAsBinary.Right : currentAsBinary.Left).WithAdditionalAnnotations(Formatter.Annotation));
        }
            public override void VisitAssignmentExpression(AssignmentExpressionSyntax node)
            {
                if (node.Left != null)
                {
                    var walker = new EventArgsRowWalker(_semanticModel, _pxContext);
                    node.Left.Accept(walker);
                    bool found = walker.Success;

                    if (!found)
                    {
                        _variableMemberAccessWalker.Reset();
                        node.Left.Accept(_variableMemberAccessWalker);
                        found = _variableMemberAccessWalker.Success;
                    }

                    if (found)
                    {
                        _context.ReportDiagnostic(Diagnostic.Create(Descriptors.PX1047_RowChangesInEventHandlers,
                                                                    node.GetLocation(), _messageArgs));
                    }
                }
            }
        public bool IsVulnerable(SemanticModel model, AssignmentExpressionSyntax syntax, DiagnosticId ruleId)
        {
            var leftSyntax = syntax?.Left as MemberAccessExpressionSyntax;

            if (leftSyntax == null)
            {
                return(false);
            }

            if (string.Compare(leftSyntax.Name.Identifier.ValueText, "Filter", StringComparison.OrdinalIgnoreCase) != 0)
            {
                return(false);
            }

            var leftSymbol = model.GetSymbolInfo(leftSyntax).Symbol;

            if (leftSymbol == null)
            {
                return(false);
            }

            if (!leftSymbol.ToString().StartsWith("System.DirectoryServices.DirectorySearcher"))
            {
                return(false);
            }

            var expressionAnalyzer = SyntaxNodeAnalyzerFactory.Create(syntax.Right);

            if (expressionAnalyzer.CanIgnore(model, syntax.Right))
            {
                return(false);
            }
            if (expressionAnalyzer.CanSuppress(model, syntax.Right, ruleId))
            {
                return(false);
            }

            return(true);
        }
        void AnalyzeAssignment(SyntaxNodeAnalysisContext context, AssignmentExpressionSyntax assignment)
        {
            var constructor = assignment.GetContainingConstructor();
            if (constructor == null)
            {
                return;
            }

            var symbol = context.SemanticModel.GetSymbolInfo(assignment.Left).Symbol;
            if (symbol?.Kind == SymbolKind.Local)
            {
                return;
            }

            var constructorSymbol = context.SemanticModel.GetDeclaredSymbol(constructor);
            if (symbol?.ContainingType == constructorSymbol.ContainingType)
            {
                return;
            }

            context.ReportDiagnostic(Diagnostic.Create(Rule, assignment.GetLocation(), constructorSymbol.Name));
        }
Exemple #24
0
        public bool IsVulnerable(SemanticModel model, AssignmentExpressionSyntax syntax)
        {
            if (!ContainsCertificateValidationCallback(syntax))
            {
                return(false);
            }

            var symbol = ModelExtensions.GetSymbolInfo(model, syntax.Left).Symbol as IPropertySymbol;

            if (symbol == null)
            {
                return(false);
            }

            //NOTE: only flagging those hard-coding a return value of true. Therefore could miss scenarios where the value is hardcoded in a const, config value.
            //TODO: therefore need dataflow to analyzer further
            //TODO: can we evaluate the expression? Possibly with the scripting lib. Would need to gather any references needed to execute.

            if (symbol.Name == "ServerCertificateValidationCallback" &&
                symbol.ContainingType.Name == "HttpWebRequest")
            {
                if (IsTrueLamdaExpression(syntax))
                {
                    return(true);
                }

                if (IsTrueDelegateMethod(syntax))
                {
                    return(true);
                }

                if (IsTrueMethod(model, syntax))
                {
                    return(true);
                }
            }

            return(false);
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            InitializerExpressionSyntax initializer,
            CancellationToken cancellationToken)
        {
            SeparatedSyntaxList <ExpressionSyntax> expressions = initializer.Expressions;

            ImplicitElementAccessSyntax implicitElementAccess = ImplicitElementAccess(
                BracketedArgumentList(
                    OpenBracketToken().WithTriviaFrom(initializer.OpenBraceToken),
                    SingletonSeparatedList(Argument(expressions[0]).WithFormatterAnnotation()),
                    CloseBracketToken()));

            AssignmentExpressionSyntax assignment = SimpleAssignmentExpression(
                implicitElementAccess,
                EqualsToken().WithTriviaFrom(initializer.ChildTokens().FirstOrDefault()),
                expressions[1]
                .AppendTrailingTrivia(initializer.CloseBraceToken.GetLeadingAndTrailingTrivia())
                .WithFormatterAnnotation());

            return(await document.ReplaceNodeAsync(initializer, assignment, cancellationToken).ConfigureAwait(false));
        }
        private static bool IsTrueMethod(SemanticModel model, AssignmentExpressionSyntax syntax)
        {
            var identifierNameSyntax = syntax.Right as IdentifierNameSyntax;

            if (identifierNameSyntax != null)
            {
                var method = model.SyntaxTree.GetRoot().DescendantNodes().OfType <MethodDeclarationSyntax>()
                             .Where(p => p.Identifier.ValueText == identifierNameSyntax.Identifier.ValueText);

                var methodReturnsHardcodedTrue =
                    method.Any(p => p.DescendantNodes().OfType <ReturnStatementSyntax>().Any(
                                   q =>
                                   q.Expression is LiteralExpressionSyntax &&
                                   q.Expression.Kind() == SyntaxKind.TrueLiteralExpression));

                if (methodReturnsHardcodedTrue)
                {
                    return(true);
                }
            }
            return(false);
        }
        private static SyntaxKind GetBinaryExpressionKind(AssignmentExpressionSyntax assignmentExpression)
        {
            switch (assignmentExpression.Kind())
            {
            case SyntaxKind.AddAssignmentExpression:
                return(SyntaxKind.AddExpression);

            case SyntaxKind.SubtractAssignmentExpression:
                return(SyntaxKind.SubtractExpression);

            case SyntaxKind.MultiplyAssignmentExpression:
                return(SyntaxKind.MultiplyExpression);

            case SyntaxKind.DivideAssignmentExpression:
                return(SyntaxKind.DivideExpression);

            case SyntaxKind.ModuloAssignmentExpression:
                return(SyntaxKind.ModuloExpression);

            case SyntaxKind.AndAssignmentExpression:
                return(SyntaxKind.BitwiseAndExpression);

            case SyntaxKind.OrAssignmentExpression:
                return(SyntaxKind.BitwiseOrExpression);

            case SyntaxKind.ExclusiveOrAssignmentExpression:
                return(SyntaxKind.ExclusiveOrExpression);

            case SyntaxKind.LeftShiftAssignmentExpression:
                return(SyntaxKind.LeftShiftExpression);

            case SyntaxKind.RightShiftAssignmentExpression:
                return(SyntaxKind.RightShiftExpression);
            }

            SyntaxDebug.Fail(assignmentExpression);
            return(SyntaxKind.None);
        }
            private bool IsSimpleForIncrementor(CS.Syntax.ForStatementSyntax node, string variableName)
            {
#if false
                name++;
                name--;
                ++name;
                --name;
                name += v3;
                name -= v3;
#endif
                if (node.Incrementors.Count == 1)
                {
                    ExpressionSyntax incrementor = node.Incrementors[0];
                    if (incrementor.IsKind(CS.SyntaxKind.PostIncrementExpression) ||
                        incrementor.IsKind(CS.SyntaxKind.PostDecrementExpression))
                    {
                        return(((CS.Syntax.PostfixUnaryExpressionSyntax)incrementor).Operand is CS.Syntax.IdentifierNameSyntax identifierName &&
                               identifierName.Identifier.ValueText == variableName);
                    }

                    if (incrementor.IsKind(CS.SyntaxKind.PreIncrementExpression) ||
                        incrementor.IsKind(CS.SyntaxKind.PreDecrementExpression))
                    {
                        return(((CS.Syntax.PrefixUnaryExpressionSyntax)incrementor).Operand is CS.Syntax.IdentifierNameSyntax identifierName &&
                               identifierName.Identifier.ValueText == variableName);
                    }

                    if (incrementor.IsKind(CS.SyntaxKind.AddAssignmentExpression) ||
                        incrementor.IsKind(CS.SyntaxKind.SubtractAssignmentExpression))
                    {
                        AssignmentExpressionSyntax binaryExpression = (CS.Syntax.AssignmentExpressionSyntax)incrementor;
                        return(binaryExpression.Left is CS.Syntax.IdentifierNameSyntax identifierName &&
                               identifierName.Identifier.ValueText == variableName);
                    }
                }

                return(false);
            }
Exemple #29
0
            public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax node)
            {
                // Note - leave this as SyntaxNode for now, we might have already re-written it
                var newNode = base.VisitAssignmentExpression(node);

                if (newNode.Kind() == SyntaxKind.SimpleAssignmentExpression)
                {
                    // It's okay to just look at the text, since we're explicitly looking for an
                    // identifier standing alone, and we know we're in a local's initializer.
                    // The text can only bind to the initializer.
                    var assignment = (AssignmentExpressionSyntax)newNode;
                    var name       = assignment.Left.Kind() == SyntaxKind.IdentifierName
                        ? (IdentifierNameSyntax)assignment.Left
                        : null;

                    if (name != null && IsReference(name))
                    {
                        return(assignment.Right);
                    }
                }

                return(newNode);
            }
        private static async Task <Document> ApplyObserveEventLamdaFixAsync(
            CancellationToken cancellationToken,
            CodeFixContext context,
            AssignmentExpressionSyntax assignment,
            bool usesArg)
        {
            var editor = await DocumentEditor.CreateAsync(context.Document, cancellationToken)
                         .ConfigureAwait(false);

            var eventSymbol      = (IEventSymbol)editor.SemanticModel.GetSymbolSafe(assignment.Left, cancellationToken);
            var observeSubscribe = GetObservableFromEventString(eventSymbol)
                                   .Replace("HANDLERTYPE", eventSymbol.Type.ToDisplayString())
                                   .Replace("ARGTYPE", ArgType(eventSymbol))
                                   .Replace("LEFT", assignment.Left.ToString())
                                   .Replace("LAMBDA", Lambda((ParenthesizedLambdaExpressionSyntax)assignment.Right, usesArg));

            editor.ReplaceNode(
                assignment,
                SyntaxFactory.ParseExpression(observeSubscribe)
                .WithLeadingTrivia(assignment.GetLeadingTrivia())
                .WithAdditionalAnnotations(Simplifier.Annotation));
            return(editor.GetChangedDocument());
        }
Exemple #31
0
        private BoundExpression BindAssignmentExpression(AssignmentExpressionSyntax syntax)
        {
            var name            = syntax.IdentifierToken.Text;
            var boundExpression = BindExpression(syntax.Expression);

            if (!_scope.TryLookup(name, out var variable))
            {
                _diagnostics.ReportUndefinedName(syntax.IdentifierToken.Span, name);
                return(boundExpression);
            }

            if (variable.IsReadOnly)
            {
                _diagnostics.ReportCannotAssign(syntax.EqualsToken.Span, name);
            }

            if (boundExpression.Type != variable.Type)
            {
                _diagnostics.ReportCannotConvert(syntax.Expression.Span, boundExpression.Type, variable.Type);
                return(boundExpression);
            }
            return(new BoundAssignmentExpression(variable, boundExpression));
        }
Exemple #32
0
        private Diagnostic AnalyzeSimpleAssignmentExpression(AssignmentExpressionSyntax node, SemanticModel semanticModel)
        {
            if (node.Right?.IsKind(SyntaxKind.NullLiteralExpression) is true)
            {
                var method = node.GetEnclosingMethod(semanticModel);
                if (method?.Parameters.Length > 0)
                {
                    var names = method.Parameters.Where(_ => _.RefKind == RefKind.None).Select(_ => _.Name).ToHashSet();

                    var name = node.Left.ToCleanedUpString();
                    if (names.Contains(name))
                    {
                        // TODO RKN: Check for ForEach
                        if (node.FirstAncestorOrSelf <SimpleLambdaExpressionSyntax>() != null)
                        {
                            return(Issue(name, node));
                        }
                    }
                }
            }

            return(null);
        }
        public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax node)
        {
            (bool anyLineTooLong, SyntaxTrivia newLeadingTrivia) = IsAnyLineTooLong(node);
            if (!anyLineTooLong)
            {
                return(base.VisitAssignmentExpression(node));
            }

            IList <SyntaxToken>        dotTokens     = GetDescendentTokens(node, SyntaxKind.DotToken);
            IList <SyntaxNode>         argumentNodes = GetArgumentNodes(node);
            AssignmentExpressionSyntax newNode;

            if (dotTokens.Count > argumentNodes.Count)
            {
                newNode = SplitLongLinesOnDotToken(node, dotTokens, newLeadingTrivia);
            }
            else
            {
                newNode = SplitLongLinesOnCommaToken(node, argumentNodes, newLeadingTrivia);
            }

            return(base.VisitAssignmentExpression(newNode));
        }
            public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax node)
            {
                // Note - leave this as SyntaxNode for now, we might have already re-written it
                var newNode = base.VisitAssignmentExpression(node);

                if (newNode.Kind() == SyntaxKind.SimpleAssignmentExpression)
                {
                    // It's okay to just look at the text, since we're explicitly looking for an
                    // identifier standing alone, and we know we're in a local's initializer.
                    // The text can only bind to the initializer.
                    var assignment = (AssignmentExpressionSyntax)newNode;
                    var name = assignment.Left.Kind() == SyntaxKind.IdentifierName
                        ? (IdentifierNameSyntax)assignment.Left
                        : null;

                    if (name != null && IsReference(name))
                    {
                        return assignment.Right;
                    }
                }

                return newNode;
            }
        // TupleExpression "(a, b) = qix"
        // ParenthesizedVariableDesignation "var (a, b) = quix" inside a DeclarationExpression
        public override void VisitAssignmentExpression(AssignmentExpressionSyntax node)
        {
            var leftTupleCount = GetTupleCount(node.Left);

            if (leftTupleCount != 0)
            {
                var assignmentRight = node.Right;
                var namedTypeSymbol = semanticModel.GetSymbolInfo(assignmentRight).Symbol?.GetSymbolType();
                if (namedTypeSymbol != null)
                {
                    var deconstructors = namedTypeSymbol.GetMembers("Deconstruct");
                    if (deconstructors.Length == 1)
                    {
                        UsedSymbols.Add(deconstructors.First());
                    }
                    else if (deconstructors.Length > 1 && FindDeconstructor(deconstructors, leftTupleCount) is {} deconstructor)
                    {
                        UsedSymbols.Add(deconstructor);
                    }
                }
            }

            base.VisitAssignmentExpression(node);
Exemple #36
0
        private static bool IsCompliantAssignmentInsideExpression(AssignmentExpressionSyntax assignment, ExpressionSyntax topParenthesizedExpression)
        {
            var expressionParent = topParenthesizedExpression.Parent.FirstAncestorOrSelf <ExpressionSyntax>();

            if (expressionParent == null)
            {
                // not inside an expression
                return(true);
            }

            if (IsCompliantCoalesceExpression(expressionParent, assignment))
            {
                return(true);
            }

            if (RelationalExpressionKinds.Contains(expressionParent.Kind()) &&
                IsInStatementCondition(expressionParent))
            {
                return(true);
            }

            return(AllowedParentExpressionKinds.Contains(expressionParent.Kind()));
        }
 private void CreateTempLocal(string tempLocalName, AssignmentExpressionSyntax statement)
 {
     PreSerializationStatements.Add(LocalDeclarationStatement
                                    (
                                        VariableDeclaration
                                        (
                                            IdentifierName
                                            (
                                                Identifier
                                                (
                                                    TriviaList(),
                                                    SyntaxKind.VarKeyword,
                                                    "var",
                                                    "var",
                                                    TriviaList()
                                                )
                                            )
                                        )
                                        .WithVariables
                                        (
                                            SingletonSeparatedList <VariableDeclaratorSyntax>
                                            (
                                                VariableDeclarator
                                                (
                                                    Identifier(tempLocalName)
                                                )
                                                .WithInitializer
                                                (
                                                    EqualsValueClause
                                                    (
                                                        statement.Right
                                                    )
                                                )
                                            )
                                        )
                                    ));
 }
Exemple #38
0
        public static async Task <Document> RefactorAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken)
        {
            SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            ExpressionSyntax condition = ifStatement.Condition;

            AssignmentExpressionSyntax assignment = GetSimpleAssignmentExpression(ifStatement.Statement);

            if (assignment.Right.IsKind(SyntaxKind.FalseLiteralExpression))
            {
                condition = LogicalNotExpression(condition.WithoutTrivia()).WithTriviaFrom(condition);
            }

            ExpressionStatementSyntax newNode = SimpleAssignmentExpressionStatement(assignment.Left, condition)
                                                .WithTriviaFrom(ifStatement)
                                                .WithFormatterAnnotation();

            SyntaxNode newRoot = root.ReplaceNode(ifStatement, newNode);

            return(document.WithSyntaxRoot(newRoot));
        }
Exemple #39
0
        public override void VisitAssignmentExpression(AssignmentExpressionSyntax node)
        {
            // Always get the right IR but not always the left. In some cases with setters we don't need the left. This avoids loading the left twice.
            IShaderIR leftIR  = null;
            IShaderIR rightIR = WalkAndGetResult(node.Right);

            // If the token isn't the assignment op, then this must be a compound assignment (e.g. '+=').
            var token = node.OperatorToken.Text;

            if (token != "=")
            {
                // To do the compound we have to load the left now.
                leftIR = WalkAndGetResult(node.Left);
                var lhsType = GetSymbolType(node.Left);
                var rhsType = GetSymbolType(node.Right);

                // Generate the token for the binary op in the compound (just strip the '=' off) and then visit the binary expression.
                var binaryOp = token.Substring(0, token.Length - 1);
                VisitBinaryExpression(node, lhsType, leftIR, rhsType, rightIR, binaryOp);
                // Do whatever remaining logic for the assignment with the result of the binary expression.
                rightIR = mContext.Pop();
            }

            // If the left side is actually a setter, then we have to flip the assignment around to call the setter
            var leftSymbol = GetSymbol(node.Left);

            // One complicated case is if the left is actually a member access (e.g. Vec3.XY = rhs).
            // In this case, we need to call the setter on Vec3 (the expression of the member access)
            if (node.Left is MemberAccessExpressionSyntax memberAccessNode && leftSymbol.IsStatic == false)
            {
                FunctionKey functionKey = null;
                // Try and get the function key for this symbol depending on if it's a field, property, etc...
                if (leftSymbol is IPropertySymbol propertySymbol && !propertySymbol.IsReadOnly)
                {
                    functionKey = new FunctionKey(propertySymbol.SetMethod);
                }
        private VariableState VisitAssignment(AssignmentExpressionSyntax node, ExecutionState state)
        {
            var            symbol   = state.GetSymbol(node.Left);
            MethodBehavior behavior = behaviorRepo.GetInjectableMethodBehavior(symbol);

            var variableState = VisitExpression(node.Right, state);

            if (node.Left is IdentifierNameSyntax)
            {
                var assignmentIdentifier = node.Left as IdentifierNameSyntax;
                state.UpdateValue(ResolveIdentifier(assignmentIdentifier.Identifier), variableState);
            }

            if (behavior != null &&                              //If the API is at risk
                variableState.taint != VariableTaint.CONSTANT && //Skip safe values
                variableState.taint != VariableTaint.SAFE)
            {
                var newRule    = LocaleUtil.GetDescriptor(behavior.vulnerabilityLocale);
                var diagnostic = Diagnostic.Create(newRule, node.GetLocation());
                state.AnalysisContext.ReportDiagnostic(diagnostic);
            }

            return(variableState);
        }
Exemple #41
0
        private static Task <Document> RemoveRedundantAssignmentBeforeReturnStatementAsync(
            Document document,
            AssignmentExpressionSyntax assignmentExpression,
            CancellationToken cancellationToken)
        {
            var statement = (StatementSyntax)assignmentExpression.Parent;

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            int index = statements.IndexOf(statement);

            statements = statements.RemoveAt(index);

            var returnStatement = (ReturnStatementSyntax)statement.NextStatement();

            SyntaxTriviaList trivia = statementsInfo
                                      .Parent
                                      .DescendantTrivia(TextSpan.FromBounds(statement.SpanStart, returnStatement.SpanStart))
                                      .ToSyntaxTriviaList()
                                      .EmptyIfWhitespace();

            trivia = statement
                     .GetLeadingTrivia()
                     .AddRange(trivia);

            returnStatement = returnStatement
                              .WithExpression(assignmentExpression.Right.WithTriviaFrom(returnStatement.Expression))
                              .WithLeadingTrivia(trivia)
                              .WithFormatterAnnotation();

            statements = statements.ReplaceAt(index, returnStatement);

            return(document.ReplaceStatementsAsync(statementsInfo, statements, cancellationToken));
        }
        public bool IsVulnerable(SemanticModel model, AssignmentExpressionSyntax syntax, DiagnosticId ruleId)
        {
            if (!ContainsCertificateValidationCallback(syntax))
            {
                return(false);
            }

            var symbol = ModelExtensions.GetSymbolInfo(model, syntax.Left).Symbol as IPropertySymbol;

            if (symbol == null)
            {
                return(false);
            }

            //TODO: only flagging those hard-coding a return value of true. Therefore could miss scenarios where the value is hardcoded in a const, config value.
            if (symbol.Name == "ServerCertificateValidationCallback" &&
                symbol.ContainingType.Name == "HttpWebRequest")
            {
                if (IsTrueLamdaExpression(syntax))
                {
                    return(true);
                }

                if (IsTrueDelegateMethod(syntax))
                {
                    return(true);
                }

                if (IsTrueMethod(model, syntax))
                {
                    return(true);
                }
            }

            return(false);
        }
Exemple #43
0
        private void CollectVariablesFromDeconstruction(
            ExpressionSyntax possibleTupleDeclaration,
            AssignmentExpressionSyntax deconstruction
            )
        {
            switch (possibleTupleDeclaration.Kind())
            {
            case SyntaxKind.TupleExpression:
            {
                var tuple = (TupleExpressionSyntax)possibleTupleDeclaration;
                foreach (ArgumentSyntax arg in tuple.Arguments)
                {
                    CollectVariablesFromDeconstruction(arg.Expression, deconstruction);
                }
                break;
            }

            case SyntaxKind.DeclarationExpression:
            {
                var declarationExpression =
                    (DeclarationExpressionSyntax)possibleTupleDeclaration;
                CollectVariablesFromDeconstruction(
                    declarationExpression.Designation,
                    declarationExpression.Type,
                    deconstruction
                    );
                break;
            }

            default:
            {
                Visit(possibleTupleDeclaration);
                break;
            }
            }
        }
Exemple #44
0
        public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax node)
        {
            var nodeSemanticModel = _semanticModel.Compilation.GetSemanticModel(node.SyntaxTree);
            var typeInfo          = nodeSemanticModel.GetTypeInfo(node);

            ExpressionSyntax replaceValueSyntaxNode = _randomTypeGenerator.ResolveType(typeInfo.Type.ToString());

            //if (typeInfo.Type.IsAbstract) // TODO: rethink this, might be abstract class, not interface
            //{
            //    //get a type that implements that interface
            //    string toBeResolvedType =
            //        _randomTypeGenerator.GetTypeForInterface(typeInfo.Type.Name);

            //    replaceValueSyntaxNode = toBeResolvedType != null ?
            //        _randomTypeGenerator.ResolveType(toBeResolvedType) : null;
            //}
            //else
            //{
            //    replaceValueSyntaxNode =
            //        _randomTypeGenerator.ResolveType(typeInfo.Type.ToString());
            //}

            if (replaceValueSyntaxNode != null)
            {
                var newAssignmentNode =
                    SyntaxFactory.AssignmentExpression(
                        node.Kind(),
                        node.Left,
                        replaceValueSyntaxNode).NormalizeWhitespace();

                var mutatedClassRoot = _classRootNode.ReplaceNode(node, newAssignmentNode);
                _mutantCreator.CreateNewMutant(mutatedClassRoot, false);
            }

            return(node);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="AssignmentExpression"/> class.
 /// </summary>
 /// <param name="syntaxNode"></param>
 public AssignmentExpression(AssignmentExpressionSyntax syntaxNode)
     : this(syntaxNode, null)
 {
 }
Exemple #46
0
 private static bool ReferenceInAssignmentRight(List <IdentifierNameSyntax> references, AssignmentExpressionSyntax currentAssignment)
 {
     return(references.Any(reference =>
                           reference.SpanStart >= currentAssignment.Right.SpanStart &&
                           reference.SpanStart < currentAssignment.Right.Span.End));
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="AssignmentExpression"/> class.
 /// </summary>
 /// <param name="syntaxNode"></param>
 /// <param name="semanticModel"></param>
 public AssignmentExpression(AssignmentExpressionSyntax syntaxNode, SemanticModel semanticModel)
     : base(syntaxNode, semanticModel)
 {
 }
Exemple #48
0
 private static bool InAnonymous(AssignmentExpressionSyntax currentAssignment, BlockSyntax declaringBlock)
 {
     return(currentAssignment.Ancestors()
            .TakeWhile(ancestor => ancestor != declaringBlock)
            .Any(ancestor => ancestor is AnonymousFunctionExpressionSyntax));
 }
Exemple #49
0
 private static bool InLoop(AssignmentExpressionSyntax currentAssignment, BlockSyntax declaringBlock)
 {
     return(currentAssignment.Ancestors()
            .TakeWhile(ancestor => ancestor != declaringBlock)
            .Any(ancestor => LoopKinds.Contains(ancestor.Kind())));
 }
 private static string GetOperatorText(AssignmentExpressionSyntax assignment)
 {
     return(GetOperatorText(GetPostfixUnaryOperatorKind(assignment)));
 }
        public static void Analyze(SyntaxNodeAnalysisContext context, AssignmentExpressionSyntax assignment)
        {
            switch (assignment.Kind())
            {
            case SyntaxKind.AddAssignmentExpression:
            case SyntaxKind.SubtractAssignmentExpression:
            {
                ExpressionSyntax left  = assignment.Left;
                ExpressionSyntax right = assignment.Right;

                if (left?.IsMissing == false &&
                    right?.IsNumericLiteralExpression(1) == true)
                {
                    ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(left, context.CancellationToken);

                    if (typeSymbol?.SupportsPrefixOrPostfixUnaryOperator() == true &&
                        !assignment.SpanContainsDirectives())
                    {
                        ReportDiagnostic(context, assignment);

                        SyntaxToken operatorToken = assignment.OperatorToken;

                        if (operatorToken.Span.Length == 2)
                        {
                            context.ReportDiagnostic(FadeOutDescriptor, Location.Create(assignment.SyntaxTree, new TextSpan(operatorToken.SpanStart, 1)));
                        }

                        context.ReportNode(FadeOutDescriptor, assignment.Right);
                    }
                }

                break;
            }

            case SyntaxKind.SimpleAssignmentExpression:
            {
                ExpressionSyntax left  = assignment.Left;
                ExpressionSyntax right = assignment.Right;

                if (left?.IsMissing == false &&
                    right?.IsMissing == false &&
                    right.IsKind(SyntaxKind.AddExpression, SyntaxKind.SubtractExpression))
                {
                    var binaryExpression         = (BinaryExpressionSyntax)right;
                    ExpressionSyntax binaryLeft  = binaryExpression.Left;
                    ExpressionSyntax binaryRight = binaryExpression.Right;

                    if (binaryLeft?.IsMissing == false &&
                        binaryRight?.IsNumericLiteralExpression(1) == true)
                    {
                        ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(left, context.CancellationToken);

                        if (typeSymbol?.SupportsPrefixOrPostfixUnaryOperator() == true &&
                            left.IsEquivalentTo(binaryLeft, topLevel: false) &&
                            !assignment.SpanContainsDirectives())
                        {
                            ReportDiagnostic(context, assignment);

                            context.ReportToken(FadeOutDescriptor, assignment.OperatorToken);
                            context.ReportNode(FadeOutDescriptor, binaryLeft);
                            context.ReportNode(FadeOutDescriptor, binaryRight);
                        }
                    }
                }

                break;
            }
            }
        }
Exemple #52
0
 private void ReportAssignmentOperatorError(AssignmentExpressionSyntax node, DiagnosticBag diagnostics, BoundExpression left, BoundExpression right, LookupResultKind resultKind)
 {
     if (((SyntaxKind)node.OperatorToken.RawKind == SyntaxKind.PlusEqualsToken || (SyntaxKind)node.OperatorToken.RawKind == SyntaxKind.MinusEqualsToken) &&
         (object)left.Type != null && left.Type.TypeKind == TypeKind.Delegate)
     {
         // Special diagnostic for delegate += and -= about wrong right-hand-side
         HashSet<DiagnosticInfo> useSiteDiagnostics = null;
         var conversion = this.Conversions.ClassifyConversionFromExpression(right, left.Type, ref useSiteDiagnostics);
         Debug.Assert(!conversion.IsImplicit);
         GenerateImplicitConversionError(diagnostics, right.Syntax, conversion, right, left.Type);
         // discard use-site diagnostics
     }
     else
     {
         ReportBinaryOperatorError(node, diagnostics, node.OperatorToken, left, right, resultKind);
     }
 }
		private bool MatchingAssignmentExpressionExists(
			AssignmentExpressionSyntax addAssignment,
			IEnumerable<AssignmentExpressionSyntax> subtractAssignments)
		{
			var changedAssignment = SyntaxFactory.AssignmentExpression(
				SyntaxKind.SubtractAssignmentExpression,
				addAssignment.Left,
				addAssignment.Right);

			return subtractAssignments.Any(x => x.IsEquivalentTo(changedAssignment));
		}
Exemple #54
0
        /// <summary>
        /// For "receiver.event += expr", produce "receiver.add_event(expr)".
        /// For "receiver.event -= expr", produce "receiver.remove_event(expr)".
        /// </summary>
        /// <remarks>
        /// Performs some validation of the accessor that couldn't be done in CheckEventValueKind, because
        /// the specific accessor wasn't known.
        /// </remarks>
        private BoundExpression BindEventAssignment(AssignmentExpressionSyntax node, BoundEventAccess left, BoundExpression right, BinaryOperatorKind opKind, DiagnosticBag diagnostics)
        {
            Debug.Assert(opKind == BinaryOperatorKind.Addition || opKind == BinaryOperatorKind.Subtraction);

            bool hasErrors = false;

            EventSymbol eventSymbol = left.EventSymbol;
            BoundExpression receiverOpt = left.ReceiverOpt;

            TypeSymbol delegateType = left.Type;

            HashSet<DiagnosticInfo> useSiteDiagnostics = null;
            Conversion argumentConversion = this.Conversions.ClassifyConversionFromExpression(right, delegateType, ref useSiteDiagnostics);

            if (!argumentConversion.IsImplicit || !argumentConversion.IsValid) // NOTE: dev10 appears to allow user-defined conversions here.
            {
                hasErrors = true;
                if (delegateType.IsDelegateType()) // Otherwise, suppress cascading.
                {
                    GenerateImplicitConversionError(diagnostics, node, argumentConversion, right, delegateType);
                }
            }

            BoundExpression argument = CreateConversion(right, argumentConversion, delegateType, diagnostics);

            bool isAddition = opKind == BinaryOperatorKind.Addition;
            MethodSymbol method = isAddition ? eventSymbol.AddMethod : eventSymbol.RemoveMethod;

            TypeSymbol type;
            if ((object)method == null)
            {
                type = this.GetSpecialType(SpecialType.System_Void, diagnostics, node); //we know the return type would have been void

                // There will be a diagnostic on the declaration if it is from source.
                if (!eventSymbol.OriginalDefinition.IsFromCompilation(this.Compilation))
                {
                    // CONSIDER: better error code?  ERR_EventNeedsBothAccessors?
                    Error(diagnostics, ErrorCode.ERR_MissingPredefinedMember, node, delegateType, SourceEventSymbol.GetAccessorName(eventSymbol.Name, isAddition));
                }
            }
            else if (eventSymbol.IsWindowsRuntimeEvent)
            {
                // Return type is actually void because this call will be later encapsulated in a call
                // to WindowsRuntimeMarshal.AddEventHandler or RemoveEventHandler, which has the return
                // type of void.
                type = this.GetSpecialType(SpecialType.System_Void, diagnostics, node);
            }
            else
            {
                type = method.ReturnType;
                if (!this.IsAccessible(method, ref useSiteDiagnostics, this.GetAccessThroughType(receiverOpt)))
                {
                    // CONSIDER: depending on the accessibility (e.g. if it's private), dev10 might just report the whole event bogus.
                    Error(diagnostics, ErrorCode.ERR_BadAccess, node, method);
                    hasErrors = true;
                }
            }

            diagnostics.Add(node, useSiteDiagnostics);

            return new BoundEventAssignmentOperator(
                syntax: node,
                @event: eventSymbol,
                isAddition: isAddition,
                isDynamic: right.HasDynamicType(),
                receiverOpt: receiverOpt,
                argument: argument,
                type: type,
                hasErrors: hasErrors);
        }
Exemple #55
0
        private BoundExpression BindCompoundAssignment(AssignmentExpressionSyntax node, DiagnosticBag diagnostics)
        {
            BoundExpression left = BindValue(node.Left, diagnostics, GetBinaryAssignmentKind(node.Kind()));
            BoundExpression right = BindValue(node.Right, diagnostics, BindValueKind.RValue);
            BinaryOperatorKind kind = SyntaxKindToBinaryOperatorKind(node.Kind());

            // If either operand is bad, don't try to do binary operator overload resolution; that will just
            // make cascading errors.  

            if (left.Kind == BoundKind.EventAccess)
            {
                BinaryOperatorKind kindOperator = kind.Operator();
                switch (kindOperator)
                {
                    case BinaryOperatorKind.Addition:
                    case BinaryOperatorKind.Subtraction:
                        return BindEventAssignment(node, (BoundEventAccess)left, right, kindOperator, diagnostics);

                        // fall-through for other operators, if RHS is dynamic we produce dynamic operation, otherwise we'll report an error ...
                }
            }

            if (left.HasAnyErrors || right.HasAnyErrors)
            {
                // NOTE: no overload resolution candidates.
                return new BoundCompoundAssignmentOperator(node, BinaryOperatorSignature.Error, left, right,
                    Conversion.NoConversion, Conversion.NoConversion, LookupResultKind.Empty, CreateErrorType(), hasErrors: true);
            }

            HashSet<DiagnosticInfo> useSiteDiagnostics = null;

            if (left.HasDynamicType() || right.HasDynamicType())
            {
                if (IsLegalDynamicOperand(right) && IsLegalDynamicOperand(left))
                {
                    var finalDynamicConversion = this.Compilation.Conversions.ClassifyConversionFromExpression(right, left.Type, ref useSiteDiagnostics);
                    diagnostics.Add(node, useSiteDiagnostics);

                    return new BoundCompoundAssignmentOperator(
                        node,
                        new BinaryOperatorSignature(
                            kind.WithType(BinaryOperatorKind.Dynamic).WithOverflowChecksIfApplicable(CheckOverflowAtRuntime),
                            left.Type,
                            right.Type,
                            Compilation.DynamicType),
                        left,
                        right,
                        Conversion.NoConversion,
                        finalDynamicConversion,
                        LookupResultKind.Viable,
                        left.Type,
                        hasErrors: false);
                }
                else
                {
                    Error(diagnostics, ErrorCode.ERR_BadBinaryOps, node, node.OperatorToken.Text, left.Display, right.Display);

                    // error: operator can't be applied on dynamic and a type that is not convertible to dynamic:
                    return new BoundCompoundAssignmentOperator(node, BinaryOperatorSignature.Error, left, right,
                        Conversion.NoConversion, Conversion.NoConversion, LookupResultKind.Empty, CreateErrorType(), hasErrors: true);
                }
            }

            if (left.Kind == BoundKind.EventAccess && !CheckEventValueKind((BoundEventAccess)left, BindValueKind.Assignment, diagnostics))
            {
                // If we're in a place where the event can be assigned, then continue so that we give errors
                // about the types and operator not lining up.  Otherwise, just report that the event can't
                // be used here.

                // NOTE: no overload resolution candidates.
                return new BoundCompoundAssignmentOperator(node, BinaryOperatorSignature.Error, left, right,
                    Conversion.NoConversion, Conversion.NoConversion, LookupResultKind.NotAVariable, CreateErrorType(), hasErrors: true);
            }

            // A compound operator, say, x |= y, is bound as x = (X)( ((T)x) | ((T)y) ). We must determine
            // the binary operator kind, the type conversions from each side to the types expected by
            // the operator, and the type conversion from the return type of the operand to the left hand side.
            // 
            // We can get away with binding the right-hand-side of the operand into its converted form early.
            // This is convenient because first, it is never rewritten into an access to a temporary before
            // the conversion, and second, because that is more convenient for the "d += lambda" case.
            // We want to have the converted (bound) lambda in the bound tree, not the unconverted unbound lambda.

            LookupResultKind resultKind;
            ImmutableArray<MethodSymbol> originalUserDefinedOperators;
            BinaryOperatorAnalysisResult best = this.BinaryOperatorOverloadResolution(kind, left, right, node, diagnostics, out resultKind, out originalUserDefinedOperators);
            if (!best.HasValue)
            {
                ReportAssignmentOperatorError(node, diagnostics, left, right, resultKind);
                return new BoundCompoundAssignmentOperator(node, BinaryOperatorSignature.Error, left, right,
                    Conversion.NoConversion, Conversion.NoConversion, resultKind, originalUserDefinedOperators, CreateErrorType(), hasErrors: true);
            }

            // The rules in the spec for determining additional errors are bit confusing. In particular
            // this line is misleading:
            //
            // "for predefined operators ... x op= y is permitted if both x op y and x = y are permitted"
            //
            // That's not accurate in many cases. For example, "x += 1" is permitted if x is string or
            // any enum type, but x = 1 is not legal for strings or enums.
            //
            // The correct rules are spelled out in the spec:
            //
            // Spec §7.17.2:
            // An operation of the form x op= y is processed by applying binary operator overload 
            // resolution (§7.3.4) as if the operation was written x op y. 
            // Let R be the return type of the selected operator, and T the type of x. Then,
            //
            // * If an implicit conversion from an expression of type R to the type T exists, 
            //   the operation is evaluated as x = (T)(x op y), except that x is evaluated only once. 
            //   [no cast is inserted, unless the conversion is implicit dynamic]
            // * Otherwise, if 
            //   (1) the selected operator is a predefined operator, 
            //   (2) if R is explicitly convertible to T, and 
            //   (3.1) if y is implicitly convertible to T or 
            //   (3.2) the operator is a shift operator... [then cast the result to T]
            // * Otherwise ... a binding-time error occurs.

            // So let's tease that out. There are two possible errors: the conversion from the
            // operator result type to the left hand type could be bad, and the conversion
            // from the right hand side to the left hand type could be bad. 
            //
            // We report the first error under the following circumstances:
            //
            // * The final conversion is bad, or
            // * The final conversion is explicit and the selected operator is not predefined
            //
            // We report the second error under the following circumstances:
            //
            // * The final conversion is explicit, and
            // * The selected operator is predefined, and
            // * the selected operator is not a shift, and
            // * the right-to-left conversion is not implicit

            bool hasError = false;

            BinaryOperatorSignature bestSignature = best.Signature;

            if (CheckOverflowAtRuntime)
            {
                bestSignature = new BinaryOperatorSignature(
                    bestSignature.Kind.WithOverflowChecksIfApplicable(CheckOverflowAtRuntime),
                    bestSignature.LeftType,
                    bestSignature.RightType,
                    bestSignature.ReturnType,
                    bestSignature.Method);
            }

            var leftType = left.Type;

            Conversion finalConversion = Conversions.ClassifyConversionFromType(bestSignature.ReturnType, leftType, ref useSiteDiagnostics);
            BoundExpression rightConverted = CreateConversion(right, best.RightConversion, bestSignature.RightType, diagnostics);

            bool isPredefinedOperator = !bestSignature.Kind.IsUserDefined();

            if (!finalConversion.IsValid || finalConversion.IsExplicit && !isPredefinedOperator)
            {
                hasError = true;
                GenerateImplicitConversionError(diagnostics, this.Compilation, node, finalConversion, bestSignature.ReturnType, leftType);
            }
            else
            {
                ReportDiagnosticsIfObsolete(diagnostics, finalConversion, node, hasBaseReceiver: false);
            }

            if (finalConversion.IsExplicit &&
                isPredefinedOperator &&
                !kind.IsShift())
            {
                Conversion rightToLeftConversion = this.Conversions.ClassifyConversionFromExpression(right, leftType, ref useSiteDiagnostics);
                if (!rightToLeftConversion.IsImplicit || !rightToLeftConversion.IsValid)
                {
                    hasError = true;
                    GenerateImplicitConversionError(diagnostics, node, rightToLeftConversion, right, leftType);
                }
            }

            diagnostics.Add(node, useSiteDiagnostics);

            if (!hasError && leftType.IsVoidPointer())
            {
                Error(diagnostics, ErrorCode.ERR_VoidError, node);
                hasError = true;
            }

            // Any events that weren't handled above (by BindEventAssignment) are bad - we just followed this 
            // code path for the diagnostics.  Make sure we don't report success.
            Debug.Assert(left.Kind != BoundKind.EventAccess || hasError);

            Conversion leftConversion = best.LeftConversion;
            ReportDiagnosticsIfObsolete(diagnostics, leftConversion, node, hasBaseReceiver: false);

            return new BoundCompoundAssignmentOperator(node, bestSignature, left, rightConverted,
                leftConversion, finalConversion, resultKind, originalUserDefinedOperators, leftType, hasError);
        }
        private ExpressionSyntax ParseSubExpression(uint precedence)
        {
            if (Current.Kind == SyntaxKind.CompileKeyword)
            {
                var compile = Match(SyntaxKind.CompileKeyword);
                var shaderTarget = Match(SyntaxKind.IdentifierToken);
                var shaderFunctionName = ParseIdentifier();
                var shaderFunction = new InvocationExpressionSyntax(shaderFunctionName, ParseParenthesizedArgumentList(false));
                return new CompileExpressionSyntax(compile, shaderTarget, shaderFunction);
            }

            ExpressionSyntax leftOperand;
            SyntaxKind opKind;

            // No left operand, so we need to parse one -- possibly preceded by a
            // unary operator.
            var tk = Current.Kind;
            if (SyntaxFacts.IsPrefixUnaryExpression(tk))
            {
                opKind = SyntaxFacts.GetPrefixUnaryExpression(tk);
                leftOperand = ParsePrefixUnaryExpression(opKind);
            }
            else
            {
                // Not a unary operator - get a primary expression.
                leftOperand = ParseTerm();
            }

            while (true)
            {
                // We either have a binary or assignment operator here, or we're finished.
                tk = Current.Kind;

                var isAssignmentOperator = false;
                if (SyntaxFacts.IsBinaryExpression(tk)
                    && (!_greaterThanTokenIsNotOperator || tk != SyntaxKind.GreaterThanToken)
                    && ((tk != SyntaxKind.GreaterThanToken || !_allowGreaterThanTokenAroundRhsExpression) && Lookahead.Kind != SyntaxKind.SemiToken))
                {
                    opKind = SyntaxFacts.GetBinaryExpression(tk);
                }
                else if (SyntaxFacts.IsAssignmentExpression(tk))
                {
                    opKind = SyntaxFacts.GetAssignmentExpression(tk);
                    isAssignmentOperator = true;
                }
                else
                {
                    break;
                }

                var newPrecedence = SyntaxFacts.GetOperatorPrecedence(opKind);

                Debug.Assert(newPrecedence > 0); // All binary operators must have precedence > 0!

                // Check the precedence to see if we should "take" this operator
                if (newPrecedence < precedence)
                    break;

                // Same precedence, but not right-associative -- deal with this "later"
                if (newPrecedence == precedence && !SyntaxFacts.IsRightAssociative(opKind))
                    break;

                // Precedence is okay, so we'll "take" this operator.
                var opToken = NextToken();

                SyntaxToken lessThanToken = null;
                if (isAssignmentOperator && _allowGreaterThanTokenAroundRhsExpression)
                    lessThanToken = NextTokenIf(SyntaxKind.LessThanToken);

                var rightOperand = ParseSubExpression(newPrecedence);

                SyntaxToken greaterThanToken = null;
                if (lessThanToken != null)
                    greaterThanToken = NextTokenIf(SyntaxKind.GreaterThanToken);

                if (isAssignmentOperator)
                    leftOperand = new AssignmentExpressionSyntax(opKind, leftOperand, opToken, lessThanToken, rightOperand, greaterThanToken);
                else
                    leftOperand = new BinaryExpressionSyntax(opKind, leftOperand, opToken, rightOperand);
            }

            var conditionalPrecedence = SyntaxFacts.GetOperatorPrecedence(SyntaxKind.ConditionalExpression);
            if (tk == SyntaxKind.QuestionToken && precedence <= conditionalPrecedence)
            {
                var questionToken = NextToken();

                var colonLeft = ParseSubExpression(conditionalPrecedence);
                var colon = Match(SyntaxKind.ColonToken);

                var colonRight = ParseSubExpression(conditionalPrecedence);
                leftOperand = new ConditionalExpressionSyntax(leftOperand, questionToken, colonLeft, colon, colonRight);
            }

            return leftOperand;
        }
        private BoundAssignmentOperator BindAssignment(AssignmentExpressionSyntax node, DiagnosticBag diagnostics)
        {
            Debug.Assert(node != null);
            Debug.Assert(node.Left != null);
            Debug.Assert(node.Right != null);

            var op1 = BindValue(node.Left, diagnostics, BindValueKind.Assignment); // , BIND_MEMBERSET);
            var op2 = BindValue(node.Right, diagnostics, BindValueKind.RValue); // , BIND_RVALUEREQUIRED);

            return BindAssignment(node, op1, op2, diagnostics);
        }
        private BoundAssignmentOperator BindAssignment(AssignmentExpressionSyntax node, BoundExpression op1, BoundExpression op2, DiagnosticBag diagnostics)
        {
            Debug.Assert(op1 != null);
            Debug.Assert(op2 != null);

            bool hasErrors = (op1.HasAnyErrors || op2.HasAnyErrors);

            if (!op1.HasAnyErrors)
            {
                // Build bound conversion. The node might not be used if this is a dynamic conversion 
                // but diagnostics should be reported anyways.
                var conversion = GenerateConversionForAssignment(op1.Type, op2, diagnostics);

                // If the result is a dynamic assignment operation (SetMember or SetIndex), 
                // don't generate the boxing conversion to the dynamic type.
                // Leave the values as they are, and deal with the conversions at runtime.
                if (op1.Kind != BoundKind.DynamicIndexerAccess &&
                    op1.Kind != BoundKind.DynamicMemberAccess &&
                    op1.Kind != BoundKind.DynamicObjectInitializerMember)
                {
                    op2 = conversion;
                }
            }

            TypeSymbol type;
            if ((op1.Kind == BoundKind.EventAccess) &&
                ((BoundEventAccess)op1).EventSymbol.IsWindowsRuntimeEvent)
            {
                // Event assignment is a call to void WindowsRuntimeMarshal.AddEventHandler<T>().
                type = this.GetSpecialType(SpecialType.System_Void, diagnostics, node);
            }
            else
            {
                type = op1.Type;
            }

            return new BoundAssignmentOperator(node, op1, op2, type, hasErrors: hasErrors);
        }
 private static void CheckRightExpressionForRemovableToStringCall(SyntaxNodeAnalysisContext context,
                                                                  AssignmentExpressionSyntax assignment)
 {
     CheckExpressionForRemovableToStringCall(context, assignment.Right, assignment.Left, 1);
 }
Exemple #60
0
 public override void VisitAssignmentExpression(AssignmentExpressionSyntax node)
 {
     base.VisitAssignmentExpression(node);
     CheckAssignment(node.Left, node.Right);
 }