Ensure System.Text.Json SG diagnostics don't use Location values from referenced...
authorEirik Tsarpalis <eirik.tsarpalis@gmail.com>
Thu, 27 Jul 2023 12:13:27 +0000 (13:13 +0100)
committerGitHub <noreply@github.com>
Thu, 27 Jul 2023 12:13:27 +0000 (13:13 +0100)
20 files changed:
docs/project/list-of-diagnostics.md
src/libraries/System.Text.Json/gen/Helpers/RoslynExtensions.cs
src/libraries/System.Text.Json/gen/JsonSourceGenerator.DiagnosticDescriptors.cs
src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs
src/libraries/System.Text.Json/gen/Resources/Strings.resx
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf
src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorIncrementalTests.cs

index b412207..7ea3ee4 100644 (file)
@@ -258,7 +258,7 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
 |  __`SYSLIB1221`__ | JsonSourceGenerator does not support this C# language version. |
 |  __`SYSLIB1222`__ | Constructor annotated with JsonConstructorAttribute is inaccessible. |
 |  __`SYSLIB1223`__ | Attributes deriving from JsonConverterAttribute are not supported by the source generator. |
-|  __`SYSLIB1224`__ | *`SYSLIB1220`-`SYSLIB229` reserved for System.Text.Json.SourceGeneration.* |
+|  __`SYSLIB1224`__ | Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext. |
 |  __`SYSLIB1225`__ | *`SYSLIB1220`-`SYSLIB229` reserved for System.Text.Json.SourceGeneration.* |
 |  __`SYSLIB1226`__ | *`SYSLIB1220`-`SYSLIB229` reserved for System.Text.Json.SourceGeneration.* |
 |  __`SYSLIB1227`__ | *`SYSLIB1220`-`SYSLIB229` reserved for System.Text.Json.SourceGeneration.* |
index 695bc01..b0cb90e 100644 (file)
@@ -27,10 +27,10 @@ namespace System.Text.Json.SourceGeneration
 
         public static string GetFullyQualifiedName(this ITypeSymbol type) => type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
 
-        public static Location? GetDiagnosticLocation(this ISymbol typeSymbol)
+        public static Location? GetLocation(this ISymbol typeSymbol)
             => typeSymbol.Locations.Length > 0 ? typeSymbol.Locations[0] : null;
 
-        public static Location? GetDiagnosticLocation(this AttributeData attributeData)
+        public static Location? GetLocation(this AttributeData attributeData)
         {
             SyntaxReference? reference = attributeData.ApplicationSyntaxReference;
             return reference?.SyntaxTree.GetLocation(reference.Span);
@@ -39,9 +39,14 @@ namespace System.Text.Json.SourceGeneration
         /// <summary>
         /// Creates a copy of the Location instance that does not capture a reference to Compilation.
         /// </summary>
-        [return: NotNullIfNotNull(nameof(location))]
-        public static Location? GetTrimmedLocation(this Location? location)
-            => location is null ? null : Location.Create(location.SourceTree?.FilePath ?? "", location.SourceSpan, location.GetLineSpan().Span);
+        public static Location GetTrimmedLocation(this Location location)
+            => Location.Create(location.SourceTree?.FilePath ?? "", location.SourceSpan, location.GetLineSpan().Span);
+
+        /// <summary>
+        /// Returns true if the specified location is contained in one of the syntax trees in the compilation.
+        /// </summary>
+        public static bool ContainsLocation(this Compilation compilation, Location location)
+            => location.SourceTree != null && compilation.ContainsSyntaxTree(location.SourceTree);
 
         /// <summary>
         /// Removes any type metadata that is erased at compile time, such as NRT annotations and tuple labels.
index 000acd0..9f1947a 100644 (file)
@@ -114,6 +114,14 @@ namespace System.Text.Json.SourceGeneration
                 category: JsonConstants.SystemTextJsonSourceGenerationName,
                 defaultSeverity: DiagnosticSeverity.Warning,
                 isEnabledByDefault: true);
+
+            public static DiagnosticDescriptor JsonSerializableAttributeOnNonContextType { get; } = new DiagnosticDescriptor(
+                id: "SYSLIB1224",
+                title: new LocalizableResourceString(nameof(SR.JsonSerializableAttributeOnNonContextTypeTitle), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)),
+                messageFormat: new LocalizableResourceString(nameof(SR.JsonSerializableAttributeOnNonContextTypeMessageFormat), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)),
+                category: JsonConstants.SystemTextJsonSourceGenerationName,
+                defaultSeverity: DiagnosticSeverity.Warning,
+                isEnabledByDefault: true);
         }
     }
 }
index 24ac7cc..3242dcc 100644 (file)
@@ -47,9 +47,18 @@ namespace System.Text.Json.SourceGeneration
 #pragma warning restore
 
             public List<DiagnosticInfo> Diagnostics { get; } = new();
