Backend/RiderPlugin/ForTea.RiderPlugin/ProtocolAware/Highlighting/Impl/T4OutputExtensionFrontendNotifier.cs (87 lines of code) (raw):
using System.Collections.Generic;
using GammaJul.ForTea.Core.Psi.Cache;
using GammaJul.ForTea.Core.TemplateProcessing;
using GammaJul.ForTea.Core.TemplateProcessing.Services;
using GammaJul.ForTea.Core.Tree;
using JetBrains.Annotations;
using JetBrains.Application.Parts;
using JetBrains.DocumentManagers;
using JetBrains.Lifetimes;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Caches;
using JetBrains.ReSharper.Psi.Files;
using JetBrains.ReSharper.Resources.Shell;
namespace JetBrains.ForTea.RiderPlugin.ProtocolAware.Highlighting.Impl
{
[SolutionComponent(InstantiationEx.LegacyDefault)]
public sealed class T4OutputExtensionFrontendNotifier : T4IndirectFileChangeObserverBase
{
[NotNull] private DocumentManager DocumentManager { get; }
[NotNull] private IT4FileDependencyGraph Graph { get; }
[NotNull] private IPsiFiles PsiFiles { get; }
public T4OutputExtensionFrontendNotifier(
Lifetime lifetime,
[NotNull] IT4FileGraphNotifier notifier,
[NotNull] DocumentManager documentManager,
[NotNull] IT4FileDependencyGraph graph,
[NotNull] IPsiServices services,
[NotNull] IPsiCachesState state,
[NotNull] IPsiFiles psiFiles
) : base(lifetime, notifier, services, state)
{
DocumentManager = documentManager;
Graph = graph;
PsiFiles = psiFiles;
}
protected override string ActivityName => "T4 frontend notification about file output extension";
protected override void AfterCommitSync(ISet<IPsiSourceFile> indirectDependencies)
{
using var outerCookie = ReadLockCookie.Create();
// Cache them in a closure, because they are lost otherwise
PsiFiles.ExecuteAfterCommitAllDocuments(() =>
{
using var cookie = ReadLockCookie.Create();
foreach (var file in indirectDependencies)
{
NotifyFrontend(file);
}
});
}
protected override void OnFilesIndirectlyAffected(
T4FileInvalidationData data,
ISet<IPsiSourceFile> indirectDependencies
)
{
base.OnFilesIndirectlyAffected(data, indirectDependencies);
indirectDependencies.Add(data.DirectlyAffectedFile);
}
public void NotifyFrontend([NotNull] IPsiSourceFile file)
{
var listener = TryGetListener(file);
if (listener == null) return;
string extension = GetTargetExtension(file);
listener.ExtensionChanged(extension);
}
[CanBeNull]
private string GetTargetExtension([NotNull] IPsiSourceFile file)
{
var root = Graph.FindBestRoot(file);
var psi = root.GetPrimaryPsiFile();
if (!(psi is IT4File t4File)) return null;
string extension = t4File.GetTargetExtension();
if (extension != null) return extension;
var provider = file.GetSolution().GetComponent<IT4TemplateKindProvider>();
if (provider.IsPreprocessedTemplate(root)) return null;
return T4CSharpCodeGenerationUtils.DefaultTargetExtension;
}
[CanBeNull]
private T4OutputExtensionChangeListener TryGetListener([NotNull] IPsiSourceFile file)
{
var projectFile = file.ToProjectFile();
if (projectFile == null) return null;
if (!projectFile.IsValid()) return null;
var document = DocumentManager.TryGetDocument(projectFile);
return document?.GetOutputExtensionChangeListener();
}
}
}