-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fantomas: move out-of-process (#252)
- Loading branch information
Showing
31 changed files
with
664 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
ReSharper.FSharp/src/FSharp.Fantomas.Host/FSharp.Fantomas.Host.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net461</TargetFramework> | ||
<AssemblyName>JetBrains.ReSharper.Plugins.FSharp.Fantomas.Host</AssemblyName> | ||
<OutputType>Exe</OutputType> | ||
<LangVersion>$(CSharpLanguageVersion)</LangVersion> | ||
<RootNamespace>JetBrains.ReSharper.Plugins.FSharp.Fantomas.Host</RootNamespace> | ||
</PropertyGroup> | ||
|
||
<!-- TODO: needed for 461 (because the default is x86), remove for netstandard/net5 --> | ||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> | ||
<PlatformTarget>AnyCPU</PlatformTarget> | ||
</PropertyGroup> | ||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> | ||
<PlatformTarget>AnyCPU</PlatformTarget> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\FSharp.Fantomas.Protocol\FSharp.Fantomas.Protocol.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="JetBrains.Fantomas" Version="$(FantomasVersion)" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<None Update="JetBrains.ReSharper.Plugins.FSharp.Fantomas.Host.runtimeconfig.json"> | ||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||
</None> | ||
</ItemGroup> | ||
|
||
<Import Project="$(DotNetSdkPath)\Build\SubplatformReference.Psi.Features_src.Props" Condition="Exists('$(DotNetSdkPath)\Build\SubplatformReference.Psi.Features_src.Props')" /> | ||
<Import Project="$(DotNetSdkPath)\Build\SubplatformReference.ReSharperAutomationTools_src_ReSharperHost.Props" Condition="Exists('$(DotNetSdkPath)\Build\SubplatformReference.ReSharperAutomationTools_src_ReSharperHost.Props')" /> | ||
</Project> |
10 changes: 10 additions & 0 deletions
10
.../FSharp.Fantomas.Host/JetBrains.ReSharper.Plugins.FSharp.Fantomas.Host.runtimeconfig.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"runtimeOptions": { | ||
"tfm": "netcoreapp5.0", | ||
"framework": { | ||
"name": "Microsoft.NETCore.App", | ||
"version": "5.0.0" | ||
}, | ||
"rollForward": "Major" | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
ReSharper.FSharp/src/FSharp.Fantomas.Host/src/FantomasAssemblyResolver.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Reflection; | ||
|
||
namespace JetBrains.ReSharper.Plugins.FSharp.Fantomas.Host | ||
{ | ||
public static class FantomasAssemblyResolver | ||
{ | ||
private const string AdditionalProbingPathsEnvVar = "RIDER_PLUGIN_ADDITIONAL_PROBING_PATHS"; | ||
private static readonly List<string> OurAdditionalProbingPaths = new List<string>(); | ||
|
||
static FantomasAssemblyResolver() | ||
{ | ||
var paths = Environment.GetEnvironmentVariable(AdditionalProbingPathsEnvVar); | ||
if (string.IsNullOrWhiteSpace(paths)) return; | ||
|
||
foreach (var path in paths.Split(';')) | ||
{ | ||
if (!string.IsNullOrEmpty(path)) OurAdditionalProbingPaths.Add(path); | ||
} | ||
} | ||
|
||
public static Assembly Resolve(object sender, ResolveEventArgs eventArgs) | ||
{ | ||
var assemblyName = $"{new AssemblyName(eventArgs.Name).Name}.dll"; | ||
|
||
foreach (var path in OurAdditionalProbingPaths) | ||
{ | ||
var assemblyPath = Path.Combine(path, assemblyName); | ||
if (!File.Exists(assemblyPath)) continue; | ||
|
||
var assembly = Assembly.LoadFrom(assemblyPath); | ||
return assembly; | ||
} | ||
|
||
Console.Error.Write($"\nFailed to resolve assembly by name '{eventArgs.Name}'" + | ||
$"\n Requesting assembly: {eventArgs.RequestingAssembly?.FullName}" + | ||
$"\n Probing paths: {string.Join("\n", OurAdditionalProbingPaths)}"); | ||
return null; | ||
} | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
ReSharper.FSharp/src/FSharp.Fantomas.Host/src/FantomasCodeFormatter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using Fantomas; | ||
using FSharp.Compiler.CodeAnalysis; | ||
using FSharp.Compiler.Diagnostics; | ||
using FSharp.Compiler.Text; | ||
using JetBrains.ReSharper.Plugins.FSharp.Fantomas.Server; | ||
using Microsoft.FSharp.Collections; | ||
using Microsoft.FSharp.Control; | ||
|
||
namespace JetBrains.ReSharper.Plugins.FSharp.Fantomas.Host | ||
{ | ||
internal class FantomasCodeFormatter | ||
{ | ||
private readonly FSharpChecker myChecker = | ||
FSharpChecker.Create(null, null, null, null, null, null, null, null, null, null); | ||
|
||
private readonly FormatConfig.FormatConfig myDefaultFormatConfig = FormatConfig.FormatConfig.Default; | ||
|
||
public string FormatSelection(RdFormatSelectionArgs args) => | ||
FSharpAsync.StartAsTask( | ||
CodeFormatter.FormatSelectionAsync(args.FileName, Convert(args.Range), | ||
SourceOrigin.SourceOrigin.NewSourceString(args.Source), Convert(args.FormatConfig), | ||
Convert(args.ParsingOptions), myChecker), null, null) | ||
.Result.Replace("\r\n", args.NewLineText); | ||
|
||
public string FormatDocument(RdFormatDocumentArgs args) => | ||
FSharpAsync.StartAsTask( | ||
CodeFormatter.FormatDocumentAsync(args.FileName, SourceOrigin.SourceOrigin.NewSourceString(args.Source), | ||
Convert(args.FormatConfig), Convert(args.ParsingOptions), myChecker), null, null) | ||
.Result.Replace("\r\n", args.NewLineText); | ||
|
||
private static Range Convert(RdFcsRange range) => | ||
CodeFormatter.MakeRange(range.FileName, range.StartLine, range.StartCol, range.EndLine, range.EndCol); | ||
|
||
private static FSharpParsingOptions Convert(RdFcsParsingOptions options) => | ||
new FSharpParsingOptions(new[] {options.LastSourceFile}, | ||
ListModule.OfArray(options.ConditionalCompilationDefines), FSharpDiagnosticOptions.Default, false, | ||
options.LightSyntax, false, options.IsExe); | ||
|
||
private FormatConfig.FormatConfig Convert(RdFantomasFormatConfig config) => | ||
new FormatConfig.FormatConfig(config.IndentSize, config.MaxLineLength, config.SemicolonAtEndOfLine, | ||
config.SpaceBeforeParameter, config.SpaceBeforeLowercaseInvocation, config.SpaceBeforeUppercaseInvocation, | ||
config.SpaceBeforeClassConstructor, config.SpaceBeforeMember, config.SpaceBeforeColon, config.SpaceAfterComma, | ||
config.SpaceBeforeSemicolon, config.SpaceAfterSemicolon, config.IndentOnTryWith, config.SpaceAroundDelimiter, | ||
config.MaxIfThenElseShortWidth, config.MaxInfixOperatorExpression, config.MaxRecordWidth, | ||
myDefaultFormatConfig.MaxRecordNumberOfItems, myDefaultFormatConfig.RecordMultilineFormatter, | ||
config.MaxArrayOrListWidth, myDefaultFormatConfig.MaxArrayOrListNumberOfItems, | ||
myDefaultFormatConfig.ArrayOrListMultilineFormatter, config.MaxValueBindingWidth, | ||
config.MaxFunctionBindingWidth, myDefaultFormatConfig.MaxDotGetExpressionWidth, | ||
config.MultilineBlockBracketsOnSameColumn, config.NewlineBetweenTypeDefinitionAndMembers, | ||
config.KeepIfThenInSameLine, config.MaxElmishWidth, config.SingleArgumentWebMode, | ||
config.AlignFunctionSignatureToIndentation, config.AlternativeLongMemberDefinitions, | ||
myDefaultFormatConfig.MultiLineLambdaClosingNewline, myDefaultFormatConfig.DisableElmishSyntax, | ||
myDefaultFormatConfig.EndOfLine, myDefaultFormatConfig.StrictMode); | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
ReSharper.FSharp/src/FSharp.Fantomas.Host/src/FantomasEndPoint.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
using JetBrains.Collections.Viewable; | ||
using JetBrains.Diagnostics; | ||
using JetBrains.Lifetimes; | ||
using JetBrains.Platform.RdFramework.ExternalProcess; | ||
using JetBrains.Platform.RdFramework.ExternalProcess.Util; | ||
using JetBrains.Rd.Impl; | ||
using JetBrains.Util; | ||
using JetBrains.Rd.Tasks; | ||
using JetBrains.ReSharper.Plugins.FSharp.Fantomas.Protocol; | ||
using JetBrains.ReSharper.Plugins.FSharp.Fantomas.Server; | ||
|
||
namespace JetBrains.ReSharper.Plugins.FSharp.Fantomas.Host | ||
{ | ||
internal class ExternalFormatterEndPoint : ProtocolEndPoint<RdFantomasModel, RdSimpleDispatcher> | ||
{ | ||
private readonly FantomasCodeFormatter myCodeFormatter; | ||
protected override string ProtocolName => "External Formatter Host"; | ||
|
||
public ExternalFormatterEndPoint() : base(FantomasProtocolConstants.PARENT_PROCESS_PID_ENV_VARIABLE) | ||
{ | ||
myCodeFormatter = new FantomasCodeFormatter(); | ||
} | ||
|
||
protected override RdSimpleDispatcher InitDispatcher(Lifetime lifetime, ILogger logger) => | ||
new RdSimpleDispatcher(lifetime, logger); | ||
|
||
protected override void InitLogger(Lifetime lifetime, string path) => | ||
ProtocolEndPointUtil.InitLogger(path, lifetime, LoggingLevel.TRACE); | ||
|
||
protected override RdFantomasModel InitModel(Lifetime lifetime, JetBrains.Rd.Impl.Protocol protocol) | ||
{ | ||
var model = new RdFantomasModel(lifetime, protocol); | ||
|
||
model.FormatSelection.Set(FormatSelection); | ||
model.FormatDocument.Set(FormatDocument); | ||
model.Exit.Advise(lifetime, Terminate); | ||
|
||
return model; | ||
} | ||
|
||
private string FormatSelection(RdFormatSelectionArgs args) => myCodeFormatter.FormatSelection(args); | ||
private string FormatDocument(RdFormatDocumentArgs args) => myCodeFormatter.FormatDocument(args); | ||
|
||
protected override void Run(Lifetime lifetime, RdSimpleDispatcher dispatcher) => dispatcher.Run(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using System; | ||
|
||
namespace JetBrains.ReSharper.Plugins.FSharp.Fantomas.Host | ||
{ | ||
public static class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
AppDomain.CurrentDomain.AssemblyResolve += FantomasAssemblyResolver.Resolve; | ||
MainInternal(args); | ||
} | ||
|
||
private static void MainInternal(string[] args) | ||
{ | ||
var endPoint = new ExternalFormatterEndPoint(); | ||
|
||
var portValue = args[0]; | ||
var logPath = string.Empty; | ||
if (args.Length > 1) | ||
{ | ||
logPath = args[1]; | ||
} | ||
|
||
endPoint.Start(portValue, logPath); | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
ReSharper.FSharp/src/FSharp.Fantomas.Protocol/FSharp.Fantomas.Protocol.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net461</TargetFramework> | ||
<LangVersion>$(CSharpLanguageVersion)</LangVersion> | ||
<AssemblyName>JetBrains.ReSharper.Plugins.FSharp.Fantomas.Protocol</AssemblyName> | ||
<RootNamespace>JetBrains.ReSharper.Plugins.FSharp.Fantomas.Protocol</RootNamespace> | ||
</PropertyGroup> | ||
|
||
<Import Project="$(DotNetSdkPath)\Build\SubplatformReference.Psi.Features_src.Props" Condition="Exists('$(DotNetSdkPath)\Build\SubplatformReference.Psi.Features_src.Props')" /> | ||
<Import Project="$(DotNetSdkPath)\Build\SubplatformReference.ReSharperAutomationTools_src_ReSharperHost.Props" Condition="Exists('$(DotNetSdkPath)\Build\SubplatformReference.ReSharperAutomationTools_src_ReSharperHost.Props')" /> | ||
</Project> |
17 changes: 17 additions & 0 deletions
17
ReSharper.FSharp/src/FSharp.Fantomas.Protocol/src/FantomasConnection.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using JetBrains.DataFlow; | ||
using JetBrains.Lifetimes; | ||
using JetBrains.Platform.RdFramework.ExternalProcess; | ||
using JetBrains.Rd; | ||
using JetBrains.ReSharper.Plugins.FSharp.Fantomas.Client; | ||
|
||
namespace JetBrains.ReSharper.Plugins.FSharp.Fantomas.Protocol | ||
{ | ||
public class FantomasConnection : ProtocolConnection<RdFantomasModel> | ||
{ | ||
public FantomasConnection(Lifetime lifetime, RdFantomasModel protocolModel, | ||
IProtocol protocol, StartupOutputWriter startupOutputWriter, int processId, ISignal<int> processUnexpectedExited) | ||
: base(lifetime, protocolModel, protocol, startupOutputWriter, processId, processUnexpectedExited) | ||
{ | ||
} | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
ReSharper.FSharp/src/FSharp.Fantomas.Protocol/src/FantomasProcess.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using JetBrains.Application.Processes; | ||
using JetBrains.Application.Threading; | ||
using JetBrains.Core; | ||
using JetBrains.DataFlow; | ||
using JetBrains.Diagnostics; | ||
using JetBrains.Lifetimes; | ||
using JetBrains.Platform.RdFramework.ExternalProcess; | ||
using JetBrains.Rd; | ||
using JetBrains.ReSharper.Plugins.FSharp.Fantomas.Client; | ||
using JetBrains.Util; | ||
|
||
namespace JetBrains.ReSharper.Plugins.FSharp.Fantomas.Protocol | ||
{ | ||
public class FantomasProcess : ProtocolExternalProcess<RdFantomasModel, FantomasConnection> | ||
{ | ||
protected override string Name => "External Formatter"; | ||
|
||
protected override RdFantomasModel CreateModel(Lifetime lifetime, IProtocol protocol) => | ||
new RdFantomasModel(lifetime, protocol); | ||
|
||
protected override FantomasConnection CreateConnection(Lifetime lifetime, | ||
RdFantomasModel model, IProtocol protocol, StartupOutputWriter outputWriter, int processId, | ||
Signal<int> processUnexpectedExited) => | ||
new FantomasConnection(lifetime, model, protocol, outputWriter, processId, | ||
processUnexpectedExited); | ||
|
||
protected override ProcessStartInfo GetProcessStartInfo(int port) | ||
{ | ||
var launchPath = GetType().Assembly.GetPath().Directory.Combine(FantomasProtocolConstants.PROCESS_FILENAME); | ||
Assertion.Assert(launchPath.ExistsFile, $"can't find '{FantomasProtocolConstants.PROCESS_FILENAME}'"); | ||
|
||
return new ProcessStartInfo | ||
{ | ||
Arguments = | ||
$"{port} \"{FantomasProtocolConstants.LogFolder.Combine($"{DateTime.UtcNow:yyyy_MM_dd_HH_mm_ss_ffff}.log")}\"", | ||
FileName = launchPath.FullPath | ||
}; | ||
} | ||
|
||
protected override IDictionary<string, string> GetAdditionalProcessEnvVars() | ||
{ | ||
return new Dictionary<string, string>() | ||
{ | ||
{ | ||
"RIDER_PLUGIN_ADDITIONAL_PROBING_PATHS", | ||
Environment.GetEnvironmentVariable("RIDER_PLUGIN_ADDITIONAL_PROBING_PATHS") | ||
}, | ||
{ | ||
FantomasProtocolConstants.PARENT_PROCESS_PID_ENV_VARIABLE, | ||
Process.GetCurrentProcess().Id.ToString() | ||
}, | ||
}; | ||
} | ||
|
||
protected override bool Shutdown(RdFantomasModel model) | ||
{ | ||
model.Proto.Scheduler.Queue(() => model.Exit.Fire(Unit.Instance)); | ||
return true; | ||
} | ||
|
||
public FantomasProcess(Lifetime lifetime, ILogger logger, IShellLocks locks, | ||
IProcessStartInfoPatcher processInfoPatcher, JetProcessRuntimeRequest request) | ||
: base(lifetime, logger, locks, processInfoPatcher, request) | ||
{ | ||
} | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
ReSharper.FSharp/src/FSharp.Fantomas.Protocol/src/FantomasProcessFactory.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using JetBrains.Annotations; | ||
using JetBrains.Application.Processes; | ||
using JetBrains.Application.Threading; | ||
using JetBrains.Lifetimes; | ||
using JetBrains.ProjectModel; | ||
using JetBrains.Util; | ||
|
||
namespace JetBrains.ReSharper.Plugins.FSharp.Fantomas.Protocol | ||
{ | ||
[SolutionComponent] | ||
public class FantomasProcessFactory | ||
{ | ||
[NotNull] private readonly ISolutionProcessStartInfoPatcher mySolutionProcessStartInfoPatcher; | ||
[NotNull] private readonly ILogger myLogger; | ||
[NotNull] private readonly IShellLocks myShellLocks; | ||
|
||
public FantomasProcessFactory( | ||
[NotNull] ISolutionProcessStartInfoPatcher solutionProcessStartInfoPatcher, | ||
[NotNull] ILogger logger, | ||
[NotNull] IShellLocks shellLocks) | ||
{ | ||
mySolutionProcessStartInfoPatcher = solutionProcessStartInfoPatcher; | ||
myLogger = logger; | ||
myShellLocks = shellLocks; | ||
} | ||
|
||
public FantomasProcess Create(Lifetime lifetime) | ||
{ | ||
return new FantomasProcess(lifetime, | ||
myLogger, | ||
myShellLocks, | ||
mySolutionProcessStartInfoPatcher, | ||
JetProcessRuntimeRequest.CreateInternalRuntime()); | ||
} | ||
} | ||
} |
Oops, something went wrong.