示例#1
0
 public void LogError(string format, params object[] args)
 {
     #if !NET_3_5
     _buildEngine.LogErrorEvent(new BuildErrorEventArgs("Semiodesk.Trinity", "", "", 0, 0, 0, 0, string.Format(format, args), "Semiodesk", "OntologyGenerator", DateTime.Now));
     #else
     _buildEngine.LogErrorEvent(new BuildErrorEventArgs("Semiodesk.Trinity", "", "", 0, 0, 0, 0, string.Format(format, args), "Semiodesk", "OntologyGenerator"));
     #endif
 }
示例#2
0
        /// <summary>
        /// Attempts to load the specified project if it hasn't already been loaded.
        /// </summary>
        /// <param name="path">The path to the project to load.</param>
        /// <param name="toolsVersion">The ToolsVersion to use when loading the project.</param>
        /// <param name="projectCollection">The <see cref="ProjectCollection"/> to load the project into.</param>
        /// <param name="projectLoadSettings">Specifies the <see cref="ProjectLoadSettings"/> to use when loading projects.</param>
        /// <param name="project">Contains the loaded <see cref="Project"/> if one was loaded.</param>
        /// <returns><code>true</code> if the project was loaded, otherwise <code>false</code>.</returns>
        private bool TryLoadProject(string path, string toolsVersion, ProjectCollection projectCollection, ProjectLoadSettings projectLoadSettings, out Project project)
        {
            project = null;
            bool   shouldLoadProject;
            string fullPath = path.ToFullPathInCorrectCase();

            lock (_loadedProjects)
            {
                shouldLoadProject = _loadedProjects.Add(fullPath);
            }
            if (!shouldLoadProject)
            {
                return(false);
            }
            long now = DateTime.Now.Ticks;

            try
            {
                project = new Project(fullPath, null, toolsVersion, projectCollection, projectLoadSettings);
            }
            catch (InvalidProjectFileException e)
            {
                _buildEngine.LogErrorEvent(new BuildErrorEventArgs(
                                               subcategory: null,
                                               code: e.ErrorCode,
                                               file: e.ProjectFile,
                                               lineNumber: e.LineNumber,
                                               columnNumber: e.ColumnNumber,
                                               endLineNumber: e.EndLineNumber,
                                               endColumnNumber: e.EndColumnNumber,
                                               message: e.Message,
                                               helpKeyword: e.HelpKeyword,
                                               senderName: null));
                return(false);
            }
            catch (Exception e)
            {
                _buildEngine.LogErrorEvent(new BuildErrorEventArgs(
                                               subcategory: null,
                                               code: null,
                                               file: path,
                                               lineNumber: 0,
                                               columnNumber: 0,
                                               endLineNumber: 0,
                                               endColumnNumber: 0,
                                               message: e.ToString(),
                                               helpKeyword: null,
                                               senderName: null));
                return(false);
            }
            if (CollectStats)
            {
                Statistics.TryAddProjectLoadTime(path, TimeSpan.FromTicks(DateTime.Now.Ticks - now));
            }
            return(true);
        }
示例#3
0
        public void LogError(string message,
                             params object[] messageArgs)
        {
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }

            BuildErrorEventArgs beea = new BuildErrorEventArgs(
                null, null, buildEngine.ProjectFileOfTaskNode, 0, 0, 0, 0, FormatString(message, messageArgs),
                helpKeywordPrefix, null);

            buildEngine.LogErrorEvent(beea);
            hasLoggedErrors = true;
        }
