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)); } }
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; }