+            private Location? _contextClassLocation;
 
             public void ReportDiagnostic(DiagnosticDescriptor descriptor, Location? location, params object?[]? messageArgs)
             {
+                Debug.Assert(_contextClassLocation != null);
+
+                if (location is null || !_knownSymbols.Compilation.ContainsLocation(location))
+                {
+                    // If location is null or is a location outside of the current compilation, fall back to the location of the context class.
+                    location = _contextClassLocation;
+                }
+
                 Diagnostics.Add(new DiagnosticInfo
                 {
                     Descriptor = descriptor,
@@ -82,50 +91,53 @@ namespace System.Text.Json.SourceGeneration
                 // Ensure context-scoped metadata caches are empty.
                 Debug.Assert(_typesToGenerate.Count == 0);
                 Debug.Assert(_generatedTypes.Count == 0);
+                Debug.Assert(_contextClassLocation is null);
 
                 INamedTypeSymbol? contextTypeSymbol = semanticModel.GetDeclaredSymbol(contextClassDeclaration, cancellationToken);
                 Debug.Assert(contextTypeSymbol != null);
 
+                _contextClassLocation = contextTypeSymbol.GetLocation();
+                Debug.Assert(_contextClassLocation is not null);
+
                 if (!_knownSymbols.JsonSerializerContextType.IsAssignableFrom(contextTypeSymbol))
                 {
+                    ReportDiagnostic(DiagnosticDescriptors.JsonSerializableAttributeOnNonContextType, _contextClassLocation, contextTypeSymbol.ToDisplayString());
                     return null;
                 }
 
-                if (!TryParseJsonSerializerContextAttributes(
-                    contextTypeSymbol,
+                ParseJsonSerializerContextAttributes(contextTypeSymbol,
                     out List<TypeToGenerate>? rootSerializableTypes,
-                    out SourceGenerationOptionsSpec? options))
-                {
-                    // Context does not specify any source gen attributes.
-                    return null;
-                }
+                    out SourceGenerationOptionsSpec? options);
 
                 if (rootSerializableTypes is null)
                 {
-                    // No types were indicated with [JsonSerializable]
+                    // No types were annotated with JsonSerializableAttribute.
+                    // Can only be reached if a [JsonSerializable(null)] declaration has been made.
+                    // Do not emit a diagnostic since a NRT warning will also be emitted.
                     return null;
                 }
 
+                Debug.Assert(rootSerializableTypes.Count > 0);
+
                 LanguageVersion? langVersion = _knownSymbols.Compilation.GetLanguageVersion();
                 if (langVersion is null or < MinimumSupportedLanguageVersion)
                 {
                     // Unsupported lang version should be the first (and only) diagnostic emitted by the generator.
-                    ReportDiagnostic(DiagnosticDescriptors.JsonUnsupportedLanguageVersion, contextTypeSymbol.GetDiagnosticLocation(), langVersion?.ToDisplayString(), MinimumSupportedLanguageVersion.ToDisplayString());
+                    ReportDiagnostic(DiagnosticDescriptors.JsonUnsupportedLanguageVersion, _contextClassLocation, langVersion?.ToDisplayString(), MinimumSupportedLanguageVersion.ToDisplayString());
                     return null;
                 }
 
-                Location contextLocation = contextClassDeclaration.GetLocation();
                 if (!TryGetNestedTypeDeclarations(contextClassDeclaration, semanticModel, cancellationToken, out List<string>? classDeclarationList))
                 {
                     // Class or one of its containing types is not partial so we can't add to it.
-                    ReportDiagnostic(DiagnosticDescriptors.ContextClassesMustBePartial, contextLocation, contextTypeSymbol.Name);
+                    ReportDiagnostic(DiagnosticDescriptors.ContextClassesMustBePartial, _contextClassLocation, contextTypeSymbol.Name);
                     return null;
                 }
 
                 // Enqueue attribute data for spec generation
                 foreach (TypeToGenerate rootSerializableType in rootSerializableTypes)
                 {
-                    EnqueueType(rootSerializableType.Type, rootSerializableType.Mode, rootSerializableType.TypeInfoPropertyName, rootSerializableType.AttributeLocation);
+                    _typesToGenerate.Enqueue(rootSerializableType);
                 }
 
                 // Walk the transitive type graph generating specs for every encountered type.
@@ -135,7 +147,7 @@ namespace System.Text.Json.SourceGeneration
                     TypeToGenerate typeToGenerate = _typesToGenerate.Dequeue();
                     if (!_generatedTypes.ContainsKey(typeToGenerate.Type))
                     {
-                        TypeGenerationSpec spec = ParseTypeGenerationSpec(typeToGenerate, contextTypeSymbol, contextLocation, options);
+                        TypeGenerationSpec spec = ParseTypeGenerationSpec(typeToGenerate, contextTypeSymbol, options);
                         _generatedTypes.Add(typeToGenerate.Type, spec);
                     }
                 }
@@ -154,6 +166,7 @@ namespace System.Text.Json.SourceGeneration
                 // Clear the caches of generated metadata between the processing of context classes.
                 _generatedTypes.Clear();
                 _typesToGenerate.Clear();
+                _contextClassLocation = null;
                 return contextGenSpec;
             }
 
@@ -195,7 +208,7 @@ namespace System.Text.Json.SourceGeneration
                 return true;
             }
 
