Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions AutoDI.Build/AssemblyResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public AssemblyResolver(IEnumerable<string> assembliesToInclude, ILogger logger)
_assemblyCache[assembly.Name.Name] = assembly;
}
}

logger.Info("Done loading referenced assemblies");
}

Expand All @@ -43,7 +43,7 @@ public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderPar
return assemblyDefinition;
}
assemblyDefinition = base.Resolve(name, readParameters);

if (assemblyDefinition != null)
{
_logger.Debug($"Resolved assembly {name.FullName} from '{assemblyDefinition.MainModule.FileName}'", DebugLogLevel.Verbose);
Expand Down Expand Up @@ -98,9 +98,10 @@ private AssemblyDefinition OnResolveFailure(object sender, AssemblyNameReference
assembly = Assembly.LoadWithPartialName(reference.Name);
#pragma warning restore 618
}
catch (FileNotFoundException)
catch (FileNotFoundException ex)
{
_logger.Warning($"Failed to resolve '{reference.Name}'");
var additionalInformation = StackTracer.GetStackTrace(ex);
_logger.Warning($"Failed to resolve '{reference.Name}'", additionalInformation);
assembly = null;
}

Expand Down
5 changes: 3 additions & 2 deletions AutoDI.Build/ILogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ public interface ILogger

void Debug(string message, DebugLogLevel debugLevel);
void Info(string message);
void Warning(string message);
void Error(string message);
void Warning(string message, AdditionalInformation additionalInformation = null);
//This could probably just replace the AdditionalInformation class with SequencePoint
void Error(string message, AdditionalInformation additionalInformation);
}
}
9 changes: 7 additions & 2 deletions AutoDI.Build/MultipleConstructorException.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
namespace AutoDI.Build
using Mono.Cecil;

namespace AutoDI.Build
{
internal class MultipleConstructorException : AutoDIBuildException
{
public MultipleConstructorException(string message) : base(message)
public MethodDefinition DuplicateConstructor { get; }

public MultipleConstructorException(string message, MethodDefinition duplicateContructor) : base(message)
{
DuplicateConstructor = duplicateContructor;
}
}
}
70 changes: 41 additions & 29 deletions AutoDI.Build/ProcessAssemblyTask.Container.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ partial class ProcessAssemblyTask
{
//TODO: out parameters... yuck
private TypeDefinition GenerateAutoDIClass(Mapping mapping, Settings settings, ICodeGenerator codeGenerator,
out MethodDefinition initMethod)
out MethodDefinition initMethod)
{
var containerType = new TypeDefinition(Constants.Namespace, Constants.TypeName,
TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed
| TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit)
TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed
| TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit)
{
BaseType = Import.System.Object
};

FieldDefinition globalServiceProvider =
ModuleDefinition.CreateStaticReadonlyField(Constants.GlobalServiceProviderName, false, Import.System.IServiceProvider);
ModuleDefinition.CreateStaticReadonlyField(Constants.GlobalServiceProviderName, false, Import.System.IServiceProvider);
containerType.Fields.Add(globalServiceProvider);

MethodDefinition configureMethod = GenerateAddServicesMethod(mapping, settings, containerType, codeGenerator);
Expand All @@ -40,8 +40,8 @@ private TypeDefinition GenerateAutoDIClass(Mapping mapping, Settings settings, I
private MethodDefinition GenerateAddServicesMethod(Mapping mapping, Settings settings, TypeDefinition containerType, ICodeGenerator codeGenerator)
{
var method = new MethodDefinition("AddServices",
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,
Import.System.Void);
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,
Import.System.Void);

var serviceCollection = new ParameterDefinition("collection", ParameterAttributes.None, Import.DependencyInjection.IServiceCollection);
method.Parameters.Add(serviceCollection);
Expand Down Expand Up @@ -85,13 +85,13 @@ private MethodDefinition GenerateAddServicesMethod(Mapping mapping, Settings set
Logger.Debug($"Processing map for {registration.TargetType.FullName}", DebugLogLevel.Verbose);

if (!factoryMethods.TryGetValue(registration.TargetType.FullName,
out MethodDefinition factoryMethod))
out MethodDefinition factoryMethod))
{
factoryMethod = GenerateFactoryMethod(registration.TargetType, factoryIndex, codeGenerator);
if (factoryMethod == null)
{
Logger.Debug($"No acceptable constructor for '{registration.TargetType.FullName}', skipping map",
DebugLogLevel.Verbose);
DebugLogLevel.Verbose);
continue;
}
factoryMethods[registration.TargetType.FullName] = factoryMethod;
Expand All @@ -105,8 +105,8 @@ private MethodDefinition GenerateAddServicesMethod(Mapping mapping, Settings set

TypeReference importedKey = ModuleDefinition.ImportReference(registration.Key);
Logger.Debug(
$"Mapping {importedKey.FullName} => {registration.TargetType.FullName} ({registration.Lifetime})",
DebugLogLevel.Default);
$"Mapping {importedKey.FullName} => {registration.TargetType.FullName} ({registration.Lifetime})",
DebugLogLevel.Default);
processor.Emit(OpCodes.Ldtoken, importedKey);
processor.Emit(OpCodes.Call, Import.System.Type.GetTypeFromHandle);

