示例#1
0
        /// <summary>
        /// Reports <see cref="Diagnostic"/> s for a single <see cref="LocalFunctionStatementSyntax"/>.
        /// </summary>
        /// <param name="diagnosticReceiver">
        /// <see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/> s.
        /// </param>
        /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
        /// <param name="localFunction">
        /// <see cref="LocalFunctionStatementSyntax"/> to report <see cref="Diagnostic"/> for.
        /// </param>
        /// <param name="cancellationToken">
        /// <see cref="CancellationToken"/> that specifies if the operation should be canceled.
        /// </param>
        public static void ReportDiagnosticsForLocalFunction(
            IDiagnosticReceiver diagnosticReceiver,
            DefaultParamCompilationData compilation,
            LocalFunctionStatementSyntax localFunction,
            CancellationToken cancellationToken = default
            )
        {
            if (localFunction is null)
            {
                return;
            }

            SemanticModel semanticModel = compilation.Compilation.GetSemanticModel(localFunction.SyntaxTree);

            if (HasDefaultParamAttribute(localFunction, semanticModel, compilation.DefaultParamAttribute !))
            {
                ISymbol?symbol = semanticModel.GetDeclaredSymbol(localFunction, cancellationToken);

                if (symbol is not IMethodSymbol s)
                {
                    return;
                }

                DefaultParamMethodAnalyzer.WithDiagnostics.ReportDiagnosticForInvalidMethodType(diagnosticReceiver, s);
            }
        }
