public override void VisitAssignmentExpression([NotNull] IAssignmentExpression operation) { if (operation.Target is ILocalReferenceExpression targetLocal && local.Equals(targetLocal.Local)) { TrySetEvent(operation.Value); } base.VisitAssignmentExpression(operation); }
public override void VisitSimpleAssignment([NotNull] ISimpleAssignmentOperation operation) { if (operation.Target is ILocalReferenceOperation targetLocal && local.Equals(targetLocal.Local)) { TrySetEvent(operation.Value); } base.VisitSimpleAssignment(operation); }
public override void VisitVariableDeclarator([NotNull] IVariableDeclaratorOperation operation) { base.VisitVariableDeclarator(operation); if (currentLocal.Equals(operation.Symbol) && operation.Initializer != null) { AnalyzeAssignmentValue(operation.Initializer.Value); } }
public override void VisitVariableDeclarationStatement([NotNull] IVariableDeclarationStatement operation) { base.VisitVariableDeclarationStatement(operation); foreach (IVariableDeclaration variable in operation.Declarations) { if (currentLocal.Equals(variable.Variables.Single())) { AnalyzeAssignmentValue(variable.Initializer); } } }
public override void VisitVariableDeclarator([NotNull] IVariableDeclaratorOperation operation) { base.VisitVariableDeclarator(operation); if (currentLocal.Equals(operation.Symbol) && EndsBeforeMaxLocation(operation)) { IVariableInitializerOperation initializer = operation.GetVariableInitializer(); if (initializer != null) { AnalyzeAssignmentValue(initializer.Value); } } }
private static LocalInfo FindInitializedVariable( IdentifierNameSyntax identifierName, VariableDeclaratorSyntax variableDeclarator, SemanticModel semanticModel, CancellationToken cancellationToken) { string name = identifierName.Identifier.ValueText; ILocalSymbol localSymbol = null; if (string.Equals(variableDeclarator.Identifier.ValueText, name, StringComparison.Ordinal)) { if (localSymbol == null) { localSymbol = semanticModel.GetSymbol(identifierName, cancellationToken) as ILocalSymbol; if (localSymbol == null) { return(default(LocalInfo)); } } if (localSymbol.Equals(semanticModel.GetDeclaredSymbol(variableDeclarator, cancellationToken))) { return(new LocalInfo(variableDeclarator, localSymbol)); } } return(default(LocalInfo)); }
private static IEnumerable <int> GetAssignedIndexes(IEnumerable <StatementSyntax> statements, ILocalSymbol symbol, SemanticModel semanticModel) { foreach (var statement in statements) { var assignment = statement as AssignmentStatementSyntax; if (assignment == null) { yield break; } var invocation = assignment.Left as InvocationExpressionSyntax; if (invocation == null || invocation.ArgumentList == null || invocation.ArgumentList.Arguments.Count != 1) { yield break; } var assignedSymbol = semanticModel.GetSymbolInfo(invocation.Expression).Symbol; if (!symbol.Equals(assignedSymbol)) { yield break; } var argument = invocation.ArgumentList.Arguments.First(); var index = GetConstantArgumentValue(argument, semanticModel); if (!index.HasValue) { yield break; } yield return(index.Value); } }
private static bool IsEndingWithDispose(SemanticModel semanticModel, List <StatementSyntax> insideUsing, ILocalSymbol disposableLocal) { var lastInUsingAsCall = (((insideUsing.LastOrDefault() as ExpressionStatementSyntax)?.Expression as InvocationExpressionSyntax)?.Expression as MemberAccessExpressionSyntax); if (lastInUsingAsCall == null) { return(false); } var targetSymbol = semanticModel.GetSymbolInfo(lastInUsingAsCall.Expression); if (!disposableLocal.Equals(targetSymbol.Symbol)) { return(false); } var dispose = semanticModel.Compilation.GetSpecialType(SpecialType.System_IDisposable).GetMembers("Dispose").Single(); var calledMethod = semanticModel.GetSymbolInfo(lastInUsingAsCall).Symbol; if (!dispose.Equals(calledMethod)) { return(false); } return(true); }
private static bool IsAddedToFieldOrProperty(ILocalSymbol symbol, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken) { using (var pooledInvocations = InvocationWalker.Borrow(block)) { foreach (var invocation in pooledInvocations.Invocations) { var method = semanticModel.GetSymbolSafe(invocation, cancellationToken) as IMethodSymbol; if (method?.Name == "Add") { using (var nameWalker = IdentifierNameWalker.Borrow(invocation.ArgumentList)) { foreach (var identifierName in nameWalker.IdentifierNames) { var argSymbol = semanticModel.GetSymbolSafe(identifierName, cancellationToken); if (symbol.Equals(argSymbol)) { return(true); } } } } } } return(false); }
private static VariableDeclaratorSyntax FindInitializedVariable( SeparatedSyntaxList <VariableDeclaratorSyntax> declarators, IdentifierNameSyntax identifierName, SemanticModel semanticModel, CancellationToken cancellationToken) { string name = identifierName.Identifier.ValueText; ILocalSymbol localSymbol = null; foreach (VariableDeclaratorSyntax declarator in declarators) { if (name == declarator.Identifier.ValueText) { if (localSymbol == null) { localSymbol = semanticModel.GetSymbol(identifierName, cancellationToken) as ILocalSymbol; if (localSymbol == null) { return(null); } } if (localSymbol.Equals(semanticModel.GetDeclaredSymbol(declarator, cancellationToken))) { return(declarator); } } } return(null); }
private static async Task <Document> RefactorAsync( Document document, ForEachStatementSyntax forEachStatement, CancellationToken cancellationToken) { int position = forEachStatement.SpanStart; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string name = NameGenerator.Default.EnsureUniqueLocalName(DefaultNames.EnumeratorVariable, semanticModel, position, cancellationToken: cancellationToken); InvocationExpressionSyntax expression = SimpleMemberInvocationExpression(forEachStatement.Expression, IdentifierName(WellKnownMemberNames.GetEnumeratorMethodName)); VariableDeclarationSyntax variableDeclaration = VariableDeclaration(VarType(), Identifier(name).WithRenameAnnotation(), expression); MemberAccessExpressionSyntax currentExpression = SimpleMemberAccessExpression(IdentifierName(name), IdentifierName("Current")); ILocalSymbol localSymbol = semanticModel.GetDeclaredSymbol(forEachStatement, cancellationToken); StatementSyntax statement = forEachStatement.Statement; StatementSyntax newStatement = statement.ReplaceNodes( statement .DescendantNodes() .Where(node => node.Kind() == SyntaxKind.IdentifierName && localSymbol.Equals(semanticModel.GetSymbol(node, cancellationToken))), (node, _) => currentExpression.WithTriviaFrom(node)); WhileStatementSyntax whileStatement = WhileStatement( SimpleMemberInvocationExpression(IdentifierName(name), IdentifierName("MoveNext")), newStatement); if (semanticModel .GetSpeculativeMethodSymbol(position, expression)? .ReturnType .Implements(SpecialType.System_IDisposable, allInterfaces: true) == true) { UsingStatementSyntax usingStatement = UsingStatement( variableDeclaration, default(ExpressionSyntax), Block(whileStatement)); usingStatement = usingStatement .WithLeadingTrivia(forEachStatement.GetLeadingTrivia()) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(forEachStatement, usingStatement, cancellationToken).ConfigureAwait(false)); } else { LocalDeclarationStatementSyntax localDeclaration = LocalDeclarationStatement(variableDeclaration) .WithLeadingTrivia(forEachStatement.GetLeadingTrivia()) .WithFormatterAnnotation(); var newStatements = new StatementSyntax[] { localDeclaration, whileStatement.WithFormatterAnnotation() }; return(await document.ReplaceNodeAsync(forEachStatement, newStatements, cancellationToken).ConfigureAwait(false)); } }
public static void AnalyzeCatchClause(SyntaxNodeAnalysisContext context) { var catchClause = (CatchClauseSyntax)context.Node; BlockSyntax block = catchClause.Block; if (block == null) { return; } CatchDeclarationSyntax declaration = catchClause.Declaration; if (declaration == null) { return; } SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; ILocalSymbol symbol = semanticModel.GetDeclaredSymbol(declaration, cancellationToken); if (symbol?.IsErrorType() != false) { return; } //TODO: SyntaxWalker foreach (SyntaxNode node in block.DescendantNodes(descendIntoChildren: f => f.Kind() != SyntaxKind.CatchClause)) { if (node.Kind() != SyntaxKind.ThrowStatement) { continue; } var throwStatement = (ThrowStatementSyntax)node; ExpressionSyntax expression = throwStatement.Expression; if (expression == null) { continue; } ISymbol expressionSymbol = semanticModel.GetSymbol(expression, cancellationToken); if (!symbol.Equals(expressionSymbol)) { continue; } context.ReportDiagnostic( DiagnosticDescriptors.RemoveOriginalExceptionFromThrowStatement, expression); } }
private bool IsAccessedOutOfScope(SyntaxNode scope) { Debug.Assert(scope != null); var localStatementStart = _localStatement.SpanStart; var comparisonSpanStart = _comparison.SpanStart; var variableName = _localSymbol.Name; var scopeSpan = scope.Span; // Iterate over all descendent nodes to find possible out-of-scope references. foreach (var descendentNode in _enclosingBlock.DescendantNodes()) { var descendentNodeSpanStart = descendentNode.SpanStart; if (descendentNodeSpanStart <= localStatementStart) { // We're not interested in nodes that are apeared before // the local declaration statement. It's either an error // or not the local reference we're looking for. continue; } if ( descendentNodeSpanStart >= comparisonSpanStart && scopeSpan.Contains(descendentNode.Span) ) { // If this is in the scope and after null-check, we don't bother checking the symbol. continue; } if ( descendentNode.IsKind( SyntaxKind.IdentifierName, out IdentifierNameSyntax identifierName ) && identifierName.Identifier.ValueText == variableName && _localSymbol.Equals( _semanticModel.GetSymbolInfo(identifierName, _cancellationToken).Symbol ) ) { // If we got here, it means we have a local // reference out of scope of the pattern variable. return(true); } } // Either no reference were found, or all // references were inside the given scope. return(false); }
private static bool OnlyUsedToAccessTupleFields( SemanticModel semanticModel, SyntaxNode searchScope, ILocalSymbol local, ArrayBuilder <MemberAccessExpressionSyntax> memberAccessLocations, CancellationToken cancellationToken ) { var localName = local.Name; foreach ( var identifierName in searchScope.DescendantNodes().OfType <IdentifierNameSyntax>() ) { if (identifierName.Identifier.ValueText == localName) { var symbol = semanticModel .GetSymbolInfo(identifierName, cancellationToken) .GetAnySymbol(); if (local.Equals(symbol)) { if (!(identifierName.Parent is MemberAccessExpressionSyntax memberAccess)) { // We referenced the local in a location where we're not accessing a // field off of it. i.e. Console.WriteLine(tupleLocal); return(false); } var member = semanticModel .GetSymbolInfo(memberAccess, cancellationToken) .GetAnySymbol(); if (!(member is IFieldSymbol field)) { // Accessed some non-field member of it (like .ToString()). return(false); } if (field.IsImplicitlyDeclared) { // They're referring to .Item1-.ItemN. We can't update this to refer to the local return(false); } memberAccessLocations.Add(memberAccess); } } } return(true); }
private static IEnumerable <IdentifierNameSyntax> GetVariableReferences( ForEachStatementSyntax forEachStatement, SemanticModel semanticModel, CancellationToken cancellationToken) { ILocalSymbol symbol = semanticModel.GetDeclaredSymbol(forEachStatement, cancellationToken); foreach (SyntaxNode node in forEachStatement.Statement.DescendantNodes()) { if (node.IsKind(SyntaxKind.IdentifierName) && symbol.Equals(semanticModel.GetSymbol(node, cancellationToken))) { yield return((IdentifierNameSyntax)node); } } }
private static bool IsPassedAsArgument(StatementSyntax statement, SemanticModel semanticModel, ILocalSymbol identitySymbol) { if (statement == null) { return(false); } var args = statement.DescendantNodes().OfKind <ArgumentSyntax>(SyntaxKind.Argument); foreach (var arg in args) { var argSymbol = semanticModel.GetSymbolInfo(arg.Expression).Symbol; if (identitySymbol.Equals(argSymbol)) { return(true); } } return(false); }
private static IdentifierNameSyntax FindLastReference( ILocalSymbol symbol, SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) { IdentifierNameSyntax lastReference = null; foreach (SyntaxNode descendant in node.DescendantNodes()) { if ((descendant is IdentifierNameSyntax identifierName) && symbol.Equals(semanticModel.GetSymbol(identifierName, cancellationToken))) { lastReference = identifierName; } } return(lastReference); }
public static void Analyze(SyntaxNodeAnalysisContext context, CatchClauseSyntax catchClause) { CatchDeclarationSyntax declaration = catchClause.Declaration; if (declaration != null) { BlockSyntax block = catchClause.Block; if (block != null) { ILocalSymbol symbol = context .SemanticModel .GetDeclaredSymbol(catchClause.Declaration, context.CancellationToken); if (symbol != null) { foreach (SyntaxNode node in block.DescendantNodes(f => !f.IsKind(SyntaxKind.CatchClause))) { if (node.IsKind(SyntaxKind.ThrowStatement)) { var throwStatement = (ThrowStatementSyntax)node; if (throwStatement.Expression != null) { ISymbol expressionSymbol = context .SemanticModel .GetSymbol(throwStatement.Expression, context.CancellationToken); if (expressionSymbol != null && symbol.Equals(expressionSymbol)) { context.ReportDiagnostic( DiagnosticDescriptors.RemoveOriginalExceptionFromThrowStatement, throwStatement.Expression); } } } } } } } }
private static bool IsAssignedToField(ExpressionStatementSyntax expressionStatement, SemanticModel semanticModel, ILocalSymbol identitySymbol) { if (expressionStatement == null) { return(false); } if (!expressionStatement.Expression.IsKind(SyntaxKind.SimpleAssignmentExpression)) { return(false); } var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression; var assignmentTarget = semanticModel.GetSymbolInfo(assignment.Left).Symbol; if (assignmentTarget?.Kind != SymbolKind.Field) { return(false); } var assignmentSource = semanticModel.GetSymbolInfo(assignment.Right).Symbol; return(identitySymbol.Equals(assignmentSource)); }
private bool IsExIsCoroutineStoppedExceptionExp(ExpressionSyntax exp, ILocalSymbol exceptionSymbol, SemanticModel model) { BinaryExpressionSyntax binExp = exp as BinaryExpressionSyntax; if (binExp == null || binExp.OperatorToken.Kind() != SyntaxKind.IsKeyword) { return(false); } ILocalSymbol leftSymbol = model.GetSymbolInfo(binExp.Left).Symbol as ILocalSymbol; INamedTypeSymbol rightSymbol = model.GetSymbolInfo(binExp.Right).Symbol as INamedTypeSymbol; if (leftSymbol != null && leftSymbol.Equals(exceptionSymbol) && rightSymbol == CoroutineStoppedExceptionType) { return(true); } return(false); }
private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) { if (GeneratedCodeAnalyzer?.IsGeneratedCode(context) == true) { return; } var catchClause = (CatchClauseSyntax)context.Node; if (catchClause.Declaration == null || catchClause.Block == null) { return; } ILocalSymbol symbol = context .SemanticModel .GetDeclaredSymbol(catchClause.Declaration, context.CancellationToken); if (symbol != null) { foreach (SyntaxNode node in catchClause.Block.DescendantNodes(f => !f.IsKind(SyntaxKind.CatchClause))) { if (node.IsKind(SyntaxKind.ThrowStatement)) { var throwStatement = (ThrowStatementSyntax)node; if (throwStatement.Expression != null) { ISymbol expressionSymbol = context .SemanticModel .GetSymbolInfo(throwStatement.Expression, context.CancellationToken) .Symbol; if (expressionSymbol != null && symbol.Equals(expressionSymbol)) { context.ReportDiagnostic( DiagnosticDescriptors.RemoveOriginalExceptionFromThrowStatement, throwStatement.Expression.GetLocation()); } } } } } if (catchClause.Declaration.Type != null && catchClause.Block.Statements.Count == 0) { ITypeSymbol typeSymbol = context .SemanticModel .GetTypeInfo(catchClause.Declaration.Type, context.CancellationToken) .Type; if (typeSymbol != null) { INamedTypeSymbol exceptionTypeSymbol = context.GetTypeByMetadataName("System.Exception"); if (typeSymbol.Equals(exceptionTypeSymbol)) { context.ReportDiagnostic( DiagnosticDescriptors.AvoidEmptyCatchClauseThatCatchesSystemException, catchClause.CatchKeyword.GetLocation()); } } } }
private static bool IsPassedAsArgument(StatementSyntax statement, SemanticModel semanticModel, ILocalSymbol identitySymbol) { if (statement == null) return false; var args = statement.DescendantNodes().OfKind<ArgumentSyntax>(SyntaxKind.Argument); foreach (var arg in args) { var argSymbol = semanticModel.GetSymbolInfo(arg.Expression).Symbol; if (identitySymbol.Equals(argSymbol)) return true; } return false; }
private static bool IsUsedAfter(ILocalSymbol local, InvocationExpressionSyntax invocation, SyntaxNodeAnalysisContext context, out IReadOnlyList <Location> locations) { if (local.TrySingleDeclaration(context.CancellationToken, out var declaration) && declaration.TryFirstAncestor(out BlockSyntax block)) { List <Location> temp = null; using (var walker = IdentifierNameWalker.Borrow(block)) { foreach (var identifierName in walker.IdentifierNames) { if (identifierName.Identifier.ValueText == local.Name && invocation.IsExecutedBefore(identifierName) == ExecutedBefore.Yes && context.SemanticModel.TryGetSymbol(identifierName, context.CancellationToken, out ILocalSymbol candidate) && local.Equals(candidate) && !IsAssigned(identifierName) && !IsReassigned(identifierName)) { if (temp == null) { temp = new List <Location>(); } temp.Add(identifierName.GetLocation()); } } locations = temp; return(locations != null); } } locations = null; return(false); bool IsAssigned(IdentifierNameSyntax identifier) { switch (identifier.Parent) { case AssignmentExpressionSyntax assignment: return(assignment.Left == identifier); case ArgumentSyntax argument when argument.RefOrOutKeyword.IsKind(SyntaxKind.OutKeyword): return(true); } return(false); } bool IsReassigned(ExpressionSyntax location) { using (var walker = MutationWalker.For(local, context.SemanticModel, context.CancellationToken)) { foreach (var mutation in walker.All()) { if (mutation.TryFirstAncestorOrSelf(out ExpressionSyntax expression) && invocation.IsExecutedBefore(expression) != ExecutedBefore.No && expression.IsExecutedBefore(location) != ExecutedBefore.No) { return(true); } } } return(false); } }
private static IEnumerable<int> GetAssignedIndexes(IEnumerable<StatementSyntax> statements, ILocalSymbol symbol, SemanticModel semanticModel) { foreach (var statement in statements) { var assignment = statement as AssignmentStatementSyntax; if (assignment == null) { yield break; } var invocation = assignment.Left as InvocationExpressionSyntax; if (invocation?.ArgumentList == null || invocation.ArgumentList.Arguments.Count != 1) { yield break; } var assignedSymbol = semanticModel.GetSymbolInfo(invocation.Expression).Symbol; if (!symbol.Equals(assignedSymbol)) { yield break; } var argument = invocation.ArgumentList.Arguments.First(); var index = GetConstantArgumentValue(argument, semanticModel); if (!index.HasValue) { yield break; } yield return index.Value; } }
private bool WouldCauseDefiniteAssignmentErrors( SemanticModel semanticModel, VariableDeclarationSyntax localDeclaration, VariableDeclaratorSyntax localDeclarator, BlockSyntax enclosingBlock, ILocalSymbol outLocalSymbol, CancellationToken cancellationToken) { // See if we have something like: // // int i = 0; // if (Goo() || Bar(out i)) // { // Console.WriteLine(i); // } // // In this case, inlining the 'i' would cause it to longer be definitely // assigned in the WriteLine invocation. // Find all the current read-references to the local. var query = from t in enclosingBlock.DescendantTokens() where t.Kind() == SyntaxKind.IdentifierToken where t.ValueText == outLocalSymbol.Name let id = t.Parent as IdentifierNameSyntax where id != null where !id.IsOnlyWrittenTo() let symbol = semanticModel.GetSymbolInfo(id).GetAnySymbol() where outLocalSymbol.Equals(symbol) select id; var references = query.ToImmutableArray <SyntaxNode>(); var root = semanticModel.SyntaxTree.GetCompilationUnitRoot(cancellationToken); // Ensure we can track the references and the local variable as we make edits // to the tree. var rootWithTrackedNodes = root.TrackNodes( references.Concat(ImmutableArray.Create <SyntaxNode>(localDeclarator, localDeclaration, enclosingBlock))); // Now, take the local variable and remove it's initializer. Then go to all // the locations where we read from it. If they're definitely assigned, then // that means the out-var did it's work and assigned the variable across all // paths. If it's not definitely assigned, then we can't inline this variable. var currentLocalDeclarator = rootWithTrackedNodes.GetCurrentNode(localDeclarator); var currentLocalDeclaration = rootWithTrackedNodes.GetCurrentNode(localDeclaration); var updatedDeclaration = currentLocalDeclaration .ReplaceNode(currentLocalDeclarator, currentLocalDeclarator.WithInitializer(null)); // If the declaration was a "var" declaration, then replace "var" with the actual // type of the local. This way we don't get a "'var v' requires an initializer" which // will suppress the message about definite assignment later. if (updatedDeclaration.Type.IsVar) { updatedDeclaration = updatedDeclaration.WithType( outLocalSymbol.Type.GenerateTypeSyntax()); } var rootWithoutInitializer = rootWithTrackedNodes.ReplaceNode( currentLocalDeclaration, updatedDeclaration); var rootWithoutInitializerTree = root.SyntaxTree.WithRootAndOptions( rootWithoutInitializer, root.SyntaxTree.Options); // Fork the compilation so we can do this analysis. var newCompilation = semanticModel.Compilation.ReplaceSyntaxTree( root.SyntaxTree, rootWithoutInitializerTree); var newSemanticModel = newCompilation.GetSemanticModel(rootWithoutInitializerTree); // NOTE: there is no current compiler API to determine if a variable is definitely // assigned or not. So, for now, we just get diagnostics for this block and see if // we get any definite assignment errors where we have a reference to the symbol. If // so, then we don't offer the fix. rootWithoutInitializer = (CompilationUnitSyntax)rootWithoutInitializerTree.GetRoot(cancellationToken); var currentBlock = rootWithoutInitializer.GetCurrentNode(enclosingBlock); var diagnostics = newSemanticModel.GetDiagnostics(currentBlock.Span, cancellationToken); var diagnosticSpans = diagnostics.Where(d => d.Id == CS0165) .Select(d => d.Location.SourceSpan) .Distinct(); var newReferenceSpans = rootWithoutInitializer.GetCurrentNodes <SyntaxNode>(references) .Select(n => n.Span) .Distinct(); return(diagnosticSpans.Intersect(newReferenceSpans).Any()); }
private static bool IsAssignedToField(ExpressionStatementSyntax expressionStatement, SemanticModel semanticModel, ILocalSymbol identitySymbol) { if (expressionStatement == null) return false; if (!expressionStatement.Expression.IsKind(SyntaxKind.SimpleAssignmentExpression)) return false; var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression; var assignmentTarget = semanticModel.GetSymbolInfo(assignment.Left).Symbol; if (assignmentTarget?.Kind != SymbolKind.Field) return false; var assignmentSource = semanticModel.GetSymbolInfo(assignment.Right).Symbol; return (identitySymbol.Equals(assignmentSource)); }