Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge release/dev16.10 to main #53033

Merged
merged 30 commits into from
Apr 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2de59fd
Do not show UI if no managed projects are loaded
jmarolf Apr 26, 2021
363d5ac
Kick work down if new work comes in
CyrusNajmabadi Apr 27, 2021
0e1253d
Cleanup
CyrusNajmabadi Apr 27, 2021
e435f17
Test hook
CyrusNajmabadi Apr 27, 2021
b3506f7
Simplify code.
CyrusNajmabadi Apr 27, 2021
31c94cf
Simplify queuing
CyrusNajmabadi Apr 27, 2021
2db89d0
reoder'
CyrusNajmabadi Apr 27, 2021
56fd68c
Simplify queuing
CyrusNajmabadi Apr 27, 2021
057a4a1
use helper'
CyrusNajmabadi Apr 27, 2021
896c501
ensure ordering
CyrusNajmabadi Apr 27, 2021
1181c11
Extract'
CyrusNajmabadi Apr 27, 2021
ec0a12e
Update EditAndContinueCapabilities.cs (#52935)
davidwengier Apr 27, 2021
158e7ff
Handle disposal
CyrusNajmabadi Apr 27, 2021
0b4a2c7
Ensure we don't reference cancellation token from this point on.
CyrusNajmabadi Apr 27, 2021
185187c
Simplify
CyrusNajmabadi Apr 27, 2021
1ed5dc6
Simplify
CyrusNajmabadi Apr 27, 2021
2c48c8e
Merge remote-tracking branch 'upstream/release/dev16.10' into restart…
CyrusNajmabadi Apr 27, 2021
35555e5
NRT
CyrusNajmabadi Apr 27, 2021
617e59c
Merge pull request #52946 from CyrusNajmabadi/restartTagging
CyrusNajmabadi Apr 27, 2021
d3801b3
Optimize the case when we have a generator not producing output
jasonmalinowski Apr 27, 2021
34b64e7
Move to Ubuntu 18.04 queue
JoeRobich Apr 28, 2021
845c245
Make CodeAction.CustomTags internal
JoeRobich Apr 29, 2021
caa91bd
Merge pull request #52979 from jasonmalinowski/fix-generator-assert
jasonmalinowski Apr 29, 2021
2ec1c6c
Merge pull request #52995 from dotnet/dev/jorobich/move-ubuntu-queue
JoeRobich Apr 29, 2021
776d0c9
Remove CustomTags from CodeAction constructors
JoeRobich Apr 29, 2021
f015548
Fix EnC capabilties check for runtimes that aren't returning capabili…
davidwengier Apr 29, 2021
92f460a
Merge pull request #52934 from jmarolf/bugfix/more-resilient-editor-f…
jmarolf Apr 29, 2021
e01744e
Merge pull request #53008 from JoeRobich/make-customtags-internal
JoeRobich Apr 29, 2021
327698b
Disable CompileTimeSolutionProvider
tmat Apr 29, 2021
de369e7
Implement the right interface
tmat Apr 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ jobs:
jobName: Build_Unix_Debug
testArtifactName: Transport_Artifacts_Unix_Debug
configuration: Debug
vmImageName: 'ubuntu-16.04'
vmImageName: 'ubuntu-18.04'

- template: eng/pipelines/test-unix-job.yml
parameters:
Expand All @@ -127,7 +127,7 @@ jobs:
buildJobName: Build_Unix_Debug
testArtifactName: Transport_Artifacts_Unix_Debug
configuration: Debug
testArguments: --testCoreClr --helixQueueName Ubuntu.1604.Amd64.Open
testArguments: --testCoreClr --helixQueueName Ubuntu.1804.Amd64.Open

- template: eng/pipelines/test-unix-job-single-machine.yml
parameters:
Expand All @@ -137,7 +137,7 @@ jobs:
testArtifactName: Transport_Artifacts_Unix_Debug
configuration: Debug
testArguments: --testCoreClr
queueName: 'BuildPool.Ubuntu.1604.amd64.Open'
queueName: 'BuildPool.Ubuntu.1804.amd64.Open'

- template: eng/pipelines/test-unix-job.yml
parameters:
Expand Down Expand Up @@ -201,7 +201,7 @@ jobs:
- job: Correctness_SourceBuild
pool:
name: NetCorePublic-Pool
queue: BuildPool.Ubuntu.1604.amd64.Open
queue: BuildPool.Ubuntu.1804.amd64.Open
timeoutInMinutes: 90
steps:
- template: eng/pipelines/checkout-unix-task.yml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public ReferenceHighlightingViewTaggerProvider(
{
}

protected override TaggerDelay EventChangeDelay => TaggerDelay.Short;
protected override TaggerDelay EventChangeDelay => TaggerDelay.Medium;

protected override ITaggerEventSource CreateEventSource(ITextView textView, ITextBuffer subjectBuffer)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,12 @@ internal static TimeSpan ComputeTimeDelay(this TaggerDelay behavior, ITextBuffer
}

internal static TimeSpan ComputeTimeDelay(this TaggerDelay behavior)
{
switch (behavior)
=> behavior switch
{
case TaggerDelay.NearImmediate:
return TimeSpan.FromMilliseconds(NearImmediateDelay);
case TaggerDelay.Short:
return TimeSpan.FromMilliseconds(ShortDelay);
case TaggerDelay.Medium:
return TimeSpan.FromMilliseconds(MediumDelay);
case TaggerDelay.OnIdle:
default:
return TimeSpan.FromMilliseconds(IdleDelay);
}
}
TaggerDelay.NearImmediate => TimeSpan.FromMilliseconds(NearImmediateDelay),
TaggerDelay.Short => TimeSpan.FromMilliseconds(ShortDelay),
TaggerDelay.Medium => TimeSpan.FromMilliseconds(MediumDelay),
_ => TimeSpan.FromMilliseconds(IdleDelay),
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Tagging;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Options;
Expand Down Expand Up @@ -61,9 +62,14 @@ private sealed partial class TagSource : ForegroundThreadAffinitizedObject

/// <summary>
/// Work queue that collects event notifications and kicks off the work to process them.
/// The value that is passed here tells us if this is the initial tag computation or not.
/// </summary>
private readonly AsyncBatchingWorkQueue<bool> _eventWorkQueue;
private Task _eventWorkQueue = Task.CompletedTask;

/// <summary>
/// Series of tokens used to cancel previous outstanding work when new work comes in. Also used as the lock
/// to ensure threadsafe writing of _eventWorkQueue.
/// </summary>
private readonly CancellationSeries _cancellationSeries;

/// <summary>
/// Work queue that collects high priority requests to call TagsChanged with.
Expand Down Expand Up @@ -120,12 +126,7 @@ public TagSource(
_dataSource = dataSource;
_asyncListener = asyncListener;

_eventWorkQueue = new AsyncBatchingWorkQueue<bool>(
_dataSource.EventChangeDelay.ComputeTimeDelay(),
ProcessEventsAsync,
EqualityComparer<bool>.Default,
asyncListener,
_disposalTokenSource.Token);
_cancellationSeries = new CancellationSeries(_disposalTokenSource.Token);

_highPriTagsChangedQueue = new AsyncBatchingWorkQueue<NormalizedSnapshotSpanCollection>(
TaggerDelay.NearImmediate.ComputeTimeDelay(),
Expand Down Expand Up @@ -153,12 +154,11 @@ public TagSource(
DebugRecordInitialStackTrace();

_eventSource = CreateEventSource();

Connect();

// Start computing the initial set of tags immediately. We want to get the UI
// to a complete state as soon as possible.
_eventWorkQueue.AddWork(/*initialTags*/ true);
EnqueueWork(initialTags: true);

return;

Expand Down Expand Up @@ -199,6 +199,8 @@ private void Dispose()

// Stop computing any initial tags if we've been asked for them.
_disposalTokenSource.Cancel();
_cancellationSeries.Dispose();

_disposed = true;
_dataSource.RemoveTagSource(_textViewOpt, _subjectBuffer);
GC.SuppressFinalize(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
Expand All @@ -15,6 +14,7 @@
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
Expand All @@ -28,10 +28,7 @@ internal partial class AbstractAsynchronousTaggerProvider<TTag>
{
private partial class TagSource
{
private void OnEventSourceChanged(object sender, TaggerEventArgs _)
=> _eventWorkQueue.AddWork(/*initialTags*/ false);

private void OnCaretPositionChanged(object sender, CaretPositionChangedEventArgs e)
private void OnCaretPositionChanged(object? _, CaretPositionChangedEventArgs e)
{
this.AssertIsForeground();

Expand Down Expand Up @@ -66,7 +63,7 @@ private void RemoveAllTags()
RaiseTagsChanged(snapshot.TextBuffer, new DiffResult(added: null, removed: new(oldTagTree.GetSpans(snapshot).Select(s => s.Span))));
}

private void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e)
private void OnSubjectBufferChanged(object? _, TextContentChangedEventArgs e)
{
this.AssertIsForeground();
UpdateTagsForTextChange(e);
Expand Down Expand Up @@ -166,13 +163,42 @@ private TagSpanIntervalTree<TTag> GetTagTree(ITextSnapshot snapshot, ImmutableDi
: new TagSpanIntervalTree<TTag>(snapshot.TextBuffer, _dataSource.SpanTrackingMode);
}

private async Task ProcessEventsAsync(ImmutableArray<bool> events, CancellationToken cancellationToken)
private void OnEventSourceChanged(object? _1, TaggerEventArgs _2)
{
EnqueueWork(initialTags: false);
}

private void EnqueueWork(bool initialTags)
{
// Can only have at most a single `true` and `false` value in this as we are deduping these notification values.
Contract.ThrowIfTrue(events.Length > 2);
var initialTags = events.Contains(true);
await this.ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
await RecomputeTagsForegroundAsync(initialTags, cancellationToken).ConfigureAwait(false);
lock (_cancellationSeries)
{
try
{
// cancel the last piece of computation work and enqueue the next. This doesn't apply for the very
// first tag request we make. We don't want that to be cancellable as we want that result to be
// shown as soon as possible.
var cancellationToken = initialTags ? _disposalTokenSource.Token : _cancellationSeries.CreateNext();

// Continue after the preceeding task unilaterally. Note that we pass LazyCancellation so that
// we still wait for that task to complete even if cancelled before we proceed. This is necessary
// as that prior task may mutate state (even if cancelled) so we cannot proceed until we know it
// is completely done.
_eventWorkQueue = _eventWorkQueue.ContinueWithAfterDelayFromAsync(
async _ =>
{
await this.ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
await RecomputeTagsForegroundAsync(initialTags, cancellationToken).ConfigureAwait(false);
},
cancellationToken,
(int)_dataSource.EventChangeDelay.ComputeTimeDelay().TotalMilliseconds,
TaskContinuationOptions.None,
TaskScheduler.Default).CompletesAsyncOperation(_asyncListener.BeginAsyncOperation(nameof(EnqueueWork)));
}
catch (ObjectDisposedException)
{
// can happen if our type was disposed and we try to get a new token from _cancellationSeries.
}
}
}

/// <summary>
Expand All @@ -187,6 +213,8 @@ private async Task ProcessEventsAsync(ImmutableArray<bool> events, CancellationT
private async Task RecomputeTagsForegroundAsync(bool initialTags, CancellationToken cancellationToken)
{
this.AssertIsForeground();
if (cancellationToken.IsCancellationRequested)
return;

using (Logger.LogBlock(FunctionId.Tagger_TagSource_RecomputeTags, cancellationToken))
{
Expand All @@ -210,15 +238,22 @@ private async Task RecomputeTagsForegroundAsync(bool initialTags, CancellationTo
oldState, spansToTag, caretPosition, textChangeRange, oldTagTrees, cancellationToken);
await ProduceTagsAsync(context).ConfigureAwait(false);

cancellationToken.ThrowIfCancellationRequested();

// Process the result to determine what changed.
var newTagTrees = ComputeNewTagTrees(oldTagTrees, context);
var bufferToChanges = ProcessNewTagTrees(spansToTag, oldTagTrees, newTagTrees, cancellationToken);

// Then switch back to the UI thread to update our state and kick off the work to notify the editor.
await this.ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

// Once we assign our state, we're uncancellable. We must report the changed information
// to the editor. The only case where it's ok not to is if the tagger itself is disposed.
cancellationToken = CancellationToken.None;

this.CachedTagTrees = newTagTrees;
this.State = context.State;

OnTagsChangedForBuffer(bufferToChanges, initialTags);
}
}
Expand All @@ -229,7 +264,7 @@ private ImmutableArray<DocumentSnapshotSpan> GetSpansAndDocumentsToTag()

// TODO: Update to tag spans from all related documents.

var snapshotToDocumentMap = new Dictionary<ITextSnapshot, Document>();
using var _ = PooledDictionary<ITextSnapshot, Document?>.GetInstance(out var snapshotToDocumentMap);
var spansToTag = _dataSource.GetSpansToTag(_textViewOpt, _subjectBuffer);

var spansAndDocumentsToTag = spansToTag.SelectAsArray(span =>
Expand Down Expand Up @@ -292,7 +327,7 @@ private ImmutableDictionary<ITextBuffer, TagSpanIntervalTree<TTag>> ComputeNewTa
return newTagTrees;
}

private TagSpanIntervalTree<TTag> ComputeNewTagTree(
private TagSpanIntervalTree<TTag>? ComputeNewTagTree(
ImmutableDictionary<ITextBuffer, TagSpanIntervalTree<TTag>> oldTagTrees,
ITextBuffer textBuffer,
IEnumerable<ITagSpan<TTag>> newTags,
Expand Down Expand Up @@ -473,15 +508,15 @@ private static DiffResult ComputeDifference(

return new DiffResult(new(added), new(removed));

static ITagSpan<TTag> NextOrNull(IEnumerator<ITagSpan<TTag>> enumerator)
static ITagSpan<TTag>? NextOrNull(IEnumerator<ITagSpan<TTag>> enumerator)
=> enumerator.MoveNext() ? enumerator.Current : null;
}

/// <summary>
/// Returns the TagSpanIntervalTree containing the tags for the given buffer. If no tags
/// exist for the buffer at all, null is returned.
/// </summary>
private TagSpanIntervalTree<TTag> TryGetTagIntervalTreeForBuffer(ITextBuffer buffer)
private TagSpanIntervalTree<TTag>? TryGetTagIntervalTreeForBuffer(ITextBuffer buffer)
{
this.AssertIsForeground();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ internal enum EditAndContinueCapabilities
/// <summary>
/// Creating a new type definition.
/// </summary>
NewTypeDefinition = 1 << 2
NewTypeDefinition = 1 << 4
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,15 @@ public async ValueTask StartDebuggingSessionAsync(Solution solution, IManagedEdi
SpecializedCollections.EmptyEnumerable<KeyValuePair<DocumentId, CommittedSolution.DocumentState>>();

var runtimeCapabilities = await debuggerService.GetCapabilitiesAsync(cancellationToken).ConfigureAwait(false);

var capabilities = ParseCapabilities(runtimeCapabilities);

// For now, runtimes aren't returning capabilities, we just fall back to a known set.
if (capabilities == EditAndContinueCapabilities.None)
{
capabilities = EditAndContinueCapabilities.Baseline | EditAndContinueCapabilities.AddMethodToExistingType | EditAndContinueCapabilities.AddStaticFieldToExistingType | EditAndContinueCapabilities.AddInstanceFieldToExistingType | EditAndContinueCapabilities.NewTypeDefinition;
}

var newSession = new DebuggingSession(solution, debuggerService, capabilities, _compilationOutputsProvider, initialDocumentStates, _debuggingSessionTelemetry, _editSessionTelemetry);
var previousSession = Interlocked.CompareExchange(ref _debuggingSession, newSession, null);
Contract.ThrowIfFalse(previousSession == null, "New debugging session can't be started until the existing one has ended.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ public Factory()
public CompileTimeSolutionProvider(Workspace workspace)
{
_workspace = workspace;
_enabled = workspace.Services.GetRequiredService<IExperimentationService>().IsExperimentEnabled(WellKnownExperimentNames.RazorLspEditorFeatureFlag);
// TODO:
//_enabled = workspace.Services.GetRequiredService<IExperimentationService>().IsExperimentEnabled(WellKnownExperimentNames.RazorLspEditorFeatureFlag);
_enabled = false;

workspace.WorkspaceChanged += (s, e) =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.EditorConfigSettings;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Host.Mef;
Expand Down Expand Up @@ -79,6 +81,13 @@ public int CreateEditorInstance(uint grfCreateDoc,
pgrfCDW = 0;
pbstrEditorCaption = null;

if (!_workspace.CurrentSolution.Projects.Any(p => p.Language == LanguageNames.CSharp || p.Language == LanguageNames.VisualBasic))
{
// If there are no VB or C# projects loaded in the solution (so an editorconfig file in a C++ project) then we want their
// editorfactory to present the file instead of use showing ours
return VSConstants.VS_E_UNSUPPORTEDFORMAT;
}

// Validate inputs
if ((grfCreateDoc & (VSConstants.CEF_OPENFILE | VSConstants.CEF_SILENT)) == 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
namespace Microsoft.VisualStudio.LanguageServices.EditAndContinue
{
[Shared]
[Export(typeof(IManagedEditAndContinueLanguageService))]
[Export(typeof(IManagedHotReloadLanguageService))]
[ExportMetadata("UIContext", Guids.EncCapableProjectExistsInWorkspaceUIContextString)]
internal sealed class ManagedHotReloadLanguageService : IManagedHotReloadLanguageService
{
Expand Down
Loading