Expand All @@ -116,9 +116,9 @@ private MethodDefinition GenerateAddServicesMethod(Mapping mapping, Settings set
processor.Emit(OpCodes.Ldnull);
processor.Emit(OpCodes.Ldftn, factoryMethod);
processor.Emit(OpCodes.Newobj,
ModuleDefinition.ImportReference(
funcCtor.MakeGenericDeclaringType(Import.System.IServiceProvider,
ModuleDefinition.ImportReference(registration.TargetType))));
ModuleDefinition.ImportReference(
funcCtor.MakeGenericDeclaringType(Import.System.IServiceProvider,
ModuleDefinition.ImportReference(registration.TargetType))));

processor.Emit(OpCodes.Ldc_I4, (int)registration.Lifetime);

Expand Down Expand Up @@ -147,14 +147,14 @@ private MethodDefinition GenerateAddServicesMethod(Mapping mapping, Settings set
processor.Append(handlerEnd);

var exceptionHandler =
new ExceptionHandler(ExceptionHandlerType.Catch)
{
CatchType = Import.System.Exception,
TryStart = tryStart,
TryEnd = handlerStart,
HandlerStart = handlerStart,
HandlerEnd = afterCatch
};
new ExceptionHandler(ExceptionHandlerType.Catch)
{
CatchType = Import.System.Exception,
TryStart = tryStart,
TryEnd = handlerStart,
HandlerStart = handlerStart,
HandlerEnd = afterCatch
};

method.Body.ExceptionHandlers.Add(exceptionHandler);

Expand All @@ -176,11 +176,23 @@ private MethodDefinition GenerateAddServicesMethod(Mapping mapping, Settings set
}
catch (MultipleConstructorException e)
{
Logger.Error($"Failed to create map for {registration}\r\n{e}");
var additionalInformation = StackTracer.GetStackTrace(e);
if (e.DuplicateConstructor?.DebugInformation?.HasSequencePoints == true)
{
SequencePoint sequencePoint = e.DuplicateConstructor.DebugInformation.SequencePoints.First();
additionalInformation = new AdditionalInformation
{
File = sequencePoint.Document.Url,
Column = sequencePoint.StartColumn,
Line = sequencePoint.StartLine
};
}
Logger.Error($"Failed to create map for {registration}\r\n{e}", additionalInformation);
}
catch (Exception e)
{
Logger.Warning($"Failed to create map for {registration}\r\n{e}");
var additionalInformation = StackTracer.GetStackTrace(e);
Logger.Warning($"Failed to create map for {registration}\r\n{e}", additionalInformation);
}
}
}
Expand Down Expand Up @@ -229,8 +241,8 @@ private MethodDefinition GenerateFactoryMethod(TypeDefinition targetType, int in
if (targetTypeCtor == null) return null;

var factory = new MethodDefinition($"<{targetType.Name}>_generated_{index}",
MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static,
ModuleDefinition.ImportReference(targetType));
MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static,
ModuleDefinition.ImportReference(targetType));
factory.Parameters.Add(new ParameterDefinition("serviceProvider", ParameterAttributes.None, Import.System.IServiceProvider));

