using System; using System.Collections.Generic; using GammaJul.ForTea.Core.Parsing; using GammaJul.ForTea.Core.TemplateProcessing.CodeCollecting.Interrupt; using GammaJul.ForTea.Core.Tree; using JetBrains.Annotations; using JetBrains.Application.Parts; using JetBrains.Application.Threading; using JetBrains.Diagnostics; using JetBrains.ForTea.RiderPlugin.Model; using JetBrains.ForTea.RiderPlugin.TemplateProcessing.CodeGeneration; using JetBrains.ForTea.RiderPlugin.TemplateProcessing.Managing; using JetBrains.ProjectModel; using JetBrains.RdBackend.Common.Features.ProjectModel.View; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.Tree; using JetBrains.ReSharper.Resources.Shell; using JetBrains.Util; using JetBrains.Util.dataStructures; namespace JetBrains.ForTea.RiderPlugin.ProtocolAware.Services.Impl { [SolutionComponent(Instantiation.DemandAnyThreadUnsafe)] public sealed class T4TemplatePreprocessingManager : IT4TemplatePreprocessingManager { private DateTime PreviousExecutedFileWriteTime { get; set; } [NotNull] private IT4TargetFileManager TargetFileManager { get; } [NotNull] private IT4BuildMessageConverter BuildMessageConverter { get; } [NotNull] private ILogger Logger { get; } public T4TemplatePreprocessingManager( [NotNull] IT4TargetFileManager targetFileManager, [NotNull] ILogger logger, [NotNull] IT4BuildMessageConverter buildMessageConverter ) { TargetFileManager = targetFileManager; Logger = logger; BuildMessageConverter = buildMessageConverter; } public void TryPreprocess(IT4File file) { Logger.Verbose("Trying to preprocess a file"); var psiSourceFile = file.PhysicalPsiSourceFile.NotNull(); var lastWriteTimeUtc = psiSourceFile.LastWriteTimeUtc; if (lastWriteTimeUtc == PreviousExecutedFileWriteTime) return; PreviousExecutedFileWriteTime = lastWriteTimeUtc; Preprocess(file); } public T4PreprocessingResult Preprocess(IT4File file) { Logger.Verbose("Preprocessing a file"); var psiSourceFile = file.PhysicalPsiSourceFile.NotNull(); var projectFile = psiSourceFile.ToProjectFile().NotNull(); var solution = file.GetSolution(); var contextFreeTree = psiSourceFile.BuildT4Tree(); var location = new T4FileLocation(solution.GetComponent().GetIdByItem(projectFile)); try { string message = T4RiderCodeGeneration.GeneratePreprocessedCode(contextFreeTree).RawText; solution.Locks.ExecuteOrQueueEx(solution.GetSolutionLifetimes().UntilSolutionCloseLifetime, "T4 template preprocessing", () => { using (WriteLockCookie.Create()) { TargetFileManager.SavePreprocessResults(file, message); } }); return new T4PreprocessingResult(location, true, new List()); } catch (T4OutputGenerationException e) { var message = BuildMessageConverter.ToT4BuildMessages(e.FailureDatum.AsEnumerable()); return new T4PreprocessingResult(location, false, message); } } } }