@@ -68,9 +68,13 @@ private ICollection<OutputProperty> GetProperties(Type type)
6868 var getter = property . GetGetMethod ( false ) ;
6969 if ( getter is null ) continue ;
7070
71+ // Check if we have a setter
72+ var setter = property . GetSetMethod ( false ) ;
73+ var isReadonly = ! property . CanWrite || setter is null ;
74+
7175 var destinationName = GetDestinationName ( property . Name ) ;
72- var destinationType = GetDestinationType ( property . PropertyType , property . CustomAttributes ) ;
73- outputProperties . Add ( new OutputProperty ( property . Name , property . PropertyType , destinationType . InnerType , destinationName , destinationType . TypeName , destinationType . ImportType , destinationType . IsBuiltin , destinationType . IsArray , TypeChecks . IsNullable ( property . PropertyType ) ) ) ;
76+ var destinationType = GetDestinationType ( property . PropertyType , property . CustomAttributes , isReadonly ) ;
77+ outputProperties . Add ( new OutputProperty ( property . Name , property . PropertyType , destinationType . InnerType , destinationName , destinationType . TypeName , destinationType . ImportType , destinationType . IsBuiltin , destinationType . IsArray , TypeChecks . IsNullable ( property . PropertyType ) , destinationType . IsReadonly ) ) ;
7478 }
7579
7680 // Look at base classes
@@ -86,57 +90,57 @@ private ICollection<OutputProperty> GetProperties(Type type)
8690
8791 private static string GetDestinationName ( string name ) => name . ToTypeScriptName ( ) ;
8892
89- private DestinationType GetDestinationType ( in Type sourceType , IEnumerable < CustomAttributeData > customAttributes )
93+ private DestinationType GetDestinationType ( in Type sourceType , IEnumerable < CustomAttributeData > customAttributes , bool isReadonly )
9094 {
9195 if ( _configuration . TypeMaps . TryGetValue ( sourceType . FullName ! , out string ? destType ) )
92- return new DestinationType ( destType , true , false , null ) ;
96+ return new DestinationType ( destType , true , false , isReadonly , null ) ;
9397
9498 if ( CustomMappedTypes . TryGetValue ( sourceType , out OutputType ? customType ) )
95- return new DestinationType ( customType . Name , false , false , null ) ;
99+ return new DestinationType ( customType . Name , false , false , isReadonly , null ) ;
96100
97101 if ( TypeChecks . ImplementsIDictionary ( sourceType ) )
98102 {
99- var keyType = GetDestinationType ( TypeChecks . GetGenericType ( sourceType , 0 ) , customAttributes ) ;
103+ var keyType = GetDestinationType ( TypeChecks . GetGenericType ( sourceType , 0 ) , customAttributes , isReadonly ) ;
100104 var valueType = TypeChecks . GetGenericType ( sourceType , 1 ) ;
101- var valueDestinationType = GetDestinationType ( valueType , customAttributes ) ;
105+ var valueDestinationType = GetDestinationType ( valueType , customAttributes , isReadonly ) ;
102106
103107 var isBuiltin = keyType . IsBuiltin && valueDestinationType . IsBuiltin ;
104108
105- return new DestinationType ( $ "{{ [key: { keyType . TypeName } ]: { valueDestinationType . FullTypeName } }}", isBuiltin , false , valueType , valueDestinationType . TypeName ) ;
109+ return new DestinationType ( $ "{{ [key: { keyType . TypeName } ]: { valueDestinationType . FullTypeName } }}", isBuiltin , false , isReadonly , valueType , valueDestinationType . TypeName ) ;
106110 }
107111
108112 if ( TypeChecks . ImplementsIEnumerable ( sourceType ) )
109113 {
110114 var innerType = TypeChecks . GetGenericType ( sourceType ) ;
111115
112- var ( TypeName , _, IsBuiltin , _, _) = GetDestinationType ( innerType , customAttributes ) ;
113- return new DestinationType ( TypeName , IsBuiltin , true , innerType ) ;
116+ var ( TypeName , _, IsBuiltin , _, IsReadonly , _) = GetDestinationType ( innerType , customAttributes , isReadonly ) ;
117+ return new DestinationType ( TypeName , IsBuiltin , true , IsReadonly , innerType ) ;
114118 }
115119
116120 if ( TypeChecks . IsValueTuple ( sourceType ) )
117121 {
118122 var arguments = sourceType . GenericTypeArguments ;
119- var argumentDestinationTypes = arguments . Select ( arg => GetDestinationType ( arg , customAttributes ) ) ;
123+ var argumentDestinationTypes = arguments . Select ( arg => GetDestinationType ( arg , customAttributes , isReadonly ) ) ;
120124 var isBuiltin = argumentDestinationTypes . All ( arg => arg . IsBuiltin ) ;
121125
122126 var argumentList = argumentDestinationTypes . Select ( ( arg , idx ) => $ "item{ idx + 1 } : { arg . FullTypeName } ") ;
123127 var typeName = $ "{{ { string . Join ( ", " , argumentList ) } }}";
124128
125- return new DestinationType ( typeName , isBuiltin , false , null ) ;
129+ return new DestinationType ( typeName , isBuiltin , false , isReadonly , null ) ;
126130 }
127131
128132 if ( TypeChecks . IsNullable ( sourceType ) )
129133 {
130- return GetDestinationType ( sourceType . GenericTypeArguments . First ( ) , customAttributes ) ;
134+ return GetDestinationType ( sourceType . GenericTypeArguments . First ( ) , customAttributes , isReadonly ) ;
131135 }
132136
133137 if ( customAttributes . Any ( x => x . AttributeType . FullName == "System.Runtime.CompilerServices.DynamicAttribute" ) )
134- return new DestinationType ( DestinationTypes . Dynamic , true , false , null ) ;
138+ return new DestinationType ( DestinationTypes . Dynamic , true , false , isReadonly , null ) ;
135139
136140 // FIXME: Check if this is one of our types?
137141 var outputType = Convert ( sourceType ) ;
138142 CustomMappedTypes . Add ( sourceType , outputType ) ;
139- return new DestinationType ( outputType . Name , false , false , null ) ;
143+ return new DestinationType ( outputType . Name , false , false , isReadonly , null ) ;
140144
141145 // throw new ArgumentException($"Unexpected type: {sourceType}");
142146 }
0 commit comments