/// <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); }
/// <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 <paramref name="symbol"/> or either <see langword="partial"/> or <see langword="extern"/>. /// </summary> /// <param name="diagnosticReceiver"><see cref="IDiagnosticReceiver"/> that is used to report <see cref="Diagnostic"/>s.</param> /// <param name="symbol"><see cref="IMethodSymbol"/> to analyze.</param> /// <param name="declaration">Main <see cref="MethodDeclarationSyntax"/> of the <paramref name="symbol"/>.</param> /// <returns><see langword="true"/> if the <paramref name="symbol"/> is valid (is not <see langword="partial"/> or <see langword="extern"/>), otherwise <see langword="false"/>.</returns> public static bool AnalyzeAgainstPartialOrExtern( IDiagnosticReceiver diagnosticReceiver, IMethodSymbol symbol, MethodDeclarationSyntax declaration ) { if (symbol.IsExtern || symbol.IsPartial(declaration)) { diagnosticReceiver.ReportDiagnostic(DefaultParamDiagnostics.DUR0102_MethodCannotBePartialOrExtern, symbol); return(false); } return(true); }
public static bool AnalyzeConfiguration( IDiagnosticReceiver diagnosticReceiver, IAssemblySymbol assembly, EnumServicesConfiguration configuration, AttributeSyntax syntax) { if (!IsValidServicesValue(configuration.EnumServices)) { diagnosticReceiver.ReportDiagnostic( DUR0201_InvalidEnumValue, syntax.GetArgumentLocation(nameof(EnumServicesAttribute.Services)), assembly); } }
/// <summary> /// Analyzes if the specified <paramref name="symbol"/> is partial. /// </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="cancellationToken"><see cref="CancellationToken"/> that specifies if the operation should be canceled.</param> /// <returns><see langword="true"/> if the <paramref name="symbol"/> is not partial, <see langword="false"/> otherwise.</returns> public static bool AnalyzeAgainstPartial( IDiagnosticReceiver diagnosticReceiver, INamedTypeSymbol symbol, CancellationToken cancellationToken = default ) { TypeDeclarationSyntax[] syntaxes = symbol.DeclaringSyntaxReferences .Select(r => r.GetSyntax(cancellationToken)) .OfType <TypeDeclarationSyntax>() .ToArray(); if (syntaxes.Length > 1 || syntaxes[0].Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword))) { diagnosticReceiver.ReportDiagnostic(DefaultParamDiagnostics.DUR0122_DoNotUseDefaultParamOnPartialType, symbol); return(false); } return(true); }
/// <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); }