Beispiel #1
0
        private void ProcessField(StringBuilder source, IndentUtil indent, IFieldSymbol fieldSymbol, ISymbol attributeSymbol)
        {
            // get the name and type of the field
            string      fieldName = fieldSymbol.Name;
            ITypeSymbol fieldType = fieldSymbol.Type;

            // get the AutoNotify attribute from the field, and any associated data
            AttributeData attributeData    = fieldSymbol.GetAttributes().Single(ad => ad.AttributeClass.Equals(attributeSymbol, SymbolEqualityComparer.Default));
            TypedConstant overridenNameOpt = attributeData.NamedArguments.SingleOrDefault(kvp => kvp.Key == "PropertyName").Value;

            string propertyName = chooseName(fieldName, overridenNameOpt);

            if (propertyName.Length == 0 || propertyName == fieldName)
            {
                //TODO: issue a diagnostic that we can't process this field
                return;
            }

            source.AppendLine($@"
{indent.Value}public {fieldType} {propertyName} 
{indent.Value}{{
{indent.Value2}get 
{indent.Value2}{{
{indent.Value3}return this.{fieldName};
{indent.Value2}}}

{indent.Value2}set
{indent.Value2}{{
{indent.Value3}this.{fieldName} = value;
{indent.Value3}this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof({propertyName})));
{indent.Value2}}}
{indent.Value}}}");

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

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

                if (fieldName.Length == 1)
                {
                    return(fieldName.ToUpper());
                }

                return(fieldName.Substring(0, 1).ToUpper() + fieldName.Substring(1));
            }
        }
Beispiel #2
0
        private string ProcessClass(INamedTypeSymbol classSymbol, List <IFieldSymbol> fields, ISymbol attributeSymbol, ISymbol notifySymbol, GeneratorExecutionContext context)
        {
            if (!classSymbol.ContainingSymbol.Equals(classSymbol.ContainingNamespace, SymbolEqualityComparer.Default))
            {
                return(null); //TODO: issue a diagnostic that it must be top level
            }

            var builder         = new StringBuilder();
            var indent          = new IndentUtil();
            var namespaceSymbol = classSymbol.ContainingNamespace;

            if (!namespaceSymbol.IsGlobalNamespace)
            {
                builder.AppendLine($@"namespace {namespaceSymbol.Name}
{{");
                indent.IncreaseSimple();
            }


            builder.AppendLine($@"
{indent.Value}public partial class {classSymbol.Name} : {notifySymbol.ToDisplayString()}
{indent.Value}{{");

            using var marker = indent.Increase();
            // if the class doesn't implement INotifyPropertyChanged already, add it
            if (!classSymbol.Interfaces.Contains(notifySymbol))
            {
                builder.Append($"{indent.Value}public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;");
            }

            // create properties for each field
            foreach (IFieldSymbol fieldSymbol in fields)
            {
                ProcessField(builder, indent, fieldSymbol, attributeSymbol);
            }

            marker.Revert();
            builder.Append($"{indent.Value}}}");

            if (!namespaceSymbol.IsGlobalNamespace)
            {
                indent.Decrease();
                builder.AppendLine("}");
            }

            return(builder.ToString());
        }
 public Marker(IndentUtil indentUtil, int count)
 {
     _util  = indentUtil;
     _count = count;
 }