提交 fab56edb 编写于 作者: D Dustin Campbell

Merge pull request #4356 from DustinCampbell/portable-features

Initial work to make Features layer portable
......@@ -8,16 +8,9 @@ internal static class CompletionOptions
{
public const string FeatureName = "Completion";
[ExportOption]
public static readonly PerLanguageOption<bool> HideAdvancedMembers = new PerLanguageOption<bool>(FeatureName, "HideAdvancedMembers", defaultValue: false);
[ExportOption]
public static readonly PerLanguageOption<bool> IncludeKeywords = new PerLanguageOption<bool>(FeatureName, "IncludeKeywords", defaultValue: true);
[ExportOption]
public static readonly PerLanguageOption<bool> TriggerOnTyping = new PerLanguageOption<bool>(FeatureName, "TriggerOnTyping", defaultValue: true);
[ExportOption]
public static readonly PerLanguageOption<bool> TriggerOnTypingLetters = new PerLanguageOption<bool>(FeatureName, "TriggerOnTypingLetters", defaultValue: true);
}
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
namespace Microsoft.CodeAnalysis.Completion
{
[ExportOptionProvider, Shared]
internal class CompletionOptionsProvider : IOptionProvider
{
private readonly IEnumerable<IOption> _options = new List<IOption>
{
CompletionOptions.HideAdvancedMembers,
CompletionOptions.IncludeKeywords,
CompletionOptions.TriggerOnTyping,
CompletionOptions.TriggerOnTypingLetters
}.ToImmutableArray();
public IEnumerable<IOption> GetOptions()
{
return _options;
}
}
}
......@@ -8,28 +8,13 @@ internal static class InternalDiagnosticsOptions
{
public const string OptionName = "InternalDiagnosticsOptions";
[ExportOption]
public static readonly Option<bool> BlueSquiggleForBuildDiagnostic = new Option<bool>(OptionName, "Blue Squiggle For Build Diagnostic", defaultValue: false);
[ExportOption]
public static readonly Option<bool> UseDiagnosticEngineV2 = new Option<bool>(OptionName, "Use Diagnostic Engine V2", defaultValue: false);
[ExportOption]
public static readonly Option<bool> CompilationEndCodeFix = new Option<bool>(OptionName, "Enable Compilation End Code Fix", defaultValue: true);
[ExportOption]
public static readonly Option<bool> UseCompilationEndCodeFixHeuristic = new Option<bool>(OptionName, "Enable Compilation End Code Fix With Heuristic", defaultValue: true);
[ExportOption]
public static readonly Option<bool> BuildErrorIsTheGod = new Option<bool>(OptionName, "Make build errors to take over everything", defaultValue: false);
[ExportOption]
public static readonly Option<bool> ClearLiveErrorsForProjectBuilt = new Option<bool>(OptionName, "Clear all live errors of projects that got built", defaultValue: false);
[ExportOption]
public static readonly Option<bool> PreferLiveErrorsOnOpenedFiles = new Option<bool>(OptionName, "Live errors will be preferred over errors from build on opened files from same analyzer", defaultValue: true);
[ExportOption]
public static readonly Option<bool> PreferBuildErrorsOverLiveErrors = new Option<bool>(OptionName, "Errors from build will be preferred over live errors from same analyzer", defaultValue: true);
}
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
namespace Microsoft.CodeAnalysis.Diagnostics
{
[ExportOptionProvider, Shared]
internal class InternalDiagnosticsOptionsProvider : IOptionProvider
{
private readonly IEnumerable<IOption> _options = new List<IOption>
{
InternalDiagnosticsOptions.BlueSquiggleForBuildDiagnostic,
InternalDiagnosticsOptions.UseDiagnosticEngineV2,
InternalDiagnosticsOptions.CompilationEndCodeFix,
InternalDiagnosticsOptions.UseCompilationEndCodeFixHeuristic,
InternalDiagnosticsOptions.BuildErrorIsTheGod,
InternalDiagnosticsOptions.ClearLiveErrorsForProjectBuilt,
InternalDiagnosticsOptions.PreferLiveErrorsOnOpenedFiles,
InternalDiagnosticsOptions.PreferBuildErrorsOverLiveErrors
}.ToImmutableArray();
public IEnumerable<IOption> GetOptions()
{
return _options;
}
}
}
......@@ -8,13 +8,8 @@ internal static class ExtractMethodOptions
{
public const string FeatureName = "ExtractMethod";
[ExportOption]
public static readonly PerLanguageOption<bool> AllowBestEffort = new PerLanguageOption<bool>(FeatureName, "Allow Best Effort", defaultValue: false);
[ExportOption]
public static readonly PerLanguageOption<bool> DontPutOutOrRefOnStruct = new PerLanguageOption<bool>(FeatureName, "Don't Put Out Or Ref On Strcut", defaultValue: true);
[ExportOption]
public static readonly PerLanguageOption<bool> AllowMovingDeclaration = new PerLanguageOption<bool>(FeatureName, "Allow Moving Declaration", defaultValue: false);
}
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
namespace Microsoft.CodeAnalysis.ExtractMethod
{
[ExportOptionProvider, Shared]
internal class ExtractMethodOptionsProvider : IOptionProvider
{
private readonly IEnumerable<IOption> _options = new List<IOption>
{
ExtractMethodOptions.AllowBestEffort,
ExtractMethodOptions.DontPutOutOrRefOnStruct,
ExtractMethodOptions.AllowMovingDeclaration
}.ToImmutableArray();
public IEnumerable<IOption> GetOptions()
{
return _options;
}
}
}
......@@ -47,10 +47,6 @@
<Project>{1EE8CAD3-55F9-4D91-96B2-084641DA9A6C}</Project>
<Name>CodeAnalysis</Name>
</ProjectReference>
<ProjectReference Include="..\..\Workspaces\Core\Desktop\Workspaces.Desktop.csproj">
<Project>{2e87fa96-50bb-4607-8676-46521599f998}</Project>
<Name>Workspaces.Desktop</Name>
</ProjectReference>
<ProjectReference Include="..\..\Workspaces\Core\Portable\Workspaces.csproj">
<Project>{5F8D2414-064A-4B3A-9B42-8E2A04246BE5}</Project>
<Name>Workspaces</Name>
......@@ -159,6 +155,7 @@
<Compile Include="Completion\CompletionList.cs" />
<Compile Include="Completion\CompletionListContext.cs" />
<Compile Include="Completion\CompletionOptions.cs" />
<Compile Include="Completion\CompletionOptionsProvider.cs" />
<Compile Include="Completion\CompletionService.cs" />
<Compile Include="Completion\CompletionTriggerInfo.cs" />
<Compile Include="Completion\CompletionTriggerReason.cs" />
......@@ -187,6 +184,7 @@
<Compile Include="Diagnostics\AnalyzerUpdateArgsId.cs" />
<Compile Include="Diagnostics\EngineV1\DiagnosticIncrementalAnalyzer.SolutionCrawlerAnalysisState.cs" />
<Compile Include="Diagnostics\HostDiagnosticAnalyzerPackage.cs" />
<Compile Include="Diagnostics\InternalDiagnosticsOptionsProvider.cs" />
<Compile Include="Diagnostics\PredefinedBuildTools.cs" />
<Compile Include="Diagnostics\DiagnosticAnalyzerService_BuildSynchronization.cs" />
<Compile Include="Diagnostics\EngineV1\DiagnosticIncrementalAnalyzer.ProjectAnalyzerReferenceChangedEventArgs.cs" />
......@@ -235,6 +233,7 @@
<Compile Include="EditAndContinue\BidirectionalMap.cs" />
<Compile Include="EditAndContinue\StateMachineKind.cs" />
<Compile Include="EditAndContinue\TraceLog.cs" />
<Compile Include="ExtractMethod\ExtractMethodOptionsProvider.cs" />
<Compile Include="FeaturesResources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
......@@ -252,7 +251,10 @@
<Compile Include="IntroduceVariable\AbstractIntroduceVariableService.IntroduceVariableAllOccurrenceCodeAction.cs" />
<Compile Include="LanguageServices\ProjectInfoService\IProjectInfoService.cs" />
<Compile Include="QuickInfo\QuickInfoUtilities.cs" />
<Compile Include="Shared\Options\OrganizerOptionsProvider.cs" />
<Compile Include="Shared\Options\ServiceComponentOnOffOptionsProvider.cs" />
<Compile Include="Shared\Options\ServiceFeatureOnOffOptions.cs" />
<Compile Include="Shared\Options\ServiceFeatureOnOffOptionsProvider.cs" />
<Compile Include="Shared\Utilities\LinkedFilesSymbolEquivalenceComparer.cs" />
<Compile Include="Shared\Utilities\SupportedPlatformData.cs" />
<Compile Include="Completion\Providers\SymbolCompletionItem.cs" />
......@@ -512,6 +514,7 @@
<Compile Include="SolutionCrawler\IIncrementalAnalyzer.cs" />
<Compile Include="SolutionCrawler\IncrementalAnalyzerBase.cs" />
<Compile Include="SolutionCrawler\IncrementalAnalyzerProviderBase.cs" />
<Compile Include="SolutionCrawler\InternalSolutionCrawlerOptionsProvider.cs" />
<Compile Include="SolutionCrawler\InvocationReasons.cs" />
<Compile Include="SolutionCrawler\InvocationReasons_Constants.cs" />
<Compile Include="SolutionCrawler\ISolutionCrawlerProgressReporter.cs" />
......@@ -539,8 +542,6 @@
<Compile Include="SolutionCrawler\SolutionCrawlerRegistrationService.cs" />
<Compile Include="Workspace\BackgroundCompiler.cs" />
<Compile Include="Workspace\BackgroundParser.cs" />
<Compile Include="Workspace\FileTracker.cs" />
<Compile Include="Workspace\Kernel32File.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="FeaturesResources.resx">
......
......@@ -11,7 +11,7 @@ internal partial class OrganizerOptions
public static PerLanguageOption<bool> PlaceSystemNamespaceFirst
{
get { return Microsoft.CodeAnalysis.Editing.GenerationOptions.PlaceSystemNamespaceFirst; }
get { return Editing.GenerationOptions.PlaceSystemNamespaceFirst; }
}
/// <summary>
......@@ -20,7 +20,6 @@ public static PerLanguageOption<bool> PlaceSystemNamespaceFirst
/// maintain any customized value for this setting, even through versions that have not
/// implemented this feature yet.
/// </summary>
[ExportOption]
public static readonly PerLanguageOption<bool> WarnOnBuildErrors = new PerLanguageOption<bool>(FeatureName, "WarnOnBuildErrors", defaultValue: true);
}
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
namespace Microsoft.CodeAnalysis.Shared.Options
{
[ExportOptionProvider, Shared]
internal class OrganizerOptionsProvider : IOptionProvider
{
private readonly IEnumerable<IOption> _options = new List<IOption>
{
OrganizerOptions.WarnOnBuildErrors
}.ToImmutableArray();
public IEnumerable<IOption> GetOptions()
{
return _options;
}
}
}
......@@ -11,7 +11,6 @@ internal static class ServiceComponentOnOffOptions
{
public const string OptionName = "FeatureManager/Components";
[ExportOption]
public static readonly Option<bool> DiagnosticProvider = new Option<bool>(OptionName, "Diagnostic Provider", defaultValue: true);
}
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
namespace Microsoft.CodeAnalysis.Shared.Options
{
[ExportOptionProvider, Shared]
internal class ServiceComponentOnOffOptionsProvider : IOptionProvider
{
private readonly IEnumerable<IOption> _options = new List<IOption>
{
ServiceComponentOnOffOptions.DiagnosticProvider
}.ToImmutableArray();
public IEnumerable<IOption> GetOptions()
{
return _options;
}
}
}
......@@ -8,7 +8,6 @@ internal static class ServiceFeatureOnOffOptions
{
public const string OptionName = "ServiceFeaturesOnOff";
[ExportOption]
public static readonly PerLanguageOption<bool> ClosedFileDiagnostic = new PerLanguageOption<bool>(OptionName, "Closed File Diagnostic", defaultValue: true);
}
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
namespace Microsoft.CodeAnalysis.Shared.Options
{
[ExportOptionProvider, Shared]
internal class ServiceFeatureOnOffOptionsProvider : IOptionProvider
{
private readonly IEnumerable<IOption> _options = new List<IOption>
{
ServiceFeatureOnOffOptions.ClosedFileDiagnostic
}.ToImmutableArray();
public IEnumerable<IOption> GetOptions()
{
return _options;
}
}
}
......@@ -8,25 +8,12 @@ internal static class InternalSolutionCrawlerOptions
{
public const string OptionName = "SolutionCrawler";
[ExportOption]
public static readonly Option<bool> SolutionCrawler = new Option<bool>("FeatureManager/Components", "Solution Crawler", defaultValue: true);
[ExportOption]
public static readonly Option<int> ActiveFileWorkerBackOffTimeSpanInMS = new Option<int>(OptionName, "Active file worker backoff timespan in ms", defaultValue: 800);
[ExportOption]
public static readonly Option<int> AllFilesWorkerBackOffTimeSpanInMS = new Option<int>(OptionName, "All files worker backoff timespan in ms", defaultValue: 1500);
[ExportOption]
public static readonly Option<int> EntireProjectWorkerBackOffTimeSpanInMS = new Option<int>(OptionName, "Entire project analysis worker backoff timespan in ms", defaultValue: 5000);
[ExportOption]
public static readonly Option<int> SemanticChangeBackOffTimeSpanInMS = new Option<int>(OptionName, "Semantic change backoff timespan in ms", defaultValue: 100);
[ExportOption]
public static readonly Option<int> ProjectPropagationBackOffTimeSpanInMS = new Option<int>(OptionName, "Project propagation backoff timespan in ms", defaultValue: 500);
[ExportOption]
public static readonly Option<int> PreviewBackOffTimeSpanInMS = new Option<int>(OptionName, "Preview backoff timespan in ms", defaultValue: 500);
}
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Composition;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers;
namespace Microsoft.CodeAnalysis.SolutionCrawler
{
[ExportOptionProvider, Shared]
internal class InternalSolutionCrawlerOptionsProvider : IOptionProvider
{
private readonly IEnumerable<IOption> _options = new List<IOption>
{
InternalSolutionCrawlerOptions.SolutionCrawler,
InternalSolutionCrawlerOptions.ActiveFileWorkerBackOffTimeSpanInMS,
InternalSolutionCrawlerOptions.AllFilesWorkerBackOffTimeSpanInMS,
InternalSolutionCrawlerOptions.EntireProjectWorkerBackOffTimeSpanInMS,
InternalSolutionCrawlerOptions.SemanticChangeBackOffTimeSpanInMS,
InternalSolutionCrawlerOptions.ProjectPropagationBackOffTimeSpanInMS,
InternalSolutionCrawlerOptions.PreviewBackOffTimeSpanInMS
}.ToImmutableArray();
public IEnumerable<IOption> GetOptions()
{
return _options;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Host
{
/// <summary>
/// A class that tracks file changes on disk and invokes user actions
/// when changes happen.
/// </summary>
internal class FileTracker
{
// guards watchers and actions
private readonly NonReentrantLock _guard = new NonReentrantLock();
private readonly Dictionary<string, FileSystemWatcher> _watchers =
new Dictionary<string, FileSystemWatcher>();
private readonly Dictionary<string, FileActions> _fileActionsMap =
new Dictionary<string, FileActions>();
public FileTracker()
{
}
private FileActions GetFileActions_NoLock(string path)
{
_guard.AssertHasLock();
FileActions actions;
if (!_fileActionsMap.TryGetValue(path, out actions))
{
actions = new FileActions(this, path);
_fileActionsMap.Add(path, actions);
}
return actions;
}
public bool IsTracking(string path)
{
if (path == null)
{
return false;
}
using (_guard.DisposableWait())
{
return _fileActionsMap.ContainsKey(path);
}
}
public void Track(string path, Action action)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
using (_guard.DisposableWait())
{
var fileActions = this.GetFileActions_NoLock(path);
fileActions.AddAction_NoLock(action);
var directory = Path.GetDirectoryName(path);
if (!_watchers.ContainsKey(directory))
{
var watcher = new FileSystemWatcher(directory);
watcher.Changed += OnFileChanged;
watcher.EnableRaisingEvents = true;
}
}
}
public void StopTracking(string path)
{
if (path != null)
{
using (_guard.DisposableWait())
{
_fileActionsMap.Remove(path);
}
}
}
private void OnFileChanged(object sender, FileSystemEventArgs args)
{
FileActions actions;
using (_guard.DisposableWait())
{
actions = this.GetFileActions_NoLock(args.FullPath);
}
actions.InvokeActions();
}
public void Dispose()
{
using (_guard.DisposableWait())
{
foreach (var watcher in _watchers.Values)
{
watcher.Dispose();
}
_watchers.Clear();
_fileActionsMap.Clear();
}
}
private class FileActions
{
private readonly FileTracker _tracker;
private readonly string _path;
private ImmutableArray<Action> _actions;
private Task _invokeTask;
public FileActions(FileTracker tracker, string path)
{
_tracker = tracker;
_path = path;
_actions = ImmutableArray.Create<Action>();
}
public void AddAction_NoLock(Action action)
{
_tracker._guard.AssertHasLock();
_actions = _actions.Add(action);
}
public void InvokeActions()
{
using (_tracker._guard.DisposableWait())
{
// only start invoke task if one is not already running
if (_invokeTask == null)
{
_invokeTask = Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current);
_invokeTask.ContinueWithAfterDelay(() => TryInvokeActions(_actions), CancellationToken.None, 100, TaskContinuationOptions.None, TaskScheduler.Current);
}
}
}
private void TryInvokeActions(ImmutableArray<Action> actions)
{
if (actions.Length == 0)
{
return;
}
// only invoke actions if the writer that caused the event is done
// determine this by checking to see if we can read the file
using (var stream = Kernel32File.Open(_path, FileAccess.Read, FileMode.Open, throwException: false))
{
if (stream != null)
{
stream.Close();
foreach (var action in actions)
{
action();
}
// clear invoke task so any following changes get additional invocations
using (_tracker._guard.DisposableWait())
{
_invokeTask = null;
}
}
else
{
// try again after a short delay
using (_tracker._guard.DisposableWait())
{
_invokeTask.ContinueWithAfterDelay(() => TryInvokeActions(_actions), CancellationToken.None, 100, TaskContinuationOptions.None, TaskScheduler.Current);
}
}
}
}
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using IO = System.IO;
namespace Microsoft.CodeAnalysis.Host
{
internal static class Kernel32File
{
internal static IO.FileStream Open(string path, IO.FileAccess access, IO.FileMode mode, IO.FileShare share = IO.FileShare.None, bool throwException = true)
{
var fileHandle = CreateFile(path, GetFileAccess(access), GetFileShare(share), default(IntPtr), GetFileMode(mode));
if (fileHandle.IsInvalid)
{
if (throwException)
{
HandleCOMError(Marshal.GetLastWin32Error());
}
else
{
return null;
}
}
return new IO.FileStream(fileHandle, access);
}
[Flags]
private enum FileShare
{
FILE_SHARE_NONE = 0x00,
FILE_SHARE_READ = 0x01,
FILE_SHARE_WRITE = 0x02,
FILE_SHARE_DELETE = 0x04
}
private enum FileMode
{
CREATE_NEW = 1,
CREATE_ALWAYS = 2,
OPEN_EXISTING = 3,
OPEN_ALWAYS = 4,
TRUNCATE_EXISTING = 5
}
private enum FileAccess
{
GENERIC_READ = unchecked((int)0x80000000),
GENERIC_WRITE = 0x40000000
}
[DllImport("kernel32", SetLastError = true)]
private static extern SafeFileHandle CreateFile(string filename,
FileAccess desiredAccess,
FileShare shareMode,
IntPtr attributes,
FileMode creationDisposition,
uint flagsAndAttributes = 0,
IntPtr templateFile = default(IntPtr));
private static void HandleCOMError(int error)
{
throw new System.ComponentModel.Win32Exception(error);
}
private static FileMode GetFileMode(IO.FileMode mode)
{
if (mode != IO.FileMode.Append)
{
return (FileMode)(int)mode;
}
else
{
return (FileMode)(int)IO.FileMode.OpenOrCreate;
}
}
private static FileAccess GetFileAccess(IO.FileAccess access)
{
return access == IO.FileAccess.Read ?
FileAccess.GENERIC_READ :
FileAccess.GENERIC_WRITE;
}
private static FileShare GetFileShare(IO.FileShare share)
{
return (FileShare)(int)share;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册