예제 #1
0
 void AppendNamespace(INamedTypeSymbol classSymbol, CsharpCodeBuilder codeBuilder)
 {
     if (!classSymbol.ContainingNamespace.IsGlobalNamespace)
     {
         codeBuilder.AppendCodeLines($"namespace {classSymbol.ContainingNamespace.ToDisplayString()}");
         codeBuilder.BeginSegment();
     }
 }
예제 #2
0
        private void AppendClassDefinition(INamedTypeSymbol classSymbol, CsharpCodeBuilder codeBuilder)
        {
            var classSymbols = classSymbol.GetContainerClassChains();

            for (int i = 0; i < classSymbols.Count; i++)
            {
                var parentClass = classSymbols[i];
                if (i == classSymbols.Count - 1)
                {
                    codeBuilder.AppendCodeLines($@"static partial class {parentClass.GetClassSymbolDisplayText()}");
                }
                else
                {
                    codeBuilder.AppendCodeLines($@"partial class {parentClass.GetClassSymbolDisplayText()}");
                }
                codeBuilder.BeginSegment();
            }
        }
예제 #3
0
        void AppendClassDefinition(INamedTypeSymbol classSymbol, CsharpCodeBuilder codeBuilder)
        {
            var classSymbols = classSymbol.GetContainerClassChains();

            foreach (var parentClass in classSymbols)
            {
                codeBuilder.AppendCodeLines($@"partial class {parentClass.GetClassSymbolDisplayText()}");
                codeBuilder.BeginSegment();
            }
        }
        void AppendPublicCtor(INamedTypeSymbol classSymbol, IDictionary <string, ArgumentInfo> nameMapper, bool isDependencyInjection, bool nullCheck, CsharpCodeBuilder codeBuilder)
        {
            if (isDependencyInjection)
            {
                codeBuilder.AppendCodeLines("[Microsoft.Extensions.DependencyInjection.ActivatorUtilitiesConstructor]");
            }

            string args = string.Join(", ", nameMapper.Select(p => p.Value.GetCtorMethodArgumentItem()));


            codeBuilder.AppendCodeLines($"public {classSymbol.Name}({args})");
            var baseCtorArgs = nameMapper.Values.Where(p => p.Source == ArgumentSource.BaseCtor);

            if (baseCtorArgs.Any())
            {
                string baseArgs = string.Join(", ", baseCtorArgs.Select(p => $"{p.MemberName}: {p.ArgName}"));
                codeBuilder.AppendCodeLines($"    : base({baseArgs})");
            }


            codeBuilder.BeginSegment();
            // lines
            foreach (var member in nameMapper.Values.Where(p => p.Source != ArgumentSource.BaseCtor))
            {
                codeBuilder.AppendCodeLines(BuildCtorAssignLine(member));
            }

            codeBuilder.EndSegment();

            string BuildCtorAssignLine(ArgumentInfo argumentInfo)
            {
                if (nullCheck && !argumentInfo.ArgTypeSymbol.IsValueType)
                {
                    return($"this.{argumentInfo.MemberName} = {argumentInfo.ArgName} ?? throw new System.ArgumentNullException(nameof({argumentInfo.ArgName}));");
                }
                else
                {
                    return($"this.{argumentInfo.MemberName} = {argumentInfo.ArgName};");
                }
            }
        }
예제 #5
0
        void AppendSingletonBody(INamedTypeSymbol classSymbol, CsharpCodeBuilder codeBuilder)
        {
            var instanceName = classSymbol.GetAttributes().Where(p => p.AttributeClass.SafeEquals(typeof(SingletonPatternAttribute)))
                               .Select(p => p.NamedArguments.Where(t => t.Key == nameof(SingletonPatternAttribute.InstancePropertyName)).Where(t => !t.Value.IsNull).Select(t => (string)t.Value.Value).FirstOrDefault())
                               .FirstOrDefault();

            instanceName = string.IsNullOrEmpty(instanceName) ? SingletonPatternAttribute.DefaultInstanceName : instanceName;

            var content = $@"private static readonly Lazy<{classSymbol.GetClassSymbolDisplayText()}> LazyInstance = new Lazy<{classSymbol.GetClassSymbolDisplayText()}>(() => new {classSymbol.GetClassSymbolDisplayText()}(), true);

private {classSymbol.Name}() {{ }}

public static {classSymbol.GetClassSymbolDisplayText()} {instanceName} => LazyInstance.Value;";

            codeBuilder.AppendCodeLines(content);
        }
예제 #6
0
 void AppendUsingLines(INamedTypeSymbol _, CsharpCodeBuilder codeBuilder)
 {
     codeBuilder.AppendCodeLines("using System;");
 }
