未验证 提交 4c32f5e4 编写于 作者: D David Barbet 提交者: GitHub

Merge pull request #53072 from dotnet/merges/release/dev16.10-to-release/dev16.10-vs-deps

Merge release/dev16.10 to release/dev16.10-vs-deps
......@@ -27,6 +27,9 @@ internal SubstitutedNestedTypeSymbol(SubstitutedNamedTypeSymbol newContainer, Na
{
}
internal override bool GetUnificationUseSiteDiagnosticRecursive(ref DiagnosticInfo result, Symbol owner, ref HashSet<TypeSymbol> checkedTypes)
=> OriginalDefinition.GetUnificationUseSiteDiagnosticRecursive(ref result, owner, ref checkedTypes);
internal override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotationsNoUseSiteDiagnostics
{
get { return GetTypeParametersAsTypeArguments(); }
......
......@@ -159,6 +159,8 @@ internal override ImmutableArray<NamedTypeSymbol> GetInterfacesToEmit()
throw ExceptionUtilities.Unreachable;
}
internal abstract override bool GetUnificationUseSiteDiagnosticRecursive(ref DiagnosticInfo result, Symbol owner, ref HashSet<TypeSymbol> checkedTypes);
public sealed override IEnumerable<string> MemberNames
{
get
......
......@@ -7123,5 +7123,108 @@ static void M()
Diagnostic(ErrorCode.ERR_BadArity, "GetServiceC<>").WithArguments("Program.GetServiceC<T1, T2>()", "method", "2").WithLocation(14, 9)
);
}
[Fact, WorkItem(1279758, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1279758/")]
public void RecursiveConstraintsFromUnifiedAssemblies_1()
{
var code = @"
public abstract class A<T1, T2>
where T1 : A<T1, T2>
where T2 : A<T1, T2>.B<T1, T2>
{
public abstract class B<T3, T4>
where T3 : A<T3, T4>
where T4 : A<T3, T4>.B<T3, T4>
{ }
}
public class C : A<C, C.D>
{
public class D : A<C, C.D>.B<C, D>
{
}
}
";
var metadataComp = CreateEmptyCompilation(code, new[] { MscorlibRef_v20 }, assemblyName: "assembly1");
metadataComp.VerifyDiagnostics();
var comp = CreateCompilation(@"System.Console.WriteLine(typeof(C.D).FullName);",
new[] { metadataComp.EmitToImageReference() },
targetFramework: TargetFramework.Mscorlib45);
// warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy
DiagnosticDescription expectedDiagnostic = Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "assembly1", "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "mscorlib").WithLocation(1, 1);
// These are unification use-site diagnostics. The original stackoverflow bug here came from checking constraints as part of
// unification diagnostic calculation, so we want to verify that these are present to make sure we're testing the correct scenario.
comp.VerifyDiagnostics(
expectedDiagnostic,
// warning CS1701: Assuming assembly reference 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' used by 'assembly1' matches identity 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' of 'mscorlib', you may need to supply runtime policy
expectedDiagnostic
);
CompileAndVerify(
comp.WithOptions(comp.Options.WithSpecificDiagnosticOptions("CS1701", ReportDiagnostic.Suppress)),
expectedOutput: "C+D");
var c = comp.GetTypeByMetadataName("C");
Assert.True(c.ContainingModule.HasUnifiedReferences);
Assert.Equal(expectedDiagnostic.Code, c.GetUseSiteDiagnostic().Code);
}
[Fact, WorkItem(1279758, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1279758/")]
public void RecursiveConstraintsFromUnifiedAssemblies_2()
{
var remappedCode = @"public class F {}";
var remappedComp11 = CreateCompilation(
new AssemblyIdentity("remapped", new Version("1.0.0.0"), publicKeyOrToken: SigningTestHelpers.PublicKey, hasPublicKey: true),
new[] { remappedCode },
TargetFrameworkUtil.NetStandard20References.ToArray(),
TestOptions.ReleaseDll.WithPublicSign(true));
var remappedComp12 = CreateCompilation(
new AssemblyIdentity("remapped", new Version("2.0.0.0"), publicKeyOrToken: SigningTestHelpers.PublicKey, hasPublicKey: true),
new[] { remappedCode },
TargetFrameworkUtil.NetStandard20References.ToArray(),
TestOptions.ReleaseDll.WithPublicSign(true));
var code = @"
public abstract class A<T1, T2>
where T1 : A<T1, T2>
where T2 : A<T1, T2>.B<T1, T2>
{
public abstract class B<T3, T4>
where T3 : A<T3, T4>
where T4 : A<T3, T4>.B<T3, T4>
{ }
}
public class C : A<C, C.D>
{
public class D : A<C, C.D>.B<C, D>
{
}
}
public class G : F {}
";
var metadataComp = CreateCompilation(code, new[] { remappedComp11.EmitToImageReference() }, assemblyName: "intermediate", targetFramework: TargetFramework.NetStandard20);
metadataComp.VerifyDiagnostics();
var comp = CreateCompilation(@"
System.Console.WriteLine(typeof(C.D).FullName);
System.Console.WriteLine(typeof(G).FullName);
",
new[] { metadataComp.EmitToImageReference(), remappedComp12.EmitToImageReference() },
targetFramework: TargetFramework.NetStandard20);
comp.VerifyDiagnostics(
// warning CS1701: Assuming assembly reference 'remapped, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2' used by 'intermediate' matches identity 'remapped, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2' of 'remapped', you may need to supply runtime policy
Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("remapped, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "intermediate", "remapped, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "remapped").WithLocation(1, 1)
);
var c = comp.GetTypeByMetadataName("C");
Assert.Null(c.GetUseSiteDiagnostic());
Assert.True(c.ContainingModule.HasUnifiedReferences);
}
}
}
......@@ -5839,6 +5839,43 @@ BC32044: Type argument 'String' does not inherit from or implement the constrain
</expected>)
End Sub
<Fact, WorkItem(1279758, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1279758/")>
Public Sub RecursiveConstraintsFromUnifiedAssemblies()
Dim metadataComp = CreateCompilationWithMscorlib40(
<compilation>
<file name="a.vb"><![CDATA[
Public Class A(Of T1 As A(Of T1, T2), T2 As A(Of T1, T2).B(Of T1, T2))
Public Class B(Of T3 As A(Of T3, T4), T4 As A(Of T3, T4).B(Of T3, T4))
End Class
End Class
Public Class C
Inherits A(Of C, C.D)
Public Class D
Inherits A(Of C, C.D).B(Of C, C.D)
End Class
End Class]]>
</file>
</compilation>, assemblyName:="assembly1")
metadataComp.AssertTheseDiagnostics()
Dim finalComp = CreateCompilationWithMscorlib45(
<compilation>
<file name="b.vb"><![CDATA[
Class D
Shared Sub Main()
System.Console.WriteLine(GetType(C.D).FullName)
End Sub
End Class]]>
</file>
</compilation>, {metadataComp.EmitToImageReference()})
finalComp.AssertTheseDiagnostics()
Assert.Null(finalComp.GetTypeByMetadataName("C").GetUseSiteErrorInfo())
End Sub
End Class
End Namespace
......@@ -45,6 +45,9 @@
<CheckBox x:Name="Show_Remove_Unused_References_command_in_Solution_Explorer_experimental"
Content="{x:Static local:AdvancedOptionPageStrings.Option_Show_Remove_Unused_References_command_in_Solution_Explorer_experimental}" />
<CheckBox x:Name="Enable_file_logging_for_diagnostics"
Content="{x:Static local:AdvancedOptionPageStrings.Option_Enable_file_logging_for_diagnostics}" />
</StackPanel>
</GroupBox>
<GroupBox x:Uid="UsingDirectivesGroupBox"
......
......@@ -46,6 +46,7 @@ public AdvancedOptionPageControl(OptionStore optionStore, IComponentModel compon
BindToOption(Background_analysis_scope_full_solution, SolutionCrawlerOptions.BackgroundAnalysisScopeOption, BackgroundAnalysisScope.FullSolution, LanguageNames.CSharp);
BindToOption(Enable_navigation_to_decompiled_sources, FeatureOnOffOptions.NavigateToDecompiledSources);
BindToOption(Use_64bit_analysis_process, RemoteHostOptions.OOP64Bit);
BindToOption(Enable_file_logging_for_diagnostics, InternalDiagnosticsOptions.EnableFileLoggingForDiagnostics);
BindToOption(Show_Remove_Unused_References_command_in_Solution_Explorer_experimental, FeatureOnOffOptions.OfferRemoveUnusedReferences, () =>
{
// If the option has not been set by the user, check if the option to remove unused references
......
......@@ -271,6 +271,9 @@ public static string Option_Show_Remove_Unused_References_command_in_Solution_Ex
public static string Enable_all_features_in_opened_files_from_source_generators_experimental
=> ServicesVSResources.Enable_all_features_in_opened_files_from_source_generators_experimental;
public static string Option_Enable_file_logging_for_diagnostics
=> ServicesVSResources.Enable_file_logging_for_diagnostics;
public static string Show_inheritance_margin
=> ServicesVSResources.Show_inheritance_margin;
......
......@@ -1653,6 +1653,9 @@ I agree to all of the foregoing:</value>
<data name="Show_Remove_Unused_References_command_in_Solution_Explorer_experimental" xml:space="preserve">
<value>Show "Remove Unused References" command in Solution Explorer (experimental)</value>
</data>
<data name="Enable_file_logging_for_diagnostics" xml:space="preserve">
<value>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</value>
</data>
<data name="This_action_cannot_be_undone_Do_you_wish_to_continue" xml:space="preserve">
<value>This action cannot be undone. Do you wish to continue?</value>
</data>
......
......@@ -38,6 +38,7 @@ protected override ILogger CreateLogger(TelemetrySession telemetrySession)
CodeMarkerLogger.Instance,
new EtwLogger(_optionsService),
new VSTelemetryLogger(telemetrySession),
new FileLogger(_optionsService),
Logger.GetLogger());
protected override void TelemetrySessionInitialized()
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">Povolit diagnostiku pull (experimentální, vyžaduje restart)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">Pull-Diagnose aktivieren (experimentell, Neustart erforderlich)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">Habilitar diagnósticos "pull" (experimental, requiere reiniciar)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">Activer les diagnostics de 'tirage (pull)' (expérimental, nécessite un redémarrage)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">Abilita diagnostica 'pull' (sperimentale, richiede il riavvio)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">'pull' 診断を有効にする (試験段階、再起動が必要)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">'풀' 진단 사용(실험적, 다시 시작 필요)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">Włącz diagnostykę operacji „pull” (eksperymentalne, wymaga ponownego uruchomienia)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">Habilitar o diagnóstico de 'pull' (experimental, exige uma reinicialização)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">Включить диагностику "pull" (экспериментальная функция, требуется перезапуск)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">'Pull' tanılamasını etkinleştir (deneysel, yeniden başlatma gerekir)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">启用“拉取”诊断(实验性,需要重启)</target>
......
......@@ -297,6 +297,11 @@
<target state="new">Enable all features in opened files from source generators (experimental)</target>
<note />
</trans-unit>
<trans-unit id="Enable_file_logging_for_diagnostics">
<source>Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</source>
<target state="new">Enable file logging for diagnostics (logged in '%Temp%\Roslyn' folder)</target>
<note />
</trans-unit>
<trans-unit id="Enable_pull_diagnostics_experimental_requires_restart">
<source>Enable 'pull' diagnostics (experimental, requires restart)</source>
<target state="translated">啟用 'pull' 診斷 (實驗性,需要重新啟動)</target>
......
......@@ -32,6 +32,8 @@
Content="{x:Static local:AdvancedOptionPageStrings.Option_use_64bit_analysis_process}" />
<CheckBox x:Name="Show_Remove_Unused_References_command_in_Solution_Explorer_experimental"
Content="{x:Static local:AdvancedOptionPageStrings.Option_Show_Remove_Unused_References_command_in_Solution_Explorer_experimental}" />
<CheckBox x:Name="Enable_file_logging_for_diagnostics"
Content="{x:Static local:AdvancedOptionPageStrings.Option_Enable_file_logging_for_diagnostics}" />
</StackPanel>
</GroupBox>
<GroupBox x:Uid="ImportDirectivesGroupBox"
......
......@@ -4,6 +4,7 @@
Imports System.Windows
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.DocumentationComments
Imports Microsoft.CodeAnalysis.Editing
Imports Microsoft.CodeAnalysis.Editor.Implementation.SplitComment
......@@ -41,6 +42,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
BindToOption(Background_analysis_scope_open_files, SolutionCrawlerOptions.BackgroundAnalysisScopeOption, BackgroundAnalysisScope.OpenFilesAndProjects, LanguageNames.VisualBasic)
BindToOption(Background_analysis_scope_full_solution, SolutionCrawlerOptions.BackgroundAnalysisScopeOption, BackgroundAnalysisScope.FullSolution, LanguageNames.VisualBasic)
BindToOption(Use_64bit_analysis_process, RemoteHostOptions.OOP64Bit)
BindToOption(Enable_file_logging_for_diagnostics, InternalDiagnosticsOptions.EnableFileLoggingForDiagnostics)
BindToOption(Show_Remove_Unused_References_command_in_Solution_Explorer_experimental, FeatureOnOffOptions.OfferRemoveUnusedReferences,
Function()
' If the option has Not been set by the user, check if the option to remove unused references
......
......@@ -287,6 +287,9 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
Public ReadOnly Property Enable_all_features_in_opened_files_from_source_generators_experimental As String =
ServicesVSResources.Enable_all_features_in_opened_files_from_source_generators_experimental
Public ReadOnly Property Option_Enable_file_logging_for_diagnostics As String =
ServicesVSResources.Enable_file_logging_for_diagnostics
Public ReadOnly Property Show_inheritance_margin As String =
ServicesVSResources.Show_inheritance_margin
......
......@@ -30,5 +30,8 @@ internal static class InternalDiagnosticsOptions
public static readonly Option2<DiagnosticMode> RazorDiagnosticMode = new(nameof(InternalDiagnosticsOptions), nameof(RazorDiagnosticMode), defaultValue: DiagnosticMode.Pull,
storageLocations: new LocalUserProfileStorageLocation(LocalRegistryPath + "RazorDiagnosticMode"));
public static readonly Option2<bool> EnableFileLoggingForDiagnostics = new(nameof(InternalDiagnosticsOptions), nameof(EnableFileLoggingForDiagnostics), defaultValue: false,
storageLocations: new LocalUserProfileStorageLocation(LocalRegistryPath + "EnableFileLoggingForDiagnostics"));
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Internal.Log
{
/// <summary>
/// A logger that publishes events to a log file.
/// </summary>
internal sealed class FileLogger : ILogger
{
private readonly object _gate;
private readonly string _logFilePath;
private readonly StringBuilder _buffer;
private bool _enabled;
/// <summary>
/// Task queue to serialize all the IO to the log file.
/// </summary>
private readonly TaskQueue _taskQueue;
public FileLogger(IGlobalOptionService optionService, string logFilePath)
{
_logFilePath = logFilePath;
_gate = new();
_buffer = new();
_taskQueue = new(AsynchronousOperationListenerProvider.NullListener, TaskScheduler.Default);
_enabled = optionService.GetOption(InternalDiagnosticsOptions.EnableFileLoggingForDiagnostics);
optionService.OptionChanged += OptionService_OptionChanged;
}
public FileLogger(IGlobalOptionService optionService)
: this(optionService, Path.Combine(Path.GetTempPath(), "Roslyn", "Telemetry", GetLogFileName()))
{
}
private static string GetLogFileName()
=> DateTime.Now.ToString().Replace(' ', '_').Replace('/', '_').Replace(':', '_') + ".log";
private void OptionService_OptionChanged(object? sender, OptionChangedEventArgs e)
{
if (e.Option == InternalDiagnosticsOptions.EnableFileLoggingForDiagnostics)
{
Contract.ThrowIfNull(e.Value);
_enabled = (bool)e.Value;
}
}
public bool IsEnabled(FunctionId functionId)
{
if (!_enabled)
{
return false;
}
// Limit logged function IDs to keep a reasonable log file size.
var str = functionId.ToString();
return str.StartsWith("Diagnostic") ||
str.StartsWith("CodeAnalysisService") ||
str.StartsWith("Workspace") ||
str.StartsWith("WorkCoordinator") ||
str.StartsWith("IncrementalAnalyzerProcessor") ||
str.StartsWith("ExternalErrorDiagnosticUpdateSource");
}
private void Log(FunctionId functionId, string message)
{
_taskQueue.ScheduleTask(nameof(FileLogger), () =>
{
lock (_gate)
{
_buffer.AppendLine($"{DateTime.Now} ({functionId}) : {message}");
try
{
if (!File.Exists(_logFilePath))
{
Directory.CreateDirectory(PathUtilities.GetDirectoryName(_logFilePath));
}
File.AppendAllText(_logFilePath, _buffer.ToString());
_buffer.Clear();
}
catch (IOException)
{
// Ignore IOException, we will log the buffer contents in next Log call.
}
}
}, CancellationToken.None);
}
public void Log(FunctionId functionId, LogMessage logMessage)
=> Log(functionId, logMessage.GetMessage());
public void LogBlockStart(FunctionId functionId, LogMessage logMessage, int uniquePairId, CancellationToken cancellationToken)
=> LogBlockEvent(functionId, logMessage, uniquePairId, "BlockStart");
public void LogBlockEnd(FunctionId functionId, LogMessage logMessage, int uniquePairId, int delta, CancellationToken cancellationToken)
=> LogBlockEvent(functionId, logMessage, uniquePairId, cancellationToken.IsCancellationRequested ? "BlockCancelled" : "BlockEnd");
private void LogBlockEvent(FunctionId functionId, LogMessage logMessage, int uniquePairId, string blockEvent)
=> Log(functionId, $"[{blockEvent} - {uniquePairId}] {logMessage.GetMessage()}");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册