public static void Emit(EmitPhase phase, RecordProperty prop, StringBuilder output) { string typeName = (prop.IsValueType || prop.Nullable == Microsoft.CodeAnalysis.NullableAnnotation.NotAnnotated) ? prop.FullTypeName : prop.FullTypeName + "?"; switch (phase) { case EmitPhase.Interface: output.AppendLine($" {typeName} {prop.PropertyName} {{get; set;}}"); break; case EmitPhase.PropImplementation: output.AppendLine($" protected {typeName} {Names.PropPrefix}{prop.PropertyName};"); output.AppendLine($" public {typeName} {prop.PropertyName}"); output.AppendLine(" {"); output.AppendLine($" get => {Names.PropPrefix}{prop.PropertyName};"); output.AppendLine(" set"); output.AppendLine(" {"); output.AppendLine($" {Names.SetDirtyMethod}();"); output.AppendLine($" {Names.PropPrefix}{prop.PropertyName} = value;"); output.AppendLine(" }"); output.AppendLine(" }"); break; case EmitPhase.Constructor: output.AppendLine($" {Names.PropPrefix}{prop.PropertyName} = value.{prop.PropertyName};"); break; case EmitPhase.Finish: output.AppendLine($" {prop.PropertyName} = {Names.PropPrefix}{prop.PropertyName},"); break; } }
public static void Emit(EmitPhase phase, RecordProperty prop, StringBuilder output) { var imProp = Names.PropPrefix + "o_" + prop.PropertyName; var builderProp = Names.PropPrefix + "b_" + prop.PropertyName; switch (phase) { case EmitPhase.Interface: output.AppendLine($" {prop.FullTypeName}.Builder {prop.PropertyName} {{get;}}"); break; case EmitPhase.PropImplementation: if (prop.Nullable == Microsoft.CodeAnalysis.NullableAnnotation.NotAnnotated) { output.AppendLine($" protected {prop.FullTypeName} {imProp};"); } else { output.AppendLine($" protected {prop.FullTypeName}? {imProp};"); } output.AppendLine($" private {prop.FullTypeName}.Builder? {builderProp} = null;"); output.AppendLine($" public {prop.FullTypeName}.Builder {prop.PropertyName}"); output.AppendLine(" {"); output.AppendLine(" get"); output.AppendLine(" {"); output.AppendLine($" if ({builderProp} == null) {{"); if (prop.FullTypeName.StartsWith("global::System.Collections.Immutable.ImmutableArray")) { // ImmutableArray is a struct and need to use IsDefault to check null output.AppendLine($" {builderProp} = {imProp}.IsDefault ? {prop.FullTypeName}.Empty.ToBuilder() : {imProp}.ToBuilder();"); } else { output.AppendLine($" {builderProp} = ({imProp} ?? {prop.FullTypeName}.Empty).ToBuilder();"); } output.AppendLine($" {Names.AddCheckDirtyMethod}(() => {{"); output.AppendLine($" var newVal = {builderProp}.ToImmutable();"); output.AppendLine($" if (!object.ReferenceEquals(newVal, {imProp})) {{"); output.AppendLine($" {Names.SetDirtyMethod}();"); output.AppendLine($" {imProp} = newVal;"); output.AppendLine(" }"); output.AppendLine($" {builderProp} = null;"); output.AppendLine(" });"); output.AppendLine(" }"); output.AppendLine($" return {builderProp};"); output.AppendLine(" }"); output.AppendLine(" }"); break; case EmitPhase.Constructor: output.AppendLine($" {imProp} = value.{prop.PropertyName};"); break; case EmitPhase.Finish: // The CheckDirty method above is called before Finish, and sets any changes back into imProp output.AppendLine($" {prop.PropertyName} = {imProp},"); break; } }
public static void Emit(EmitPhase phase, DraftableRecord record, RecordProperty prop, StringBuilder output) { if (prop.Nullable == Microsoft.CodeAnalysis.NullableAnnotation.NotAnnotated) { EmitNonNullable(phase, record, prop, output); } else { EmitNullable(phase, record, prop, output); } }
private static void EmitNullable(EmitPhase phase, DraftableRecord record, RecordProperty prop, StringBuilder output) { var propRecord = prop.TypeIsDraftable; var createdPropName = Names.PropPrefix + "creat_" + prop.PropertyName; var draftPropName = Names.PropPrefix + "draft_" + prop.PropertyName; var originalProp = $"((({record.FullyQualifiedRecordName}){Names.OriginalProp}).{prop.PropertyName})"; switch (phase) { case EmitPhase.Interface: output.AppendLine($" {propRecord.FullyQualifiedInterfaceName}? {prop.PropertyName} {{get;}}"); output.AppendLine($" {propRecord.FullyQualifiedInterfaceName}? Set{prop.PropertyName}({prop.FullTypeName}? value);"); break; case EmitPhase.PropImplementation: output.AppendLine($" protected bool {createdPropName} = false;"); output.AppendLine($" protected {propRecord.FullyQualifiedDraftInstanceClassName}? {draftPropName} = null;"); output.AppendLine($" public {propRecord.FullyQualifiedInterfaceName}? {prop.PropertyName}"); output.AppendLine(" {"); output.AppendLine($" get {{"); output.AppendLine($" if (!{createdPropName}) {{"); output.AppendLine($" {createdPropName} = true;"); output.AppendLine($" var original = {originalProp};"); output.AppendLine($" if (original != null) {{"); output.AppendLine($" {draftPropName} = new {propRecord.FullyQualifiedDraftInstanceClassName}(original, this);"); output.AppendLine(" }"); // close if checking original prop not null output.AppendLine(" }"); // close if checking not created output.AppendLine($" return {draftPropName};"); output.AppendLine(" }"); // close get output.AppendLine(" }"); output.AppendLine($" public {propRecord.FullyQualifiedInterfaceName}? Set{prop.PropertyName}({prop.FullTypeName}? value)"); output.AppendLine(" {"); output.AppendLine($" {Names.SetDirtyMethod}();"); output.AppendLine($" {createdPropName} = true;"); output.AppendLine($" {draftPropName} = value == null ? null : new {propRecord.FullyQualifiedDraftInstanceClassName}(value, this);"); output.AppendLine($" return {draftPropName};"); output.AppendLine(" }"); break; case EmitPhase.Constructor: // nothing needed here, not initialized until the first get break; case EmitPhase.Finish: output.AppendLine($" {prop.PropertyName} = {createdPropName} ? {draftPropName}?.{Names.FinishMethod}() : {originalProp},"); break; } }
private void EmitProperties(EmitPhase phase, DraftableRecord rds, StringBuilder output) { foreach (var prop in rds.Properties) { if (prop.TypeIsDraftable != null) { PropDraftable.Emit(phase, rds, prop, output); } else if (prop.IsImmutableCollection) { PropImmutableCollection.Emit(phase, prop, output); } else { PropNonDraftable.Emit(phase, prop, output); } } }