-            private TypeRef EnqueueType(ITypeSymbol type, JsonSourceGenerationMode? generationMode, string? typeInfoPropertyName = null, Location? attributeLocation = null)
+            private TypeRef EnqueueType(ITypeSymbol type, JsonSourceGenerationMode? generationMode)
             {
                 // Trim compile-time erased metadata such as tuple labels and NRT annotations.
                 type = _knownSymbols.Compilation.EraseCompileTimeMetadata(type);
@@ -209,14 +222,15 @@ namespace System.Text.Json.SourceGeneration
                 {
                     Type = type,
                     Mode = generationMode,
-                    TypeInfoPropertyName = typeInfoPropertyName,
-                    AttributeLocation = attributeLocation,
+                    TypeInfoPropertyName = null,
+                    Location = type.GetLocation(),
+                    AttributeLocation = null,
                 });
 
                 return new TypeRef(type);
             }
 
-            private bool TryParseJsonSerializerContextAttributes(
+            private void ParseJsonSerializerContextAttributes(
                 INamedTypeSymbol contextClassSymbol,
                 out List<TypeToGenerate>? rootSerializableTypes,
                 out SourceGenerationOptionsSpec? options)
@@ -246,8 +260,6 @@ namespace System.Text.Json.SourceGeneration
                         options = ParseJsonSourceGenerationOptionsAttribute(contextClassSymbol, attributeData);
                     }
                 }
-
-                return rootSerializableTypes != null || options != null;
             }
 
             private SourceGenerationOptionsSpec ParseJsonSourceGenerationOptionsAttribute(INamedTypeSymbol contextType, AttributeData attributeData)
@@ -399,18 +411,18 @@ namespace System.Text.Json.SourceGeneration
                 };
             }
 
-            private static TypeToGenerate? ParseJsonSerializableAttribute(AttributeData attributeData)
+            private TypeToGenerate? ParseJsonSerializableAttribute(AttributeData attributeData)
             {
-                ITypeSymbol? typeSymbol = null;
-                string? typeInfoPropertyName = null;
-                JsonSourceGenerationMode? generationMode = null;
-
                 Debug.Assert(attributeData.ConstructorArguments.Length == 1);
-                foreach (TypedConstant value in attributeData.ConstructorArguments)
+                var typeSymbol = (ITypeSymbol?)attributeData.ConstructorArguments[0].Value;
+                if (typeSymbol is null)
                 {
-                    typeSymbol = value.Value as ITypeSymbol;
+                    return null;
                 }
 
+                JsonSourceGenerationMode? generationMode = null;
+                string? typeInfoPropertyName = null;
+
                 foreach (KeyValuePair<string, TypedConstant> namedArg in attributeData.NamedArguments)
                 {
                     switch (namedArg.Key)
@@ -426,26 +438,31 @@ namespace System.Text.Json.SourceGeneration
                     }
                 }
 
-                if (typeSymbol is null)
+                Location? location = typeSymbol.GetLocation();
+                Location? attributeLocation = attributeData.GetLocation();
+                Debug.Assert(attributeLocation != null);
+
+                if (location is null || !_knownSymbols.Compilation.ContainsLocation(location))
                 {
-                    return null;
+                    // For symbols located outside the compilation, fall back to attribute location instead.
+                    location = attributeLocation;
                 }
 
                 return new TypeToGenerate
                 {
-                    Type = typeSymbol,
+                    Type = _knownSymbols.Compilation.EraseCompileTimeMetadata(typeSymbol),
                     Mode = generationMode,
                     TypeInfoPropertyName = typeInfoPropertyName,
-                    AttributeLocation = attributeData.GetDiagnosticLocation(),
+                    Location = location,
+                    AttributeLocation = attributeLocation,
                 };
             }
 