示例#2
0
            /// <inheritdoc cref="DefaultParamDelegateAnalyzer.WithDiagnostics.Analyze(IDiagnosticReceiver, INamedTypeSymbol, DefaultParamCompilationData, CancellationToken)"/>
            public static bool Analyze(
                IDiagnosticReceiver diagnosticReceiver,
                INamedTypeSymbol symbol,
                DefaultParamCompilationData compilation,
                CancellationToken cancellationToken = default
                )
            {
                TypeParameterContainer typeParameters = TypeParameterContainer.CreateFrom(symbol, compilation, cancellationToken);

                if (!typeParameters.HasDefaultParams)
                {
                    return(false);
                }

                ImmutableArray <AttributeData> attributes = symbol.GetAttributes();

                INamedTypeSymbol[] containingTypes = symbol.GetContainingTypeSymbols().ToArray();

                bool isValid = AnalyzeAgainstProhibitedAttributes(diagnosticReceiver, symbol, compilation, attributes);

                isValid &= AnalyzeContainingTypes(diagnosticReceiver, symbol, compilation, containingTypes, cancellationToken);
                isValid &= AnalyzeAgainstPartial(diagnosticReceiver, symbol, cancellationToken);
                isValid &= AnalyzeTypeParameters(diagnosticReceiver, symbol, in typeParameters);

                if (isValid)
                {
                    string targetNamespace = GetTargetNamespace(symbol, compilation, attributes, containingTypes);

                    isValid &= AnalyzeCollidingMembers(diagnosticReceiver, symbol, in typeParameters, compilation, targetNamespace, out _, attributes, containingTypes, cancellationToken);
                }

                ShouldInheritInsteadOfCopying(diagnosticReceiver, symbol, compilation, attributes, containingTypes);

                return(isValid);
            }
            /// <summary>
            /// Fully analyzes the specified <paramref name="symbol"/>.
            /// </summary>
            /// <param name="diagnosticReceiver">
            /// <see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/> s.
            /// </param>
            /// <param name="symbol"><see cref="INamedTypeSymbol"/> to analyze.</param>
            /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
            /// <param name="cancellationToken">
            /// <see cref="CancellationToken"/> that specifies if the operation should be canceled.
            /// </param>
            /// <returns>
            /// <see langword="true"/> if the <paramref name="symbol"/> is valid, otherwise <see langword="false"/>.
            /// </returns>
            public static bool Analyze(
                IDiagnosticReceiver diagnosticReceiver,
                INamedTypeSymbol symbol,
                DefaultParamCompilationData compilation,
                CancellationToken cancellationToken = default
                )
            {
                TypeParameterContainer typeParameters = TypeParameterContainer.CreateFrom(symbol, compilation, cancellationToken);

                if (!typeParameters.HasDefaultParams)
                {
                    return(false);
                }

                bool isValid = AnalyzeAgainstProhibitedAttributes(diagnosticReceiver, symbol, compilation, out AttributeData[]? attributes);

                isValid &= AnalyzeContainingTypes(diagnosticReceiver, symbol, compilation, out INamedTypeSymbol[]? containingTypes, cancellationToken);
                isValid &= AnalyzeTypeParameters(diagnosticReceiver, symbol, in typeParameters);

                if (isValid)
                {
                    string targetNamespace = GetTargetNamespace(symbol, compilation, attributes !, containingTypes !);

                    return(AnalyzeCollidingMembers(diagnosticReceiver, symbol, in typeParameters, compilation, targetNamespace, out _, attributes !, containingTypes !, cancellationToken));
                }

                return(false);
            }
            /// <summary>
            /// Analyzes if the containing types of the <paramref name="symbol"/> are valid and reports appropriate <see cref="Diagnostic"/>s.
            /// </summary>
            /// <param name="diagnosticReceiver"><see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/>s.</param>
            /// <param name="symbol"><see cref="ISymbol"/> to analyze.</param>
            /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
            /// <param name="containingTypes">An array of the <paramref name="symbol"/>'s containing types' <see cref="INamedTypeSymbol"/>s. Returned if the method itself returns <see langword="true"/>.</param>
            /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
            /// <returns><see langword="true"/> if the containing types of the <paramref name="symbol"/> are valid, otherwise <see langword="false"/>.</returns>
            public static bool AnalyzeContainingTypes(
                IDiagnosticReceiver diagnosticReceiver,
                ISymbol symbol,
                DefaultParamCompilationData compilation,
                INamedTypeSymbol[]?containingTypes  = null,
                CancellationToken cancellationToken = default
                )
            {
                InitializeContainingTypes(ref containingTypes, symbol);

                bool isValid = true;

                if (containingTypes.Length > 0)
                {
                    foreach (INamedTypeSymbol parent in containingTypes)
                    {
                        if (!HasPartialKeyword(parent, cancellationToken))
                        {
                            diagnosticReceiver.ReportDiagnostic(DefaultParamDiagnostics.DUR0101_ContainingTypeMustBePartial, parent);
                            isValid = false;
                        }

                        ImmutableArray <ITypeParameterSymbol> typeParameters = parent.TypeParameters;

                        if (typeParameters.Length > 0 && typeParameters.SelectMany(t => t.GetAttributes()).Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, compilation.DefaultParamAttribute)))
                        {
                            diagnosticReceiver.ReportDiagnostic(DefaultParamDiagnostics.DUR0126_DefaultParamMembersCannotBeNested, symbol);
                            isValid = false;
                        }
                    }
                }

                return(isValid);
            }
            /// <summary>
            /// Analyzes if the containing types of the <paramref name="symbol"/> are valid and reports appropriate <see cref="Diagnostic"/>s. If the <paramref name="symbol"/> is valid, returns an array of <see cref="ITypeData"/>s of its containing types.
            /// </summary>
            /// <param name="diagnosticReceiver"><see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/>s.</param>
            /// <param name="symbol"><see cref="ISymbol"/> to analyze.</param>
            /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
            /// <param name="containingTypes">An array of the <paramref name="symbol"/>'s containing types' <see cref="ITypeData"/>s. Returned if the method itself returns <see langword="true"/>.</param>
            /// <returns><see langword="true"/> if the containing types of the <paramref name="symbol"/> are valid, otherwise <see langword="false"/>.</returns>
            public static bool AnalyzeContainingTypes(
                IDiagnosticReceiver diagnosticReceiver,
                ISymbol symbol,
                DefaultParamCompilationData compilation,
                [NotNullWhen(true)] out ITypeData[]?containingTypes
                )
            {
                ITypeData[] types   = symbol.GetContainingTypes(compilation).ToArray();
                bool        isValid = true;

                if (types.Length > 0)
                {
                    foreach (ITypeData parent in types)
                    {
                        if (!parent.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)))
                        {
                            diagnosticReceiver.ReportDiagnostic(DefaultParamDiagnostics.DUR0101_ContainingTypeMustBePartial, parent.Symbol);
                            isValid = false;
                        }

                        ImmutableArray <ITypeParameterSymbol> typeParameters = parent.Symbol.TypeParameters;

                        if (typeParameters.Length > 0 && typeParameters.SelectMany(t => t.GetAttributes()).Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, compilation.DefaultParamAttribute)))
                        {
                            diagnosticReceiver.ReportDiagnostic(DefaultParamDiagnostics.DUR0126_DefaultParamMembersCannotBeNested, symbol);
                            isValid = false;
                        }
                    }
                }

                containingTypes = isValid ? types : null;

                return(isValid);
            }