示例#4
0
        static string[] GetReferences(List <string> references, IBuildEngine log)
        {
            var res = new List <string> ();

            foreach (var r in references)
            {
                if (File.Exists(r))
                {
                    res.Add(r);
                    continue;
                }

                Assembly assembly = null;

                try {
                    if (!r.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || !r.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
                    {
                        assembly = Assembly.LoadWithPartialName(r);
                    }

                    if (assembly != null)
                    {
                        res.Add(assembly.Location);
                        continue;
                    }
                } catch {
                }

                log.LogErrorEvent(new BuildErrorEventArgs("", "", "", 0, 0, 0, 0, "Assembly reference {r} could not be resolved", "", ""));
            }

            return(res.ToArray());
        }
        /// <summary>
        /// Replays the provided binlog file in the current build engine
        /// </summary>
        public static void Replay(IBuildEngine engine, string filePath)
        {
            if (File.Exists(filePath))
            {
                var replaySource = new Microsoft.Build.Logging.BinaryLogReplayEventSource();

                replaySource.MessageRaised += (s, e) => engine.LogMessageEvent(e);
                replaySource.WarningRaised += (s, e) => engine.LogWarningEvent(e);
                replaySource.ErrorRaised   += (s, e) => engine.LogErrorEvent(e);

                replaySource.Replay(filePath);
            }
        }
示例#6
0
        public Boolean Initialize(
            String taskName,
            IDictionary <String, TaskPropertyInfo> parameterGroup,
            String taskBody,
            IBuildEngine taskFactoryLoggingHost
            )
        {
            InitializationResult initResult = null;

            try
            {
                var taskBodyElement = XElement.Parse(taskBody);

                initResult = InitializeAsync(
                    new InitializationArgs(
                        taskBodyElement.ElementAnyNS(NUGET_FW)?.Value,
                        taskBodyElement.ElementAnyNS(NUGET_RID)?.Value,
                        taskBodyElement.ElementAnyNS(NUGET_FW_PACKAGE_ID)?.Value,
                        taskBodyElement.ElementAnyNS(NUGET_FW_PACKAGE_VERSION)?.Value,
                        false,
                        taskBodyElement.ElementAnyNS(NUGET_CONFIG_FILE)?.Value,
                        taskBodyElement.ElementAnyNS(PACKAGE_ID)?.Value,
                        taskBodyElement.ElementAnyNS(PACKAGE_VERSION)?.Value,
                        taskBodyElement.ElementAnyNS(PACKAGE_ID_IS_SELF)?.Value?.ParseAsBooleanSafe() ?? false,
                        taskBodyElement.ElementAnyNS(ASSEMBLY_PATH)?.Value,
                        (taskBodyElement.ElementAnyNS(TASK_NAME)?.Value).DefaultIfNullOrEmpty(taskName),
                        taskBodyElement.ElementAnyNS(TASK_METHOD_NAME)?.Value,
                        taskFactoryLoggingHost
                        )
                    ).GetAwaiter().GetResult();
            }
            catch (Exception exc)
            {
                if (taskFactoryLoggingHost == null)
                {
                    Console.Error.WriteLine("Error in initialization: " + exc);
                }
                else
                {
                    taskFactoryLoggingHost.LogErrorEvent("NMSBT001".AsNuGetMSBuildError(
                                                             taskFactoryLoggingHost.ProjectFileOfTaskNode,
                                                             null,
                                                             exc: exc
                                                             ));
                }
            }

            this._initResult = initResult;

            return(initResult != null);
        }
示例#7
0
        public void log_an_error_event_containing(string message, params object[] args)
        {
            if (build_engine == null)
            {
                return;
            }

            build_engine.LogErrorEvent(new BuildErrorEventArgs(
                                           string.Empty,
                                           string.Empty,
                                           string.Empty, 0, 0, 0, 0,
                                           string.Format(message, args),
                                           string.Empty, calling_task.GetType().Name));
        }
 /// <summary>
 /// Logs errors from TaskLoader
 /// </summary>
 private void LogErrorDelegate(string taskLocation, int taskLine, int taskColumn, string message, params object[] messageArgs)
 {
     buildEngine.LogErrorEvent(new BuildErrorEventArgs(
                                   null,
                                   null,
                                   taskLocation,
                                   taskLine,
                                   taskColumn,
                                   0,
                                   0,
                                   ResourceUtilities.FormatString(AssemblyResources.GetString(message), messageArgs),
                                   null,
                                   taskName
                                   )
                               );
 }
示例#9
0
        private void LogError(string value)
        {
            BuildErrorEventArgs error = new BuildErrorEventArgs(
                subcategory: null,
                code: null,
                file: _buildEngine.ProjectFileOfTaskNode,
                lineNumber: _buildEngine.LineNumberOfTaskNode,
                columnNumber: _buildEngine.ColumnNumberOfTaskNode,
                endLineNumber: 0,
                endColumnNumber: 0,
                message: value,
                helpKeyword: null,
                senderName: _taskName,
                eventTimestamp: DateTime.UtcNow);

            _buildEngine.LogErrorEvent(error);
            _hasLoggedErrors = true;
        }
示例#10
0
        /// <summary>
        /// The send report message.
        /// </summary>
        /// <param name="eventArgs">
        /// The event args.
        /// </param>
        /// <param name="buildEngine">
        /// The build engine.
        /// </param>
        /// <param name="senderName">
        /// The sender name.
        /// </param>
        public static void SendDeploymentMangerMessage(
            DeploymentMangerMessageEventArgs eventArgs, IBuildEngine buildEngine, string senderName)
        {
            switch (eventArgs.ReportMessageType)
            {
            case DeploymentMangerMessageType.Information:
                buildEngine.LogMessageEvent(
                    new BuildMessageEventArgs(eventArgs.Message, String.Empty, senderName, MessageImportance.Normal));
                break;

            case DeploymentMangerMessageType.Warning:
                buildEngine.LogWarningEvent(
                    new BuildWarningEventArgs(
                        "Reporting",
                        eventArgs.Method,
                        buildEngine.ProjectFileOfTaskNode,
                        buildEngine.LineNumberOfTaskNode,
                        buildEngine.ColumnNumberOfTaskNode,
                        0,
                        0,
                        eventArgs.Message,
                        String.Empty,
                        senderName));
                break;

            case DeploymentMangerMessageType.Error:

                buildEngine.LogErrorEvent(
                    new BuildErrorEventArgs(
                        "Reporting",
                        eventArgs.Method,
                        buildEngine.ProjectFileOfTaskNode,
                        buildEngine.LineNumberOfTaskNode,
                        buildEngine.ColumnNumberOfTaskNode,
                        0,
                        0,
                        eventArgs.Message,
                        String.Empty,
                        senderName));
                break;
            }
        }
        public static bool LogMessage(IBuildEngine buildEngine, BuildMessageEventArgs args)
        {
            bool success = true;
            if (args.Importance == MessageImportance.High)
            {
                int index = 0;
                using (TextReader reader = new StringReader(args.Message))
                {
                    for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
                    {
                        Match match = tsLintRegex.Match(line);
                        if (match.Success)
                        {
                            int lineNumber = int.Parse(match.Groups["LineNumber"].Value);
                            int columnNumber = int.Parse(match.Groups["ColumnNumber"].Value);
                            BuildErrorEventArgs errorArgs = new BuildErrorEventArgs(
                                string.Empty,
                                string.Empty,
                                match.Groups["FileName"].Value,
                                lineNumber,
                                columnNumber,
                                0,
                                0,
                                match.Groups["End"].Value,
                                string.Empty,
                                string.Empty);
                            buildEngine.LogErrorEvent(errorArgs);
                            success = false;
                            index++;
                            if (index == 100)
                            {
                                break;
                            }
                        }
                    }
                }
            }

            buildEngine.LogMessageEvent(args);
            return success;
        }
示例#12
0
        /// <summary>
        /// Replays the provided binlog file in the current build engine
        /// </summary>
        public static void Replay(IBuildEngine engine, string filePath, TaskLoggingHelper log)
        {
            if (File.Exists(filePath))
            {
                try
                {
                    var replaySource = new Microsoft.Build.Logging.BinaryLogReplayEventSource();

                    replaySource.MessageRaised += (s, e) => engine.LogMessageEvent(e);
                    replaySource.WarningRaised += (s, e) => engine.LogWarningEvent(e);
                    replaySource.ErrorRaised   += (s, e) => engine.LogErrorEvent(e);

                    replaySource.Replay(filePath);
                }
                catch (Exception e)
                {
                    var fileSize = File.Exists(filePath) ? new FileInfo(filePath).Length : -1;

                    log.LogWarning($"Failed to replay source generation controller build messages (path:{filePath}, size:{fileSize}) : {e}");
                }
            }
        }
示例#13
0
        private void LogBuildEvent(IssueKind issueKind, string message, MessageImportance messageImportance, string code = null,
                                   string path = null, int startLine = 0, int startColumn = 0, int endLine = 0, int endColumn = 0)
        {
            switch (issueKind)
            {
            case IssueKind.Error:
                _buildEngine.LogErrorEvent(new BuildErrorEventArgs(
                                               null, code, path, startLine, startColumn, endLine, endColumn, message, code, ProductConstants.ToolName));
                break;

            case IssueKind.Warning:
                _buildEngine.LogWarningEvent(new BuildWarningEventArgs(
                                                 null, code, path, startLine, startColumn, endLine, endColumn, message, code, ProductConstants.ToolName));
                break;

            default:
                var formattedMessage = $"[{ProductConstants.ToolName}] {message}";
                _buildEngine.LogMessageEvent(new BuildMessageEventArgs(
                                                 null, code, path, startLine, startColumn, endLine, endColumn, formattedMessage, code, ProductConstants.ToolName, messageImportance));
                break;
            }
        }
示例#14
0
 /// <inheritdoc cref="ISlnGenLogger.LogError" />
 public void LogError(string message, string code = null) => _buildEngine.LogErrorEvent(new BuildErrorEventArgs(null, code, null, 0, 0, 0, 0, message, null, null));
示例#15
0
        static bool?CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem,
                                string projectDirectory, bool verifyIl,
                                MessageImportance logImportance
                                , bool debuggerLaunch = false)
        {
            if (debuggerLaunch)
            {
                // According this https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debugger.launch?view=net-6.0#remarks
                // documentation, on not windows platform Debugger.Launch() always return true without running a debugger.
                if (System.Diagnostics.Debugger.Launch())
                {
                    // Set timeout at 1 minut.
                    var time    = new System.Diagnostics.Stopwatch();
                    var timeout = TimeSpan.FromMinutes(1);
                    time.Start();

                    // wait for the debugger to be attacked or timeout.
                    while (!System.Diagnostics.Debugger.IsAttached && time.Elapsed < timeout)
                    {
                        engine.LogMessage($"[PID:{System.Diagnostics.Process.GetCurrentProcess().Id}] Wating attach debugger. Elapsed {time.Elapsed}...", MessageImportance.High);
                        System.Threading.Thread.Sleep(100);
                    }

                    time.Stop();
                    if (time.Elapsed >= timeout)
                    {
                        engine.LogMessage("Wating attach debugger timeout.", MessageImportance.Normal);
                    }
                }
                else
                {
                    engine.LogMessage("Debugging cancelled.", MessageImportance.Normal);
                }
            }
            var asm    = typeSystem.TargetAssemblyDefinition;
            var emres  = new EmbeddedResources(asm);
            var avares = new AvaloniaResources(asm, projectDirectory);

            if (avares.Resources.Count(CheckXamlName) == 0 && emres.Resources.Count(CheckXamlName) == 0)
            {
                // Nothing to do
                return(null);
            }

            var clrPropertiesDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlHelpers",
                                                      TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            asm.MainModule.Types.Add(clrPropertiesDef);
            var indexerAccessorClosure = new TypeDefinition("CompiledAvaloniaXaml", "!IndexerAccessorFactoryClosure",
                                                            TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            asm.MainModule.Types.Add(indexerAccessorClosure);

            var(xamlLanguage, emitConfig) = AvaloniaXamlIlLanguage.Configure(typeSystem);
            var compilerConfig = new AvaloniaXamlIlCompilerConfiguration(typeSystem,
                                                                         typeSystem.TargetAssembly,
                                                                         xamlLanguage,
                                                                         XamlXmlnsMappings.Resolve(typeSystem, xamlLanguage),
                                                                         AvaloniaXamlIlLanguage.CustomValueConverter,
                                                                         new XamlIlClrPropertyInfoEmitter(typeSystem.CreateTypeBuilder(clrPropertiesDef)),
                                                                         new XamlIlPropertyInfoAccessorFactoryEmitter(typeSystem.CreateTypeBuilder(indexerAccessorClosure)),
                                                                         new DeterministicIdGenerator());


            var contextDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlContext",
                                                TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            asm.MainModule.Types.Add(contextDef);

            var contextClass = XamlILContextDefinition.GenerateContextClass(typeSystem.CreateTypeBuilder(contextDef), typeSystem,
                                                                            xamlLanguage, emitConfig);

            var compiler = new AvaloniaXamlIlCompiler(compilerConfig, emitConfig, contextClass)
            {
                EnableIlVerification = verifyIl
            };

            var editorBrowsableAttribute = typeSystem
                                           .GetTypeReference(typeSystem.FindType("System.ComponentModel.EditorBrowsableAttribute"))
                                           .Resolve();
            var editorBrowsableCtor =
                asm.MainModule.ImportReference(editorBrowsableAttribute.GetConstructors()
                                               .First(c => c.Parameters.Count == 1));

            var runtimeHelpers = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
            var createRootServiceProviderMethod = asm.MainModule.ImportReference(
                typeSystem.GetTypeReference(runtimeHelpers).Resolve().Methods
                .First(x => x.Name == "CreateRootServiceProviderV2"));

            var loaderDispatcherDef = new TypeDefinition("CompiledAvaloniaXaml", "!XamlLoader",
                                                         TypeAttributes.Class, asm.MainModule.TypeSystem.Object);


            loaderDispatcherDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor)
            {
                ConstructorArguments = { new CustomAttributeArgument(editorBrowsableCtor.Parameters[0].ParameterType, 1) }
            });


            var loaderDispatcherMethod = new MethodDefinition("TryLoad",
                                                              MethodAttributes.Static | MethodAttributes.Public,
                                                              asm.MainModule.TypeSystem.Object)
            {
                Parameters = { new ParameterDefinition(asm.MainModule.TypeSystem.String) }
            };

            loaderDispatcherDef.Methods.Add(loaderDispatcherMethod);
            asm.MainModule.Types.Add(loaderDispatcherDef);

            var stringEquals = asm.MainModule.ImportReference(asm.MainModule.TypeSystem.String.Resolve().Methods.First(
                                                                  m =>
                                                                  m.IsStatic && m.Name == "Equals" && m.Parameters.Count == 2 &&
                                                                  m.ReturnType.FullName == "System.Boolean" &&
                                                                  m.Parameters[0].ParameterType.FullName == "System.String" &&
                                                                  m.Parameters[1].ParameterType.FullName == "System.String"));

            bool CompileGroup(IResourceGroup group)
            {
                var typeDef = new TypeDefinition("CompiledAvaloniaXaml", "!" + group.Name,
                                                 TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

                typeDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor)
                {
                    ConstructorArguments = { new CustomAttributeArgument(editorBrowsableCtor.Parameters[0].ParameterType, 1) }
                });
                asm.MainModule.Types.Add(typeDef);
                var builder = typeSystem.CreateTypeBuilder(typeDef);

                foreach (var res in group.Resources.Where(CheckXamlName).OrderBy(x => x.FilePath.ToLowerInvariant()))
                {
                    try
                    {
                        engine.LogMessage($"XAMLIL: {res.Name} -> {res.Uri}", logImportance);

                        // StreamReader is needed here to handle BOM
                        var xaml   = new StreamReader(new MemoryStream(res.FileContents)).ReadToEnd();
                        var parsed = XDocumentXamlParser.Parse(xaml);

                        var initialRoot = (XamlAstObjectNode)parsed.Root;


                        var precompileDirective = initialRoot.Children.OfType <XamlAstXmlDirective>()
                                                  .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Precompile");
                        if (precompileDirective != null)
                        {
                            var precompileText = (precompileDirective.Values[0] as XamlAstTextNode)?.Text.Trim()
                                                 .ToLowerInvariant();
                            if (precompileText == "false")
                            {
                                continue;
                            }
                            if (precompileText != "true")
                            {
                                throw new XamlParseException("Invalid value for x:Precompile", precompileDirective);
                            }
                        }

                        var classDirective = initialRoot.Children.OfType <XamlAstXmlDirective>()
                                             .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Class");
                        IXamlType classType = null;
                        if (classDirective != null)
                        {
                            if (classDirective.Values.Count != 1 || !(classDirective.Values[0] is XamlAstTextNode tn))
                            {
                                throw new XamlParseException("x:Class should have a string value", classDirective);
                            }
                            classType = typeSystem.TargetAssembly.FindType(tn.Text);
                            if (classType == null)
                            {
                                throw new XamlParseException($"Unable to find type `{tn.Text}`", classDirective);
                            }
                            compiler.OverrideRootType(parsed,
                                                      new XamlAstClrTypeReference(classDirective, classType, false));
                            initialRoot.Children.Remove(classDirective);
                        }


                        compiler.Transform(parsed);
                        var populateName = classType == null ? "Populate:" + res.Name : "!XamlIlPopulate";
                        var buildName    = classType == null ? "Build:" + res.Name : null;

                        var classTypeDefinition =
                            classType == null ? null : typeSystem.GetTypeReference(classType).Resolve();


                        var populateBuilder = classTypeDefinition == null ?
                                              builder :
                                              typeSystem.CreateTypeBuilder(classTypeDefinition);
                        compiler.Compile(parsed, contextClass,
                                         compiler.DefinePopulateMethod(populateBuilder, parsed, populateName,
                                                                       classTypeDefinition == null),
                                         buildName == null ? null : compiler.DefineBuildMethod(builder, parsed, buildName, true),
                                         builder.DefineSubType(compilerConfig.WellKnownTypes.Object, "NamespaceInfo:" + res.Name,
                                                               true),
                                         (closureName, closureBaseType) =>
                                         populateBuilder.DefineSubType(closureBaseType, closureName, false),
                                         res.Uri, res
                                         );


                        if (classTypeDefinition != null)
                        {
                            var compiledPopulateMethod = typeSystem.GetTypeReference(populateBuilder).Resolve()
                                                         .Methods.First(m => m.Name == populateName);

                            var designLoaderFieldType = typeSystem
                                                        .GetType("System.Action`1")
                                                        .MakeGenericType(typeSystem.GetType("System.Object"));

                            var designLoaderFieldTypeReference = (GenericInstanceType)typeSystem.GetTypeReference(designLoaderFieldType);
                            designLoaderFieldTypeReference.GenericArguments[0] =
                                asm.MainModule.ImportReference(designLoaderFieldTypeReference.GenericArguments[0]);
                            designLoaderFieldTypeReference = (GenericInstanceType)
                                                             asm.MainModule.ImportReference(designLoaderFieldTypeReference);

                            var designLoaderLoad =
                                typeSystem.GetMethodReference(
                                    designLoaderFieldType.Methods.First(m => m.Name == "Invoke"));
                            designLoaderLoad =
                                asm.MainModule.ImportReference(designLoaderLoad);
                            designLoaderLoad.DeclaringType = designLoaderFieldTypeReference;

                            var designLoaderField = new FieldDefinition("!XamlIlPopulateOverride",
                                                                        FieldAttributes.Static | FieldAttributes.Private, designLoaderFieldTypeReference);
                            classTypeDefinition.Fields.Add(designLoaderField);

                            const string TrampolineName = "!XamlIlPopulateTrampoline";
                            var          trampoline     = new MethodDefinition(TrampolineName,
                                                                               MethodAttributes.Static | MethodAttributes.Private, asm.MainModule.TypeSystem.Void);
                            trampoline.Parameters.Add(new ParameterDefinition(classTypeDefinition));
                            classTypeDefinition.Methods.Add(trampoline);

                            var regularStart = Instruction.Create(OpCodes.Call, createRootServiceProviderMethod);

                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse, regularStart));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, designLoaderLoad));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

                            trampoline.Body.Instructions.Add(regularStart);
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, compiledPopulateMethod));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                            CopyDebugDocument(trampoline, compiledPopulateMethod);

                            var foundXamlLoader = false;
                            // Find AvaloniaXamlLoader.Load(this) and replace it with !XamlIlPopulateTrampoline(this)
                            foreach (var method in classTypeDefinition.Methods
                                     .Where(m => !m.Attributes.HasFlag(MethodAttributes.Static)))
                            {
                                var i = method.Body.Instructions;
                                for (var c = 1; c < i.Count; c++)
                                {
                                    if (i[c].OpCode == OpCodes.Call)
                                    {
                                        var op = i[c].Operand as MethodReference;

                                        // TODO: Throw an error
                                        // This usually happens when same XAML resource was added twice for some weird reason
                                        // We currently support it for dual-named default theme resource
                                        if (op != null &&
                                            op.Name == TrampolineName)
                                        {
                                            foundXamlLoader = true;
                                            break;
                                        }
                                        if (op != null &&
                                            op.Name == "Load" &&
                                            op.Parameters.Count == 1 &&
                                            op.Parameters[0].ParameterType.FullName == "System.Object" &&
                                            op.DeclaringType.FullName == "Avalonia.Markup.Xaml.AvaloniaXamlLoader")
                                        {
                                            if (MatchThisCall(i, c - 1))
                                            {
                                                i[c].Operand    = trampoline;
                                                foundXamlLoader = true;
                                            }
                                        }
                                    }
                                }
                            }

                            if (!foundXamlLoader)
                            {
                                var ctors = classTypeDefinition.GetConstructors()
                                            .Where(c => !c.IsStatic).ToList();
                                // We can inject xaml loader into default constructor
                                if (ctors.Count == 1 && ctors[0].Body.Instructions.Count(o => o.OpCode != OpCodes.Nop) == 3)
                                {
                                    var i      = ctors[0].Body.Instructions;
                                    var retIdx = i.IndexOf(i.Last(x => x.OpCode == OpCodes.Ret));
                                    i.Insert(retIdx, Instruction.Create(OpCodes.Call, trampoline));
                                    i.Insert(retIdx, Instruction.Create(OpCodes.Ldarg_0));
                                }
                                else
                                {
                                    throw new InvalidProgramException(
                                              $"No call to AvaloniaXamlLoader.Load(this) call found anywhere in the type {classType.FullName} and type seems to have custom constructors.");
                                }
                            }
                        }

                        if (buildName != null || classTypeDefinition != null)
                        {
                            var compiledBuildMethod = buildName == null ?
                                                      null :
                                                      typeSystem.GetTypeReference(builder).Resolve()
                                                      .Methods.First(m => m.Name == buildName);
                            var parameterlessConstructor = compiledBuildMethod != null ?
                                                           null :
                                                           classTypeDefinition.GetConstructors().FirstOrDefault(c =>
                                                                                                                c.IsPublic && !c.IsStatic && !c.HasParameters);

                            if (compiledBuildMethod != null || parameterlessConstructor != null)
                            {
                                var i   = loaderDispatcherMethod.Body.Instructions;
                                var nop = Instruction.Create(OpCodes.Nop);
                                i.Add(Instruction.Create(OpCodes.Ldarg_0));
                                i.Add(Instruction.Create(OpCodes.Ldstr, res.Uri));
                                i.Add(Instruction.Create(OpCodes.Call, stringEquals));
                                i.Add(Instruction.Create(OpCodes.Brfalse, nop));
                                if (parameterlessConstructor != null)
                                {
                                    i.Add(Instruction.Create(OpCodes.Newobj, parameterlessConstructor));
                                }
                                else
                                {
                                    i.Add(Instruction.Create(OpCodes.Call, createRootServiceProviderMethod));
                                    i.Add(Instruction.Create(OpCodes.Call, compiledBuildMethod));
                                }

                                i.Add(Instruction.Create(OpCodes.Ret));
                                i.Add(nop);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        int lineNumber = 0, linePosition = 0;
                        if (e is XamlParseException xe)
                        {
                            lineNumber   = xe.LineNumber;
                            linePosition = xe.LinePosition;
                        }
                        engine.LogErrorEvent(new BuildErrorEventArgs("Avalonia", "XAMLIL", res.FilePath,
                                                                     lineNumber, linePosition, lineNumber, linePosition,
                                                                     e.Message, "", "Avalonia"));
                        return(false);
                    }
                    res.Remove();
                }


                // Technically that's a hack, but it fixes corert incompatibility caused by deterministic builds
                int dupeCounter = 1;

                foreach (var grp in typeDef.NestedTypes.GroupBy(x => x.Name))
                {
                    if (grp.Count() > 1)
                    {
                        foreach (var dupe in grp)
                        {
                            dupe.Name += "_dup" + dupeCounter++;
                        }
                    }
                }


                return(true);
            }

            if (emres.Resources.Count(CheckXamlName) != 0)
            {
                if (!CompileGroup(emres))
                {
                    return(false);
                }
            }
            if (avares.Resources.Count(CheckXamlName) != 0)
            {
                if (!CompileGroup(avares))
                {
                    return(false);
                }
                avares.Save();
            }

            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
            return(true);
        }
