Example #1
0
        public async ThreadingTasks.Task <string> ProcessTemplateAsync(string inputFilename, string content, ITextTemplatingCallback callback, object hierarchy, bool debugging = false)
        {
            if (this is ITextTemplatingComponents Component)
            {
                Component.Hierarchy        = hierarchy;
                Component.Callback         = callback;
                Component.TemplateFile     = inputFilename;
                LastInvocationRaisedErrors = false;
                Component.Host.SetFileExtension(SearchForLanguage(content, "C#") ? ".cs" : ".vb");

                await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                try
                {
                    try
                    {
                        runFactory = await GetTransformationRunFactoryAsync(subSonicOutput.GetOutputTextWriter(), SubSonicCoreVisualStudioAsyncPackage.Singleton.CancellationTokenSource.Token);
                    }
                    catch (Exception ex)
                    {
                        await LogErrorAsync(string.Format(CultureInfo.CurrentCulture, SubSonicCoreErrors.ExceptionStartingRunFactoryProcess, ex), new Location(inputFilename));

                        runFactory = null;
                    }

                    if (runFactory == null)
                    {
                        await LogErrorAsync(SubSonicCoreErrors.ErrorStartingRunFactoryProcess, new Location(TemplateFile));

                        if (debugging)
                        {
                            ProcessTemplateEventArgs args = new ProcessTemplateEventArgs
                            {
                                TemplateOutput = SubSonicCoreErrors.DebugErrorOutput,
                                Succeeded      = false
                            };
                            this.OnTransformProcessCompleted(args);
                        }
                        return(SubSonicCoreErrors.DebugErrorOutput);
                    }

                    if (!SubSonicCoreVisualStudioAsyncPackage.Singleton.CancellationTokenSource.IsCancellationRequested)
                    {   // we have not been cancelled so let's continue
                        // we need to prepare the transformation and send the important parts over to the T4 Host Process
                        if (Engine.PrepareTransformationRunner(content, Component.Host, runFactory, debugging) is IProcessTransformationRunner runner)
                        {
                            if (!debugging)
                            {   // if we are not debugging we can wait for the process to finish
                                // and we do not need to attach to the host process.
                                try
                                {
                                    if (runFactory.StartTransformation(runner.RunnerId) is TextTemplatingCallback result)
                                    {
                                        if (result.Errors.HasErrors)
                                        {
                                            Callback.Errors.AddRange(result.Errors);

                                            foreach (var templateError in result.Errors)
                                            {
                                                await LogErrorAsync(templateError.Message, templateError.Location, templateError.IsWarning);
                                            }
                                        }

                                        Component.Callback.SetFileExtension(result.Extension);

                                        return(result.TemplateOutput);
                                    }
                                    else if (runFactory.GetErrors(runner.RunnerId) is TemplateErrorCollection errors)
                                    {
                                        Callback.Errors.AddRange(errors);

                                        foreach (var templateError in errors)
                                        {
                                            await LogErrorAsync(templateError.Message, templateError.Location, templateError.IsWarning);
                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    if (TemplatingEngine.IsCriticalException(ex))
                                    {
                                        throw;
                                    }
                                    await LogErrorAsync(ex.ToString(), new Location(Host.TemplateFile));
                                }
                                finally
                                {
                                    runFactory.DisposeOfRunner(runner.RunnerId); // clean up the runner
                                }
                            }
                            else
                            {   // when debugging this we will attach to the process
                                // the ui thread will be waiting for a callback from process to complete generation of file.
                                bool success = false;

                                try
                                {
                                    foreach (EnvDTE.Process process in package.DTE.Debugger.LocalProcesses)
                                    {
                                        if (process.ProcessID == (this.transformProcess?.Id ?? default))
                                        {
                                            process.Attach();
                                            success = true;
                                            break;
                                        }
                                    }
                                }
                                catch (Exception attachException)
                                {
                                    await LogErrorAsync(string.Format(CultureInfo.CurrentCulture, SubSonicCoreErrors.ExceptionAttachingToRunFactoryProcess, attachException), new Location(inputFilename));
                                }

                                if (success)
                                {
                                    Dispatcher uiDispatcher = Dispatcher.CurrentDispatcher;
                                    this.debugThread = new Thread(() => StartTransformation(inputFilename, runner, uiDispatcher));
                                    this.debugThread.Start();
                                }
                                else
                                {
                                    await LogErrorAsync(SubSonicCoreErrors.ErrorAttachingToRunFactoryProcess, new Location(inputFilename));

                                    ProcessTemplateEventArgs args = new ProcessTemplateEventArgs
                                    {
                                        TemplateOutput = SubSonicCoreErrors.DebugErrorOutput,
                                        Succeeded      = false
                                    };
                                    this.OnTransformProcessCompleted(args);
                                }
                            }
                        }
                        else
                        {
                            ProcessTemplateEventArgs args = new ProcessTemplateEventArgs();
                            if (debugging)
                            {
                                args.TemplateOutput = SubSonicCoreErrors.DebugErrorOutput;
                                args.Succeeded      = false;
                                this.OnTransformProcessCompleted(args);
                            }

                            await LogErrorsAsync(transformationHost.Errors.ToCompilerErrorCollection());
                        }
                    }
                }
                catch (IOException)
                {
                    if (transformProcess != null)
                    {
                        try
                        {
                            transformProcess.Kill();
                        }
                        catch (Exception)
                        { }
                        finally
                        {
                            transformProcess = null;
                        }
                    }

                    RemotingServices.Disconnect(new Uri($"ipc://{TransformationRunFactory.TransformationRunFactoryService}"));
                }
            }
            return(SubSonicCoreErrors.DebugErrorOutput);
        }