示例#6
0
 /// <inheritdoc cref="DefaultParamDelegateAnalyzer.Analyze(INamedTypeSymbol, DefaultParamCompilationData, CancellationToken)"/>
 public static bool Analyze(
     INamedTypeSymbol symbol,
     DefaultParamCompilationData compilation,
     CancellationToken cancellationToken = default
     )
 {
     return(DefaultParamDelegateAnalyzer.Analyze(symbol, compilation, cancellationToken));
 }
示例#7
0
        private void Analyze(
            DefaultParamCompilationData compilation,
            SyntaxNodeAnalysisContext context,
            ConcurrentDictionary <FileLinePositionSpan, T> dict
            )
        {
            Analyze(compilation, context, out T? data);

            if (data is not null)
            {
                dict.AddOrUpdate(context.Node.GetLocation().GetLineSpan(), data, (_, _) => data);
            }
        }
            /// <summary>
            /// Analyzes if the <paramref name="symbol"/> has <see cref="DurianGeneratedAttribute"/> or <see cref="GeneratedCodeAttribute"/> and reports <see cref="Diagnostic"/>s if the <paramref name="symbol"/> is not valid. If the <paramref name="symbol"/> is valid, returns an array of <paramref name="attributes"/> of that <paramref name="symbol"/>.
            /// </summary>
            /// <param name="diagnosticReceiver"><see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/>s.</param>
            /// <param name="symbol"><see cref="ISymbol"/> to analyze.</param>
            /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
            /// <param name="attributes">An array of <see cref="AttributeData"/>s of the <paramref name="symbol"/>. Returned if the method itself returns <see langword="true"/>.</param>
            /// <returns><see langword="true"/> if the <paramref name="symbol"/> is valid (does not have the prohibited attributes), otherwise <see langword="false"/>.</returns>
            public static bool AnalyzeAgainstProhibitedAttributes(
                IDiagnosticReceiver diagnosticReceiver,
                ISymbol symbol,
                DefaultParamCompilationData compilation,
                out AttributeData[]?attributes
                )
            {
                AttributeData[] attrs   = symbol.GetAttributes().ToArray();
                bool            isValid = AnalyzeAgainstProhibitedAttributes(diagnosticReceiver, symbol, compilation, attrs);

                attributes = isValid ? attrs : null;
                return(isValid);
            }
示例#9
0
        /// <summary>
        /// Enumerates through all the <see cref="MethodDeclarationSyntax"/>es collected by the <paramref name="syntaxReceiver"/> and returns an array of <see cref="DefaultParamMethodData"/>s created from the valid ones.
        /// </summary>
        /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
        /// <param name="syntaxReceiver"><see cref="DefaultParamSyntaxReceiver"/> that collected the <see cref="MethodDeclarationSyntax"/>es.</param>
        /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
        public static DefaultParamMethodData[] GetValidMethods(
            DefaultParamCompilationData compilation,
            DefaultParamSyntaxReceiver syntaxReceiver,
            CancellationToken cancellationToken = default
            )
        {
            if (compilation is null || syntaxReceiver is null || syntaxReceiver.CandidateMethods.Count == 0)
            {
                return(Array.Empty <DefaultParamMethodData>());
            }

            return(GetValidMethods_Internal(compilation, syntaxReceiver.CandidateMethods.ToArray(), cancellationToken));
        }
示例#10
0
 /// <inheritdoc cref="DefaultParamAnalyzer.WithDiagnostics.AnalyzeAgainstProhibitedAttributes(IDiagnosticReceiver, ISymbol, DefaultParamCompilationData, out AttributeData[])"/>
 public static bool AnalyzeAgainstProhibitedAttributes(
     IDiagnosticReceiver diagnosticReceiver,
     INamedTypeSymbol symbol,
     DefaultParamCompilationData compilation,
     [NotNullWhen(true)] out AttributeData[]?attributes
     )
 {
     return(DefaultParamAnalyzer.WithDiagnostics.AnalyzeAgainstProhibitedAttributes(
                diagnosticReceiver,
                symbol,
                compilation,
                out attributes
                ));
 }
示例#11
0
        /// <summary>
        /// Fully analyzes the specified <paramref name="symbol"/>.
        /// </summary>
        /// <param name="symbol"><see cref="INamedTypeSymbol"/> to analyze.</param>
        /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
        /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
        /// <returns><see langword="true"/> if the <paramref name="symbol"/> is valid, otherwise <see langword="false"/>.</returns>
        public static bool Analyze(
            INamedTypeSymbol symbol,
            DefaultParamCompilationData compilation,
            CancellationToken cancellationToken = default
            )
        {
            TypeParameterContainer typeParameters = TypeParameterContainer.CreateFrom(symbol, compilation, cancellationToken);

            if (!typeParameters.HasDefaultParams)
            {
                return(false);
            }

            if (AnalyzeAgainstProhibitedAttributes(symbol, compilation, out AttributeData[]? attributes) &&
            /// <summary>
            /// Analyzes if the containing types of the <paramref name="symbol"/> are valid and reports appropriate <see cref="Diagnostic"/>s.
            /// </summary>
            /// <param name="diagnosticReceiver"><see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/>s.</param>
            /// <param name="symbol"><see cref="ISymbol"/> to analyze.</param>
            /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
            /// <param name="containingTypes">An array of the <paramref name="symbol"/>'s containing types' <see cref="INamedTypeSymbol"/>s. Returned if the method itself returns <see langword="true"/>.</param>
            /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
            /// <returns><see langword="true"/> if the containing types of the <paramref name="symbol"/> are valid, otherwise <see langword="false"/>.</returns>
            public static bool AnalyzeContainingTypes(
                IDiagnosticReceiver diagnosticReceiver,
                ISymbol symbol,
                DefaultParamCompilationData compilation,
                [NotNullWhen(true)] out INamedTypeSymbol[]?containingTypes,
                CancellationToken cancellationToken = default
                )
            {
                INamedTypeSymbol[] types = symbol.GetContainingTypeSymbols().ToArray();
                bool isValid             = AnalyzeContainingTypes(diagnosticReceiver, symbol, compilation, types, cancellationToken);

                containingTypes = isValid ? types : null;
                return(isValid);
            }
            /// <summary>
            /// Enumerates through all the <see cref="DelegateDeclarationSyntax"/>es collected by the <paramref name="syntaxReceiver"/> and returns an array of <see cref="DefaultParamDelegateData"/>s created from the valid ones.
            /// </summary>
            /// <param name="diagnosticReceiver"><see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/>s.</param>
            /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
            /// <param name="syntaxReceiver"><see cref="DefaultParamSyntaxReceiver"/> that collected the <see cref="DelegateDeclarationSyntax"/>es.</param>
            /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
            public static DefaultParamDelegateData[] GetValidDelegates(
                IDiagnosticReceiver diagnosticReceiver,
                DefaultParamCompilationData compilation,
                DefaultParamSyntaxReceiver syntaxReceiver,
                CancellationToken cancellationToken = default
                )
            {
                if (compilation is null || diagnosticReceiver is null || syntaxReceiver is null || syntaxReceiver.CandidateDelegates.Count == 0)
                {
                    return(Array.Empty <DefaultParamDelegateData>());
                }

                return(GetValidDelegates_Internal(diagnosticReceiver, compilation, syntaxReceiver.CandidateDelegates.ToArray(), cancellationToken));
            }
示例#14
0
 /// <inheritdoc cref="DefaultParamAnalyzer.WithDiagnostics.AnalyzeAgainstProhibitedAttributes(IDiagnosticReceiver, ISymbol, DefaultParamCompilationData, IEnumerable{AttributeData}?)"/>
 public static bool AnalyzeAgainstProhibitedAttributes(
     IDiagnosticReceiver diagnosticReceiver,
     ISymbol symbol,
     DefaultParamCompilationData compilation,
     IEnumerable <AttributeData>?attributes = null
     )
 {
     return(DefaultParamAnalyzer.WithDiagnostics.AnalyzeAgainstProhibitedAttributes(
                diagnosticReceiver,
                symbol,
                compilation,
                attributes
                ));
 }
示例#15
0
        /// <summary>
        /// Gets an <see cref="int"/> value of an enum property of either <c>Durian.Configuration.DefaultParamConfigurationAttribute</c> applied to the target <see cref="ISymbol"/> or <c>Durian.Configuration.DefaultParamScopedConfigurationAttribute</c> applied to one of the <see cref="ISymbol"/>'s <paramref name="containingTypes"/>.
        /// </summary>
        /// <param name="propertyName">Name of the property to get the value of.</param>
        /// <param name="attributes">Attributes of the target <see cref="ISymbol"/>.</param>
        /// <param name="containingTypes">Types that contain the target <see cref="ISymbol"/>.</param>
        /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
        /// <param name="defaultValue">Value to be returned when no other valid configuration value is found.</param>
        public static int GetConfigurationEnumValue(
            string propertyName,
            IEnumerable <AttributeData> attributes,
            INamedTypeSymbol[] containingTypes,
            DefaultParamCompilationData compilation,
            int defaultValue
            )
        {
            if (!TryGetConfigurationPropertyValue(attributes, compilation.DefaultParamConfigurationAttribute !, propertyName, out int value))
            {
                return(GetConfigurationEnumValueOnContainingTypes(propertyName, containingTypes, compilation, defaultValue));
            }

            return(value);
        }
        /// <summary>
        /// Fully analyzes the specified <paramref name="symbol"/>.
        /// </summary>
        /// <param name="symbol"><see cref="IMethodSymbol"/> to analyze.</param>
        /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
        /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
        /// <returns><see langword="true"/> if the <paramref name="symbol"/> is valid, otherwise <see langword="false"/>.</returns>
        public static bool Analyze(
            IMethodSymbol symbol,
            DefaultParamCompilationData compilation,
            CancellationToken cancellationToken = default
            )
        {
            TypeParameterContainer typeParameters = TypeParameterContainer.CreateFrom(symbol, compilation, cancellationToken);

            if (!typeParameters.HasDefaultParams && !symbol.IsOverride)
            {
                return(false);
            }

            return(AnalyzeCore(symbol, compilation, ref typeParameters, cancellationToken));
        }
            /// <inheritdoc/>
            protected override bool Analyze(
                DefaultParamCompilationData compilation,
                SyntaxNodeAnalysisContext context,
                [NotNullWhen(true)] out DefaultParamDelegateData?data
                )
            {
                if (context.Node is not TypeParameterListSyntax || context.Node.Parent is not DelegateDeclarationSyntax declaration)
                {
                    data = null;
                    return(false);
                }

                IDiagnosticReceiver diagnosticReceiver = DiagnosticReceiverFactory.SyntaxNode(context);

                return(WithDiagnostics.ValidateAndCreate(diagnosticReceiver, compilation, declaration, out data, context.CancellationToken));
            }
示例#18
0
        /// <summary>
        /// Reports <see cref="Diagnostic"/> s for <see cref="LocalFunctionStatementSyntax"/> es
        /// returned by the <see cref="GetCandidateLocalFunctions()"/> method.
        /// </summary>
        /// <param name="diagnosticReceiver">
        /// <see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/> s.
        /// </param>
        /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
        /// <param name="collectedLocalFunctions">
        /// A collection of <see cref="LocalFunctionStatementSyntax"/> to report the <see
        /// cref="Diagnostic"/> s for.
        /// </param>
        /// <param name="cancellationToken">
        /// <see cref="CancellationToken"/> that specifies if the operation should be canceled.
        /// </param>
        public static void ReportDiagnosticsForLocalFunctions(
            IDiagnosticReceiver diagnosticReceiver,
            DefaultParamCompilationData compilation,
            IEnumerable <LocalFunctionStatementSyntax> collectedLocalFunctions,
            CancellationToken cancellationToken = default
            )
        {
            if (collectedLocalFunctions is null || compilation is null || diagnosticReceiver is null)
            {
                return;
            }

            foreach (LocalFunctionStatementSyntax fn in collectedLocalFunctions)
            {
                ReportDiagnosticsForLocalFunction(diagnosticReceiver, compilation, fn, cancellationToken);
            }
        }
示例#19
0
        /// <summary>
        /// Reports <see cref="Diagnostic"/> s for <see cref="LocalFunctionStatementSyntax"/> es
        /// returned by the <see cref="GetCandidateLocalFunctions()"/> method.
        /// </summary>
        /// <param name="diagnosticReceiver">
        /// <see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/> s.
        /// </param>
        /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
        /// <param name="syntaxReceiver">
        /// <see cref="DefaultParamSyntaxReceiver"/> that collected the <see
        /// cref="LocalFunctionStatementSyntax"/> to report <see cref="Diagnostic"/> for.
        /// </param>
        /// <param name="cancellationToken">
        /// <see cref="CancellationToken"/> that specifies if the operation should be canceled.
        /// </param>
        public static void ReportDiagnosticsForLocalFunctions(
            IDiagnosticReceiver diagnosticReceiver,
            DefaultParamCompilationData compilation,
            DefaultParamSyntaxReceiver syntaxReceiver,
            CancellationToken cancellationToken = default
            )
        {
            if (diagnosticReceiver is null || compilation is null || syntaxReceiver is null || syntaxReceiver.CandidateLocalFunctions is null || syntaxReceiver.CandidateLocalFunctions.Count == 0)
            {
                return;
            }

            foreach (LocalFunctionStatementSyntax fn in syntaxReceiver.CandidateLocalFunctions)
            {
                ReportDiagnosticsForLocalFunction(diagnosticReceiver, compilation, fn, cancellationToken);
            }
        }
            /// <inheritdoc/>
            protected override bool Analyze(
                DefaultParamCompilationData compilation,
                SyntaxNodeAnalysisContext context,
                [NotNullWhen(true)] out IDefaultParamTarget?data
                )
            {
                data = null;

                if (context.Node is not TypeParameterListSyntax || context.Node.Parent is not LocalFunctionStatementSyntax declaration)
                {
                    return(false);
                }

                IDiagnosticReceiver diagnosticReceiver = DiagnosticReceiverFactory.SyntaxNode(context);

                ReportDiagnosticsForLocalFunction(diagnosticReceiver, compilation, declaration, context.CancellationToken);
                return(false);
            }
        /// <summary>
        /// Enumerates through all the <paramref name="collectedTypes"/> and returns an array of <see cref="DefaultParamTypeData"/>s created from the valid ones.
        /// </summary>
        /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
        /// <param name="collectedTypes">A collection of <see cref="TypeDeclarationSyntax"/>es to validate.</param>
        /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
        public static DefaultParamTypeData[] GetValidTypes(
            DefaultParamCompilationData compilation,
            IEnumerable <TypeDeclarationSyntax> collectedTypes,
            CancellationToken cancellationToken = default
            )
        {
            if (compilation is null || collectedTypes is null || compilation is null)
            {
                return(Array.Empty <DefaultParamTypeData>());
            }

            TypeDeclarationSyntax[] collected = collectedTypes.ToArray();

            if (collected.Length == 0)
            {
                return(Array.Empty <DefaultParamTypeData>());
            }

            return(GetValidTypes_Internal(compilation, collected, cancellationToken));
        }
        /// <summary>
        /// Specifies, if the <see cref="SemanticModel"/>, <see cref="INamedTypeSymbol"/> and <see cref="TypeParameterContainer"/> can be created from the given <paramref name="declaration"/>.
        /// If so, returns them.
        /// </summary>
        /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
        /// <param name="declaration"><see cref="TypeDeclarationSyntax"/> to validate.</param>
        /// <param name="semanticModel"><see cref="SemanticModel"/> of the <paramref name="declaration"/>.</param>
        /// <param name="symbol"><see cref="INamedTypeSymbol"/> created from the <paramref name="declaration"/>.</param>
        /// <param name="typeParameters"><see cref="TypeParameterContainer"/> that contains the <paramref name="declaration"/>'s type parameters.</param>
        /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
        public static bool GetValidationData(
            DefaultParamCompilationData compilation,
            TypeDeclarationSyntax declaration,
            [NotNullWhen(true)] out SemanticModel?semanticModel,
            [NotNullWhen(true)] out INamedTypeSymbol?symbol,
            out TypeParameterContainer typeParameters,
            CancellationToken cancellationToken = default
            )
        {
            semanticModel  = compilation.Compilation.GetSemanticModel(declaration.SyntaxTree);
            typeParameters = GetTypeParameters(declaration, semanticModel, compilation, cancellationToken);

            if (!typeParameters.HasDefaultParams)
            {
                symbol = null !;
                return(false);
            }

            symbol = semanticModel.GetDeclaredSymbol(declaration, cancellationToken) !;

            return(symbol is not null);
        }
            /// <summary>
            /// Analyzes if the provided collection of <see cref="AttributeData"/>s contains <see cref="DurianGeneratedAttribute"/> or <see cref="GeneratedCodeAttribute"/> and reports appropriate <see cref="Diagnostic"/>s.
            /// </summary>
            /// <param name="diagnosticReceiver"><see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/>s.</param>
            /// <param name="symbol"><see cref="ISymbol"/> that owns the <paramref name="attributes"/>.</param>
            /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
            /// <param name="attributes">A collection of <see cref="AttributeData"/> to analyze.</param>
            /// <returns><see langword="true"/> if all the <paramref name="attributes"/> are valid (neither of them is prohibited), otherwise <see langword="false"/>.</returns>
            public static bool AnalyzeAgainstProhibitedAttributes(
                IDiagnosticReceiver diagnosticReceiver,
                ISymbol symbol,
                DefaultParamCompilationData compilation,
                IEnumerable <AttributeData>?attributes = null
                )
            {
                InitializeAttributes(ref attributes, symbol);

                foreach (AttributeData attr in attributes)
                {
                    if (SymbolEqualityComparer.Default.Equals(attr.AttributeClass, compilation.GeneratedCodeAttribute) ||
                        SymbolEqualityComparer.Default.Equals(attr.AttributeClass, compilation.DurianGeneratedAttribute))
                    {
                        diagnosticReceiver.ReportDiagnostic(DefaultParamDiagnostics.DUR0104_DefaultParamCannotBeAppliedWhenGenerationAttributesArePresent, symbol);

                        return(false);
                    }
                }

                return(true);
            }
示例#24
0
        /// <summary>
        /// Gets an <see cref="int"/> value of an enum property <c>Durian.Configuration.DefaultParamScopedConfigurationAttribute</c> applied to one of the <see cref="ISymbol"/>'s <paramref name="containingTypes"/>.
        /// </summary>
        /// <param name="propertyName">Name of the property to get the value of.</param>
        /// <param name="containingTypes">Types that contain the target <see cref="ISymbol"/>.</param>
        /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
        /// <param name="defaultValue">Value to be returned when no other valid configuration value is found.</param>
        public static int GetConfigurationEnumValueOnContainingTypes(
            string propertyName,
            INamedTypeSymbol[] containingTypes,
            DefaultParamCompilationData compilation,
            int defaultValue
            )
        {
            int length = containingTypes.Length;

            if (length > 0)
            {
                INamedTypeSymbol scopedAttribute = compilation.DefaultParamScopedConfigurationAttribute !;

                foreach (INamedTypeSymbol type in containingTypes.Reverse())
                {
                    if (TryGetConfigurationPropertyValue(type.GetAttributes(), scopedAttribute, propertyName, out int value))
                    {
                        return(value);
                    }
                }
            }

            return(defaultValue);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="DefaultParamMethodData"/> class.
 /// </summary>
 /// <param name="declaration"><see cref="MethodDeclarationSyntax"/> this <see cref="DefaultParamMethodData"/> represents.</param>
 /// <param name="compilation">Parent <see cref="DefaultParamCompilationData"/> of this <see cref="DefaultParamMethodData"/>.</param>
 /// <param name="typeParameters"><see cref="TypeParameterContainer"/> that contains type parameters of this member.</param>
 /// <exception cref="ArgumentNullException">
 /// <paramref name="declaration"/> is <see langword="null"/>. -or- <paramref name="compilation"/> is <see langword="null"/>
 /// </exception>
 public DefaultParamMethodData(MethodDeclarationSyntax declaration, DefaultParamCompilationData compilation, in TypeParameterContainer typeParameters) : base(declaration, compilation)
 /// <summary>
 /// Enumerates through all the <paramref name="collectedTypes"/> and returns an array of <see cref="DefaultParamTypeData"/>s created from the valid ones. If the target <see cref="DefaultParamTypeData"/> already exists in the specified <paramref name="cache"/>, includes it instead.
 /// </summary>
 /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
 /// <param name="collectedTypes">A collection of <see cref="TypeDeclarationSyntax"/>es to validate.</param>
 /// <param name="cache">Container of cached <see cref="DefaultParamTypeData"/>s.</param>
 /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
 public static DefaultParamTypeData[] GetValidTypes(
     DefaultParamCompilationData compilation,
     IEnumerable <TypeDeclarationSyntax> collectedTypes,
     in CachedData <DefaultParamTypeData> cache,
示例#27
0
 /// <summary>
 /// Creates a new <see cref="TypeParameterData"/> based on the specified <paramref name="typeParameter"/>.
 /// </summary>
 /// <param name="typeParameter"><see cref="TypeParameterSyntax"/> to create the <see cref="TypeParameterData"/> from.</param>
 /// <param name="semanticModel"><see cref="Microsoft.CodeAnalysis.SemanticModel"/> of the target <paramref name="typeParameter"/>.</param>
 /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
 /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
 public static TypeParameterData CreateFrom(TypeParameterSyntax typeParameter, SemanticModel semanticModel, DefaultParamCompilationData compilation, CancellationToken cancellationToken = default)
 {
     return(CreateFrom(typeParameter, semanticModel, compilation.DefaultParamAttribute !, cancellationToken));
 }
示例#28
0
 /// <summary>
 /// Creates a new <see cref="TypeParameterData"/> based on the specified <paramref name="symbol"/>.
 /// </summary>
 /// <param name="symbol"><see cref="ITypeParameterSymbol"/> to create the <see cref="TypeParameterData"/> from.</param>
 /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
 /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
 public static TypeParameterData CreateFrom(ITypeParameterSymbol symbol, DefaultParamCompilationData compilation, CancellationToken cancellationToken = default)
 {
     if (symbol.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(cancellationToken) is not TypeParameterSyntax syntax)
     {
         return(default);
 /// <summary>
 /// Enumerates through all the <see cref="DelegateDeclarationSyntax"/>es collected by the <paramref name="syntaxReceiver"/> and returns an array of <see cref="DefaultParamDelegateData"/>s created from the valid ones. If the target <see cref="DefaultParamDelegateData"/> already exists in the specified <paramref name="cache"/>, includes it instead.
 /// </summary>
 /// <param name="diagnosticReceiver"><see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/>s.</param>
 /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
 /// <param name="syntaxReceiver"><see cref="DefaultParamSyntaxReceiver"/> that collected the <see cref="DelegateDeclarationSyntax"/>es.</param>
 /// <param name="cache">Container of cached <see cref="DefaultParamDelegateData"/>s.</param>
 /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
 public static DefaultParamDelegateData[] GetValidDelegates(
     IDiagnosticReceiver diagnosticReceiver,
     DefaultParamCompilationData compilation,
     DefaultParamSyntaxReceiver syntaxReceiver,
     in CachedData <DefaultParamDelegateData> cache,
示例#30
0
 /// <summary>
 /// Enumerates through all the <see cref="MethodDeclarationSyntax"/>es collected by the <paramref name="syntaxReceiver"/> and returns an array of <see cref="DefaultParamMethodData"/>s created from the valid ones. If the target <see cref="DefaultParamMethodData"/> already exists in the specified <paramref name="cache"/>, includes it instead.
 /// </summary>
 /// <param name="compilation">Current <see cref="DefaultParamCompilationData"/>.</param>
 /// <param name="syntaxReceiver"><see cref="DefaultParamSyntaxReceiver"/> that collected the <see cref="MethodDeclarationSyntax"/>es.</param>
 /// <param name="cache">Container of cached <see cref="DefaultParamMethodData"/>s.</param>
 /// <param name="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param>
 public static DefaultParamMethodData[] GetValidMethods(
     DefaultParamCompilationData compilation,
     DefaultParamSyntaxReceiver syntaxReceiver,
     in CachedData <DefaultParamMethodData> cache,