private void OnCodeGenerated(UnrealModuleInfo module, UnrealModuleType moduleAssetType, string typeName, string path, CSharpTextBuilder code) { if (codeManager != null) { codeManager.OnCodeGenerated(module, moduleAssetType, typeName, path, code.ToString()); } }
public string TestMe(bool rename, string str) { CSharpTextBuilder builder = new CSharpTextBuilder(); AppendDocComment(builder, str, rename); return(builder.ToString()); }
private void GenerateCodeForStruct(UnrealModuleInfo module, UStruct unrealStruct) { bool isBlueprintType = unrealStruct.IsA <UUserDefinedStruct>() || unrealStruct.IsA <UBlueprintGeneratedClass>(); StructInfo structInfo = GetStructInfo(unrealStruct, isBlueprintType); string typeName = GetTypeName(unrealStruct); UnrealModuleType moduleAssetType; string currentNamespace = GetModuleNamespace(unrealStruct, out moduleAssetType); List <string> namespaces = GetDefaultNamespaces(); CSharpTextBuilder builder = new CSharpTextBuilder(Settings.IndentType); if (!string.IsNullOrEmpty(currentNamespace)) { builder.AppendLine("namespace " + currentNamespace); builder.OpenBrace(); } string accessSpecifier = "public"; StringBuilder modifiers = new StringBuilder(accessSpecifier); if (Settings.UseAbstractTypes && structInfo.IsClass && structInfo.Class.HasAnyClassFlags(EClassFlags.Abstract)) { modifiers.Append(" abstract"); } StringBuilder baseTypeStr = new StringBuilder(); UStruct parentStruct = unrealStruct.GetSuperStruct(); if (parentStruct != null && parentStruct != UClass.GetClass <UInterface>() && unrealStruct != UClass.GetClass <UInterface>()) { baseTypeStr.Append(GetTypeName(parentStruct, namespaces)); } if (structInfo.IsClass) { foreach (FImplementedInterface implementedInterface in structInfo.Class.Interfaces) { if (baseTypeStr.Length > 0) { baseTypeStr.Append(", "); } baseTypeStr.Append(GetTypeName(implementedInterface.InterfaceClass, namespaces)); } } if (baseTypeStr.Length > 0) { baseTypeStr.Insert(0, " : "); } AppendDocComment(builder, unrealStruct, isBlueprintType); AppendAttribute(builder, unrealStruct, module, structInfo); if (structInfo.IsInterface) { System.Diagnostics.Debug.Assert(structInfo.Class.Interfaces.Length == 0, "TODO: Interfaces inheriting other interfaces"); string baseInterface = unrealStruct == UClass.GetClass <UInterface>() ? string.Empty : (baseTypeStr.Length == 0 ? " : " : ", ") + Names.IInterface; builder.AppendLine(modifiers + " interface " + typeName + baseTypeStr + baseInterface); } else if (structInfo.IsClass) { builder.AppendLine(modifiers + " partial class " + typeName + baseTypeStr); } else { if (structInfo.StructAsClass) { builder.AppendLine(modifiers + " partial class " + typeName + " : " + Names.StructAsClass); } else { if (structInfo.IsBlittable) { string structLayout = UpdateTypeNameNamespace("StructLayout", "System.Runtime.InteropServices", namespaces); string layoutKind = UpdateTypeNameNamespace("LayoutKind", "System.Runtime.InteropServices", namespaces); builder.AppendLine("[" + structLayout + "(" + layoutKind + ".Sequential)]"); } builder.AppendLine(modifiers + " partial struct " + typeName); } } builder.OpenBrace(); string typeNameEx = structInfo.IsInterface ? typeName + "Impl" : typeName; // Create a seperate builder for building the interface "Impl" class CSharpTextBuilder interfaceImplBuilder = null; if (structInfo.IsInterface) { interfaceImplBuilder = new CSharpTextBuilder(); interfaceImplBuilder.AppendLine(accessSpecifier + " sealed class " + typeNameEx + " : " + Names.IInterfaceImpl + ", " + typeName); interfaceImplBuilder.Indent(); // Move the indent to the same as builder for this point interfaceImplBuilder.OpenBrace(); // Open the class brace } // Create a seperate builder for properties which will be inserted into the native type info initializer CSharpTextBuilder offsetsBuilder = new CSharpTextBuilder(Settings.IndentType); offsetsBuilder.AppendLine("static " + typeNameEx + "()"); offsetsBuilder.IndentCount = builder.IndentCount;// Move the indent to the same as builder offsetsBuilder.OpenBrace(); offsetsBuilder.AppendLine("if (" + Names.UnrealTypes_CanLazyLoadNativeType + "(typeof(" + typeNameEx + ")))"); offsetsBuilder.OpenBrace(); offsetsBuilder.AppendLine(Settings.VarNames.LoadNativeType + "();"); offsetsBuilder.CloseBrace(); offsetsBuilder.AppendLine(Names.UnrealTypes_OnCCtorCalled + "(typeof(" + typeNameEx + "));"); offsetsBuilder.CloseBrace(); offsetsBuilder.AppendLine(); offsetsBuilder.AppendLine("static void " + Settings.VarNames.LoadNativeType + "()"); offsetsBuilder.OpenBrace(); if (structInfo.HasStaticFunction) { builder.AppendLine("static IntPtr " + Settings.VarNames.ClassAddress + ";"); offsetsBuilder.AppendLine(Settings.VarNames.ClassAddress + " = " + (structInfo.IsStruct ? Names.NativeReflection_GetStruct : Names.NativeReflection_GetClass) + "(\"" + unrealStruct.GetPathName() + "\");"); } else { offsetsBuilder.AppendLine("IntPtr " + Settings.VarNames.ClassAddress + " = " + (structInfo.IsStruct ? Names.NativeReflection_GetStruct : Names.NativeReflection_GetClass) + "(\"" + unrealStruct.GetPathName() + "\");"); } if (structInfo.StructAsClass) { offsetsBuilder.AppendLine(typeName + Settings.VarNames.StructAddress + " = " + Settings.VarNames.ClassAddress + ";"); } else if (structInfo.IsStruct) { offsetsBuilder.AppendLine(typeName + Settings.VarNames.StructSize + " = " + Names.NativeReflection_GetStructSize + "(" + Settings.VarNames.ClassAddress + ");"); } if (structInfo.IsStruct && parentStruct != null) { // Export base properties if (Settings.InlineBaseStruct || structInfo.StructAsClass) { UScriptStruct tempParentStruct = parentStruct as UScriptStruct; while (tempParentStruct != null) { StructInfo tempParentStructInfo = GetStructInfo(tempParentStruct); if (tempParentStructInfo != null) { foreach (UProperty property in tempParentStructInfo.GetProperties()) { if (!tempParentStructInfo.IsCollapsedProperty(property)) { GenerateCodeForProperty(module, builder, offsetsBuilder, property, tempParentStructInfo.IsBlueprintType, structInfo, namespaces, tempParentStructInfo.GetPropertyName(property)); } } } tempParentStruct = tempParentStruct.GetSuperStruct() as UScriptStruct; } } else { builder.AppendLine(GetTypeName(parentStruct, namespaces) + " Base;"); } } // Export properties foreach (UProperty property in structInfo.GetProperties()) { if (!structInfo.IsCollapsedProperty(property)) { GenerateCodeForProperty(module, builder, offsetsBuilder, property, isBlueprintType, structInfo, namespaces, structInfo.GetPropertyName(property)); } } foreach (CollapsedMember collapsedMember in structInfo.GetCollapsedMembers()) { GenerateCodeForProperty(module, builder, offsetsBuilder, collapsedMember, isBlueprintType, namespaces); } // Export functions List <ExtensionMethodInfo> extensionMethods = new List <ExtensionMethodInfo>(); foreach (UFunction function in structInfo.GetFunctions()) { if (!structInfo.IsCollapsedFunction(function)) { if (!structInfo.IsInterface) { // If this isn't an interface and the function can be made into an extension method then do so ExtensionMethodInfo extensionMethodInfo = ExtensionMethodInfo.Create(function); if (extensionMethodInfo != null) { extensionMethods.Add(extensionMethodInfo); } } if (function.HasAnyFunctionFlags(EFunctionFlags.Delegate | EFunctionFlags.MulticastDelegate)) { AppendDelegateSignature(module, builder, function, unrealStruct, isBlueprintType, namespaces); builder.AppendLine(); } else if (structInfo.IsInterface) { AppendFunctionOffsets(interfaceImplBuilder, offsetsBuilder, function, false, false, namespaces); AppendDocComment(builder, function, isBlueprintType); AppendAttribute(builder, function, module); builder.AppendLine(GetFunctionSignature(module, function, unrealStruct, namespaces) + ";"); builder.AppendLine(); // Always require a per-instance function address on the interfaces "Impl" class. // This isn't really required if the target function isn't an event but since we are working // with interfaces it is probably best to make sure functions are resolved properly. If we decide // to change this to not require a per-instance function address make sure to update AppendFunctionOffsets // which adds the per-instance function address to the class. Also update AssemblyRewriter.Interface.cs // Also update the "ResetInterface" code which always expects an per-instance address to reset. AppendAttribute(interfaceImplBuilder, function, module); interfaceImplBuilder.AppendLine(GetFunctionSignature(module, function, unrealStruct, null, "public", FunctionSigFlags.None, namespaces)); interfaceImplBuilder.OpenBrace(); AppendFunctionBody(interfaceImplBuilder, function, false, false, true, namespaces); interfaceImplBuilder.CloseBrace(); builder.AppendLine(); } else { AppendFunctionOffsets(builder, offsetsBuilder, function, false, false, namespaces); AppendDocComment(builder, function, isBlueprintType); AppendAttribute(builder, function, module); bool hasSuperFunction = function.GetSuperFunction() != null; if (function.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent) && !hasSuperFunction) { // Define the declaration method which will call the correct UFunction for the UObject instance builder.AppendLine(GetFunctionSignature(module, function, unrealStruct, namespaces)); builder.OpenBrace(); AppendFunctionBody(builder, function, false, false, true, namespaces); builder.CloseBrace(); builder.AppendLine(); } if (function.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent)) { if (!Settings.UseExplicitImplementationMethods) { // Used to hide the _Implementation method from being visible in intellisense builder.AppendLine("[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]"); } // Define the _Implementation method builder.AppendLine(GetFunctionSignatureImpl(module, function, unrealStruct, namespaces)); } else { builder.AppendLine(GetFunctionSignature(module, function, unrealStruct, namespaces)); } builder.OpenBrace(); AppendFunctionBody(builder, function, false, false, false, namespaces); builder.CloseBrace(); builder.AppendLine(); } } } if (structInfo.StructAsClass) { if (Settings.GenerateIsValidSafeguards) { builder.AppendLine("static bool " + typeName + Settings.VarNames.IsValid + ";"); // Append XXXX_IsValid = Prop1_IsValid && Prop2_IsValid && Prop3_IsValid...; AppendStructIsValid(offsetsBuilder, typeName, structInfo, parentStruct); } builder.AppendLine("static IntPtr " + typeName + Settings.VarNames.StructAddress + ";"); builder.AppendLine(); builder.AppendLine("protected override IntPtr GetStructAddress()"); builder.OpenBrace(); builder.AppendLine("return " + typeName + Settings.VarNames.StructAddress + ";"); builder.CloseBrace(); builder.AppendLine(); } else if (structInfo.IsStruct) { if (Settings.GenerateIsValidSafeguards && !structInfo.IsBlittable) { builder.AppendLine("static bool " + typeName + Settings.VarNames.IsValid + ";"); } builder.AppendLine("static int " + typeName + Settings.VarNames.StructSize + ";"); builder.AppendLine(); // Add the struct Copy() method (for non blittable structs) builder.AppendLine("public " + typeName + " " + Settings.VarNames.StructCopy + "()"); builder.OpenBrace(); builder.AppendLine(typeName + " result = this;"); foreach (UProperty property in structInfo.GetProperties()) { if (!structInfo.IsCollapsedProperty(property) && IsCollectionProperty(property)) { string propertyName = GetMemberName(property, structInfo.GetPropertyName(property)); builder.AppendLine("if (this." + propertyName + " != null)"); builder.OpenBrace(); UStructProperty structProperty = property as UStructProperty; StructInfo propertyStructInfo = structProperty == null || structProperty.Struct == null ? null : GetStructInfo(structProperty.Struct); if (propertyStructInfo != null && !propertyStructInfo.IsBlittable) { builder.AppendLine("result." + propertyName + " = new " + GetTypeName(property, namespaces) + "();"); builder.AppendLine("for (int i = 0; i < this." + propertyName + ".Count; ++i)"); builder.OpenBrace(); builder.AppendLine("result." + propertyName + ".Add(this." + propertyName + "[i]." + Settings.VarNames.StructCopy + "());"); builder.CloseBrace(); } else { builder.AppendLine("result." + propertyName + " = new " + GetTypeName(property, namespaces) + "(" + "this." + propertyName + ");"); } builder.CloseBrace(); } } if (Settings.InlineBaseStruct) { UScriptStruct tempParentStruct = parentStruct as UScriptStruct; while (tempParentStruct != null) { StructInfo tempParentStructInfo = GetStructInfo(tempParentStruct); if (tempParentStructInfo != null) { foreach (UProperty property in tempParentStructInfo.GetProperties()) { if (!tempParentStructInfo.IsCollapsedProperty(property) && IsCollectionProperty(property)) { string propertyName = GetMemberName(property, tempParentStructInfo.GetPropertyName(property)); builder.AppendLine("if (this." + propertyName + " != null)"); builder.OpenBrace(); builder.AppendLine("result." + propertyName + " = new " + GetTypeName(property, namespaces) + "(" + "this." + propertyName + ");"); builder.CloseBrace(); } } } tempParentStruct = tempParentStruct.GetSuperStruct() as UScriptStruct; } } builder.AppendLine("return result;"); builder.CloseBrace(); builder.AppendLine(); if (structInfo.IsBlittable) { // Validate the size of the blittable struct offsetsBuilder.AppendLine(Names.NativeReflection_ValidateBlittableStructSize + "(" + Settings.VarNames.ClassAddress + ", typeof(" + typeName + "));"); } else { if (Settings.GenerateIsValidSafeguards) { // Append XXXX_IsValid = Prop1_IsValid && Prop2_IsValid && Prop3_IsValid...; AppendStructIsValid(offsetsBuilder, typeName, structInfo, parentStruct); } builder.AppendLine("public static " + typeName + " FromNative(IntPtr nativeBuffer)"); builder.OpenBrace(); builder.AppendLine("return new " + typeName + "(nativeBuffer);"); builder.CloseBrace(); builder.AppendLine(); builder.AppendLine("public static void ToNative(IntPtr nativeBuffer, " + typeName + " value)"); builder.OpenBrace(); builder.AppendLine("value.ToNative(nativeBuffer);"); builder.CloseBrace(); builder.AppendLine(); builder.AppendLine("public static " + typeName + " FromNative(IntPtr nativeBuffer, int arrayIndex, IntPtr prop)"); builder.OpenBrace(); builder.AppendLine("return new " + typeName + "(nativeBuffer + (arrayIndex * " + typeName + Settings.VarNames.StructSize + "));"); builder.CloseBrace(); builder.AppendLine(); builder.AppendLine("public static void ToNative(IntPtr nativeBuffer, int arrayIndex, IntPtr prop, " + typeName + " value)"); builder.OpenBrace(); builder.AppendLine("value.ToNative(nativeBuffer + (arrayIndex * " + typeName + Settings.VarNames.StructSize + "));"); builder.CloseBrace(); builder.AppendLine(); builder.AppendLine("public void ToNative(IntPtr nativeStruct)"); builder.OpenBrace(); AppendStructMarshalerBody(builder, typeName, structInfo, parentStruct, true, namespaces); builder.CloseBrace(); builder.AppendLine(); builder.AppendLine("public " + typeName + "(IntPtr nativeStruct)"); builder.OpenBrace(); /*if (Settings.UObjectAsBlittableType) * { * // UObject types will have an additional backing field which needs to be assigned before being able to * // assign the property * // - The alternative would be to modify the property assignment code to target the backing field instead of * // the property. This is probably the ideal way of doing it but we would need to use a different marshaler * // (BlittableTypeMarshaler<> instead of UObjectMarshaler<>) and ensure the marshaler change doesn't impact * // other generated code elsewhere. * foreach (UProperty property in structInfo.GetProperties()) * { * UObjectProperty objectProperty = property as UObjectProperty; * if (objectProperty != null) * { * string propertyName = GetMemberName(property, structInfo.GetPropertyName(property)); * builder.AppendLine(propertyName + Settings.VarNames.UObjectBlittableName + " = IntPtr.Zero;"); * } * } * }*/ AppendStructMarshalerBody(builder, typeName, structInfo, parentStruct, false, namespaces); builder.CloseBrace(); builder.AppendLine(); } } if (loadNativeTypeInjected.Contains(typeName)) { offsetsBuilder.AppendLine(Settings.VarNames.LoadNativeTypeInjected + "(" + Settings.VarNames.ClassAddress + ");"); } offsetsBuilder.CloseBrace(); // Add the offsets builder if it isn't empty (always required for structs due to struct size export) // Interfaces are built up seperately in a different class which must be added after the interface body. if (!structInfo.IsInterface && (structInfo.HasContent || structInfo.IsStruct)) { builder.AppendLine(offsetsBuilder.ToString()); builder.AppendLine(); } // Remove any trailing empty lines before adding the close brace builder.RemovePreviousEmptyLines(); builder.CloseBrace(); // Add the "Impl" wrapper class for interfaces. This is always required so that we have a default // interface implementation that we can call. if (structInfo.IsInterface) { if (structInfo.HasContent) { interfaceImplBuilder.AppendLine();// Whitespace // Add the ResetInterface method to reset the state of a pooled interface instance interfaceImplBuilder.AppendLine("public override void ResetInterface()"); interfaceImplBuilder.OpenBrace(); foreach (UFunction function in structInfo.GetFunctions()) { interfaceImplBuilder.AppendLine(GetFunctionName(function) + Settings.VarNames.InstanceFunctionAddress + " = IntPtr.Zero;"); } interfaceImplBuilder.CloseBrace(); interfaceImplBuilder.AppendLine(); // Whitespace } interfaceImplBuilder.AppendLine(offsetsBuilder.ToString()); // Add the offsets to the "Impl" class interfaceImplBuilder.CloseBrace(); // Add the close brace for the "Impl" class builder.AppendLine(); // Empty line between interface and "Impl" class builder.AppendLine(interfaceImplBuilder.ToString()); // Add the "Impl" class below the interface } if (!string.IsNullOrEmpty(currentNamespace)) { builder.CloseBrace(); } builder.InsertNamespaces(currentNamespace, namespaces, Settings.SortNamespaces); OnCodeGenerated(module, moduleAssetType, typeName, unrealStruct.GetPathName(), builder); if (extensionMethods.Count > 0) { GenerateCodeForExtensionMethods(module, unrealStruct, extensionMethods); } }
public void OnCodeGenerated(CodeGenerator.UnrealModuleInfo module, UnrealModuleType moduleAssetType, string typeName, string path, CSharpTextBuilder code) { // Note: path will be empty if using combined enums file or global delegates files string root, directory, moduleName, assetName, memberName; FPackageName.GetPathInfo(path, out root, out directory, out moduleName, out assetName, out memberName); //Log("path:'{0}' root:'{1}' directory:'{2}' asset:'{3}' member:'{4}'", path, root, directory, assetName, memberName); string rootFolderName = GetRootFolderName(path, root, module.Type, moduleAssetType); if (string.IsNullOrEmpty(rootFolderName) && !string.IsNullOrEmpty(path)) { Log(ELogVerbosity.Error, "Unknown asset root '{0}' ModuleType:'{1}' ModuleAssetType:'{2}' Path:'{3}'", root, module.Type, moduleAssetType, path); return; } string name = Settings.UseTypeNameAsSourceFileName || string.IsNullOrEmpty(assetName) ? typeName : assetName; string sourceFilePath = null; string projPath = null; string slnPath = null; switch (module.Type) { case UnrealModuleType.Game: { string relativeSourceFilePath = null; if (EmulateGameFolderStructure(moduleAssetType)) { relativeSourceFilePath = Path.Combine(directory, name + ".cs"); } else { relativeSourceFilePath = name + ".cs"; } sourceFilePath = Path.Combine(Settings.GetGeneratedCodeDir(), rootFolderName, relativeSourceFilePath); slnPath = GameSlnPath; projPath = GameProjPath; } break; case UnrealModuleType.EnginePlugin: case UnrealModuleType.Engine: { bool mergeAsPluginProj = false; bool mergeAsUnrealProj = false; switch (Settings.EngineProjMerge) { case CodeGeneratorSettings.ManagedEngineProjMerge.Engine: if (module.Type == UnrealModuleType.Engine) { mergeAsUnrealProj = true; } break; case CodeGeneratorSettings.ManagedEngineProjMerge.Plugins: if (module.Type == UnrealModuleType.EnginePlugin) { mergeAsPluginProj = true; } break; case CodeGeneratorSettings.ManagedEngineProjMerge.EngineAndPlugins: if (module.Type == UnrealModuleType.EnginePlugin) { mergeAsPluginProj = true; } else { mergeAsUnrealProj = true; } break; case CodeGeneratorSettings.ManagedEngineProjMerge.EngineAndPluginsCombined: mergeAsUnrealProj = true; break; } if (mergeAsPluginProj || mergeAsUnrealProj) { string projName = mergeAsUnrealProj ? "UnrealEngine.csproj" : "UnrealEngine.Plugins.csproj"; if (Settings.EngineProjMerge == CodeGeneratorSettings.ManagedEngineProjMerge.EngineAndPluginsCombined) { projPath = Path.Combine(Settings.GetManagedModulesDir(), projName); } else { projPath = Path.Combine(Settings.GetManagedModulesDir(), rootFolderName, projName); } } else { projPath = Path.Combine(Settings.GetManagedModulesDir(), rootFolderName, module.Name, module.Name + ".csproj"); } sourceFilePath = Path.Combine(Settings.GetManagedModulesDir(), rootFolderName, module.Name, name + ".cs"); if (Settings.ModulesLocation == CodeGeneratorSettings.ManagedModulesLocation.GameFolderCombineSln) { slnPath = GameSlnPath; } else if (Settings.ModulesLocation == CodeGeneratorSettings.ManagedModulesLocation.GameFolderCombineSlnProj) { slnPath = GameSlnPath; projPath = GameProjPath; } else { slnPath = Path.Combine(Settings.GetManagedModulesDir(), "UnrealEngine.sln"); } } break; case UnrealModuleType.GamePlugin: { sourceFilePath = Path.Combine(Settings.GetGeneratedCodeDir(), rootFolderName, module.Name, name + ".cs"); slnPath = GameSlnPath; if (Settings.GameProjMerge == CodeGeneratorSettings.ManagedGameProjMerge.GameAndPlugins) { projPath = GameProjPath; } else if (Settings.GameProjMerge == CodeGeneratorSettings.ManagedGameProjMerge.Plugins) { projPath = Path.Combine(Settings.GetManagedDir(), rootFolderName, "GamePlugins.csproj"); } else { projPath = Path.Combine(Settings.GetManagedDir(), rootFolderName, module.Name, module.Name + ".csproj"); } } break; } if (!string.IsNullOrWhiteSpace(sourceFilePath)) { sourceFilePath = Path.GetFullPath(sourceFilePath); } if (!string.IsNullOrWhiteSpace(projPath)) { projPath = Path.GetFullPath(projPath); } if (!string.IsNullOrWhiteSpace(slnPath)) { slnPath = Path.GetFullPath(slnPath); } if (string.IsNullOrWhiteSpace(sourceFilePath) || string.IsNullOrWhiteSpace(projPath) || string.IsNullOrWhiteSpace(slnPath)) { Log(ELogVerbosity.Error, "Unknown output location for '{0}' '{1}'", typeName, path); } else if (!ValidateOutputPath(sourceFilePath) || !ValidateOutputPath(projPath) || !ValidateOutputPath(slnPath)) { Log(ELogVerbosity.Error, "Invalid output path '{0}'", sourceFilePath); } else { //FMessage.Log(ELogVerbosity.Log, sourceFilePath + " | " + projPath + " | " + slnPath); try { if (UpdateSolutionAndProject(slnPath, projPath)) { if (!AddSourceFile(slnPath, projPath, sourceFilePath, code.ToString())) { Log(ELogVerbosity.Error, "Failed to add source file '{0}'", sourceFilePath); } } else { Log(ELogVerbosity.Error, "Failed to create sln/csproj '{0}' '{1}'", slnPath, projPath); } } catch (Exception e) { Log(ELogVerbosity.Error, "Exception when adding source file '{0}' {1}", sourceFilePath, e); } } }