-            private TypeGenerationSpec ParseTypeGenerationSpec(in TypeToGenerate typeToGenerate, INamedTypeSymbol contextType, Location contextLocation, SourceGenerationOptionsSpec? options)
+            private TypeGenerationSpec ParseTypeGenerationSpec(in TypeToGenerate typeToGenerate, INamedTypeSymbol contextType, SourceGenerationOptionsSpec? options)
             {
                 Debug.Assert(IsSymbolAccessibleWithin(typeToGenerate.Type, within: contextType), "should not generate metadata for inaccessible types.");
 
                 ITypeSymbol type = typeToGenerate.Type;
-                Location typeLocation = type.GetDiagnosticLocation() ?? typeToGenerate.AttributeLocation ?? contextLocation;
 
                 ClassType classType;
                 JsonPrimitiveTypeKind? primitiveTypeKind = GetPrimitiveTypeKind(type);
@@ -465,7 +482,7 @@ namespace System.Text.Json.SourceGeneration
                 bool implementsIJsonOnSerialized = false;
                 bool implementsIJsonOnSerializing = false;
 
-                ProcessTypeCustomAttributes(typeToGenerate, contextType, typeLocation,
+                ProcessTypeCustomAttributes(typeToGenerate, contextType,
                     out JsonNumberHandling? numberHandling,
                     out JsonUnmappedMemberHandling? unmappedMemberHandling,
                     out JsonObjectCreationHandling? preferredPropertyObjectCreationHandling,
@@ -553,11 +570,11 @@ namespace System.Text.Json.SourceGeneration
 
                     if (!TryGetDeserializationConstructor(type, useDefaultCtorInAnnotatedStructs, out IMethodSymbol? constructor))
                     {
-                        ReportDiagnostic(DiagnosticDescriptors.MultipleJsonConstructorAttribute, typeLocation, type.ToDisplayString());
+                        ReportDiagnostic(DiagnosticDescriptors.MultipleJsonConstructorAttribute, typeToGenerate.Location, type.ToDisplayString());
                     }
                     else if (constructor != null && !IsSymbolAccessibleWithin(constructor, within: contextType))
                     {
-                        ReportDiagnostic(DiagnosticDescriptors.JsonConstructorInaccessible, typeLocation, type.ToDisplayString());
+                        ReportDiagnostic(DiagnosticDescriptors.JsonConstructorInaccessible, typeToGenerate.Location, type.ToDisplayString());
                         constructor = null;
                     }
 
@@ -567,7 +584,7 @@ namespace System.Text.Json.SourceGeneration
                     implementsIJsonOnSerialized = _knownSymbols.IJsonOnSerializedType.IsAssignableFrom(type);
 
                     ctorParamSpecs = ParseConstructorParameters(typeToGenerate, constructor, out constructionStrategy, out constructorSetsRequiredMembers);
-                    propertySpecs = ParsePropertyGenerationSpecs(contextType, typeToGenerate, typeLocation, options, out hasExtensionDataProperty, out fastPathPropertyIndices);
+                    propertySpecs = ParsePropertyGenerationSpecs(contextType, typeToGenerate, options, out hasExtensionDataProperty, out fastPathPropertyIndices);
                     propertyInitializerSpecs = ParsePropertyInitializers(ctorParamSpecs, propertySpecs, constructorSetsRequiredMembers, ref constructionStrategy);
                 }
 
@@ -576,14 +593,14 @@ namespace System.Text.Json.SourceGeneration
 
                 if (classType is ClassType.TypeUnsupportedBySourceGen)
                 {
-                    ReportDiagnostic(DiagnosticDescriptors.TypeNotSupported, typeToGenerate.AttributeLocation ?? typeLocation, type.ToDisplayString());
+                    ReportDiagnostic(DiagnosticDescriptors.TypeNotSupported, typeToGenerate.AttributeLocation ?? typeToGenerate.Location, type.ToDisplayString());
                 }
 
                 if (!_generatedContextAndTypeNames.Add((contextType.Name, typeInfoPropertyName)))
                 {
                     // The context name/property name combination will result in a conflict in generated types.
                     // Workaround for https://github.com/dotnet/roslyn/issues/54185 by keeping track of the file names we've used.
-                    ReportDiagnostic(DiagnosticDescriptors.DuplicateTypeName, typeToGenerate.AttributeLocation ?? contextLocation, typeInfoPropertyName);
+                    ReportDiagnostic(DiagnosticDescriptors.DuplicateTypeName, typeToGenerate.AttributeLocation ?? _contextClassLocation, typeInfoPropertyName);
                     classType = ClassType.TypeUnsupportedBySourceGen;
                 }
 
@@ -621,7 +638,6 @@ namespace System.Text.Json.SourceGeneration
             private void ProcessTypeCustomAttributes(
                 in TypeToGenerate typeToGenerate,
                 INamedTypeSymbol contextType,
-                Location typeLocation,
                 out JsonNumberHandling? numberHandling,
                 out JsonUnmappedMemberHandling? unmappedMemberHandling,
                 out JsonObjectCreationHandling? objectCreationHandling,
@@ -669,7 +685,7 @@ namespace System.Text.Json.SourceGeneration
 
                         if (!isPolymorphic && typeToGenerate.Mode == JsonSourceGenerationMode.Serialization)
                         {
-                            ReportDiagnostic(DiagnosticDescriptors.PolymorphismNotSupported, typeLocation, typeToGenerate.Type.ToDisplayString());
+                            ReportDiagnostic(DiagnosticDescriptors.PolymorphismNotSupported, typeToGenerate.Location, typeToGenerate.Type.ToDisplayString());
                         }
 
                         isPolymorphic = true;
@@ -845,11 +861,11 @@ namespace System.Text.Json.SourceGeneration
             private List<PropertyGenerationSpec> ParsePropertyGenerationSpecs(
                 INamedTypeSymbol contextType,
                 in TypeToGenerate typeToGenerate,
-                Location typeLocation,
                 SourceGenerationOptionsSpec? options,
                 out bool hasExtensionDataProperty,
                 out List<int>? fastPathPropertyIndices)
             {
+                Location? typeLocation = typeToGenerate.Location;
                 List<PropertyGenerationSpec> properties = new();
                 PropertyHierarchyResolutionState state = new();
                 hasExtensionDataProperty = false;
@@ -1048,7 +1064,7 @@ namespace System.Text.Json.SourceGeneration
             private PropertyGenerationSpec? ParsePropertyGenerationSpec(
                 INamedTypeSymbol contextType,
                 TypeRef declaringType,
-                Location typeLocation,
+                Location? typeLocation,
                 ITypeSymbol memberType,
                 ISymbol memberInfo,
                 ref bool typeHasExtensionDataProperty,
@@ -1084,7 +1100,7 @@ namespace System.Text.Json.SourceGeneration
 
                 if (hasJsonIncludeButIsInaccessible)
                 {
-                    ReportDiagnostic(DiagnosticDescriptors.InaccessibleJsonIncludePropertiesNotSupported, memberInfo.GetDiagnosticLocation(), declaringType.Name, memberInfo.Name);
+                    ReportDiagnostic(DiagnosticDescriptors.InaccessibleJsonIncludePropertiesNotSupported, memberInfo.GetLocation(), declaringType.Name, memberInfo.Name);
                 }
 
                 if (isExtensionData)
@@ -1096,7 +1112,7 @@ namespace System.Text.Json.SourceGeneration
 
                     if (!IsValidDataExtensionPropertyType(memberType))
                     {
-                        ReportDiagnostic(DiagnosticDescriptors.DataExtensionPropertyInvalid, memberInfo.GetDiagnosticLocation(), declaringType.Name, memberInfo.Name);
+                        ReportDiagnostic(DiagnosticDescriptors.DataExtensionPropertyInvalid, memberInfo.GetLocation(), declaringType.Name, memberInfo.Name);
                     }
 
                     typeHasExtensionDataProperty = true;
@@ -1457,7 +1473,7 @@ namespace System.Text.Json.SourceGeneration
 
                 if (!SymbolEqualityComparer.Default.Equals(attributeData.AttributeClass, _knownSymbols.JsonConverterAttributeType))
                 {
-                    ReportDiagnostic(DiagnosticDescriptors.DerivedJsonConverterAttributesNotSupported, attributeData.GetDiagnosticLocation(), attributeData.AttributeClass!.ToDisplayString());
+                    ReportDiagnostic(DiagnosticDescriptors.DerivedJsonConverterAttributesNotSupported, attributeData.GetLocation(), attributeData.AttributeClass!.ToDisplayString());
                     return null;
                 }
 
@@ -1472,13 +1488,13 @@ namespace System.Text.Json.SourceGeneration
                     !_knownSymbols.JsonConverterType.IsAssignableFrom(namedConverterType) ||
                     !namedConverterType.Constructors.Any(c => c.Parameters.Length == 0 && IsSymbolAccessibleWithin(c, within: contextType)))
                 {
-                    ReportDiagnostic(DiagnosticDescriptors.JsonConverterAttributeInvalidType, attributeData.GetDiagnosticLocation(), converterType?.ToDisplayString() ?? "null", declaringSymbol.ToDisplayString());
+                    ReportDiagnostic(DiagnosticDescriptors.JsonConverterAttributeInvalidType, attributeData.GetLocation(), converterType?.ToDisplayString() ?? "null", declaringSymbol.ToDisplayString());
                     return null;
                 }
 
                 if (_knownSymbols.JsonStringEnumConverterType.IsAssignableFrom(converterType))
                 {
-                    ReportDiagnostic(DiagnosticDescriptors.JsonStringEnumConverterNotSupportedInAot, attributeData.GetDiagnosticLocation(), declaringSymbol.ToDisplayString());
+                    ReportDiagnostic(DiagnosticDescriptors.JsonStringEnumConverterNotSupportedInAot, attributeData.GetLocation(), declaringSymbol.ToDisplayString());
                 }
 
                 return new TypeRef(converterType);
@@ -1735,9 +1751,10 @@ namespace System.Text.Json.SourceGeneration
             private readonly struct TypeToGenerate
             {
                 public required ITypeSymbol Type { get; init; }
-                public JsonSourceGenerationMode? Mode { get; init; }
-                public string? TypeInfoPropertyName { get; init; }
-                public Location? AttributeLocation { get; init; }
+                public required JsonSourceGenerationMode? Mode { get; init; }
+                public required string? TypeInfoPropertyName { get; init; }
+                public required Location? Location { get; init; }
+                public required Location? AttributeLocation { get; init; }
             }
         }
     }
index 3495443..85d64b6 100644 (file)
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <data name="DuplicateTypeNameMessageFormat" xml:space="preserve">
-    <value>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</value>
+    <value>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</value>
   </data>
   <data name="DuplicateTypeNameTitle" xml:space="preserve">
     <value>Duplicate type name.</value>
   <data name="JsonConstructorInaccessibleMessageFormat" xml:space="preserve">
     <value>The constructor on type '{0}' has been annotated with JsonConstructorAttribute but is not accessible by the source generator.</value>
   </data>
+  <data name="JsonSerializableAttributeOnNonContextTypeTitle" xml:space="preserve">
+    <value>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</value>
+  </data>
+  <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>
 </root>
index 1f31e7a..167c175 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">Existuje několik typů s názvem {0}. Zdroj se vygeneroval pro první zjištěný typ. Tuto kolizi vyřešíte pomocí JsonSerializableAttribute.TypeInfoPropertyName.</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">Existuje několik typů s názvem {0}. Zdroj se vygeneroval pro první zjištěný typ. Tuto kolizi vyřešíte pomocí JsonSerializableAttribute.TypeInfoPropertyName.</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">JsonConverterAttribute.Type obsahuje neplatný nebo nepřístupný argument.</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">Člen {0} byl opatřen poznámkou jsonStringEnumConverter, což není v nativním AOT podporováno. Zvažte použití obecného objektu JsonStringEnumConverter&lt;TEnum&gt;.</target>
index 71d1d1b..013b5bd 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">Es sind mehrere Typen namens "{0}" vorhanden. Die Quelle wurde für den ersten festgestellten Typ generiert. Verwenden Sie "JsonSerializableAttribute.TypeInfoPropertyName", um diesen Konflikt zu beheben.</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">Es sind mehrere Typen namens "{0}" vorhanden. Die Quelle wurde für den ersten festgestellten Typ generiert. Verwenden Sie "JsonSerializableAttribute.TypeInfoPropertyName", um diesen Konflikt zu beheben.</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">"JsonConverterAttribute.Type" enthält ein ungültiges oder nicht zugängliches Argument.</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">Der Member "{0}" wurde mit "JsonStringEnumConverter" kommentiert, was in nativem AOT nicht unterstützt wird. Erwägen Sie stattdessen die Verwendung des generischen "JsonStringEnumConverter&lt;TEnum&gt;".</target>
index 75e5520..d425fbd 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">Hay varios tipos denominados {0}. El origen se generó para el primero detectado. Use "JsonSerializableAttribute.TypeInfoPropertyName" para resolver esta colisión.</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">Hay varios tipos denominados {0}. El origen se generó para el primero detectado. Use "JsonSerializableAttribute.TypeInfoPropertyName" para resolver esta colisión.</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">“JsonConverterAttribute.Type” contiene un argumento no válido o inaccesible.</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">El miembro '{0}' se ha anotado con 'JsonStringEnumConverter', que no se admite en AOT nativo. Considere la posibilidad de usar el elemento genérico "JsonStringEnumConverter&lt;TEnum&gt;" en su lugar.</target>
index 03be4b8..0f8aeae 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">Plusieurs types nommés {0}. La source a été générée pour la première détection détectée. Utilisez « JsonSerializableAttribute.TypeInfoPropertyName » pour résoudre cette collision.</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">Plusieurs types nommés {0}. La source a été générée pour la première détection détectée. Utilisez « JsonSerializableAttribute.TypeInfoPropertyName » pour résoudre cette collision.</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">'JsonConverterAttribute.Type' contient un argument non valide ou inaccessible.</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">Le membre '{0}' a été annoté avec 'JsonStringEnumConverter', ce qui n’est pas pris en charge dans AOT natif. Utilisez plutôt le générique 'JsonStringEnumConverter&lt;TEnum&gt;'.</target>
index b3b1d84..55f83a0 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">Sono presenti più tipi denominati {0}. L'origine è stata generata per il primo tipo rilevato. Per risolvere questa collisione, usare 'JsonSerializableAttribute.TypeInfoPropertyName'.</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">Sono presenti più tipi denominati {0}. L'origine è stata generata per il primo tipo rilevato. Per risolvere questa collisione, usare 'JsonSerializableAttribute.TypeInfoPropertyName'.</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">'JsonConverterAttribute.Type' contiene un argomento non valido o inaccessibile.</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">Il membro '{0}' è stato annotato con 'JsonStringEnumConverter' che non è supportato in AOT nativo. Provare a usare il generico 'JsonStringEnumConverter&lt;TEnum&gt;'.</target>
index b50a94b..c96e927 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">{0} と名前が付けられた種類が複数あります。最初に検出されたものに対してソースが生成されました。この問題を解決するには、'JsonSerializableAttribute.TypeInfoPropertyName' を使用します。</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">{0} と名前が付けられた種類が複数あります。最初に検出されたものに対してソースが生成されました。この問題を解決するには、'JsonSerializableAttribute.TypeInfoPropertyName' を使用します。</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">'JsonConverterAttribute.Type' に無効な、またはアクセスできない引数が含まれています。</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">メンバー '{0}' には、ネイティブ AOT ではサポートされていない 'JsonStringEnumConverter' の注釈が付けられています。 代わりに汎用の 'JsonStringEnumConverter&lt;TEnum&gt;' を使用することを検討してください。</target>
index 5f90e2a..4b22d15 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">이름이 {0}인 형식이 여러 개 있습니다. 처음 검색한 원본에 대해 원본이 생성되었습니다. 이 충돌을 해결하려면 'JsonSerializableAttribute.TypeInfoPropertyName'을 사용하세요.</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">이름이 {0}인 형식이 여러 개 있습니다. 처음 검색한 원본에 대해 원본이 생성되었습니다. 이 충돌을 해결하려면 'JsonSerializableAttribute.TypeInfoPropertyName'을 사용하세요.</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">'JsonConverterAttribute.Type'에 잘못되었거나 액세스할 수 없는 인수가 포함되어 있습니다.</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">'{0}' 멤버에 네이티브 AOT에서 지원되지 않는 'JsonStringEnumConverter'로 주석이 달렸습니다. 대신 제네릭 'JsonStringEnumConverter&lt;TEnum&gt;'을 사용해 보세요.</target>
index 70b4639..90276fa 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">Istnieje wiele typów o nazwie {0}. Wygenerowano źródło dla pierwszego wykrytego elementu. Aby rozwiązać tę kolizję, użyj „JsonSerializableAttribute. TypeInfoPropertyName”.</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">Istnieje wiele typów o nazwie {0}. Wygenerowano źródło dla pierwszego wykrytego elementu. Aby rozwiązać tę kolizję, użyj „JsonSerializableAttribute. TypeInfoPropertyName”.</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">Typ „JsonConverterAttribute.Type” zawiera nieprawidłowy lub niedostępny argument.</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">Element członkowski '{0}' został opatrzony adnotacją 'JsonStringEnumConverter', która nie jest obsługiwana w natywnym AOT. Zamiast tego należy rozważyć użycie ogólnego konwertera „JsonStringEnumConverter&lt;TEnum&gt;”.</target>
index 291c30a..4cf255e 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">Existem vários tipos chamados {0}. A fonte foi gerada para o primeiro detectado. Use 'JsonSerializableAttribute.TypeInfoPropertyName' para resolver esta colisão.</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">Existem vários tipos chamados {0}. A fonte foi gerada para o primeiro detectado. Use 'JsonSerializableAttribute.TypeInfoPropertyName' para resolver esta colisão.</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">O "JsonConverterAttribute.Type" contém um argumento inválido ou inacessível.</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">O membro "{0}" foi anotado com "JsonStringEnumConverter" que não tem suporte na AOT nativa. Considere usar o genérico "JsonStringEnumConverter&lt;TEnum&gt;".</target>
index 87a7936..dbfa2bd 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">Существует несколько типов с именем {0}. Исходный код сформирован для первого обнаруженного типа. Используйте JsonSerializableAttribute.TypeInfoPropertyName для устранения этого конфликта.</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">Существует несколько типов с именем {0}. Исходный код сформирован для первого обнаруженного типа. Используйте JsonSerializableAttribute.TypeInfoPropertyName для устранения этого конфликта.</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">Аргумент "JsonConverterAttribute.Type" содержит недопустимый или недоступный аргумент.</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">Элемент "{0}" содержит примечание JsonStringEnumConverter, что не поддерживается в собственном AOT. Вместо этого рассмотрите возможность использовать универсальный параметр JsonStringEnumConverter&lt;TEnum&gt;.</target>
index 9f41469..aa2b98b 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">{0} adını taşıyan birden çok tür var. Kaynak, algılanan ilk tür için oluşturuldu. Bu çarpışmayı çözmek için 'JsonSerializableAttribute.TypeInfoPropertyName' özelliğini kullanın.</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">{0} adını taşıyan birden çok tür var. Kaynak, algılanan ilk tür için oluşturuldu. Bu çarpışmayı çözmek için 'JsonSerializableAttribute.TypeInfoPropertyName' özelliğini kullanın.</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">'JsonConverterAttribute.Type' geçersiz veya erişilemeyen bir bağımsız değişken içeriyor.</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">'{0}' adlı üyeye yerel AOT’de desteklenmeyen 'JsonStringEnumConverter' parametresi eklendi. bunun yerine genel 'JsonStringEnumConverter&lt;TEnum&gt;' parametresini kullanmayı deneyin.</target>
index 5a656d9..5498c96 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">有多个名为 {0} 的类型。已为第一个检测到类型的生成源。请使用 'JsonSerializableAttribute.TypeInfoPropertyName' 以解决此冲突。</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">有多个名为 {0} 的类型。已为第一个检测到类型的生成源。请使用 'JsonSerializableAttribute.TypeInfoPropertyName' 以解决此冲突。</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">"JsonConverterAttribute.Type" 包含无效或不可访问的参数。</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">成员“{0}”已使用本机 AOT 中不支持的 "JsonStringEnumConverter" 进行批注。请改为考虑使用泛型 "JsonStringEnumConverter&lt;TEnum&gt;"。</target>
index fa1cefb..e4652c6 100644 (file)
@@ -33,8 +33,8 @@
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameMessageFormat">
-        <source>There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
-        <target state="translated">有多個名為 {0} 的類型。已為偵測到的第一個項目產生來源。請使用 'JsonSerializableAttribute.TypeInfoPropertyName' 解決此衝突。</target>
+        <source>There are multiple types named '{0}'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.</source>
+        <target state="needs-review-translation">有多個名為 {0} 的類型。已為偵測到的第一個項目產生來源。請使用 'JsonSerializableAttribute.TypeInfoPropertyName' 解決此衝突。</target>
         <note />
       </trans-unit>
       <trans-unit id="DuplicateTypeNameTitle">
         <target state="translated">'JsonConverterAttribute.Type' 包含無效或無法存取的引數。</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="new">The type '{0}' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated.</target>
+        <note />
+      </trans-unit>
+      <trans-unit id="JsonSerializableAttributeOnNonContextTypeTitle">
+        <source>Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</source>
+        <target state="new">Types annotated with JsonSerializableAttribute must be classes deriving from JsonSerializerContext.</target>
+        <note />
+      </trans-unit>
       <trans-unit id="JsonStringEnumConverterNotSupportedMessageFormat">
         <source>The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter&lt;TEnum&gt;' instead.</source>
         <target state="translated">成員 '{0}' 已使用原生 AOT 不支援的 'JsonStringEnumConverter' 加上標註。請考慮改用一般 'JsonStringEnumConverter&lt;TEnum&gt;'。</target>
index 4155df9..98f2b71 100644 (file)
@@ -177,12 +177,11 @@ namespace System.Text.Json.SourceGeneration.UnitTests
             Compilation compilation = CompilationHelper.CreateRepeatedLocationsCompilation();
             JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation, disableDiagnosticValidation: true);
 
-            INamedTypeSymbol symbol = (INamedTypeSymbol)compilation.GetSymbolsWithName("JsonContext").FirstOrDefault();
-            Location location = symbol.GetAttributes()[1].GetLocation();
+            Location location = compilation.GetSymbolsWithName("JsonContext").FirstOrDefault().GetAttributes()[1].GetLocation();
 
             var expectedDiagnostics = new DiagnosticData[]
             {
-                new(DiagnosticSeverity.Warning, location, "There are multiple types named Location. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.")
+                new(DiagnosticSeverity.Warning, location, "There are multiple types named 'Location'. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.")
             };
 
             CompilationHelper.AssertEqualDiagnosticMessages(expectedDiagnostics, result.Diagnostics);
@@ -556,5 +555,79 @@ namespace System.Text.Json.SourceGeneration.UnitTests
 
             CompilationHelper.AssertEqualDiagnosticMessages(expectedDiagnostics, result.Diagnostics);
         }
