/// <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); } } }
/// <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)); }
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); }
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()); }
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)); }
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);
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 ) ) ) ) )); }
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)); }
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); }
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); }
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; } } }
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) { }
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) { }
private static bool InAnonymous(AssignmentExpressionSyntax currentAssignment, BlockSyntax declaringBlock) { return(currentAssignment.Ancestors() .TakeWhile(ancestor => ancestor != declaringBlock) .Any(ancestor => ancestor is AnonymousFunctionExpressionSyntax)); }
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; } } }
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)); }
/// <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); }
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); }
public override void VisitAssignmentExpression(AssignmentExpressionSyntax node) { base.VisitAssignmentExpression(node); CheckAssignment(node.Left, node.Right); }