예제 #7
0
        private CodeFile ProcessClass(INamedTypeSymbol classSymbol, List <IFieldSymbol> fields, CodeWriter codeWriter)
        {
            var compilation = codeWriter.Compilation;
            INamedTypeSymbol notifySymbol =
                compilation.GetTypeByMetadataName("System.ComponentModel.INotifyPropertyChanged");

            var classSymbols = classSymbol.GetContainerClassChains();


            CsharpCodeBuilder codeBuilder = new CsharpCodeBuilder();

            var allNamespaces = new HashSet <string>();

            allNamespaces.Add("System.ComponentModel");

            foreach (var usingNamespace in allNamespaces.OrderBy(p => p))
            {
                codeBuilder.AppendCodeLines($"using {usingNamespace};");
            }

            //codeBuilder.AppendCodeLines($@"using System.ComponentModel;");
            if (!classSymbol.ContainingNamespace.IsGlobalNamespace)
            {
                codeBuilder.AppendCodeLines($"namespace {classSymbol.ContainingNamespace.ToDisplayString()}");
                codeBuilder.BeginSegment();
            }

            foreach (var parentClass in classSymbols)
            {
                if (parentClass != classSymbol)
                {
                    codeBuilder.AppendCodeLines($@"partial class {parentClass.GetClassSymbolDisplayText()}");
                    codeBuilder.BeginSegment();
                }
            }


            if (!classSymbol.AllInterfaces.Contains(notifySymbol))
            {
                codeBuilder.AppendCodeLines(
                    $@"partial class {classSymbol.GetClassSymbolDisplayText()} : {notifySymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)}");
                codeBuilder.BeginSegment();
                codeBuilder.AppendCodeLines("public event PropertyChangedEventHandler PropertyChanged;");
            }
            else
            {
                codeBuilder.AppendCodeLines($@"partial class {classSymbol.Name}");
                codeBuilder.BeginSegment();
            }

            // create properties for each field
            foreach (IFieldSymbol fieldSymbol in fields)
            {
                ProcessField(codeBuilder, fieldSymbol, codeWriter);
            }

            codeBuilder.EndAllSegments();
            return(new CodeFile
            {
                BasicName = classSymbol.GetCodeFileBasicName(),
                Content = codeBuilder.ToString(),
            });
        }
예제 #8
0
        private static void ProcessField(CsharpCodeBuilder source, IFieldSymbol fieldSymbol, CodeWriter codeWriter)
        {
            // get the name and type of the field
            string      fieldName = fieldSymbol.Name;
            ITypeSymbol fieldType = fieldSymbol.Type;

            AttributeData attributeData = fieldSymbol.GetAttributes()
                                          .Single(p => p.AttributeClass.SafeEquals(typeof(AutoNotifyAttribute)));
            // get the AutoNotify attribute from the field, and any associated data

            TypedConstant overridenNameOpt =
                attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == nameof(AutoNotifyAttribute.PropertyName)).Value;

            string propertyName = chooseName(fieldName, overridenNameOpt);

            if (!System.Text.RegularExpressions.Regex.IsMatch(propertyName, "^[_a-zA-Z][_a-zA-Z0-9]*$"))
            {
                codeWriter.Context.ReportDiagnostic(KnifeDiagnostic.AutoNotify.InvalidPropertyName(propertyName));
            }
            if (propertyName == fieldName)
            {
                codeWriter.Context.ReportDiagnostic(KnifeDiagnostic.AutoNotify.PropertyNameEqualFieldName(propertyName));
            }

            source.AppendCodeLines($@"
public {fieldType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} {propertyName} 
{{
    get 
    {{
        return this.{fieldName};
    }}
    set
    {{
        if(this.{fieldName} != value)
        {{
            this.{fieldName} = value;
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof({propertyName})));
        }}
    }}
}}

");

            string chooseName(string field, TypedConstant overridenNameOption)
            {
                if (!overridenNameOption.IsNull)
                {
                    return(overridenNameOption.Value.ToString());
                }

                field = field.TrimStart('_');
                if (field.Length == 0)
                {
                    return(string.Empty);
                }

                if (field.Length == 1)
                {
                    return(field.ToUpperInvariant());
                }

                return(field.Substring(0, 1).ToUpperInvariant() + field.Substring(1));
            }
        }
예제 #9
0
 private void AppendUsingLines(INamedTypeSymbol _, CsharpCodeBuilder codeBuilder)
 {
     codeBuilder.AppendCodeLines("using System.Collections.Generic;");
     codeBuilder.AppendCodeLines("using System.Linq;");
 }