internal static string GetResolvedString(SyntaxNodeAnalysisContext context, ExpressionSyntax expression, ref bool isNotConstant) { if (expression == null) return string.Empty; string result; if (_conditionalWeakTable.TryGetValue(expression, out result)) { return result; } switch (expression.Kind()) { case SyntaxKind.AddExpression: var addExpression = (BinaryExpressionSyntax)expression; result = GetResolvedString(context, addExpression.Left, ref isNotConstant) + GetResolvedString(context, addExpression.Right, ref isNotConstant); break; case SyntaxKind.IdentifierName: var value = context.SemanticModel.GetConstantValue(expression); result = value.HasValue ? value.Value as string : string.Empty; break; case SyntaxKind.StringLiteralExpression: var literalExpression = (LiteralExpressionSyntax)expression; result = literalExpression.Token.Value as string; break; default: isNotConstant = true; result = string.Empty; break; } _conditionalWeakTable.Add(expression, result); return result; }
static bool CanBeNull(SemanticModel semanticModel, ExpressionSyntax expression, CancellationToken cancellationToken) { var info = semanticModel.GetTypeInfo(expression, cancellationToken); if (info.ConvertedType.IsReferenceType || info.ConvertedType.IsNullableType()) return true; return false; }
void Check(SyntaxNodeAnalysisContext nodeContext, ExpressionSyntax condition) { if (condition == null) return; if (condition.IsKind(SyntaxKind.TrueLiteralExpression) || condition.IsKind(SyntaxKind.FalseLiteralExpression)) return; var resolveResult = nodeContext.SemanticModel.GetConstantValue(condition); if (!resolveResult.HasValue || !(resolveResult.Value is bool)) return; var value = (bool)resolveResult.Value; nodeContext.ReportDiagnostic(Diagnostic.Create( descriptor.Id, descriptor.Category, string.Format(descriptor.MessageFormat.ToString(), value), descriptor.DefaultSeverity, descriptor.DefaultSeverity, descriptor.IsEnabledByDefault, 4, descriptor.Title, descriptor.Description, descriptor.HelpLinkUri, condition.GetLocation(), null, new[] { value.ToString() } )); }
public static bool IsComplexExpression(ExpressionSyntax expr) { var loc = expr.GetLocation().GetLineSpan(); return loc.StartLinePosition.Line != loc.EndLinePosition.Line || expr is ConditionalExpressionSyntax || expr is BinaryExpressionSyntax; }
private static bool CheckExpression(ExpressionSyntax constant, ExpressionSyntax modulus, out int constantValue) { return SillyBitwiseOperation.TryGetConstantIntValue(constant, out constantValue) && constantValue != 0 && ExpressionIsModulus(modulus); }
/// <param name="typeSyntax">The argument to typeof.</param> /// <param name="allowedMap"> /// Keys are GenericNameSyntax nodes representing unbound generic types. /// Values are false if the node should result in an error and true otherwise. /// </param> /// <param name="isUnboundGenericType">True if no constructed generic type was encountered.</param> public static void Visit(ExpressionSyntax typeSyntax, out Dictionary<GenericNameSyntax, bool> allowedMap, out bool isUnboundGenericType) { OpenTypeVisitor visitor = new OpenTypeVisitor(); visitor.Visit(typeSyntax); allowedMap = visitor.allowedMap; isUnboundGenericType = visitor.seenGeneric && !visitor.seenConstructed; }
private static bool IsExpectedActualAssertion(ExpressionSyntax expression) { var expr = expression as MemberAccessExpressionSyntax; if (expr == null) { return false; } var identifier = expr.Expression as IdentifierNameSyntax; if (identifier == null) { return false; } if (identifier.Identifier.Text != "Assert") { return false; } var methodName = expr.Name.Identifier.Text; if (methodName == "Equal" // Xunit || methodName == "AreEqual" // NUnit, MSTest || methodName == "NotEqual" // Xunit || methodName == "AreNotEqual" // NUnit, MSTest ) { return true; } return false; }
internal static void BasicNameVerification(ExpressionSyntax nameTree, string name) { // Verification of the change Assert.IsType(typeof(IdentifierNameSyntax), nameTree); var genericName = nameTree as IdentifierNameSyntax; Assert.Equal(genericName.ToString(), name); }
/// <summary> /// Analyzes if type information is obvious to the reader by simply looking at the assignment expression. /// </summary> /// <remarks> /// <paramref name="typeInDeclaration"/> accepts null, to be able to cater to codegen features /// that are about to generate a local declaration and do not have this information to pass in. /// Things (like analyzers) that do have a local declaration already, should pass this in. /// </remarks> public static bool IsTypeApparentInAssignmentExpression( TypeStylePreference stylePreferences, ExpressionSyntax initializerExpression, SemanticModel semanticModel, CancellationToken cancellationToken, ITypeSymbol typeInDeclaration = null) { // default(type) if (initializerExpression.IsKind(SyntaxKind.DefaultExpression)) { return true; } // literals, use var if options allow usage here. if (initializerExpression.IsAnyLiteralExpression()) { return stylePreferences.HasFlag(TypeStylePreference.ImplicitTypeForIntrinsicTypes); } // constructor invocations cases: // = new type(); if (initializerExpression.IsKind(SyntaxKind.ObjectCreationExpression) && !initializerExpression.IsKind(SyntaxKind.AnonymousObjectCreationExpression)) { return true; } // explicit conversion cases: // (type)expr, expr is type, expr as type if (initializerExpression.IsKind(SyntaxKind.CastExpression) || initializerExpression.IsKind(SyntaxKind.IsExpression) || initializerExpression.IsKind(SyntaxKind.AsExpression)) { return true; } // other Conversion cases: // a. conversion with helpers like: int.Parse methods // b. types that implement IConvertible and then invoking .ToType() // c. System.Convert.Totype() var memberName = GetRightmostInvocationExpression(initializerExpression).GetRightmostName(); if (memberName == null) { return false; } var methodSymbol = semanticModel.GetSymbolInfo(memberName, cancellationToken).Symbol as IMethodSymbol; if (methodSymbol == null) { return false; } if (memberName.IsRightSideOfDot()) { var containingTypeName = memberName.GetLeftSideOfDot(); return IsPossibleCreationOrConversionMethod(methodSymbol, typeInDeclaration, semanticModel, containingTypeName, cancellationToken); } return false; }
internal static bool? GetBool(ExpressionSyntax trueExpression) { var pExpr = trueExpression as LiteralExpressionSyntax; if (pExpr == null || !(pExpr.Token.Value is bool)) return null; return (bool)pExpr.Token.Value; }
internal static void ArrayNameVerification(ExpressionSyntax nameTree, string arrayName, int numRanks) { Assert.IsType(typeof(ArrayTypeSyntax), nameTree); var arrayType = nameTree as ArrayTypeSyntax; Assert.Equal(arrayType.ElementType.ToString(), arrayName); Assert.Equal(arrayType.RankSpecifiers.Count(), numRanks); }
public static bool ContainsCheck(ExpressionSyntax expr) { if (expr is InvocationExpressionSyntax) { var i = (InvocationExpressionSyntax)expr; if (i.ArgumentList.Arguments.Count == 1) { // include some special methods from QuickGraph return new string[] { "Contains", "ContainsVertex", "ContainsEdge", "ContainsKey" }.Any(n => n.Equals(SimpleMethodName(i))); } else { return false; } } else if (expr is PrefixUnaryExpressionSyntax && expr.Kind == SyntaxKind.LogicalNotExpression) { return ContainsCheck(((PrefixUnaryExpressionSyntax)expr).Operand); } else { return false; } }
// TODO: Add support for Expression<T> private IEnumerable<ITypeSymbol> GetTypes(ExpressionSyntax expression) { if (seenExpressionGetType.Add(expression)) { IEnumerable<ITypeSymbol> types; // BUG: (vladres) Are following expressions parenthesized correctly? // BUG: // BUG: (davip) It is parenthesized incorrectly. This problem was introduced in Changeset 822325 when // BUG: this method was changed from returning a single ITypeSymbol to returning an IEnumerable<ITypeSymbol> // BUG: to better deal with overloads. The old version was: // BUG: // BUG: if (!IsUnusableType(type = GetTypeSimple(expression)) || // BUG: !IsUnusableType(type = GetTypeComplex(expression))) // BUG: { return type; } // BUG: // BUG: The intent is to only use *usable* types, whether simple or complex. I have confirmed this intent with Ravi, who made the change. // BUG: // BUG: Note that the current implementation of GetTypesComplex and GetTypesSimple already ensure the returned value // BUG: is a usable type, so there should not (currently) be any observable effect of this logic error. // BUG: // BUG: (vladres) Please remove this comment once the bug is fixed. if ((types = GetTypesSimple(expression).Where(t => !IsUnusableType(t))).Any() || (types = GetTypesComplex(expression)).Where(t => !IsUnusableType(t)).Any()) { return types; } } return SpecializedCollections.EmptyEnumerable<ITypeSymbol>(); }
private Document IntroduceLocalDeclarationIntoLambda( SemanticDocument document, ExpressionSyntax expression, IdentifierNameSyntax newLocalName, LocalDeclarationStatementSyntax declarationStatement, SyntaxNode oldLambda, bool allOccurrences, CancellationToken cancellationToken) { var oldBody = oldLambda is ParenthesizedLambdaExpressionSyntax ? (ExpressionSyntax)((ParenthesizedLambdaExpressionSyntax)oldLambda).Body : (ExpressionSyntax)((SimpleLambdaExpressionSyntax)oldLambda).Body; var rewrittenBody = Rewrite( document, expression, newLocalName, document, oldBody, allOccurrences, cancellationToken); var delegateType = document.SemanticModel.GetTypeInfo(oldLambda, cancellationToken).ConvertedType as INamedTypeSymbol; var newBody = delegateType != null && delegateType.DelegateInvokeMethod != null && delegateType.DelegateInvokeMethod.ReturnsVoid ? SyntaxFactory.Block(declarationStatement) : SyntaxFactory.Block(declarationStatement, SyntaxFactory.ReturnStatement(rewrittenBody)); newBody = newBody.WithAdditionalAnnotations(Formatter.Annotation); var newLambda = oldLambda is ParenthesizedLambdaExpressionSyntax ? ((ParenthesizedLambdaExpressionSyntax)oldLambda).WithBody(newBody) : (SyntaxNode)((SimpleLambdaExpressionSyntax)oldLambda).WithBody(newBody); var newRoot = document.Root.ReplaceNode(oldLambda, newLambda); return document.Document.WithSyntaxRoot(newRoot); }
/// <summary> /// The Enumerable.Last method will only special case indexable types that implement <see cref="IList{T}" />. Types /// which implement only <see cref="IReadOnlyList{T}"/> will be treated the same as IEnumerable{T} and go through a /// full enumeration. This method identifies such types. /// /// At this point it only identifies <see cref="IReadOnlyList{T}"/> directly but could easily be extended to support /// any type which has an index and count property. /// </summary> private bool IsTypeWithInefficientLinqMethods(SyntaxNodeAnalysisContext context, ExpressionSyntax targetSyntax, ITypeSymbol readonlyListType, ITypeSymbol listType) { var targetTypeInfo = context.SemanticModel.GetTypeInfo(targetSyntax); if (targetTypeInfo.Type == null) { return false; } var targetType = targetTypeInfo.Type; // If this type is simply IReadOnlyList<T> then no further checking is needed. if (targetType.TypeKind == TypeKind.Interface && targetType.OriginalDefinition.Equals(readonlyListType)) { return true; } bool implementsReadOnlyList = false; bool implementsList = false; foreach (var current in targetType.AllInterfaces) { if (current.OriginalDefinition.Equals(readonlyListType)) { implementsReadOnlyList = true; } if (current.OriginalDefinition.Equals(listType)) { implementsList = true; } } return implementsReadOnlyList && !implementsList; }
protected MemberSyntax(ExpressionSyntax expression) { if (expression == null) throw new ArgumentNullException("expression"); Expression = expression; }
private IEnumerable<ITypeSymbol> GetTypesSimple(ExpressionSyntax expression) { if (expression != null) { var typeInfo = SemanticModel.GetTypeInfo(expression, CancellationToken); var symbolInfo = SemanticModel.GetSymbolInfo(expression, CancellationToken); if (symbolInfo.CandidateReason != CandidateReason.WrongArity) { ITypeSymbol type = typeInfo.Type; // If it bound to a method, try to get the Action/Func form of that method. if (type == null && symbolInfo.GetAllSymbols().Count() == 1 && symbolInfo.GetAllSymbols().First().Kind == SymbolKind.Method) { var method = symbolInfo.GetAllSymbols().First(); type = method.ConvertToType(this.Compilation); } if (IsUsableTypeFunc(type)) { return SpecializedCollections.SingletonEnumerable(type); } } } return SpecializedCollections.EmptyEnumerable<ITypeSymbol>(); }
/// <summary> /// There are two kinds of deconstruction-assignments which this binding handles: tuple and non-tuple. /// /// Returns a BoundDeconstructionAssignmentOperator with a list of deconstruction steps and assignment steps. /// Deconstruct steps for tuples have no invocation to Deconstruct, but steps for non-tuples do. /// The caller is responsible for releasing all the ArrayBuilders in checkedVariables. /// </summary> private BoundDeconstructionAssignmentOperator BindDeconstructionAssignment( CSharpSyntaxNode node, ExpressionSyntax right, ArrayBuilder<DeconstructionVariable> checkedVariables, DiagnosticBag diagnostics, bool isDeclaration, BoundDeconstructValuePlaceholder rhsPlaceholder = null) { // receiver for first Deconstruct step var boundRHS = rhsPlaceholder ?? BindValue(right, diagnostics, BindValueKind.RValue); boundRHS = FixTupleLiteral(checkedVariables, boundRHS, node, diagnostics); if ((object)boundRHS.Type == null) { // we could still not infer a type for the RHS FailRemainingInferences(checkedVariables, diagnostics); return new BoundDeconstructionAssignmentOperator( node, isDeclaration, FlattenDeconstructVariables(checkedVariables), boundRHS, ImmutableArray<BoundDeconstructionDeconstructStep>.Empty, ImmutableArray<BoundDeconstructionAssignmentStep>.Empty, ImmutableArray<BoundDeconstructionAssignmentStep>.Empty, ImmutableArray<BoundDeconstructionConstructionStep>.Empty, GetSpecialType(SpecialType.System_Void, diagnostics, node), hasErrors: true); } var deconstructionSteps = ArrayBuilder<BoundDeconstructionDeconstructStep>.GetInstance(1); var conversionSteps = ArrayBuilder<BoundDeconstructionAssignmentStep>.GetInstance(1); var assignmentSteps = ArrayBuilder<BoundDeconstructionAssignmentStep>.GetInstance(1); var constructionStepsOpt = isDeclaration ? null : ArrayBuilder<BoundDeconstructionConstructionStep>.GetInstance(1); bool hasErrors = !DeconstructIntoSteps( new BoundDeconstructValuePlaceholder(boundRHS.Syntax, boundRHS.Type), node, diagnostics, checkedVariables, deconstructionSteps, conversionSteps, assignmentSteps, constructionStepsOpt); TypeSymbol returnType = isDeclaration ? GetSpecialType(SpecialType.System_Void, diagnostics, node) : hasErrors ? CreateErrorType() : constructionStepsOpt.Last().OutputPlaceholder.Type; var deconstructions = deconstructionSteps.ToImmutableAndFree(); var conversions = conversionSteps.ToImmutableAndFree(); var assignments = assignmentSteps.ToImmutableAndFree(); var constructions = isDeclaration ? default(ImmutableArray<BoundDeconstructionConstructionStep>) : constructionStepsOpt.ToImmutableAndFree(); FailRemainingInferences(checkedVariables, diagnostics); return new BoundDeconstructionAssignmentOperator( node, isDeclaration, FlattenDeconstructVariables(checkedVariables), boundRHS, deconstructions, conversions, assignments, constructions, returnType, hasErrors: hasErrors); }
private static bool IsRequiredCastForReferenceEqualityComparison(ITypeSymbol outerType, CastExpressionSyntax castExpression, SemanticModel semanticModel, out ExpressionSyntax other) { if (outerType.SpecialType == SpecialType.System_Object) { var expression = castExpression.WalkUpParentheses(); var parentNode = expression.Parent; if (parentNode.IsKind(SyntaxKind.EqualsExpression) || parentNode.IsKind(SyntaxKind.NotEqualsExpression)) { // Reference comparison. var binaryExpression = (BinaryExpressionSyntax)parentNode; other = binaryExpression.Left == expression ? binaryExpression.Right : binaryExpression.Left; // Explicit cast not required if we are comparing with type parameter with a class constraint. var otherType = semanticModel.GetTypeInfo(other).Type; if (otherType != null && otherType.TypeKind != TypeKind.TypeParameter) { return !other.WalkDownParentheses().IsKind(SyntaxKind.CastExpression); } } } other = null; return false; }
internal static bool CheckExceptionType(SemanticModel model, ObjectCreationExpressionSyntax objectCreateExpression, out ExpressionSyntax paramNode) { paramNode = null; var type = model.GetTypeInfo(objectCreateExpression).Type; if (type == null) return false; if (type.Name == typeof(ArgumentException).Name) { if (objectCreateExpression.ArgumentList.Arguments.Count >= 2) { paramNode = objectCreateExpression.ArgumentList.Arguments[1].Expression; } return paramNode != null; } if (type.Name == typeof(ArgumentNullException).Name || type.Name == typeof(ArgumentOutOfRangeException).Name || type.Name == "DuplicateWaitObjectException") { if (objectCreateExpression.ArgumentList.Arguments.Count >= 1) { paramNode = objectCreateExpression.ArgumentList.Arguments[0].Expression; } return paramNode != null; } return false; }
public CallSyntax(ExpressionSyntax expression, IEnumerable<ExpressionSyntax> arguments) { Requires.NotNull(expression, nameof(expression)); Expression = expression; Arguments = arguments.ToList(); }
internal void CollectLocalsFromDeconstruction( ExpressionSyntax declaration, LocalDeclarationKind kind, ArrayBuilder<LocalSymbol> locals, SyntaxNode deconstructionStatement, Binder enclosingBinderOpt = null) { switch (declaration.Kind()) { case SyntaxKind.TupleExpression: { var tuple = (TupleExpressionSyntax)declaration; foreach (var arg in tuple.Arguments) { CollectLocalsFromDeconstruction(arg.Expression, kind, locals, deconstructionStatement, enclosingBinderOpt); } break; } case SyntaxKind.DeclarationExpression: { var declarationExpression = (DeclarationExpressionSyntax)declaration; CollectLocalsFromDeconstruction( declarationExpression.Designation, declarationExpression.Type, kind, locals, deconstructionStatement, enclosingBinderOpt); break; } case SyntaxKind.IdentifierName: break; default: throw ExceptionUtilities.UnexpectedValue(declaration.Kind()); } }
private bool IsCorrectReturnType(ExpressionSyntax expression, SemanticModel semanticModel) { INamedTypeSymbol taskType = null; INamedTypeSymbol returnType = null; return TryGetTypes(expression, semanticModel, out taskType, out returnType) && semanticModel.Compilation.ClassifyConversion(taskType, returnType).Exists; }
static CodeAction AddIsNaNIssue(Document document, SemanticModel semanticModel, SyntaxNode root, BinaryExpressionSyntax node, ExpressionSyntax argExpr, string floatType) { return CodeActionFactory.Create(node.Span, DiagnosticSeverity.Warning, string.Format(node.IsKind(SyntaxKind.EqualsExpression) ? "Replace with '{0}.IsNaN(...)' call" : "Replace with '!{0}.IsNaN(...)' call", floatType), token => { SyntaxNode newRoot; ExpressionSyntax expr; var arguments = new SeparatedSyntaxList<ArgumentSyntax>(); arguments = arguments.Add(SyntaxFactory.Argument(argExpr)); expr = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ParseExpression(floatType), SyntaxFactory.IdentifierName("IsNaN") ), SyntaxFactory.ArgumentList( arguments ) ); if (node.IsKind(SyntaxKind.NotEqualsExpression)) expr = SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, expr); expr = expr.WithAdditionalAnnotations(Formatter.Annotation); newRoot = root.ReplaceNode((SyntaxNode)node, expr); return Task.FromResult(document.WithSyntaxRoot(newRoot)); }); }
public QueryUnboundLambdaState(UnboundLambda unbound, Binder binder, RangeVariableMap rangeVariableMap, ImmutableArray<RangeVariableSymbol> parameters, ExpressionSyntax body) : this(unbound, binder, rangeVariableMap, parameters, (LambdaSymbol lambdaSymbol, ExecutableCodeBinder lambdaBodyBinder, DiagnosticBag diagnostics) => { BoundExpression expression = lambdaBodyBinder.BindValue(body, diagnostics, BindValueKind.RValue); return lambdaBodyBinder.WrapExpressionLambdaBody(expression, body, diagnostics); }) { }
private bool IsConstant(ExpressionSyntax expression) { switch (expression.Kind()) { case SyntaxKind.CharacterLiteralExpression: case SyntaxKind.FalseLiteralExpression: case SyntaxKind.NullLiteralExpression: case SyntaxKind.NumericLiteralExpression: case SyntaxKind.StringLiteralExpression: case SyntaxKind.TrueLiteralExpression: { return true; } case SyntaxKind.SimpleMemberAccessExpression: case SyntaxKind.IdentifierName: { ISymbol symbol = _model.GetSymbolInfo(expression).Symbol; if (symbol != null && symbol.Kind == SymbolKind.Field) { return ((IFieldSymbol)symbol).IsConst; } break; } } return false; }
public override FlatOperand Resolve(ExpressionSyntax expression, ArgumentListSyntax argumentList, TypeInfo result_type, SymbolInfo si, FlatOperand into_lvalue, Function function, List<FlatStatement> instructions) { FlatOperand fop_subject; if (expression is IdentifierNameSyntax) { // typeof this fop_subject = FlatOperand.ThisRef(FlatValue.FromType(result_type.ConvertedType)); } else if (expression is MemberAccessExpressionSyntax) { MemberAccessExpressionSyntax meas = (MemberAccessExpressionSyntax)expression; fop_subject = function.ResolveExpression(meas.Expression, null, instructions); } else { throw new NotImplementedException("GetMetaTable on expression type " + expression.GetType().ToString()); } if (into_lvalue == null) { FlatOperand fop_register = function.AllocateRegister(""); into_lvalue = fop_register.GetLValue(function, instructions); } instructions.Add(FlatStatement.GETMETATABLE(into_lvalue, fop_subject)); return into_lvalue.AsRValue(FlatValue.Table()); }
private INamedTypeSymbol FindSymbol(ExpressionSyntax expression) { while (true) { var parenthesizedExpression = expression as ParenthesizedExpressionSyntax; if (parenthesizedExpression != null) { expression = parenthesizedExpression.Expression; continue; } var castExpression = expression as CastExpressionSyntax; if (castExpression != null) { return semanticModel.GetTypeInfo(castExpression.Type).Type as INamedTypeSymbol; } if (expression is InvocationExpressionSyntax)//Handled by invocationanalzyer { return null; } var localSymbol = semanticModel.GetSymbolInfo(expression).Symbol as ILocalSymbol; return localSymbol?.Type as INamedTypeSymbol; } }
public static bool IsComplexCondition(ExpressionSyntax expr) { var loc = expr.GetLocation().GetLineSpan(); if (loc.StartLinePosition.Line != loc.EndLinePosition.Line) return true; if (expr is LiteralExpressionSyntax || expr is IdentifierNameSyntax || expr is MemberAccessExpressionSyntax || expr is InvocationExpressionSyntax) return false; var pexpr = expr as ParenthesizedExpressionSyntax; if (pexpr != null) return IsComplexCondition(pexpr.Expression); var uOp = expr as PrefixUnaryExpressionSyntax; if (uOp != null) return IsComplexCondition(uOp.Operand); var bop = expr as BinaryExpressionSyntax; if (bop == null) return true; return !(bop.IsKind(SyntaxKind.GreaterThanExpression) || bop.IsKind(SyntaxKind.GreaterThanOrEqualExpression) || bop.IsKind(SyntaxKind.EqualsExpression) || bop.IsKind(SyntaxKind.NotEqualsExpression) || bop.IsKind(SyntaxKind.LessThanExpression) || bop.IsKind(SyntaxKind.LessThanOrEqualExpression)); }
internal void CollectLocalsFromDeconstruction( ExpressionSyntax declaration, LocalDeclarationKind kind, ArrayBuilder<LocalSymbol> locals, SyntaxNode deconstructionStatement, Binder enclosingBinderOpt = null) { switch (declaration.Kind()) { case SyntaxKind.TupleExpression: { var tuple = (TupleExpressionSyntax)declaration; foreach (var arg in tuple.Arguments) { CollectLocalsFromDeconstruction(arg.Expression, kind, locals, deconstructionStatement, enclosingBinderOpt); } break; } case SyntaxKind.DeclarationExpression: { var declarationExpression = (DeclarationExpressionSyntax)declaration; CollectLocalsFromDeconstruction( declarationExpression.Designation, declarationExpression.Type, kind, locals, deconstructionStatement, enclosingBinderOpt); break; } case SyntaxKind.IdentifierName: break; default: // In broken code, we can have an arbitrary expression here. Collect its expression variables. ExpressionVariableFinder.FindExpressionVariables(this, locals, declaration); break; } }
private void ReportDiagnostic(ExpressionSyntax expression, TypeInfo typeInfo) { var diagnostic = Diagnostic.Create(StringFormatArgumentImplicitToStringAnalyzer.Rule, expression.GetLocation(), typeInfo.Type.ToDisplayString()); this.context.ReportDiagnostic(diagnostic); }
private static ExpressionSyntax LogicallyInvertImpl( ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken) { if (expression == null) { return(expression); } switch (expression.Kind()) { case SyntaxKind.SimpleMemberAccessExpression: case SyntaxKind.InvocationExpression: case SyntaxKind.ElementAccessExpression: case SyntaxKind.PostIncrementExpression: case SyntaxKind.PostDecrementExpression: case SyntaxKind.ObjectCreationExpression: case SyntaxKind.AnonymousObjectCreationExpression: case SyntaxKind.TypeOfExpression: case SyntaxKind.DefaultExpression: case SyntaxKind.CheckedExpression: case SyntaxKind.UncheckedExpression: case SyntaxKind.IdentifierName: { return(DefaultInvert(expression)); } case SyntaxKind.LogicalNotExpression: { return(((PrefixUnaryExpressionSyntax)expression).Operand); } case SyntaxKind.CastExpression: { return(DefaultInvert(expression)); } case SyntaxKind.LessThanExpression: case SyntaxKind.LessThanOrEqualExpression: case SyntaxKind.GreaterThanExpression: case SyntaxKind.GreaterThanOrEqualExpression: { return((semanticModel != null) ? InvertLessThanOrGreaterThan((BinaryExpressionSyntax)expression, semanticModel, cancellationToken) : DefaultInvert(expression)); } case SyntaxKind.IsExpression: case SyntaxKind.AsExpression: case SyntaxKind.IsPatternExpression: { return(DefaultInvert(expression)); } case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: { return(InvertBinaryExpression((BinaryExpressionSyntax)expression)); } case SyntaxKind.BitwiseAndExpression: { return(InvertBinaryExpression((BinaryExpressionSyntax)expression, semanticModel, cancellationToken)); } case SyntaxKind.ExclusiveOrExpression: { return(DefaultInvert(expression)); } case SyntaxKind.BitwiseOrExpression: case SyntaxKind.LogicalOrExpression: case SyntaxKind.LogicalAndExpression: { return(InvertBinaryExpression((BinaryExpressionSyntax)expression, semanticModel, cancellationToken)); } case SyntaxKind.ConditionalExpression: { return(InvertConditionalExpression((ConditionalExpressionSyntax)expression, semanticModel, cancellationToken)); } case SyntaxKind.SimpleAssignmentExpression: case SyntaxKind.AddAssignmentExpression: case SyntaxKind.SubtractAssignmentExpression: case SyntaxKind.MultiplyAssignmentExpression: case SyntaxKind.DivideAssignmentExpression: case SyntaxKind.ModuloAssignmentExpression: case SyntaxKind.AndAssignmentExpression: case SyntaxKind.ExclusiveOrAssignmentExpression: case SyntaxKind.OrAssignmentExpression: case SyntaxKind.LeftShiftAssignmentExpression: case SyntaxKind.RightShiftAssignmentExpression: { return(DefaultInvert(expression)); } case SyntaxKind.TrueLiteralExpression: { return(FalseLiteralExpression()); } case SyntaxKind.FalseLiteralExpression: { return(TrueLiteralExpression()); } case SyntaxKind.ParenthesizedExpression: { var parenthesizedExpression = (ParenthesizedExpressionSyntax)expression; ExpressionSyntax expression2 = parenthesizedExpression.Expression; if (expression2 == null) { return(parenthesizedExpression); } if (expression2.IsMissing) { return(parenthesizedExpression); } ExpressionSyntax newExpression = LogicallyInvertImpl(expression2, semanticModel, cancellationToken); newExpression = newExpression.WithTriviaFrom(expression2); return(parenthesizedExpression.WithExpression(newExpression)); } case SyntaxKind.AwaitExpression: { return(DefaultInvert(expression)); } } Debug.Fail($"Logical inversion of unknown kind '{expression.Kind()}'"); return(DefaultInvert(expression)); }
/// <summary> /// Returns new expression that represents logical inversion of the specified expression. /// </summary> /// <param name="expression"></param> /// <param name="cancellationToken"></param> public static ExpressionSyntax LogicallyInvert( ExpressionSyntax expression, CancellationToken cancellationToken = default(CancellationToken)) { return(LogicallyInvert(expression, semanticModel: null, cancellationToken)); }
private static bool IsArgumentOnExceptionList(ExpressionSyntax argumentExpression) { return(argumentExpression != null && ArgumentExceptionSyntaxKinds.Any(argumentExpression.IsKind)); }
private static void AnalyzeConditionalExpression(SyntaxNodeAnalysisContext context) { var conditionalExpression = (ConditionalExpressionSyntax)context.Node; ExpressionSyntax condition = conditionalExpression.Condition; if (condition.IsMissing) { return; } ExpressionSyntax whenTrue = conditionalExpression.WhenTrue; if (whenTrue.IsMissing) { return; } if (SyntaxTriviaAnalysis.IsTokenFollowedWithNewLineAndNotPrecededWithNewLine(condition, conditionalExpression.QuestionToken, whenTrue)) { if (!AnalyzerOptions.AddNewLineAfterConditionalOperatorInsteadOfBeforeIt.IsEnabled(context)) { ReportDiagnostic(DiagnosticRules.AddNewLineBeforeConditionalOperatorInsteadOfAfterItOrViceVersa, conditionalExpression.QuestionToken, ImmutableDictionary <string, string> .Empty); return; } } else if (SyntaxTriviaAnalysis.IsTokenPrecededWithNewLineAndNotFollowedWithNewLine(condition, conditionalExpression.QuestionToken, whenTrue)) { if (AnalyzerOptions.AddNewLineAfterConditionalOperatorInsteadOfBeforeIt.IsEnabled(context)) { ReportDiagnostic(DiagnosticRules.ReportOnly.AddNewLineAfterConditionalOperatorInsteadOfBeforeIt, conditionalExpression.QuestionToken, DiagnosticProperties.AnalyzerOption_Invert); return; } } ExpressionSyntax whenFalse = conditionalExpression.WhenFalse; if (!whenFalse.IsMissing) { if (SyntaxTriviaAnalysis.IsTokenFollowedWithNewLineAndNotPrecededWithNewLine(whenTrue, conditionalExpression.ColonToken, whenFalse)) { if (!AnalyzerOptions.AddNewLineAfterConditionalOperatorInsteadOfBeforeIt.IsEnabled(context)) { ReportDiagnostic(DiagnosticRules.AddNewLineBeforeConditionalOperatorInsteadOfAfterItOrViceVersa, conditionalExpression.ColonToken, ImmutableDictionary <string, string> .Empty); } } else if (SyntaxTriviaAnalysis.IsTokenPrecededWithNewLineAndNotFollowedWithNewLine(whenTrue, conditionalExpression.ColonToken, whenFalse)) { if (AnalyzerOptions.AddNewLineAfterConditionalOperatorInsteadOfBeforeIt.IsEnabled(context)) { ReportDiagnostic(DiagnosticRules.ReportOnly.AddNewLineAfterConditionalOperatorInsteadOfBeforeIt, conditionalExpression.ColonToken, DiagnosticProperties.AnalyzerOption_Invert); } } } void ReportDiagnostic(DiagnosticDescriptor descriptor, SyntaxToken token, ImmutableDictionary <string, string> properties) { DiagnosticHelpers.ReportDiagnostic( context, descriptor, Location.Create(token.SyntaxTree, token.Span.WithLength(0)), properties: properties, AnalyzerOptions.AddNewLineAfterConditionalOperatorInsteadOfBeforeIt); } }
private static bool IsSanitizedQuery(ExpressionSyntax expression, SemanticModel model) { return(model.GetConstantValue(expression).HasValue); }
static bool IsMethodRequiringAwait(ExpressionSyntax call, SyntaxNodeAnalysisContext context) => context.SemanticModel.GetSymbolInfo(call).Symbol is IMethodSymbol methodSymbol &&
public IEnumerable <StatementSyntax> AddComponent(TranslationContext context, ExpressionSyntax entity, ExpressionSyntax componentDeclaration, TypeSyntax componentTypeSyntax, bool isSharedComponent) { string expressionId = isSharedComponent ? nameof(EntityManager.AddSharedComponentData) : nameof(EntityManager.AddComponentData); yield return(ExpressionStatement(RoslynBuilder.MethodInvocation( expressionId, IdentifierName(nameof(EntityManager)), new[] { Argument(entity), Argument(componentDeclaration) }, new[] { componentTypeSyntax }))); }
public void BuildCriteria(RoslynEcsTranslator translator, TranslationContext context, ExpressionSyntax entity, IEnumerable <CriteriaModel> criteriaModels) { this.BuildCriteria( translator, context, entity, criteriaModels.Where(x => x.Criteria.Any()), ContinueStatement() ); }
public IEnumerable <StatementSyntax> RemoveComponent(TranslationContext context, ExpressionSyntax entity, string componentName) { yield return(ExpressionStatement(RoslynBuilder.MethodInvocation( nameof(EntityManager.RemoveComponent), IdentifierName(nameof(EntityManager)), new[] { Argument(entity) }, new[] { IdentifierName(Identifier(componentName)) }))); }
public static bool AreConditionsEqual(ExpressionSyntax cond1, ExpressionSyntax cond2) { if (cond1 == null || cond2 == null) return false; return cond1.SkipParens().IsEquivalentTo(cond2.SkipParens(), true); }
public SyntaxNode SendEvent(TranslationContext translatorContext, ExpressionSyntax entity, Type eventType, ExpressionSyntax newEventSyntax) { throw new NotImplementedException(); }
private ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded) { var vbConvertedType = _semanticModel.GetTypeInfo(vbNode).ConvertedType; switch (conversionKind) { case TypeConversionKind.Unknown: case TypeConversionKind.Identity: return(addParenthesisIfNeeded ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode); case TypeConversionKind.DestructiveCast: case TypeConversionKind.NonDestructiveCast: var typeName = (TypeSyntax)_csSyntaxGenerator.TypeExpression(vbConvertedType); if (csNode is CastExpressionSyntax cast && cast.Type.IsEquivalentTo(typeName)) { return(csNode); } return(ValidSyntaxFactory.CastExpression(typeName, csNode)); case TypeConversionKind.Conversion: return(AddExplicitConvertTo(vbNode, csNode, vbConvertedType)); default: throw new ArgumentOutOfRangeException(); } }
/// <summary> /// Inverts a boolean condition. Note: The condition object can be frozen (from AST) it's cloned internally. /// </summary> /// <param name="condition">The condition to invert.</param> public static ExpressionSyntax InvertCondition(ExpressionSyntax condition) { return InvertConditionInternal(condition); }
public ExpressionSyntax AddExplicitConvertTo(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, ITypeSymbol type) { var displayType = type.ToMinimalDisplayString(_semanticModel, vbNode.SpanStart); if (csNode is InvocationExpressionSyntax invoke && invoke.Expression is MemberAccessExpressionSyntax expr && expr.Expression is IdentifierNameSyntax name && name.Identifier.ValueText == "Conversions" && expr.Name.Identifier.ValueText == $"To{displayType}") { return(csNode); } var method = typeof(Microsoft.VisualBasic.CompilerServices.Conversions).GetMethod($"To{displayType}"); if (method == null) { throw new NotImplementedException($"Unimplemented conversion for {displayType}"); } // Need to use Conversions rather than Convert to match what VB does, eg. True -> -1 _extraUsingDirectives.Add("Microsoft.VisualBasic.CompilerServices"); var memberAccess = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("Conversions"), SyntaxFactory.IdentifierName($"To{displayType}")); var arguments = SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(csNode))); return(SyntaxFactory.InvocationExpression(memberAccess, arguments)); }
private static void AnalyzeEqualsNotEquals( SyntaxNodeAnalysisContext context, BinaryExpressionSyntax binaryExpression, ExpressionSyntax left, ExpressionSyntax right, SyntaxKind kind, SyntaxKind kind2) { SyntaxKind leftKind = left.Kind(); if (leftKind == kind) { switch (AnalyzeExpression(right, context.SemanticModel, context.CancellationToken)) { case AnalysisResult.Boolean: { SimplifyBooleanComparisonAnalysis.ReportDiagnostic(context, binaryExpression, left, right, fadeOut: true); break; } case AnalysisResult.LogicalNotWithNullableBoolean: { SimplifyBooleanComparisonAnalysis.ReportDiagnostic(context, binaryExpression, left, right, fadeOut: false); break; } } } else if (leftKind == kind2) { switch (AnalyzeExpression(right, context.SemanticModel, context.CancellationToken)) { case AnalysisResult.Boolean: { RemoveRedundantBooleanLiteralAnalysis.ReportDiagnostic(context, binaryExpression, left, right); break; } case AnalysisResult.LogicalNotWithNullableBoolean: { SimplifyBooleanComparisonAnalysis.ReportDiagnostic(context, binaryExpression, left, right, fadeOut: false); break; } } } else { SyntaxKind rightKind = right.Kind(); if (rightKind == kind) { switch (AnalyzeExpression(left, context.SemanticModel, context.CancellationToken)) { case AnalysisResult.Boolean: { SimplifyBooleanComparisonAnalysis.ReportDiagnostic(context, binaryExpression, left, right, fadeOut: true); break; } case AnalysisResult.LogicalNotWithNullableBoolean: { SimplifyBooleanComparisonAnalysis.ReportDiagnostic(context, binaryExpression, left, right, fadeOut: false); break; } } } else if (rightKind == kind2) { switch (AnalyzeExpression(left, context.SemanticModel, context.CancellationToken)) { case AnalysisResult.Boolean: { RemoveRedundantBooleanLiteralAnalysis.ReportDiagnostic(context, binaryExpression, left, right); break; } case AnalysisResult.LogicalNotWithNullableBoolean: { SimplifyBooleanComparisonAnalysis.ReportDiagnostic(context, binaryExpression, left, right, fadeOut: false); break; } } } } }
private static void CheckForBooleanConstant(BinaryExpressionSyntax binaryExpression, ExpressionSyntax booleanContantExpression, ErrorLocation errorLocation, SyntaxNodeAnalysisContext context, bool leftSide) { var expression = leftSide ? binaryExpression.Left : binaryExpression.Right; if (!EquivalenceChecker.AreEquivalent(expression.RemoveParentheses(), booleanContantExpression)) { return; } Location location; switch (errorLocation) { case ErrorLocation.Normal: location = expression.GetLocation(); break; case ErrorLocation.Extended: location = CalculateExtendedLocation(binaryExpression, leftSide); break; case ErrorLocation.Inverted: location = CalculateExtendedLocation(binaryExpression, !leftSide); break; default: location = null; break; } context.ReportDiagnostic(Diagnostic.Create(rule, location)); }
public ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, bool addParenthesisIfNeeded = false, bool alwaysExplicit = false, bool implicitCastFromIntToEnum = false) { var conversionKind = AnalyzeConversion(vbNode, alwaysExplicit, implicitCastFromIntToEnum); csNode = addParenthesisIfNeeded && (conversionKind == TypeConversionKind.DestructiveCast || conversionKind == TypeConversionKind.NonDestructiveCast) ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode; return(AddExplicitConversion(vbNode, csNode, conversionKind, addParenthesisIfNeeded)); }
private static void CheckForBooleanConstantOnLeftReportOnExtendedLocation(BinaryExpressionSyntax binaryExpression, ExpressionSyntax booleanContantExpression, SyntaxNodeAnalysisContext context) { CheckForBooleanConstant(binaryExpression, booleanContantExpression, ErrorLocation.Extended, context, leftSide: true); }
private (ExpressionSyntax fullInvocation, string identifierToken) PrepandCallToInvocation(IdentifierNameSyntax mockedObjectIdentifier, string prepandCall, ExpressionSyntax lambdaBody) { var prependInvocation = SyntaxFactory.InvocationExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, mockedObjectIdentifier, SyntaxFactory.IdentifierName(prepandCall))); var nameToken = lambdaBody.DescendantNodes().First(x => x.Kind() == mockedObjectIdentifier.Kind() && ((IdentifierNameSyntax)x).Identifier.ValueText == mockedObjectIdentifier.Identifier.ValueText); var fullInvocation = lambdaBody.ReplaceNode(nameToken, prependInvocation); return(fullInvocation, mockedObjectIdentifier.Identifier.ValueText); }
public static void AnalyzeSimpleAssignmentExpression(SyntaxNodeAnalysisContext context) { if (context.Node.SpanContainsDirectives()) { return; } var assignment = (AssignmentExpressionSyntax)context.Node; if (assignment.IsParentKind(SyntaxKind.ObjectInitializerExpression)) { return; } ExpressionSyntax left = assignment.Left; ExpressionSyntax right = assignment.Right; if (left?.IsMissing != false) { return; } if (right?.IsKind(SyntaxKind.AddExpression, SyntaxKind.SubtractExpression) != true) { return; } var binaryExpression = (BinaryExpressionSyntax)right; ExpressionSyntax binaryLeft = binaryExpression.Left; ExpressionSyntax binaryRight = binaryExpression.Right; if (binaryLeft?.IsMissing != false) { return; } if (binaryRight?.IsNumericLiteralExpression("1") != true) { return; } ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(left, context.CancellationToken); if (typeSymbol?.SupportsPrefixOrPostfixUnaryOperator() != true) { return; } if (!CSharpFactory.AreEquivalent(left, binaryLeft)) { return; } string operatorText = GetOperatorText(assignment); ReportDiagnostic(context, assignment, operatorText); context.ReportToken(DiagnosticDescriptors.UsePostfixUnaryOperatorInsteadOfAssignmentFadeOut, assignment.OperatorToken, operatorText); context.ReportNode(DiagnosticDescriptors.UsePostfixUnaryOperatorInsteadOfAssignmentFadeOut, binaryLeft, operatorText); context.ReportNode(DiagnosticDescriptors.UsePostfixUnaryOperatorInsteadOfAssignmentFadeOut, binaryRight, operatorText); }
private static void CheckForBooleanConstantOnRightReportOnNormalLocation(BinaryExpressionSyntax binaryExpression, ExpressionSyntax booleanContantExpression, SyntaxNodeAnalysisContext context) { CheckForBooleanConstant(binaryExpression, booleanContantExpression, ErrorLocation.Normal, context, leftSide: false); }
private static bool HasFloatingType(ExpressionSyntax right, ExpressionSyntax left, SemanticModel semanticModel) { return(IsExpressionFloatingType(right, semanticModel) || IsExpressionFloatingType(left, semanticModel)); }
private static void Analyze(SyntaxNodeAnalysisContext context, SyntaxNode node, BlockSyntax body) { if (body == null) { return; } if (body.ContainsDiagnostics) { return; } SyntaxList <StatementSyntax> statements = body.Statements; if (statements.Count != 2) { return; } if (!(statements[0] is IfStatementSyntax ifStatement)) { return; } if (!(statements[1] is ReturnStatementSyntax returnStatement)) { return; } ExpressionSyntax returnExpression = returnStatement.Expression; if (returnExpression?.IsKind(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression) != true) { return; } if (ifStatement.SpanOrTrailingTriviaContainsDirectives()) { return; } if (returnStatement.SpanOrLeadingTriviaContainsDirectives()) { return; } SimpleIfStatementInfo simpleIf = SyntaxInfo.SimpleIfStatementInfo(ifStatement); if (!simpleIf.Success) { return; } StatementSyntax statement = simpleIf.IfStatement.SingleNonBlockStatementOrDefault(); if (statement == null) { return; } SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(statement); if (!assignmentInfo.Success) { return; } if (!assignmentInfo.Left.IsKind(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression)) { return; } SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(simpleIf.Condition, semanticModel: semanticModel, allowedStyles: NullCheckStyles.CheckingNull, cancellationToken: cancellationToken); if (!nullCheck.Success) { return; } ExpressionSyntax expression = nullCheck.Expression; if (!expression.IsKind(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression)) { return; } if (!(semanticModel.GetSymbol(expression, cancellationToken) is IFieldSymbol fieldSymbol)) { return; } if (!ExpressionEquals(expression, assignmentInfo.Left)) { return; } if (fieldSymbol.Type.IsNullableType() && returnExpression.Kind() == SyntaxKind.SimpleMemberAccessExpression) { var memberAccessExpression = (MemberAccessExpressionSyntax)returnExpression; if (memberAccessExpression.Name is IdentifierNameSyntax identifierName && string.Equals(identifierName.Identifier.ValueText, "Value", StringComparison.Ordinal)) { returnExpression = memberAccessExpression.Expression; } } if (!ExpressionEquals(expression, returnExpression)) { return; } DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.SimplifyLazyInitialization, Location.Create(node.SyntaxTree, TextSpan.FromBounds(ifStatement.SpanStart, returnStatement.Span.End))); }
internal ParenthesizedExpressionSyntax(SyntaxTree syntaxTree, SyntaxToken openParenthesisToken, ExpressionSyntax expression, SyntaxToken closeParenthesisToken) : base(syntaxTree) { OpenParenthesisToken = openParenthesisToken; Expression = expression; CloseParenthesisToken = closeParenthesisToken; }
private static bool IsExpressionFloatingType(ExpressionSyntax expression, SemanticModel semanticModel) { return(semanticModel.GetTypeInfo(expression).Type.IsAny(KnownType.FloatingPointNumbers)); }
private async Task ComputeCodeFixAsync(CodeFixContext context, Diagnostic diagnostic, ExpressionSyntax expression, SimpleNameSyntax simpleName) { switch (simpleName.Identifier.ValueText) { case "Count": { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ComputeCodeFix(context, diagnostic, expression, simpleName, semanticModel, "Count", "Length"); break; } case "Length": { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ComputeCodeFix(context, diagnostic, expression, simpleName, semanticModel, "Length", "Count"); break; } } }
private static BinaryExpressionSyntax TryGetBinaryExpression(ExpressionSyntax expression) { return(expression.RemoveParentheses() as BinaryExpressionSyntax); }
private BoundExpression BindExpression(ExpressionSyntax node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } switch (node.Kind) { case SyntaxKind.TrueLiteralExpression: case SyntaxKind.FalseLiteralExpression: case SyntaxKind.NumericLiteralExpression: return(BindLiteralExpression((LiteralExpressionSyntax)node)); case SyntaxKind.StringLiteralExpression: return(BindStringLiteralExpression((StringLiteralExpressionSyntax)node)); case SyntaxKind.IdentifierName: return(BindIdentifierName((IdentifierNameSyntax)node)); case SyntaxKind.QualifiedName: return(BindQualifiedName((QualifiedNameSyntax)node)); case SyntaxKind.PreDecrementExpression: case SyntaxKind.PreIncrementExpression: case SyntaxKind.UnaryMinusExpression: case SyntaxKind.UnaryPlusExpression: case SyntaxKind.LogicalNotExpression: case SyntaxKind.BitwiseNotExpression: return(BindPrefixUnaryExpression((PrefixUnaryExpressionSyntax)node)); case SyntaxKind.PostDecrementExpression: case SyntaxKind.PostIncrementExpression: return(BindPostfixUnaryExpression((PostfixUnaryExpressionSyntax)node)); case SyntaxKind.AddExpression: case SyntaxKind.MultiplyExpression: case SyntaxKind.SubtractExpression: case SyntaxKind.DivideExpression: case SyntaxKind.ModuloExpression: case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: case SyntaxKind.GreaterThanExpression: case SyntaxKind.LessThanExpression: case SyntaxKind.GreaterThanOrEqualExpression: case SyntaxKind.LessThanOrEqualExpression: case SyntaxKind.BitwiseAndExpression: case SyntaxKind.BitwiseOrExpression: case SyntaxKind.ExclusiveOrExpression: case SyntaxKind.LeftShiftExpression: case SyntaxKind.RightShiftExpression: case SyntaxKind.LogicalOrExpression: case SyntaxKind.LogicalAndExpression: return(BindBinaryExpression((BinaryExpressionSyntax)node)); case SyntaxKind.FieldAccessExpression: return(BindFieldAccessExpression((FieldAccessExpressionSyntax)node)); case SyntaxKind.FunctionInvocationExpression: return(BindFunctionInvocationExpression((FunctionInvocationExpressionSyntax)node)); case SyntaxKind.MethodInvocationExpression: return(BindMethodInvocationExpression((MethodInvocationExpressionSyntax)node)); case SyntaxKind.NumericConstructorInvocationExpression: return(BindNumericConstructorInvocationExpression((NumericConstructorInvocationExpressionSyntax)node)); case SyntaxKind.SimpleAssignmentExpression: case SyntaxKind.AddAssignmentExpression: case SyntaxKind.SubtractAssignmentExpression: case SyntaxKind.MultiplyAssignmentExpression: case SyntaxKind.DivideAssignmentExpression: case SyntaxKind.ModuloAssignmentExpression: case SyntaxKind.AndAssignmentExpression: case SyntaxKind.ExclusiveOrAssignmentExpression: case SyntaxKind.OrAssignmentExpression: case SyntaxKind.LeftShiftAssignmentExpression: case SyntaxKind.RightShiftAssignmentExpression: return(BindAssignmentExpression((AssignmentExpressionSyntax)node)); case SyntaxKind.CastExpression: return(BindCastExpression((CastExpressionSyntax)node)); case SyntaxKind.CompoundExpression: return(BindCompoundExpression((CompoundExpressionSyntax)node)); case SyntaxKind.ParenthesizedExpression: return(BindParenthesizedExpression((ParenthesizedExpressionSyntax)node)); case SyntaxKind.ConditionalExpression: return(BindConditionalExpression((ConditionalExpressionSyntax)node)); case SyntaxKind.ElementAccessExpression: return(BindElementAccessExpression((ElementAccessExpressionSyntax)node)); case SyntaxKind.ArrayInitializerExpression: return(BindArrayInitializerExpression((ArrayInitializerExpressionSyntax)node)); case SyntaxKind.CompileExpression: return(BindCompileExpression((CompileExpressionSyntax)node)); default: throw new ArgumentOutOfRangeException(node.Kind.ToString()); } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsAnyCodeFixEnabled( CodeFixIdentifiers.FixMemberAccessName, CodeFixIdentifiers.RemoveAwaitKeyword)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out SyntaxNode node, predicate: f => f.IsKind( SyntaxKind.AwaitExpression, SyntaxKind.IdentifierName, SyntaxKind.GenericName, SyntaxKind.MemberBindingExpression))) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.TypeDoesNotContainDefinitionAndNoExtensionMethodCouldBeFound: { switch (node) { case SimpleNameSyntax simpleName: { Debug.Assert(node.IsKind(SyntaxKind.IdentifierName, SyntaxKind.GenericName), node.Kind().ToString()); if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.FixMemberAccessName)) { break; } if (!simpleName.IsParentKind(SyntaxKind.SimpleMemberAccessExpression)) { break; } var memberAccess = (MemberAccessExpressionSyntax)simpleName.Parent; if (memberAccess.IsParentKind(SyntaxKind.InvocationExpression)) { break; } await ComputeCodeFixAsync(context, diagnostic, memberAccess.Expression, simpleName).ConfigureAwait(false); break; } case MemberBindingExpressionSyntax memberBindingExpression: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.FixMemberAccessName)) { break; } if (!(memberBindingExpression.Parent is ConditionalAccessExpressionSyntax conditionalAccessExpression)) { break; } await ComputeCodeFixAsync(context, diagnostic, conditionalAccessExpression.Expression, memberBindingExpression.Name).ConfigureAwait(false); break; } case AwaitExpressionSyntax awaitExpression: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveAwaitKeyword)) { break; } CodeAction codeAction = CodeAction.Create( "Remove 'await'", cancellationToken => { ExpressionSyntax expression = awaitExpression.Expression; SyntaxTriviaList leadingTrivia = awaitExpression .GetLeadingTrivia() .AddRange(awaitExpression.AwaitKeyword.TrailingTrivia.EmptyIfWhitespace()) .AddRange(expression.GetLeadingTrivia().EmptyIfWhitespace()); ExpressionSyntax newNode = expression.WithLeadingTrivia(leadingTrivia); return(context.Document.ReplaceNodeAsync(awaitExpression, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } break; } } } }