示例#1
0
        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;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
示例#4
0
 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;
                }
            }
示例#6
0
        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();
        }
示例#7
0
 protected bool IsTypeSupported(System.Type type) => ResourceTypes.Contains(type);
示例#8
0
        /// <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);
 }
示例#10
0
        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);
 }
示例#13
0
        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()));
 }
示例#15
0
        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);
                    }
                }
            });
        }
示例#17
0
 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);
                    }
                });
            });
        }
示例#19
0
        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;
            }
        }
示例#21
0
        public virtual bool GetBoolValue()
        {
            string s = GetStringValue();

            return(!string.IsNullOrEmpty(s) && !FalseStrings.Contains(s));
        }
示例#22
0
        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));
 }
示例#24
0
        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);
示例#28
0
 private bool IsMethodWithSpecialAttribute(IMethodSymbol methodSymbol)
 => methodSymbol.GetAttributes().Any(a => _attributeSetForMethodsToIgnore.Contains(a.AttributeClass));
示例#29
0
        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);
            });
        }
示例#30
0
        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;
            }
        }
示例#32
0
 public static bool Contains <TSource>(this ImmutableHashSet <TSource> source, TSource value)
 => source.Contains(value);
示例#33
0
        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");
                }
            });
        }
示例#34
0
 public bool Contains(string reason)
 {
     return(_reasons.Contains(reason));
 }
示例#35
0
 /// <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&lt;T&gt;.
 /// </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);
            }
示例#37
0
 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;
        }
示例#39
0
 private bool SatisfiesRole(ImmutableHashSet <string> memberRoles)
 {
     return(string.IsNullOrEmpty(Settings.UseRole) || memberRoles.Contains(Settings.UseRole));
 }
示例#40
0
        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;
        }
示例#41
0
        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());
 }
示例#43
0
 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);
         }
     }
 }