Skip to content

Commit

Permalink
Merge pull request #42113 from dotnet/merges/master-to-master-vs-deps
Browse files Browse the repository at this point in the history
Merge master to master-vs-deps
  • Loading branch information
msftbot[bot] committed Mar 3, 2020
2 parents 421bc98 + 646456e commit 66f4958
Show file tree
Hide file tree
Showing 38 changed files with 1,200 additions and 868 deletions.
4 changes: 2 additions & 2 deletions docs/Language Feature Status.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ efforts behind them.
| [Native ints](https://github.com/dotnet/csharplang/issues/435) | [features/NativeInt](https://github.com/dotnet/roslyn/tree/features/NativeInt) | [In Progress](https://github.com/dotnet/roslyn/issues/38821) | [cston](https://github.com/cston) | [333fred](https://github.com/333fred), [gafter](https://github.com/gafter) | [jaredpar](https://github.com/jaredpar) |
| [Attributes on local functions](https://github.com/dotnet/csharplang/issues/1888) | [features/local-function-attributes](https://github.com/dotnet/roslyn/tree/features/local-function-attributes) | [Merged](https://github.com/dotnet/roslyn/issues/38801) | [RikkiGibson](https://github.com/RikkiGibson) | [agocke](https://github.com/agocke) | [agocke](https://github.com/agocke) |
| [Function pointers](https://github.com/dotnet/csharplang/issues/191) | [function-pointers](https://github.com/dotnet/roslyn/tree/features/function-pointers) | [In Progress](https://github.com/dotnet/roslyn/issues/38830) | [333fred](https://github.com/333fred) | [AlekseyTs](https://github.com/AlekseyTs) | [jaredpar](https://github.com/jaredpar) |
| [Pattern matching improvements](https://github.com/dotnet/csharplang/issues/2850) | [features/patterns3](https://github.com/dotnet/roslyn/tree/features/patterns3) | In progress | [gafter](https://github.com/gafter) | [RikkiGibson](https://github.com/RikkiGibson),[agocke](https://github.com/agocke) | [gafter](https://github.com/gafter) |
| [Pattern matching improvements](https://github.com/dotnet/csharplang/issues/2850) | [features/patterns3](https://github.com/dotnet/roslyn/tree/features/patterns3) | [In progress](https://github.com/dotnet/roslyn/issues/41502) ([test](https://github.com/dotnet/roslyn/issues/40727)) | [gafter](https://github.com/gafter) | [RikkiGibson](https://github.com/RikkiGibson),[agocke](https://github.com/agocke) | [gafter](https://github.com/gafter) |
| [Static lambdas](https://github.com/dotnet/csharplang/issues/275) | [features/static-lambdas](https://github.com/dotnet/roslyn/tree/features/static-lambdas) | [In progress](https://github.com/dotnet/roslyn/issues/39606) | [CyrusNajmabadi](https://github.com/CyrusNajmabadi) | [jcouv](https://github.com/jcouv) | [jcouv](https://github.com/jcouv) |
| [Records](https://github.com/dotnet/csharplang/issues/39) | [features/records](https://github.com/dotnet/roslyn/tree/features/records) | In progress | [agocke](https://github.com/agocke) | [gafter](https://github.com/gafter), [333fred](https://github.com/333fred) | [agocke](https://github.com/agocke) |
| [Records](https://github.com/dotnet/csharplang/issues/39) | [features/records](https://github.com/dotnet/roslyn/tree/features/records) | [In progress](https://github.com/dotnet/roslyn/issues/40726) | [agocke](https://github.com/agocke) | [gafter](https://github.com/gafter), [333fred](https://github.com/333fred) | [agocke](https://github.com/agocke) |

# C# 8.0

Expand Down
59 changes: 58 additions & 1 deletion src/Compilers/Core/Portable/InternalUtilities/FatalError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Threading;

#if COMPILERCORE
namespace Microsoft.CodeAnalysis
Expand Down Expand Up @@ -74,6 +75,13 @@ public static void OverwriteHandler(Action<Exception>? value)
s_fatalHandler = value;
}

private static bool IsCurrentOperationBeingCancelled(Exception exception, CancellationToken cancellationToken)
#if NET20 // CancellationToken is not defined on NET20, we have an empty stub for it to reduce the amount of conditional code.
=> exception is OperationCanceledException;
#else
=> exception is OperationCanceledException && cancellationToken.IsCancellationRequested;
#endif

/// <summary>
/// Use in an exception filter to report a fatal error.
/// Unless the exception is <see cref="OperationCanceledException"/>
Expand All @@ -92,7 +100,24 @@ public static bool ReportUnlessCanceled(Exception exception)
}

/// <summary>
/// Use in an exception filter to report a non fatal error.
/// Use in an exception filter to report a fatal error.
/// Calls <see cref="Handler"/> unless the operation has been cancelled.
/// The exception is passed through (the method returns false).
/// </summary>
/// <returns>False to avoid catching the exception.</returns>
[DebuggerHidden]
public static bool ReportUnlessCanceled(Exception exception, CancellationToken cancellationToken)
{
if (IsCurrentOperationBeingCancelled(exception, cancellationToken))
{
return false;
}

return Report(exception);
}

/// <summary>
/// Use in an exception filter to report a non-fatal error.
/// Unless the exception is <see cref="OperationCanceledException"/>
/// it calls <see cref="NonFatalHandler"/>. The exception isn't passed through (the method returns true).
/// </summary>
Expand All @@ -108,6 +133,23 @@ public static bool ReportWithoutCrashUnlessCanceled(Exception exception)
return ReportWithoutCrash(exception);
}

/// <summary>
/// Use in an exception filter to report a non-fatal error.
/// Calls <see cref="NonFatalHandler"/> unless the operation has been cancelled.
/// The exception isn't passed through (the method returns true).
/// </summary>
/// <returns>True to catch the exception.</returns>
[DebuggerHidden]
public static bool ReportWithoutCrashUnlessCanceled(Exception exception, CancellationToken cancellationToken)
{
if (IsCurrentOperationBeingCancelled(exception, cancellationToken))
{
return false;
}

return ReportWithoutCrash(exception);
}

/// <summary>
/// Use in an exception filter to report a fatal error.
/// Unless the exception is <see cref="NotImplementedException"/>
Expand Down Expand Up @@ -180,6 +222,21 @@ public static bool ReportWithoutCrashUnlessCanceledAndPropagate(Exception except
return false;
}

/// <summary>
/// Report a non-fatal error like <see cref="ReportWithoutCrash"/> but propagates the exception, unless the operation has been cancelled.
/// </summary>
/// <returns>False to propagate the exception.</returns>
[DebuggerHidden]
public static bool ReportWithoutCrashUnlessCanceledAndPropagate(Exception exception, CancellationToken cancellationToken)
{
if (!IsCurrentOperationBeingCancelled(exception, cancellationToken))
{
Report(exception, s_nonFatalHandler);
}

return false;
}

private static readonly object s_reportedMarker = new object();

private static void Report(Exception exception, Action<Exception>? handler)
Expand Down
24 changes: 0 additions & 24 deletions src/Compilers/Core/Portable/SourceCodeKind.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,4 @@ public enum SourceCodeKind
[EditorBrowsable(EditorBrowsableState.Never)]
Interactive = 2,
}

internal static partial class SourceCodeKindExtensions
{
internal static SourceCodeKind MapSpecifiedToEffectiveKind(this SourceCodeKind kind)
{
switch (kind)
{
case SourceCodeKind.Script:
#pragma warning disable CS0618 // SourceCodeKind.Interactive is obsolete
case SourceCodeKind.Interactive:
#pragma warning restore CS0618 // SourceCodeKind.Interactive is obsolete
return SourceCodeKind.Script;

case SourceCodeKind.Regular:
default:
return SourceCodeKind.Regular;
}
}

internal static bool IsValid(this SourceCodeKind value)
{
return value >= SourceCodeKind.Regular && value <= SourceCodeKind.Script;
}
}
}
32 changes: 32 additions & 0 deletions src/Compilers/Core/Portable/SourceCodeKindExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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.

#nullable enable

namespace Microsoft.CodeAnalysis
{
internal static partial class SourceCodeKindExtensions
{
internal static SourceCodeKind MapSpecifiedToEffectiveKind(this SourceCodeKind kind)
{
switch (kind)
{
case SourceCodeKind.Script:
#pragma warning disable CS0618 // SourceCodeKind.Interactive is obsolete
case SourceCodeKind.Interactive:
#pragma warning restore CS0618 // SourceCodeKind.Interactive is obsolete
return SourceCodeKind.Script;

case SourceCodeKind.Regular:
default:
return SourceCodeKind.Regular;
}
}

internal static bool IsValid(this SourceCodeKind value)
{
return value >= SourceCodeKind.Regular && value <= SourceCodeKind.Script;
}
}
}
101 changes: 44 additions & 57 deletions src/EditorFeatures/Core.Wpf/IWpfDifferenceViewerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Differencing;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Projection;
using Microsoft.VisualStudio.Threading;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Editor.Shared.Extensions
Expand All @@ -17,85 +19,71 @@ internal static class IWpfDifferenceViewerExtensions
{
private class SizeToFitHelper : ForegroundThreadAffinitizedObject
{
private int _calculationStarted;
private readonly IWpfDifferenceViewer _diffViewer;
private readonly TaskCompletionSource<object> _taskCompletion;

private readonly double _minWidth;

private double _width;
private double _height;

public SizeToFitHelper(IThreadingContext threadingContext, IWpfDifferenceViewer diffViewer, double minWidth)
: base(threadingContext)
{
_calculationStarted = 0;
_diffViewer = diffViewer;
_minWidth = minWidth;
_taskCompletion = new TaskCompletionSource<object>();
}

public async Task SizeToFitAsync()
public async Task SizeToFitAsync(CancellationToken cancellationToken)
{
// The following work must always happen on UI thread.
AssertIsForeground();

// We won't know how many lines there will be in the inline diff or how
// wide the widest line in the inline diff will be until the inline diff
// snapshot has been computed. We register an event handler here that will
// allow us to calculate the required width and height once the inline diff
// snapshot has been computed.
_diffViewer.DifferenceBuffer.SnapshotDifferenceChanged += SnapshotDifferenceChanged;

// The inline diff snapshot may already have been computed before we registered the
// above event handler. In this case, we can go ahead and calculate the required width
// and height.
CalculateSize();

// IDifferenceBuffer calculates the inline diff snapshot on the UI thread (on idle).
// Since we are already on the UI thread, we need to yield control so that the
// inline diff snapshot computation (and the event handler we registered above to
// calculate required width and height) get a chance to run and we need to wait until
// this computation is complete. Once computation is complete, the width and height
// need to be set from the UI thread. We use ConfigureAwait(true) to stay on the UI thread.
await _taskCompletion.Task.ConfigureAwait(true);

// The following work must always happen on UI thread.
AssertIsForeground();
await ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

#pragma warning disable CA2007 // Consider calling ConfigureAwait on the awaited task (containing method uses JTF)
await CalculateSizeAsync(cancellationToken);
#pragma warning restore CA2007 // Consider calling ConfigureAwait on the awaited task

// We have the height and width required to display the inline diff snapshot now.
// Set the height and width of the IWpfDifferenceViewer accordingly.
_diffViewer.VisualElement.Width = _width;
_diffViewer.VisualElement.Height = _height;
}

private void SnapshotDifferenceChanged(object sender, SnapshotDifferenceChangeEventArgs args)
private async Task<IProjectionSnapshot> GetInlineBufferSnapshotAsync(CancellationToken cancellationToken)
{
// The following work must always happen on UI thread.
AssertIsForeground();
cancellationToken.ThrowIfCancellationRequested();

if (_diffViewer.DifferenceBuffer.CurrentInlineBufferSnapshot is { } snapshot)
{
return snapshot;
}

// This event handler will only be called when the inline diff snapshot computation is complete.
Contract.ThrowIfNull(_diffViewer.DifferenceBuffer.CurrentInlineBufferSnapshot);
var completionSource = new TaskCompletionSource<IProjectionSnapshot>(TaskCreationOptions.RunContinuationsAsynchronously);
_diffViewer.DifferenceBuffer.SnapshotDifferenceChanged += HandleSnapshotDifferenceChanged;

// We can go ahead and calculate the required height and width now.
CalculateSize();
}
// Handle cases where the snapshot was set between the previous check and the event registration
if (_diffViewer.DifferenceBuffer.CurrentInlineBufferSnapshot is { } snapshot2)
completionSource.SetResult(snapshot2);

private void CalculateSize()
{
// The following work must always happen on UI thread.
AssertIsForeground();
try
{
return await completionSource.Task.WithCancellation(cancellationToken).ConfigureAwaitRunInline();
}
finally
{
_diffViewer.DifferenceBuffer.SnapshotDifferenceChanged -= HandleSnapshotDifferenceChanged;
}

if ((_diffViewer.DifferenceBuffer.CurrentInlineBufferSnapshot == null) ||
(Interlocked.CompareExchange(ref _calculationStarted, 1, 0) == 1))
// Local function
void HandleSnapshotDifferenceChanged(object sender, SnapshotDifferenceChangeEventArgs e)
{
// Return if inline diff snapshot is not yet ready or
// if the size calculation is already in progress.
return;
// This event handler will only be called when the inline diff snapshot computation is complete.
Contract.ThrowIfNull(_diffViewer.DifferenceBuffer.CurrentInlineBufferSnapshot);

completionSource.SetResult(_diffViewer.DifferenceBuffer.CurrentInlineBufferSnapshot);
}
}

// Unregister the event handler - we don't need it anymore since the inline diff
// snapshot is available at this point.
_diffViewer.DifferenceBuffer.SnapshotDifferenceChanged -= SnapshotDifferenceChanged;
private async Task CalculateSizeAsync(CancellationToken cancellationToken)
{
await ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

IWpfTextView textView;
ITextSnapshot snapshot;
Expand All @@ -112,7 +100,9 @@ private void CalculateSize()
else
{
textView = _diffViewer.InlineView;
snapshot = _diffViewer.DifferenceBuffer.CurrentInlineBufferSnapshot;
#pragma warning disable CA2007 // Consider calling ConfigureAwait on the awaited task (containing method uses JTF)
snapshot = await GetInlineBufferSnapshotAsync(cancellationToken);
#pragma warning restore CA2007 // Consider calling ConfigureAwait on the awaited task
}

// Perform a layout without actually rendering the content on the screen so that
Expand All @@ -130,9 +120,6 @@ private void CalculateSize()
_height = textView.LineHeight * (textView.ZoomLevel / 100) * // Height of each line.
snapshot.LineCount; // Number of lines.
Contract.ThrowIfFalse(IsNormal(_height));

// Calculation of required height and width is now complete.
_taskCompletion.SetResult(null);
}

private static bool IsNormal(double value)
Expand All @@ -141,10 +128,10 @@ private static bool IsNormal(double value)
}
}

public static Task SizeToFitAsync(this IWpfDifferenceViewer diffViewer, IThreadingContext threadingContext, double minWidth = 400.0)
public static Task SizeToFitAsync(this IWpfDifferenceViewer diffViewer, IThreadingContext threadingContext, double minWidth = 400.0, CancellationToken cancellationToken = default)
{
var helper = new SizeToFitHelper(threadingContext, diffViewer, minWidth);
return helper.SizeToFitAsync();
return helper.SizeToFitAsync(cancellationToken);
}
}
}

0 comments on commit 66f4958

Please sign in to comment.