diff --git a/.github/workflows/runtests.yml b/.github/workflows/runtests.yml
index 8499c6fcf..92486bc38 100644
--- a/.github/workflows/runtests.yml
+++ b/.github/workflows/runtests.yml
@@ -22,7 +22,7 @@ jobs:
with:
fetch-depth: 0 # needed for GitVersioning to work
- name: Setup NuGet
- uses: NuGet/setup-nuget@v1
+ uses: NuGet/setup-nuget@v2
- name: Cache NuGet packages
uses: actions/cache@v4
id: cache
@@ -61,7 +61,7 @@ jobs:
with:
fetch-depth: 0
- name: Setup NuGet
- uses: NuGet/setup-nuget@v1
+ uses: NuGet/setup-nuget@v2
- name: Cache NuGet packages
uses: actions/cache@v4
id: cache
diff --git a/.gitignore b/.gitignore
index d2ada0cd0..3bc552dc3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -361,3 +361,5 @@ Tests/W3CTestSuite/images
Tests/W3CTestSuite/png
Tests/W3CTestSuite/resources
Tests/W3CTestSuite/svg
+
+Source/Generated/**/*.cs
diff --git a/Generators/AvailableElementsGenerator.cs b/Generators/AvailableElementsGenerator.cs
index 8c11bff9b..ee206cb27 100644
--- a/Generators/AvailableElementsGenerator.cs
+++ b/Generators/AvailableElementsGenerator.cs
@@ -5,7 +5,6 @@
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
namespace Svg.Generators
@@ -26,78 +25,6 @@ public class AvailableElementsGenerator : ISourceGenerator
DiagnosticSeverity.Error,
isEnabledByDefault: true);
- #region Model
-
- ///
- /// The object model used to generate SvgElements descriptors.
- ///
- private const string ModelText = @"//
-#nullable disable
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Globalization;
-
-namespace Svg
-{
- [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
- public sealed class ElementFactoryAttribute : Attribute
- {
- }
-
- internal enum DescriptorType
- {
- Property,
- Event
- }
-
- internal interface ISvgPropertyDescriptor
- {
- DescriptorType DescriptorType { get; }
- string AttributeName { get; }
- string AttributeNamespace { get; }
- TypeConverter Converter { get; }
- Type Type { get; }
- object GetValue(object component);
- void SetValue(object component, ITypeDescriptorContext context, CultureInfo culture, object value);
- }
-
- internal class SvgPropertyDescriptor : ISvgPropertyDescriptor
- {
- public DescriptorType DescriptorType { get; }
- public string AttributeName { get; }
- public string AttributeNamespace { get; }
- public TypeConverter Converter { get; }
- public Type Type { get; } = typeof(TU);
- private Func Getter { get; }
- private Action Setter { get; }
-
- public SvgPropertyDescriptor(DescriptorType descriptorType, string attributeName, string attributeNamespace, TypeConverter converter, Func getter, Action setter)
- {
- DescriptorType = descriptorType;
- AttributeName = attributeName;
- AttributeNamespace = attributeNamespace;
- Converter = converter;
- Getter = getter;
- Setter = setter;
- }
-
- public object GetValue(object component)
- {
- return (object)Getter((T)component);
- }
-
- public void SetValue(object component, ITypeDescriptorContext context, CultureInfo culture, object value)
- {
- if (Converter != null)
- {
- Setter((T)component, (TU)Converter.ConvertFrom(context, culture, value));
- }
- }
- }
-}";
- #endregion
-
///
public void Initialize(GeneratorInitializationContext context)
{
@@ -109,17 +36,13 @@ public void Initialize(GeneratorInitializationContext context)
///
public void Execute(GeneratorExecutionContext context)
{
- // Add the ElementFactory model source to compilation.
- context.AddSource("Svg_Model", SourceText.From(ModelText, Encoding.UTF8));
-
// Check is we have our SyntaxReceiver object used to filter compiled code.
if (!(context.SyntaxReceiver is SyntaxReceiver receiver))
{
return;
}
- var options = (context.Compilation as CSharpCompilation)?.SyntaxTrees[0].Options as CSharpParseOptions;
- var compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(ModelText, Encoding.UTF8), options));
+ var compilation = context.Compilation;
var elementFactoryAttribute = compilation.GetTypeByMetadataName("Svg.ElementFactoryAttribute");
if (elementFactoryAttribute is null)
@@ -367,7 +290,7 @@ internal virtual bool SetValue(string attributeName, ITypeDescriptorContext cont
}}
}}
");
- context.AddSource($"Svg_SvgElement_Properties.cs", SourceText.From(source.ToString(), Encoding.UTF8));
+ context.AddSource($"Svg.SvgElement.Properties.g.cs", SourceText.From(source.ToString(), Encoding.UTF8));
source.Clear();
// Generate SvgElement derived classes with descriptor Properties dictionary.
@@ -456,7 +379,7 @@ internal override bool SetValue(string attributeName, ITypeDescriptorContext con
}}
}}
");
- context.AddSource($"{namespaceElement.Replace('.', '_')}_{element.Symbol.Name}_Properties.cs", SourceText.From(source.ToString(), Encoding.UTF8));
+ context.AddSource($"{namespaceElement}.{element.Symbol.Name}.Properties.g.cs", SourceText.From(source.ToString(), Encoding.UTF8));
source.Clear();
}
@@ -492,7 +415,7 @@ internal static class SvgElements
}
}
");
- context.AddSource($"Svg_SvgElements.cs", SourceText.From(source.ToString(), Encoding.UTF8));
+ context.AddSource($"Svg.SvgElements.g.cs", SourceText.From(source.ToString(), Encoding.UTF8));
source.Clear();
// Generate ElementFactory class.
@@ -586,7 +509,7 @@ internal partial class {classElementFactory}
}}
}}");
- context.AddSource($"{namespaceElementFactory.Replace('.', '_')}_{elementFactorySymbol.Name}_ElementFactory.cs", SourceText.From(source.ToString(), Encoding.UTF8));
+ context.AddSource($"{namespaceElementFactory}.{elementFactorySymbol.Name}.ElementFactory.g.cs", SourceText.From(source.ToString(), Encoding.UTF8));
source.Clear();
}
@@ -755,6 +678,10 @@ private static IEnumerable GetBaseTypes(INamedTypeSymbol named
{
"System.String" => "System.ComponentModel.StringConverter",
"System.Single" => "System.ComponentModel.SingleConverter",
+ "System.Int16" => "System.ComponentModel.Int16Converter",
+ "System.Int32" => "System.ComponentModel.Int32Converter",
+ "System.Int64" => "System.ComponentModel.Int64Converter",
+ "System.Boolean" => "System.ComponentModel.BooleanConverter",
"System.Uri" => "System.UriTypeConverter",
_ => null
};
@@ -863,149 +790,5 @@ private static IEnumerable GetElementProperties(Compilation compilatio
}
}
}
-
- ///
- /// Symbol member type.
- ///
- private enum MemberType
- {
- ///
- /// Property symbol.
- ///
- Property,
- ///
- /// Event symbol.
- ///
- Event
- }
-
- ///
- /// The SvgElement object property/event.
- ///
- private class Property
- {
- ///
- /// Gets or sets property/event symbol.
- ///
- public ISymbol Symbol { get; }
-
- ///
- /// Gets or sets property/event symbol member type.
- ///
- public MemberType MemberType { get; }
-
- ///
- /// Gets or sets property/event attribute name.
- ///
- public string AttributeName { get; }
-
- ///
- /// Gets or sets property/event attribute namespace.
- ///
- public string AttributeNamespace { get; }
-
- ///
- /// Gets or sets property/event type converter type string.
- ///
- public string? Converter { get; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The property/event symbol.
- /// The property/event symbol member type.
- /// The property/event attribute name.
- /// The property/event attribute namespace.
- /// The property/event type converter type string.
- public Property(ISymbol symbol, MemberType memberType, string attributeName, string attributeNamespace, string? converter)
- {
- Symbol = symbol;
- MemberType = memberType;
- AttributeName = attributeName;
- AttributeNamespace = attributeNamespace;
- Converter = converter;
- }
- }
-
- ///
- /// Custom equality comparer using for cmparison.
- ///
- private class PropertyEqualityComparer : IEqualityComparer
- {
- ///
- public bool Equals(Property p1, Property p2)
- {
- return SymbolEqualityComparer.Default.Equals(p1.Symbol, p2.Symbol);
- }
-
- ///
- public int GetHashCode(Property p)
- {
-#pragma warning disable RS1024
- return p.Symbol.GetHashCode();
-#pragma warning restore RS1024
- }
- }
-
- ///
- /// The SvgElement object.
- ///
- private class Element
- {
- ///
- /// Gets or sets element type symbol.
- ///
- public INamedTypeSymbol Symbol { get; }
-
- ///
- /// Gets or sets element name.
- ///
- public string? ElementName { get; }
-
- ///
- /// Gets or sets classes that use element name.
- ///
- public List ClassNames { get; }
-
- ///
- /// Gets or sets element properties list.
- ///
- public List Properties { get; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The element type symbol.
- /// The element name.
- /// The classes that use element name.
- /// The element properties list.
- public Element(INamedTypeSymbol symbol, string? elementName, List classNames, List properties)
- {
- Symbol = symbol;
- ElementName = elementName;
- ClassNames = classNames;
- Properties = properties;
- }
- }
-
- ///
- /// The SyntaxReceiver is used to filter compiled code. This enable quick and easy way to filter compiled code.
- ///
- private class SyntaxReceiver : ISyntaxReceiver
- {
- ///
- /// Gets the list of all candidate class.
- ///
- public List CandidateClasses { get; } = new();
-
- ///
- public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
- {
- if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax)
- {
- CandidateClasses.Add(classDeclarationSyntax);
- }
- }
- }
}
}
diff --git a/Generators/Element.cs b/Generators/Element.cs
new file mode 100644
index 000000000..e660cdbc2
--- /dev/null
+++ b/Generators/Element.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis;
+
+namespace Svg.Generators
+{
+ ///
+ /// The SvgElement object.
+ ///
+ class Element
+ {
+ ///
+ /// Gets or sets element type symbol.
+ ///
+ public INamedTypeSymbol Symbol { get; }
+
+ ///
+ /// Gets or sets element name.
+ ///
+ public string? ElementName { get; }
+
+ ///
+ /// Gets or sets classes that use element name.
+ ///
+ public List ClassNames { get; }
+
+ ///
+ /// Gets or sets element properties list.
+ ///
+ public List Properties { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The element type symbol.
+ /// The element name.
+ /// The classes that use element name.
+ /// The element properties list.
+ public Element(INamedTypeSymbol symbol, string? elementName, List classNames, List properties)
+ {
+ Symbol = symbol;
+ ElementName = elementName;
+ ClassNames = classNames;
+ Properties = properties;
+ }
+ }
+}
diff --git a/Generators/MemberType.cs b/Generators/MemberType.cs
new file mode 100644
index 000000000..e040d1fc2
--- /dev/null
+++ b/Generators/MemberType.cs
@@ -0,0 +1,17 @@
+namespace Svg.Generators
+{
+ ///
+ /// Symbol member type.
+ ///
+ enum MemberType
+ {
+ ///
+ /// Property symbol.
+ ///
+ Property,
+ ///
+ /// Event symbol.
+ ///
+ Event
+ }
+}
diff --git a/Generators/Property.cs b/Generators/Property.cs
new file mode 100644
index 000000000..8bcc46091
--- /dev/null
+++ b/Generators/Property.cs
@@ -0,0 +1,52 @@
+using Microsoft.CodeAnalysis;
+
+namespace Svg.Generators
+{
+ ///
+ /// The SvgElement object property/event.
+ ///
+ class Property
+ {
+ ///
+ /// Gets or sets property/event symbol.
+ ///
+ public ISymbol Symbol { get; }
+
+ ///
+ /// Gets or sets property/event symbol member type.
+ ///
+ public MemberType MemberType { get; }
+
+ ///
+ /// Gets or sets property/event attribute name.
+ ///
+ public string AttributeName { get; }
+
+ ///
+ /// Gets or sets property/event attribute namespace.
+ ///
+ public string AttributeNamespace { get; }
+
+ ///
+ /// Gets or sets property/event type converter type string.
+ ///
+ public string? Converter { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The property/event symbol.
+ /// The property/event symbol member type.
+ /// The property/event attribute name.
+ /// The property/event attribute namespace.
+ /// The property/event type converter type string.
+ public Property(ISymbol symbol, MemberType memberType, string attributeName, string attributeNamespace, string? converter)
+ {
+ Symbol = symbol;
+ MemberType = memberType;
+ AttributeName = attributeName;
+ AttributeNamespace = attributeNamespace;
+ Converter = converter;
+ }
+ }
+}
diff --git a/Generators/PropertyEqualityComparer.cs b/Generators/PropertyEqualityComparer.cs
new file mode 100644
index 000000000..6da19d8e9
--- /dev/null
+++ b/Generators/PropertyEqualityComparer.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis;
+
+namespace Svg.Generators
+{
+ ///
+ /// Custom equality comparer using for cmparison.
+ ///
+ class PropertyEqualityComparer : IEqualityComparer
+ {
+ ///
+ public bool Equals(Property p1, Property p2)
+ {
+ return SymbolEqualityComparer.Default.Equals(p1.Symbol, p2.Symbol);
+ }
+
+ ///
+ public int GetHashCode(Property p)
+ {
+#pragma warning disable RS1024
+ return p.Symbol.GetHashCode();
+#pragma warning restore RS1024
+ }
+ }
+}
diff --git a/Generators/Svg.Generators.csproj b/Generators/Svg.Generators.csproj
index 9ada21dd0..5ec25fb2a 100644
--- a/Generators/Svg.Generators.csproj
+++ b/Generators/Svg.Generators.csproj
@@ -19,7 +19,7 @@
-
+
diff --git a/Generators/SyntaxReceiver.cs b/Generators/SyntaxReceiver.cs
new file mode 100644
index 000000000..3ac51d56e
--- /dev/null
+++ b/Generators/SyntaxReceiver.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+
+namespace Svg.Generators
+{
+ ///
+ /// The SyntaxReceiver is used to filter compiled code. This enable quick and easy way to filter compiled code.
+ ///
+ class SyntaxReceiver : ISyntaxReceiver
+ {
+ ///
+ /// Gets the list of all candidate class.
+ ///
+ public List CandidateClasses { get; } = new();
+
+ ///
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
+ {
+ if (syntaxNode is ClassDeclarationSyntax classDeclarationSyntax)
+ {
+ CandidateClasses.Add(classDeclarationSyntax);
+ }
+ }
+ }
+}
diff --git a/Source/Generated/Readme.md b/Source/Generated/Readme.md
new file mode 100644
index 000000000..3e5c91e8e
--- /dev/null
+++ b/Source/Generated/Readme.md
@@ -0,0 +1,5 @@
+### Geneated
+A directory of the generated source codes.
+- The generated files are excluded from the repository.
+- These files will not be directly included in the project.
+- To view the generated files, turn "Show All Files" on in the VS.
\ No newline at end of file
diff --git a/Source/Svg.csproj b/Source/Svg.csproj
index c0aa6b26f..802d91cbe 100644
--- a/Source/Svg.csproj
+++ b/Source/Svg.csproj
@@ -37,7 +37,7 @@
true
snupkg
true
- $(BaseIntermediateOutputPath)\$(Configuration)\$(TargetFramework)\GeneratedFiles
+ Generated
diff --git a/Source/Svg.sln b/Source/Svg.sln
index add02a0d1..fdca85558 100644
--- a/Source/Svg.sln
+++ b/Source/Svg.sln
@@ -35,10 +35,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Svg.Benchmark", "..\Tests\S
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Generators", "Generators", "{FAFD6DC7-5203-4CED-A151-66379DD43695}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Svg.Custom", "..\Svg.Custom\Svg.Custom.csproj", "{6FAA2B79-FE5C-456B-A743-E9290665B223}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Svg.Tests.Common", "..\Tests\Svg.Tests.Common\Svg.Tests.Common.csproj", "{D7C625E8-79EA-4859-A457-2C4A90786790}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Svg.Custom", "..\Tests\Svg.Custom\Svg.Custom.csproj", "{AD112647-446B-4DAC-8D90-17B0F5FA7188}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -85,14 +85,14 @@ Global
{8DEB3EA7-5915-4EB9-8052-85A7AC4379EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8DEB3EA7-5915-4EB9-8052-85A7AC4379EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DEB3EA7-5915-4EB9-8052-85A7AC4379EC}.Release|Any CPU.Build.0 = Release|Any CPU
- {6FAA2B79-FE5C-456B-A743-E9290665B223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6FAA2B79-FE5C-456B-A743-E9290665B223}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6FAA2B79-FE5C-456B-A743-E9290665B223}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6FAA2B79-FE5C-456B-A743-E9290665B223}.Release|Any CPU.Build.0 = Release|Any CPU
{D7C625E8-79EA-4859-A457-2C4A90786790}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D7C625E8-79EA-4859-A457-2C4A90786790}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7C625E8-79EA-4859-A457-2C4A90786790}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D7C625E8-79EA-4859-A457-2C4A90786790}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AD112647-446B-4DAC-8D90-17B0F5FA7188}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AD112647-446B-4DAC-8D90-17B0F5FA7188}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AD112647-446B-4DAC-8D90-17B0F5FA7188}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AD112647-446B-4DAC-8D90-17B0F5FA7188}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -108,6 +108,7 @@ Global
{BACDD1F4-B97D-4E27-BD09-6957633FF484} = {FAFD6DC7-5203-4CED-A151-66379DD43695}
{8DEB3EA7-5915-4EB9-8052-85A7AC4379EC} = {2EC3F3A0-F097-43EF-A603-9B82E3061469}
{D7C625E8-79EA-4859-A457-2C4A90786790} = {2EC3F3A0-F097-43EF-A603-9B82E3061469}
+ {AD112647-446B-4DAC-8D90-17B0F5FA7188} = {2EC3F3A0-F097-43EF-A603-9B82E3061469}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5096EEB3-8F41-44B5-BCF9-58743A59AB21}
diff --git a/Source/SvgModel.cs b/Source/SvgModel.cs
new file mode 100644
index 000000000..5378eeef4
--- /dev/null
+++ b/Source/SvgModel.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+
+namespace Svg
+{
+ [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
+ public sealed class ElementFactoryAttribute : Attribute
+ {
+ }
+
+ internal enum DescriptorType
+ {
+ Property,
+ Event
+ }
+
+ internal interface ISvgPropertyDescriptor
+ {
+ DescriptorType DescriptorType { get; }
+ string AttributeName { get; }
+ string AttributeNamespace { get; }
+ TypeConverter Converter { get; }
+ Type Type { get; }
+ object GetValue(object component);
+ void SetValue(object component, ITypeDescriptorContext context, CultureInfo culture, object value);
+ }
+
+ internal class SvgPropertyDescriptor : ISvgPropertyDescriptor
+ {
+ public DescriptorType DescriptorType { get; }
+ public string AttributeName { get; }
+ public string AttributeNamespace { get; }
+ public TypeConverter Converter { get; }
+ public Type Type { get; } = typeof(TU);
+ private Func Getter { get; }
+ private Action Setter { get; }
+
+ public SvgPropertyDescriptor(DescriptorType descriptorType, string attributeName,
+ string attributeNamespace, TypeConverter converter, Func getter, Action setter)
+ {
+ DescriptorType = descriptorType;
+ AttributeName = attributeName;
+ AttributeNamespace = attributeNamespace;
+ Converter = converter;
+ Getter = getter;
+ Setter = setter;
+ }
+
+ public object GetValue(object component)
+ {
+ return (object)Getter((T)component);
+ }
+
+ public void SetValue(object component, ITypeDescriptorContext context, CultureInfo culture, object value)
+ {
+ if (Converter != null)
+ {
+ Setter((T)component, (TU)Converter.ConvertFrom(context, culture, value));
+ }
+ }
+ }
+}
diff --git a/Svg.Custom/Svg.Custom.csproj b/Tests/Svg.Custom/Svg.Custom.csproj
similarity index 89%
rename from Svg.Custom/Svg.Custom.csproj
rename to Tests/Svg.Custom/Svg.Custom.csproj
index 7b4d346e4..0f538e18d 100644
--- a/Svg.Custom/Svg.Custom.csproj
+++ b/Tests/Svg.Custom/Svg.Custom.csproj
@@ -11,7 +11,7 @@
True
disable
true
- $(BaseIntermediateOutputPath)\$(Configuration)\$(TargetFramework)\GeneratedFiles
+ $(SvgSourcesBasePath)\Generated
$(DefineConstants);NO_SDC
10.0
@@ -24,7 +24,7 @@
- ..
+ ..\..
@@ -42,6 +42,11 @@
+
+
+
+
+
$(DefineConstants);NETSTANDARD;NETSTANDARD20