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

Hook up the new remote-solution-events-stream to the UnitTest-SolutionCrawler. #64150

Conversation

CyrusNajmabadi
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi commented Sep 20, 2022

This PR contains the changes to the new unit-testing crawler to move it off from having direct Workspace dependencies (since we won't have a workspace in the future in OOP) and to hook it up to the new legacy-solution-events stream created in the prior PR. Relevant pieces are documented to look at.

@CyrusNajmabadi CyrusNajmabadi changed the base branch from main to features/solutionEvents September 20, 2022 20:21
#if false // Not used in unit testing crawling
Workspace workspace
#endif
);
Copy link
Member Author

Choose a reason for hiding this comment

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

IUnitTestingIncrementalAnalyzer? CreateIncrementalAnalyzer(
#if false // Not used in unit testing crawling
Workspace workspace
#endif
Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

This is also a general pattern i'm using in the fork. Instead of deleting, i'm IFDEF'ing out so we can see how this drifts from teh original.

Copy link
Member

@tmat tmat Sep 20, 2022

Choose a reason for hiding this comment

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

Wouldn't simple diff of the files show that? Perhaps we could keep the file names the same.

Copy link
Member Author

Choose a reason for hiding this comment

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

possibly... though i worry about the diffs getting too far apart (and things like naming confusing it). I'm flexible on this htough. if we prefer just deleting, that's also ok with me.

}

internal sealed class UnitTestingRegistration
{
public readonly int CorrelationId;
public readonly Workspace Workspace;
public readonly string WorkspaceKind;
public readonly SolutionServices Services;
Copy link
Member Author

Choose a reason for hiding this comment

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

the general idea here was to get us off of 'Workspace' and onto the constituent pieces that are needed instead. These pieces are possible today to get (obviously, since we still have workspaces), but they shoudl also be hopefully not a problem to get even as we heavily refactor oop and get rid of hte RemoteWorkspace type.

ProjectId? preferableProjectId,
#if false // Not used in unit testing crawling
ProjectDependencyGraph dependencyGraph,
IDiagnosticAnalyzerService? service,
Copy link
Member Author

Choose a reason for hiding this comment

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

the dependency graph and diagservice are used by solution-crawler to order what files to analyze, preferring files with diagnostics in them (so they can be removed quickly if fixed). Such a concept is irrelevant for unittest source-discovery. So this greatly simplifies things and prevents the need for workspace access to compute this data and pass it along.

Copy link
Contributor

Choose a reason for hiding this comment

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

If a change is made in one project, was the dependency graph being used to ensure that the files in this project are analyzed before other projects that depend on it?

Copy link
Member Author

Choose a reason for hiding this comment

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

@shyamnamboodiripad No, we would do this:

                        foreach (var dependingProjectId in dependencyGraph.GetProjectsThatDirectlyDependOnThisProject(projectId))
                        {
                            if (workQueue.ContainsKey(dependingProjectId) && analyzerService?.ContainsDiagnostics(Workspace, dependingProjectId) == true)
                            {
                                return dependingProjectId;
                            }
                        }

So it was only relevant if the projects actually contain diagnostics. if not, then the dependency graph had no effect.

@@ -157,8 +161,6 @@ public void Dispose()
RaiseCancellation_NoLock(cancellations);
}

protected Workspace Workspace => _workspace;
Copy link
Member Author

Choose a reason for hiding this comment

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

goal was to get rid of storage of the workspace (and exposing it like this). that way when this doesn't prevent us from removing RemoteWorkspace.

@@ -259,6 +273,7 @@ protected CancellationToken GetNewCancellationToken_NoLock(object key)
return projectId;
}

#if false // Not used in unit testing crawling
// prefer project that directly depends on the given project and has diagnostics as next project to
// process
Copy link
Member Author

Choose a reason for hiding this comment

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

irrelevant to unittesting solution crawling. source-discovery is unrelated to where diagnostics are.


_registration.Workspace.WorkspaceChanged += OnWorkspaceChanged;
_registration.Workspace.TextDocumentOpened += OnTextDocumentOpened;
_registration.Workspace.TextDocumentClosed += OnTextDocumentClosed;
Copy link
Member Author

Choose a reason for hiding this comment

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

