提交 79d5850f 编写于 作者: G Gen Lu

Merge remote-tracking branch 'dotnet/master' into MergeFromMaster

......@@ -37,17 +37,7 @@ public VisualStudioWorkspaceDiagnosticAnalyzerProviderService(VisualStudioWorksp
// Get the analyzer assets for installed VSIX extensions through the VSIX extension manager.
var extensionManager = workspace.GetVsService<SVsExtensionManager, IVsExtensionManager>();
// get rootfolder and shellfolder location
string rootFolder;
string shellFolder;
if (TryGetRootAndShellFolder(extensionManager, out shellFolder, out rootFolder))
{
_hostDiagnosticAnalyzerInfo = GetHostAnalyzerPackagesWithName(extensionManager, rootFolder, shellFolder);
return;
}
// if we can't get rootFolder/shellFolder location, use old behavior.
_hostDiagnosticAnalyzerInfo = GetHostAnalyzerPackages(extensionManager);
_hostDiagnosticAnalyzerInfo = GetHostAnalyzerPackagesWithName(extensionManager);
}
public IEnumerable<HostDiagnosticAnalyzerPackage> GetHostDiagnosticAnalyzerPackages()
......@@ -67,14 +57,14 @@ internal static IAnalyzerAssemblyLoader GetLoader()
}
// internal for testing purpose
internal static ImmutableArray<HostDiagnosticAnalyzerPackage> GetHostAnalyzerPackagesWithName(IVsExtensionManager extensionManager, string rootFolder, string shellFolder)
internal static ImmutableArray<HostDiagnosticAnalyzerPackage> GetHostAnalyzerPackagesWithName(IVsExtensionManager extensionManager)
{
var builder = ImmutableArray.CreateBuilder<HostDiagnosticAnalyzerPackage>();
foreach (var extension in extensionManager.GetEnabledExtensions(AnalyzerContentTypeName))
{
var name = extension.Header.LocalizedName;
var assemblies = extension.Content.Where(ShouldInclude)
.Select(c => GetContentLocation(shellFolder, rootFolder, extension.InstallPath, c.RelativePath))
.Select(c => extension.GetContentLocation(c))
.WhereNotNull();
builder.Add(new HostDiagnosticAnalyzerPackage(name, assemblies.ToImmutableArray()));
......@@ -100,49 +90,6 @@ internal static ImmutableArray<HostDiagnosticAnalyzerPackage> GetHostAnalyzerPac
return ImmutableArray.Create(new HostDiagnosticAnalyzerPackage(name: null, assemblies: references.ToImmutable()));
}
private static bool TryGetRootAndShellFolder(IVsExtensionManager extensionManager, out string shellFolder, out string rootFolder)
{
// use reflection to get this information. currently there is no other way to get this information
shellFolder = GetProperty(extensionManager, "ShellFolder");
rootFolder = GetProperty(extensionManager, "RootFolder");
return !string.IsNullOrEmpty(rootFolder) && !string.IsNullOrEmpty(shellFolder);
}
private static string GetContentLocation(string shellFolder, string rootFolder, string installPath, string relativePath)
{
// extension manager should expose an API that doesn't require this.
const string ShellFolderToken = "$ShellFolder$";
const string RootFolderToken = "$RootFolder$";
if (relativePath.StartsWith(ShellFolderToken))
{
return relativePath.Replace(ShellFolderToken, shellFolder);
}
else if (relativePath.StartsWith(RootFolderToken))
{
return relativePath.Replace(RootFolderToken, rootFolder);
}
string contentLocation = null;
try
{
contentLocation = Path.Combine(installPath, relativePath);
}
//Path.Combine will throw an ArgumentException if either of the two path arguments contain illegal characters.
//We'll just catch this exception here and ignore the paths with illegal characters.
catch (ArgumentException)
{
}
return contentLocation;
}
private static string GetProperty(IVsExtensionManager extensionManager, string propertyName)
{
return (string)extensionManager.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(extensionManager);
}
private static bool ShouldInclude(IExtensionContent content)
{
return string.Equals(content.ContentTypeName, AnalyzerContentTypeName, StringComparison.InvariantCultureIgnoreCase);
......
......@@ -49,6 +49,34 @@ static GCManager()
});
}
/// <summary>
/// Turn off low latency GC mode.
///
/// if there is a pending low latency mode request, Latency mode will go back to its original status as
/// pending request timeout. once it goes back to its original status, it will not go back to low latency mode again.
/// </summary>
internal static void TurnOffLowLatencyMode()
{
if (s_delayMilliseconds <= 0)
{
// if it is already turned off, we don't do anything.
return;
}
// first set delay to 0 to turn it off
s_delayMilliseconds = 0;
// explictly call Full GC to remove impact of SustainedLowLatency
// this is based on finding on https://github.com/dotnet/roslyn/issues/6802
// one of reason we do this here is so that GC do compact on fragmented memory.
// which will in return let us have bigger continuous free memory chunk.
for (var i = 0; i < 5; i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
/// <summary>
/// Call this method to suppress expensive blocking Gen 2 garbage GCs in
/// scenarios where high-latency is unacceptable (e.g. processing typing input).
......
// 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.ComponentModel.Composition;
using Microsoft.VisualStudio.Utilities;
using Microsoft.Internal.VisualStudio.Shell.TableControl;
using System;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource
{
/// <summary>
/// Supporession column definition filter
/// </summary>
/// <remarks>
/// TODO: Move this column down to the shell as it is shared by multiple issue sources (Roslyn and FxCop).
/// </remarks>
[Export(typeof(EntryFilterDefinition))]
[Name(SuppressionStateColumnDefinition.ColumnName)]
internal class SuppressionStateColumnFilterDefinition : EntryFilterDefinition
{
public override bool HasAttribute(string key) => string.Equals(NonActionable, key, StringComparison.OrdinalIgnoreCase);
}
}
......@@ -8,6 +8,7 @@
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Options;
using Microsoft.VisualStudio.LanguageServices.Implementation;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
......@@ -79,6 +80,12 @@ public int OnBroadcastMessage(uint msg, IntPtr wParam, IntPtr lParam)
_workspace.Services.GetService<IErrorReportingService>().ShowErrorInfo(ServicesVSResources.FullSolutionAnalysisOff, () => { });
}
// turn off low latency GC mode.
// once we hit this, not hitting "Out of memory" exception is more important than typing being smooth all the time.
// once it is turned off, user will hit time to time keystroke which responsive time is more than 50ms. in our own perf lab,
// about 1-2% was over 50ms with this off when we first introduced this GC mode.
GCManager.TurnOffLowLatencyMode();
break;
}
}
......
......@@ -79,6 +79,7 @@
<Compile Include="Implementation\SolutionSize\SolutionSizeTracker.cs" />
<Compile Include="Implementation\TableDataSource\DiagnosticTableControlEventProcessorProvider.AggregateDiagnosticTableControlEventProcessor.cs" />
<Compile Include="Implementation\TableDataSource\Suppression\IVisualStudioDiagnosticListSuppressionStateService.cs" />
<Compile Include="Implementation\TableDataSource\Suppression\SuppressionStateColumnFilterDefinition.cs" />
<Compile Include="Implementation\TableDataSource\Suppression\VisualStudioDiagnosticListTableCommandHandler.cs" />
<Compile Include="Implementation\TableDataSource\Suppression\VisualStudioDiagnosticListSuppressionStateService.cs" />
<Compile Include="Implementation\TableDataSource\Suppression\DiagnosticTableControlEventProcessorProvider.SuppressionStateProcessor.cs" />
......
......@@ -2,6 +2,7 @@
Imports System.ComponentModel
Imports System.Globalization
Imports System.IO
Imports System.Xml
Imports Microsoft.CodeAnalysis
Imports Microsoft.VisualStudio.ExtensionManager
......@@ -29,18 +30,27 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics
Assert.Equal(_contentType, contentTypeName)
For Each location In _locations
Dim installedExceptionMock As New Mock(Of IInstalledExtension)(MockBehavior.Strict)
installedExceptionMock.SetupGet(Function(m) m.InstallPath).Returns("\InstallPath")
installedExceptionMock.SetupGet(Function(m) m.Content).Returns(
SpecializedCollections.SingletonEnumerable(Of IExtensionContent)(New MockContent(_contentType, location)))
Dim installedExtensionMock As New Mock(Of IInstalledExtension)(MockBehavior.Strict)
Dim contentMock = New MockContent(_contentType, location)
installedExtensionMock.SetupGet(Function(m) m.Content).Returns(
SpecializedCollections.SingletonEnumerable(Of IExtensionContent)(contentMock))
installedExtensionMock.Setup(Function(m) m.GetContentLocation(contentMock)).Returns(Function()
If contentMock.RelativePath.IndexOf("$RootFolder$") >= 0 Then
Return contentMock.RelativePath.Replace("$RootFolder$", "ResolvedRootFolder")
ElseIf contentMock.RelativePath.IndexOf("$ShellFolder$") >= 0 Then
Return contentMock.RelativePath.Replace("$ShellFolder$", "ResolvedShellFolder")
Else
Return Path.Combine("\InstallPath", contentMock.RelativePath)
End If
End Function)
Dim headerMock As New Mock(Of IExtensionHeader)(MockBehavior.Strict)
headerMock.SetupGet(Function(h) h.LocalizedName).Returns("Vsix")
installedExceptionMock.SetupGet(Function(m) m.Header).Returns(headerMock.Object)
installedExtensionMock.SetupGet(Function(m) m.Header).Returns(headerMock.Object)
Yield installedExceptionMock.Object
Yield installedExtensionMock.Object
Next
End Function
......
......@@ -13,7 +13,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics
<Fact>
Public Sub GetHostAnalyzerPackagesWithNameTest()
Dim extensionManager = New MockExtensionManager("Microsoft.VisualStudio.Analyzer", "$RootFolder$\test\test.dll", "$ShellFolder$\test\test.dll", "test\test.dll")
Dim packages = VisualStudioWorkspaceDiagnosticAnalyzerProviderService.GetHostAnalyzerPackagesWithName(extensionManager, "ResolvedRootFolder", "ResolvedShellFolder")
Dim packages = VisualStudioWorkspaceDiagnosticAnalyzerProviderService.GetHostAnalyzerPackagesWithName(extensionManager)
Assert.Equal(packages.Count(), 3)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册