public AutoInterfaceTemplateAttribute(AutoInterfaceTargets targets)
 {
     this.Targets = targets;
 }
示例#2
0
 public PartialTemplate(AutoInterfaceTargets memberTargets, Regex?memberFilter, TemplateDefinition template)
 {
     this.MemberTargets = memberTargets;
     this.MemberFilter  = memberFilter;
     this.Template      = template;
 }
    private static List <AutoInterfaceRecord> CollectRecords(GeneratorExecutionContext context, ISymbol symbol, ITypeSymbol receiverType, INamedTypeSymbol autoInterfaceAttributeSymbol, INamedTypeSymbol autoInterfaceTemplateAttributeSymbol)
    {
        List <PartialTemplate> templateParts = new();
        Dictionary <ISymbol, HashSet <INamedTypeSymbol> > danglingInterfaceTypesBySymbols = new(SymbolEqualityComparer.Default);

        foreach (AttributeData attribute in symbol.GetAttributes())
        {
            if (attribute.AttributeClass != null && attribute.AttributeClass.Equals(autoInterfaceTemplateAttributeSymbol, SymbolEqualityComparer.Default))
            {
                ITypeSymbol?type = receiverType.WithNullableAnnotation(NullableAnnotation.NotAnnotated);

                AutoInterfaceTargets memberTargets = (AutoInterfaceTargets)Convert.ToInt32(attribute.ConstructorArguments[0].Value);

                if (type.TypeKind == TypeKind.Interface)
                {
                    if (type is INamedTypeSymbol interfaceType)
                    {
                        if (receiverType.IsMatchByTypeOrImplementsInterface(type))
                        {
                            string?templateBody     = null;
                            string?templateFileName = null;
                            string?templateLanguage = null;
                            string?memberFilter     = null;

                            #region collect named arguments [only one argument for now]

                            foreach (KeyValuePair <string, TypedConstant> arg in attribute.NamedArguments)
                            {
                                switch (arg.Key)
                                {
                                case "FileName":
                                {
                                    if (arg.Value.Value is string s)
                                    {
                                        templateFileName = s;
                                    }
                                }
                                break;

                                case "Body":
                                {
                                    if (arg.Value.Value is string s)
                                    {
                                        templateBody = s;
                                    }
                                }
                                break;

                                case "Language":
                                {
                                    if (arg.Value.Value is string s)
                                    {
                                        templateLanguage = s;
                                    }
                                }
                                break;

                                case "Filter":
                                {
                                    if (arg.Value.Value is string s)
                                    {
                                        memberFilter = s;
                                    }
                                }
                                break;
                                }
                            }

                            #endregion

                            if (templateBody != null && templateBody.Trim().Length > 0)
                            {
                                if (templateFileName != null && templateFileName.Trim().Length > 0)
                                {
                                    Helpers.ReportDiagnostic(context, "BK-AG12", nameof(AutoInterfaceResource.AG12_title), nameof(AutoInterfaceResource.AG12_message), nameof(AutoInterfaceResource.AG12_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax()
                                                             );
                                    continue;
                                }

                                Regex?rxMemberFilter = null;
                                if (memberFilter != null && memberFilter.Length > 0)
                                {
                                    try
                                    {
                                        rxMemberFilter = new Regex(memberFilter, RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
                                    }
                                    catch
                                    {
                                        Helpers.ReportDiagnostic(context, "BK-AG15", nameof(AutoInterfaceResource.AG15_title), nameof(AutoInterfaceResource.AG15_message), nameof(AutoInterfaceResource.AG15_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax(),
                                                                 memberFilter);
                                        continue;
                                    }
                                }

                                templateParts.Add(new PartialTemplate(memberTargets, rxMemberFilter, new TemplateDefinition(templateLanguage ?? "scriban", templateBody.Trim())));
                                if (danglingInterfaceTypesBySymbols.TryGetValue(symbol, out HashSet <INamedTypeSymbol> interfaceTypes) == false)
                                {
                                    danglingInterfaceTypesBySymbols[symbol] = interfaceTypes = new HashSet <INamedTypeSymbol>(SymbolEqualityComparer.Default);
                                }

                                interfaceTypes.Add(interfaceType);
                            }
                            else if (templateFileName != null && templateFileName.Trim().Length > 0)
                            {
                                string?content = null;

                                AdditionalText?file = context.AdditionalFiles.FirstOrDefault(i => i.Path.EndsWith(templateFileName));
                                if (file != null)
                                {
                                    content = file.GetText()?.ToString()?.Trim();
                                    if (content == null)
                                    {
                                        content = "";
                                    }
                                }
                                else
                                {
                                    Helpers.ReportDiagnostic(context, "BK-AG11", nameof(AutoInterfaceResource.AG11_title), nameof(AutoInterfaceResource.AG11_message), nameof(AutoInterfaceResource.AG11_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax(),
                                                             templateFileName);
                                    continue;
                                }

                                if (string.IsNullOrEmpty(templateLanguage))
                                {
                                    string extension = Path.GetExtension(templateFileName).ToLowerInvariant();
                                    if (extension.StartsWith("."))
                                    {
                                        extension = extension.Substring(1);
                                    }
                                    templateLanguage = extension;
                                }

                                Regex?rxMemberFilter = null;
                                if (memberFilter != null && memberFilter.Length > 0)
                                {
                                    try
                                    {
                                        rxMemberFilter = new Regex(memberFilter, RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
                                    }
                                    catch
                                    {
                                        Helpers.ReportDiagnostic(context, "BK-AG15", nameof(AutoInterfaceResource.AG15_title), nameof(AutoInterfaceResource.AG15_message), nameof(AutoInterfaceResource.AG15_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax(),
                                                                 memberFilter);
                                        continue;
                                    }
                                }

                                templateParts.Add(new PartialTemplate(memberTargets, rxMemberFilter, new TemplateDefinition(templateLanguage ?? "scriban", content)));
                                if (danglingInterfaceTypesBySymbols.TryGetValue(symbol, out HashSet <INamedTypeSymbol> interfaceTypes) == false)
                                {
                                    danglingInterfaceTypesBySymbols[symbol] = interfaceTypes = new HashSet <INamedTypeSymbol>(SymbolEqualityComparer.Default);
                                }

                                interfaceTypes.Add(interfaceType);
                            }
                            else
                            {
                                Helpers.ReportDiagnostic(context, "BK-AG14", nameof(AutoInterfaceResource.AG14_title), nameof(AutoInterfaceResource.AG14_message), nameof(AutoInterfaceResource.AG14_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax()
                                                         );
                                continue;
                            }
                        }
                        else
                        {
                            Helpers.ReportDiagnostic(context, "BK-AG04", nameof(AutoInterfaceResource.AG04_title), nameof(AutoInterfaceResource.AG04_message), nameof(AutoInterfaceResource.AG04_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax(),
                                                     receiverType.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat));
                            continue;
                        }
                    }
                    else
                    {
                        Helpers.ReportDiagnostic(context, "BK-AG09", nameof(AutoInterfaceResource.AG09_title), nameof(AutoInterfaceResource.AG09_message), nameof(AutoInterfaceResource.AG09_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax(),
                                                 157834);
                        continue;
                    }
                }
                else
                {
                    Helpers.ReportDiagnostic(context, "BK-AG03", nameof(AutoInterfaceResource.AG03_title), nameof(AutoInterfaceResource.AG03_message), nameof(AutoInterfaceResource.AG03_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax(),
                                             type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat));
                    continue;
                }
            }
        }

        List <AutoInterfaceRecord> records = new();

        foreach (AttributeData attribute in symbol.GetAttributes())
        {
            if (attribute.AttributeClass != null && attribute.AttributeClass.Equals(autoInterfaceAttributeSymbol, SymbolEqualityComparer.Default))
            {
                ITypeSymbol?type = null;
                bool?       includeBaseInterfaces = null;
                bool?       preferCoalesce        = null;

                if (attribute.ConstructorArguments.Length == 0)
                {
                    type = receiverType.WithNullableAnnotation(NullableAnnotation.NotAnnotated);
                }
                else
                {
                    if (attribute.ConstructorArguments[0].Value is ITypeSymbol targetType)
                    {
                        type = targetType;
                    }
                }

                if (type == null)
                {
                    Helpers.ReportDiagnostic(context, "BK-AG07", nameof(AutoInterfaceResource.AG07_title), nameof(AutoInterfaceResource.AG07_message), nameof(AutoInterfaceResource.AG07_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax());
                    continue;
                }
                else if (type.TypeKind == TypeKind.Interface)
                {
                    if (type is INamedTypeSymbol interfaceType)
                    {
                        string?templateBody     = null;
                        string?templateFileName = null;
                        string?templateLanguage = null;

                        #region collect named arguments

                        foreach (KeyValuePair <string, TypedConstant> arg in attribute.NamedArguments)
                        {
                            switch (arg.Key)
                            {
                            case "TemplateFileName":
                            {
                                if (arg.Value.Value is string s)
                                {
                                    templateFileName = s;
                                }
                            }
                            break;

                            case "TemplateBody":
                            {
                                if (arg.Value.Value is string s)
                                {
                                    templateBody = s;
                                }
                            }
                            break;

                            case "TemplateLanguage":
                            {
                                if (arg.Value.Value is string s)
                                {
                                    templateLanguage = s;
                                }
                            }
                            break;

                            case "IncludeBaseInterfaces":
                            {
                                if (arg.Value.Value is bool b)
                                {
                                    includeBaseInterfaces = b;
                                }
                            }
                            break;

                            case "PreferCoalesce":
                            {
                                if (arg.Value.Value is bool b)
                                {
                                    preferCoalesce = b;
                                }
                            }
                            break;
                            }
                        }

                        #endregion

                        TemplateDefinition?template = null;
                        if (templateBody != null && templateBody.Trim().Length > 0)
                        {
                            if (templateFileName != null && templateFileName.Trim().Length > 0)
                            {
                                Helpers.ReportDiagnostic(context, "BK-AG12", nameof(AutoInterfaceResource.AG12_title), nameof(AutoInterfaceResource.AG12_message), nameof(AutoInterfaceResource.AG12_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax()
                                                         );
                                continue;
                            }

                            template = new TemplateDefinition(templateLanguage ?? "scriban", templateBody.Trim());
                        }
                        else if (templateFileName != null && templateFileName.Trim().Length > 0)
                        {
                            string?content = null;

                            AdditionalText?file = context.AdditionalFiles.FirstOrDefault(i => i.Path.EndsWith(templateFileName));
                            if (file != null)
                            {
                                content = file.GetText()?.ToString()?.Trim();
                                if (content == null)
                                {
                                    content = "";
                                }
                            }
                            else
                            {
                                Helpers.ReportDiagnostic(context, "BK-AG11", nameof(AutoInterfaceResource.AG11_title), nameof(AutoInterfaceResource.AG11_message), nameof(AutoInterfaceResource.AG11_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax(),
                                                         templateFileName);
                                continue;
                            }

                            if (string.IsNullOrEmpty(templateLanguage))
                            {
                                string extension = Path.GetExtension(templateFileName).ToLowerInvariant();
                                if (extension.StartsWith("."))
                                {
                                    extension = extension.Substring(1);
                                }
                                templateLanguage = extension;
                            }

                            if (templateParts.Count > 0)
                            {
                                Helpers.ReportDiagnostic(context, "BK-AG13", nameof(AutoInterfaceResource.AG13_title), nameof(AutoInterfaceResource.AG13_message), nameof(AutoInterfaceResource.AG13_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax()
                                                         );
                                continue;
                            }

                            template = new TemplateDefinition(templateLanguage ?? "scriban", content);
                        }

                        if (includeBaseInterfaces == null)
                        {
                            includeBaseInterfaces = false;
                        }

                        if (preferCoalesce == null)
                        {
                            preferCoalesce = true;
                        }

                        if (receiverType.IsMatchByTypeOrImplementsInterface(type))
                        {
                            danglingInterfaceTypesBySymbols.Remove(symbol);
                            records.Add(new AutoInterfaceRecord(symbol, receiverType, interfaceType, template, templateParts, false, preferCoalesce.Value));
                            if (includeBaseInterfaces.Value)
                            {
                                foreach (INamedTypeSymbol baseInterfaceType in interfaceType.AllInterfaces)
                                {
                                    records.Add(new AutoInterfaceRecord(symbol, receiverType, baseInterfaceType, template, templateParts, false, preferCoalesce.Value));
                                }
                            }
                        }
                        else if (receiverType.IsAllInterfaceMembersImplementedBySignature(type) &&
                                 (includeBaseInterfaces.Value == false || interfaceType.AllInterfaces.All(i => receiverType.IsMatchByTypeOrImplementsInterface(i) || receiverType.IsAllInterfaceMembersImplementedBySignature(i))))
                        {
                            danglingInterfaceTypesBySymbols.Remove(symbol);
                            records.Add(new AutoInterfaceRecord(symbol, receiverType, interfaceType, template, templateParts, true, preferCoalesce.Value));
                            if (includeBaseInterfaces.Value)
                            {
                                foreach (INamedTypeSymbol baseInterfaceType in interfaceType.AllInterfaces)
                                {
                                    bool byType = receiverType.IsMatchByTypeOrImplementsInterface(baseInterfaceType);
                                    records.Add(new AutoInterfaceRecord(symbol, receiverType, baseInterfaceType, template, templateParts, !byType, preferCoalesce.Value));
                                }
                            }
                        }
                        else
                        {
                            Helpers.ReportDiagnostic(context, "BK-AG04", nameof(AutoInterfaceResource.AG04_title), nameof(AutoInterfaceResource.AG04_message), nameof(AutoInterfaceResource.AG04_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax(),
                                                     receiverType.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat));
                            continue;
                        }
                    }
                    else
                    {
                        Helpers.ReportDiagnostic(context, "BK-AG09", nameof(AutoInterfaceResource.AG09_title), nameof(AutoInterfaceResource.AG09_message), nameof(AutoInterfaceResource.AG09_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax(),
                                                 157834);
                        continue;
                    }
                }
                else
                {
                    Helpers.ReportDiagnostic(context, "BK-AG03", nameof(AutoInterfaceResource.AG03_title), nameof(AutoInterfaceResource.AG03_message), nameof(AutoInterfaceResource.AG03_description), DiagnosticSeverity.Error, attribute.ApplicationSyntaxReference?.GetSyntax(),
                                             type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat));
                    continue;
                }
            }
        }

        foreach (KeyValuePair <ISymbol, HashSet <INamedTypeSymbol> > danglingInterfaceTypes in danglingInterfaceTypesBySymbols)
        {
            foreach (INamedTypeSymbol interfaceType in danglingInterfaceTypes.Value)
            {
                records.Add(new AutoInterfaceRecord(danglingInterfaceTypes.Key, receiverType, interfaceType, null, templateParts, false, false));
            }
        }

        return(records);
    }