Skip to content

Commit

Permalink
Merge pull request #59 from digocesar/deprecated-annotation
Browse files Browse the repository at this point in the history
Insert @deprecated comment when type is Obsolete in C#
  • Loading branch information
SafeerH authored Jun 7, 2024
2 parents c847af3 + 86e47eb commit 22c4182
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 22 deletions.
34 changes: 31 additions & 3 deletions converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ const createConverter = config => {
if (!config.omitFilePathComment) {
rows.push(`// ${filename}`);
}
if (model.Obsolete) {
rows.push(formatObsoleteMessage(model.ObsoleteMessage, ''));
}
rows.push(`export interface ${model.ModelName}${baseClasses} {`);

const propertySemicolon = config.omitSemicolon ? '' : ';';
Expand All @@ -79,6 +82,9 @@ const createConverter = config => {
}

members.forEach(member => {
if (member.Obsolete) {
rows.push(formatObsoleteMessage(member.ObsoleteMessage, ' '));
}
rows.push(` ${convertProperty(member)}${propertySemicolon}`);
});

Expand All @@ -95,6 +101,10 @@ const createConverter = config => {

const entries = Object.entries(enum_.Values);

if (enum_.Obsolete) {
rows.push(formatObsoleteMessage(enum_.ObsoleteMessage, ''));
}

const getEnumStringValue = (value) => config.camelCaseEnums
? camelcase(value)
: value;
Expand All @@ -113,12 +123,15 @@ const createConverter = config => {
} else {
rows.push(`export enum ${enum_.Identifier} {`);

entries.forEach(([key, value]) => {
entries.forEach(([key, entry]) => {
if (entry.Obsolete) {
rows.push(formatObsoleteMessage(entry.ObsoleteMessage, ' '));
}
if (config.numericEnums) {
if (value == null) {
if (entry.Value == null) {
rows.push(` ${key},`);
} else {
rows.push(` ${key} = ${value},`);
rows.push(` ${key} = ${entry.Value},`);
}
} else {
rows.push(` ${key} = '${getEnumStringValue(key)}',`);
Expand All @@ -131,6 +144,21 @@ const createConverter = config => {
return rows;
};

const formatObsoleteMessage = (obsoleteMessage, indentation) => {
if (obsoleteMessage) {
obsoleteMessage = ' ' + obsoleteMessage;
} else {
obsoleteMessage = '';
}

let deprecationMessage = '';
deprecationMessage += `${indentation}/**\n`;
deprecationMessage += `${indentation} * @deprecated${obsoleteMessage}\n`;
deprecationMessage += `${indentation} */`;

return deprecationMessage;
}

const convertProperty = property => {
const optional = property.Type.endsWith('?');
const identifier = convertIdentifier(optional ? `${property.Identifier.split(' ')[0]}?` : property.Identifier.split(' ')[0]);
Expand Down
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ dotnetProcess.stderr.on('data', err => {
dotnetProcess.stdout.on('end', () => {
let json;

//console.log(stdout);

try {
// Extract the JSON content between the markers
const startMarker = '<<<<<<START_JSON>>>>>>';
Expand Down
28 changes: 23 additions & 5 deletions lib/csharp-models-to-json/EnumCollector.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

Expand All @@ -8,27 +7,46 @@ namespace CSharpModelsToJson
public class Enum
{
public string Identifier { get; set; }
public Dictionary<string, object> Values { get; set; }
public bool Obsolete { get; set; }
public string ObsoleteMessage { get; set; }
public Dictionary<string, EnumValue> Values { get; set; }
}

public class EnumValue
{
public string Value { get; set; }
public bool Obsolete { get; set; }
public string ObsoleteMessage { get; set; }
}


public class EnumCollector: CSharpSyntaxWalker
{
public readonly List<Enum> Enums = new List<Enum>();

public override void VisitEnumDeclaration(EnumDeclarationSyntax node)
{
var values = new Dictionary<string, object>();
var values = new Dictionary<string, EnumValue>();

foreach (var member in node.Members) {
var value = member.EqualsValue != null
var equalsValue = member.EqualsValue != null
? member.EqualsValue.Value.ToString()
: null;

values[member.Identifier.ToString()] = value?.Replace("_", "");
var value = new EnumValue
{
Value = equalsValue?.Replace("_", ""),
Obsolete = Util.IsObsolete(member.AttributeLists),
ObsoleteMessage = Util.GetObsoleteMessage(member.AttributeLists)
};

values[member.Identifier.ToString()] = value;
}

this.Enums.Add(new Enum() {
Identifier = node.Identifier.ToString(),
Obsolete = Util.IsObsolete(node.AttributeLists),
ObsoleteMessage = Util.GetObsoleteMessage(node.AttributeLists),
Values = values
});
}
Expand Down
9 changes: 9 additions & 0 deletions lib/csharp-models-to-json/ModelCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ public class Model
public IEnumerable<Field> Fields { get; set; }
public IEnumerable<Property> Properties { get; set; }
public IEnumerable<string> BaseClasses { get; set; }
public bool Obsolete { get; set; }
public string ObsoleteMessage { get; set; }

}

public class Field
Expand All @@ -24,6 +27,8 @@ public class Property
{
public string Identifier { get; set; }
public string Type { get; set; }
public bool Obsolete { get; set; }
public string ObsoleteMessage { get; set; }
}

public class ModelCollector : CSharpSyntaxWalker
Expand Down Expand Up @@ -81,6 +86,8 @@ private static Model CreateModel(TypeDeclarationSyntax node)
.Where(property => !IsIgnored(property.AttributeLists))
.Select(ConvertProperty),
BaseClasses = node.BaseList?.Types.Select(s => s.ToString()),
Obsolete = Util.IsObsolete(node.AttributeLists),
ObsoleteMessage = Util.GetObsoleteMessage(node.AttributeLists),
};
}

Expand All @@ -106,6 +113,8 @@ private static bool IsAccessible(SyntaxTokenList modifiers) => modifiers.All(mod
{
Identifier = property.Identifier.ToString(),
Type = property.Type.ToString(),
Obsolete = Util.IsObsolete(property.AttributeLists),
ObsoleteMessage = Util.GetObsoleteMessage(property.AttributeLists)
};
}
}
11 changes: 9 additions & 2 deletions lib/csharp-models-to-json/Program.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Extensions.Configuration;
using Ganss.IO;
using System.Text;

namespace CSharpModelsToJson
{
Expand Down Expand Up @@ -36,13 +37,19 @@ static void Main(string[] args)
files.Add(parseFile(fileName));
}

string json = JsonSerializer.Serialize(files);
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

string json = JsonSerializer.Serialize(files, options);

var sb = new StringBuilder();
sb.AppendLine("<<<<<<START_JSON>>>>>>");
sb.AppendLine(json);
sb.AppendLine("<<<<<<END_JSON>>>>>>");

System.Console.OutputEncoding = System.Text.Encoding.UTF8;
System.Console.WriteLine(sb.ToString());
}

Expand Down
31 changes: 31 additions & 0 deletions lib/csharp-models-to-json/Util.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Linq;

namespace CSharpModelsToJson
{
internal static class Util
{
internal static bool IsObsolete(SyntaxList<AttributeListSyntax> attributeLists) =>
attributeLists.Any(attributeList =>
attributeList.Attributes.Any(attribute =>
attribute.Name.ToString().Equals("Obsolete") || attribute.Name.ToString().Equals("ObsoleteAttribute")));

internal static string GetObsoleteMessage(SyntaxList<AttributeListSyntax> attributeLists)
{
foreach (var attributeList in attributeLists)
{
var obsoleteAttribute =
attributeList.Attributes.FirstOrDefault(attribute =>
attribute.Name.ToString().Equals("Obsolete") || attribute.Name.ToString().Equals("ObsoleteAttribute"));

if (obsoleteAttribute != null)
return obsoleteAttribute.ArgumentList == null
? null
: obsoleteAttribute.ArgumentList.Arguments.ToString()?.TrimStart('@').Trim('"');
}

return null;
}
}
}
11 changes: 5 additions & 6 deletions lib/csharp-models-to-json_test/EnumCollector_test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@ public enum SampleEnum
Assert.That(model, Is.Not.Null);
Assert.That(model.Values, Is.Not.Null);

var values = model.Values.ToArray();
Assert.That(values[0].Value, Is.Null);
Assert.That(values[1].Value, Is.EqualTo("7"));
Assert.That(values[2].Value, Is.Null);
Assert.That(values[3].Value, Is.EqualTo("4"));
Assert.That(values[4].Value, Is.Null);
Assert.That(model.Values["A"].Value, Is.Null);
Assert.That(model.Values["B"].Value, Is.EqualTo("7"));
Assert.That(model.Values["C"].Value, Is.Null);
Assert.That(model.Values["D"].Value, Is.EqualTo("4"));
Assert.That(model.Values["E"].Value, Is.Null);
}
}
}
72 changes: 66 additions & 6 deletions lib/csharp-models-to-json_test/ModelCollector_test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,66 @@ public void DictionaryInheritance_ReturnsIndexAccessor()
Assert.That(modelCollector.Models.First().BaseClasses, Is.EqualTo(new[] { "Dictionary<string, string>" }));
}

[Test]
public void ReturnObsoleteClassInfo()
{
var tree = CSharpSyntaxTree.ParseText(@"
[Obsolete(@""test"")]
public class A
{
[Obsolete(@""test prop"")]
public string A { get; set }
public string B { get; set }
}"
);

var root = (CompilationUnitSyntax)tree.GetRoot();

var modelCollector = new ModelCollector();
modelCollector.VisitClassDeclaration(root.DescendantNodes().OfType<ClassDeclarationSyntax>().First());

var model = modelCollector.Models.First();

Assert.That(model, Is.Not.Null);
Assert.That(model.Properties, Is.Not.Null);

Assert.That(model.Obsolete, Is.True);
Assert.That(model.ObsoleteMessage, Is.EqualTo("test"));

Assert.That(model.Properties.First(x => x.Identifier.Equals("A")).Obsolete, Is.True);
Assert.That(model.Properties.First(x => x.Identifier.Equals("A")).ObsoleteMessage, Is.EqualTo("test prop"));

Assert.That(model.Properties.First(x => x.Identifier.Equals("B")).Obsolete, Is.False);
Assert.That(model.Properties.First(x => x.Identifier.Equals("B")).ObsoleteMessage, Is.Null);
}

[Test]
public void ReturnObsoleteEnumInfo()
{
var tree = CSharpSyntaxTree.ParseText(@"
[Obsolete(@""test"")]
public enum A
{
A = 0,
B = 1,
}"
);

var root = (CompilationUnitSyntax)tree.GetRoot();

var enumCollector = new EnumCollector();
enumCollector.VisitEnumDeclaration(root.DescendantNodes().OfType<EnumDeclarationSyntax>().First());

var model = enumCollector.Enums.First();

Assert.That(model, Is.Not.Null) ;
Assert.That(model.Values, Is.Not.Null);

Assert.That(model.Obsolete, Is.True);
Assert.That(model.ObsoleteMessage, Is.EqualTo("test"));
}

[Test]
public void EnumBinaryValue()
{
Expand All @@ -200,12 +260,12 @@ public enum A {
Assert.That(model, Is.Not.Null);
Assert.That(model.Values, Is.Not.Null);

Assert.That(model.Values["A"], Is.EqualTo("1"));
Assert.That(model.Values["B"], Is.EqualTo("1002"));
Assert.That(model.Values["C"], Is.EqualTo("0b011"));
Assert.That(model.Values["D"], Is.EqualTo("0b00000100"));
Assert.That(model.Values["E"], Is.EqualTo("0x005"));
Assert.That(model.Values["F"], Is.EqualTo("0x00001a"));
Assert.That(model.Values["A"].Value, Is.EqualTo("1"));
Assert.That(model.Values["B"].Value, Is.EqualTo("1002"));
Assert.That(model.Values["C"].Value, Is.EqualTo("0b011"));
Assert.That(model.Values["D"].Value, Is.EqualTo("0b00000100"));
Assert.That(model.Values["E"].Value, Is.EqualTo("0x005"));
Assert.That(model.Values["F"].Value, Is.EqualTo("0x00001a"));
}

}
Expand Down
2 changes: 2 additions & 0 deletions test-files/TestFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class TestClass
/// </summary>
public int IntProperty { get; set; }

[Obsolete("obsolete test prop")]
public string StringProperty { get; set; }

public DateTime DateTimeProperty { get; set; }
Expand All @@ -29,6 +30,7 @@ public enum TestEnum {
D = 0b_0000_0100, // binary: 4 in decimal
E = 0x005, // hexadecimal: 5 in decimal
F = 0x000_01a, // hexadecimal: 26 in decimal
[Obsolete("obsolete test enum")]
G // 27 in decimal
}
}

0 comments on commit 22c4182

Please sign in to comment.