示例#16
0
        static bool?CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem)
        {
            var asm    = typeSystem.TargetAssemblyDefinition;
            var embrsc = new EmbeddedResources(asm);

            if (embrsc.Resources.Count(CheckXamlName) == 0)
            {
                // Nothing to do
                return(null);
            }

            var xamlLanguage = new XamlLanguageTypeMappings(typeSystem)
            {
                XmlnsAttributes =
                {
                    typeSystem.GetType("Avalonia.Metadata.XmlnsDefinitionAttribute"),
                },
                ContentAttributes =
                {
                    typeSystem.GetType("Robust.Client.UserInterface.XAML.ContentAttribute")
                },
                UsableDuringInitializationAttributes =
                {
                    typeSystem.GetType("Robust.Client.UserInterface.XAML.UsableDuringInitializationAttribute")
                },
                DeferredContentPropertyAttributes =
                {
                    typeSystem.GetType("Robust.Client.UserInterface.XAML.DeferredContentAttribute")
                },
                RootObjectProvider = typeSystem.GetType("Robust.Client.UserInterface.XAML.ITestRootObjectProvider"),
                UriContextProvider = typeSystem.GetType("Robust.Client.UserInterface.XAML.ITestUriContext"),
                ProvideValueTarget = typeSystem.GetType("Robust.Client.UserInterface.XAML.ITestProvideValueTarget"),
            };
            var emitConfig = new XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult>
            {
                ContextTypeBuilderCallback = (b, c) => EmitNameScopeField(xamlLanguage, typeSystem, b, c)
            };

            var transformerconfig = new TransformerConfiguration(
                typeSystem,
                typeSystem.TargetAssembly,
                xamlLanguage,
                XamlXmlnsMappings.Resolve(typeSystem, xamlLanguage), CustomValueConverter);

            var contextDef = new TypeDefinition("CompiledRobustXaml", "XamlIlContext",
                                                TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            asm.MainModule.Types.Add(contextDef);
            var contextClass = XamlILContextDefinition.GenerateContextClass(typeSystem.CreateTypeBuilder(contextDef), typeSystem,
                                                                            xamlLanguage, emitConfig);

            var compiler =
                new RobustXamlILCompiler(transformerconfig, emitConfig, true);

            var loaderDispatcherDef = new TypeDefinition("CompiledRobustXaml", "!XamlLoader",
                                                         TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            var loaderDispatcherMethod = new MethodDefinition("TryLoad",
                                                              MethodAttributes.Static | MethodAttributes.Public,
                                                              asm.MainModule.TypeSystem.Object)
            {
                Parameters = { new ParameterDefinition(asm.MainModule.TypeSystem.String) }
            };

            loaderDispatcherDef.Methods.Add(loaderDispatcherMethod);
            asm.MainModule.Types.Add(loaderDispatcherDef);

            var stringEquals = asm.MainModule.ImportReference(asm.MainModule.TypeSystem.String.Resolve().Methods.First(
                                                                  m =>
                                                                  m.IsStatic && m.Name == "Equals" && m.Parameters.Count == 2 &&
                                                                  m.ReturnType.FullName == "System.Boolean" &&
                                                                  m.Parameters[0].ParameterType.FullName == "System.String" &&
                                                                  m.Parameters[1].ParameterType.FullName == "System.String"));

            bool CompileGroup(IResourceGroup group)
            {
                var typeDef = new TypeDefinition("CompiledRobustXaml", "!" + group.Name, TypeAttributes.Class,
                                                 asm.MainModule.TypeSystem.Object);

                //typeDef.CustomAttributes.Add(new CustomAttribute(ed));
                asm.MainModule.Types.Add(typeDef);
                var builder = typeSystem.CreateTypeBuilder(typeDef);

                foreach (var res in group.Resources.Where(CheckXamlName))
                {
                    try
                    {
                        engine.LogMessage($"XAMLIL: {res.Name} -> {res.Uri}", MessageImportance.Low);

                        var xaml   = new StreamReader(new MemoryStream(res.FileContents)).ReadToEnd();
                        var parsed = XDocumentXamlParser.Parse(xaml);

                        var initialRoot = (XamlAstObjectNode)parsed.Root;

                        var classDirective = initialRoot.Children.OfType <XamlAstXmlDirective>()
                                             .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Class");
                        string classname;
                        if (classDirective != null && classDirective.Values[0] is XamlAstTextNode tn)
                        {
                            classname = tn.Text;
                        }
                        else
                        {
                            classname = res.Name.Replace(".xaml", "");
                        }

                        var classType = typeSystem.TargetAssembly.FindType(classname);
                        if (classType == null)
                        {
                            throw new Exception($"Unable to find type '{classname}'");
                        }

                        compiler.Transform(parsed);

                        var populateName = $"Populate:{res.Name}";
                        var buildName    = $"Build:{res.Name}";

                        var classTypeDefinition = typeSystem.GetTypeReference(classType).Resolve();

                        var populateBuilder = typeSystem.CreateTypeBuilder(classTypeDefinition);

                        compiler.Compile(parsed, contextClass,
                                         compiler.DefinePopulateMethod(populateBuilder, parsed, populateName,
                                                                       classTypeDefinition == null),
                                         compiler.DefineBuildMethod(builder, parsed, buildName, true),
                                         null,
                                         (closureName, closureBaseType) =>
                                         populateBuilder.DefineSubType(closureBaseType, closureName, false),
                                         res.Uri, res
                                         );

                        //add compiled populate method
                        var compiledPopulateMethod = typeSystem.GetTypeReference(populateBuilder).Resolve().Methods
                                                     .First(m => m.Name == populateName);

                        const string TrampolineName = "!XamlIlPopulateTrampoline";
                        var          trampoline     = new MethodDefinition(TrampolineName,
                                                                           MethodAttributes.Static | MethodAttributes.Private, asm.MainModule.TypeSystem.Void);
                        trampoline.Parameters.Add(new ParameterDefinition(classTypeDefinition));
                        classTypeDefinition.Methods.Add(trampoline);

                        trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
                        trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                        trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, compiledPopulateMethod));
                        trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

                        var foundXamlLoader = false;
                        // Find RobustXamlLoader.Load(this) and replace it with !XamlIlPopulateTrampoline(this)
                        foreach (var method in classTypeDefinition.Methods
                                 .Where(m => !m.Attributes.HasFlag(MethodAttributes.Static)))
                        {
                            var i = method.Body.Instructions;
                            for (var c = 1; c < i.Count; c++)
                            {
                                if (i[c].OpCode == OpCodes.Call)
                                {
                                    var op = i[c].Operand as MethodReference;

                                    if (op != null &&
                                        op.Name == TrampolineName)
                                    {
                                        foundXamlLoader = true;
                                        break;
                                    }

                                    if (op != null &&
                                        op.Name == "Load" &&
                                        op.Parameters.Count == 1 &&
                                        op.Parameters[0].ParameterType.FullName == "System.Object" &&
                                        op.DeclaringType.FullName == "Robust.Client.UserInterface.XAML.RobustXamlLoader")
                                    {
                                        if (MatchThisCall(i, c - 1))
                                        {
                                            i[c].Operand    = trampoline;
                                            foundXamlLoader = true;
                                        }
                                    }
                                }
                            }
                        }

                        if (!foundXamlLoader)
                        {
                            var ctors = classTypeDefinition.GetConstructors()
                                        .Where(c => !c.IsStatic).ToList();
                            // We can inject xaml loader into default constructor
                            if (ctors.Count == 1 && ctors[0].Body.Instructions.Count(o => o.OpCode != OpCodes.Nop) == 3)
                            {
                                var i      = ctors[0].Body.Instructions;
                                var retIdx = i.IndexOf(i.Last(x => x.OpCode == OpCodes.Ret));
                                i.Insert(retIdx, Instruction.Create(OpCodes.Call, trampoline));
                                i.Insert(retIdx, Instruction.Create(OpCodes.Ldarg_0));
                            }
                            else
                            {
                                throw new InvalidProgramException(
                                          $"No call to RobustXamlLoader.Load(this) call found anywhere in the type {classType.FullName} and type seems to have custom constructors.");
                            }
                        }

                        //add compiled build method
                        var compiledBuildMethod = typeSystem.GetTypeReference(builder).Resolve().Methods
                                                  .First(m => m.Name == buildName);
                        var parameterlessCtor = classTypeDefinition.GetConstructors()
                                                .FirstOrDefault(c => c.IsPublic && !c.IsStatic && !c.HasParameters);

                        if (compiledBuildMethod != null && parameterlessCtor != null)
                        {
                            var i   = loaderDispatcherMethod.Body.Instructions;
                            var nop = Instruction.Create(OpCodes.Nop);
                            i.Add(Instruction.Create(OpCodes.Ldarg_0));
                            i.Add(Instruction.Create(OpCodes.Ldstr, res.Uri));
                            i.Add(Instruction.Create(OpCodes.Call, stringEquals));
                            i.Add(Instruction.Create(OpCodes.Brfalse, nop));
                            if (parameterlessCtor != null)
                            {
                                i.Add(Instruction.Create(OpCodes.Newobj, parameterlessCtor));
                            }
                            else
                            {
                                i.Add(Instruction.Create(OpCodes.Call, compiledBuildMethod));
                            }

                            i.Add(Instruction.Create(OpCodes.Ret));
                            i.Add(nop);
                        }
                    }
                    catch (Exception e)
                    {
                        engine.LogErrorEvent(new BuildErrorEventArgs("XAMLIL", "", res.FilePath, 0, 0, 0, 0,
                                                                     $"{res.FilePath}: {e.Message}", "", "CompileRobustXaml"));
                    }
                }
                return(true);
            }

            if (embrsc.Resources.Count(CheckXamlName) != 0)
            {
                if (!CompileGroup(embrsc))
                {
                    return(false);
                }
            }

            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
            return(true);
        }
