Skip to content

Commit

Permalink
refactored out System.Text.Json from ElementDataProvider.cs using Sou…
Browse files Browse the repository at this point in the history
…rceGeneration
  • Loading branch information
JensKrumsieck committed Jul 23, 2023
1 parent 9dd75d6 commit 1a27287
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 98 deletions.
1 change: 0 additions & 1 deletion ChemSharp.Molecules/ChemSharp.Molecules.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

<ItemGroup>
<PackageReference Include="Nodo" Version="1.0.0"/>
<PackageReference Include="System.Text.Json" Version="7.0.2"/>
<ProjectReference Include="..\ChemSharp\ChemSharp.csproj"/>
<ProjectReference Include="..\Generators\ChemSharp.Molecules.Generator\ChemSharp.Molecules.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
Expand Down
18 changes: 7 additions & 11 deletions ChemSharp.Molecules/Element.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Text.Json.Serialization;

namespace ChemSharp.Molecules;
namespace ChemSharp.Molecules;

/// <summary>
/// represents a chemical element
Expand All @@ -18,7 +16,7 @@ public class Element
private static readonly string[] Metalloids = {"B", "Si", "Ge", "As", "Sb", "Bi", "Se", "Te", "Po"};
private static readonly string[] NonMetals = {"H", "C", "N", "O", "P", "S", "Se"};

[JsonIgnore] private string? _color;
private string? _color;

