Skip to content

Production code changes to aid with test stabilization#25558

Merged
sharwell merged 13 commits intodotnet:dev15.7.xfrom
sharwell:export-provider
Mar 23, 2018
Merged

Production code changes to aid with test stabilization#25558
sharwell merged 13 commits intodotnet:dev15.7.xfrom
sharwell:export-provider

Conversation

@sharwell
Copy link
Copy Markdown
Contributor

@sharwell sharwell commented Mar 17, 2018

This pull request contains the changes to production code resulting from a larger effort to stabilize flaky tests.

  • Move the listener/waiter test hooks to the workspaces layer
  • Cancel pending asynchronous operations when IdleProcessor stops
  • Extract interface ISerializer from Serializer
  • Convert ISerializer to workspace service ISerializerService
  • Add service creation hooks for HostServices implementations
  • Avoid possible MEF composition in Workspace.Dispose
  • Make AssetService.s_serializer a per-instance field
  • Make PrimaryWorkspace a MEF component instead of static
  • Make SolutionService.PrimaryWorkspace a per-instance property
  • Add the ability to hook RoslynServices.HostServices during testing
  • Place ITextBufferCloneService in ITextBuffer.Properties instead of separate tracking in SnapshotSourceText

Customer scenario

This is a change to improve the testability of our code. It is not intended to produce any user-visible behavior or performance changes.

Bugs this fixes

n/a (but supports fixing many flaky test issues)

Workarounds, if any

None

Risk

Relatively low. The risk here primarily lies in a few changes to internal APIs. Downstream consumers accessing PrimaryWorkspace, Serializer, or a couple Roslyn remoting types through IVT will need to update their code to avoid this path.

Performance impact

No expected performance impact in production.

Is this a regression from a previous update?

This is a developer/contributor regression. Our tests have become more sensitive to mutable data sharing across test boundaries as we adopt updated dependencies that impose stricter requirements for asynchronous code, increasing the chances that tests will fail in CI builds.

Root cause analysis

See previous.

How was the bug found?

CI test process dump analysis.

Test documentation updated?

No change to testing approaches results directly from this change.

@sharwell sharwell added the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Mar 17, 2018
@sharwell sharwell requested a review from a team as a code owner March 17, 2018 15:56
@sharwell sharwell changed the title [WIP] Production code changes to aid with test stabilization Production code changes to aid with test stabilization Mar 17, 2018
[assembly: TypeForwardedTo(typeof(Microsoft.CodeAnalysis.Shared.TestHooks.IAsynchronousOperationWaiter))]
[assembly: TypeForwardedTo(typeof(Microsoft.CodeAnalysis.Shared.TestHooks.IAsynchronousOperationListener))]
[assembly: TypeForwardedTo(typeof(Microsoft.CodeAnalysis.Shared.TestHooks.IAsyncToken))]
[assembly: TypeForwardedTo(typeof(Microsoft.CodeAnalysis.Shared.TestHooks.TaskExtensions))]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, why are these needed? for F#/TS/JS?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Considering the impact of other changes coming in this PR, I'm guessing these are not going to be necessary in the final revision. However, I decided to make the relocation separate from the removal of the original types.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have some tracking bug to track (eventually) getting rid of them?

Copy link
Copy Markdown
Contributor Author

@sharwell sharwell Mar 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change was intended to avoid the need to have WorkspacesTestUtilities reference Features. This is no longer avoidable, and WorkspacesTestUtilities ended up taking a reference all the way to RemoteWorkspaces. However, this change may still be beneficial as part of work to ensure all asynchronous operations started by Roslyn are tracked.

},
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would benefit from comments explaining what's going on here. A comment also explaining that this should run unilaterally, regardless of how AsyncProcessorTask completes might be good.

},
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate code. Can we we share with above?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be using LazyCancellation here? in other words, is it ok if this code runs before some antecedent tasks completes, but after the cancellation token controlling another intermediary tasks completes? In other words, should this be using the semantics of SafeContinueWith?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't LazyCancellation only have an effect on continuations that specify a CancellationToken?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so (but i'm not totally sure). I thought it was more about the antecedent tasks and if they used a cancellation token. in other words, if i have tasks:

A <- B <- C (i.e. B depends on A and C depends on B)

And 'A' is running, but B gets canceled. The question is: should 'C' run? LazyCancellation (to me) says: "No. All antecedent tasks are not completed. Even though B transitioned ot Canceled, C should not run yet because 'A' is still running".

