Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[System.Text.Json] Improve error handling of ref structs, including collection types with ref struct elements. #106083

Merged
merged 4 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -263,7 +263,7 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
| __`SYSLIB1222`__ | Constructor annotated with JsonConstructorAttribute is inaccessible. |
| __`SYSLIB1223`__ | Attributes deriving from JsonConverterAttribute are not supported by the source generator. |
| __`SYSLIB1224`__ | Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext. |
| __`SYSLIB1225`__ | *`SYSLIB1220`-`SYSLIB1229` reserved for System.Text.Json.SourceGeneration.* |
| __`SYSLIB1225`__ | Type includes ref like property, field or constructor parameter. |
eiriktsarpalis marked this conversation as resolved.
Show resolved Hide resolved
| __`SYSLIB1226`__ | *`SYSLIB1220`-`SYSLIB1229` reserved for System.Text.Json.SourceGeneration.* |
| __`SYSLIB1227`__ | *`SYSLIB1220`-`SYSLIB1229` reserved for System.Text.Json.SourceGeneration.* |
| __`SYSLIB1228`__ | *`SYSLIB1220`-`SYSLIB1229` reserved for System.Text.Json.SourceGeneration.* |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ internal static class DiagnosticDescriptors
category: JsonConstants.SystemTextJsonSourceGenerationName,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);

public static DiagnosticDescriptor TypeContainsRefLikeMember { get; } = DiagnosticDescriptorHelper.Create(
id: "SYSLIB1225",
title: new LocalizableResourceString(nameof(SR.TypeContainsRefLikeMemberTitle), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)),
messageFormat: new LocalizableResourceString(nameof(SR.TypeContainsRefLikeMemberFormat), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)),
category: JsonConstants.SystemTextJsonSourceGenerationName,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true);
}
}
}
36 changes: 30 additions & 6 deletions src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ private TypeGenerationSpec ParseTypeGenerationSpec(in TypeToGenerate typeToGener
out TypeRef? customConverterType,
out bool isPolymorphic);

if (type is INamedTypeSymbol { IsUnboundGenericType: true } or IErrorTypeSymbol)
if (type is { IsRefLikeType: true } or INamedTypeSymbol { IsUnboundGenericType: true } or IErrorTypeSymbol)
{
classType = ClassType.TypeUnsupportedBySourceGen;
}
Expand Down Expand Up @@ -574,6 +574,12 @@ private TypeGenerationSpec ParseTypeGenerationSpec(in TypeToGenerate typeToGener
immutableCollectionFactoryTypeFullName = null;
collectionType = default;
}
else if (valueType.IsRefLikeType || keyType?.IsRefLikeType is true)
{
classType = ClassType.TypeUnsupportedBySourceGen;
immutableCollectionFactoryTypeFullName = null;
collectionType = default;
}
else
{
if (type.CanUseDefaultConstructorForDeserialization(out IMethodSymbol? defaultCtor))
Expand Down Expand Up @@ -1157,13 +1163,23 @@ private bool IsValidDataExtensionPropertyType(ITypeSymbol type)
}

if ((!canUseGetter && !canUseSetter && !hasJsonIncludeButIsInaccessible) ||
!IsSymbolAccessibleWithin(memberType, within: contextType) ||
(memberType.IsRefLikeType && ignoreCondition is JsonIgnoreCondition.Always))
!IsSymbolAccessibleWithin(memberType, within: contextType))
{
// Skip the member if either of the two conditions hold
// 1. Member has no accessible getters or setters (but is not marked with JsonIncludeAttribute since we need to throw a runtime exception) OR
// 2. The member type is not accessible within the generated context OR
eiriktsarpalis marked this conversation as resolved.
Show resolved Hide resolved
// 3. The member is of a ref-like type that is also ignored (we keep all other ignored members for backward compat)
return null;
}

if (memberType.IsRefLikeType)
{
// Skip all ref-like members and emit a diagnostic
// unless the property is being explicitly ignored.
eiriktsarpalis marked this conversation as resolved.
Show resolved Hide resolved
if (ignoreCondition is not JsonIgnoreCondition.Always)
{
ReportDiagnostic(DiagnosticDescriptors.TypeContainsRefLikeMember, memberInfo.GetLocation(), declaringType.Name, memberInfo.Name);
}

return null;
}

