Cleaned up support for OptimizationLevel.
This commit is contained in:
Родитель
e652e24cc3
Коммит
ed3bf9d83e
|
@ -5,9 +5,6 @@ using Microsoft.CodeAnalysis;
|
|||
namespace MirrorSharp.Internal.Abstraction {
|
||||
internal interface ILanguage {
|
||||
[NotNull] string Name { get; }
|
||||
[NotNull] ParseOptions DefaultParseOptions { get; }
|
||||
[NotNull] CompilationOptions DefaultCompilationOptions { get; }
|
||||
|
||||
[NotNull] ILanguageSession CreateSession([NotNull] string text, ParseOptions parseOptions, CompilationOptions compilationOptions, [CanBeNull] IReadOnlyCollection<MetadataReference> assemblyReferences);
|
||||
[NotNull] ILanguageSession CreateSession([NotNull] string text, OptimizationLevel? optimizationLevel, ParseOptions parseOptions, CompilationOptions compilationOptions, [CanBeNull] IReadOnlyCollection<MetadataReference> assemblyReferences);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace MirrorSharp.Internal.Handlers {
|
|||
|
||||
private void SetOptimize(WorkSession session, string value) {
|
||||
var level = (OptimizationLevel)Enum.Parse(typeof(OptimizationLevel), value, true);
|
||||
session.ChangeCompilationOptions(nameof(CompilationOptions.OptimizationLevel), o => o.WithOptimizationLevel(level));
|
||||
session.ChangeOptimizationLevel(level);
|
||||
}
|
||||
|
||||
private async Task SendOptionsEchoAsync(WorkSession session, ICommandResultSender sender, CancellationToken cancellationToken) {
|
||||
|
|
|
@ -15,6 +15,8 @@ using MirrorSharp.Internal.Reflection;
|
|||
namespace MirrorSharp.Internal.Roslyn {
|
||||
internal abstract class RoslynLanguageBase : ILanguage {
|
||||
private readonly MefHostServices _hostServices;
|
||||
private readonly ParseOptions _defaultParseOptions;
|
||||
private readonly CompilationOptions _defaultCompilationOptions;
|
||||
private readonly ImmutableArray<ISignatureHelpProviderWrapper> _defaultSignatureHelpProviders;
|
||||
private readonly ImmutableDictionary<string, ImmutableArray<CodeFixProvider>> _defaultCodeFixProvidersIndexedByDiagnosticIds;
|
||||
private readonly ImmutableArray<DiagnosticAnalyzer> _defaultAnalyzers;
|
||||
|
@ -36,8 +38,8 @@ namespace MirrorSharp.Internal.Roslyn {
|
|||
Assembly.Load(new AssemblyName(featuresAssemblyName)),
|
||||
Assembly.Load(new AssemblyName(workspacesAssemblyName)),
|
||||
});
|
||||
DefaultParseOptions = defaultParseOptions;
|
||||
DefaultCompilationOptions = defaultCompilationOptions;
|
||||
_defaultParseOptions = defaultParseOptions;
|
||||
_defaultCompilationOptions = defaultCompilationOptions;
|
||||
_defaultAssemblyReferences = ImmutableList.Create<MetadataReference>(
|
||||
MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location)
|
||||
);
|
||||
|
@ -53,14 +55,17 @@ namespace MirrorSharp.Internal.Roslyn {
|
|||
}
|
||||
|
||||
public string Name { get; }
|
||||
public ParseOptions DefaultParseOptions { get; }
|
||||
public CompilationOptions DefaultCompilationOptions { get; }
|
||||
|
||||
public ILanguageSession CreateSession(string text, ParseOptions parseOptions, CompilationOptions compilationOptions, IReadOnlyCollection<MetadataReference> assemblyReferences) {
|
||||
public ILanguageSession CreateSession(string text, OptimizationLevel? optimizationLevel, ParseOptions parseOptions, CompilationOptions compilationOptions, IReadOnlyCollection<MetadataReference> assemblyReferences) {
|
||||
var projectId = ProjectId.CreateNewId();
|
||||
|
||||
compilationOptions = compilationOptions ?? _defaultCompilationOptions;
|
||||
if (optimizationLevel != null)
|
||||
compilationOptions = compilationOptions.WithOptimizationLevel(optimizationLevel.Value);
|
||||
|
||||
var projectInfo = ProjectInfo.Create(
|
||||
projectId, VersionStamp.Create(), "_", "_", Name,
|
||||
parseOptions: parseOptions,
|
||||
parseOptions: parseOptions ?? _defaultParseOptions,
|
||||
compilationOptions: compilationOptions,
|
||||
metadataReferences: assemblyReferences ?? _defaultAssemblyReferences,
|
||||
analyzerReferences: _defaultAnalyzerReferences
|
||||
|
|
|
@ -9,9 +9,9 @@ using MirrorSharp.Internal.Roslyn;
|
|||
namespace MirrorSharp.Internal {
|
||||
internal class WorkSession : IWorkSession {
|
||||
[CanBeNull] private readonly IWorkSessionOptions _options;
|
||||
[NotNull] private readonly IDictionary<string, Func<ParseOptions, ParseOptions>> _parseOptionsChanges = new Dictionary<string, Func<ParseOptions, ParseOptions>>();
|
||||
[NotNull] private readonly IDictionary<string, Func<CompilationOptions, CompilationOptions>> _compilationOptionsChanges = new Dictionary<string, Func<CompilationOptions, CompilationOptions>>();
|
||||
[NotNull] private ILanguage _language;
|
||||
[CanBeNull] private OptimizationLevel? _optimizationLevel;
|
||||
private ILanguageSession _languageSession;
|
||||
private string _lastText = "";
|
||||
|
||||
|
@ -30,26 +30,10 @@ namespace MirrorSharp.Internal {
|
|||
Reset();
|
||||
}
|
||||
|
||||
public void ChangeParseOptions([NotNull] string key, [NotNull] Func<ParseOptions, ParseOptions> change) {
|
||||
Argument.NotNull(nameof(key), key);
|
||||
Argument.NotNull(nameof(change), change);
|
||||
|
||||
if (_parseOptionsChanges.TryGetValue(key, out var current) && current == change)
|
||||
return;
|
||||
_parseOptionsChanges[key] = change;
|
||||
if (_languageSession is RoslynSession roslyn && change(roslyn.Project.ParseOptions) == roslyn.Project.ParseOptions)
|
||||
return;
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void ChangeCompilationOptions([NotNull] string key, [NotNull] Func<CompilationOptions, CompilationOptions> change) {
|
||||
Argument.NotNull(nameof(key), key);
|
||||
Argument.NotNull(nameof(change), change);
|
||||
if (_compilationOptionsChanges.TryGetValue(key, out var current) && current == change)
|
||||
return;
|
||||
_compilationOptionsChanges[key] = change;
|
||||
if (_languageSession is RoslynSession roslyn && change(roslyn.Project.CompilationOptions) == roslyn.Project.CompilationOptions)
|
||||
public void ChangeOptimizationLevel([CanBeNull] OptimizationLevel? optimizationLevel) {
|
||||
if (optimizationLevel == _optimizationLevel)
|
||||
return;
|
||||
_optimizationLevel = optimizationLevel;
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
@ -62,19 +46,14 @@ namespace MirrorSharp.Internal {
|
|||
}
|
||||
|
||||
private void Initialize() {
|
||||
var parseOptions = _options?.GetDefaultParseOptionsByLanguageName?.Invoke(Language.Name) ?? Language.DefaultParseOptions;
|
||||
foreach (var change in _parseOptionsChanges.Values) {
|
||||
parseOptions = change(parseOptions);
|
||||
}
|
||||
var compilationOptions = _options?.GetDefaultCompilationOptionsByLanguageName?.Invoke(Language.Name) ?? Language.DefaultCompilationOptions;
|
||||
foreach (var change in _compilationOptionsChanges.Values) {
|
||||
compilationOptions = change(compilationOptions);
|
||||
}
|
||||
var parseOptions = _options?.GetDefaultParseOptionsByLanguageName?.Invoke(Language.Name);
|
||||
var compilationOptions = _options?.GetDefaultCompilationOptionsByLanguageName?.Invoke(Language.Name);
|
||||
var assemblyReferences = _options?.GetDefaultMetadataReferencesByLanguageName?.Invoke(Language.Name);
|
||||
_languageSession = Language.CreateSession(_lastText, parseOptions, compilationOptions, assemblyReferences);
|
||||
_languageSession = Language.CreateSession(_lastText, OptimizationLevel, parseOptions, compilationOptions, assemblyReferences);
|
||||
}
|
||||
|
||||
public IWorkSessionOptions Options => _options;
|
||||
public OptimizationLevel? OptimizationLevel => _optimizationLevel;
|
||||
[NotNull] public ILanguage Language => _language;
|
||||
[NotNull]
|
||||
public ILanguageSession LanguageSession {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.FSharp.Compiler.AbstractIL.Internal;
|
||||
|
@ -11,9 +10,7 @@ using MirrorSharp.Internal.Abstraction;
|
|||
namespace MirrorSharp.FSharp {
|
||||
public class FSharpLanguage : ILanguage {
|
||||
public const string Name = "F#";
|
||||
|
||||
ParseOptions ILanguage.DefaultParseOptions => null;
|
||||
CompilationOptions ILanguage.DefaultCompilationOptions => null;
|
||||
|
||||
private readonly ImmutableArray<string> _defaultAssemblyReferencePaths;
|
||||
|
||||
static FSharpLanguage() {
|
||||
|
@ -22,18 +19,18 @@ namespace MirrorSharp.FSharp {
|
|||
|
||||
internal FSharpLanguage() {
|
||||
var fsharpAssembly = typeof(FSharpOption<>).GetTypeInfo().Assembly;
|
||||
_defaultAssemblyReferencePaths = ImmutableArray.Create<string>(
|
||||
_defaultAssemblyReferencePaths = ImmutableArray.Create(
|
||||
// note: this currently does not work on .NET Core, which is why this project isn't netstandard
|
||||
typeof(object).GetTypeInfo().Assembly.Location,
|
||||
new Uri(fsharpAssembly.EscapedCodeBase).LocalPath
|
||||
);
|
||||
}
|
||||
|
||||
ILanguageSession ILanguage.CreateSession(string text, ParseOptions parseOptions, CompilationOptions compilationOptions, IReadOnlyCollection<MetadataReference> assemblyReferences) {
|
||||
ILanguageSession ILanguage.CreateSession(string text, OptimizationLevel? optimizationLevel, ParseOptions parseOptions, CompilationOptions compilationOptions, IReadOnlyCollection<MetadataReference> assemblyReferences) {
|
||||
if (assemblyReferences != null)
|
||||
throw new NotSupportedException();
|
||||
|
||||
return new FSharpSession(text, _defaultAssemblyReferencePaths);
|
||||
return new FSharpSession(text, _defaultAssemblyReferencePaths, optimizationLevel);
|
||||
}
|
||||
|
||||
string ILanguage.Name => Name;
|
||||
|
|
|
@ -18,20 +18,14 @@ namespace MirrorSharp.FSharp {
|
|||
private readonly FSharpChecker _checker;
|
||||
private readonly FSharpProjectOptions _projectOptions;
|
||||
|
||||
public FSharpSession(string text, ImmutableArray<string> assemblyReferencePaths) {
|
||||
public FSharpSession(string text, ImmutableArray<string> assemblyReferencePaths, OptimizationLevel? optimizationLevel) {
|
||||
_checker = FSharpChecker.Create(null, null, null, false);
|
||||
_text = text;
|
||||
|
||||
var otherOptions = new List<string> { "--noframework" };
|
||||
foreach (var path in assemblyReferencePaths) {
|
||||
// ReSharper disable once HeapView.ObjectAllocation (Not worth fixing for now)
|
||||
otherOptions.Add("-r:" + path);
|
||||
}
|
||||
|
||||
_projectOptions = new FSharpProjectOptions(
|
||||
"_",
|
||||
projectFileNames: new[] { "_.fs" },
|
||||
otherOptions: otherOptions.ToArray(),
|
||||
otherOptions: ConvertToOptions(assemblyReferencePaths, optimizationLevel),
|
||||
referencedProjects: Array.Empty<Tuple<string, FSharpProjectOptions>>(),
|
||||
isIncompleteTypeCheckEnvironment: true,
|
||||
useScriptResolutionRules: false,
|
||||
|
@ -42,6 +36,23 @@ namespace MirrorSharp.FSharp {
|
|||
);
|
||||
}
|
||||
|
||||
private static string[] ConvertToOptions(ImmutableArray<string> assemblyReferencePaths, OptimizationLevel? optimizationLevel) {
|
||||
var options = new List<string> {"--noframework"};
|
||||
if (optimizationLevel == OptimizationLevel.Release) {
|
||||
options.Add("--debug-");
|
||||
options.Add("--optimize+");
|
||||
}
|
||||
else if (optimizationLevel == OptimizationLevel.Debug) {
|
||||
options.Add("--debug+");
|
||||
options.Add("--optimize-");
|
||||
}
|
||||
foreach (var path in assemblyReferencePaths) {
|
||||
// ReSharper disable once HeapView.ObjectAllocation (Not worth fixing for now)
|
||||
options.Add("-r:" + path);
|
||||
}
|
||||
return options.ToArray();
|
||||
}
|
||||
|
||||
public async Task<ImmutableArray<Diagnostic>> GetDiagnosticsAsync(CancellationToken cancellationToken) {
|
||||
var (parsed, check) = await FSharpAsync.StartAsTask(
|
||||
_checker.ParseAndCheckFileInProject("_.fs", 0, _text, _projectOptions, null), null, cancellationToken
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/Browsers/Browsers/@EntryValue">C27+,E12+,FF21+,IE11+,S9+</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=3C2A0FC7_002D4485_002D4654_002DB3B2_002D5717A2F2C97A_002Fd_003Abower_005Fcomponents/@EntryIndexedValue">ExplicitlyExcluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=70BCCC0E_002D6EEF_002D40D0_002D932A_002D87F9C42BD67B_002Fd_003Awwwroot_002Fd_003Abower_005Fcomponents/@EntryIndexedValue">ExplicitlyExcluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=D2EB1CDD_002D12B5_002D4FDC_002DA56C_002D8A327200E759_002Fd_003Abower_005Fcomponents/@EntryIndexedValue">ExplicitlyExcluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=FF13139E_002D69D3_002D472E_002DB4FE_002DAC2623AD67B9_002Fd_003Abower_005Fcomponents/@EntryIndexedValue">ExplicitlyExcluded</s:String>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
|
@ -16,11 +19,19 @@ using Newtonsoft.Json;
|
|||
|
||||
namespace MirrorSharp.Testing {
|
||||
public class MirrorSharpTestDriver {
|
||||
private static readonly LanguageManager LanguageManager = new LanguageManager(new[] {
|
||||
LanguageNames.CSharp,
|
||||
LanguageNames.VisualBasic,
|
||||
"F#"
|
||||
});
|
||||
private static readonly LanguageManager LanguageManager = CreateLanguageManager();
|
||||
|
||||
private static LanguageManager CreateLanguageManager() {
|
||||
var languageNames = new List<string> {
|
||||
LanguageNames.CSharp,
|
||||
LanguageNames.VisualBasic
|
||||
};
|
||||
var basePath = Path.GetDirectoryName(new Uri(typeof(LanguageManager).GetTypeInfo().Assembly.CodeBase).LocalPath);
|
||||
if (File.Exists(Path.Combine(basePath, "MirrorSharp.FSharp.dll")))
|
||||
languageNames.Add("F#");
|
||||
|
||||
return new LanguageManager(languageNames);
|
||||
}
|
||||
|
||||
private MirrorSharpTestDriver([CanBeNull] MirrorSharpOptions options = null, [CanBeNull] string languageName = LanguageNames.CSharp) {
|
||||
var language = LanguageManager.GetLanguage(languageName);
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MirrorSharp.Internal;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using MirrorSharp.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace MirrorSharp.Tests {
|
||||
using static CommandIds;
|
||||
|
||||
public class FSharpTests {
|
||||
[Fact]
|
||||
public async void SlowUpdate_ProducesNoDiagnostics_IfCodeIsValid() {
|
||||
|
@ -46,5 +44,20 @@ namespace MirrorSharp.Tests {
|
|||
}).ToArray()
|
||||
);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(OptimizationLevel.Debug)]
|
||||
[InlineData(OptimizationLevel.Release)]
|
||||
public async void SetOptions_DoesNotProduceAnyDiagnosticIssues_WithEitherOptimizationLevel(OptimizationLevel level) {
|
||||
var driver = MirrorSharpTestDriver.New();
|
||||
await driver.SendSetOptionsAsync(new Dictionary<string, string> {
|
||||
{ "language", "F#" },
|
||||
{ "optimize", level.ToString() }
|
||||
});
|
||||
await driver.SendReplaceTextAsync("1 |> ignore");
|
||||
var result = await driver.SendSlowUpdateAsync();
|
||||
|
||||
Assert.Empty(result.Diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,14 @@
|
|||
<RootNamespace>MirrorSharp.Tests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE;DEBUG;NET46;ROSLYN20</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<DefineConstants>TRACE;RELEASE;NET46;ROSLYN20</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="..\Tests.Shared\MirrorSharp.Tests.Shared.projitems" Label="Shared" />
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace MirrorSharp.Tests {
|
|||
[Fact]
|
||||
public async void ExecuteAsync_PreservesSessionWorkspace_WhenUpdatingOptimizeToTheSameValue() {
|
||||
var driver = MirrorSharpTestDriver.New().SetText("test");
|
||||
driver.Session.ChangeCompilationOptions(nameof(CompilationOptions.OptimizationLevel), c => c.WithOptimizationLevel(OptimizationLevel.Release));
|
||||
driver.Session.ChangeOptimizationLevel(OptimizationLevel.Release);
|
||||
var workspace = driver.Session.Roslyn.Workspace;
|
||||
await driver.SendAsync(SetOptions, "optimize=release");
|
||||
Assert.Same(workspace, driver.Session.Roslyn.Workspace);
|
||||
|
|
Загрузка…
Ссылка в новой задаче