This is regardless of the cancellation token passed to C.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephentoub For guidance.

Copy link
Copy Markdown
Contributor Author

@sharwell sharwell Mar 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 I looked at https://referencesource.microsoft.com and it seems to only impact cases where a cancellation token is involved.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CyrusNajmabadi is correct re "I thought it was more about the antecedent tasks and if they used a cancellation token." If you have:

Task a = ...;
Task b = a.ContinueWith(..., token);
Task c = b.ContinueWith(...);

and while a is running the token has cancellation requested, should c be allowed to run immediately or must it wait for a to finish.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephentoub I believe you may have misunderstood the context. In my code, I pass CancellationToken.None to ContinueWith. I am claiming that TaskContinuationOptions.LazyCancellation will never have an impact on a call to ContinueWith called in this manner.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't look at your code; I was commenting on the behavior of LazyCancellation and what it actually does.

Given the code:

Task a = ...;
Task b = a.ContinueWith(..., token);
Task c = b.ContinueWith(...);

c can end up running concurrently with a. To prevent that, you can make it:

Task a = ...;
Task b = a.ContinueWith(..., token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Default);
Task c = b.ContinueWith(...);

and then c will not run concurrently with a. If that token is None, then it doesn't matter because it won't be canceled prior to a completing (it could still be canceled by other means, e.g. if you passed TaskContinuationOptions.OnlyOnFaulted and the antecedent completed in another state, but in such cases the antecedent needs to be completed for that cancellation to happen).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is the case, can we comment that it's ok for us to not pass LazyCancellation here as it seems to only be relevant for the ContinueWith's that take cancellation tokens?

Thanks!


public Serializer(HostWorkspaceServices workspaceServices)
[Obsolete("This exported object must be obtained through the MEF export provider.", error: true)]
public SerializerService(HostWorkspaceServices workspaceServices)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cute. i like that. we should do that in a lot of places :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ #25560