ILProcessor factoryProcessor = factory.Body.GetILProcessor();
Expand Down Expand Up @@ -261,8 +273,8 @@ private MethodDefinition GenerateFactoryMethod(TypeDefinition targetType, int in
private MethodDefinition GenerateInitMethod(MethodDefinition configureMethod, FieldDefinition globalServiceProvider)
{
var initMethod = new MethodDefinition(Constants.InitMethodName,
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,
Import.System.Void);
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,
Import.System.Void);
var configureAction = new ParameterDefinition("configure", ParameterAttributes.None, Import.System.Action.Type.MakeGenericInstanceType(Import.AutoDI.IApplicationBuilder.Type));
initMethod.Parameters.Add(configureAction);

Expand Down Expand Up @@ -326,8 +338,8 @@ private MethodDefinition GenerateInitMethod(MethodDefinition configureMethod, Fi
private MethodDefinition GenerateDisposeMethod(FieldDefinition globalServiceProvider)
{
var disposeMethod = new MethodDefinition("Dispose",
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,
Import.System.Void);
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,
Import.System.Void);

VariableDefinition disposable = new VariableDefinition(Import.System.IDisposable.Type);
disposeMethod.Body.Variables.Add(disposable);
Expand Down
3 changes: 2 additions & 1 deletion AutoDI.Build/ProcessAssemblyTask.Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ private Settings LoadSettings()
}
catch (SettingsParseException e)
{
Logger.Error($"Failed to parse AutoDI settings{Environment.NewLine}{e.Message}");
var additionalInformation = StackTracer.GetStackTrace(e);
Logger.Error($"Failed to parse AutoDI settings{Environment.NewLine}{e.Message}",additionalInformation);
return null;
}

Expand Down
3 changes: 2 additions & 1 deletion AutoDI.Build/ProcessAssemblyTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ protected override bool WeaveAssembly()
var sb = new StringBuilder();
for (Exception e = ex; e != null; e = e.InnerException)
sb.AppendLine(e.ToString());
Logger.Error(sb.ToString());
var additionalInformation = StackTracer.GetStackTrace(ex);
Logger.Error(sb.ToString(),additionalInformation);
return false;
}
}
Expand Down
34 changes: 34 additions & 0 deletions AutoDI.Build/StackTracer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Diagnostics;

namespace AutoDI.Build
{
public static class StackTracer
{
public static AdditionalInformation GetStackTrace(Exception exception)
{
//var trace = new StackTrace(exception, true);
//var reflectedType = trace.GetFrame(0).GetMethod().ReflectedType;
var additionalInformation = new AdditionalInformation();
//if (reflectedType != null)
//{
// additionalInformation = new AdditionalInformation()
// {
// Column = trace.GetFrame(0).GetFileColumnNumber(),
// Line = trace.GetFrame(0).GetFileLineNumber(),
// //MethodName = reflectedType.FullName,
// File = trace.GetFrame(0).GetFileName()
// };
//
//}
return additionalInformation;
}
}

public class AdditionalInformation
{
public string File { get; set; }
public int Line { get; set; }
public int Column { get; set; }
}
}
20 changes: 16 additions & 4 deletions AutoDI.Build/TaskLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ public TaskLogger(Task task)
_task = task ?? throw new ArgumentNullException(nameof(task));
}

public void Error(string message)
public void Error(string message, AdditionalInformation additionalInformation)
{
ErrorLogged = true;
_task.BuildEngine.LogErrorEvent(new BuildErrorEventArgs("", "", null, 0, 0, 0, 0, $"{MessageSender} {message}", "", MessageSender));
_task.BuildEngine.LogErrorEvent(new BuildErrorEventArgs("", "", additionalInformation.File, additionalInformation.Line, additionalInformation.Column,
additionalInformation.Line, additionalInformation.Column, $"{MessageSender} {message}", "", MessageSender));
}

public void Debug(string message, DebugLogLevel debugLevel)
Expand All @@ -38,9 +39,20 @@ public void Info(string message)
_task.BuildEngine.LogMessageEvent(new BuildMessageEventArgs($"{MessageSender} {message}", "", MessageSender, MessageImportance.Normal));
}

public void Warning(string message)
public void Warning(string message, AdditionalInformation additionalInformation)
{
_task.BuildEngine.LogWarningEvent(new BuildWarningEventArgs("", "", null, 0, 0, 0, 0, $"{MessageSender} {message}", "", MessageSender));
if (additionalInformation == null)
{
_task.BuildEngine.LogWarningEvent(new BuildWarningEventArgs("", "", null, 0, 0, 0, 0,
$"{MessageSender} {message}", "",
MessageSender));
}
else
{
_task.BuildEngine.LogWarningEvent(new BuildWarningEventArgs("", "", additionalInformation.File,
additionalInformation.Line, additionalInformation.Column, 0, 0, $"{MessageSender} {message}", "",
MessageSender));
}
}
}
}
2 changes: 1 addition & 1 deletion AutoDI.Build/TypeDefinitionMixins.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static MethodDefinition GetMappingConstructor(this TypeDefinition targetT
{
if (annotatedConstructors.Length > 1)
{
throw new MultipleConstructorException($"More then one constructor on '{targetType.Name}' annotated with DiConstructorAttribute");
throw new MultipleConstructorException($"More then one constructor on '{targetType.Name}' annotated with DiConstructorAttribute", annotatedConstructors[1]);
}
targetTypeCtor = annotatedConstructors[0];
}
Expand Down