Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/project/list-of-diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
| __`SYSLIB1223`__ | Attributes deriving from JsonConverterAttribute are not supported by the source generator. |
| __`SYSLIB1224`__ | Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext. |
| __`SYSLIB1225`__ | Type includes ref like property, field or constructor parameter. |
| __`SYSLIB1226`__ | _`SYSLIB1220`-`SYSLIB1229` reserved for System.Text.Json.SourceGeneration._ |
| __`SYSLIB1226`__ | 'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations. |
| __`SYSLIB1227`__ | _`SYSLIB1220`-`SYSLIB1229` reserved for System.Text.Json.SourceGeneration._ |
| __`SYSLIB1228`__ | _`SYSLIB1220`-`SYSLIB1229` reserved for System.Text.Json.SourceGeneration._ |
| __`SYSLIB1229`__ | _`SYSLIB1220`-`SYSLIB1229` reserved for System.Text.Json.SourceGeneration._ |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ public KnownTypeSymbols(Compilation compilation)
public INamedTypeSymbol? JsonDerivedTypeAttributeType => GetOrResolveType("System.Text.Json.Serialization.JsonDerivedTypeAttribute", ref _JsonDerivedTypeAttributeType);
private Option<INamedTypeSymbol?> _JsonDerivedTypeAttributeType;

public INamedTypeSymbol? JsonIgnoreAttributeType => GetOrResolveType("System.Text.Json.Serialization.JsonIgnoreAttribute", ref _JsonIgnoreAttributeType);
private Option<INamedTypeSymbol?> _JsonIgnoreAttributeType;

public INamedTypeSymbol? JsonNumberHandlingAttributeType => GetOrResolveType("System.Text.Json.Serialization.JsonNumberHandlingAttribute", ref _JsonNumberHandlingAttributeType);
private Option<INamedTypeSymbol?> _JsonNumberHandlingAttributeType;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ internal static class DiagnosticDescriptors
category: JsonConstants.SystemTextJsonSourceGenerationName,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static DiagnosticDescriptor JsonIgnoreConditionAlwaysInvalidOnType { get; } = DiagnosticDescriptorHelper.Create(
id: "SYSLIB1226",
title: new LocalizableResourceString(nameof(SR.JsonIgnoreConditionAlwaysInvalidOnTypeTitle), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)),
messageFormat: new LocalizableResourceString(nameof(SR.JsonIgnoreConditionAlwaysInvalidOnTypeFormat), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)),
category: JsonConstants.SystemTextJsonSourceGenerationName,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);
}
}
}
39 changes: 38 additions & 1 deletion src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ private TypeGenerationSpec ParseTypeGenerationSpec(in TypeToGenerate typeToGener
out JsonNumberHandling? numberHandling,
out JsonUnmappedMemberHandling? unmappedMemberHandling,
out JsonObjectCreationHandling? preferredPropertyObjectCreationHandling,
out JsonIgnoreCondition? typeIgnoreCondition,
out bool foundJsonConverterAttribute,
out TypeRef? customConverterType,
out bool isPolymorphic);
Expand Down Expand Up @@ -691,7 +692,7 @@ private TypeGenerationSpec ParseTypeGenerationSpec(in TypeToGenerate typeToGener
implementsIJsonOnSerialized = _knownSymbols.IJsonOnSerializedType.IsAssignableFrom(type);

ctorParamSpecs = ParseConstructorParameters(typeToGenerate, constructor, out constructionStrategy, out constructorSetsRequiredMembers);
propertySpecs = ParsePropertyGenerationSpecs(contextType, typeToGenerate, options, out hasExtensionDataProperty, out fastPathPropertyIndices);
propertySpecs = ParsePropertyGenerationSpecs(contextType, typeToGenerate, typeIgnoreCondition, options, out hasExtensionDataProperty, out fastPathPropertyIndices);
propertyInitializerSpecs = ParsePropertyInitializers(ctorParamSpecs, propertySpecs, constructorSetsRequiredMembers, ref constructionStrategy);
}