示例#17
0
        public void LogError(string pattern, params object[] args)
        {
            var message = new BuildErrorEventArgs("TemplatorSyntax", "Templator001", "fileName", 0, 0, 0, 0, pattern.Format(args), string.Empty, "TemplatorSyntax");

            _engine.LogErrorEvent(message);
        }
 public void Error(string message, params object[] args)
 {
     _buildEngine.LogErrorEvent(new BuildErrorEventArgs("", "", "", 0, 0, 0, 0, Format(message, args), "", _sender));
 }
示例#19
0
        /// <inheritdoc cref="ISlnGenLogger.LogError" />
        public override void LogError(string message, string code = null)
        {
            _buildEngine.LogErrorEvent(new BuildErrorEventArgs(null, code, null, 0, 0, 0, 0, message, null, null));

            base.LogError(message, code);
        }
示例#20
0
		static string[] GetReferences (List<string> references, IBuildEngine log)
		{
			var res = new List<string> ();
			foreach (var r in references) {
				if (File.Exists (r)) {
					res.Add (r);
					continue;
				}

				Assembly assembly = null;

				try {
					if (!r.EndsWith (".dll", StringComparison.OrdinalIgnoreCase) || !r.EndsWith (".exe", StringComparison.OrdinalIgnoreCase)) {
						assembly = Assembly.LoadWithPartialName (r);
					}

					if (assembly != null) {
						res.Add (assembly.Location);
						continue;
					}
				} catch {
				}

				log.LogErrorEvent (new BuildErrorEventArgs ("", "", "", 0, 0, 0, 0, "Assembly reference {r} could not be resolved", "", ""));
			}

			return res.ToArray ();
		}