static Element()
{
Expand Down Expand Up @@ -49,7 +47,6 @@ static Element()
/// <summary>
/// Constructor for Json Serialization
/// </summary>
[JsonConstructor]
#pragma warning disable CS8618
public Element() { }
#pragma warning restore CS8618
Expand Down Expand Up @@ -83,17 +80,16 @@ public Element(string symbol)
/// <summary>
/// Returns Element Color
/// </summary>
[JsonIgnore]
public string Color => _color ??= ElementDataProvider.ColorData[Symbol];

[JsonIgnore] public bool IsMetal => !IsMetalloid && !IsNonMetal;
[JsonIgnore] public int Charge { get; set; }
public bool IsMetal => !IsMetalloid && !IsNonMetal;
public int Charge { get; set; }

[JsonIgnore] public int Electrons => AtomicNumber - Charge;
public int Electrons => AtomicNumber - Charge;

[JsonIgnore] public bool IsMetalloid => Metalloids.Contains(Symbol);
public bool IsMetalloid => Metalloids.Contains(Symbol);

[JsonIgnore] public bool IsNonMetal => NonMetals.Contains(Symbol) || Group is 18 or 17;
public bool IsNonMetal => NonMetals.Contains(Symbol) || Group is 18 or 17;
public string Name { get; set; }
public string Symbol { get; set; }
public string Appearance { get; set; }
Expand Down
79 changes: 0 additions & 79 deletions ChemSharp.Molecules/ElementDataProvider.cs

This file was deleted.

5 changes: 0 additions & 5 deletions ChemSharp/ChemSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,4 @@
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'netstandard2.1'">
<PackageReference Include="PolySharp" Version="1.12.1"/>
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Resources\colorData.txt"/>
<EmbeddedResource Include="Resources\elements.json"/>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<PackageId>ChemSharp.Molecules.Generator</PackageId>
Expand All @@ -9,12 +9,18 @@
<IncludeBuildOutput>false</IncludeBuildOutput>
</PropertyGroup>

<ItemGroup>
<EmbeddedResource Include="Resources\colorData.txt"/>
<EmbeddedResource Include="Resources\elements.json"/>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0"/>
<PackageReference Include="System.Text.Json" Version="7.0.3"/>
</ItemGroup>
<ItemGroup>
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false"/>
Expand Down
104 changes: 104 additions & 0 deletions Generators/ChemSharp.Molecules.Generator/ElementProviderGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System.Collections.ObjectModel;
using System.Text;
using System.Text.Json;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;

namespace ChemSharp.Molecules.Generator;

[Generator]
public class ElementProviderGenerator : ISourceGenerator
{
private const string Indent = " ";

/// <summary>
/// Where the colorData is located
/// </summary>
private const string ColorSource = "ChemSharp.Molecules.Generator.Resources.colorData.txt";

/// <summary>
/// Where the element data is located
/// </summary>
private const string ApiSource = "ChemSharp.Molecules.Generator.Resources.elements.json";

public void Initialize(GeneratorInitializationContext context)
{
_elementData = EnsureApiData();
_colorData = EnsureColorData();
}
public void Execute(GeneratorExecutionContext context)
{
var sb = new StringBuilder();
sb.AppendLine("using System.Collections.Generic;");
sb.Append(@$"namespace ChemSharp.Molecules{{
public static class ElementDataProvider{{
public static Dictionary<string, string> ColorData => _colorData;
public static Element[] ElementData => _elementData;
private static Element[] _elementData = new Element[]{{
");
foreach (var jsonElement in _elementData)
{
sb.AppendLine(Space(3) + "new Element(){");
sb.AppendLine(Space(4) + $"Name = \"{jsonElement.TryGetString("Name")}\",");
sb.AppendLine(Space(4) + $"Symbol = \"{jsonElement.TryGetString("Symbol")}\",");
sb.AppendLine(Space(4) + $"Appearance = \"{jsonElement.TryGetString("Appearance")}\",");
sb.AppendLine(Space(4) + $"AtomicWeight = {jsonElement.TryGetDouble("AtomicWeight")},");
sb.AppendLine(Space(4) + $"AtomicNumber = {jsonElement.TryGetInt("AtomicNumber")},");
sb.AppendLine(Space(4) + $"Group = {jsonElement.TryGetInt("Group")},");
sb.AppendLine(Space(4) + $"Period = {jsonElement.TryGetInt("Period")},");
sb.AppendLine(Space(4) + $"Block = \"{jsonElement.TryGetString("Block")}\",");
sb.AppendLine(Space(4) + $"Category = \"{jsonElement.TryGetString("Category")}\",");
sb.AppendLine(
Space(4) + $"ElectronConfiguration = \"{jsonElement.TryGetString("ElectronConfiguration")}\",");
sb.AppendLine(Space(4) + $"Electronegativity = {jsonElement.TryGetDouble("Electronegativity")},");
sb.AppendLine(Space(4) + $"CovalentRadius = {jsonElement.TryGetInt("CovalentRadius")},");
sb.AppendLine(Space(4) + $"AtomicRadius = {jsonElement.TryGetInt("AtomicRadius")},");
sb.AppendLine(Space(4) + $"VdWRadius = {jsonElement.TryGetInt("VdWRadius")},");
sb.AppendLine(Space(4) + $"CAS = \"{jsonElement.TryGetString("CAS")}\",");
sb.AppendLine(Space(3) + "},");
}

sb.Append(@$"
}};
private static Dictionary<string, string> _colorData = new Dictionary<string,string>(){{
");
foreach (var kvp in _colorData) sb.AppendLine(Space(3) + $"{{\"{kvp.Key}\",\"{kvp.Value}\"}},");
sb.Append(@$"
}};
}}
}}");
context.AddSource($"ElementDataProvider_generated", SourceText.From(sb.ToString(), Encoding.UTF8));
}

private static JsonElement[] EnsureApiData()
{
var raw = ResourceUtil.ReadResourceString(ApiSource);
return JsonSerializer.Deserialize<JsonElement[]>(raw)!;
}
/// <summary>
/// Loads Color Data from ColorSource
/// </summary>
/// <returns></returns>
private static ReadOnlyDictionary<string, string> EnsureColorData()
{
var data = ResourceUtil.ReadResourceString(ColorSource);
var dic = data.Split(new[] {"\n", "\r\n", "\r"}, StringSplitOptions.RemoveEmptyEntries)
.Select(line => line.Split(','))
.ToDictionary(columns => columns[0], columns => columns[1]);
return new ReadOnlyDictionary<string, string>(dic);
}

private static string Space(int spacers)
{
var res = new StringBuilder();
for (var i = 0; i < spacers; i++)
res.Append(Indent);
return res.ToString();
}

#pragma warning disable CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
private JsonElement[] _elementData;
private ReadOnlyDictionary<string, string> _colorData;
#pragma warning restore CS8618 // Ein Non-Nullable-Feld muss beim Beenden des Konstruktors einen Wert ungleich NULL enthalten. Erwägen Sie die Deklaration als Nullable.
}
36 changes: 36 additions & 0 deletions Generators/ChemSharp.Molecules.Generator/JsonTools.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Globalization;
using System.Text.Json;

namespace ChemSharp.Molecules.Generator;

public static class JsonTools
{
public static string TryGetString(this JsonElement jsonObject, string propertyName)
{
if (!jsonObject.TryGetProperty(propertyName, out var value))
return "";
return value.GetString() ?? "";
}

public static string TryGetInt(this JsonElement jsonObject, string propertyName)
{
if (!jsonObject.TryGetProperty(propertyName, out var value))
return 0.ToString(CultureInfo.InvariantCulture);
if (value.ValueKind != JsonValueKind.Number)
return 0.ToString(CultureInfo.InvariantCulture);
if (!value.TryGetInt32(out var @int))
return 0.ToString(CultureInfo.InvariantCulture);
return @int.ToString(CultureInfo.InvariantCulture);
}

public static string TryGetDouble(this JsonElement jsonObject, string propertyName)
{
if (!jsonObject.TryGetProperty(propertyName, out var value))
return 0d.ToString(CultureInfo.InvariantCulture);
if (value.ValueKind != JsonValueKind.Number)
return 0d.ToString(CultureInfo.InvariantCulture);
if (!value.TryGetDouble(out var @double))
return 0d.ToString(CultureInfo.InvariantCulture);
return @double.ToString(CultureInfo.InvariantCulture);
}
}
35 changes: 35 additions & 0 deletions Generators/ChemSharp.Molecules.Generator/ResourceUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Reflection;

namespace ChemSharp.Molecules.Generator;

public static class ResourceUtil
{
/// <summary>
/// Loads ResourceStream
/// </summary>
/// <param name="resourceName"></param>
/// <returns></returns>
public static Stream LoadResource(string resourceName) => Assembly.GetAssembly(typeof(ResourceUtil))
?.GetManifestResourceStream(resourceName);

/// <summary>
/// Reads a String from Resource
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string ReadResourceString(string path)
{
StreamReader sr;
if (path.Contains("ChemSharp.Molecules.Generator.Resources")) //resource loading
{
var stream = LoadResource(path);
sr = new StreamReader(stream);
}
else
sr = new StreamReader(path);

var data = sr.ReadToEnd();
sr.Close();
return data;
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@
"Category": "",
"ElectronConfiguration": "[He] 2s2 2p6",
"ElectronsPerShell": "2, 8",
"Electronegativity": null,
"CovalentRadius": 58,
"AtomicRadius": 38,
"VdWRadius": 154,
Expand Down

0 comments on commit 1a27287

Please sign in to comment.