Expand Down Expand Up @@ -748,13 +749,15 @@ private void ProcessTypeCustomAttributes(
out JsonNumberHandling? numberHandling,
out JsonUnmappedMemberHandling? unmappedMemberHandling,
out JsonObjectCreationHandling? objectCreationHandling,
out JsonIgnoreCondition? typeIgnoreCondition,
out bool foundJsonConverterAttribute,
out TypeRef? customConverterType,
out bool isPolymorphic)
{
numberHandling = null;
unmappedMemberHandling = null;
objectCreationHandling = null;
typeIgnoreCondition = null;
customConverterType = null;
foundJsonConverterAttribute = false;
isPolymorphic = false;
Expand Down Expand Up @@ -784,6 +787,27 @@ private void ProcessTypeCustomAttributes(
foundJsonConverterAttribute = true;
}

if (SymbolEqualityComparer.Default.Equals(attributeType, _knownSymbols.JsonIgnoreAttributeType))
{
ImmutableArray<KeyValuePair<string, TypedConstant>> namedArgs = attributeData.NamedArguments;

if (namedArgs.Length == 0)
{
typeIgnoreCondition = JsonIgnoreCondition.Always;
}
else if (namedArgs.Length == 1 &&
namedArgs[0].Value.Type?.ToDisplayString() == JsonIgnoreConditionFullName)
{
typeIgnoreCondition = (JsonIgnoreCondition)namedArgs[0].Value.Value!;
}

if (typeIgnoreCondition == JsonIgnoreCondition.Always)
{
ReportDiagnostic(DiagnosticDescriptors.JsonIgnoreConditionAlwaysInvalidOnType, typeToGenerate.Location, typeToGenerate.Type.ToDisplayString());
typeIgnoreCondition = null; // Reset so it doesn't affect properties
}
}

if (SymbolEqualityComparer.Default.Equals(attributeType, _knownSymbols.JsonDerivedTypeAttributeType))
{
Debug.Assert(attributeData.ConstructorArguments.Length > 0);
Expand Down Expand Up @@ -978,6 +1002,7 @@ private bool TryResolveCollectionType(
private List<PropertyGenerationSpec> ParsePropertyGenerationSpecs(
INamedTypeSymbol contextType,
in TypeToGenerate typeToGenerate,
JsonIgnoreCondition? typeIgnoreCondition,
SourceGenerationOptionsSpec? options,
out bool hasExtensionDataProperty,
out List<int>? fastPathPropertyIndices)
Expand Down Expand Up @@ -1060,6 +1085,7 @@ void AddMember(
typeLocation,
memberType,
memberInfo,
typeIgnoreCondition,
ref hasExtensionDataProperty,
generationMode,
options);
Expand Down Expand Up @@ -1208,6 +1234,7 @@ private bool IsValidDataExtensionPropertyType(ITypeSymbol type)
Location? typeLocation,
ITypeSymbol memberType,
ISymbol memberInfo,
JsonIgnoreCondition? typeIgnoreCondition,
ref bool typeHasExtensionDataProperty,
JsonSourceGenerationMode? generationMode,
SourceGenerationOptionsSpec? options)
Expand All @@ -1227,6 +1254,16 @@ private bool IsValidDataExtensionPropertyType(ITypeSymbol type)
out bool isExtensionData,
out bool hasJsonRequiredAttribute);

// Fall back to the type-level [JsonIgnore] if no member-level attribute is specified.
// WhenWritingNull is invalid for non-nullable value types; treat as Never in that case
// so that the type-level annotation still overrides the global JSO DefaultIgnoreCondition.
if (ignoreCondition is null && typeIgnoreCondition is not null)
{
ignoreCondition = typeIgnoreCondition == JsonIgnoreCondition.WhenWritingNull && !memberType.IsNullableType()
? JsonIgnoreCondition.Never
: typeIgnoreCondition;
}

ProcessMember(
contextType,
memberInfo,
Expand Down
6 changes: 6 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,10 @@
<data name="TypeContainsRefLikeMemberFormat" xml:space="preserve">
<value>The type '{0}' includes the ref like property, field or constructor parameter '{1}'. No source code will be generated for the property, field or constructor.</value>
</data>
<data name="JsonIgnoreConditionAlwaysInvalidOnTypeTitle" xml:space="preserve">
<value>'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</value>
</data>
<data name="JsonIgnoreConditionAlwaysInvalidOnTypeFormat" xml:space="preserve">
<value>The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</value>
</data>
</root>
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@
<target state="translated">JsonConverterAttribute.Type obsahuje neplatný nebo nepřístupný argument.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeFormat">
<source>The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</source>
<target state="new">The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeTitle">
<source>'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</source>
<target state="new">'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</target>
<note />
</trans-unit>
<trans-unit id="JsonSerializableAttributeOnNonContextTypeMessageFormat">
<source>The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</source>
<target state="translated">Typ „{0}“ byl anotován atributem JsonSerializableAttribute, ale není odvozen od třídy JsonSerializerContext. Nebude vygenerován žádný zdrojový kód.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@
<target state="translated">"JsonConverterAttribute.Type" enthält ein ungültiges oder nicht zugängliches Argument.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeFormat">
<source>The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</source>
<target state="new">The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeTitle">
<source>'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</source>
<target state="new">'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</target>
<note />
</trans-unit>
<trans-unit id="JsonSerializableAttributeOnNonContextTypeMessageFormat">
<source>The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</source>
<target state="translated">Der Typ "{0}" wurde mit JsonSerializableAttribute kommentiert, ist aber nicht von JsonSerializerContext abgeleitet. Es wird kein Quellcode generiert.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@
<target state="translated">“JsonConverterAttribute.Type” contiene un argumento no válido o inaccesible.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeFormat">
<source>The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</source>
<target state="new">The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeTitle">
<source>'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</source>
<target state="new">'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</target>
<note />
</trans-unit>
<trans-unit id="JsonSerializableAttributeOnNonContextTypeMessageFormat">
<source>The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</source>
<target state="translated">El tipo "{0}" se ha anotado con JsonSerializableAttribute, pero no se deriva de JsonSerializerContext. No se generará ningún código fuente.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@
<target state="translated">'JsonConverterAttribute.Type' contient un argument non valide ou inaccessible.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeFormat">
<source>The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</source>
<target state="new">The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeTitle">
<source>'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</source>
<target state="new">'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</target>
<note />
</trans-unit>
<trans-unit id="JsonSerializableAttributeOnNonContextTypeMessageFormat">
<source>The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</source>
<target state="translated">Le type '{0}' a été annoté avec l'attribut JsonSerializable mais ne dérive pas de JsonSerializerContext. Aucun code source ne sera généré.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@
<target state="translated">'JsonConverterAttribute.Type' contiene un argomento non valido o inaccessibile.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeFormat">
<source>The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</source>
<target state="new">The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeTitle">
<source>'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</source>
<target state="new">'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</target>
<note />
</trans-unit>
<trans-unit id="JsonSerializableAttributeOnNonContextTypeMessageFormat">
<source>The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</source>
<target state="translated">Il tipo '{0}' è stato annotato con JsonSerializableAttribute ma non deriva da JsonSerializerContext. Non verrà generato alcun codice sorgente.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@
<target state="translated">'JsonConverterAttribute.Type' に無効な、またはアクセスできない引数が含まれています。</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeFormat">
<source>The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</source>
<target state="new">The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeTitle">
<source>'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</source>
<target state="new">'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</target>
<note />
</trans-unit>
<trans-unit id="JsonSerializableAttributeOnNonContextTypeMessageFormat">
<source>The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</source>
<target state="translated">型 '{0}' は JsonSerializableAttribute で注釈が付けられていますが、JsonSerializerContext から派生したものではありません。ソース コードは生成されません。</target>
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@
<target state="translated">'JsonConverterAttribute.Type'에 잘못되었거나 액세스할 수 없는 인수가 포함되어 있습니다.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeFormat">
<source>The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</source>
<target state="new">The type '{0}' has been annotated with 'JsonIgnoreAttribute' using 'JsonIgnoreCondition.Always' which is not valid on type declarations. The attribute will be ignored.</target>
<note />
</trans-unit>
<trans-unit id="JsonIgnoreConditionAlwaysInvalidOnTypeTitle">
<source>'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</source>
<target state="new">'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations.</target>
<note />
</trans-unit>
<trans-unit id="JsonSerializableAttributeOnNonContextTypeMessageFormat">
<source>The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</source>
<target state="translated">'{0}' 형식에 JsonSerializableAttribute 주석이 추가되었지만 JsonSerializerContext에서 파생되지 않았습니다. 소스 코드가 생성되지 않습니다.</target>
Expand Down
Loading
Loading