private async Task HandleAsync( IProjectSubscriptionUpdate projectUpdate, IProjectCatalogSnapshot catalogSnapshot, RuleHandlerType handlerType) { AggregateCrossTargetProjectContext?currentAggregateContext = await _host !.GetCurrentAggregateProjectContextAsync(); if (currentAggregateContext == null || _currentProjectContext != currentAggregateContext) { return; } // Get the inner workspace project context to update for this change. ITargetFramework?targetFrameworkToUpdate = currentAggregateContext.GetProjectFramework(projectUpdate.ProjectConfiguration); if (targetFrameworkToUpdate == null) { return; } // Broken design time builds sometimes cause updates with no project changes and sometimes // cause updates with a project change that has no difference. // We handle the former case here, and the latter case is handled in the CommandLineItemHandler. if (projectUpdate.ProjectChanges.Count == 0) { return; } // Create an object to track dependency changes. var changesBuilder = new CrossTargetDependenciesChangesBuilder(); // Give each handler a chance to register dependency changes. foreach (Lazy <IDependenciesRuleHandler, IOrderPrecedenceMetadataView> handler in _handlers) { ImmutableHashSet <string> handlerRules = handler.Value.GetRuleNames(handlerType); // Slice project changes to include only rules the handler claims an interest in. var projectChanges = projectUpdate.ProjectChanges .Where(x => handlerRules.Contains(x.Key)) .ToImmutableDictionary(); if (projectChanges.Any(x => x.Value.Difference.AnyChanges)) { handler.Value.Handle(projectChanges, targetFrameworkToUpdate, changesBuilder); } } ImmutableDictionary <ITargetFramework, IDependenciesChanges>?changes = changesBuilder.TryBuildChanges(); if (changes != null) { // Notify subscribers of a change in dependency data DependenciesChanged?.Invoke( this, new DependencySubscriptionChangedEventArgs( currentAggregateContext.TargetFrameworks, currentAggregateContext.ActiveTargetFramework, catalogSnapshot, changes)); } // record all the rules that have occurred _treeTelemetryService.ObserveTargetFrameworkRules(targetFrameworkToUpdate, projectUpdate.ProjectChanges.Keys); }
public override void Initialize(AnalysisContext context) { // TODO: Consider making this analyzer thread-safe. //context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationStartContext => { INamedTypeSymbol eventsArgSymbol = compilationStartContext.Compilation.GetTypeByMetadataName("System.EventArgs"); // Ignore conditional methods (FxCop compat - One conditional will often call another conditional method as its only use of a parameter) INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationStartContext.Compilation); // Ignore methods with special serialization attributes (FxCop compat - All serialization methods need to take 'StreamingContext') INamedTypeSymbol onDeserializingAttribute = WellKnownTypes.OnDeserializingAttribute(compilationStartContext.Compilation); INamedTypeSymbol onDeserializedAttribute = WellKnownTypes.OnDeserializedAttribute(compilationStartContext.Compilation); INamedTypeSymbol onSerializingAttribute = WellKnownTypes.OnSerializingAttribute(compilationStartContext.Compilation); INamedTypeSymbol onSerializedAttribute = WellKnownTypes.OnSerializedAttribute(compilationStartContext.Compilation); ImmutableHashSet <INamedTypeSymbol> attributeSetForMethodsToIgnore = ImmutableHashSet.Create(conditionalAttributeSymbol, onDeserializedAttribute, onDeserializingAttribute, onSerializedAttribute, onSerializingAttribute); compilationStartContext.RegisterOperationBlockStartActionInternal(startOperationBlockContext => { // We only care about methods. if (startOperationBlockContext.OwningSymbol.Kind != SymbolKind.Method) { return; } // We only care about methods with parameters. var method = (IMethodSymbol)startOperationBlockContext.OwningSymbol; if (method.Parameters.IsEmpty) { return; } // Ignore implicitly declared methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat). if (method.IsImplicitlyDeclared || method.IsAbstract || method.IsVirtual || method.IsOverride || method.IsImplementationOfAnyInterfaceMember() || method.IsFinalizer()) { return; } // Ignore event handler methods "Handler(object, MyEventArgs)" if (eventsArgSymbol != null && method.Parameters.Length == 2 && method.Parameters[0].Type.SpecialType == SpecialType.System_Object && method.Parameters[1].Type.Inherits(eventsArgSymbol)) { return; } // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'. if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass))) { return; } // Initialize local mutable state in the start action. var analyzer = new UnusedParametersAnalyzer(method); // Register an intermediate non-end action that accesses and modifies the state. startOperationBlockContext.RegisterOperationActionInternal(analyzer.AnalyzeOperation, OperationKind.ParameterReferenceExpression); // Register an end action to report diagnostics based on the final state. startOperationBlockContext.RegisterOperationBlockEndAction(analyzer.OperationBlockEndAction); }); }); }
//TODO: Try to simplify this method - it's very hard to follow private IEnumerable <ExpressionSyntax> SearchForFindCalls(SyntaxNodeAnalysisContext context, MethodDeclarationSyntax method, IDictionary <IMethodSymbol, bool> searched, bool isRoot) { var invocations = method.DescendantNodes().OfType <InvocationExpressionSyntax>(); foreach (var invocation in invocations) { SymbolInfo symbolInfo; if (!context.TryGetSymbolInfo(invocation, out symbolInfo)) { continue; } var methodSymbol = symbolInfo.Symbol as IMethodSymbol; if (methodSymbol != null) { if (searched.ContainsKey(methodSymbol)) { if (searched[methodSymbol]) { yield return(invocation); } } else { if (FindMethodNames.Contains(methodSymbol.Name) && ContainingSymbols.Contains(methodSymbol.ContainingSymbol.ToString())) { searched.Add(methodSymbol, true); yield return(invocation); } else { var methodDeclarations = methodSymbol.DeclaringSyntaxReferences; searched.Add(methodSymbol, false); //let's assume there won't be any calls foreach (var methodDeclaration in methodDeclarations) { var theMethodSyntax = methodDeclaration.GetSyntax() as MethodDeclarationSyntax; if (theMethodSyntax != null) { var childFindCallers = SearchForFindCalls(context, theMethodSyntax, searched, false); if (childFindCallers != null && childFindCallers.Any()) { searched[methodSymbol] = true; //update the searched dictionary with new info if (isRoot) { _indirectCallers.Add(invocation, childFindCallers.First()); } yield return(invocation); break; } } } } } } } }
public static bool ShowExternalSiteLink(PVService service) { return(!servicesWithoutExternalSiteLink.Contains(service)); }
private static bool ShouldRunProviderForStateType(StateType stateTypeId, DiagnosticAnalyzer provider, DiagnosticAnalyzerDriver driver, out bool supportsSemanticInSpan, ImmutableHashSet<string> diagnosticIds = null, Func<DiagnosticAnalyzer, ImmutableArray<DiagnosticDescriptor>> getDescriptor = null) { Debug.Assert(!IsAnalyzerSuppressed(provider, driver.Project.CompilationOptions, driver)); supportsSemanticInSpan = false; if (diagnosticIds != null && getDescriptor(provider).All(d => !diagnosticIds.Contains(d.Id))) { return false; } switch (stateTypeId) { case StateType.Syntax: return provider.SupportsSyntaxDiagnosticAnalysis(driver); case StateType.Document: return provider.SupportsSemanticDiagnosticAnalysis(driver, out supportsSemanticInSpan); case StateType.Project: return provider.SupportsProjectDiagnosticAnalysis(driver); default: throw ExceptionUtilities.Unreachable; } }
private static ImmutableDictionary<SyntaxTree, ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<Diagnostic>>> GetImmutable( ImmutableHashSet<DiagnosticAnalyzer> analyzers, Dictionary<SyntaxTree, Dictionary<DiagnosticAnalyzer, ImmutableArray<Diagnostic>.Builder>> localDiagnosticsOpt) { if (localDiagnosticsOpt == null) { return ImmutableDictionary<SyntaxTree, ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<Diagnostic>>>.Empty; } var builder = ImmutableDictionary.CreateBuilder<SyntaxTree, ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<Diagnostic>>>(); var perTreeBuilder = ImmutableDictionary.CreateBuilder<DiagnosticAnalyzer, ImmutableArray<Diagnostic>>(); foreach (var diagnosticsByTree in localDiagnosticsOpt) { var tree = diagnosticsByTree.Key; foreach (var diagnosticsByAnalyzer in diagnosticsByTree.Value) { if (analyzers.Contains(diagnosticsByAnalyzer.Key)) { perTreeBuilder.Add(diagnosticsByAnalyzer.Key, diagnosticsByAnalyzer.Value.ToImmutable()); } } builder.Add(tree, perTreeBuilder.ToImmutable()); perTreeBuilder.Clear(); } return builder.ToImmutable(); }
protected bool IsTypeSupported(System.Type type) => ResourceTypes.Contains(type);
/// <summary> /// Determine whether there is any substitution of type parameters that will /// make two types identical. /// </summary> /// <param name="t1">LHS</param> /// <param name="t2">RHS</param> /// <param name="substitution"> /// Substitutions performed so far (or null for none). /// Keys are type parameters, values are types (possibly type parameters). /// Will be updated with new substitutions by the callee. /// Should be ignored when false is returned. /// </param> /// <param name="untouchables"> /// Set of type symbols that cannot be replaced by substitution. /// </param> /// <returns>True if there exists a type map such that Map(LHS) == Map(RHS).</returns> /// <remarks> /// Derived from Dev10's BSYMMGR::UnifyTypes. /// Two types will not unify if they have different custom modifiers. /// </remarks> private static bool CanUnifyHelper(TypeWithModifiers t1, TypeWithModifiers t2, ref MutableTypeMap substitution, ImmutableHashSet <TypeParameterSymbol> untouchables) { if (t1 == t2) { return(true); } else if ((object)t1.Type == null || (object)t2.Type == null) { // Can't both be null or they would have been equal return(false); } if (substitution != null) { t1 = t1.SubstituteType(substitution); t2 = t2.SubstituteType(substitution); } // If one of the types is a type parameter, then the substitution could make them equal. if (t1 == t2) { return(true); } // We can avoid a lot of redundant checks if we ensure that we only have to check // for type parameters on the LHS if (!t1.Type.IsTypeParameter() && t2.Type.IsTypeParameter()) { TypeWithModifiers tmp = t1; t1 = t2; t2 = tmp; } // If t1 is not a type parameter, then neither is t2 Debug.Assert(t1.Type.IsTypeParameter() || !t2.Type.IsTypeParameter()); switch (t1.Type.Kind) { case SymbolKind.ArrayType: { if (t2.Type.TypeKind != t1.Type.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers)) { return(false); } ArrayTypeSymbol at1 = (ArrayTypeSymbol)t1.Type; ArrayTypeSymbol at2 = (ArrayTypeSymbol)t2.Type; if (!at1.HasSameShapeAs(at2)) { return(false); } return(CanUnifyHelper(new TypeWithModifiers(at1.ElementType, at1.CustomModifiers), new TypeWithModifiers(at2.ElementType, at2.CustomModifiers), ref substitution, untouchables)); } case SymbolKind.PointerType: { if (t2.Type.TypeKind != t1.Type.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers)) { return(false); } PointerTypeSymbol pt1 = (PointerTypeSymbol)t1.Type; PointerTypeSymbol pt2 = (PointerTypeSymbol)t2.Type; return(CanUnifyHelper(new TypeWithModifiers(pt1.PointedAtType, pt1.CustomModifiers), new TypeWithModifiers(pt2.PointedAtType, pt2.CustomModifiers), ref substitution, untouchables)); } case SymbolKind.NamedType: case SymbolKind.ErrorType: { if (t2.Type.TypeKind != t1.Type.TypeKind || !t2.CustomModifiers.SequenceEqual(t1.CustomModifiers)) { return(false); } NamedTypeSymbol nt1 = (NamedTypeSymbol)t1.Type; NamedTypeSymbol nt2 = (NamedTypeSymbol)t2.Type; if (nt1.IsTupleType) { if (!nt2.IsTupleType) { return(false); } return(CanUnifyHelper(new TypeWithModifiers(nt1.TupleUnderlyingType), new TypeWithModifiers(nt2.TupleUnderlyingType), ref substitution, untouchables)); } if (!nt1.IsGenericType) { return(!nt2.IsGenericType && nt1 == nt2); } else if (!nt2.IsGenericType) { return(false); } int arity = nt1.Arity; if (nt2.Arity != arity || nt2.OriginalDefinition != nt1.OriginalDefinition) { return(false); } var nt1Arguments = nt1.TypeArgumentsNoUseSiteDiagnostics; var nt2Arguments = nt2.TypeArgumentsNoUseSiteDiagnostics; var nt1HasModifiers = nt1.HasTypeArgumentsCustomModifiers; var nt2HasModifiers = nt2.HasTypeArgumentsCustomModifiers; for (int i = 0; i < arity; i++) { if (!CanUnifyHelper(new TypeWithModifiers(nt1Arguments[i], nt1HasModifiers ? nt1.GetTypeArgumentCustomModifiers(i) : default(ImmutableArray <CustomModifier>)), new TypeWithModifiers(nt2Arguments[i], nt2HasModifiers ? nt2.GetTypeArgumentCustomModifiers(i) : default(ImmutableArray <CustomModifier>)), ref substitution, untouchables)) { return(false); } } // Note: Dev10 folds this into the loop since GetTypeArgsAll includes type args for containing types // TODO: Calling CanUnifyHelper for the containing type is an overkill, we simply need to go through type arguments for all containers. return((object)nt1.ContainingType == null || CanUnifyHelper(new TypeWithModifiers(nt1.ContainingType), new TypeWithModifiers(nt2.ContainingType), ref substitution, untouchables)); } case SymbolKind.TypeParameter: { // These substitutions are not allowed in C# if (t2.Type.TypeKind == TypeKind.Pointer || t2.Type.SpecialType == SpecialType.System_Void) { return(false); } TypeParameterSymbol tp1 = (TypeParameterSymbol)t1.Type; // Perform the "occurs check" - i.e. ensure that t2 doesn't contain t1 to avoid recursive types // Note: t2 can't be the same type param - we would have caught that with ReferenceEquals above if (Contains(t2.Type, tp1)) { return(false); } // @MattWindsor91 (Concept-C# 2017) // Quickfix to make sure that, when there are two TPs // to be unified, and both are associated, we //var isAssocFlowingInwards = // t2.Type.IsTypeParameter() // && ((TypeParameterSymbol)t2.Type).IsAssociatedType // && tp1.IsAssociatedType; if (!untouchables.Contains(tp1)) // && !isAssocFlowingInwards) { if (t1.CustomModifiers.IsDefaultOrEmpty) { AddSubstitution(ref substitution, tp1, t2); return(true); } if (t1.CustomModifiers.SequenceEqual(t2.CustomModifiers)) { AddSubstitution(ref substitution, tp1, new TypeWithModifiers(t2.Type)); return(true); } if (t1.CustomModifiers.Length < t2.CustomModifiers.Length && t1.CustomModifiers.SequenceEqual(t2.CustomModifiers.Take(t1.CustomModifiers.Length))) { AddSubstitution(ref substitution, tp1, new TypeWithModifiers(t2.Type, ImmutableArray.Create(t2.CustomModifiers, t1.CustomModifiers.Length, t2.CustomModifiers.Length - t1.CustomModifiers.Length))); return(true); } } if (t2.Type.IsTypeParameter()) { var tp2 = (TypeParameterSymbol)t2.Type; if (!untouchables.Contains(tp2)) { if (t2.CustomModifiers.IsDefaultOrEmpty) { AddSubstitution(ref substitution, tp2, t1); return(true); } if (t2.CustomModifiers.Length < t1.CustomModifiers.Length && t2.CustomModifiers.SequenceEqual(t1.CustomModifiers.Take(t2.CustomModifiers.Length))) { AddSubstitution(ref substitution, tp2, new TypeWithModifiers(t1.Type, ImmutableArray.Create(t1.CustomModifiers, t2.CustomModifiers.Length, t1.CustomModifiers.Length - t2.CustomModifiers.Length))); return(true); } } } return(false); } default: { return(t1 == t2); } } }
private bool SatisfiesRole(ImmutableHashSet<string> memberRoles) { if (string.IsNullOrEmpty(Settings.UseRole)) return true; return memberRoles.Contains(Settings.UseRole); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { var diagnostic = context.Diagnostics.FirstOrDefault(d => _fixableSet.Contains(d.Id)); if (diagnostic == null) { return; } string originalName = diagnostic.Properties[NameAnalyzer.NameProperty]; string desiredNameStr = diagnostic.Properties[NameAnalyzer.DesiredNameProperty]; NameType desiredName; if (!Enum.TryParse(desiredNameStr, out desiredName)) { return; } var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken); var token = root.FindToken(diagnostic.Location.SourceSpan.Start); if (token.Text != originalName) { return; } string docName = context.Document.Name; if (docName.Length - 3 == originalName.Length && docName.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) && context.Document.Name.StartsWith(originalName, StringComparison.OrdinalIgnoreCase)) { // So this is an entity like "FooBarBiz" in a file named "FooBarBiz.cs". // We can continue to warn on these, but registering a *fix* for them would // be inappropriate, since while the Roslyn API allows us to rename items like, // these, we cannot change the file name. return; } Func <string, string> renamer = null; switch (desiredName) { case NameType.UnderScoreCamelCased: renamer = RenameUnderscore; break; case NameType.CamelCased: renamer = RenameCamelCase; break; case NameType.PascalCased: renamer = RenamePascal; break; case NameType.IPascalCased: renamer = RenameInterface; break; case NameType.TPascalCased: renamer = RenameTypeParam; break; default: Debug.Assert(!Enum.IsDefined(typeof(NameType), desiredName)); break; } context.RegisterCodeFix(CodeAction.Create(PrivateTitle, c => RenameAsync(context.Document, token.Parent, originalName, renamer, c), diagnostic.Id), diagnostic); }
private static async Task<bool> ShouldRunAnalyzerForStateTypeAsync(DiagnosticAnalyzerDriver driver, DiagnosticAnalyzer analyzer, StateType stateTypeId, ImmutableHashSet<string> diagnosticIds = null, Func<DiagnosticAnalyzer, ImmutableArray<DiagnosticDescriptor>> getDescriptors = null) { Debug.Assert(!driver.IsAnalyzerSuppressed(analyzer)); if (diagnosticIds != null && getDescriptors(analyzer).All(d => !diagnosticIds.Contains(d.Id))) { return false; } switch (stateTypeId) { case StateType.Syntax: return await analyzer.SupportsSyntaxDiagnosticAnalysisAsync(driver).ConfigureAwait(false); case StateType.Document: return await analyzer.SupportsSemanticDiagnosticAnalysisAsync(driver).ConfigureAwait(false); case StateType.Project: return await analyzer.SupportsProjectDiagnosticAnalysisAsync(driver).ConfigureAwait(false); default: throw ExceptionUtilities.Unreachable; } }
private static bool IsFieldRelevant(IFieldSymbol fieldSymbol, ImmutableHashSet<IFieldSymbol> fieldsOfClass) { return fieldSymbol != null && !fieldSymbol.IsConst && !fieldSymbol.IsReadOnly && fieldsOfClass.Contains(fieldSymbol); }
private static ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<Diagnostic>> GetImmutable( ImmutableHashSet<DiagnosticAnalyzer> analyzers, Dictionary<DiagnosticAnalyzer, ImmutableArray<Diagnostic>.Builder> nonLocalDiagnosticsOpt) { if (nonLocalDiagnosticsOpt == null) { return ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<Diagnostic>>.Empty; } var builder = ImmutableDictionary.CreateBuilder<DiagnosticAnalyzer, ImmutableArray<Diagnostic>>(); foreach (var diagnosticsByAnalyzer in nonLocalDiagnosticsOpt) { if (analyzers.Contains(diagnosticsByAnalyzer.Key)) { builder.Add(diagnosticsByAnalyzer.Key, diagnosticsByAnalyzer.Value.ToImmutable()); } } return builder.ToImmutable(); }
/// <summary> /// Only the nodes that are in the <see cref="includeNodes"/> set. /// </summary> public MetricsGossip Filter(ImmutableHashSet <Address> includeNodes) { return(Copy(Nodes.Where(x => includeNodes.Contains(x.Address)).ToImmutableHashSet())); }
public async Task <LSP.CompletionList?> HandleRequestAsync(LSP.CompletionParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document == null) { return(null); } // C# and VB share the same LSP language server, and thus share the same default trigger characters. // We need to ensure the trigger character is valid in the document's language. For example, the '{' // character, while a trigger character in VB, is not a trigger character in C#. if (request.Context != null && request.Context.TriggerKind == LSP.CompletionTriggerKind.TriggerCharacter && !char.TryParse(request.Context.TriggerCharacter, out var triggerCharacter) && !char.IsLetterOrDigit(triggerCharacter) && !IsValidTriggerCharacterForDocument(document, triggerCharacter)) { return(null); } var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false); var completionOptions = await GetCompletionOptionsAsync(document, cancellationToken).ConfigureAwait(false); var completionService = document.Project.LanguageServices.GetRequiredService <CompletionService>(); // TO-DO: More LSP.CompletionTriggerKind mappings are required to properly map to Roslyn CompletionTriggerKinds. // https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1178726 var completionTrigger = await ProtocolConversions.LSPToRoslynCompletionTriggerAsync(request.Context, document, position, cancellationToken).ConfigureAwait(false); var list = await completionService.GetCompletionsAsync(document, position, completionTrigger, options : completionOptions, cancellationToken : cancellationToken).ConfigureAwait(false); if (list == null || list.Items.IsEmpty || cancellationToken.IsCancellationRequested) { return(null); } var lspVSClientCapability = context.ClientCapabilities.HasVisualStudioLspCapability() == true; var snippetsSupported = context.ClientCapabilities.TextDocument?.Completion?.CompletionItem?.SnippetSupport ?? false; var commitCharactersRuleCache = new Dictionary <ImmutableArray <CharacterSetModificationRule>, string[]>(CommitCharacterArrayComparer.Instance); // Cache the completion list so we can avoid recomputation in the resolve handler var resultId = _completionListCache.UpdateCache(request.TextDocument, list); // Feature flag to enable the return of TextEdits instead of InsertTexts (will increase payload size). // Flag is defined in VisualStudio\Core\Def\PackageRegistration.pkgdef. // We also check against the CompletionOption for test purposes only. Contract.ThrowIfNull(context.Solution); var featureFlagService = context.Solution.Workspace.Services.GetRequiredService <IExperimentationService>(); var returnTextEdits = featureFlagService.IsExperimentEnabled(WellKnownExperimentNames.LSPCompletion) || completionOptions.GetOption(CompletionOptions.ForceRoslynLSPCompletionExperiment, document.Project.Language); SourceText?documentText = null; TextSpan? defaultSpan = null; LSP.Range?defaultRange = null; if (returnTextEdits) { // We want to compute the document's text just once. documentText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); // We use the first item in the completion list as our comparison point for span // and range for optimization when generating the TextEdits later on. var completionChange = await completionService.GetChangeAsync( document, list.Items.First(), cancellationToken : cancellationToken).ConfigureAwait(false); // If possible, we want to compute the item's span and range just once. // Individual items can override this range later. defaultSpan = completionChange.TextChange.Span; defaultRange = ProtocolConversions.TextSpanToRange(defaultSpan.Value, documentText); } var supportsCompletionListData = context.ClientCapabilities.HasCompletionListDataCapability(); var completionResolveData = new CompletionResolveData() { ResultId = resultId, }; var stringBuilder = new StringBuilder(); using var _ = ArrayBuilder <LSP.CompletionItem> .GetInstance(out var lspCompletionItems); foreach (var item in list.Items) { var completionItemResolveData = supportsCompletionListData ? null : completionResolveData; var lspCompletionItem = await CreateLSPCompletionItemAsync( request, document, item, completionItemResolveData, lspVSClientCapability, completionTrigger, commitCharactersRuleCache, completionService, context.ClientName, returnTextEdits, snippetsSupported, stringBuilder, documentText, defaultSpan, defaultRange, cancellationToken).ConfigureAwait(false); lspCompletionItems.Add(lspCompletionItem); } var completionList = new LSP.VSCompletionList { Items = lspCompletionItems.ToArray(), SuggestionMode = list.SuggestionModeItem != null, }; if (supportsCompletionListData) { completionList.Data = completionResolveData; } if (context.ClientCapabilities.HasCompletionListCommitCharactersCapability()) { PromoteCommonCommitCharactersOntoList(completionList); } var optimizedCompletionList = new LSP.OptimizedVSCompletionList(completionList); return(optimizedCompletionList); // Local functions bool IsValidTriggerCharacterForDocument(Document document, char triggerCharacter) { if (document.Project.Language == LanguageNames.CSharp) { return(_csharpTriggerCharacters.Contains(triggerCharacter)); } else if (document.Project.Language == LanguageNames.VisualBasic) { return(_vbTriggerCharacters.Contains(triggerCharacter)); } // Typescript still calls into this for completion. // Since we don't know what their trigger characters are, just return true. return(true); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics on generated code. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationStartAnalysisContext) => { if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemSecurityAuthenticationSslProtocols, out INamedTypeSymbol sslProtocolsSymbol)) { return; } compilationStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IFieldReferenceOperation fieldReferenceOperation = (IFieldReferenceOperation)operationAnalysisContext.Operation; if (IsReferencingSslProtocols( fieldReferenceOperation, out bool isDeprecatedProtocol, out bool isHardcodedOkayProtocol)) { if (isDeprecatedProtocol) { operationAnalysisContext.ReportDiagnostic( fieldReferenceOperation.CreateDiagnostic( DeprecatedRule, fieldReferenceOperation.Field.Name)); } else if (isHardcodedOkayProtocol) { operationAnalysisContext.ReportDiagnostic( fieldReferenceOperation.CreateDiagnostic( HardcodedRule, fieldReferenceOperation.Field.Name)); } } }, OperationKind.FieldReference); compilationStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IOperation valueOperation; switch (operationAnalysisContext.Operation) { case IAssignmentOperation assignmentOperation: // Make sure this is an assignment operation for a SslProtocols value. if (!sslProtocolsSymbol.Equals(assignmentOperation.Target.Type)) { return; } valueOperation = assignmentOperation.Value; break; case IArgumentOperation argumentOperation: if (!sslProtocolsSymbol.Equals(argumentOperation.Type)) { return; } valueOperation = argumentOperation.Value; break; case IReturnOperation returnOperation: if (returnOperation.ReturnedValue == null || !sslProtocolsSymbol.Equals(returnOperation.ReturnedValue.Type)) { return; } valueOperation = returnOperation.ReturnedValue; break; case IVariableInitializerOperation variableInitializerOperation: if (variableInitializerOperation.Value != null && !sslProtocolsSymbol.Equals(variableInitializerOperation.Value.Type)) { return; } valueOperation = variableInitializerOperation.Value; break; default: Debug.Fail("Unhandled IOperation " + operationAnalysisContext.Operation.Kind); return; } // Find the topmost operation with a bad bit set, unless we find an operation that would've been // flagged by the FieldReference callback above. IOperation foundDeprecatedOperation = null; bool foundDeprecatedReference = false; IOperation foundHardcodedOperation = null; bool foundHardcodedReference = false; foreach (IOperation childOperation in valueOperation.DescendantsAndSelf()) { if (childOperation is IFieldReferenceOperation fieldReferenceOperation && IsReferencingSslProtocols( fieldReferenceOperation, out var isDeprecatedProtocol, out var isHardcodedOkayProtocol)) { if (isDeprecatedProtocol) { foundDeprecatedReference = true; } else if (isHardcodedOkayProtocol) { foundHardcodedReference = true; } if (foundDeprecatedReference && foundHardcodedReference) { return; } } if (childOperation.ConstantValue.HasValue && childOperation.ConstantValue.Value is int integerValue) { if (foundDeprecatedOperation == null && // Only want the first. (integerValue & UnsafeBits) != 0) { foundDeprecatedOperation = childOperation; } if (foundHardcodedOperation == null && // Only want the first. (integerValue & HardcodedBits) != 0) { foundHardcodedOperation = childOperation; } } } if (foundDeprecatedOperation != null && !foundDeprecatedReference) { operationAnalysisContext.ReportDiagnostic( foundDeprecatedOperation.CreateDiagnostic( DeprecatedRule, foundDeprecatedOperation.ConstantValue)); } if (foundHardcodedOperation != null && !foundHardcodedReference) { operationAnalysisContext.ReportDiagnostic( foundHardcodedOperation.CreateDiagnostic( HardcodedRule, foundHardcodedOperation.ConstantValue)); } }, OperationKind.SimpleAssignment, OperationKind.CompoundAssignment, OperationKind.Argument, OperationKind.Return, OperationKind.VariableInitializer); return; // Local function(s). bool IsReferencingSslProtocols( IFieldReferenceOperation fieldReferenceOperation, out bool isDeprecatedProtocol, out bool isHardcodedOkayProtocol) { if (sslProtocolsSymbol.Equals(fieldReferenceOperation.Field.ContainingType)) { if (HardcodedSslProtocolsMetadataNames.Contains(fieldReferenceOperation.Field.Name)) { isHardcodedOkayProtocol = true; isDeprecatedProtocol = false; } else if (fieldReferenceOperation.Field.Name == "None") { isHardcodedOkayProtocol = false; isDeprecatedProtocol = false; } else { isDeprecatedProtocol = true; isHardcodedOkayProtocol = false; } return(true); } else { isHardcodedOkayProtocol = false; isDeprecatedProtocol = false; return(false); } } }); }
private static bool IsStringCreatingMethod(IMethodSymbol method) { return(method.ContainingType.SpecialType == SpecialType.System_String && s_stringMethodNames.Contains(method.Name)); }
public override void Initialize(AnalysisContext context) { // TODO: Consider making this analyzer thread-safe. //context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationStartContext => { INamedTypeSymbol eventsArgSymbol = compilationStartContext.Compilation.GetTypeByMetadataName("System.EventArgs"); // Ignore conditional methods (FxCop compat - One conditional will often call another conditional method as its only use of a parameter) INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationStartContext.Compilation); // Ignore methods with special serialization attributes (FxCop compat - All serialization methods need to take 'StreamingContext') INamedTypeSymbol onDeserializingAttribute = WellKnownTypes.OnDeserializingAttribute(compilationStartContext.Compilation); INamedTypeSymbol onDeserializedAttribute = WellKnownTypes.OnDeserializedAttribute(compilationStartContext.Compilation); INamedTypeSymbol onSerializingAttribute = WellKnownTypes.OnSerializingAttribute(compilationStartContext.Compilation); INamedTypeSymbol onSerializedAttribute = WellKnownTypes.OnSerializedAttribute(compilationStartContext.Compilation); INamedTypeSymbol obsoleteAttribute = WellKnownTypes.ObsoleteAttribute(compilationStartContext.Compilation); ImmutableHashSet <INamedTypeSymbol> attributeSetForMethodsToIgnore = ImmutableHashSet.Create( conditionalAttributeSymbol, onDeserializedAttribute, onDeserializingAttribute, onSerializedAttribute, onSerializingAttribute, obsoleteAttribute); ImmutableHashSet <INamedTypeSymbol> exceptionsToSkip = ImmutableHashSet.Create( WellKnownTypes.NotImplementedException(compilationStartContext.Compilation), WellKnownTypes.NotSupportedException(compilationStartContext.Compilation)); UnusedParameterDictionary unusedMethodParameters = new ConcurrentDictionary <IMethodSymbol, ISet <IParameterSymbol> >(); ISet <IMethodSymbol> methodsUsedAsDelegates = new HashSet <IMethodSymbol>(); // Create a list of functions to exclude from analysis. We assume that any function that is used in an IMethodBindingExpression // cannot have its signature changed, and add it to the list of methods to be excluded from analysis. compilationStartContext.RegisterOperationAction(operationContext => { var methodBinding = (IMethodReferenceOperation)operationContext.Operation; methodsUsedAsDelegates.Add(methodBinding.Method.OriginalDefinition); }, OperationKind.MethodReference); compilationStartContext.RegisterOperationBlockStartAction(startOperationBlockContext => { // We only care about methods. if (startOperationBlockContext.OwningSymbol.Kind != SymbolKind.Method) { return; } // We only care about methods with parameters. var method = (IMethodSymbol)startOperationBlockContext.OwningSymbol; if (method.Parameters.IsEmpty) { return; } // Ignore implicitly declared methods, extern methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat). if (method.IsImplicitlyDeclared || method.IsExtern || method.IsAbstract || method.IsVirtual || method.IsOverride || method.IsImplementationOfAnyInterfaceMember() || method.IsFinalizer()) { return; } // Ignore property accessors. if (method.IsPropertyAccessor()) { return; } // Ignore event handler methods "Handler(object, MyEventArgs)" if (eventsArgSymbol != null && method.Parameters.Length == 2 && method.Parameters[0].Type.SpecialType == SpecialType.System_Object && method.Parameters[1].Type.Inherits(eventsArgSymbol)) { return; } // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'. if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass))) { return; } // Ignore methods that were used as delegates if (methodsUsedAsDelegates.Contains(method)) { return; } // Initialize local mutable state in the start action. var analyzer = new UnusedParametersAnalyzer(method, unusedMethodParameters, exceptionsToSkip); // Register an intermediate non-end action that accesses and modifies the state. startOperationBlockContext.RegisterOperationAction(analyzer.AnalyzeOperation, OperationKind.ParameterReference); // Register an end action to add unused parameters to the unusedMethodParameters dictionary startOperationBlockContext.RegisterOperationBlockEndAction(analyzer.OperationBlockEndAction); }); // Register a compilation end action to filter all methods used as delegates and report any diagnostics compilationStartContext.RegisterCompilationEndAction(compilationAnalysisContext => { // Report diagnostics for unused parameters. var unusedParameters = unusedMethodParameters.Where(kvp => !methodsUsedAsDelegates.Contains(kvp.Key)).SelectMany(kvp => kvp.Value); foreach (var parameter in unusedParameters) { var diagnostic = Diagnostic.Create(Rule, parameter.Locations[0], parameter.Name, parameter.ContainingSymbol.Name); compilationAnalysisContext.ReportDiagnostic(diagnostic); } }); }); }
protected override void AnalyzeAssertInvocation(OperationAnalysisContext context, IInvocationOperation assertOperation) { if (!AssertHelper.TryGetActualAndConstraintOperations(assertOperation, out var actualOperation, out var constraintExpression)) { return; } if (actualOperation == null) { return; } var actualType = AssertHelper.GetUnwrappedActualType(actualOperation); if (actualType == null) { return; } foreach (var constraintPartExpression in constraintExpression.ConstraintParts) { if (constraintPartExpression.HasIncompatiblePrefixes() || HasCustomComparer(constraintPartExpression) || constraintPartExpression.HasUnknownExpressions()) { continue; } var constraintMethod = constraintPartExpression.GetConstraintMethod(); if (constraintMethod == null) { continue; } if (!SupportedConstraints.Contains(constraintMethod.Name)) { continue; } var expectedOperation = constraintPartExpression.GetExpectedArgument(); if (expectedOperation == null) { continue; } var expectedType = expectedOperation.Type; if (expectedType == null) { continue; } if (actualType.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { actualType = ((INamedTypeSymbol)actualType).TypeArguments[0]; } if (expectedType.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { expectedType = ((INamedTypeSymbol)expectedType).TypeArguments[0]; } if (actualType.SpecialType == SpecialType.System_Object || expectedType.SpecialType == SpecialType.System_Object) { // An instance of object might not implement IComparable resulting in runtime errors. context.ReportDiagnostic(Diagnostic.Create( comparableOnObjectDescriptor, expectedOperation.Syntax.GetLocation(), constraintMethod.Name)); } else if (!CanCompare(actualType, expectedType, context.Compilation)) { context.ReportDiagnostic(Diagnostic.Create( comparableTypesDescriptor, expectedOperation.Syntax.GetLocation(), constraintMethod.Name)); } } }
private static bool ShouldRunAnalyzerForStateType(DiagnosticAnalyzer analyzer, StateType stateTypeId, ImmutableHashSet<string> diagnosticIds = null, Func<DiagnosticAnalyzer, ImmutableArray<DiagnosticDescriptor>> getDescriptors = null) { if (diagnosticIds != null && getDescriptors(analyzer).All(d => !diagnosticIds.Contains(d.Id))) { return false; } switch (stateTypeId) { case StateType.Syntax: return analyzer.SupportsSyntaxDiagnosticAnalysis(); case StateType.Document: return analyzer.SupportsSemanticDiagnosticAnalysis(); case StateType.Project: return analyzer.SupportsProjectDiagnosticAnalysis(); default: throw ExceptionUtilities.Unreachable; } }
public virtual bool GetBoolValue() { string s = GetStringValue(); return(!string.IsNullOrEmpty(s) && !FalseStrings.Contains(s)); }
private static void AddNonLocalDiagnostics( ImmutableDictionary<DiagnosticAnalyzer, ImmutableArray<Diagnostic>> nonLocalDiagnostics, ImmutableHashSet<DiagnosticAnalyzer> excludedAnalyzers, ImmutableArray<Diagnostic>.Builder builder) { foreach (var diagnosticsByAnalyzer in nonLocalDiagnostics) { if (excludedAnalyzers.Contains(diagnosticsByAnalyzer.Key)) { continue; } builder.AddRange(diagnosticsByAnalyzer.Value); } }
/// <summary> /// Fast file exists for AssemblyFoldersFromConfig. /// </summary> internal bool FileExists(string path) { // Make sure that the file is in one of the directories under the assembly folders ex location // if it is not then we can not use this fast file existence check return(_useOriginalFileExists ? _fileExists(path) : _filesInDirectories.Contains(path)); }
private static void AnalyzeMethod( IMethodSymbol method, OperationBlockStartAnalysisContext startOperationBlockContext, UnusedParameterDictionary unusedMethodParameters, INamedTypeSymbol eventsArgSymbol, ISet <IMethodSymbol> methodsUsedAsDelegates, ImmutableHashSet <INamedTypeSymbol> attributeSetForMethodsToIgnore) { // We only care about methods with parameters. if (method.Parameters.IsEmpty) { return; } // Ignore implicitly declared methods, extern methods, abstract methods, virtual methods, interface implementations and finalizers (FxCop compat). if (method.IsImplicitlyDeclared || method.IsExtern || method.IsAbstract || method.IsVirtual || method.IsOverride || method.IsImplementationOfAnyInterfaceMember() || method.IsFinalizer()) { return; } // Ignore property accessors. if (method.IsPropertyAccessor()) { return; } // Ignore event handler methods "Handler(object, MyEventArgs)" if (eventsArgSymbol != null && method.Parameters.Length == 2 && method.Parameters[0].Type.SpecialType == SpecialType.System_Object && method.Parameters[1].Type.Inherits(eventsArgSymbol)) { return; } // Ignore methods with any attributes in 'attributeSetForMethodsToIgnore'. if (method.GetAttributes().Any(a => a.AttributeClass != null && attributeSetForMethodsToIgnore.Contains(a.AttributeClass))) { return; } // Ignore methods that were used as delegates if (methodsUsedAsDelegates.Contains(method)) { return; } // Initialize local mutable state in the start action. var analyzer = new UnusedParametersAnalyzer(method, unusedMethodParameters); // Register an intermediate non-end action that accesses and modifies the state. startOperationBlockContext.RegisterOperationAction(analyzer.AnalyzeParameterReference, OperationKind.ParameterReference); // Register an end action to add unused parameters to the unusedMethodParameters dictionary startOperationBlockContext.RegisterOperationBlockEndAction(analyzer.OperationBlockEndAction); }
public override async Task<ImmutableArray<DiagnosticData>> GetDiagnosticsForIdsAsync(Solution solution, ProjectId projectId = null, DocumentId documentId = null, ImmutableHashSet<string> diagnosticIds = null, CancellationToken cancellationToken = default(CancellationToken)) { var diagnostics = await GetDiagnosticsAsync(solution, projectId, documentId, cancellationToken).ConfigureAwait(false); return diagnostics.Where(d => diagnosticIds.Contains(d.Id)).ToImmutableArrayOrEmpty(); }
private void AnalyzeInvocation(SyntaxNodeAnalysisContext context) { var invocation = context.Node as TInvocationExpressionSyntax; 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(RegisterSymbolActionName, method, _analysisContext, _compilationStartAnalysisContext); bool isRegisterSyntaxNodeAction = IsRegisterAction(RegisterSyntaxNodeActionName, method, _analysisContext, _compilationStartAnalysisContext, _codeBlockStartAnalysisContext); bool isRegisterCodeBlockStartAction = IsRegisterAction(RegisterCodeBlockStartActionName, method, _analysisContext, _compilationStartAnalysisContext); bool isRegisterOperationAction = IsRegisterAction(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))) { if (argumentCount == 1) { DiagnosticDescriptor rule; if (isRegisterSymbolAction) { rule = MissingSymbolKindArgumentRule; } else if (isRegisterOperationAction) { rule = MissingOperationKindArgumentRule; } else { rule = MissingSyntaxKindArgumentRule; } SyntaxNode invocationExpression = GetInvocationExpression(invocation); Diagnostic diagnostic = Diagnostic.Create(rule, invocationExpression.GetLocation()); context.ReportDiagnostic(diagnostic); } else if (isRegisterSymbolAction) { foreach (SyntaxNode argument in arguments.Skip(1)) { symbol = semanticModel.GetSymbolInfo(argument, context.CancellationToken).Symbol; if (symbol != null && symbol.Kind == SymbolKind.Field && _symbolKind.Equals(symbol.ContainingType) && !s_supportedSymbolKinds.Contains(symbol.Name)) { Diagnostic diagnostic = Diagnostic.Create(UnsupportedSymbolKindArgumentRule, argument.GetLocation(), symbol.Name); context.ReportDiagnostic(diagnostic); } } } } } } } } if (method.TypeParameters.Length > 0 && (isRegisterSyntaxNodeAction || isRegisterCodeBlockStartAction)) { ITypeSymbol typeArgument = null; if (method.TypeParameters.Length == 1) { if (method.TypeParameters[0].Name == TLanguageKindEnumName) { typeArgument = method.TypeArguments[0]; } } else { ITypeParameterSymbol typeParam = method.TypeParameters.SingleOrDefault(t => t.Name == 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, TLanguageKindEnumName, method.Name); context.ReportDiagnostic(diagnostic); } } }
static bool CanReplaceIdentifierWithPredefinedType(string identifier) => s_predefinedTypeMetadataNames.Contains(identifier);
private bool IsMethodWithSpecialAttribute(IMethodSymbol methodSymbol) => methodSymbol.GetAttributes().Any(a => _attributeSetForMethodsToIgnore.Contains(a.AttributeClass));
public override void Initialize(AnalysisContext analysisContext) { analysisContext.EnableConcurrentExecution(); analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); analysisContext.RegisterCompilationStartAction( compilationStartAnalysisContext => { Compilation compilation = compilationStartAnalysisContext.Compilation; ImmutableHashSet <INamedTypeSymbol> nativeResourceTypes = ImmutableHashSet.Create( WellKnownTypes.IntPtr(compilation), WellKnownTypes.UIntPtr(compilation), WellKnownTypes.HandleRef(compilation) ); var disposableType = WellKnownTypes.IDisposable(compilation); compilationStartAnalysisContext.RegisterOperationAction( operationAnalysisContext => { var assignment = (IAssignmentOperation)operationAnalysisContext.Operation; IOperation target = assignment.Target; if (target == null) { // This can happen if the left-hand side is an undefined symbol. return; } if (target.Kind != OperationKind.FieldReference) { return; } var fieldReference = (IFieldReferenceOperation)target; var field = fieldReference.Member as IFieldSymbol; if (field == null || field.Kind != SymbolKind.Field || field.IsStatic) { return; } if (!nativeResourceTypes.Contains(field.Type)) { return; } INamedTypeSymbol containingType = field.ContainingType; if (containingType == null || containingType.IsValueType) { return; } if (!containingType.AllInterfaces.Contains(disposableType)) { return; } if (containingType.HasFinalizer()) { return; } if (assignment.Value == null || assignment.Value.Kind != OperationKind.Invocation) { return; } var invocation = (IInvocationOperation)assignment.Value; if (invocation == null) { return; } IMethodSymbol method = invocation.TargetMethod; // TODO: What about COM? if (method.GetDllImportData() == null) { return; } operationAnalysisContext.ReportDiagnostic(containingType.CreateDiagnostic(Rule)); }, OperationKind.SimpleAssignment); }); }
private bool UpdateDataMap(IDiagnosticUpdateSource source, DiagnosticsUpdatedArgs args) { // we expect source who uses this ability to have small number of diagnostics. lock (_gate) { Debug.Assert(_updateSources.Contains(source)); // The diagnostic service itself caches all diagnostics produced by the IDiagnosticUpdateSource's. As // such, we want to grab all the diagnostics (regardless of push/pull setting) and cache inside // ourselves. Later, when anyone calls GetDiagnostics or GetDiagnosticBuckets we will check if their // push/pull request matches the current user setting and return these if appropriate. var diagnostics = args.GetAllDiagnosticsRegardlessOfPushPullSetting(); // check cheap early bail out if (diagnostics.Length == 0 && !_map.ContainsKey(source)) { // no new diagnostic, and we don't have update source for it. return(false); } // 2 different workspaces (ex, PreviewWorkspaces) can return same Args.Id, we need to // distinguish them. so we separate diagnostics per workspace map. var workspaceMap = _map.GetOrAdd( source, _ => new Dictionary <Workspace, Dictionary <object, Data> >() ); if (diagnostics.Length == 0 && !workspaceMap.ContainsKey(args.Workspace)) { // no new diagnostic, and we don't have workspace for it. return(false); } var diagnosticDataMap = workspaceMap.GetOrAdd( args.Workspace, _ => new Dictionary <object, Data>() ); diagnosticDataMap.Remove(args.Id); if (diagnosticDataMap.Count == 0 && diagnostics.Length == 0) { workspaceMap.Remove(args.Workspace); if (workspaceMap.Count == 0) { _map.Remove(source); } return(true); } if (diagnostics.Length > 0) { // save data only if there is a diagnostic var data = source.SupportGetDiagnostics ? new Data(args) : new Data(args, diagnostics); diagnosticDataMap.Add(args.Id, data); } return(true); } }
private static void HandleMemberList(SyntaxNodeAnalysisContext context, ImmutableArray <OrderingTrait> elementOrder, int accessibilityIndex, SyntaxList <MemberDeclarationSyntax> members, AccessLevel defaultAccessLevel) { MemberDeclarationSyntax previousMember = null; var previousSyntaxKind = SyntaxKind.None; var previousAccessLevel = AccessLevel.NotSpecified; bool previousIsConst = false; bool previousIsReadonly = false; bool previousIsStatic = false; foreach (var member in members) { var currentSyntaxKind = member.Kind(); currentSyntaxKind = currentSyntaxKind == SyntaxKind.EventFieldDeclaration ? SyntaxKind.EventDeclaration : currentSyntaxKind; // if the SyntaxKind of this member (e.g. SyntaxKind.IncompleteMember) will not // be handled, skip early. if (!MemberKinds.Contains(currentSyntaxKind)) { continue; } var modifiers = member.GetModifiers(); AccessLevel currentAccessLevel = MemberOrderHelper.GetAccessLevelForOrdering(member, modifiers); bool currentIsConst = modifiers.Any(SyntaxKind.ConstKeyword); bool currentIsReadonly = modifiers.Any(SyntaxKind.ReadOnlyKeyword); bool currentIsStatic = modifiers.Any(SyntaxKind.StaticKeyword); if (previousAccessLevel != AccessLevel.NotSpecified) { bool compareAccessLevel = true; for (int j = 0; compareAccessLevel && j < accessibilityIndex; j++) { switch (elementOrder[j]) { case OrderingTrait.Kind: if (previousSyntaxKind != currentSyntaxKind) { compareAccessLevel = false; } continue; case OrderingTrait.Constant: if (previousIsConst != currentIsConst) { compareAccessLevel = false; } continue; case OrderingTrait.Readonly: if (previousIsReadonly != currentIsReadonly) { compareAccessLevel = false; } continue; case OrderingTrait.Static: if (previousIsStatic != currentIsStatic) { compareAccessLevel = false; } continue; case OrderingTrait.Accessibility: default: continue; } } if (compareAccessLevel && currentAccessLevel > previousAccessLevel) { context.ReportDiagnostic( Diagnostic.Create( Descriptor, NamedTypeHelpers.GetNameOrIdentifierLocation(member), AccessLevelHelper.GetName(currentAccessLevel), AccessLevelHelper.GetName(previousAccessLevel))); } } previousMember = member; previousSyntaxKind = currentSyntaxKind; previousAccessLevel = currentAccessLevel; previousIsConst = currentIsConst; previousIsReadonly = currentIsReadonly; previousIsStatic = currentIsStatic; } }
public static bool Contains <TSource>(this ImmutableHashSet <TSource> source, TSource value) => source.Contains(value);
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics on generated code. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationStartAnalysisContext) => { var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartAnalysisContext.Compilation); if (!wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemNetSecurityProtocolType, out var securityProtocolTypeTypeSymbol) || !wellKnownTypeProvider.TryGetOrCreateTypeByMetadataName( WellKnownTypeNames.SystemNetServicePointManager, out var servicePointManagerTypeSymbol)) { return; } compilationStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { var fieldReferenceOperation = (IFieldReferenceOperation)operationAnalysisContext.Operation; // Make sure we're not inside an &= assignment like: // ServicePointManager.SecurityProtocol &= ~(SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11) // cuz &= is at worst, disabling protocol versions. if (IsReferencingSecurityProtocolType( fieldReferenceOperation, out var isDeprecatedProtocol, out var isHardCodedOkayProtocol) && null == fieldReferenceOperation.GetAncestor <ICompoundAssignmentOperation>( OperationKind.CompoundAssignment, IsAndEqualsServicePointManagerAssignment)) { if (isDeprecatedProtocol) { operationAnalysisContext.ReportDiagnostic( fieldReferenceOperation.CreateDiagnostic( DeprecatedRule, fieldReferenceOperation.Field.Name)); } else if (isHardCodedOkayProtocol) { operationAnalysisContext.ReportDiagnostic( fieldReferenceOperation.CreateDiagnostic( HardCodedRule, fieldReferenceOperation.Field.Name)); } } }, OperationKind.FieldReference); compilationStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { var assignmentOperation = (IAssignmentOperation)operationAnalysisContext.Operation; // Make sure this is an assignment operation for a SecurityProtocolType, and not // an assignment like: // ServicePointManager.SecurityProtocol &= ~(SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11) // cuz &= is at worst, disabling protocol versions. if (!securityProtocolTypeTypeSymbol.Equals(assignmentOperation.Target.Type) || (assignmentOperation is ICompoundAssignmentOperation compoundAssignmentOperation && IsAndEqualsServicePointManagerAssignment(compoundAssignmentOperation))) { return; } // Find the topmost operation with a bad bit set, unless we find an operation that would've been // flagged by the FieldReference callback above. IOperation foundDeprecatedOperation = null; bool foundDeprecatedReference = false; IOperation foundHardCodedOperation = null; bool foundHardCodedReference = false; foreach (IOperation childOperation in assignmentOperation.Value.DescendantsAndSelf()) { if (childOperation is IFieldReferenceOperation fieldReferenceOperation && IsReferencingSecurityProtocolType( fieldReferenceOperation, out var isDeprecatedProtocol, out var isHardCodedOkayProtocol)) { if (isDeprecatedProtocol) { foundDeprecatedReference = true; } else if (isHardCodedOkayProtocol) { foundHardCodedReference = true; } if (foundDeprecatedReference && foundHardCodedReference) { return; } } if (childOperation.ConstantValue.HasValue && childOperation.ConstantValue.Value is int integerValue) { if (foundDeprecatedOperation == null && // Only want the first. (integerValue & UnsafeBits) != 0) { foundDeprecatedOperation = childOperation; } if (foundHardCodedOperation == null && // Only want the first. (integerValue & HardCodedBits) != 0) { foundHardCodedOperation = childOperation; } } } if (foundDeprecatedOperation != null && !foundDeprecatedReference) { operationAnalysisContext.ReportDiagnostic( foundDeprecatedOperation.CreateDiagnostic( DeprecatedRule, foundDeprecatedOperation.ConstantValue)); } if (foundHardCodedOperation != null && !foundHardCodedReference) { operationAnalysisContext.ReportDiagnostic( foundHardCodedOperation.CreateDiagnostic( HardCodedRule, foundHardCodedOperation.ConstantValue)); } }, OperationKind.SimpleAssignment, OperationKind.CompoundAssignment); return; // Local function(s). bool IsReferencingSecurityProtocolType( IFieldReferenceOperation fieldReferenceOperation, out bool isDeprecatedProtocol, out bool isHardCodedOkayProtocol) { if (securityProtocolTypeTypeSymbol.Equals(fieldReferenceOperation.Field.ContainingType)) { if (HardCodedSafeProtocolMetadataNames.Contains(fieldReferenceOperation.Field.Name)) { isHardCodedOkayProtocol = true; isDeprecatedProtocol = false; } else if (fieldReferenceOperation.Field.Name == SystemDefaultName) { isHardCodedOkayProtocol = false; isDeprecatedProtocol = false; } else { isDeprecatedProtocol = true; isHardCodedOkayProtocol = false; } return(true); } else { isHardCodedOkayProtocol = false; isDeprecatedProtocol = false; return(false); } } bool IsAndEqualsServicePointManagerAssignment(ICompoundAssignmentOperation compoundAssignmentOperation) { return(compoundAssignmentOperation.OperatorKind == BinaryOperatorKind.And && compoundAssignmentOperation.Target is IPropertyReferenceOperation targetPropertyReference && targetPropertyReference.Instance == null && servicePointManagerTypeSymbol.Equals(targetPropertyReference.Property.ContainingType) && targetPropertyReference.Property.MetadataName == "SecurityProtocol"); } }); }
public bool Contains(string reason) { return(_reasons.Contains(reason)); }
/// <summary> /// Determine if the specific method is an Add method that adds to a collection. /// </summary> /// <param name="method">The method to test.</param> /// <returns>'true' if <paramref name="method"/> is believed to be the add method of a collection.</returns> /// <remarks> /// The current heuristic is that we consider a method to be an add method if its name begins with "Add" and its /// enclosing type derives from ICollection or any instantiation of ICollection<T>. /// </remarks> public static bool IsCollectionAddMethod(this IMethodSymbol method, ImmutableHashSet <INamedTypeSymbol> iCollectionTypes) => !iCollectionTypes.IsEmpty && method.Name.StartsWith("Add", StringComparison.Ordinal) && method.ContainingType.AllInterfaces.Any(i => iCollectionTypes.Contains(i.OriginalDefinition));
public void OperationBlockEndAction(OperationBlockAnalysisContext context) { // Check to see if the method just throws a NotImplementedException/NotSupportedException. If it does, // we shouldn't warn about parameters. // Note that VB method bodies with 1 action have 3 operations. // The first is the actual operation, the second is a label statement, and the third is a return // statement. The last two are implicit in these scenarios. // Filter out operation roots with no IOperation API support (OperationKind.None) var operationBlocks = context.OperationBlocks; if (operationBlocks.Any(operation => operation.IsOperationNoneRoot())) { operationBlocks = operationBlocks.Where(operation => !operation.IsOperationNoneRoot()).ToImmutableArray(); } if (operationBlocks.Length == 1 && operationBlocks[0] is IBlockOperation methodBlock) { bool IsSingleStatementBody(IBlockOperation body) { return(body.Operations.Length == 1 || (body.Operations.Length == 3 && body.Syntax.Language == LanguageNames.VisualBasic && body.Operations[1] is ILabeledOperation labeledOp && labeledOp.IsImplicit && body.Operations[2] is IReturnOperation returnOp && returnOp.IsImplicit)); } if (IsSingleStatementBody(methodBlock)) { var innerOperation = methodBlock.Operations.First(); // Because of https://github.com/dotnet/roslyn/issues/23152, there can be an expression-statement // wrapping expression-bodied throw operations. Compensate by unwrapping if necessary. if (innerOperation.Kind == OperationKind.ExpressionStatement && innerOperation is IExpressionStatementOperation exprStatement) { innerOperation = exprStatement.Operation; } if (innerOperation.Kind == OperationKind.Throw && innerOperation is IThrowOperation throwOperation && throwOperation.Exception.Kind == OperationKind.ObjectCreation && throwOperation.Exception is IObjectCreationOperation createdException) { if (_exceptionsToSkip.Contains(createdException.Type.OriginalDefinition)) { return; } } } } // Do not raise warning for unused 'this' parameter of an extension method. if (_method.IsExtensionMethod) { var thisParamter = _unusedParameters.Where(p => p.Ordinal == 0).FirstOrDefault(); _unusedParameters.Remove(thisParamter); } _finalUnusedParameters.Add(_method, _unusedParameters); }
public static bool IsAzureNextGenResource(this Resource resource) => AzureNextGenResourceTypes.Contains(resource.GetType());
private static SourceText RemoveSymbolNamesFromSourceText(SourceText sourceText, ImmutableHashSet<string> linesToRemove) { if (linesToRemove.IsEmpty) { return sourceText; } HashSet<string> lines = GetLinesFromSourceText(sourceText); var newLines = lines.Where(line => !linesToRemove.Contains(line)); IOrderedEnumerable<string> sortedLines = newLines.OrderBy(s => s, StringComparer.Ordinal); SourceText newSourceText = sourceText.Replace(new TextSpan(0, sourceText.Length), string.Join(Environment.NewLine, sortedLines)); return newSourceText; }
private bool SatisfiesRole(ImmutableHashSet <string> memberRoles) { return(string.IsNullOrEmpty(Settings.UseRole) || memberRoles.Contains(Settings.UseRole)); }
private static async Task<ImmutableArray<Diagnostic>> GetFilteredDiagnosticsAsync(Task<IEnumerable<Diagnostic>> getDiagnosticsTask, ImmutableHashSet<string> diagnosticIds) { if (getDiagnosticsTask != null) { var diagnostics = await getDiagnosticsTask.ConfigureAwait(false); if (diagnostics != null) { return diagnostics.Where(d => d != null && diagnosticIds.Contains(d.Id)).ToImmutableArray(); } } return ImmutableArray<Diagnostic>.Empty; }
public sealed override void Initialize(AnalysisContext context) { ImmutableHashSet <string> cachedDeserializationMethodNames = this.DeserializationMethodNames; Debug.Assert(!String.IsNullOrWhiteSpace(this.DeserializerTypeMetadataName)); Debug.Assert(!String.IsNullOrWhiteSpace(this.SerializationBinderPropertyMetadataName)); Debug.Assert(cachedDeserializationMethodNames != null); Debug.Assert(!cachedDeserializationMethodNames.IsEmpty); Debug.Assert(this.BinderDefinitelyNotSetDescriptor != null); Debug.Assert(this.BinderMaybeNotSetDescriptor != null); context.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics on generated code. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); // For PropertySetAnalysis dataflow analysis. PropertyMapperCollection propertyMappers = new PropertyMapperCollection( new PropertyMapper( this.SerializationBinderPropertyMetadataName, PropertySetCallbacks.FlagIfNull)); HazardousUsageEvaluatorCollection hazardousUsageEvaluators = new HazardousUsageEvaluatorCollection( cachedDeserializationMethodNames.Select( methodName => new HazardousUsageEvaluator( methodName, PropertySetCallbacks.HazardousIfAllFlaggedOrAllUnknown))); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationStartAnalysisContext) => { if (!compilationStartAnalysisContext.Compilation.TryGetOrCreateTypeByMetadataName( this.DeserializerTypeMetadataName, out INamedTypeSymbol deserializerTypeSymbol)) { return; } PooledHashSet <(IOperation Operation, ISymbol ContainingSymbol)> rootOperationsNeedingAnalysis = PooledHashSet <(IOperation, ISymbol)> .GetInstance(); compilationStartAnalysisContext.RegisterOperationBlockStartAction( (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) => { var owningSymbol = operationBlockStartAnalysisContext.OwningSymbol; // TODO: Handle case when exactly one of the below rules is configured to skip analysis. if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, BinderDefinitelyNotSetDescriptor, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken) && owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartAnalysisContext.Options, BinderMaybeNotSetDescriptor, operationBlockStartAnalysisContext.Compilation, operationBlockStartAnalysisContext.CancellationToken)) { return; } operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IObjectCreationOperation creationOperation = (IObjectCreationOperation)operationAnalysisContext.Operation; if (deserializerTypeSymbol.Equals(creationOperation.Type)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add((operationAnalysisContext.Operation.GetRoot(), operationAnalysisContext.ContainingSymbol)); } } }, OperationKind.ObjectCreation); operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation; if (Equals(invocationOperation.Instance?.Type, deserializerTypeSymbol) && cachedDeserializationMethodNames.Contains(invocationOperation.TargetMethod.Name)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add((operationAnalysisContext.Operation.GetRoot(), operationAnalysisContext.ContainingSymbol)); } } }, OperationKind.Invocation); operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IMethodReferenceOperation methodReferenceOperation = (IMethodReferenceOperation)operationAnalysisContext.Operation; if (Equals(methodReferenceOperation.Instance?.Type, deserializerTypeSymbol) && cachedDeserializationMethodNames.Contains( methodReferenceOperation.Method.MetadataName)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add((operationAnalysisContext.Operation.GetRoot(), operationAnalysisContext.ContainingSymbol)); } } }, OperationKind.MethodReference); }); compilationStartAnalysisContext.RegisterCompilationEndAction( (CompilationAnalysisContext compilationAnalysisContext) => { PooledDictionary <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; try { lock (rootOperationsNeedingAnalysis) { if (!rootOperationsNeedingAnalysis.Any()) { return; } allResults = PropertySetAnalysis.BatchGetOrComputeHazardousUsages( compilationAnalysisContext.Compilation, rootOperationsNeedingAnalysis, compilationAnalysisContext.Options, this.DeserializerTypeMetadataName, DoNotUseInsecureDeserializerWithoutBinderBase.ConstructorMapper, propertyMappers, hazardousUsageEvaluators, InterproceduralAnalysisConfiguration.Create( compilationAnalysisContext.Options, SupportedDiagnostics, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive, cancellationToken: compilationAnalysisContext.CancellationToken)); } if (allResults == null) { return; } foreach (KeyValuePair <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> kvp in allResults) { DiagnosticDescriptor descriptor; switch (kvp.Value) { case HazardousUsageEvaluationResult.Flagged: descriptor = this.BinderDefinitelyNotSetDescriptor; break; case HazardousUsageEvaluationResult.MaybeFlagged: descriptor = this.BinderMaybeNotSetDescriptor; break; default: Debug.Fail($"Unhandled result value {kvp.Value}"); continue; } compilationAnalysisContext.ReportDiagnostic( Diagnostic.Create( descriptor, kvp.Key.Location, kvp.Key.Method.ToDisplayString( SymbolDisplayFormat.MinimallyQualifiedFormat))); } } finally { rootOperationsNeedingAnalysis.Free(); allResults?.Free(); } }); }); }
/// <summary> /// Only the nodes that are in the <paramref name="includeNodes"/> set. /// </summary> public MetricsGossip Filter(ImmutableHashSet<Address> includeNodes) { return Copy(Nodes.Where(x => includeNodes.Contains(x.Address)).ToImmutableHashSet()); }
public Reachability RemoveObservers(ImmutableHashSet<UniqueAddress> nodes) { if (nodes.Count == 0) { return this; } else { var newRecords = _records.FindAll(r => !nodes.Contains(r.Observer)); if (newRecords.Count == _records.Count) { return this; } else { var newVersions = _versions.RemoveRange(nodes); return new Reachability(newRecords, newVersions); } } }