[ExportWorkspaceServiceFactory(typeof(ISerializerService), layer: ServiceLayer.Default), Shared]
internal class SerializerServiceFactory : IWorkspaceServiceFactory
{
[Obsolete("This is the factory method for " + nameof(SerializerService) + ".", error: true)]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we have our own subclass for this attribute? it reads as if: "this is obsolete and hsould not be used. people should transition to something else". But, in reality, it just means: "it's only for use by mef. we want to keep it, but you should not reference it directly in your code."

Something like "MefConstructorAttribute : ObsoleteAttribute"?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ ObsoleteAttribute is sealed, but I'm considering creating a class that holds a const string for the message with a comment on that declaration.

Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nits.

{
private static readonly ReaderWriterLockSlim s_registryGate = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
private static Workspace s_primaryWorkspace;
private readonly ReaderWriterLockSlim s_registryGate = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s_registryGate [](start = 46, length = 14)

s_ prefix no longer needed as this is an instance variable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Fixed in 9c28f4a

private static readonly ReaderWriterLockSlim s_registryGate = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
private static Workspace s_primaryWorkspace;
private readonly ReaderWriterLockSlim s_registryGate = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
private Workspace s_primaryWorkspace;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s_primaryWorkspace [](start = 26, length = 18)

s_ prefix no longer needed as this is an instance variable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Fixed in 9c28f4a

private static bool s_infoBarReported = false;

private static void ShowInfoBar()
private static void ShowInfoBar(Workspace workspace)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we assert when this is null? The API is a no-op if this is null hence seems like a required paramter.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea. I'm not familiar with this code and was simply trying to preserve behavior in the absence of static state class PrimaryWorkspace.

return new MefV1HostServices(container);
}

internal static void HookServiceCreation(CreationHook hook)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal static void HookServiceCreation(CreationHook hook) [](start = 7, length = 60)

Should we assert that s_CreationHook is null? Lacking that seems like we will risk introducing bugs by silently overwriting the previous vaule.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ No. In the cleanup step for the test hook, the creation hook is replaced by a non-null hook that produces an informative exception/test failure in the event code attempts to create an ExportProvider after the test exits the isolation boundary.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For cases where the overwrite is inteended a force parameter could be employed.


In reply to: 175523407 [](ancestors = 175523407)

@sharwell
Copy link
Copy Markdown
Contributor Author

📝 @CyrusNajmabadi @jaredpar I'm going to apply code changes resulting from code review after I work with HeeJae to complete the final behavior step.

AsyncProcessorTask.ContinueWith(
_ =>
{
foreach (var (documentId, data) in _pendingWork)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documentId, [](start = 42, length = 11)

Consider using _ instead of documentId to make it clear it's not used.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Fixed in 9c28f4a

AsyncProcessorTask.ContinueWith(
_ =>
{
foreach (var (projectId, data) in _pendingWork)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

projectId [](start = 46, length = 9)

consider using _ instead of projecTId to make it clear it's not used.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Fixed in 9c28f4a

data.AsyncToken.Dispose();
}

_pendingWork.Clear();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_pendingWork.Clear(); [](start = 28, length = 21)

Why aren't the operations on _pendingWork guarded by the appropriate gate here?

Copy link
Copy Markdown
Contributor Author

@sharwell sharwell Mar 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Fixed in 9c28f4a

protected AbstractGraphProvider(
IGlyphService glyphService,
SVsServiceProvider serviceProvider,
CodeAnalysis.Workspace workspace,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeAnalysis.Workspace workspace, [](start = 11, length = 34)

A bit disturbing this parameter was provided before and simply ignored.


namespace Microsoft.CodeAnalysis
{
internal static class PrimaryWorkspace
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal static class PrimaryWorkspace [](start = 4, length = 38)

I support all removal of global mutable statics.

Copy link
Copy Markdown
Member

@jasonmalinowski jasonmalinowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hitting request changes because I'm worried about the PrimaryWorkspace change, and specifically that SourceTextContainers are now holding onto workspaces. It's often the case that the extension methods that pass "null" might be the first use of an ITextBuffer (or will be after any refactoring) and thus we'll end up disabling cloning for derived SourceTexts. If this causes a perf regression that blocks insertion that would be a problem. I suggested an alternative use which is still a mutable static but a more constrained mutable static that if only set in VisualStudioWorkspace or the like would mean we can mitigate that risk, until we get @olegtk to give us a proper API and remove the need entirely.

If we can confirm there isn't an RPS regression I'll happily pinch my nose and hit signoff.

I could also imagine the PrimaryWorkspace thing could break Visual Studio for Mac. Any breakage is good in that they should stop using just as we should stop using it, but heads up to @KirillOsenkov either way.

Massive thank you for breaking this up commit-by-commit. Was easy to follow and was pretty easy to guess where you were going.

[assembly: TypeForwardedTo(typeof(Microsoft.CodeAnalysis.Shared.TestHooks.IAsynchronousOperationWaiter))]
[assembly: TypeForwardedTo(typeof(Microsoft.CodeAnalysis.Shared.TestHooks.IAsynchronousOperationListener))]
[assembly: TypeForwardedTo(typeof(Microsoft.CodeAnalysis.Shared.TestHooks.IAsyncToken))]
[assembly: TypeForwardedTo(typeof(Microsoft.CodeAnalysis.Shared.TestHooks.TaskExtensions))]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have some tracking bug to track (eventually) getting rid of them?

{
internal delegate MefV1HostServices CreationHook(IEnumerable<Assembly> assemblies);

private static CreationHook s_CreationHook;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would like a comment that this is test-only. I can imagine people doing really terrible things with this thinking this is a "feature".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Added comments in 37a1d2c

internal static void HookServiceCreation(CreationHook hook)
{
s_CreationHook = hook;
s_defaultHost = null;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment why. I can guess, but I'm not necessarily the next person to touch this. 😄

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Added comments in 37a1d2c

{
internal delegate MefHostServices CreationHook(IEnumerable<Assembly> assemblies, bool requestingDefaultHost);

private static CreationHook s_CreationHook;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto: comment this is test only. Even better: name the field appropriately.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Added comments in 37a1d2c

{
public static SourceTextContainer AsTextContainer(this ITextBuffer buffer)
=> TextBufferContainer.From(buffer);
=> TextBufferContainer.From(workspace: null, buffer);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one worries me, since it's entirely likely the very first use of an ITextBuffer goes through this API (at least it is in my project system refactoring), which then means it's not going to get a workspace and never will. This may very well be causing a perf regression if the cloning stuff is necessary. Will probably have to ask for an RPS run then prior to this being merged unless we have an alternate solution, since taking an RPS regression now would cause codeflow to miss a few deadlines.

To be honest, it looks like this is all so we can call ITextBufferCloneService.Clone(ITextImage), which we could just have a static function that's Function<ITextImage, ITextBuffer> and we set that in VisualStudioWorkspace so it's OK for VS, and not set it in tests. Yes, statics are evil, but hey, at least instead of the static for PrimaryWorkspace now it's a single-use static that doesn't open pandora's box. Wishing I did that years ago now...

And that lives long enough until we pester @olegtk or somebody to give us a proper API here, because ITextImage.WithChanges() that returns an ITextImage would be both straightforward and also really useful.

Copy link
Copy Markdown
Contributor Author

@sharwell sharwell Mar 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you review commit 1653801 and let me know if the approach in that change is preferable? If so I will add it to this pull request.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Fixed in 4924d70

}

return null;
return _workspace?.Services.GetService<ITextBufferCloneService>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i woudl feel better if this service was simply passed in in the start, rather than having to hold onto the _workspace itself. is that doable?

Copy link
Copy Markdown
Contributor Author

@sharwell sharwell Mar 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ I replied to Jason's post regarding this with a proposed alternative. I'm waiting to hear back from reviewers.

@sharwell sharwell removed the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Mar 20, 2018
Copy link
Copy Markdown
Member

@jaredpar jaredpar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

@jaredpar jaredpar dismissed their stale review March 20, 2018 15:22

revoking review

@jaredpar
Copy link
Copy Markdown
Member

Sorry my review status is flipping. Was experimenting with CodeFlow features.


// check whether we can use text buffer factory
var factory = TextBufferFactory;
var factory = _textBufferCloneServiceOpt;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: now that that's readonly, we don't have to worry about capturing to a local which was previously required. (But hey, it's shorter than inlining, so...)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would likely change it (at least rename) if the code was more complex, but the method seems straightforward enough to keep.

@@ -82,8 +80,8 @@ public static SourceText From(Workspace workspace, ITextSnapshot editorSnapshot)
if (!s_textSnapshotMap.TryGetValue(editorSnapshot, out var snapshot))
{
// Avoid capturing `workspace` on the fast path
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: comment name needs updating.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update this in a commit in my follow-up pull request to avoid needing to rebuild everything again.


public static SourceText AsText(this ITextSnapshot textSnapshot)
=> SnapshotSourceText.From(workspace: null, textSnapshot);
=> SnapshotSourceText.From(textBufferCloneServiceOpt: null, textSnapshot);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this try fetching the service like TextBufferContainer does?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately ITextSnapshot doesn't expose any properties to try and fetch from.


public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
{
return _singleton;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_singleton seems a misnomer here: there's one you'll get through the factory, and one directly from the export below. This could just have the [ImportingConstructor] import the type below and return it, just making this an even thinner shim.

(If the only thing still using the workspace service is that inline rename thing, then just disregard this comment and we'll delete this then.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➡️ Covered as part of #25659

@sharwell
Copy link
Copy Markdown
Contributor Author

@Pilchie and/or @MattGertz for approval

@Pilchie
Copy link
Copy Markdown
Member

Pilchie commented Mar 22, 2018

Have we verified that TypeScript/F#/Xaml work with these changes? Do they have an impact on VS4Mac that we should worry about?

@sharwell
Copy link
Copy Markdown
Contributor Author

sharwell commented Mar 22, 2018

@Pilchie Not specifically, because I'm still not sure how to do that exactly. The listener-related items valuable in testing scenarios have type forwarders and shouldn't be a problem unless Workspaces needs some other IVT that Features already has. The other internal API changes were primarily used in remote workspace / OOP scenarios so it's unlikely to cause problems.

@Pilchie
Copy link
Copy Markdown
Member

Pilchie commented Mar 22, 2018

Tagging @minestarks @brettfo @mgoertz-msft - can you three take a look and chime in on whether you think this will impact your scenarios at insertion time?

@mgoertz-msft
Copy link
Copy Markdown
Contributor

@Pilchie Shouldn't affect the XAML language service as long as you don't change any of the interfaces in XamlVisualStudio.csproj. The only other concern would be if this were to affect CustomWorkspaces, which we do use in the VS codebase.

@brettfo
Copy link
Copy Markdown
Member

brettfo commented Mar 23, 2018

Looking through the changes I don't see anything that'll likely break F#, but if I could be emailed when we have a VAL build I'll run through some scenarios.

Copy link
Copy Markdown

@minestarks minestarks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No impact on TS that I can tell.

@Pilchie
Copy link
Copy Markdown
Member

Pilchie commented Mar 23, 2018

Approved - thanks for the diligence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants