/// <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); } }
/// <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); }
/// <inheritdoc cref="DefaultParamDelegateAnalyzer.Analyze(INamedTypeSymbol, DefaultParamCompilationData, CancellationToken)"/> public static bool Analyze( INamedTypeSymbol symbol, DefaultParamCompilationData compilation, CancellationToken cancellationToken = default ) { return(DefaultParamDelegateAnalyzer.Analyze(symbol, compilation, cancellationToken)); }
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); }
/// <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)); }
/// <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 )); }
/// <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)); }
/// <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 )); }
/// <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)); }
/// <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); } }
/// <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); }
/// <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,
/// <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)); }
/// <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,
/// <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,