示例#21
0
 public static void LogError(this IBuildEngine engine, BuildEngineErrorCode code, string file, string message)
 {
     engine.LogErrorEvent(new BuildErrorEventArgs("Avalonia", FormatErrorCode(code), file ?? "", 0, 0, 0, 0, message,
                                                  "", "Avalonia"));
 }
 public void LogError(string message, string file = null)
 {
     ErrorOccurred = true;
     buildEngine.LogErrorEvent(new BuildErrorEventArgs("", "", file, 0, 0, 0, 0, PrependMessage(message), "", "SqlPersistenceTask"));
 }
示例#23
0
        public async Task <Boolean> ExecuteAsync(IBuildEngine be)
        {
            const String PROCESS = "NuGetUtils.MSBuild.Exec.Perform";
            // Call process, deserialize result, set output properties.
            var tempFileLocation = Path.Combine(Path.GetTempPath(), $"NuGetUtilsExec_" + Guid.NewGuid());

            Boolean retVal;

            try
            {
                await be.LogProcessInvocationMessage(PROCESS);

                var startTime = DateTime.UtcNow;

                var returnCode = await this._processMonitor.CallProcessAndStreamOutputAsync(
                    PROCESS,
                    new PerformConfiguration <String>
                {
                    NuGetConfigurationFile     = this._initializationArgs.SettingsLocation,
                    RestoreFramework           = this._environment.ThisFramework,
                    RestoreRuntimeID           = this._environment.ThisRuntimeID,
                    SDKFrameworkPackageID      = this._environment.SDKPackageID,
                    SDKFrameworkPackageVersion = this._environment.SDKPackageVersion,
                    PackageID      = this._environment.PackageID,
                    PackageVersion = this._entrypoint.ExactPackageVersion,
                    MethodToken    = this._entrypointMethod.MethodToken,
                    AssemblyPath   = this._initializationArgs.AssemblyPath,

                    ProjectFilePath       = be?.ProjectFileOfTaskNode,
                    ShutdownSemaphoreName = NuGetUtilsExecProcessMonitor.CreateNewShutdownSemaphoreName(),
                    ReturnValuePath       = tempFileLocation,
                    InputProperties       = new JObject(
                        this._propertyInfos
                        .Where(kvp => !kvp.Value.IsOutput)
                        .Select(kvp =>
                    {
                        var valInfo = kvp.Value;
                        var val     = valInfo.Value;
                        return(new JProperty(kvp.Key, valInfo.GetInputPropertyValue()));
                    })
                        ).ToString(Formatting.None),
                },
                    this._cancellationTokenSource.Token,
                    be == null?default(Func <String, Boolean, Task>) : (line, isError) =>
                {
                    if (isError)
                    {
                        be.LogErrorEvent(new BuildErrorEventArgs(
                                             null,
                                             null,
                                             null,
                                             -1,
                                             -1,
                                             -1,
                                             -1,
                                             line,
                                             null,
                                             NuGetExecutionTaskFactory.TASK_NAME
                                             ));
                    }
                    else
                    {
                        be.LogMessageEvent(new BuildMessageEventArgs(
                                               line,
                                               null,
                                               null,
                                               MessageImportance.High
                                               ));
                    }
                    return(null);
                }
                    );

                await be.LogProcessEndMessage(PROCESS, startTime);

                if (returnCode.HasValue && File.Exists(tempFileLocation))
                {
                    using (var sReader = new StreamReader(File.Open(tempFileLocation, FileMode.Open, FileAccess.Read, FileShare.None), new UTF8Encoding(false, false), false))
                        using (var jReader = new JsonTextReader(sReader))
                        {
                            foreach (var tuple in (JObject.Load(jReader)) // No LoadAsync in 9.0.0.
                                     .Properties()
                                     .Select(p => (p, this._propertyInfos.TryGetValue(p.Name, out var prop) ? prop : null))
                                     .Where(t => t.Item2?.IsOutput ?? false)
                                     )
                            {
                                var jProp = tuple.p;
                                this._propertyInfos[jProp.Name].Value = tuple.Item2.GetOutputPropertyValue(jProp.Value);
                            }
                        }
                }

                retVal = returnCode.HasValue && returnCode.Value == 0;
            }
            catch
            {
                if (this._cancellationTokenSource.IsCancellationRequested)
                {
                    retVal = false;
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                if (File.Exists(tempFileLocation))
                {
                    File.Delete(tempFileLocation);
                }
            }

            return(retVal);
        }
示例#24
0
 void LogError(String message)
 {
     buildEngine.LogErrorEvent(new BuildErrorEventArgs(null, null, null, 0, 0, 0, 0, message, null, null));
 }
示例#25
0
        public static CompileResult Compile(IBuildEngine engine, string input, string[] references, string projectDirectory,
                                            string output)
        {
            var typeSystem = new CecilTypeSystem(references.Concat(new[] { input }), input);
            var asm        = typeSystem.TargetAssemblyDefinition;
            var emres      = new EmbeddedResources(asm);
            var avares     = new AvaloniaResources(asm, projectDirectory);

            if (avares.Resources.Count(CheckXamlName) == 0 && emres.Resources.Count(CheckXamlName) == 0)
            {
                // Nothing to do
                return(new CompileResult(true));
            }

            var xamlLanguage   = AvaloniaXamlIlLanguage.Configure(typeSystem);
            var compilerConfig = new XamlIlTransformerConfiguration(typeSystem,
                                                                    typeSystem.TargetAssembly,
                                                                    xamlLanguage,
                                                                    XamlIlXmlnsMappings.Resolve(typeSystem, xamlLanguage),
                                                                    AvaloniaXamlIlLanguage.CustomValueConverter);


            var contextDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlContext",
                                                TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            asm.MainModule.Types.Add(contextDef);

            var contextClass = XamlIlContextDefinition.GenerateContextClass(typeSystem.CreateTypeBuilder(contextDef), typeSystem,
                                                                            xamlLanguage);

            var compiler = new AvaloniaXamlIlCompiler(compilerConfig, contextClass);

            var editorBrowsableAttribute = typeSystem
                                           .GetTypeReference(typeSystem.FindType("System.ComponentModel.EditorBrowsableAttribute"))
                                           .Resolve();
            var editorBrowsableCtor =
                asm.MainModule.ImportReference(editorBrowsableAttribute.GetConstructors()
                                               .First(c => c.Parameters.Count == 1));

            var runtimeHelpers = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
            var createRootServiceProviderMethod = asm.MainModule.ImportReference(
                typeSystem.GetTypeReference(runtimeHelpers).Resolve().Methods
                .First(x => x.Name == "CreateRootServiceProviderV2"));

            var loaderDispatcherDef = new TypeDefinition("CompiledAvaloniaXaml", "!XamlLoader",
                                                         TypeAttributes.Class, asm.MainModule.TypeSystem.Object);


            loaderDispatcherDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor)
            {
                ConstructorArguments = { new CustomAttributeArgument(editorBrowsableCtor.Parameters[0].ParameterType, 1) }
            });


            var loaderDispatcherMethod = new MethodDefinition("TryLoad",
                                                              MethodAttributes.Static | MethodAttributes.Public,
                                                              asm.MainModule.TypeSystem.Object)
            {
                Parameters = { new ParameterDefinition(asm.MainModule.TypeSystem.String) }
            };

            loaderDispatcherDef.Methods.Add(loaderDispatcherMethod);
            asm.MainModule.Types.Add(loaderDispatcherDef);

            var stringEquals = asm.MainModule.ImportReference(asm.MainModule.TypeSystem.String.Resolve().Methods.First(
                                                                  m =>
                                                                  m.IsStatic && m.Name == "Equals" && m.Parameters.Count == 2 &&
                                                                  m.ReturnType.FullName == "System.Boolean" &&
                                                                  m.Parameters[0].ParameterType.FullName == "System.String" &&
                                                                  m.Parameters[1].ParameterType.FullName == "System.String"));

            bool CompileGroup(IResourceGroup group)
            {
                var typeDef = new TypeDefinition("CompiledAvaloniaXaml", "!" + group.Name,
                                                 TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

                typeDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor)
                {
                    ConstructorArguments = { new CustomAttributeArgument(editorBrowsableCtor.Parameters[0].ParameterType, 1) }
                });
                asm.MainModule.Types.Add(typeDef);
                var builder = typeSystem.CreateTypeBuilder(typeDef);

                foreach (var res in group.Resources.Where(CheckXamlName))
                {
                    try
                    {
                        // StreamReader is needed here to handle BOM
                        var xaml   = new StreamReader(new MemoryStream(res.FileContents)).ReadToEnd();
                        var parsed = XDocumentXamlIlParser.Parse(xaml);

                        var initialRoot = (XamlIlAstObjectNode)parsed.Root;


                        var precompileDirective = initialRoot.Children.OfType <XamlIlAstXmlDirective>()
                                                  .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Precompile");
                        if (precompileDirective != null)
                        {
                            var precompileText = (precompileDirective.Values[0] as XamlIlAstTextNode)?.Text.Trim()
                                                 .ToLowerInvariant();
                            if (precompileText == "false")
                            {
                                continue;
                            }
                            if (precompileText != "true")
                            {
                                throw new XamlIlParseException("Invalid value for x:Precompile", precompileDirective);
                            }
                        }

                        var classDirective = initialRoot.Children.OfType <XamlIlAstXmlDirective>()
                                             .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Class");
                        IXamlIlType classType = null;
                        if (classDirective != null)
                        {
                            if (classDirective.Values.Count != 1 || !(classDirective.Values[0] is XamlIlAstTextNode tn))
                            {
                                throw new XamlIlParseException("x:Class should have a string value", classDirective);
                            }
                            classType = typeSystem.TargetAssembly.FindType(tn.Text);
                            if (classType == null)
                            {
                                throw new XamlIlParseException($"Unable to find type `{tn.Text}`", classDirective);
                            }
                            compiler.OverrideRootType(parsed,
                                                      new XamlIlAstClrTypeReference(classDirective, classType, false));
                            initialRoot.Children.Remove(classDirective);
                        }


                        compiler.Transform(parsed);
                        var populateName = classType == null ? "Populate:" + res.Name : "!XamlIlPopulate";
                        var buildName    = classType == null ? "Build:" + res.Name : null;

                        var classTypeDefinition =
                            classType == null ? null : typeSystem.GetTypeReference(classType).Resolve();


                        var populateBuilder = classTypeDefinition == null ?
                                              builder :
                                              typeSystem.CreateTypeBuilder(classTypeDefinition);
                        compiler.Compile(parsed, contextClass,
                                         compiler.DefinePopulateMethod(populateBuilder, parsed, populateName,
                                                                       classTypeDefinition == null),
                                         buildName == null ? null : compiler.DefineBuildMethod(builder, parsed, buildName, true),
                                         builder.DefineSubType(compilerConfig.WellKnownTypes.Object, "NamespaceInfo:" + res.Name,
                                                               true),
                                         (closureName, closureBaseType) =>
                                         populateBuilder.DefineSubType(closureBaseType, closureName, false),
                                         res.Uri, res
                                         );


                        if (classTypeDefinition != null)
                        {
                            var compiledPopulateMethod = typeSystem.GetTypeReference(populateBuilder).Resolve()
                                                         .Methods.First(m => m.Name == populateName);

                            var designLoaderFieldType = typeSystem
                                                        .GetType("System.Action`1")
                                                        .MakeGenericType(typeSystem.GetType("System.Object"));

                            var designLoaderFieldTypeReference = (GenericInstanceType)typeSystem.GetTypeReference(designLoaderFieldType);
                            designLoaderFieldTypeReference.GenericArguments[0] =
                                asm.MainModule.ImportReference(designLoaderFieldTypeReference.GenericArguments[0]);
                            designLoaderFieldTypeReference = (GenericInstanceType)
                                                             asm.MainModule.ImportReference(designLoaderFieldTypeReference);

                            var designLoaderLoad =
                                typeSystem.GetMethodReference(
                                    designLoaderFieldType.Methods.First(m => m.Name == "Invoke"));
                            designLoaderLoad =
                                asm.MainModule.ImportReference(designLoaderLoad);
                            designLoaderLoad.DeclaringType = designLoaderFieldTypeReference;

                            var designLoaderField = new FieldDefinition("!XamlIlPopulateOverride",
                                                                        FieldAttributes.Static | FieldAttributes.Private, designLoaderFieldTypeReference);
                            classTypeDefinition.Fields.Add(designLoaderField);

                            const string TrampolineName = "!XamlIlPopulateTrampoline";
                            var          trampoline     = new MethodDefinition(TrampolineName,
                                                                               MethodAttributes.Static | MethodAttributes.Private, asm.MainModule.TypeSystem.Void);
                            trampoline.Parameters.Add(new ParameterDefinition(classTypeDefinition));
                            classTypeDefinition.Methods.Add(trampoline);

                            var regularStart = Instruction.Create(OpCodes.Call, createRootServiceProviderMethod);

                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse, regularStart));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, designLoaderLoad));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

                            trampoline.Body.Instructions.Add(regularStart);
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, compiledPopulateMethod));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
                            CopyDebugDocument(trampoline, compiledPopulateMethod);

                            var foundXamlLoader = false;
                            // Find AvaloniaXamlLoader.Load(this) and replace it with !XamlIlPopulateTrampoline(this)
                            foreach (var method in classTypeDefinition.Methods
                                     .Where(m => !m.Attributes.HasFlag(MethodAttributes.Static)))
                            {
                                var i = method.Body.Instructions;
                                for (var c = 1; c < i.Count; c++)
                                {
                                    if (i[c].OpCode == OpCodes.Call)
                                    {
                                        var op = i[c].Operand as MethodReference;

                                        // TODO: Throw an error
                                        // This usually happens when same XAML resource was added twice for some weird reason
                                        // We currently support it for dual-named default theme resource
                                        if (op != null &&
                                            op.Name == TrampolineName)
                                        {
                                            foundXamlLoader = true;
                                            break;
                                        }
                                        if (op != null &&
                                            op.Name == "Load" &&
                                            op.Parameters.Count == 1 &&
                                            op.Parameters[0].ParameterType.FullName == "System.Object" &&
                                            op.DeclaringType.FullName == "Avalonia.Markup.Xaml.AvaloniaXamlLoader")
                                        {
                                            if (MatchThisCall(i, c - 1))
                                            {
                                                i[c].Operand    = trampoline;
                                                foundXamlLoader = true;
                                            }
                                        }
                                    }
                                }
                            }

                            if (!foundXamlLoader)
                            {
                                var ctors = classTypeDefinition.GetConstructors()
                                            .Where(c => !c.IsStatic).ToList();
                                // We can inject xaml loader into default constructor
                                if (ctors.Count == 1 && ctors[0].Body.Instructions.Count(o => o.OpCode != OpCodes.Nop) == 3)
                                {
                                    var i      = ctors[0].Body.Instructions;
                                    var retIdx = i.IndexOf(i.Last(x => x.OpCode == OpCodes.Ret));
                                    i.Insert(retIdx, Instruction.Create(OpCodes.Call, trampoline));
                                    i.Insert(retIdx, Instruction.Create(OpCodes.Ldarg_0));
                                }
                                else
                                {
                                    throw new InvalidProgramException(
                                              $"No call to AvaloniaXamlLoader.Load(this) call found anywhere in the type {classType.FullName} and type seems to have custom constructors.");
                                }
                            }
                        }

                        if (buildName != null || classTypeDefinition != null)
                        {
                            var compiledBuildMethod = buildName == null ?
                                                      null :
                                                      typeSystem.GetTypeReference(builder).Resolve()
                                                      .Methods.First(m => m.Name == buildName);
                            var parameterlessConstructor = compiledBuildMethod != null ?
                                                           null :
                                                           classTypeDefinition.GetConstructors().FirstOrDefault(c =>
                                                                                                                c.IsPublic && !c.IsStatic && !c.HasParameters);

                            if (compiledBuildMethod != null || parameterlessConstructor != null)
                            {
                                var i   = loaderDispatcherMethod.Body.Instructions;
                                var nop = Instruction.Create(OpCodes.Nop);
                                i.Add(Instruction.Create(OpCodes.Ldarg_0));
                                i.Add(Instruction.Create(OpCodes.Ldstr, res.Uri));
                                i.Add(Instruction.Create(OpCodes.Call, stringEquals));
                                i.Add(Instruction.Create(OpCodes.Brfalse, nop));
                                if (parameterlessConstructor != null)
                                {
                                    i.Add(Instruction.Create(OpCodes.Newobj, parameterlessConstructor));
                                }
                                else
                                {
                                    i.Add(Instruction.Create(OpCodes.Call, createRootServiceProviderMethod));
                                    i.Add(Instruction.Create(OpCodes.Call, compiledBuildMethod));
                                }

                                i.Add(Instruction.Create(OpCodes.Ret));
                                i.Add(nop);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        int lineNumber = 0, linePosition = 0;
                        if (e is XamlIlParseException xe)
                        {
                            lineNumber   = xe.LineNumber;
                            linePosition = xe.LinePosition;
                        }
                        engine.LogErrorEvent(new BuildErrorEventArgs("Avalonia", "XAMLIL", res.FilePath,
                                                                     lineNumber, linePosition, lineNumber, linePosition,
                                                                     e.Message, "", "Avalonia"));
                        return(false);
                    }
                    res.Remove();
                }
                return(true);
            }

            if (emres.Resources.Count(CheckXamlName) != 0)
            {
                if (!CompileGroup(emres))
                {
                    return(new CompileResult(false));
                }
            }
            if (avares.Resources.Count(CheckXamlName) != 0)
            {
                if (!CompileGroup(avares))
                {
                    return(new CompileResult(false));
                }
                avares.Save();
            }

            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

            asm.Write(output, new WriterParameters
            {
                WriteSymbols = asm.MainModule.HasSymbols
            });

            return(new CompileResult(true, true));
        }
示例#26
0
 public void LogErrorEvent(BuildErrorEventArgs e)
 {
     _buildEngine.LogErrorEvent(e);
 }