Extract the RDT implementation for Misc files and VS open file tracker#36006
Extract the RDT implementation for Misc files and VS open file tracker#36006dibarbet merged 15 commits intodotnet:masterfrom
Conversation
heejaechang
left a comment
There was a problem hiding this comment.
do we have test for these?
|
let me tag @jasonmalinowski as well. |
Per Jason, this would be exercised in the integration tests. We have unit tests for these since it uses VS services. |
jasonmalinowski
left a comment
There was a problem hiding this comment.
I believe the slice point needs to be somewhere else, since we don't want the RDT interactions being redone by other teams since it's really tricky.
There was a problem hiding this comment.
Is the expectation that other derives outside of Roslyn will use this? My worry is whether we're best off making these private and expect the derived type to re-query if it needs them; otherwise we're exposing more here than we may want.
There was a problem hiding this comment.
My expectation would have been that all of this still lives in the base. The only bit that would be in the derived methods would be the stuff that starts on if (w.CurrentSolution.ContainsDocument(…)) stuff, where the input to the function is a DocumentId and the SourceTextContainer.
This is of course tricky because of the locking semantics, so you might have to have two methods that are implemented by derivers
void ApplyWorkspaceChangeUnderLock(Action<Workspace> w);
which just forwards to the VS workspace one that acquires the lock, and then:
void ApplyDocumentOpen(DocumentId, SourceTextContainer)
There was a problem hiding this comment.
(referring to the earlier comment) -- start what is the derived behavior here -- keep the rest still in the base.
There was a problem hiding this comment.
| public sealed class VisualStudioOpenFileTracker : AbstractOpenFileTracker<VisualStudioWorkspaceImpl> | |
| public sealed class VisualStudioWorkspaceOpenFileTracker : AbstractOpenFileTracker<VisualStudioWorkspaceImpl> |
The reason being that sometimes we use "VisualStudioBlah" to generally mean an implementation that's used for all workspace implementations running in VS; this isn't quite the same.
|
Going to update this review, per Jason - |
f2e06bd to
f8cf872
Compare
f8cf872 to
3ab2ce9
Compare
src/VisualStudio/Core/Def/Implementation/ProjectSystem/MiscellaneousFilesWorkspace.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/MiscellaneousFilesWorkspace.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/MiscellaneousFilesWorkspace.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/MiscellaneousFilesWorkspace.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/RunningDocumentTableEventSink.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/RunningDocumentTableEventSink.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/RunningDocumentTableEventSink.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/RunningDocumentTableEventSink.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/RunningDocumentTableEventSink.cs
Outdated
Show resolved
Hide resolved
...ualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.OpenFileTracker.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/TestUtilities2/CodeModel/Mocks/MockEditorAdaptersFactoryService.vb
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/RunningDocumentTableEventTracker.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/RunningDocumentTableEventTracker.cs
Outdated
Show resolved
Hide resolved
...ualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.OpenFileTracker.cs
Outdated
Show resolved
Hide resolved
...ualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.OpenFileTracker.cs
Outdated
Show resolved
Hide resolved
jasonmalinowski
left a comment
There was a problem hiding this comment.
This is on the right track but I feel like the RDT abstraction is still leaking quite a bit of RDT specifics that are worth abstracting. The "abstracted" interface to me seems too like it should be a bit simpler and just have open/close/rename/context changed. You're having clients sometimes handle one kind of open but not another, and that looks suspicious to me. It might have been what the code was doing before, but that might have been a bug.
src/VisualStudio/Core/Def/Implementation/ProjectSystem/IRunningDocumentTableEventListener.cs
Outdated
Show resolved
Hide resolved
| /// Defines the methods that get called by the <see cref="RunningDocumentTableEventTracker"/> | ||
| /// for getting notified about running document table events. | ||
| /// </summary> | ||
| internal interface IRunningDocumentTableEventListener |
There was a problem hiding this comment.
Why an interface over just events? It seems neither client needed to use all of the methods, and this pattern doesn't scale well if we ever need to add another one. That the RDT events themselves are done via interfaces is just because events hadn't been invented back then.*
(* Well, yes, COM can do events too, but let's not talk about such things in polite company.)
There was a problem hiding this comment.
I see now @tmat wanted it this way, and his argument is persuasive given what he commented on. I suspect part of the problem though was there were more events than necessary, and I guess I'm not a particularly strong believer in EventArgs being a useful pattern, so maybe that would have helped. :-)
There was a problem hiding this comment.
My experience with C# eventing is a little limited - what is the alternative to event args?
There was a problem hiding this comment.
You can be lazy and just not do the pattern. Just have delegate types that have the parameters you want.
src/VisualStudio/Core/Def/Implementation/ProjectSystem/IRunningDocumentTableEventListener.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/RunningDocumentTableEventTracker.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/RunningDocumentTableEventTracker.cs
Outdated
Show resolved
Hide resolved
| @@ -47,7 +49,6 @@ internal sealed partial class MiscellaneousFilesWorkspace : Workspace, IVsRunnin | |||
| private readonly Dictionary<uint, (ProjectId projectId, SourceTextContainer textContainer)> _docCookiesToProjectIdAndContainer = new Dictionary<uint, (ProjectId, SourceTextContainer)>(); | |||
There was a problem hiding this comment.
I must admit: I'm curious what this would look like if we replaced this dictionary operating on cookies with file names. Would this then let us toss all the cookie passing in common helper? That'd be great then when we replace this with an editor API that wouldn't be talking about cookies anyways.
There was a problem hiding this comment.
And maybe this isn't a strict requirement now, but if you squint a bit you could imagine this isn't a RunningDocumentTableEventsTracker, but just an generic abstraction over "give me the open files and let me know when that changes" -- we might be able to get rid of cookies entirely. That might be handy if we want to use the misc files workspace somewhere else since once this isn't touching the RDT directly it's pretty light on other VS tie-ins.
src/VisualStudio/Core/Def/Implementation/ProjectSystem/MiscellaneousFilesWorkspace.cs
Outdated
Show resolved
Hide resolved
...ualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspaceImpl.OpenFileTracker.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/MiscellaneousFilesWorkspace.cs
Outdated
Show resolved
Hide resolved
src/VisualStudio/Core/Def/Implementation/ProjectSystem/MiscellaneousFilesWorkspace.cs
Outdated
Show resolved
Hide resolved
Thanks for the review :)
Does that sound OK @jasonmalinowski ? |
|
Sounds good. I think the tricky bit in it's current state is the attempt to preserve behavior perhaps makes it look more confusing and more "wrong" than if we tried to clean things up a bit. I wonder if some of the differences you're trying to preserve are either bugs or oversights -- in either case looking at it in a fresh light makes it look even stranger. |
@jasonmalinowski
This should be a bit less leaky I hope. |
jasonmalinowski
left a comment
There was a problem hiding this comment.
Nice -- the Enumerate* methods still seem a bit odd to me in that they're not IEnumerable and also it feels like we can decompose them a bit better. But I wouldn't consider that blocking if you have other work piled up behind this if you want to get things going in parallel.
| _textManager = (IVsTextManager)serviceProvider.GetService(typeof(SVsTextManager)); | ||
|
|
||
| ((IVsRunningDocumentTable)_runningDocumentTable).AdviseRunningDocTableEvents(this, out _runningDocumentTableEventsCookie); | ||
| var runningDocumentTable = (IVsRunningDocumentTable4)serviceProvider.GetService(typeof(SVsRunningDocumentTable)); |
There was a problem hiding this comment.
Feels a bit strange we explicitly cast this to IVsRunningDocumentTable4 -- let the helper just take the base one and it can cast it to whatever versions it needs.
| _foregroundAffinitization.AssertIsForeground(); | ||
| if (_runningDocumentTable.IsDocumentInitialized(docCookie) && TryGetBuffer(docCookie, out var buffer)) | ||
| { | ||
| _listener.OnRenameDocument(pszMkDocumentNew, pszMkDocumentOld, buffer); |
There was a problem hiding this comment.
Nitpick: use named arguments for passing the pszMkDocumentOld/New, so there's no chance these are flipped.
| return VSConstants.E_NOTIMPL; | ||
| } | ||
|
|
||
| public bool IsMonikerValid(string fileName) => _runningDocumentTable.IsMonikerValid(fileName); |
There was a problem hiding this comment.
From the API perspective should this be called IsFileOpen?
| textBuffer = null; | ||
|
|
||
| // The cast from dynamic to object doesn't change semantics, but avoids loading the dynamic binder | ||
| // which saves us JIT time in this method. |
There was a problem hiding this comment.
Not just JIT time in this method -- avoids an entire assembly load.
| /// Applies an action to all initialized files in the RDT. | ||
| /// </summary> | ||
| /// <param name="enumerateAction">the action to apply.</param> | ||
| public void EnumerateDocumentSet(Action<string, ITextBuffer, IVsHierarchy> enumerateAction) |
There was a problem hiding this comment.
Any resaon this isn't return an IEnumerable? IEnumerable of tuple here seems most appropriate.
There was a problem hiding this comment.
(also means the enumeration is abortable...)
There was a problem hiding this comment.
Or why can't a caller just enumerate just the file names, and they can call TryGetBufferFromMoniker themselves?
There was a problem hiding this comment.
The reason I did it this way was to avoid having to return all three pieces of data. But an IEnumerable of tuple seems like a reasonable way to do it. Will update.
| /// </summary> | ||
| /// <param name="enumerateAction">the action to apply.</param> | ||
| /// <param name="fileSet">the file set to apply the action to.</param> | ||
| public void EnumerateSpecifiedDocumentSet(Action<string, ITextBuffer, IVsHierarchy> enumerateAction, IEnumerable<string> fileSet) |
There was a problem hiding this comment.
Couldn't a caller just do this via the APIs you already have?
|
|
||
| private void ConnectToRunningDocumentTable() | ||
| /// <summary> | ||
| /// The VS open file tracker handles renames through <see cref="QueueCheckForFilesBeingOpen"/> |
There was a problem hiding this comment.
Not sure comment makes sense here: might be better to say "when a file is renamed, the old document is removed and new document added by the workspace". QueueCheckForFilesBeingOpen isn't really "handing" the rename per se, it's just the helper.
|
@jasonmalinowski thanks for the review! I've addressed the comments since the CI was stuck not reporting the status anyway. Once the tests pass I'll go ahead and merge unless you have any other concerns. |
Extract the RDT implementation for Misc files and VS open file tracker
Extract the RDT implementation for Misc files and VS open file tracker
Extract the RDT implementation for Misc files and VS open file tracker
Liveshare implements their own roslyn remote workspace which tracks files using a different system. Now that we're moving it inside, we want to re-use the already created interactions with the RDT wherever possible.
This PR just extracts out the common pieces into an event system where subscribers can get notified of specific RDT events.
@jasonmalinowski @heejaechang does this look roughly like we discussed?