diff --git a/.editorconfig b/.editorconfig index 2e2d2e5e..fefcd11d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -19,3 +19,120 @@ dotnet_diagnostic.SA1642.severity = none dotnet_diagnostic.SA1643.severity = none dotnet_diagnostic.SX1309.severity = warning dotnet_diagnostic.CA2254.severity = none + +[*.cs] +#### Styles de nommage #### + +# Règles de nommage + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Spécifications de symboles + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Styles de nommage + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +dotnet_diagnostic.SA1010.severity = none + +[*.vb] +#### Styles de nommage #### + +# Règles de nommage + +dotnet_naming_rule.interface_should_be_commence_par_i.severity = suggestion +dotnet_naming_rule.interface_should_be_commence_par_i.symbols = interface +dotnet_naming_rule.interface_should_be_commence_par_i.style = commence_par_i + +dotnet_naming_rule.types_should_be_casse_pascal.severity = suggestion +dotnet_naming_rule.types_should_be_casse_pascal.symbols = types +dotnet_naming_rule.types_should_be_casse_pascal.style = casse_pascal + +dotnet_naming_rule.membres_autres_que_des_champs_should_be_casse_pascal.severity = suggestion +dotnet_naming_rule.membres_autres_que_des_champs_should_be_casse_pascal.symbols = membres_autres_que_des_champs +dotnet_naming_rule.membres_autres_que_des_champs_should_be_casse_pascal.style = casse_pascal + +# Spécifications de symboles + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.membres_autres_que_des_champs.applicable_kinds = property, event, method +dotnet_naming_symbols.membres_autres_que_des_champs.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.membres_autres_que_des_champs.required_modifiers = + +# Styles de nommage + +dotnet_naming_style.commence_par_i.required_prefix = I +dotnet_naming_style.commence_par_i.required_suffix = +dotnet_naming_style.commence_par_i.word_separator = +dotnet_naming_style.commence_par_i.capitalization = pascal_case + +dotnet_naming_style.casse_pascal.required_prefix = +dotnet_naming_style.casse_pascal.required_suffix = +dotnet_naming_style.casse_pascal.word_separator = +dotnet_naming_style.casse_pascal.capitalization = pascal_case + +dotnet_naming_style.casse_pascal.required_prefix = +dotnet_naming_style.casse_pascal.required_suffix = +dotnet_naming_style.casse_pascal.word_separator = +dotnet_naming_style.casse_pascal.capitalization = pascal_case + +[*.{cs,vb}] +tab_width = 4 +indent_size = 4 \ No newline at end of file diff --git a/TopModel.Core/FileModel/ModelFile.cs b/TopModel.Core/FileModel/ModelFile.cs index cc69125a..d0df9311 100644 --- a/TopModel.Core/FileModel/ModelFile.cs +++ b/TopModel.Core/FileModel/ModelFile.cs @@ -62,6 +62,7 @@ public class ModelFile .Concat(Classes.SelectMany(c => c.UniqueKeyReferences.SelectMany(uk => uk).Select(propRef => (propRef, (object)c.Properties.FirstOrDefault(p => p.Name == propRef.ReferenceName))))) .Concat(Classes.SelectMany(c => c.ValueReferences.SelectMany(rv => rv.Value).Select(prop => (prop.Key, (object)c.ExtendedProperties.FirstOrDefault(p => p.Name == prop.Key.ReferenceName))))) .Concat(Classes.SelectMany(c => c.FromMappers.SelectMany(m => m.ClassParams).Concat(c.ToMappers)).Select(p => (p.ClassReference as Reference, (object)p.Class))) + .Concat(Classes.SelectMany(c => c.FromMappers.SelectMany(m => m.PropertyParams)).Select(p => (p.TargetPropertyReference as Reference, (object)p.TargetProperty))) .Concat(Classes.SelectMany(c => c.FromMappers.SelectMany(m => m.ClassParams).Concat(c.ToMappers).SelectMany(m => m.MappingReferences.SelectMany(mr => new[] { (mr.Key, (object)c.ExtendedProperties.FirstOrDefault(k => k.Name == mr.Key.ReferenceName)), (mr.Value, mr.Value.ReferenceName == "false" ? new Keyword { ModelFile = c.ModelFile } : m.Mappings.Values.FirstOrDefault(k => k.Name == mr.Value.ReferenceName)) })))) .Concat(Converters.SelectMany(c => c.DomainsFromReferences.Select(d => (d as Reference, c.From.FirstOrDefault(dom => dom.Name == d.ReferenceName) as object)))) .Concat(Converters.SelectMany(c => c.DomainsToReferences.Select(d => (d as Reference, c.To.FirstOrDefault(dom => dom.Name == d.ReferenceName) as object)))) diff --git a/TopModel.Core/Loaders/ClassLoader.cs b/TopModel.Core/Loaders/ClassLoader.cs index 8d117934..7a9318c8 100644 --- a/TopModel.Core/Loaders/ClassLoader.cs +++ b/TopModel.Core/Loaders/ClassLoader.cs @@ -187,24 +187,19 @@ public Class Load(Parser parser) } else if (parser.Current is Scalar { Value: "property" }) { + var param = new PropertyMapping { FromMapper = mapper }; + mapper.Params.Add(param); while (parser.Current is not MappingEnd) { var prop = parser.Consume(); switch (prop.Value) { case "property": - var p = _propertyLoader.Load(parser); - var param = new PropertyMapping { Property = p, FromMapper = mapper }; - p.PropertyMapping = param; - mapper.Params.Add(param); + param.Property = _propertyLoader.Load(parser); + param.Property.PropertyMapping = param; break; case "target": - var targetReference = new Reference(parser.Consume()); - foreach (var cp in mapper.PropertyParams) - { - cp.TargetPropertyReference = targetReference; - } - + param.TargetPropertyReference = new Reference(parser.Consume()); break; } } diff --git a/TopModel.Core/Model/ClassMappings.cs b/TopModel.Core/Model/ClassMappings.cs index f9ecd602..9e7b8ec9 100644 --- a/TopModel.Core/Model/ClassMappings.cs +++ b/TopModel.Core/Model/ClassMappings.cs @@ -18,7 +18,7 @@ public class ClassMappings #nullable enable public string? Comment { get; set; } - public Dictionary Mappings { get; } = new(); + public Dictionary Mappings { get; } = new(); public Dictionary MappingReferences { get; } = new(); } diff --git a/TopModel.Core/Model/MappingExtensions.cs b/TopModel.Core/Model/MappingExtensions.cs new file mode 100644 index 00000000..6b3fc8f5 --- /dev/null +++ b/TopModel.Core/Model/MappingExtensions.cs @@ -0,0 +1,11 @@ +using OneOf; + +namespace TopModel.Core; + +public static class MappingExtensions +{ + public static string GetName(this OneOf mapping) + { + return mapping.Match(c => c.Name.ToString(), p => p.Property.Name); + } +} diff --git a/TopModel.Core/ModelErrorType.cs b/TopModel.Core/ModelErrorType.cs index 67633284..6a0fb244 100644 --- a/TopModel.Core/ModelErrorType.cs +++ b/TopModel.Core/ModelErrorType.cs @@ -202,6 +202,16 @@ public enum ModelErrorType /// TMD1031, + /// + /// La propriété '{mapping.Property.Name}' doit être une composition de la même classe que '{mapping.TargetProperty.Name}' pour définir un mapping entre les deux. + /// + TMD1032, + + /// + /// La propriété '{mapping.Property.Name}' ne peut pas être une composition pour définir un mapping vers '{mapping.TargetProperty.Name}'. + /// + TMD1033, + /// /// Le flux de données est introuvable dans le fichier ou l'une de ses références. /// diff --git a/TopModel.Core/ModelExtensions.cs b/TopModel.Core/ModelExtensions.cs index acb96e55..b897b7d5 100644 --- a/TopModel.Core/ModelExtensions.cs +++ b/TopModel.Core/ModelExtensions.cs @@ -1,4 +1,5 @@ -using TopModel.Core.FileModel; +using OneOf; +using TopModel.Core.FileModel; namespace TopModel.Core; @@ -118,6 +119,8 @@ public static ModelFile GetFile(this object? objet) DataFlow d => d.Location, FromMapper m => m.Reference.Location, ClassMappings c => c.Name.Location, + PropertyMapping p => p.Property.GetLocation(), + OneOf p => p.Match(c => c.GetLocation(), p => p.GetLocation()), Converter c => c.Location, _ => null }; @@ -140,6 +143,17 @@ public static ModelFile GetFile(this object? objet) } } + if (property.Class != null) + { + foreach (var mapping in property.Class.FromMappers.SelectMany(fm => fm.PropertyParams)) + { + if (mapping.TargetPropertyReference != null && mapping.TargetProperty == property) + { + yield return (mapping.TargetPropertyReference, mapping.TargetProperty.GetFile()); + } + } + } + if (property is IFieldProperty fp) { foreach (var alp in modelStore.Files.SelectMany(c => c.Properties).OfType()) diff --git a/TopModel.Core/ModelStore.cs b/TopModel.Core/ModelStore.cs index fec94afb..262bc485 100644 --- a/TopModel.Core/ModelStore.cs +++ b/TopModel.Core/ModelStore.cs @@ -1197,25 +1197,85 @@ IEnumerable ResolveAliases(IEnumerable alps) } } + foreach (var mapping in classe.FromMappers.SelectMany(fm => fm.PropertyParams)) + { + if (mapping.Property != null) + { + if (mapping.TargetPropertyReference != null) + { + var currentProperty = classe.ExtendedProperties.FirstOrDefault(p => p.Name == mapping.TargetPropertyReference.ReferenceName); + if (currentProperty == null) + { + yield return new ModelError(classe, $"La propriété '{{0}}' est introuvable sur la classe '{classe}'.", mapping.TargetPropertyReference) { ModelErrorType = ModelErrorType.TMD1004 }; + } + + mapping.TargetProperty = currentProperty; + } + else + { + var mappedProperty = classe.ExtendedProperties.FirstOrDefault(p => p.Name == mapping.Property.Name); + if (mappedProperty == null) + { + yield return new ModelError(classe, $"La propriété '{mapping.Property.Name}' est introuvable sur la classe '{classe}'.", mapping.Property.GetLocation()) { ModelErrorType = ModelErrorType.TMD1004 }; + } + + mapping.TargetProperty = mappedProperty; + } + + if (mapping.TargetProperty != null) + { + if (mapping.TargetProperty is not CompositionProperty && mapping.Property is CompositionProperty) + { + yield return new ModelError(classe, $"La propriété '{mapping.Property.Name}' ne peut pas être une composition pour définir un mapping vers '{mapping.TargetProperty.Name}'.", mapping.Property.GetLocation()) { ModelErrorType = ModelErrorType.TMD1033 }; + } + + if (mapping.TargetProperty is CompositionProperty { Composition: Class cpClass } && (mapping.Property is not CompositionProperty || ((CompositionProperty)mapping.Property).Composition != cpClass)) + { + yield return new ModelError(classe, $"La propriété '{mapping.Property.Name}' doit être une composition de la même classe que '{mapping.TargetProperty.Name}' pour définir un mapping entre les deux.", mapping.Property.GetLocation()) { ModelErrorType = ModelErrorType.TMD1032 }; + } + + if (mapping.Property.Domain != mapping.TargetProperty.Domain + && !Converters.Any(c => c.From.Any(cf => cf == mapping.Property.Domain) && c.To.Any(ct => ct == mapping.TargetProperty.Domain))) + { + yield return new ModelError(classe, $"La propriété '{mapping.Property.Name}' ne peut pas être mappée à '{mapping.TargetProperty.Name}' car elle n'a pas le même domaine ('{mapping.Property.Domain?.Name}' au lieu de '{mapping.TargetProperty.Domain?.Name}') et qu'il n'existe pas de convertisseur entre les deux.", mapping.Property.GetLocation()) { ModelErrorType = ModelErrorType.TMD1014 }; + } + } + } + } + foreach (var mapper in classe.FromMappers) { - foreach (var param in mapper.ClassParams.Where((e, i) => mapper.ClassParams.Where((p, j) => p.Name == e.Name && j < i).Any())) + foreach (var param in mapper.Params.Where((e, i) => mapper.Params.Where((p, j) => p.GetName() == e.GetName() && j < i).Any())) { - yield return new ModelError(classe, $"Le nom '{param.Name}' est déjà utilisé.", param.GetLocation()) { ModelErrorType = ModelErrorType.TMD0003 }; + yield return new ModelError(classe, $"Le nom '{param.GetName()}' est déjà utilisé.", param.GetLocation()) { ModelErrorType = ModelErrorType.TMD0003 }; } - var mappings = mapper.ClassParams.SelectMany(p => p.MappingReferences); + var mappedProperties = mapper.Params.SelectMany(p => p.Match( + p => p.MappingReferences.Where(e => e.Value.ReferenceName != "false").Select(e => e.Key), + p => + { + if (p.TargetPropertyReference != null) + { + return [p.TargetPropertyReference]; + } + + var propRef = p.Property.GetLocation() ?? new Reference(); + propRef.ReferenceName = p.Property.Name; + return [propRef]; + })); var hasDoublon = false; - foreach (var mapping in mappings.Where((e, i) => e.Value.ReferenceName != "false" && mappings.Where((p, j) => p.Value.ReferenceName != "false" && p.Key.ReferenceName == e.Key.ReferenceName && j < i).Any())) + foreach (var mapping in mappedProperties.Where((e, i) => mappedProperties.Where((p, j) => p.ReferenceName == e.ReferenceName && j < i).Any())) { hasDoublon = true; - yield return new ModelError(classe, $"La propriété '{mapping.Key.ReferenceName}' est déjà initialisée dans ce mapper.", mapping.Key) { ModelErrorType = ModelErrorType.TMD1015 }; + yield return new ModelError(classe, $"La propriété '{mapping.ReferenceName}' est déjà initialisée dans ce mapper.", mapping) { ModelErrorType = ModelErrorType.TMD1015 }; } if (!hasDoublon) { - var explicitMappings = mapper.ClassParams.SelectMany(p => p.Mappings).ToList(); + var explicitMappings = mapper.ClassParams.SelectMany(p => p.Mappings) + .Concat(mapper.PropertyParams.Select(p => new KeyValuePair(p.TargetProperty, p.Property))) + .ToList(); foreach (var param in mapper.ClassParams.Where(p => p.Class != null)) { @@ -1233,7 +1293,9 @@ IEnumerable ResolveAliases(IEnumerable alps) } } - var explicitAndAliasMappings = mapper.ClassParams.SelectMany(p => p.Mappings).ToList(); + var explicitAndAliasMappings = mapper.ClassParams.SelectMany(p => p.Mappings) + .Concat(mapper.PropertyParams.Select(p => new KeyValuePair(p.TargetProperty, p.Property))) + .ToList(); foreach (var param in mapper.ClassParams.Where(p => p.Class != null)) { @@ -1249,7 +1311,9 @@ IEnumerable ResolveAliases(IEnumerable alps) } } - var finalMappings = mapper.ClassParams.SelectMany(p => p.Mappings).ToList(); + var finalMappings = mapper.ClassParams.SelectMany(p => p.Mappings) + .Concat(mapper.PropertyParams.Select(p => new KeyValuePair(p.TargetProperty, p.Property))) + .ToList(); foreach (var mapping in finalMappings.Where((e, i) => finalMappings.Where((p, j) => p.Key == e.Key && j < i).Any())) { diff --git a/TopModel.Core/TopModel.Core.csproj b/TopModel.Core/TopModel.Core.csproj index 5502909b..6d92fc44 100644 --- a/TopModel.Core/TopModel.Core.csproj +++ b/TopModel.Core/TopModel.Core.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 enable enable true diff --git a/TopModel.Generator.Core/TopModel.Generator.Core.csproj b/TopModel.Generator.Core/TopModel.Generator.Core.csproj index dad5fb95..74317d27 100644 --- a/TopModel.Generator.Core/TopModel.Generator.Core.csproj +++ b/TopModel.Generator.Core/TopModel.Generator.Core.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 enable enable true diff --git a/TopModel.Generator.Csharp/TopModel.Generator.Csharp.csproj b/TopModel.Generator.Csharp/TopModel.Generator.Csharp.csproj index 49db8666..4c77dd65 100644 --- a/TopModel.Generator.Csharp/TopModel.Generator.Csharp.csproj +++ b/TopModel.Generator.Csharp/TopModel.Generator.Csharp.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 enable enable true diff --git a/TopModel.Generator.Javascript/TopModel.Generator.Javascript.csproj b/TopModel.Generator.Javascript/TopModel.Generator.Javascript.csproj index c9ee89a1..2f68f654 100644 --- a/TopModel.Generator.Javascript/TopModel.Generator.Javascript.csproj +++ b/TopModel.Generator.Javascript/TopModel.Generator.Javascript.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 enable enable true diff --git a/TopModel.Generator.Jpa/TopModel.Generator.Jpa.csproj b/TopModel.Generator.Jpa/TopModel.Generator.Jpa.csproj index c7c1233a..08125ec2 100644 --- a/TopModel.Generator.Jpa/TopModel.Generator.Jpa.csproj +++ b/TopModel.Generator.Jpa/TopModel.Generator.Jpa.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 enable enable true diff --git a/TopModel.Generator.Php/TopModel.Generator.Php.csproj b/TopModel.Generator.Php/TopModel.Generator.Php.csproj index 1a03a545..73fa0194 100644 --- a/TopModel.Generator.Php/TopModel.Generator.Php.csproj +++ b/TopModel.Generator.Php/TopModel.Generator.Php.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 enable enable true diff --git a/TopModel.Generator.Sql/TopModel.Generator.Sql.csproj b/TopModel.Generator.Sql/TopModel.Generator.Sql.csproj index 7c02aa0e..b38dc3c6 100644 --- a/TopModel.Generator.Sql/TopModel.Generator.Sql.csproj +++ b/TopModel.Generator.Sql/TopModel.Generator.Sql.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 enable enable true diff --git a/TopModel.Generator.Translation/TopModel.Generator.Translation.csproj b/TopModel.Generator.Translation/TopModel.Generator.Translation.csproj index b43d462d..9cf005ff 100644 --- a/TopModel.Generator.Translation/TopModel.Generator.Translation.csproj +++ b/TopModel.Generator.Translation/TopModel.Generator.Translation.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 enable enable true diff --git a/TopModel.Generator/TopModel.Generator.csproj b/TopModel.Generator/TopModel.Generator.csproj index c3d6b104..d043d172 100644 --- a/TopModel.Generator/TopModel.Generator.csproj +++ b/TopModel.Generator/TopModel.Generator.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 Exe enable enable diff --git a/TopModel.LanguageServer/CompletionHandler.cs b/TopModel.LanguageServer/CompletionHandler.cs index 281a4df1..27166f35 100644 --- a/TopModel.LanguageServer/CompletionHandler.cs +++ b/TopModel.LanguageServer/CompletionHandler.cs @@ -367,9 +367,13 @@ public override Task Handle(CompletionParams request, Cancellati var includeCompositions = false; var includeExtends = false; - if (currentLine.Contains("defaultProperty:") || currentLine.Contains("flagProperty:") || currentLine.Contains("orderProperty:")) + if (currentLine.Contains("defaultProperty:") || currentLine.Contains("flagProperty:") || currentLine.Contains("orderProperty:") || currentLine.Contains("target:")) { searchText = currentLine.Split(":")[1].Trim(); + if (currentLine.Contains("target")) + { + includeCompositions = true; + } } else { diff --git a/TopModel.LanguageServer/TopModel.LanguageServer.csproj b/TopModel.LanguageServer/TopModel.LanguageServer.csproj index 13dd7599..f27ebcef 100644 --- a/TopModel.LanguageServer/TopModel.LanguageServer.csproj +++ b/TopModel.LanguageServer/TopModel.LanguageServer.csproj @@ -3,6 +3,7 @@ Exe net6.0;net8.0 + 12 enable enable ../TopModel.VSCode/language-server-$(TargetFramework) diff --git a/TopModel.ModelGenerator/TopModel.ModelGenerator.csproj b/TopModel.ModelGenerator/TopModel.ModelGenerator.csproj index 44ac9e6d..c8f234af 100644 --- a/TopModel.ModelGenerator/TopModel.ModelGenerator.csproj +++ b/TopModel.ModelGenerator/TopModel.ModelGenerator.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 Exe enable enable diff --git a/TopModel.UI/TopModel.UI.csproj b/TopModel.UI/TopModel.UI.csproj index 3b627e95..b19f1eef 100644 --- a/TopModel.UI/TopModel.UI.csproj +++ b/TopModel.UI/TopModel.UI.csproj @@ -2,7 +2,7 @@ net6.0;net8.0 - latest + 12 enable enable true diff --git a/TopModel.Utils/TopModel.Utils.csproj b/TopModel.Utils/TopModel.Utils.csproj index 6dd0d791..8e2b855f 100644 --- a/TopModel.Utils/TopModel.Utils.csproj +++ b/TopModel.Utils/TopModel.Utils.csproj @@ -2,6 +2,7 @@ net6.0;net8.0 + 12 enable enable true