示例#1
0
        private static void AnalyzeTypeArguments(
            SyntaxNodeAnalysisContext ctx,
            AnnotationsContext annotationsContext,
            ImmutabilityContext immutabilityContext,
            SimpleNameSyntax syntax
            )
        {
            if (syntax.IsFromDocComment())
            {
                // ignore things in doccomments such as crefs
                return;
            }

            SymbolInfo info = ctx.SemanticModel.GetSymbolInfo(syntax, ctx.CancellationToken);

            // Ignore anything that cannot have type arguments/parameters
            if (!GetTypeParamsAndArgs(info.Symbol, out var typeParameters, out var typeArguments))
            {
                return;
            }

            int i             = 0;
            var paramArgPairs = typeParameters.Zip(typeArguments, (p, a) => (p, a, i++));

            foreach (var(parameter, argument, position) in paramArgPairs)
            {
                // TODO: this should eventually use information from ImmutableTypeInfo
                // however the current information about immutable type parameters
                // includes [Immutable] filling for what will instead be the upcoming
                // [OnlyIf] (e.g. it would be broken for IEnumerable<>)
                if (!annotationsContext.Objects.Immutable.IsDefined(parameter))
                {
                    continue;
                }

                if (!immutabilityContext.IsImmutable(
                        new ImmutabilityQuery(
                            ImmutableTypeKind.Total,
                            argument
                            ),
                        // If the syntax is a GenericName (has explicit type arguments) then the error should be on the argument
                        // Otherwise, it should be on the identifier itself
                        getLocation: () => syntax is GenericNameSyntax genericSyntax
                                                ? genericSyntax.TypeArgumentList.Arguments[position].GetLocation()
                                                : syntax.Identifier.GetLocation(),
                        out Diagnostic diagnostic
                        ))
                {
                    // TODO: not necessarily a good diagnostic for this use-case
                    ctx.ReportDiagnostic(diagnostic);
                }
            }
        }