private static void AnalyzeMethodDeclaration(SyntaxNodeAnalysisContext context) { var methodNode = (MethodDeclarationSyntax)context.Node; var methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodNode); var typeSymbol = methodSymbol.ContainingType; if (typeSymbol.IsStereotype() && methodSymbol.IsDataPortalOperation() && methodSymbol.DeclaredAccessibility == Accessibility.Public) { if(typeSymbol.TypeKind == TypeKind.Interface) { context.ReportDiagnostic(Diagnostic.Create( IsOperationMethodPublicAnalyzer.makeNonPublicForInterfaceRule, methodNode.Identifier.GetLocation())); } else { var properties = new Dictionary<string, string>() { [IsOperationMethodPublicAnalyzerConstants.IsSealed] = typeSymbol.IsSealed.ToString() }.ToImmutableDictionary(); context.ReportDiagnostic(Diagnostic.Create(IsOperationMethodPublicAnalyzer.makeNonPublicRule, methodNode.Identifier.GetLocation(), properties)); } } }
private static void CheckDeclarationName(MemberDeclarationSyntax member, SyntaxToken identifier, SyntaxNodeAnalysisContext context) { var symbol = context.SemanticModel.GetDeclaredSymbol(member); if (ClassName.IsTypeComRelated(symbol?.ContainingType) || symbol.IsInterfaceImplementationOrMemberOverride() || symbol.IsExtern) { return; } if (identifier.ValueText.StartsWith("_", StringComparison.Ordinal) || identifier.ValueText.EndsWith("_", StringComparison.Ordinal)) { context.ReportDiagnostic(Diagnostic.Create(Rule, identifier.GetLocation(), MethodKindNameMapping[member.Kind()], identifier.ValueText, MessageFormatUnderscore)); return; } string suggestion; if (TryGetChangedName(identifier.ValueText, out suggestion)) { var messageEnding = string.Format(MessageFormatNonUnderscore, suggestion); context.ReportDiagnostic(Diagnostic.Create(Rule, identifier.GetLocation(), MethodKindNameMapping[member.Kind()], identifier.ValueText, messageEnding)); } }
private static void HandleEmptyStatementSyntax(SyntaxNodeAnalysisContext context) { EmptyStatementSyntax syntax = (EmptyStatementSyntax)context.Node; LabeledStatementSyntax labeledStatementSyntax = syntax.Parent as LabeledStatementSyntax; if (labeledStatementSyntax != null) { BlockSyntax blockSyntax = labeledStatementSyntax.Parent as BlockSyntax; if (blockSyntax != null) { for (int i = blockSyntax.Statements.Count - 1; i >= 0; i--) { StatementSyntax statement = blockSyntax.Statements[i]; // allow an empty statement to be used for a label, but only if no non-empty statements exist // before the end of the block if (blockSyntax.Statements[i] == labeledStatementSyntax) { return; } if (!statement.IsKind(SyntaxKind.EmptyStatement)) { break; } } } } // Code must not contain empty statements context.ReportDiagnostic(Diagnostic.Create(Descriptor, syntax.GetLocation())); }
static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic) { diagnostic = default(Diagnostic); var objectCreateExpression = nodeContext.Node as ObjectCreationExpressionSyntax; ExpressionSyntax paramNode; ExpressionSyntax altParamNode; bool canAddParameterName; if (!CheckExceptionType(nodeContext.SemanticModel, objectCreateExpression, out paramNode, out altParamNode, out canAddParameterName)) return false; var paramName = GetArgumentParameterName(paramNode); if (paramName == null) return false; var validNames = GetValidParameterNames(objectCreateExpression); if (!validNames.Contains(paramName)) { // Case 1: Parameter name is swapped var altParamName = GetArgumentParameterName(altParamNode); if (altParamName != null && validNames.Contains(altParamName)) { diagnostic = Diagnostic.Create(descriptor2, altParamNode.GetLocation()); return true; } //var guessName = GuessParameterName(nodeContext.SemanticModel, objectCreateExpression, validNames); // General case: mark only diagnostic = Diagnostic.Create(descriptor, paramNode.GetLocation(), paramName); return true; } return false; }
private static void ProcessUsings(SyntaxNodeAnalysisContext context, SyntaxList<UsingDirectiveSyntax> usings) { var usingDirectives = new List<UsingDirectiveSyntax>(); var systemUsingDirectives = new List<UsingDirectiveSyntax>(); foreach (var usingDirective in usings) { if (IsAliasOrStaticUsingDirective(usingDirective)) { continue; } if (usingDirective.IsPrecededByPreprocessorDirective()) { CheckIncorrectlyOrderedUsingsAndReportDiagnostic(context, usingDirectives); CheckIncorrectlyOrderedUsingsAndReportDiagnostic(context, systemUsingDirectives); usingDirectives.Clear(); systemUsingDirectives.Clear(); } if (HasNamespaceAliasQualifier(usingDirective) || !usingDirective.IsSystemUsingDirective()) { usingDirectives.Add(usingDirective); } else { systemUsingDirectives.Add(usingDirective); } } CheckIncorrectlyOrderedUsingsAndReportDiagnostic(context, usingDirectives); CheckIncorrectlyOrderedUsingsAndReportDiagnostic(context, systemUsingDirectives); }
private static void AnalyzeNode(SyntaxNodeAnalysisContext context) { if (context.IsGenerated()) return; var objectCreationExpression = (ObjectCreationExpressionSyntax)context.Node; var type = objectCreationExpression.Type; var typeSymbol = context.SemanticModel.GetSymbolInfo(type).Symbol as ITypeSymbol; if (!typeSymbol?.ToString().EndsWith("System.ArgumentException") ?? true) return; var argumentList = objectCreationExpression.ArgumentList as ArgumentListSyntax; if ((argumentList?.Arguments.Count ?? 0) < 2) return; var paramNameLiteral = argumentList.Arguments[1].Expression as LiteralExpressionSyntax; if (paramNameLiteral == null) return; var paramNameOpt = context.SemanticModel.GetConstantValue(paramNameLiteral); if (!paramNameOpt.HasValue) return; var paramName = paramNameOpt.Value as string; IList<string> parameters; if (IsParamNameCompatibleWithCreatingContext(objectCreationExpression, paramName, out parameters)) return; var props = parameters.ToImmutableDictionary(p => $"param{p}", p => p); var diagnostic = Diagnostic.Create(Rule, paramNameLiteral.GetLocation(), props.ToImmutableDictionary(), paramName); context.ReportDiagnostic(diagnostic); }
private static bool TryGetUnusedLocalVariableDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic) { diagnostic = default(Diagnostic); var method = nodeContext.Node as MethodDeclarationSyntax; if ((method == null) || (method.Body == null)) return false; var dataFlow = nodeContext.SemanticModel.AnalyzeDataFlow(method.Body); var variablesDeclared = dataFlow.VariablesDeclared; var variablesRead = dataFlow.ReadInside.Union(dataFlow.ReadOutside); var unused = variablesDeclared.Except(variablesRead).Except(dataFlow.WrittenInside).ToArray(); if (unused.Any()) { foreach (var unusedVar in unused) { diagnostic = Diagnostic.Create(descriptor, unusedVar.Locations.First()); return true; } } return false; }
private static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic) { diagnostic = default(Diagnostic); var localDeclarationUnused = nodeContext.Node as LocalDeclarationStatementSyntax; var body = localDeclarationUnused?.Parent as BlockSyntax; if (body == null) return false; var dataFlow = nodeContext.SemanticModel.AnalyzeDataFlow(body); var variablesDeclared = dataFlow.VariablesDeclared; var variablesRead = dataFlow.ReadInside.Union(dataFlow.ReadOutside); var unused = variablesDeclared.Except(variablesRead).ToArray(); if (unused == null) return false; if (localDeclarationUnused.Declaration == null || !localDeclarationUnused.Declaration.Variables.Any()) return false; var localDeclarationSymbol = nodeContext.SemanticModel.GetDeclaredSymbol(localDeclarationUnused.Declaration.Variables.FirstOrDefault()); if (unused.Any()) { if (unused.Contains(localDeclarationSymbol)) { diagnostic = Diagnostic.Create(descriptor, localDeclarationUnused.Declaration.GetLocation()); return true; } } return false; }
private static void Analyzer(SyntaxNodeAnalysisContext context) { if (context.IsGenerated()) return; var invocationExpression = (InvocationExpressionSyntax)context.Node; var memberExpresion = invocationExpression.Expression as MemberAccessExpressionSyntax; if (memberExpresion?.Name?.ToString() != "Match") return; var memberSymbol = context.SemanticModel.GetSymbolInfo(memberExpresion).Symbol; if (memberSymbol?.ToString() != "System.Text.RegularExpressions.Regex.Match(string, string)") return; var argumentList = invocationExpression.ArgumentList as ArgumentListSyntax; if ((argumentList?.Arguments.Count ?? 0) != 2) return; var regexLiteral = argumentList.Arguments[1].Expression as LiteralExpressionSyntax; if (regexLiteral == null) return; var regexOpt = context.SemanticModel.GetConstantValue(regexLiteral); var regex = regexOpt.Value as string; try { System.Text.RegularExpressions.Regex.Match("", regex); } catch (ArgumentException e) { var diag = Diagnostic.Create(Rule, regexLiteral.GetLocation(), e.Message); context.ReportDiagnostic(diag); } }
static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic) { diagnostic = default(Diagnostic); var anyInvoke = nodeContext.Node as InvocationExpressionSyntax; var info = nodeContext.SemanticModel.GetSymbolInfo(anyInvoke); IMethodSymbol anyResolve = info.Symbol as IMethodSymbol; if (anyResolve == null) { anyResolve = info.CandidateSymbols.OfType<IMethodSymbol>().FirstOrDefault(candidate => HasPredicateVersion(candidate)); } if (anyResolve == null || !HasPredicateVersion(anyResolve)) return false; ExpressionSyntax target, followUp; TypeSyntax type; ParameterSyntax param; if (ReplaceWithOfTypeAnyAnalyzer.MatchSelect(anyInvoke, out target, out type, out param, out followUp)) { // if (member == "Where" && followUp == null) return; diagnostic = Diagnostic.Create( descriptor, anyInvoke.GetLocation() ); return true; } return false; }
private static void HandleVariableDeclaration(SyntaxNodeAnalysisContext context) { VariableDeclarationSyntax syntax = (VariableDeclarationSyntax)context.Node; if (syntax.Parent.IsKind(SyntaxKind.FieldDeclaration) || syntax.Parent.IsKind(SyntaxKind.EventFieldDeclaration)) { // This diagnostic is only for local variables. return; } if (NamedTypeHelpers.IsContainedInNativeMethodsClass(syntax)) { return; } LocalDeclarationStatementSyntax parentDeclaration = syntax.Parent as LocalDeclarationStatementSyntax; if (parentDeclaration?.IsConst ?? false) { // this diagnostic does not apply to locals constants return; } foreach (VariableDeclaratorSyntax variableDeclarator in syntax.Variables) { if (variableDeclarator == null) { continue; } var identifier = variableDeclarator.Identifier; CheckIdentifier(context, identifier); } }
static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic) { diagnostic = default(Diagnostic); var node = nodeContext.Node as InvocationExpressionSyntax; MemberAccessExpressionSyntax mre = node.Expression as MemberAccessExpressionSyntax; if (mre == null) return false; if (mre.Name.Identifier.ValueText != "StartsWith") return false; var rr = nodeContext.SemanticModel.GetSymbolInfo(node, nodeContext.CancellationToken); if (rr.Symbol == null) return false; var symbol = rr.Symbol; if (!(symbol.ContainingType != null && symbol.ContainingType.SpecialType == SpecialType.System_String)) return false; var parameters = symbol.GetParameters(); var firstParameter = parameters.FirstOrDefault(); if (firstParameter == null || firstParameter.Type.SpecialType != SpecialType.System_String) return false; // First parameter not a string var lastParameter = parameters.Last(); if (lastParameter.Type.Name == "StringComparison") return false; // already specifying a string comparison diagnostic = Diagnostic.Create( descriptor, node.GetLocation() ); return true; }
static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic) { diagnostic = default(Diagnostic); if (nodeContext.IsFromGeneratedCode()) return false; var node = nodeContext.Node as MethodDeclarationSyntax; if (!node.Modifiers.Any(m => m.IsKind(SyntaxKind.OverrideKeyword))) return false; var lastParam = node.ParameterList.Parameters.LastOrDefault(); if (lastParam == null || lastParam.Modifiers.Any(m => m.IsKind(SyntaxKind.ParamsKeyword))) return false; if (lastParam.Type == null || !lastParam.Type.IsKind(SyntaxKind.ArrayType)) return false; var rr = nodeContext.SemanticModel.GetDeclaredSymbol(node); if (rr == null || !rr.IsOverride) return false; var baseMember = rr.OverriddenMethod; if (baseMember == null || baseMember.Parameters.Length == 0 || !baseMember.Parameters.Last().IsParams) return false; diagnostic = Diagnostic.Create( descriptor, lastParam.GetLocation(), baseMember.Name ); return true; }
static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic) { diagnostic = default(Diagnostic); if (nodeContext.IsFromGeneratedCode()) return false; var node = nodeContext.Node as ConditionalExpressionSyntax; bool? trueBranch = SimplifyConditionalTernaryExpressionCodeFixProvider.GetBool(node.WhenTrue.SkipParens()); bool? falseBranch = SimplifyConditionalTernaryExpressionCodeFixProvider.GetBool(node.WhenFalse.SkipParens()); if (trueBranch == falseBranch || trueBranch == true && falseBranch == false) // Handled by RedundantTernaryExpressionIssue return false; var typeTrue = nodeContext.SemanticModel.GetTypeInfo(node.WhenTrue); var typeFalse = nodeContext.SemanticModel.GetTypeInfo(node.WhenFalse); if (typeTrue.Type == null || typeTrue.Type.SpecialType != SpecialType.System_Boolean || typeFalse.Type == null || typeFalse.Type.SpecialType != SpecialType.System_Boolean) return false; diagnostic = Diagnostic.Create( descriptor, node.GetLocation() ); return true; }
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() } )); }
static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic) { diagnostic = default(Diagnostic); InitializerExpressionSyntax initializer = null; var node = nodeContext.Node as ArrayCreationExpressionSyntax; if (node != null) initializer = node.Initializer; var inode = nodeContext.Node as ImplicitArrayCreationExpressionSyntax; if (inode != null) initializer = inode.Initializer; if (initializer == null) return false; var varInitializer = nodeContext.Node.Parent.Parent; if (varInitializer == null) return false; var variableDeclaration = varInitializer.Parent as VariableDeclarationSyntax; if (variableDeclaration != null) { if (!variableDeclaration.Type.IsKind(SyntaxKind.ArrayType)) return false; diagnostic = Diagnostic.Create( descriptor, Location.Create(nodeContext.SemanticModel.SyntaxTree, TextSpan.FromBounds((node != null ? node.NewKeyword : inode.NewKeyword).Span.Start, initializer.Span.Start)) ); return true; } return false; }
static bool TryGetDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic) { diagnostic = default(Diagnostic); var node = nodeContext.Node as LocalDeclarationStatementSyntax; var member = node.AncestorsAndSelf().FirstOrDefault(n => n is MemberDeclarationSyntax); if (member == null) return false; var symbols = nodeContext.SemanticModel.LookupSymbols(member.SpanStart); var memberSymbol = nodeContext.SemanticModel.GetDeclaredSymbol(member); foreach (var variable in node.Declaration.Variables) { var hidingMember = symbols.FirstOrDefault(v => v.Name == variable.Identifier.ValueText && ((memberSymbol.IsStatic && v.IsStatic) || !memberSymbol.IsStatic) && !v.IsKind(SymbolKind.Local) && !v.IsKind(SymbolKind.Parameter)); if (hidingMember == null) continue; var mre = variable.Initializer?.Value as MemberAccessExpressionSyntax; if (mre != null && mre.Name.Identifier.ValueText == hidingMember.Name && mre.Expression.IsKind(SyntaxKind.ThisExpression)) { // Special case: the variable is initialized from the member it is hiding // In this case, the hiding is obviously intentional and we shouldn't show a warning. continue; } string memberType = GetMemberType(hidingMember.Kind); diagnostic = Diagnostic.Create(descriptor, variable.Identifier.GetLocation(), variable.Identifier, memberType, hidingMember.Name); return true; } return false; }
private static void AnalyzeType(SyntaxNodeAnalysisContext context, TypeDeclarationSyntax typeDeclaration) { var previousFieldReadonly = true; var previousAccessLevel = AccessLevel.NotSpecified; var previousMemberStatic = true; foreach (var member in typeDeclaration.Members) { var field = member as FieldDeclarationSyntax; if (field == null) { continue; } var currentFieldReadonly = field.Modifiers.Any(SyntaxKind.ReadOnlyKeyword); var currentAccessLevel = AccessLevelHelper.GetAccessLevel(field.Modifiers); currentAccessLevel = currentAccessLevel == AccessLevel.NotSpecified ? AccessLevel.Private : currentAccessLevel; var currentMemberStatic = field.Modifiers.Any(SyntaxKind.StaticKeyword); if (currentAccessLevel == previousAccessLevel && currentMemberStatic && previousMemberStatic && currentFieldReadonly && !previousFieldReadonly) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, NamedTypeHelpers.GetNameOrIdentifierLocation(field), AccessLevelHelper.GetName(currentAccessLevel))); } previousFieldReadonly = currentFieldReadonly; previousAccessLevel = currentAccessLevel; previousMemberStatic = currentMemberStatic; } }
private static void HandleSyntaxNode(SyntaxNodeAnalysisContext context) { var node = context.Node; var documentation = node.GetDocumentationCommentTriviaSyntax(); if (documentation != null) { IEnumerable<ParameterSyntax> parameterList = GetParameters(node); if (parameterList == null) { return; } if (documentation.Content.GetFirstXmlElement(XmlCommentHelper.InheritdocXmlTag) != null) { // Ignore nodes with an <inheritdoc/> tag. return; } var xmlParameterNames = documentation.Content.GetXmlElements(XmlCommentHelper.ParamXmlTag) .Select(XmlCommentHelper.GetFirstAttributeOrDefault<XmlNameAttributeSyntax>) .Where(x => x != null) .ToImmutableArray(); foreach (var parameter in parameterList) { if (!xmlParameterNames.Any(x => x.Identifier.Identifier.ValueText == parameter.Identifier.ValueText)) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, parameter.Identifier.GetLocation(), parameter.Identifier.ValueText)); } } } }
private static void HandleArrayCreation(SyntaxNodeAnalysisContext context) { var arrayCreation = (ArrayCreationExpressionSyntax)context.Node; if (arrayCreation.Type == null) { return; } foreach (var arrayRankSpecifierSyntax in arrayCreation.Type.RankSpecifiers) { if (!arrayRankSpecifierSyntax.Sizes.Any()) { continue; } var lastSize = arrayRankSpecifierSyntax.Sizes .Last(); if (!arrayRankSpecifierSyntax.CloseBracketToken.IsMissing) { CheckIfLocationOfLastArgumentOrParameterAndCloseTokenAreTheSame( context, lastSize, arrayRankSpecifierSyntax.CloseBracketToken); } } }
private static void ProcessUsingsAndReportDiagnostic(SyntaxList<UsingDirectiveSyntax> usings, SyntaxNodeAnalysisContext context) { string systemUsingDirectivesShouldBeBeforeThisName = null; for (var i = 1; i < usings.Count; i++) { var usingDirective = usings[i]; if (usingDirective.Alias != null || !usingDirective.StaticKeyword.IsKind(SyntaxKind.None) || usingDirective.IsPrecededByPreprocessorDirective()) { continue; } if (usingDirective.IsSystemUsingDirective()) { if (systemUsingDirectivesShouldBeBeforeThisName != null) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, usingDirective.GetLocation(), usingDirective.Name.ToNormalizedString(), systemUsingDirectivesShouldBeBeforeThisName)); continue; } var previousUsing = usings[i - 1]; if (!previousUsing.IsSystemUsingDirective() || previousUsing.StaticKeyword.Kind() != SyntaxKind.None) { systemUsingDirectivesShouldBeBeforeThisName = previousUsing.Name.ToNormalizedString(); context.ReportDiagnostic(Diagnostic.Create(Descriptor, usingDirective.GetLocation(), usingDirective.Name.ToNormalizedString(), systemUsingDirectivesShouldBeBeforeThisName)); } } } }
private static void HandleBlock(SyntaxNodeAnalysisContext context) { BlockSyntax block = context.Node as BlockSyntax; if (block != null && block.Statements.Any()) { var previousStatement = block.Statements[0]; FileLinePositionSpan previousStatementLocation = previousStatement.GetLineSpan(); FileLinePositionSpan currentStatementLocation; for (int i = 1; i < block.Statements.Count; i++) { var currentStatement = block.Statements[i]; currentStatementLocation = currentStatement.GetLineSpan(); if (previousStatementLocation.EndLinePosition.Line == currentStatementLocation.StartLinePosition.Line && !IsLastTokenMissing(previousStatement)) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, block.Statements[i].GetLocation())); } previousStatementLocation = currentStatementLocation; previousStatement = currentStatement; } } }
private void AnalyzeRegexCreation(SyntaxNodeAnalysisContext context) { var objectCreation = (ObjectCreationExpressionSyntax) context.Node; var type = context.SemanticModel.GetSymbolInfo(objectCreation.Type).Symbol as ITypeSymbol; if (type == null || !type.Equals(context.SemanticModel.GetClrType(typeof(Regex)))) { return; } var pattern = objectCreation.ArgumentList.Arguments[0].Expression.GetLiteral(context.SemanticModel); if (pattern == null) { return; } try { var regex = new Regex(pattern, RegexOptions.None, Timeout); } catch (ArgumentException e) { context.ReportDiagnostic(Diagnostic.Create(InvalidRegexRule, objectCreation.ArgumentList.Arguments[0].GetLocation(), e.Message)); } }
private static void AnalyzeInvocation(SyntaxNodeAnalysisContext context, Compilation compilation) { if (context.IsGenerated()) return; var methodInvokeSyntax = context.Node as InvocationExpressionSyntax; var childNodes = methodInvokeSyntax.ChildNodes(); var methodCaller = childNodes.OfType<MemberAccessExpressionSyntax>().FirstOrDefault(); if (methodCaller == null) return; var argumentsCount = CountArguments(childNodes); var classSymbol = GetCallerClassSymbol(context.SemanticModel, methodCaller.Expression); if (classSymbol == null || !classSymbol.MightContainExtensionMethods) return; var methodSymbol = GetCallerMethodSymbol(context.SemanticModel, methodCaller.Name, argumentsCount); if (methodSymbol == null || !methodSymbol.IsExtensionMethod) return; if (ContainsDynamicArgument(context.SemanticModel, childNodes)) return; ExpressionSyntax invocationStatement; if (methodInvokeSyntax.Parent.IsNotKind(SyntaxKind.ArrowExpressionClause)) { invocationStatement = (methodInvokeSyntax.FirstAncestorOrSelfThatIsAStatement() as ExpressionStatementSyntax).Expression; } else { invocationStatement = methodInvokeSyntax.FirstAncestorOrSelfOfType<ArrowExpressionClauseSyntax>().Expression; } if (invocationStatement == null) return; if (IsSelectingADifferentMethod(childNodes, methodCaller.Name, context.Node.SyntaxTree, methodSymbol, invocationStatement, compilation)) return; context.ReportDiagnostic(Diagnostic.Create(Rule, methodCaller.GetLocation(), methodSymbol.Name, classSymbol.Name)); }
private static void HandleDocumentation(SyntaxNodeAnalysisContext context) { var documentationTrivia = context.Node as DocumentationCommentTriviaSyntax; if (documentationTrivia != null) { var summaryElement = documentationTrivia.Content.GetFirstXmlElement(XmlCommentHelper.SummaryXmlTag) as XmlElementSyntax; if (summaryElement != null) { var textElement = summaryElement.Content.FirstOrDefault() as XmlTextSyntax; if (textElement != null) { string text = XmlCommentHelper.GetText(textElement, true); if (!string.IsNullOrEmpty(text)) { if (text.TrimStart().StartsWith(DefaultText, StringComparison.Ordinal)) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, summaryElement.GetLocation())); } } } } } }
private static void AnalyzePropertyDeclaration(SyntaxNodeAnalysisContext context) { var propertyNode = (PropertyDeclarationSyntax)context.Node; if(!propertyNode.ContainsDiagnostics) { var propertySymbol = context.SemanticModel.GetDeclaredSymbol(propertyNode); var classSymbol = propertySymbol.ContainingType; if (propertySymbol != null && classSymbol != null && classSymbol.IsStereotype() && !propertySymbol.IsAbstract && !propertySymbol.IsStatic) { if (propertySymbol.GetMethod != null) { EvaluatePropertiesForSimplicityAnalyzer.AnalyzePropertyGetter(propertyNode, context); } if (propertySymbol.SetMethod != null) { EvaluatePropertiesForSimplicityAnalyzer.AnalyzePropertySetter(propertyNode, context); } } } }
private static void AnalyzeTell(SyntaxNodeAnalysisContext context) { var invocationExpr = (InvocationExpressionSyntax)context.Node; // technically this should be a MemberAccessExpression, since it's invoked as a method off of IActorRef / ICanTell var memberAccessExpr = invocationExpr.Expression as MemberAccessExpressionSyntax; if (memberAccessExpr?.Name.ToString() != TargetMethodName) return; // need to verify that this `Tell` method is actually `ICanTell.Tell` var memberSymbol = context.SemanticModel.GetSymbolInfo(memberAccessExpr).Symbol as IMethodSymbol; var memberIsICanTell = (memberSymbol?.ToString().StartsWith(ICanTellMethodFQN) ?? false) || (memberSymbol?.ToString().StartsWith(IActorRefTellMethodFQN) ?? false); var memberIsActorRefExtension = memberSymbol?.ToString().StartsWith(ActorRefImplicitSenderTellFQN) ?? false; if (!memberIsICanTell && !memberIsActorRefExtension) return; // need to get the first argument being passed to the `Tell` method var argumentList = invocationExpr.ArgumentList as ArgumentListSyntax; if ((argumentList?.Arguments.Count ?? 0) < 1) return; // ReSharper disable once PossibleNullReferenceException //already validated as not null above var messageArgument = context.SemanticModel.GetSymbolInfo(memberIsICanTell ? argumentList.Arguments[0].Expression : argumentList.Arguments[1].Expression).Symbol; var allInterfaces = ((messageArgument as INamedTypeSymbol)?.Interfaces ?? ImmutableArray<INamedTypeSymbol>.Empty).Concat(messageArgument?.ContainingType.Interfaces ?? ImmutableArray<INamedTypeSymbol>.Empty).ToImmutableArray(); if (allInterfaces.Any(y => y.ToString().StartsWith(ISystemMsgFQN))) { // found an ISystemMessage being passed into a Tell method var diagnostic = Diagnostic.Create(Rule, argumentList.GetLocation(), messageArgument.ToString(), DiagnosticSeverity.Error); context.ReportDiagnostic(diagnostic); } }
// TODO: Ideally, a load of static code analysis here, but just checking the first use would be a start. private void FirstUseOfUntrustedParameterShouldNotBeArgumentToTrustedParameter(SyntaxNodeAnalysisContext context) { var parameterSyntax = (ParameterSyntax)context.Node; var model = context.SemanticModel; var parameter = model.GetDeclaredSymbol(parameterSyntax); if (parameter.HasAttribute(TrustedAttributeName)) { return; } var container = parameter.ContainingSymbol; if ((container as IMethodSymbol)?.MethodKind == MethodKind.AnonymousFunction) { // Be lenient for anonymous functions. Not entirely sure whether this is a good idea, // admittedly. return; } var firstUse = container.DeclaringSyntaxReferences .SelectMany(syntaxRef => syntaxRef.GetSyntax().DescendantNodes()) .Select(node => ParameterUsage.ForNode(node, model, parameter)) .FirstOrDefault(usage => usage != null); if (firstUse?.CorrespondingParameter == null) { return; } if (firstUse.CorrespondingParameter.HasAttribute(TrustedAttributeName)) { context.ReportDiagnostic(UntrustedParameterIsTrusted, firstUse.UsageNode, parameter.Name, container.Name); } }
private static void AnalyzeNode(SyntaxNodeAnalysisContext context) { if (context.IsGenerated()) return; var lambda = context.Node as ExpressionSyntax; var invocation = GetInvocationIfAny(lambda); if (invocation == null || invocation.ArgumentList.Arguments.Count == 0) return; var lambdaParameters = BuildParameters(lambda); if (!MatchArguments(lambdaParameters, invocation.ArgumentList)) return; var root = lambda.SyntaxTree.GetRoot(); var newRoot = root.ReplaceNode(lambda, invocation.Expression as ExpressionSyntax); var semanticNode = GetNodeRootForAnalysis(lambda); var newSemanticNode = newRoot.DescendantNodesAndSelf() .Where(x => x.SpanStart == semanticNode.SpanStart && x.Span.OverlapsWith(context.Node.Span)) .LastOrDefault(x => x.Kind() == semanticNode.Kind()); if (newSemanticNode == null || ReplacementChangesSemantics(semanticNode, newSemanticNode, context.SemanticModel)) return; var diagnostic = Diagnostic.Create( Rule, context.Node.GetLocation(), invocation.Expression.ToString()); context.ReportDiagnostic(diagnostic); }
private static void CheckOverridableCallInConstructor(SyntaxNodeAnalysisContext c) { var invocationExpression = (InvocationExpressionSyntax)c.Node; var calledOn = (invocationExpression.Expression as MemberAccessExpressionSyntax)?.Expression; var isCalledOnThis = calledOn == null || calledOn is ThisExpressionSyntax; if (!isCalledOnThis) { return; } var enclosingSymbol = c.SemanticModel.GetEnclosingSymbol(invocationExpression.SpanStart) as IMethodSymbol; if (!IsMethodConstructor(enclosingSymbol)) { return; } var methodSymbol = c.SemanticModel.GetSymbolInfo(invocationExpression.Expression).Symbol as IMethodSymbol; if (methodSymbol != null && IsMethodOverridable(methodSymbol) && enclosingSymbol.IsInType(methodSymbol.ContainingType)) { c.ReportDiagnostic(Diagnostic.Create(Rule, invocationExpression.Expression.GetLocation(), methodSymbol.Name)); } }
private void HandleElementAccess(SyntaxNodeAnalysisContext context) { var elementAccess = (ElementAccessExpressionSyntax)context.Node; AnalyzeArgumentList(context, elementAccess.ArgumentList); }
internal static void AnalyzeNotEqualsExpression(SyntaxNodeAnalysisContext context) { Analyze(context, (BinaryExpressionSyntax)context.Node); }
private void AnalyzeTernaryConditionalExpression( SyntaxNodeAnalysisContext context, INamedTypeSymbol?expressionType, IMethodSymbol?referenceEqualsMethod) { var cancellationToken = context.CancellationToken; var conditionalExpression = (TConditionalExpressionSyntax)context.Node; var option = context.GetAnalyzerOptions().PreferNullPropagation; if (!option.Value) { return; } var syntaxFacts = GetSyntaxFacts(); syntaxFacts.GetPartsOfConditionalExpression( conditionalExpression, out var condition, out var whenTrue, out var whenFalse); var conditionNode = (TExpressionSyntax)condition; var whenTrueNode = (TExpressionSyntax)syntaxFacts.WalkDownParentheses(whenTrue); var whenFalseNode = (TExpressionSyntax)syntaxFacts.WalkDownParentheses(whenFalse); if (!TryAnalyzeCondition( context, syntaxFacts, referenceEqualsMethod, conditionNode, out var conditionPartToCheck, out var isEquals)) { return; } // Needs to be of the form: // x == null ? null : ... or // x != null ? ... : null; if (isEquals && !syntaxFacts.IsNullLiteralExpression(whenTrueNode)) { return; } if (!isEquals && !syntaxFacts.IsNullLiteralExpression(whenFalseNode)) { return; } var whenPartToCheck = isEquals ? whenFalseNode : whenTrueNode; var semanticModel = context.SemanticModel; var whenPartMatch = GetWhenPartMatch(syntaxFacts, semanticModel, conditionPartToCheck, whenPartToCheck, cancellationToken); if (whenPartMatch == null) { return; } // can't use ?. on a pointer var whenPartType = semanticModel.GetTypeInfo(whenPartMatch, cancellationToken).Type; if (whenPartType is IPointerTypeSymbol) { return; } // ?. is not available in expression-trees. Disallow the fix in that case. var type = semanticModel.GetTypeInfo(conditionalExpression, cancellationToken).Type; if (type?.IsValueType == true) { if (type is not INamedTypeSymbol namedType || namedType.ConstructedFrom.SpecialType != SpecialType.System_Nullable_T) { // User has something like: If(str is nothing, nothing, str.Length) // In this case, converting to str?.Length changes the type of this from // int to int? return; } // But for a nullable type, such as If(c is nothing, nothing, c.nullable) // converting to c?.nullable doesn't affect the type } if (IsInExpressionTree(semanticModel, conditionNode, expressionType, cancellationToken)) { return; } var locations = ImmutableArray.Create( conditionalExpression.GetLocation(), conditionPartToCheck.GetLocation(), whenPartToCheck.GetLocation()); var whenPartIsNullable = whenPartType?.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T; var properties = whenPartIsNullable ? s_whenPartIsNullableProperties : ImmutableDictionary <string, string?> .Empty; context.ReportDiagnostic(DiagnosticHelper.Create( Descriptor, conditionalExpression.GetLocation(), option.Notification.Severity, locations, properties)); }
private static void HandleMemberDeclaration(SyntaxNodeAnalysisContext context, bool needsComment, SyntaxNode node, TypeParameterListSyntax typeParameterList) { if (!needsComment) { // Documentation is not required for this element. return; } if (typeParameterList == null) { // The member does not have a type parameter list return; } var documentation = node.GetDocumentationCommentTriviaSyntax(); if (documentation == null) { // Don't report if the documentation is missing return; } if (documentation.Content.GetFirstXmlElement(XmlCommentHelper.InheritdocXmlTag) != null) { // Ignore nodes with an <inheritdoc/> tag. return; } // Check if the return value is documented var includeElement = documentation.Content.GetFirstXmlElement(XmlCommentHelper.IncludeXmlTag); if (includeElement != null) { string rawDocumentation; var declaration = context.SemanticModel.GetDeclaredSymbol(context.Node, context.CancellationToken); if (declaration == null) { return; } rawDocumentation = declaration.GetDocumentationCommentXml(expandIncludes: true, cancellationToken: context.CancellationToken); var completeDocumentation = XElement.Parse(rawDocumentation, LoadOptions.None); if (completeDocumentation.Nodes().OfType <XElement>().Any(element => element.Name == XmlCommentHelper.InheritdocXmlTag)) { // Ignore nodes with an <inheritdoc/> tag in the included XML. return; } var typeParameterAttributes = completeDocumentation.Nodes() .OfType <XElement>() .Where(element => element.Name == XmlCommentHelper.TypeParamXmlTag) .Select(element => element.Attribute(XmlCommentHelper.NameArgumentName)) .Where(x => x != null); foreach (var parameter in typeParameterList.Parameters) { if (!typeParameterAttributes.Any(x => x.Value == parameter.Identifier.ValueText)) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, parameter.Identifier.GetLocation(), parameter.Identifier.ValueText)); } } } else { var xmlParameterNames = documentation.Content.GetXmlElements(XmlCommentHelper.TypeParamXmlTag) .Select(XmlCommentHelper.GetFirstAttributeOrDefault <XmlNameAttributeSyntax>) .Where(x => x != null) .ToImmutableArray(); foreach (var parameter in typeParameterList.Parameters) { if (!xmlParameterNames.Any(x => x.Identifier.Identifier.ValueText == parameter.Identifier.ValueText)) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, parameter.Identifier.GetLocation(), parameter.Identifier.ValueText)); } } } }
private static void CheckForNullDereference(CSharpExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context) { var methodSymbol = context.SemanticModel.GetSymbolInfo(context.Node).Symbol ?? context.SemanticModel.GetDeclaredSymbol(context.Node); if (!methodSymbol.IsPubliclyAccessible()) { return; } var nullPointerCheck = new NullPointerDereference.NullPointerCheck(explodedGraph); explodedGraph.AddExplodedGraphCheck(nullPointerCheck); var identifiers = new HashSet <IdentifierNameSyntax>(); void memberAccessingHandler(object sender, MemberAccessingEventArgs args) => CollectMemberAccesses(args, identifiers, context.SemanticModel); nullPointerCheck.MemberAccessing += memberAccessingHandler; try { explodedGraph.Walk(); } finally { nullPointerCheck.MemberAccessing -= memberAccessingHandler; } foreach (var identifier in identifiers) { var message = IsArgumentOfConstructorInitializer(identifier) ? string.Format(Constructor, identifier.Identifier.ValueText) : string.Format(Method, identifier.Identifier.ValueText); context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, identifier.GetLocation(), message)); } bool IsArgumentOfConstructorInitializer(IdentifierNameSyntax identifier) => identifier.FirstAncestorOrSelf <ConstructorInitializerSyntax>() != null; }
protected override void AnalyzeNode(SyntaxNodeAnalysisContext context) { var node = context.Node; var semanticModel = context.SemanticModel; Action <Diagnostic> reportDiagnostic = context.ReportDiagnostic; var cancellationToken = context.CancellationToken; string filePath = node.SyntaxTree.FilePath; // An InitializerExpressionSyntax has an ObjectCreationExpressionSyntax as it's parent, i.e // var testing = new TestClass { Name = "Bob" }; // | |--------------| <- InitializerExpressionSyntax or SyntaxKind.ObjectInitializerExpression // |----------------------------| <- ObjectCreationExpressionSyntax or SyntaxKind.ObjectCreationExpression var initializerExpression = node as InitializerExpressionSyntax; if (initializerExpression?.Parent is ObjectCreationExpressionSyntax) { var objectCreation = node.Parent as ObjectCreationExpressionSyntax; var typeInfo = semanticModel.GetTypeInfo(objectCreation, cancellationToken); if (typeInfo.ConvertedType?.TypeKind != TypeKind.Error && typeInfo.ConvertedType?.IsReferenceType == true && objectCreation.Parent?.IsKind(SyntaxKind.EqualsValueClause) == true && objectCreation.Parent?.Parent?.IsKind(SyntaxKind.VariableDeclarator) == true) { reportDiagnostic(Diagnostic.Create(InitializerCreationRule, ((VariableDeclaratorSyntax)objectCreation.Parent.Parent).Identifier.GetLocation(), EmptyMessageArgs)); HeapAllocationAnalyzerEventSource.Logger.NewInitializerExpression(filePath); return; } } var implicitArrayExpression = node as ImplicitArrayCreationExpressionSyntax; if (implicitArrayExpression != null) { reportDiagnostic(Diagnostic.Create(ImplicitArrayCreationRule, implicitArrayExpression.NewKeyword.GetLocation(), EmptyMessageArgs)); HeapAllocationAnalyzerEventSource.Logger.NewImplicitArrayCreationExpression(filePath); return; } var newAnon = node as AnonymousObjectCreationExpressionSyntax; if (newAnon != null) { reportDiagnostic(Diagnostic.Create(AnonymousNewObjectRule, newAnon.NewKeyword.GetLocation(), EmptyMessageArgs)); HeapAllocationAnalyzerEventSource.Logger.NewAnonymousObjectCreationExpression(filePath); return; } var newArr = node as ArrayCreationExpressionSyntax; if (newArr != null) { reportDiagnostic(Diagnostic.Create(NewArrayRule, newArr.NewKeyword.GetLocation(), EmptyMessageArgs)); HeapAllocationAnalyzerEventSource.Logger.NewArrayExpression(filePath); return; } var newObj = node as ObjectCreationExpressionSyntax; if (newObj != null) { var typeInfo = semanticModel.GetTypeInfo(newObj, cancellationToken); if (typeInfo.ConvertedType != null && typeInfo.ConvertedType.TypeKind != TypeKind.Error && typeInfo.ConvertedType.IsReferenceType) { reportDiagnostic(Diagnostic.Create(NewObjectRule, newObj.NewKeyword.GetLocation(), EmptyMessageArgs)); HeapAllocationAnalyzerEventSource.Logger.NewObjectCreationExpression(filePath); } return; } var letKind = node as LetClauseSyntax; if (letKind != null) { reportDiagnostic(Diagnostic.Create(LetCauseRule, letKind.LetKeyword.GetLocation(), EmptyMessageArgs)); HeapAllocationAnalyzerEventSource.Logger.LetClauseExpression(filePath); return; } }
public static void Analyze(SyntaxNodeAnalysisContext context, in SimpleMemberInvocationExpressionInfo invocationInfo)
private void AnalyzeInvocation(SyntaxNodeAnalysisContext context) { var invocation = (TInvocationExpressionSyntax)context.Node; SemanticModel semanticModel = context.SemanticModel; ISymbol symbol = semanticModel.GetSymbolInfo(invocation, context.CancellationToken).Symbol; if (symbol == null || symbol.Kind != SymbolKind.Method || !symbol.Name.StartsWith("Register", StringComparison.Ordinal)) { return; } var method = (IMethodSymbol)symbol; NoteRegisterActionInvocation(method, invocation, semanticModel, context.CancellationToken); bool isRegisterSymbolAction = IsRegisterAction(DiagnosticWellKnownNames.RegisterSymbolActionName, method, _analysisContext, _compilationStartAnalysisContext); bool isRegisterSyntaxNodeAction = IsRegisterAction(DiagnosticWellKnownNames.RegisterSyntaxNodeActionName, method, _analysisContext, _compilationStartAnalysisContext, _codeBlockStartAnalysisContext); bool isRegisterCodeBlockStartAction = IsRegisterAction(DiagnosticWellKnownNames.RegisterCodeBlockStartActionName, method, _analysisContext, _compilationStartAnalysisContext); bool isRegisterOperationAction = IsRegisterAction(DiagnosticWellKnownNames.RegisterOperationActionName, method, _analysisContext, _compilationStartAnalysisContext, _operationBlockStartAnalysisContext); if (isRegisterSymbolAction || isRegisterSyntaxNodeAction || isRegisterOperationAction) { if (method.Parameters.Length == 2 && method.Parameters[1].IsParams) { IEnumerable <SyntaxNode>?arguments = GetArgumentExpressions(invocation); if (arguments != null) { int argumentCount = arguments.Count(); if (argumentCount >= 1) { ITypeSymbol type = semanticModel.GetTypeInfo(arguments.First(), context.CancellationToken).ConvertedType; if (type == null || type.Name.Equals(nameof(Action), StringComparison.Ordinal)) { if (argumentCount == 1) { DiagnosticDescriptor rule; if (isRegisterSymbolAction) { rule = MissingSymbolKindArgumentRule; } else if (isRegisterOperationAction) { rule = MissingOperationKindArgumentRule; } else { rule = MissingSyntaxKindArgumentRule; } SyntaxNode invocationExpression = GetInvocationExpression(invocation); Diagnostic diagnostic = invocationExpression.CreateDiagnostic(rule); context.ReportDiagnostic(diagnostic); } else if (isRegisterSymbolAction) { foreach (SyntaxNode argument in arguments.Skip(1)) { symbol = semanticModel.GetSymbolInfo(argument, context.CancellationToken).Symbol; if (symbol != null && #pragma warning disable CA1508 // Avoid dead conditional code - https://github.com/dotnet/roslyn-analyzers/issues/4519 symbol.Kind == SymbolKind.Field && #pragma warning restore CA1508 // Avoid dead conditional code _symbolKind.Equals(symbol.ContainingType) && !s_supportedSymbolKinds.Contains(symbol.Name)) { Diagnostic diagnostic = argument.CreateDiagnostic(UnsupportedSymbolKindArgumentRule, symbol.Name); context.ReportDiagnostic(diagnostic); } } } } } } } } if (!method.TypeParameters.IsEmpty && (isRegisterSyntaxNodeAction || isRegisterCodeBlockStartAction)) { ITypeSymbol?typeArgument = null; if (method.TypeParameters.Length == 1) { if (method.TypeParameters[0].Name == DiagnosticWellKnownNames.TLanguageKindEnumName) { typeArgument = method.TypeArguments[0]; } } else { ITypeParameterSymbol typeParam = method.TypeParameters.FirstOrDefault(t => t.Name == DiagnosticWellKnownNames.TLanguageKindEnumName); if (typeParam != null) { int index = method.TypeParameters.IndexOf(typeParam); typeArgument = method.TypeArguments[index]; } } if (typeArgument != null && typeArgument.TypeKind != TypeKind.TypeParameter && typeArgument.TypeKind != TypeKind.Error && !IsSyntaxKind(typeArgument)) { Location location = typeArgument.Locations[0]; if (!location.IsInSource) { SyntaxNode invocationExpression = GetInvocationExpression(invocation); location = invocationExpression.GetLocation(); } Diagnostic diagnostic = Diagnostic.Create(InvalidSyntaxKindTypeArgumentRule, location, typeArgument.Name, DiagnosticWellKnownNames.TLanguageKindEnumName, method.Name); context.ReportDiagnostic(diagnostic); } } }
private static void CheckEmptyNullableAccess(CSharpExplodedGraph explodedGraph, SyntaxNodeAnalysisContext context) { var nullPointerCheck = new NullValueAccessedCheck(explodedGraph); explodedGraph.AddExplodedGraphCheck(nullPointerCheck); var nullIdentifiers = new HashSet <IdentifierNameSyntax>(); void nullValueAccessedHandler(object sender, MemberAccessedEventArgs args) => nullIdentifiers.Add(args.Identifier); nullPointerCheck.ValuePropertyAccessed += nullValueAccessedHandler; try { explodedGraph.Walk(); } finally { nullPointerCheck.ValuePropertyAccessed -= nullValueAccessedHandler; } foreach (var nullIdentifier in nullIdentifiers) { context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, nullIdentifier.Parent.GetLocation(), nullIdentifier.Identifier.ValueText)); } }
private static void AnalyzeUsingStatement(SyntaxNodeAnalysisContext context) { var usingStatement = (UsingStatementSyntax)context.Node; StatementSyntax statement = usingStatement.Statement; if (statement?.Kind() != SyntaxKind.Block) { return; } var block = (BlockSyntax)statement; StatementSyntax lastStatement = block.Statements.LastOrDefault(); if (lastStatement == null) { return; } if (lastStatement.SpanContainsDirectives()) { return; } SimpleMemberInvocationStatementInfo info = SyntaxInfo.SimpleMemberInvocationStatementInfo(lastStatement); if (!info.Success) { return; } if (info.Arguments.Any()) { return; } string methodName = info.NameText; if (methodName != "Dispose" && methodName != "Close") { return; } ExpressionSyntax usingExpression = usingStatement.Expression; if (usingExpression != null) { if (CSharpFactory.AreEquivalent(info.Expression, usingExpression)) { ReportDiagnostic(context, info.Statement, methodName); } } else { VariableDeclarationSyntax usingDeclaration = usingStatement.Declaration; if (usingDeclaration != null && info.Expression.Kind() == SyntaxKind.IdentifierName) { var identifierName = (IdentifierNameSyntax)info.Expression; VariableDeclaratorSyntax declarator = usingDeclaration.Variables.LastOrDefault(); if (declarator != null && declarator.Identifier.ValueText == identifierName.Identifier.ValueText) { ISymbol symbol = context.SemanticModel.GetDeclaredSymbol(declarator, context.CancellationToken); if (SymbolEqualityComparer.Default.Equals(symbol, context.SemanticModel.GetSymbol(identifierName, context.CancellationToken))) { ReportDiagnostic(context, info.Statement, methodName); } } } } }
/// <summary> /// Analyzes the top-level elements of a documentation comment. /// </summary> /// <param name="context">The current analysis context.</param> /// <param name="settings">The StyleCop settings to use.</param> /// <param name="needsComment"><see langword="true"/> if the current documentation settings indicate that the /// element should be documented; otherwise, <see langword="false"/>.</param> /// <param name="syntaxList">The <see cref="XmlElementSyntax"/> or <see cref="XmlEmptyElementSyntax"/> of the node /// to examine.</param> /// <param name="diagnosticLocations">The location(s) where diagnostics, if any, should be reported.</param> protected abstract void HandleXmlElement(SyntaxNodeAnalysisContext context, StyleCopSettings settings, bool needsComment, IEnumerable <XmlNodeSyntax> syntaxList, params Location[] diagnosticLocations);
/// <summary> /// Analyzes the XML elements of a documentation comment. /// </summary> /// <param name="context">The current analysis context.</param> /// <param name="needsComment"><see langword="true"/> if the current documentation settings indicate that the /// element should be documented; otherwise, <see langword="false"/>.</param> /// <param name="completeDocumentation">The complete documentation for the declared symbol, with any /// <c><include></c> elements expanded. If the XML documentation comment included a <c><param></c> /// element, this value will be <see langword="null"/>, even if the XML documentation comment also included an /// <c><include></c> element.</param> /// <param name="diagnosticLocations">The location(s) where diagnostics, if any, should be reported.</param> protected abstract void HandleCompleteDocumentation(SyntaxNodeAnalysisContext context, bool needsComment, XElement completeDocumentation, params Location[] diagnosticLocations);
protected abstract void LanguageSpecificAnalyzeSyntax( SyntaxNodeAnalysisContext context, SyntaxTree syntaxTree, AnalyzerOptions options, CancellationToken cancellationToken );
protected abstract TContext CreateContext(SyntaxNodeAnalysisContext context);
public void AnalyzeNode(SyntaxNodeAnalysisContext context) { // Ensure only executable nodes are analyzed. Assert.NotEqual(SyntaxKind.MethodDeclaration, context.Node.Kind()); context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Node.GetLocation())); }
private void AnalyzeSqlTypeMatching(SyntaxNodeAnalysisContext context) { var expression = (AssignmentExpressionSyntax)context.Node; if (expression.Left is MemberAccessExpressionSyntax leftExpression && leftExpression.Expression is InvocationExpressionSyntax addExpression) { if (addExpression.ArgumentList.Arguments.Count < 1) { return; } var dbParameterMetaName = context.Compilation.GetTypeByMetadataName(typeof(DbParameter).FullName); var valueSymbol = context.SemanticModel.GetSymbolInfo(leftExpression).Symbol; // command.Parameters.Add().|Value| if (valueSymbol is null) { return; } if (valueSymbol.IsOverride && valueSymbol.Name == "Value" && valueSymbol is IPropertySymbol valuePropertySymbol && SymbolEqualityComparer.Default.Equals(dbParameterMetaName, valuePropertySymbol.OverriddenProperty.ContainingType) && addExpression.ArgumentList.Arguments[1].Expression is MemberAccessExpressionSyntax sqlType) { SpecialType rightExpressionType = 0; if (expression.Right is IdentifierNameSyntax identifierExpression) { rightExpressionType = context.SemanticModel.GetTypeInfo(identifierExpression).Type.SpecialType; } else if (expression.Right is BinaryExpressionSyntax binaryExpression) { if (binaryExpression.Left is CastExpressionSyntax leftCast) { rightExpressionType = context.SemanticModel.GetTypeInfo(leftCast.Expression).Type.SpecialType; } else { rightExpressionType = context.SemanticModel.GetTypeInfo(binaryExpression.Left).Type.SpecialType; } } else if (expression.Right is ExpressionSyntax expressionExpression) { rightExpressionType = context.SemanticModel.GetTypeInfo(expressionExpression).Type.SpecialType; } if (rightExpressionType is SpecialType.System_Object or SpecialType.None) { return; } if (!IsValid(rightExpressionType, sqlType.Name.Identifier.ValueText)) { var diagnostic = Diagnostic.Create(SqlTypeMatching, expression.GetLocation()); context.ReportDiagnostic(diagnostic); } } } }
private void AnalyzeClassSyntax(SyntaxNodeAnalysisContext context) { CheckStructShouldImplementIEquatable(context); }
private static void AnalyzeNode(SyntaxNodeAnalysisContext context) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Node.GetLocation())); }
/// <summary> /// Function returns members that are considered to be grouped with another member of the same interface (adjacent members). /// These members are allowed to be grouped by interface and not forced to be grouped by member name. /// Another overload (not related by interface) can be placed somewhere else. /// /// Returned ImmutableArray of interfaces for each member is used to determine whether overloads of the same interface should be grouped by name. /// If all methods of the class implement single interface, we want the overloads to be placed together within interface group. /// </summary> private static Dictionary <TMemberDeclarationSyntax, ImmutableArray <INamedTypeSymbol> > MembersGroupedByInterface(SyntaxNodeAnalysisContext c, IEnumerable <TMemberDeclarationSyntax> members) { var ret = new Dictionary <TMemberDeclarationSyntax, ImmutableArray <INamedTypeSymbol> >(); ImmutableArray <INamedTypeSymbol> currentInterfaces, previousInterfaces = ImmutableArray <INamedTypeSymbol> .Empty; TMemberDeclarationSyntax previous = null; foreach (var member in members) { currentInterfaces = FindInterfaces(c.SemanticModel, member); if (currentInterfaces.Intersect(previousInterfaces).Any()) { ret.Add(member, currentInterfaces); if (previous != null && !ret.ContainsKey(previous)) { ret.Add(previous, previousInterfaces); } } previousInterfaces = currentInterfaces; previous = member; } return(ret); }
protected abstract MemberInfo CreateMemberInfo(SyntaxNodeAnalysisContext c, TMemberDeclarationSyntax member);
private void HandleConversionOperatorDeclaration(SyntaxNodeAnalysisContext context) { var conversionOperatorDeclaration = (ConversionOperatorDeclarationSyntax)context.Node; AnalyzeParametersList(context, conversionOperatorDeclaration.ParameterList); }
private void HandleLambdaExpression(SyntaxNodeAnalysisContext context) { var lambdaExpression = (ParenthesizedLambdaExpressionSyntax)context.Node; AnalyzeParametersList(context, lambdaExpression.ParameterList); }
private void HandleMethodInvocation(SyntaxNodeAnalysisContext context) { var invocationExpression = (InvocationExpressionSyntax)context.Node; AnalyzeArgumentList(context, invocationExpression.ArgumentList); }
private void HandleMethodDeclaration(SyntaxNodeAnalysisContext context) { var methodDeclaration = (MethodDeclarationSyntax)context.Node; AnalyzeParametersList(context, methodDeclaration.ParameterList); }
private static bool TryAnalyzeInvocationCondition( SyntaxNodeAnalysisContext context, ISyntaxFacts syntaxFacts, IMethodSymbol?referenceEqualsMethod, TInvocationExpressionSyntax invocation, [NotNullWhen(true)] out TExpressionSyntax?conditionPartToCheck, out bool isEquals) { conditionPartToCheck = null; isEquals = true; if (referenceEqualsMethod == null) { return(false); } var expression = syntaxFacts.GetExpressionOfInvocationExpression(invocation); var nameNode = syntaxFacts.IsIdentifierName(expression) ? expression : syntaxFacts.IsSimpleMemberAccessExpression(expression) ? syntaxFacts.GetNameOfMemberAccessExpression(expression) : null; if (!syntaxFacts.IsIdentifierName(nameNode)) { return(false); } syntaxFacts.GetNameAndArityOfSimpleName(nameNode, out var name, out _); if (!syntaxFacts.StringComparer.Equals(name, nameof(ReferenceEquals))) { return(false); } var arguments = syntaxFacts.GetArgumentsOfInvocationExpression(invocation); if (arguments.Count != 2) { return(false); } var conditionLeft = (TExpressionSyntax)syntaxFacts.GetExpressionOfArgument(arguments[0]); var conditionRight = (TExpressionSyntax)syntaxFacts.GetExpressionOfArgument(arguments[1]); if (conditionLeft == null || conditionRight == null) { return(false); } conditionPartToCheck = GetConditionPartToCheck(syntaxFacts, conditionLeft, conditionRight); if (conditionPartToCheck == null) { return(false); } var semanticModel = context.SemanticModel; var cancellationToken = context.CancellationToken; var symbol = semanticModel.GetSymbolInfo(invocation, cancellationToken).Symbol; return(referenceEqualsMethod.Equals(symbol)); }
private void HandleIndexerDeclaration(SyntaxNodeAnalysisContext context) { var indexerDeclaration = (IndexerDeclarationSyntax)context.Node; AnalyzeBracketParametersList(context, indexerDeclaration.ParameterList); }
private void HandleAttributesList(SyntaxNodeAnalysisContext context) { var attributesList = (AttributeListSyntax)context.Node; AnalyzeAttributeList(context, attributesList); }
private void HandleDelegateDeclaration(SyntaxNodeAnalysisContext context) { var delegateDeclaration = (DelegateDeclarationSyntax)context.Node; AnalyzeParametersList(context, delegateDeclaration.ParameterList); }
private void HandleAnonymousMethod(SyntaxNodeAnalysisContext context) { var anonymousMethod = (AnonymousMethodExpressionSyntax)context.Node; AnalyzeParametersList(context, anonymousMethod.ParameterList); }
private void HandleAttribute(SyntaxNodeAnalysisContext context) { var attribute = (AttributeSyntax)context.Node; AnalyzeArgumentList(context, attribute.ArgumentList); }