instead of listening to events by hooking up to the workspace, we will instead get the events from teh new LegacySolutionEvents stream.

SolutionServices SolutionServices { get; }
/// <inheritdoc cref="Workspace.CurrentSolution"/>
Solution CurrentSolution { get; }
}
Copy link
Member Author

Choose a reason for hiding this comment

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

this is an abstraction that allows us to just get teh data we need from a workspace, without actually exposing the workspace itself.

Note that CurrentSolution is oogy as heck, but needed for SolutionCrawler (which commonly goes back to this). See the docs here though on why this is ok for this legacy/compat purpose: https://github.com/dotnet/roslyn/pull/64150/files#diff-3e98ede73fac6d34d191fb31d946bf9df7eca9d83b24fa662a1c4e8cd30c8e94R68

/// In other words, we are not keeping around the latest-primary-solution-snapshot to power UnitTesting
/// solution-crawling. We are keeping it around for perf around standard OOP snapshot requests, and this
/// component can appropriately leverage that.
/// </summary>
Copy link
Member Author

Choose a reason for hiding this comment

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

@tmat The above contains my thinking on why this direction is ok. This is jsut a super unfortunate aspect of the design of solution-crawler. However, it does feel like it's something we can support even as we move off of RemoteWorkspace in OOP.

Copy link
Member Author

Choose a reason for hiding this comment

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

The above does require is to effectively 'expose' that we are caching teh 'latest primary solution snapshot' in OOP (outside of hte syncing system). It's not ideal, but it's also hopefully very temporary esp. as we continue to push on unittesting to get off of solution-crawler (even their fork of it).

Copy link
Member

Choose a reason for hiding this comment

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

Couldn't solution crawler figure what the current solution is from the solution events? Every time in-proc workspace current solution is updated we send an event to OOP which has the snapshot, right?

Copy link
Member

Choose a reason for hiding this comment

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

I.e. the solution crawler would track what the current snapshot is instead of remote workspace.

Copy link
Member Author

Choose a reason for hiding this comment

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

Couldn't solution crawler figure what the current solution is from the solution events? Every time in-proc workspace current solution is updated we send an event to OOP which has the snapshot, right?

Maybe.................................

It does seem reasonable. And i think i will change to that in the next PR. Though it def makes me nervous that this will somehow be different due to some crazy aspect of SolutionCrawler taht we don't understand :D

I'm very torn on this work between trying to keep things as absolutely close to how SolutionCrawler works today, while also wanting to make judicious changes to keep things as unhacky as possible. This feels like it's on the fence. But worthwhile enough to do.

Copy link
Member Author

Choose a reason for hiding this comment

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

I.e. the solution crawler would track what the current snapshot is instead of remote workspace.

Yup. Understood. And i think taht is reasonable given that only the 'host' issues the stream of workspace events, and that happens in a serialized queue. So we always just reocrd the latest and have that be conceptually the same as the one the RemoteWorkspace is holding onto.

@CyrusNajmabadi CyrusNajmabadi marked this pull request as ready for review September 20, 2022 21:04
@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner September 20, 2022 21:04

namespace Microsoft.CodeAnalysis.LegacySolutionEvents
{
internal interface ILegacyWorkspaceDescriptor
Copy link
Member

Choose a reason for hiding this comment

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

ILegacyWorkspaceDescriptor

Maybe -Accessor would be better name?

Copy link
Member

Choose a reason for hiding this comment

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

Isn't WorkspaceKind available from Solution as well?

Copy link
Member

Choose a reason for hiding this comment

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

and SolutionServices also. so perhaps this just needs CurrentSolution?

Copy link
Member Author

Choose a reason for hiding this comment

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

WFM. Will rename in followup.

Copy link
Member Author

Choose a reason for hiding this comment

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

Isn't WorkspaceKind available from Solution as well?
and SolutionServices also. so perhaps this just needs CurrentSolution?

True! Ok, i can simplify this even further. Will do so in next PR :)

@CyrusNajmabadi CyrusNajmabadi merged commit d688362 into dotnet:features/solutionEvents Sep 20, 2022
@CyrusNajmabadi CyrusNajmabadi deleted the unitTestingRegistration branch September 20, 2022 22:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants