private void AddPrecedingRelevantExpressions() { // If we're not the first statement in this block, // and there's an expression or declaration statement directly above us, // then add the expressions from that as well. StatementSyntax previousStatement; var block = _parentStatement as BlockSyntax; if (block != null && block.CloseBraceToken == _token) { // If we're at the last brace of a block, use the last // statement in the block. previousStatement = block.Statements.LastOrDefault(); } else { previousStatement = _parentStatement.GetPreviousStatement(); } if (previousStatement != null) { switch (previousStatement.Kind()) { case SyntaxKind.ExpressionStatement: case SyntaxKind.LocalDeclarationStatement: AddRelevantExpressions(previousStatement, _expressions, includeDeclarations: true); break; case SyntaxKind.DoStatement: AddExpressionTerms((previousStatement as DoStatementSyntax).Condition, _expressions); AddLastStatementOfConstruct(previousStatement); break; case SyntaxKind.ForStatement: case SyntaxKind.ForEachStatement: case SyntaxKind.IfStatement: case SyntaxKind.CheckedStatement: case SyntaxKind.UncheckedStatement: case SyntaxKind.WhileStatement: case SyntaxKind.LockStatement: case SyntaxKind.SwitchStatement: case SyntaxKind.TryStatement: case SyntaxKind.UsingStatement: AddRelevantExpressions(previousStatement, _expressions, includeDeclarations: false); AddLastStatementOfConstruct(previousStatement); break; default: break; } } else { // This is the first statement of the block. Go to the nearest enclosing statement and add its expressions var statementAncestor = _parentStatement.Ancestors().OfType<StatementSyntax>().FirstOrDefault(node => !node.IsKind(SyntaxKind.Block)); if (statementAncestor != null) { AddRelevantExpressions(statementAncestor, _expressions, includeDeclarations: true); } } }
private static void CheckStatement(SyntaxNodeAnalysisContext context, StatementSyntax statement, string executed, string execute) { if (statement.IsKind(SyntaxKind.Block)) { return; } var nextStatement = context.Node.GetLastToken().GetNextToken().Parent; // This algorithm to get the next statement can sometimes return a parent statement (for example a BlockSyntax) // so we need to filter this case by returning if the nextStatement happens to be one ancestor of statement. if (nextStatement == null || statement.Ancestors().Contains(nextStatement)) { return; } var statementPosition = statement.GetLocation().GetLineSpan().StartLinePosition; var nextStatementPosition = nextStatement.GetLocation().GetLineSpan().StartLinePosition; if (statementPosition.Character == nextStatementPosition.Character) { var lineSpan = context.Node.SyntaxTree.GetText().Lines[nextStatementPosition.Line].Span; var location = Location.Create(context.Node.SyntaxTree, TextSpan.FromBounds(nextStatement.SpanStart, lineSpan.End)); context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, location, additionalLocations: new[] { statement.GetLocation() }, messageArgs: new object[] { executed, execute, nextStatementPosition.Line - statementPosition.Line + 1 })); } }
public static MemberDeclarationSyntax GetContainingMember(this StatementSyntax statement) { foreach (SyntaxNode ancestor in statement.Ancestors()) { switch (ancestor.Kind()) { case SyntaxKind.MethodDeclaration: case SyntaxKind.OperatorDeclaration: case SyntaxKind.ConversionOperatorDeclaration: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.DestructorDeclaration: case SyntaxKind.PropertyDeclaration: case SyntaxKind.EventDeclaration: case SyntaxKind.IndexerDeclaration: return((MemberDeclarationSyntax)ancestor); case SyntaxKind.IncompleteMember: case SyntaxKind.SimpleLambdaExpression: case SyntaxKind.ParenthesizedLambdaExpression: case SyntaxKind.AnonymousMethodExpression: return(null); } } return(null); }
private static Boolean GeneralTypeInStatementIsValid(StatementSyntax statement, SemanticModel semanticModel) { var type = GetTypeInfo(statement, semanticModel); var currentClass = statement.Ancestors().OfType <ClassDeclarationSyntax>().First(); var declaredSymbol = semanticModel.GetDeclaredSymbol(currentClass); if (!HasVisibleConstructor(type, declaredSymbol)) { return(false); } return(true); }
private void StoreVisitData(StatementSyntax node, List <StatementSyntax> conditionalCollection, List <StatementSyntax> unconditionalCollection) { var ancestors = node .Ancestors() .TakeWhile(n => !rootExpression.Equals(n)) .ToList(); if (ancestors.Any(n => n.IsAnyKind(lambdaOrLoop))) { return; } if (ancestors.Any(n => n.IsAnyKind(conditionalStatements))) { conditionalCollection.Add(node); } else { unconditionalCollection.Add(node); } }
// replaces the start span statement private async Task<Document> ReplaceStartSpanAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); var methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); string identifierString = CodeFixHelper.GetIfKeywordName(methodDeclaration.Body); SyntaxNode startSpan = CodeFixHelper.CreateEndOrStartSpan(generator, identifierString, "startDiagnosticSpan"); return await ReplaceNode(declaration, startSpan.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.ParseLeadingTrivia("// Determines the start of the span of the diagnostic that will be reported, ie the start of the squiggle").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }
//replaces an incorrect diagnostic span statement private async Task<Document> ReplaceSpanAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); var methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); string startIdentifier = (methodDeclaration.Body.Statements[4] as LocalDeclarationStatementSyntax).Declaration.Variables[0].Identifier.Text; string endIdentifier = (methodDeclaration.Body.Statements[5] as LocalDeclarationStatementSyntax).Declaration.Variables[0].Identifier.Text; SyntaxNode span = CodeFixNodeCreator.CreateSpan(generator, startIdentifier, endIdentifier); return await ReplaceNode(declaration, span.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ParseLeadingTrivia("// The span is the range of integers that define the position of the characters the red squiggle will underline").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }
//replaces an incorrect open parenthsis statement private async Task<Document> ReplaceOpenParenAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); var methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); string expressionString = (methodDeclaration.Body.Statements[0] as LocalDeclarationStatementSyntax).Declaration.Variables[0].Identifier.Text; SyntaxNode openParen = CodeFixNodeCreator.CreateOpenParen(generator, expressionString); return await ReplaceNode(declaration, openParen.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ParseLeadingTrivia("// Extracts the opening parenthesis of the if-statement condition").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }
// replaces the diagnostic report statement private async Task<Document> ReplaceDiagnosticReportAsync(Document document, StatementSyntax declaration, CancellationToken c) { var methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); string argumentName = CodeFixHelper.GetDiagnosticName(methodDeclaration); string contextName = CodeFixHelper.GetContextParameter(methodDeclaration); SyntaxNode diagnosticReport = CodeFixHelper.CreateDiagnosticReport(generator, argumentName, contextName); return await ReplaceNode(declaration, diagnosticReport.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.ParseLeadingTrivia("// Sends diagnostic information to the IDE to be shown to the user").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }
// replace the diagnostic creation statement private async Task<Document> ReplaceDiagnosticAsync(Document document, StatementSyntax declaration, CancellationToken c) { var methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); var classDeclaration = methodDeclaration.Ancestors().OfType<ClassDeclarationSyntax>().First(); SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); string locationName = CodeFixHelper.GetLocationName(methodDeclaration); string ruleName = CodeFixHelper.GetFirstRuleName(classDeclaration); if (ruleName == null) { return document; } SyntaxNode diagnostic = CodeFixHelper.CreateDiagnostic(generator, locationName, ruleName); return await ReplaceNode(declaration, diagnostic.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.ParseLeadingTrivia("// Holds the diagnostic and all necessary information to be reported").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }
// replaces the open paren statement private async Task<Document> ReplaceOpenParenAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); MethodDeclarationSyntax methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); string expressionString = CodeFixHelper.GetIfStatementName(methodDeclaration.Body); SyntaxNode openParen = CodeFixHelper.CreateOpenParen(generator, expressionString); return await ReplaceNode(declaration, openParen.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.ParseLeadingTrivia("// Extracts the opening parenthesis of the if-statement condition").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document).ConfigureAwait(false); }
// replaces the location statement private async Task<Document> ReplaceLocationAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); MethodDeclarationSyntax methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); string ifStatementIdentifier = CodeFixHelper.GetIfStatementName(methodDeclaration.Body); string spanIdentifier = CodeFixHelper.GetSpanName(methodDeclaration); SyntaxNode location = CodeFixHelper.CreateLocation(generator, ifStatementIdentifier, spanIdentifier); return await ReplaceNode(declaration, location.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.ParseLeadingTrivia("// Uses the span created above to create a location for the diagnostic squiggle to appear within the syntax tree passed in as an argument").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document).ConfigureAwait(false); }
// replaces the span statement private async Task<Document> ReplaceSpanAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); MethodDeclarationSyntax methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); string startIdentifier = CodeFixHelper.GetStartSpanName(methodDeclaration); string endIdentifier = CodeFixHelper.GetEndSpanName(methodDeclaration); SyntaxNode span = CodeFixHelper.CreateSpan(generator, startIdentifier, endIdentifier); return await ReplaceNode(declaration, span.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.ParseLeadingTrivia("// The span is the range of integers that define the position of the characters the red squiggle will underline").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document).ConfigureAwait(false); }
// replaces the end span statement private async Task<Document> ReplaceEndSpanAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); MethodDeclarationSyntax methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); string identifierString = CodeFixHelper.GetOpenParenName(methodDeclaration); SyntaxNode endSpan = CodeFixHelper.CreateEndOrStartSpan(generator, identifierString, "endDiagnosticSpan"); return await ReplaceNode(declaration, endSpan.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.ParseLeadingTrivia("// Determines the end of the span of the diagnostic that will be reported").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document).ConfigureAwait(false); }
private async Task<Document> ReplaceDiagnosticReportAsync(Document document, StatementSyntax declaration, CancellationToken c) { var methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); string argumentName = (methodDeclaration.Body.Statements[8] as LocalDeclarationStatementSyntax).Declaration.Variables[0].Identifier.Text; string contextName = (methodDeclaration.ParameterList.Parameters[0].Identifier.Text); SyntaxNode diagnosticReport = CodeFixNodeCreator.CreateDiagnosticReport(generator, argumentName, contextName); return await ReplaceNode(declaration, diagnosticReport.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ParseLeadingTrivia("// Sends diagnostic information to the IDE to be shown to the user").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }
private async Task<Document> ReplaceDiagnosticAsync(Document document, StatementSyntax declaration, CancellationToken c) { var methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); var classDeclaration = methodDeclaration.Ancestors().OfType<ClassDeclarationSyntax>().First(); SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); string locationName = (methodDeclaration.Body.Statements[7] as LocalDeclarationStatementSyntax).Declaration.Variables[0].Identifier.Text; string ruleName = CodeFixNodeCreator.GetFirstRuleName(classDeclaration); var diagnostic = CodeFixNodeCreator.CreateDiagnostic(generator, locationName, ruleName); return await ReplaceNode(declaration, diagnostic.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ParseLeadingTrivia("// Holds the diagnostic and all necessary information to be reported").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }
// removes the invalid statement from the method private async Task<Document> InvalidStatementAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxNode newInitializeDeclaration = CodeFixHelper.RemoveStatement(declaration); return await ReplaceNode(declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(), newInitializeDeclaration, document); }
//replace an incorrect end span statement private async Task<Document> ReplaceEndSpanAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); var methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); string identifierString = (methodDeclaration.Body.Statements[3] as LocalDeclarationStatementSyntax).Declaration.Variables[0].Identifier.Text; SyntaxNode endSpan = CodeFixNodeCreator.CreateEndOrStartSpan(generator, identifierString, "endDiagnosticSpan"); return await ReplaceNode(declaration, endSpan.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ParseLeadingTrivia("// Determines the end of the span of the diagnostic that will be reported").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }
// removes the provided statement from the method that it is in protected internal static SyntaxNode RemoveStatement(StatementSyntax statement) { MethodDeclarationSyntax initializeDeclaration = statement.Ancestors().OfType<MethodDeclarationSyntax>().First(); MethodDeclarationSyntax newInitializeDeclaration = initializeDeclaration.RemoveNode(statement, 0); return newInitializeDeclaration as SyntaxNode; }
//replace an incorrect diagnostic location statement private async Task<Document> ReplaceLocationAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); var methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); string ifStatementIdentifier = (methodDeclaration.Body.Statements[0] as LocalDeclarationStatementSyntax).Declaration.Variables[0].Identifier.Text; string spanIdentifier = (methodDeclaration.Body.Statements[6] as LocalDeclarationStatementSyntax).Declaration.Variables[0].Identifier.Text; SyntaxNode location = CodeFixNodeCreator.CreateLocation(generator, ifStatementIdentifier, spanIdentifier); return await ReplaceNode(declaration, location.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ParseLeadingTrivia("// Uses the span created above to create a location for the diagnostic squiggle to appear within the syntax tree passed in as an argument").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }
// replaces the if statement variable private async Task<Document> IncorrectIfAsync(Document document, StatementSyntax declaration, CancellationToken c) { SyntaxGenerator generator = SyntaxGenerator.GetGenerator(document); MethodDeclarationSyntax methodDeclaration = declaration.Ancestors().OfType<MethodDeclarationSyntax>().First(); string name = CodeFixHelper.GetContextParameter(methodDeclaration); SyntaxNode ifStatement = CodeFixHelper.IfHelper(generator, name); return await ReplaceNode(declaration, ifStatement.WithLeadingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.ParseLeadingTrivia("// The SyntaxNode found by the Initialize method should be cast to the expected type. Here, this type is IfStatementSyntax").ElementAt(0), SyntaxFactory.EndOfLine("\r\n"))), document); }