test: change methodology to have a mock assembly

This commit is contained in:
Sumanth Rayancha
2025-08-11 23:01:46 -04:00
parent 90b6f258f0
commit 4ee62088fa
9 changed files with 1826 additions and 2 deletions

View File

@@ -0,0 +1,266 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;
using System.Xml.Linq;
using Newtonsoft.Json;
namespace CrestronMockGenerator
{
public class AssemblyAnalyzer
{
private readonly string _assemblyPath;
private readonly string _xmlDocPath;
private Dictionary<string, string> _xmlDocumentation = new();
public AssemblyAnalyzer(string assemblyPath)
{
_assemblyPath = assemblyPath;
_xmlDocPath = Path.ChangeExtension(assemblyPath, ".xml");
if (File.Exists(_xmlDocPath))
{
LoadXmlDocumentation();
}
}
private void LoadXmlDocumentation()
{
try
{
var doc = XDocument.Load(_xmlDocPath);
var members = doc.Descendants("member");
foreach (var member in members)
{
var name = member.Attribute("name")?.Value;
var summary = member.Element("summary")?.Value?.Trim();
if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(summary))
{
_xmlDocumentation[name] = summary;
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error loading XML documentation: {ex.Message}");
}
}
public AssemblyInfo AnalyzeAssembly()
{
var assemblyInfo = new AssemblyInfo
{
Name = Path.GetFileNameWithoutExtension(_assemblyPath),
Types = new List<TypeInfo>()
};
try
{
// Use MetadataLoadContext to load assembly without dependencies
var resolver = new PathAssemblyResolver(new[] { _assemblyPath });
var mlc = new MetadataLoadContext(resolver);
var assembly = mlc.LoadFromAssemblyPath(_assemblyPath);
foreach (var type in assembly.GetExportedTypes())
{
if (type.IsSpecialName || type.Name.Contains("<>"))
continue;
var typeInfo = AnalyzeType(type);
if (typeInfo != null)
{
assemblyInfo.Types.Add(typeInfo);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Error analyzing assembly: {ex.Message}");
}
return assemblyInfo;
}
private TypeInfo? AnalyzeType(Type type)
{
try
{
var typeInfo = new TypeInfo
{
Name = type.Name,
Namespace = type.Namespace ?? "",
FullName = type.FullName ?? "",
IsInterface = type.IsInterface,
IsAbstract = type.IsAbstract,
IsSealed = type.IsSealed,
IsEnum = type.IsEnum,
IsClass = type.IsClass,
BaseType = type.BaseType?.FullName,
Documentation = GetDocumentation($"T:{type.FullName}"),
Properties = new List<PropertyInfo>(),
Methods = new List<MethodInfo>(),
Events = new List<EventInfo>(),
Fields = new List<FieldInfo>(),
Interfaces = type.GetInterfaces().Select(i => i.FullName).Where(n => n != null).ToList()
};
// Analyze properties
foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
{
typeInfo.Properties.Add(new PropertyInfo
{
Name = prop.Name,
Type = prop.PropertyType.FullName ?? "",
CanRead = prop.CanRead,
CanWrite = prop.CanWrite,
IsStatic = prop.GetMethod?.IsStatic ?? prop.SetMethod?.IsStatic ?? false,
Documentation = GetDocumentation($"P:{type.FullName}.{prop.Name}")
});
}
// Analyze methods
foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
.Where(m => !m.IsSpecialName))
{
var parameters = method.GetParameters().Select(p => new ParameterInfo
{
Name = p.Name ?? "",
Type = p.ParameterType.FullName ?? "",
IsOut = p.IsOut,
IsRef = p.ParameterType.IsByRef && !p.IsOut,
HasDefaultValue = p.HasDefaultValue,
DefaultValue = p.HasDefaultValue ? p.DefaultValue?.ToString() : null
}).ToList();
typeInfo.Methods.Add(new MethodInfo
{
Name = method.Name,
ReturnType = method.ReturnType.FullName ?? "",
IsStatic = method.IsStatic,
IsVirtual = method.IsVirtual,
IsAbstract = method.IsAbstract,
Parameters = parameters,
Documentation = GetDocumentation($"M:{type.FullName}.{method.Name}")
});
}
// Analyze events
foreach (var evt in type.GetEvents(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
{
typeInfo.Events.Add(new EventInfo
{
Name = evt.Name,
EventHandlerType = evt.EventHandlerType?.FullName ?? "",
Documentation = GetDocumentation($"E:{type.FullName}.{evt.Name}")
});
}
// Analyze fields (for enums)
if (type.IsEnum)
{
foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static))
{
if (field.Name == "value__") continue;
typeInfo.Fields.Add(new FieldInfo
{
Name = field.Name,
Type = field.FieldType.FullName ?? "",
Value = field.GetRawConstantValue()?.ToString(),
Documentation = GetDocumentation($"F:{type.FullName}.{field.Name}")
});
}
}
return typeInfo;
}
catch (Exception ex)
{
Console.WriteLine($"Error analyzing type {type.Name}: {ex.Message}");
return null;
}
}
private string GetDocumentation(string memberName)
{
return _xmlDocumentation.TryGetValue(memberName, out var doc) ? doc : "";
}
}
public class AssemblyInfo
{
public string Name { get; set; } = "";
public List<TypeInfo> Types { get; set; } = new();
}
public class TypeInfo
{
public string Name { get; set; } = "";
public string Namespace { get; set; } = "";
public string FullName { get; set; } = "";
public bool IsInterface { get; set; }
public bool IsAbstract { get; set; }
public bool IsSealed { get; set; }
public bool IsEnum { get; set; }
public bool IsClass { get; set; }
public string? BaseType { get; set; }
public List<string> Interfaces { get; set; } = new();
public string Documentation { get; set; } = "";
public List<PropertyInfo> Properties { get; set; } = new();
public List<MethodInfo> Methods { get; set; } = new();
public List<EventInfo> Events { get; set; } = new();
public List<FieldInfo> Fields { get; set; } = new();
}
public class PropertyInfo
{
public string Name { get; set; } = "";
public string Type { get; set; } = "";
public bool CanRead { get; set; }
public bool CanWrite { get; set; }
public bool IsStatic { get; set; }
public string Documentation { get; set; } = "";
}
public class MethodInfo
{
public string Name { get; set; } = "";
public string ReturnType { get; set; } = "";
public bool IsStatic { get; set; }
public bool IsVirtual { get; set; }
public bool IsAbstract { get; set; }
public List<ParameterInfo> Parameters { get; set; } = new();
public string Documentation { get; set; } = "";
}
public class ParameterInfo
{
public string Name { get; set; } = "";
public string Type { get; set; } = "";
public bool IsOut { get; set; }
public bool IsRef { get; set; }
public bool HasDefaultValue { get; set; }
public string? DefaultValue { get; set; }
}
public class EventInfo
{
public string Name { get; set; } = "";
public string EventHandlerType { get; set; } = "";
public string Documentation { get; set; } = "";
}
public class FieldInfo
{
public string Name { get; set; } = "";
public string Type { get; set; } = "";
public string? Value { get; set; }
public string Documentation { get; set; } = "";
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Reflection.MetadataLoadContext" Version="8.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,468 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace CrestronMockGenerator
{
public class MockGenerator
{
public string GenerateMockClass(TypeInfo typeInfo)
{
var compilationUnit = CompilationUnit();
// Add usings
compilationUnit = compilationUnit.AddUsings(
UsingDirective(ParseName("System")),
UsingDirective(ParseName("System.Collections.Generic")),
UsingDirective(ParseName("System.Linq"))
);
// Create namespace
var namespaceDeclaration = NamespaceDeclaration(ParseName(typeInfo.Namespace));
// Add XML documentation if available
var trivia = new List<SyntaxTrivia>();
if (!string.IsNullOrEmpty(typeInfo.Documentation))
{
trivia.Add(Comment($"/// <summary>"));
trivia.Add(Comment($"/// {typeInfo.Documentation}"));
trivia.Add(Comment($"/// </summary>"));
}
// Create type declaration
MemberDeclarationSyntax typeDeclaration;
if (typeInfo.IsEnum)
{
typeDeclaration = GenerateEnum(typeInfo);
}
else if (typeInfo.IsInterface)
{
typeDeclaration = GenerateInterface(typeInfo);
}
else
{
typeDeclaration = GenerateClass(typeInfo);
}
if (trivia.Any())
{
typeDeclaration = typeDeclaration.WithLeadingTrivia(trivia);
}
namespaceDeclaration = namespaceDeclaration.AddMembers(typeDeclaration);
compilationUnit = compilationUnit.AddMembers(namespaceDeclaration);
// Format the code
var workspace = new AdhocWorkspace();
var formattedNode = Microsoft.CodeAnalysis.Formatting.Formatter.Format(
compilationUnit,
workspace);
return formattedNode.ToFullString();
}
private EnumDeclarationSyntax GenerateEnum(TypeInfo typeInfo)
{
var enumDeclaration = EnumDeclaration(typeInfo.Name)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
foreach (var field in typeInfo.Fields)
{
var member = EnumMemberDeclaration(field.Name);
if (!string.IsNullOrEmpty(field.Value))
{
member = member.WithEqualsValue(
EqualsValueClause(ParseExpression(field.Value)));
}
if (!string.IsNullOrEmpty(field.Documentation))
{
member = member.WithLeadingTrivia(
Comment($"/// <summary>"),
Comment($"/// {field.Documentation}"),
Comment($"/// </summary>"));
}
enumDeclaration = enumDeclaration.AddMembers(member);
}
return enumDeclaration;
}
private InterfaceDeclarationSyntax GenerateInterface(TypeInfo typeInfo)
{
var interfaceDeclaration = InterfaceDeclaration(typeInfo.Name)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
// Add base interfaces
if (typeInfo.Interfaces.Any())
{
var baseList = BaseList();
foreach (var baseInterface in typeInfo.Interfaces)
{
var typeName = GetSimpleTypeName(baseInterface);
baseList = baseList.AddTypes(SimpleBaseType(ParseTypeName(typeName)));
}
interfaceDeclaration = interfaceDeclaration.WithBaseList(baseList);
}
// Add properties
foreach (var property in typeInfo.Properties)
{
var propertyDeclaration = GenerateInterfaceProperty(property);
interfaceDeclaration = interfaceDeclaration.AddMembers(propertyDeclaration);
}
// Add methods
foreach (var method in typeInfo.Methods)
{
var methodDeclaration = GenerateInterfaceMethod(method);
interfaceDeclaration = interfaceDeclaration.AddMembers(methodDeclaration);
}
// Add events
foreach (var evt in typeInfo.Events)
{
var eventDeclaration = GenerateInterfaceEvent(evt);
interfaceDeclaration = interfaceDeclaration.AddMembers(eventDeclaration);
}
return interfaceDeclaration;
}
private ClassDeclarationSyntax GenerateClass(TypeInfo typeInfo)
{
var classDeclaration = ClassDeclaration(typeInfo.Name)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
if (typeInfo.IsAbstract)
{
classDeclaration = classDeclaration.AddModifiers(Token(SyntaxKind.AbstractKeyword));
}
else if (typeInfo.IsSealed)
{
classDeclaration = classDeclaration.AddModifiers(Token(SyntaxKind.SealedKeyword));
}
// Add base class and interfaces
var baseTypes = new List<string>();
if (!string.IsNullOrEmpty(typeInfo.BaseType) && typeInfo.BaseType != "System.Object")
{
baseTypes.Add(typeInfo.BaseType);
}
baseTypes.AddRange(typeInfo.Interfaces);
if (baseTypes.Any())
{
var baseList = BaseList();
foreach (var baseType in baseTypes)
{
var typeName = GetSimpleTypeName(baseType);
baseList = baseList.AddTypes(SimpleBaseType(ParseTypeName(typeName)));
}
classDeclaration = classDeclaration.WithBaseList(baseList);
}
// Add properties
foreach (var property in typeInfo.Properties)
{
var propertyDeclaration = GenerateProperty(property);
classDeclaration = classDeclaration.AddMembers(propertyDeclaration);
}
// Add methods
foreach (var method in typeInfo.Methods)
{
var methodDeclaration = GenerateMethod(method, typeInfo.IsAbstract);
classDeclaration = classDeclaration.AddMembers(methodDeclaration);
}
// Add events
foreach (var evt in typeInfo.Events)
{
var eventDeclaration = GenerateEvent(evt);
classDeclaration = classDeclaration.AddMembers(eventDeclaration);
}
return classDeclaration;
}
private PropertyDeclarationSyntax GenerateProperty(PropertyInfo property)
{
var typeName = GetSimpleTypeName(property.Type);
var propertyDeclaration = PropertyDeclaration(ParseTypeName(typeName), property.Name)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
if (property.IsStatic)
{
propertyDeclaration = propertyDeclaration.AddModifiers(Token(SyntaxKind.StaticKeyword));
}
var accessors = new List<AccessorDeclarationSyntax>();
if (property.CanRead)
{
accessors.Add(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
}
if (property.CanWrite)
{
accessors.Add(AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
}
propertyDeclaration = propertyDeclaration.WithAccessorList(
AccessorList(List(accessors)));
if (!string.IsNullOrEmpty(property.Documentation))
{
propertyDeclaration = propertyDeclaration.WithLeadingTrivia(
Comment($"/// <summary>"),
Comment($"/// {property.Documentation}"),
Comment($"/// </summary>"));
}
return propertyDeclaration;
}
private PropertyDeclarationSyntax GenerateInterfaceProperty(PropertyInfo property)
{
var typeName = GetSimpleTypeName(property.Type);
var propertyDeclaration = PropertyDeclaration(ParseTypeName(typeName), property.Name);
var accessors = new List<AccessorDeclarationSyntax>();
if (property.CanRead)
{
accessors.Add(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
}
if (property.CanWrite)
{
accessors.Add(AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
}
propertyDeclaration = propertyDeclaration.WithAccessorList(
AccessorList(List(accessors)));
if (!string.IsNullOrEmpty(property.Documentation))
{
propertyDeclaration = propertyDeclaration.WithLeadingTrivia(
Comment($"/// <summary>"),
Comment($"/// {property.Documentation}"),
Comment($"/// </summary>"));
}
return propertyDeclaration;
}
private MethodDeclarationSyntax GenerateMethod(MethodInfo method, bool isAbstractClass)
{
var returnTypeName = GetSimpleTypeName(method.ReturnType);
var methodDeclaration = MethodDeclaration(ParseTypeName(returnTypeName), method.Name)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
if (method.IsStatic)
{
methodDeclaration = methodDeclaration.AddModifiers(Token(SyntaxKind.StaticKeyword));
}
else if (method.IsAbstract && isAbstractClass)
{
methodDeclaration = methodDeclaration.AddModifiers(Token(SyntaxKind.AbstractKeyword));
}
else if (method.IsVirtual)
{
methodDeclaration = methodDeclaration.AddModifiers(Token(SyntaxKind.VirtualKeyword));
}
// Add parameters
var parameters = new List<ParameterSyntax>();
foreach (var param in method.Parameters)
{
var paramTypeName = GetSimpleTypeName(param.Type);
var parameter = Parameter(Identifier(param.Name))
.WithType(ParseTypeName(paramTypeName));
if (param.IsOut)
{
parameter = parameter.AddModifiers(Token(SyntaxKind.OutKeyword));
}
else if (param.IsRef)
{
parameter = parameter.AddModifiers(Token(SyntaxKind.RefKeyword));
}
if (param.HasDefaultValue && !string.IsNullOrEmpty(param.DefaultValue))
{
parameter = parameter.WithDefault(
EqualsValueClause(ParseExpression(param.DefaultValue)));
}
parameters.Add(parameter);
}
methodDeclaration = methodDeclaration.WithParameterList(
ParameterList(SeparatedList(parameters)));
// Add body or semicolon
if (method.IsAbstract && isAbstractClass)
{
methodDeclaration = methodDeclaration.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
}
else
{
var statements = new List<StatementSyntax>();
// Add default implementation
if (returnTypeName != "void")
{
statements.Add(ParseStatement($"throw new NotImplementedException();"));
}
else
{
statements.Add(ParseStatement($"// Mock implementation"));
}
methodDeclaration = methodDeclaration.WithBody(Block(statements));
}
if (!string.IsNullOrEmpty(method.Documentation))
{
methodDeclaration = methodDeclaration.WithLeadingTrivia(
Comment($"/// <summary>"),
Comment($"/// {method.Documentation}"),
Comment($"/// </summary>"));
}
return methodDeclaration;
}
private MethodDeclarationSyntax GenerateInterfaceMethod(MethodInfo method)
{
var returnTypeName = GetSimpleTypeName(method.ReturnType);
var methodDeclaration = MethodDeclaration(ParseTypeName(returnTypeName), method.Name);
// Add parameters
var parameters = new List<ParameterSyntax>();
foreach (var param in method.Parameters)
{
var paramTypeName = GetSimpleTypeName(param.Type);
var parameter = Parameter(Identifier(param.Name))
.WithType(ParseTypeName(paramTypeName));
if (param.IsOut)
{
parameter = parameter.AddModifiers(Token(SyntaxKind.OutKeyword));
}
else if (param.IsRef)
{
parameter = parameter.AddModifiers(Token(SyntaxKind.RefKeyword));
}
parameters.Add(parameter);
}
methodDeclaration = methodDeclaration
.WithParameterList(ParameterList(SeparatedList(parameters)))
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken));
if (!string.IsNullOrEmpty(method.Documentation))
{
methodDeclaration = methodDeclaration.WithLeadingTrivia(
Comment($"/// <summary>"),
Comment($"/// {method.Documentation}"),
Comment($"/// </summary>"));
}
return methodDeclaration;
}
private EventFieldDeclarationSyntax GenerateEvent(EventInfo evt)
{
var typeName = GetSimpleTypeName(evt.EventHandlerType);
var eventDeclaration = EventFieldDeclaration(
VariableDeclaration(ParseTypeName(typeName))
.AddVariables(VariableDeclarator(evt.Name)))
.AddModifiers(Token(SyntaxKind.PublicKeyword));
if (!string.IsNullOrEmpty(evt.Documentation))
{
eventDeclaration = eventDeclaration.WithLeadingTrivia(
Comment($"/// <summary>"),
Comment($"/// {evt.Documentation}"),
Comment($"/// </summary>"));
}
return eventDeclaration;
}
private EventFieldDeclarationSyntax GenerateInterfaceEvent(EventInfo evt)
{
var typeName = GetSimpleTypeName(evt.EventHandlerType);
var eventDeclaration = EventFieldDeclaration(
VariableDeclaration(ParseTypeName(typeName))
.AddVariables(VariableDeclarator(evt.Name)));
if (!string.IsNullOrEmpty(evt.Documentation))
{
eventDeclaration = eventDeclaration.WithLeadingTrivia(
Comment($"/// <summary>"),
Comment($"/// {evt.Documentation}"),
Comment($"/// </summary>"));
}
return eventDeclaration;
}
private string GetSimpleTypeName(string fullTypeName)
{
// Convert full type names to simple names
var typeMappings = new Dictionary<string, string>
{
["System.Void"] = "void",
["System.String"] = "string",
["System.Int32"] = "int",
["System.Int64"] = "long",
["System.Int16"] = "short",
["System.UInt32"] = "uint",
["System.UInt64"] = "ulong",
["System.UInt16"] = "ushort",
["System.Byte"] = "byte",
["System.SByte"] = "sbyte",
["System.Boolean"] = "bool",
["System.Single"] = "float",
["System.Double"] = "double",
["System.Decimal"] = "decimal",
["System.Object"] = "object",
["System.Char"] = "char"
};
if (typeMappings.TryGetValue(fullTypeName, out var simpleName))
{
return simpleName;
}
// Handle generic types
if (fullTypeName.Contains('`'))
{
// Simplified generic handling
return "object";
}
// Return last part of the type name
var lastDot = fullTypeName.LastIndexOf('.');
return lastDot >= 0 ? fullTypeName.Substring(lastDot + 1) : fullTypeName;
}
}
}

View File

@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using Newtonsoft.Json;
namespace CrestronMockGenerator
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Crestron Mock Library Generator");
Console.WriteLine("================================");
if (args.Length < 2)
{
Console.WriteLine("Usage: CrestronMockGenerator <input-assembly-path> <output-directory>");
Console.WriteLine("Example: CrestronMockGenerator /path/to/SimplSharp.dll /output/mocks");
return;
}
var inputPath = args[0];
var outputDir = args[1];
if (!File.Exists(inputPath))
{
Console.WriteLine($"Error: Assembly file not found: {inputPath}");
return;
}
Directory.CreateDirectory(outputDir);
try
{
// Analyze the assembly
Console.WriteLine($"Analyzing assembly: {inputPath}");
var analyzer = new AssemblyAnalyzer(inputPath);
var assemblyInfo = analyzer.AnalyzeAssembly();
Console.WriteLine($"Found {assemblyInfo.Types.Count} types");
// Save assembly metadata as JSON
var metadataPath = Path.Combine(outputDir, $"{assemblyInfo.Name}.metadata.json");
var json = JsonConvert.SerializeObject(assemblyInfo, Formatting.Indented);
File.WriteAllText(metadataPath, json);
Console.WriteLine($"Saved metadata to: {metadataPath}");
// Generate mock classes
var generator = new MockGenerator();
var generatedFiles = new List<string>();
// Group types by namespace
var namespaceGroups = assemblyInfo.Types.GroupBy(t => t.Namespace);
foreach (var namespaceGroup in namespaceGroups)
{
var namespacePath = Path.Combine(outputDir, namespaceGroup.Key.Replace('.', Path.DirectorySeparatorChar));
Directory.CreateDirectory(namespacePath);
foreach (var typeInfo in namespaceGroup)
{
try
{
Console.WriteLine($"Generating mock for: {typeInfo.FullName}");
var mockCode = generator.GenerateMockClass(typeInfo);
var fileName = $"{typeInfo.Name}.cs";
var filePath = Path.Combine(namespacePath, fileName);
File.WriteAllText(filePath, mockCode);
generatedFiles.Add(filePath);
}
catch (Exception ex)
{
Console.WriteLine($"Error generating mock for {typeInfo.Name}: {ex.Message}");
}
}
}
// Generate project file
GenerateProjectFile(outputDir, assemblyInfo.Name);
Console.WriteLine($"\nGeneration complete!");
Console.WriteLine($"Generated {generatedFiles.Count} mock files");
Console.WriteLine($"Output directory: {outputDir}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
Console.WriteLine(ex.StackTrace);
}
}
static void GenerateProjectFile(string outputDir, string assemblyName)
{
var projectContent = @"<Project Sdk=""Microsoft.NET.Sdk"">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>" + assemblyName + @".Mock</AssemblyName>
<RootNamespace>" + assemblyName + @"</RootNamespace>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>" + assemblyName + @".Mock</PackageId>
<Version>1.0.0</Version>
<Description>Mock implementation of " + assemblyName + @" for testing</Description>
</PropertyGroup>
</Project>";
var projectPath = Path.Combine(outputDir, $"{assemblyName}.Mock.csproj");
File.WriteAllText(projectPath, projectContent);
Console.WriteLine($"Generated project file: {projectPath}");
}
}
}