Expand Down Expand Up @@ -1433,7 +1449,7 @@ private void ProcessMember(
if (paramCount == 0)
{
constructionStrategy = ObjectConstructionStrategy.ParameterlessConstructor;
constructorParameters = Array.Empty<ParameterGenerationSpec>();
constructorParameters = [];
}
else
{
Expand All @@ -1445,6 +1461,14 @@ private void ProcessMember(
for (int i = 0; i < paramCount; i++)
{
IParameterSymbol parameterInfo = constructor.Parameters[i];

if (parameterInfo.Type.IsRefLikeType)
{
ReportDiagnostic(DiagnosticDescriptors.TypeContainsRefLikeMember, parameterInfo.GetLocation(), type.Name, parameterInfo.Name);
constructionStrategy = ObjectConstructionStrategy.NotApplicable;
continue;
}

TypeRef parameterTypeRef = EnqueueType(parameterInfo.Type, typeToGenerate.Mode);

constructorParameters[i] = new ParameterGenerationSpec
Expand All @@ -1459,7 +1483,7 @@ private void ProcessMember(
}
}

return constructorParameters;
return constructionStrategy is ObjectConstructionStrategy.NotApplicable ? null : constructorParameters;
}

private List<PropertyInitializerGenerationSpec>? ParsePropertyInitializers(
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 @@ -207,4 +207,10 @@
<data name="JsonSerializableAttributeOnNonContextTypeMessageFormat" xml:space="preserve">
<value>The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</value>
</data>
<data name="TypeContainsRefLikeMemberTitle" xml:space="preserve">
<value>Type includes ref like property, field or constructor parameter.</value>
</data>
<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>
</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 @@ -142,6 +142,16 @@
<target state="translated">Typ obsahuje více členů s komentářem JsonExtensionDataAttribute</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
eiriktsarpalis marked this conversation as resolved.
Show resolved Hide resolved
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">Nevygenerovala se metadata serializace pro typ {0}.</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 @@ -142,6 +142,16 @@
<target state="translated">Der Typ enthält mehrere Elemente, die mit dem JsonExtensionDataAttribute versehen sind.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">Die Serialisierungsmetadaten für den Typ "{0}" wurden nicht 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 @@ -142,6 +142,16 @@
<target state="translated">El tipo tiene varios miembros anotados con JsonExtensionDataAttribute.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">No generó metadatos de serialización para el tipo '{0}".</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 @@ -142,6 +142,16 @@
<target state="translated">Le type comporte plusieurs membres annotés avec JsonExtensionDataAttribute.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">Les métadonnées de sérialisation pour le type « {0} » n’ont pas été générées.</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 @@ -142,6 +142,16 @@
<target state="translated">Nel tipo sono presenti più membri annotati con JsonExtensionDataAttribute.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">Non sono stati generati metadati di serializzazione per il tipo '{0}'.</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 @@ -142,6 +142,16 @@
<target state="translated">型には、'JsonExtensionDataAttribute' に注釈が付けられた複数のメンバーが含まれます。</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">'{0}'型 のシリアル化メタデータを生成ませんでした。</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 @@ -142,6 +142,16 @@
<target state="translated">형식에 JsonExtensionDataAttribute로 주석이 추가 된 멤버가 여러 개 있습니다.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">'{0}' 형식에 대한 직렬화 메타데이터가 생성되지 않았습니다.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@
<target state="translated">Typ ma wiele składowych opatrzonych adnotacjami za pomocą atrybutu JsonExtensionDataAttribute.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">Nie wygenerowano metadanych serializacji dla typu „{0}”.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@
<target state="translated">Tipo tem vários membros anotados com JsonExtensionDataAttribute.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">Não gerou metadados de serialização para o tipo '{0}'.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@
<target state="translated">Тип содержит несколько элементов, помеченных с помощью JsonExtensionDataAttribute.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">Метаданные сериализации для типа "{0}" не сформированы.</target>
Expand Down
10 changes: 10 additions & 0 deletions src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,16 @@
<target state="translated">Tür, JsonExtensionDataAttribute ile açıklanan birden çok üyeye sahip.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberFormat">
<source>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.</source>
<target state="new">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.</target>
<note />
</trans-unit>
<trans-unit id="TypeContainsRefLikeMemberTitle">
<source>Type includes ref like property, field or constructor parameter.</source>
<target state="new">Type includes ref like property, field or constructor parameter.</target>
<note />
</trans-unit>
<trans-unit id="TypeNotSupportedMessageFormat">
<source>Did not generate serialization metadata for type '{0}'.</source>
<target state="translated">'{0}' türü için serileştirme meta verileri oluşturulmadı.</target>
Expand Down
Loading
Loading