+
+        [Fact]
+        public void DiagnosticOnMemberFromReferencedAssembly_LocationDefaultsToContextClass()
+        {
+            Compilation referencedCompilation = CompilationHelper.CreateCompilation("""
+                using System.Text.Json.Serialization;
+
+                namespace Library
+                {
+                    public class MyPoco
+                    {
+                        [JsonConverter(typeof(int))]
+                        public int Value { get; set; }
+                    }
+                }
+                """);
+
+            // Emit the image of the referenced assembly.
+            byte[] referencedImage = CompilationHelper.CreateAssemblyImage(referencedCompilation);
+            MetadataReference[] additionalReferences = { MetadataReference.CreateFromImage(referencedImage) };
+
+            Compilation compilation = CompilationHelper.CreateCompilation("""
+                using Library;
+                using System.Text.Json.Serialization;
+
+                namespace Application
+                {
+                    [JsonSerializable(typeof(MyPoco))]
+                    public partial class MyContext : JsonSerializerContext
+                    { }
+                }
+                """, additionalReferences);
+
+            JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation, disableDiagnosticValidation: true);
+
+            Location contextLocation = compilation.GetSymbolsWithName("MyContext").First().Locations[0];
+
+            var expectedDiagnostics = new DiagnosticData[]
+            {
+                new(DiagnosticSeverity.Warning, contextLocation, "The 'JsonConverterAttribute' type 'int' specified on member 'Library.MyPoco.Value' is not a converter type or does not contain an accessible parameterless constructor."),
+            };
+
+            CompilationHelper.AssertEqualDiagnosticMessages(expectedDiagnostics, result.Diagnostics);
+        }
+
+        [Fact]
+        public void JsonSerializableAttributeOnNonContextClass()
+        {
+            Compilation compilation = CompilationHelper.CreateCompilation("""
+                using System.Text.Json.Serialization;
+
+                namespace Application
+                {
+                    [JsonSerializable(typeof(MyPoco))]
+                    public partial class MyContext : IDisposable
+                    {
+                        public void Dispose() { }
+                    }
+
+                    public class MyPoco { }
+                }
+                """);
+
+            JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation, disableDiagnosticValidation: true);
+
+            Location contextLocation = compilation.GetSymbolsWithName("MyContext").First().Locations[0];
+
+            var expectedDiagnostics = new DiagnosticData[]
+            {
+                new(DiagnosticSeverity.Warning, contextLocation, "The type 'Application.MyContext' has been annotated with JsonSerializableAttribute but does not derive from JsonSerializerContext. No source code will be generated."),
+            };
+
+            CompilationHelper.AssertEqualDiagnosticMessages(expectedDiagnostics, result.Diagnostics);
+        }
     }
 }
index 50ee8f3..7a38a7e 100644 (file)
@@ -142,6 +142,7 @@ namespace System.Text.Json.SourceGeneration.UnitTests
         {
             JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(factory(), disableDiagnosticValidation: true);
             WalkObjectGraph(result.ContextGenerationSpecs);
+            WalkObjectGraph(result.Diagnostics);
 
             static void WalkObjectGraph(object obj)
             {