private void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext analysisContext) { var typeRule = UseOfPrereleaseReturnTypeRule; var assemblyRule = UseOfPrereleaseAssemblyReturnTypeRule; // check method return type var methodDeclaration = new DeclarationSyntaxFacade(analysisContext.SemanticModel, analysisContext.Node as MethodDeclarationSyntax); if (TryReportPrereleaseAttributeDiagnostics(analysisContext, methodDeclaration, methodDeclaration.Identifier, methodDeclaration.Type, typeRule, assemblyRule)) { return; } typeRule = UseOfPrereleaseTypeRule; assemblyRule = UseOfPrereleaseAssemblyRule; // check method-local declarations foreach (var node in methodDeclaration.DescendantNodes()) { var localDeclarationStatementSyntax = node as LocalDeclarationStatementSyntax; if (localDeclarationStatementSyntax?.Declaration != null) { var variableDeclarationSyntax = localDeclarationStatementSyntax.Declaration; if (variableDeclarationSyntax.Variables.Count != 1) { continue; } var localDeclaration = new DeclarationSyntaxFacade(analysisContext.SemanticModel, localDeclarationStatementSyntax); if (TryReportPrereleaseAttributeDiagnostics(analysisContext, localDeclaration, localDeclaration.Identifier, localDeclaration.Type, typeRule, assemblyRule)) { return; } } // TODO: maybe check the initializer? } typeRule = UseOfPrereleaseTypeRule; assemblyRule = UseOfPrereleaseAssemblyRule; // rule for parameter? // check parameters var parameters = ((MethodDeclarationSyntax)methodDeclaration).ParameterList; // TODO: support parameters foreach (var parameter in parameters.Parameters) { var identifier = parameter.Identifier; var ti = analysisContext.SemanticModel.GetTypeInfo(parameter.Type); if (TryReportPrereleaseAttributeDiagnostics(analysisContext, methodDeclaration, identifier, ti.Type, typeRule, assemblyRule, "Parameter")) { return; } } }
/// declaration private bool TryReportPrereleaseAttributeDiagnostics(SyntaxNodeAnalysisContext analysisContext, DeclarationSyntaxFacade node, SyntaxToken identifier, ITypeSymbol type, DiagnosticDescriptor typeRule, DiagnosticDescriptor assemblyRule, string identifierContext = "Variable") { if (IsNodeInPrereleaseContext(analysisContext, node)) { return(false); } if (type == null) { return(false); } var attributes = type.GetAttributes(); string attributeName; if (attributes != null && attributes.Any() && TryGetPrereleaseAttributeName(attributes, out attributeName)) { var diagnostic = Diagnostic.Create(typeRule, identifier.GetLocation(), identifier.ValueText, type.ToString(), attributeName, identifierContext); analysisContext.ReportDiagnostic(diagnostic); return(true); } // check members// not sure this is needed. var attributeNames = node.AttributeLists.AttributeFullNames(analysisContext); if (attributeNames.Any() && TryGetPrereleaseAttributeName(attributeNames, out attributeName)) { var diagnostic = Diagnostic.Create(assemblyRule, identifier.GetLocation(), identifier.ValueText, type.ToString(), attributeName, identifierContext); analysisContext.ReportDiagnostic(diagnostic); return(true); } attributes = type.ContainingAssembly.GetAttributes(); if (TryGetPrereleaseAttributeName(attributes, out attributeName)) { var diagnostic = Diagnostic.Create(assemblyRule, identifier.GetLocation(), identifier.ValueText, type.ToString(), attributeName, identifierContext); analysisContext.ReportDiagnostic(diagnostic); return(true); } return(false); }
private void AnalyzePropertyDeclaration(SyntaxNodeAnalysisContext analysisContext) { var propertyDeclaration = new DeclarationSyntaxFacade(analysisContext.SemanticModel, (PropertyDeclarationSyntax)analysisContext.Node); const string identifierContext = "Property"; var identifier = propertyDeclaration.Identifier; var assemblyRule = UseOfPrereleaseAssemblyRule; // TODO: var typeRule = UseOfPrereleaseTypeRule; // TODO: TryReportPrereleaseAttributeDiagnostics(analysisContext, propertyDeclaration, identifier, propertyDeclaration.Type, typeRule, assemblyRule, identifierContext); }
private bool IsNodeInPrereleaseContext(SyntaxNodeAnalysisContext analysisContext, DeclarationSyntaxFacade node) { while (true) { var attributeNames = node.AttributeLists.AttributeFullNames(analysisContext); string attributeName; if (attributeNames.Any() && TryGetPrereleaseAttributeName(attributeNames, out attributeName)) { return(true); } if ((CSharpSyntaxNode)node is CompilationUnitSyntax) { return(false); } // then check parent node node = node.Parent; } }
private void AnalyzeFieldDeclaration(SyntaxNodeAnalysisContext analysisContext) { var fieldDeclaration = new DeclarationSyntaxFacade(analysisContext.SemanticModel, (FieldDeclarationSyntax)analysisContext.Node); const string identifierContext = "Field"; foreach (var node in fieldDeclaration.DescendantNodes()) { var variableDeclarationSyntax = node as VariableDeclarationSyntax; if (variableDeclarationSyntax?.Variables.Count != 1) { continue; } var variable = variableDeclarationSyntax.Variables.Single(); var assemblyRule = UseOfPrereleaseAssemblyRule; var typeRule = UseOfPrereleaseTypeRule; var identifier = variable.Identifier; // check field type if (TryReportPrereleaseAttributeDiagnostics(analysisContext, fieldDeclaration, identifier, fieldDeclaration.Type, typeRule, assemblyRule, identifierContext)) { return; } var expression = variable.Initializer?.Value; if (expression != null) { var castExpressionSyntax = expression as CastExpressionSyntax; if (castExpressionSyntax != null) { expression = castExpressionSyntax.Expression; // for when we fall through var ti = analysisContext.SemanticModel.GetTypeInfo(castExpressionSyntax.Type); if (TryReportPrereleaseAttributeDiagnostics(analysisContext, fieldDeclaration, identifier, ti.Type, typeRule, assemblyRule, identifierContext)) { return; } var symbol = analysisContext.SemanticModel.GetSymbolInfo(castExpressionSyntax).Symbol; TryReportPrereleaseAttributeDiagnostics(analysisContext, symbol, identifier, "Field"); } var objectCreationSyntax = (expression as ObjectCreationExpressionSyntax); var binaryExpression = expression as BinaryExpressionSyntax; if (binaryExpression != null) { var expressionSymbol = analysisContext.SemanticModel.GetSymbolInfo(binaryExpression).Symbol; TryReportPrereleaseAttributeDiagnostics(analysisContext, expressionSymbol, identifier, "Field"); } // check the initializer from object creation: if (objectCreationSyntax?.Type != null) { var ti = analysisContext.SemanticModel.GetTypeInfo(expression); if (TryReportPrereleaseAttributeDiagnostics(analysisContext, fieldDeclaration, identifier, ti.Type, typeRule, assemblyRule, identifierContext)) { return; } } // check the initialize from member access var memberAccessSyntax = expression as MemberAccessExpressionSyntax; if (memberAccessSyntax != null) { var symbolInfo = analysisContext.SemanticModel.GetSymbolInfo(memberAccessSyntax); var symbol = symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.FirstOrDefault(); if (symbol != null) { TryReportPrereleaseAttributeDiagnostics(analysisContext, symbol, identifier, identifierContext); } } var elementAccessSyntax = expression as ElementAccessExpressionSyntax; if (elementAccessSyntax != null) { var symbolInfo = analysisContext.SemanticModel.GetSymbolInfo(elementAccessSyntax); var symbol = symbolInfo.Symbol ?? symbolInfo.CandidateSymbols.FirstOrDefault(); if (symbol != null) { TryReportPrereleaseAttributeDiagnostics(analysisContext, symbol, identifier, identifierContext); } } } } }