/// <summary> /// Gets all the declared local variables in the given <paramref name="declarationGroup"/>. /// </summary> /// <param name="declarationGroup">Variable declaration group</param> public static ImmutableArray <ILocalSymbol> GetDeclaredVariables(this IVariableDeclarationGroupOperation declarationGroup) { if (declarationGroup == null) { throw new ArgumentNullException(nameof(declarationGroup)); } var arrayBuilder = ArrayBuilder <ILocalSymbol> .GetInstance(); foreach (IVariableDeclarationOperation group in declarationGroup.Declarations) { group.GetDeclaredVariables(arrayBuilder); } return(arrayBuilder.ToImmutableAndFree()); }
static async Task <Document?> HandleVariableDeclarator(IVariableDeclaratorOperation variableDeclaratorOperation, Document doc, SyntaxNode root, CancellationToken cancellationToken) { IVariableDeclarationOperation variableDeclarationOperation = (IVariableDeclarationOperation)variableDeclaratorOperation.Parent; IVariableDeclarationGroupOperation variableGroupDeclarationOperation = (IVariableDeclarationGroupOperation)variableDeclarationOperation.Parent; DocumentEditor editor = await DocumentEditor.CreateAsync(doc, cancellationToken).ConfigureAwait(false); SyntaxGenerator generator = editor.Generator; ILocalSymbol currentSymbol = variableDeclaratorOperation.Symbol; var variableInitializerOperation = variableDeclaratorOperation.GetVariableInitializer(); string unitString = (string)variableInitializerOperation.Value.ConstantValue.Value; char charValue = unitString[0]; SyntaxNode charLiteralExpressionNode = generator.LiteralExpression(charValue); var charTypeNode = generator.TypeExpression(SpecialType.System_Char); var charSyntaxNode = generator.LocalDeclarationStatement(charTypeNode, currentSymbol.Name, charLiteralExpressionNode, isConst: true); charSyntaxNode = charSyntaxNode.WithTriviaFrom(variableGroupDeclarationOperation.Syntax); var newRoot = generator.ReplaceNode(root, variableGroupDeclarationOperation.Syntax, charSyntaxNode); return(doc.WithSyntaxRoot(newRoot)); }
private bool ReportIfCanBeAwaitUsing(OperationAnalysisContext context, IOperation usingOperation, IVariableDeclarationGroupOperation operation) { foreach (var declaration in operation.Declarations) { if (declaration.Initializer?.Value != null) { if (CanBeAwaitUsing(declaration.Initializer.Value)) { ReportDiagnosticIfNeeded(context, usingOperation, "Prefer using 'await using'"); return(true); } } foreach (var declarator in declaration.Declarators) { if (declarator.Initializer != null && CanBeAwaitUsing(declarator.Initializer.Value)) { ReportDiagnosticIfNeeded(context, usingOperation, "Prefer using 'await using'"); return(true); } } } return(false); }
public override IOperation VisitVariableDeclarationGroup(IVariableDeclarationGroupOperation operation, object argument) { return(new VariableDeclarationGroupOperation(VisitArray(operation.Declarations), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit)); }
public override void VisitVariableDeclarationGroup(IVariableDeclarationGroupOperation operation) { Assert.Equal(OperationKind.VariableDeclarationGroup, operation.Kind); AssertEx.Equal(operation.Declarations, operation.Children); }
private bool TryFindMatchingLocalDeclarationImmediatelyAbove( IConditionalOperation ifOperation, ISimpleAssignmentOperation trueAssignment, ISimpleAssignmentOperation falseAssignment, out IVariableDeclarationGroupOperation localDeclaration, out IVariableDeclaratorOperation declarator) { localDeclaration = null; declarator = null; // See if both assignments are to the same local. if (!(trueAssignment.Target is ILocalReferenceOperation trueLocal) || !(falseAssignment.Target is ILocalReferenceOperation falseLocal) || !Equals(trueLocal.Local, falseLocal.Local)) { return(false); } // If so, see if that local was declared immediately above the if-statement. var parentBlock = ifOperation.Parent as IBlockOperation; if (parentBlock == null) { return(false); } var ifIndex = parentBlock.Operations.IndexOf(ifOperation); if (ifIndex <= 0) { return(false); } localDeclaration = parentBlock.Operations[ifIndex - 1] as IVariableDeclarationGroupOperation; if (localDeclaration == null) { return(false); } if (localDeclaration.Declarations.Length != 1) { return(false); } var declaration = localDeclaration.Declarations[0]; var declarators = declaration.Declarators; if (declarators.Length != 1) { return(false); } declarator = declarators[0]; var variable = declarator.Symbol; if (!Equals(variable, trueLocal.Local)) { // wasn't a declaration of the local we're assigning to. return(false); } var variableName = variable.Name; var variableInitializer = declarator.Initializer ?? declaration.Initializer; if (variableInitializer?.Value != null) { var unwrapped = UnwrapImplicitConversion(variableInitializer.Value); // the variable has to either not have an initializer, or it needs to be basic // literal/default expression. if (!(unwrapped is ILiteralOperation) && !(unwrapped is IDefaultValueOperation)) { return(false); } } // If the variable is referenced in the condition of the 'if' block, we can't merge the // declaration and assignments. return(!ReferencesLocalVariable(ifOperation.Condition, variable)); }
public sealed override void Initialize(AnalysisContext context) { context.RegisterOperationBlockStartAction( (operationBlockContext) => { if (operationBlockContext.OwningSymbol is IMethodSymbol containingMethod) { HashSet <ILocalSymbol> mightBecomeConstLocals = new HashSet <ILocalSymbol>(); HashSet <ILocalSymbol> assignedToLocals = new HashSet <ILocalSymbol>(); operationBlockContext.RegisterOperationAction( (operationContext) => { if (operationContext.Operation is IAssignmentOperation assignment) { AssignTo( assignment.Target, assignedToLocals, mightBecomeConstLocals ); } else if ( operationContext.Operation is IIncrementOrDecrementOperation increment ) { AssignTo( increment.Target, assignedToLocals, mightBecomeConstLocals ); } else { throw TestExceptionUtilities.UnexpectedValue( operationContext.Operation ); } }, OperationKind.SimpleAssignment, OperationKind.CompoundAssignment, OperationKind.Increment ); operationBlockContext.RegisterOperationAction( (operationContext) => { IInvocationOperation invocation = (IInvocationOperation)operationContext.Operation; foreach (IArgumentOperation argument in invocation.Arguments) { if ( argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref ) { AssignTo( argument.Value, assignedToLocals, mightBecomeConstLocals ); } } }, OperationKind.Invocation ); operationBlockContext.RegisterOperationAction( (operationContext) => { IVariableDeclarationGroupOperation declaration = (IVariableDeclarationGroupOperation)operationContext.Operation; foreach ( IVariableDeclaratorOperation variable in declaration.Declarations.SelectMany( decl => decl.Declarators ) ) { ILocalSymbol local = variable.Symbol; if (!local.IsConst && !assignedToLocals.Contains(local)) { var localType = local.Type; if ( ( !localType.IsReferenceType || localType.SpecialType == SpecialType.System_String ) && localType.SpecialType != SpecialType.None ) { IVariableInitializerOperation initializer = variable.GetVariableInitializer(); if ( initializer != null && initializer.Value.ConstantValue.HasValue ) { mightBecomeConstLocals.Add(local); } } } } }, OperationKind.VariableDeclarationGroup ); operationBlockContext.RegisterOperationBlockEndAction( (operationBlockEndContext) => { foreach (ILocalSymbol couldBeConstLocal in mightBecomeConstLocals) { Report( operationBlockEndContext, couldBeConstLocal, LocalCouldBeConstDescriptor ); } } ); } } ); }
public virtual void VisitVariableDeclarationGroup(IVariableDeclarationGroupOperation operation) { DefaultVisit(operation); }
public override void VisitVariableDeclarationGroup([NotNull] IVariableDeclarationGroupOperation operation) { base.VisitVariableDeclarationGroup(operation); }
public override void VisitVariableDeclarationGroup([NotNull] IVariableDeclarationGroupOperation operation) { IncrementStatementCount(operation); base.VisitVariableDeclarationGroup(operation); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { Document doc = context.Document; CancellationToken cancellationToken = context.CancellationToken; SyntaxNode root = await doc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (root.FindNode(context.Span) is SyntaxNode expression) { SemanticModel semanticModel = await doc.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var operation = semanticModel.GetOperation(expression, cancellationToken); if (operation is IArgumentOperation argumentOperation) { var localReferenceOperation = argumentOperation.Value as ILocalReferenceOperation; var literalOperation = argumentOperation.Value as ILiteralOperation; if (localReferenceOperation == null && literalOperation == null) { return; } IVariableDeclaratorOperation?variableDeclaratorOperation = default; if (localReferenceOperation != null) { ILocalSymbol localArgumentDeclaration = localReferenceOperation.Local; SyntaxReference declaringSyntaxReference = localArgumentDeclaration.DeclaringSyntaxReferences.FirstOrDefault(); if (declaringSyntaxReference is null) { return; } variableDeclaratorOperation = semanticModel.GetOperationWalkingUpParentChain(await declaringSyntaxReference.GetSyntaxAsync(cancellationToken).ConfigureAwait(false), cancellationToken) as IVariableDeclaratorOperation; if (variableDeclaratorOperation == null) { return; } var variableInitializerOperation = variableDeclaratorOperation.GetVariableInitializer(); if (variableInitializerOperation == null) { return; } IVariableDeclarationOperation variableDeclarationOperation = (IVariableDeclarationOperation)variableDeclaratorOperation.Parent; if (variableDeclarationOperation == null) { return; } IVariableDeclarationGroupOperation variableGroupDeclarationOperation = (IVariableDeclarationGroupOperation)variableDeclarationOperation.Parent; if (variableGroupDeclarationOperation.Declarations.Length != 1) { return; } if (variableDeclarationOperation.Declarators.Length != 1) { return; } } context.RegisterCodeFix( CodeAction.Create( title: MicrosoftNetCoreAnalyzersResources.PreferConstCharOverConstUnitStringInStringBuilderTitle, createChangedDocument: async c => { if (literalOperation != null) { return(await HandleStringLiteral(literalOperation, doc, root, cancellationToken).ConfigureAwait(false)); } else { RoslynDebug.Assert(variableDeclaratorOperation != null); return(await HandleVariableDeclarator(variableDeclaratorOperation !, doc, root, cancellationToken).ConfigureAwait(false)); } }, equivalenceKey: MicrosoftNetCoreAnalyzersResources.PreferConstCharOverConstUnitStringInStringBuilderMessage), context.Diagnostics);
public override bool VisitVariableDeclarationGroup([NotNull] IVariableDeclarationGroupOperation operation1, [CanBeNull] IOperation argument) { return(argument is IVariableDeclarationGroupOperation operation2 && AreBaseOperationsEqual(operation1, operation2)); }
private void AnalyzeVariableDeclarationGroupOperation(OperationAnalysisContext context, IVariableDeclarationGroupOperation declarationGroup) { foreach (var declaration in declarationGroup.Declarations) { foreach (var declarator in declaration.Declarators) { if (declarator.Initializer == null) { continue; } // ConfiguredCancelableAsyncEnumerable var variableType = declarator.Initializer.Value.GetActualType(); if (variableType == null || variableType.IsEqualTo(ConfiguredAsyncDisposableSymbol)) { return; } if (!CanAddConfigureAwait(variableType)) { return; } if (MustUseConfigureAwait(declarator.SemanticModel, declarator.Syntax, context.CancellationToken)) { context.ReportDiagnostic(s_rule, declarator.Initializer.Value); } } } }
public override void VisitVariableDeclarationGroup(IVariableDeclarationGroupOperation operation) { base.VisitVariableDeclarationGroup(operation); throw new NotImplementedException(); }