Backend/RiderPlugin/ForTea.RiderPlugin/ProtocolAware/Impl/T4ProtocolModelManager.cs (104 lines of code) (raw):
using System.Collections.Generic;
using System.Linq;
using GammaJul.ForTea.Core.Parsing;
using GammaJul.ForTea.Core.Psi.Resolve.Assemblies;
using GammaJul.ForTea.Core.Tree;
using JetBrains.Annotations;
using JetBrains.Application.Parts;
using JetBrains.ForTea.RiderPlugin.Model;
using JetBrains.ForTea.RiderPlugin.TemplateProcessing.Managing;
using JetBrains.ProjectModel;
using JetBrains.Rd.Tasks;
using JetBrains.RdBackend.Common.Features.ProjectModel;
using JetBrains.RdBackend.Common.Features.ProjectModel.View;
using JetBrains.ReSharper.Feature.Services.Protocol;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Resources.Shell;
using JetBrains.Util;
namespace JetBrains.ForTea.RiderPlugin.ProtocolAware.Impl
{
[SolutionComponent(InstantiationEx.LegacyDefault)]
public sealed class T4ProtocolModelManager
{
[NotNull] private ISolution Solution { get; }
[NotNull] private IT4TemplateCompiler Compiler { get; }
[NotNull] private IT4TargetFileManager TargetFileManager { get; }
[NotNull] private IT4BuildMessageConverter Converter { get; }
[NotNull] private IT4TemplateExecutionManager ExecutionManager { get; }
[NotNull] private IT4ProjectReferenceResolver ProjectReferenceResolver { get; }
[NotNull] private ProjectModelViewHost Host { get; }
[NotNull] private ILogger Logger { get; }
public T4ProtocolModelManager(
[NotNull] ISolution solution,
[NotNull] IT4TargetFileManager targetFileManager,
[NotNull] IT4TemplateCompiler compiler,
[NotNull] IT4BuildMessageConverter converter,
[NotNull] IT4ModelInteractionHelper helper,
[NotNull] IT4TemplateExecutionManager executionManager,
[NotNull] ILogger logger,
[NotNull] ProjectModelViewHost host,
[NotNull] IT4ProjectReferenceResolver projectReferenceResolver
)
{
Solution = solution;
TargetFileManager = targetFileManager;
Compiler = compiler;
Converter = converter;
ExecutionManager = executionManager;
Logger = logger;
ProjectReferenceResolver = projectReferenceResolver;
Host = host;
var model = solution.GetProtocolSolution().GetT4ProtocolModel();
RegisterCallbacks(model, helper);
}
private void RegisterCallbacks([NotNull] T4ProtocolModel model, [NotNull] IT4ModelInteractionHelper helper)
{
model.RequestCompilation.Set(helper.Wrap(Compile, Converter.FatalError()));
model.GetConfiguration.Set(helper.Wrap(CalculateConfiguration, new T4ConfigurationModel("", "", 0)));
model.GetProjectDependencies.Set(helper.Wrap(CalculateProjectDependencies, new List<int>()));
model.ExecutionSucceeded.Set(helper.Wrap(ExecutionSucceeded));
model.ExecutionFailed.Set(helper.Wrap(ExecutionFailed));
model.ExecutionAborted.Set(helper.Wrap(ExecutionFailed));
model.PrepareExecution.Set(helper.Wrap(PrepareExecution));
}
[CanBeNull]
private List<int> CalculateProjectDependencies([NotNull] IPsiSourceFile file) => ProjectReferenceResolver
.GetProjectDependencies(file.BuildT4Tree())
.Select(it => Host.GetIdByProjectModelElement(it))
.AsList();
[NotNull]
private T4ConfigurationModel CalculateConfiguration([NotNull] IT4File file) => new T4ConfigurationModel(
TargetFileManager.GetTemporaryExecutableLocation(file).FullPath.Replace("\\", "/"),
TargetFileManager.GetExpectedTemporaryTargetFileLocation(file).FullPath.Replace("\\", "/"),
ExecutionManager.GetEnvDTEPort(file)
);
private T4BuildResult Compile([NotNull] IPsiSourceFile sourceFile)
{
T4BuildResult result = null;
Solution.GetSolutionLifetimes().UntilSolutionCloseLifetime
.UsingNested(nested => result = Compiler.Compile(nested, sourceFile));
return result;
}
// When execution is said to succeed, we still cannot be sure whether temporary file exists or not.
// If the process being executed was the debugger process,
// it would exit normally even if the process it was debugging
// (i.e. the generated transformation process) crashed
private void ExecutionSucceeded([NotNull] IT4File file)
{
Logger.Verbose("Execution of a file succeeded");
Logger.Catch(() =>
{
// This call is not expected to fail, but just in case
using (WriteLockCookie.Create())
{
TargetFileManager.TryProcessExecutionResults(file);
}
});
ExecutionManager.OnExecutionFinished(file);
}
private void ExecutionFailed([NotNull] IT4File file)
{
Logger.Verbose("Execution of a file failed");
ExecutionManager.OnExecutionFinished(file);
}
private void PrepareExecution([NotNull] IT4File file)
{
ExecutionManager.RememberExecution(file, false);
}
}
}