DIForFunctions–improving generating of a constructor for a existing class with Roslyn
It is not so difficult to generate a new constructor for a existing class with Roslyn – however , there are some difficulties:
1. The original class must be declared “partial” – you cannot declare the second as partial if the first was not
2. The new class must be in the same namespace ( or without namespace) as the original
3. The constructor must have the types declared with full names / or get the usings from the existing class ( or , maybe , put the developer to use global usings: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10
For 1 the dotnet compiler shows an error – but you can add yours too:
private static bool HasPartial(ClassDeclarationSyntax cds)
{
if (cds.Modifiers.Count < 1)
return false;
foreach(var modif in cds.Modifiers)
{
if (modif.Text == “partial”)
return true;
}
return false;
}if (!HasPartial(cds))
{
var dd = new DiagnosticDescriptor(DiagnosticId, Title, “Please add partial to ” + cds.Identifier.Text, Category, DiagnosticSeverity.Error, isEnabledByDefault: true, description: “Please add partial to ” + cds.Identifier.Text);
Location? loc = cds.GetLocation();
var dg = Diagnostic.Create(dd, loc);
context.ReportDiagnostic(dg);
return;
}
For 2 is somehow more difficult
private static Tuple<string,string> NameAndNameSpace(ClassDeclarationSyntax c)
{
var nameClass = c.Identifier.Text;
var p = c.Parent;
var namespaceClass = “”;
while (true)
{
if (p is BaseNamespaceDeclarationSyntax bnsds)
{
namespaceClass = bnsds.Name.ToFullString();
break;
}
p = p?.Parent;
if (p == null)
break;
}
return Tuple.Create(nameClass, namespaceClass);
}
And verify if the namespace is null – if it is, do NOT generate namespace declaration
For 3 it is more complicated
private static string? FullTypeVar(SemanticModel? sem,TypeSyntax? ts)
{
if (sem == null)
return null;
if (ts is null)
return null;
var typeInfo = sem.GetTypeInfo(ts);
if (typeInfo.Type is null)
return null;var theType = ((INamedTypeSymbol)typeInfo.Type);
var typeField = theType?.ToDisplayString();
return typeField;
}
And that it is!