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

Don't crash in OOP with TS projects/documents #20435

Merged
merged 3 commits into from
Jun 30, 2017

Conversation

Pilchie
Copy link
Member

@Pilchie Pilchie commented Jun 23, 2017

Ask Mode

Customer scenario

Enable the option to perform analysis in an external process, and then either:

  1. search in solution explorer with a JS or TS file open in the editor.
  2. Put the caret on a C# identifier in a cshtml file that also contains a JS script block.

Bugs this fixes: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/454792 and https://devdiv.visualstudio.com/DevDiv/_workitems/edit/455588
Workarounds, if any: Disable the option to run these features out of process, but we'd really like to get feedback on the option to enable it by default later.
Risk: Low - just some checks specifically to prevent these cases, in the OOP specific codepaths.
Performance impact: Low - just some if checks.
Is this a regression from a previous update? Yes, if the OOP option is enabled.
Root cause analysis: Once again, we need to do more testing with JS/TS and razor scenarios.
How was the bug found? Divisional automated tests immediately after enabling the option for internal users, and internal dogfooders.

@Pilchie
Copy link
Member Author

Pilchie commented Jun 23, 2017

I recommend reviewing with ?w=1 for this one.

@@ -16,7 +16,8 @@ internal partial class CodeAnalysisService : IRemoteDocumentHighlights
{
var solution = await GetSolutionAsync().ConfigureAwait(false);
var document = solution.GetDocument(documentId);
var documentsToSearch = ImmutableHashSet.CreateRange(documentIdsToSearch.Select(solution.GetDocument));
var documentsToSearch = ImmutableHashSet.CreateRange(
Copy link
Contributor

Choose a reason for hiding this comment

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

removing this to let things crash might make bug more explicit. with this, we might not crash and didn't know that some document just silent failed to run HR. same for FAR.

Copy link
Member Author

Choose a reason for hiding this comment

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

Without this we definitely crash as soon as you edit a .cshtml file with js/ts code in it 😄

See my question in email about how to filter for highlight references.

Copy link
Member

Choose a reason for hiding this comment

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

Add comment explaining the scenario here.

Copy link
Member Author

Choose a reason for hiding this comment

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

#resolved

@heejaechang
Copy link
Contributor

👍

@Pilchie
Copy link
Member Author

Pilchie commented Jun 23, 2017

Actually - questions from people posted publicly here:

  1. Highlight references – should we filter on the VS side, the remote side, do the whole search on the VS side, do the non-remotable stuff on the VS side and then merge with the remotable stuff from the OOP side if there is any?
  2. Things that operate on the solution. We might get partial results, because only the projects that are supported OOP will return results. It looks like there is at least one “FindDeclarations” API that will fall into this bucket.

@heejaechang
Copy link
Contributor

All depends.

Not all language support OOP. So if a feature needs to run on 1 specfic language, then doing filtering on client side seems right.

If a feature needs to run on whole solution regardless of language, then the feature should run both and merge them.

  • heejae

@@ -67,7 +67,7 @@ protected AbstractAddImportFeatureService()

using (session)
{
if (session == null)
if (session == null || !RemoteSupportedLanguages.IsSupported(document.Project.Language))
Copy link
Member

Choose a reason for hiding this comment

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

How would this happen? AbstractAddImportFeatureService is only derived with C# and VB.

Copy link
Member

Choose a reason for hiding this comment

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

I would add a comment saying we're being paranoid here.

Copy link
Member Author

Choose a reason for hiding this comment

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

#resolved

@@ -31,6 +31,11 @@ internal abstract partial class AbstractNavigateToSearchService

private static Task<RemoteHostClient.Session> GetRemoteHostSessionAsync(Project project, CancellationToken cancellationToken)
{
if (!RemoteSupportedLanguages.IsSupported(project.Language))
Copy link
Member

Choose a reason for hiding this comment

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

How does this happen. AbstractNavitateToSearchService is only instantiated for C# and VB.

Copy link
Member

Choose a reason for hiding this comment

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

I would add a comment saying we are being paranoid here.

Copy link
Member Author

Choose a reason for hiding this comment

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

#resolved

@CyrusNajmabadi
Copy link
Member

I don't understand why this change is needed at all. Several of these services are C#/VB only. And so they should only be getting C#/VB documents. As such, i don't see why they'd have a problem with remoting things.

@Pilchie
Copy link
Member Author

Pilchie commented Jun 26, 2017

@CyrusNajmabadi It's quite possible not all of these are needed - I did a bunch of this via code inspection.

The two known instances so far are:

  1. A crash in highlight references in a cshtml file that contains both TS and C# - documentsToSearch ends up with nulls in it because it can't re-hydrate the IDs for the TS documents on the OOP side.
  2. A crash in solution explorer search in a solution that contains TS file - the projectId to search doesn't exist in the remote workspace.

Basically, I think we need to carefully audit, and hopefully provide some safety guarantees for the future about how to guard features that work OOP for C# and VB when they get mixed with languages that don't support OOP.

I'm definitely open to suggestions for better ways to do that.

@CyrusNajmabadi
Copy link
Member

Interesting. My primary concern here is that we are actually breaking functionality. i mean, take:

A crash in solution explorer search in a solution that contains TS file - the projectId to search doesn't exist in the remote workspace.

How was this working before?

--

My ideal would be that the remote workspace has all the project/documents/sourcetexts. It might be that it doesn't have all the services. But we would have had to be resilient to that before. Else, we would have crashed. And if the services are local, and not on the remote, then crashing indicates a degredation in functionality as those services used to work before we pushed things remotely.

@CyrusNajmabadi
Copy link
Member

So i'm ok with this. THough i would like the code to maybe be commented to explain things.

@@ -93,19 +93,22 @@ internal static partial class DeclarationFinder
private static async Task<(bool, ImmutableArray<SymbolAndProjectId>)> TryFindAllDeclarationsWithNormalQueryInRemoteProcessAsync(
Project project, SearchQuery query, SymbolFilter criteria, CancellationToken cancellationToken)
{
using (var session = await SymbolFinder.TryGetRemoteSessionAsync(
project.Solution, cancellationToken).ConfigureAwait(false))
if (RemoteSupportedLanguages.IsSupported(project.Language))
Copy link
Member

Choose a reason for hiding this comment

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

this check seems potentially appropriate. we should comment that this can be called through something like SolutionExplorer and that if this is not C#/VB that the search really can't happen at all (either on the host or remote side).

Copy link
Member Author

Choose a reason for hiding this comment

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

Strangely, nothing seems to protect against non-C#/VB projects in the in-proc case here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Looking further - this method seems to only be reachable by tests and public API. We don't use it anywhere, but if anyone else uses those public entry points with a TS/Xaml/F# project they will blow up :(

Copy link
Member Author

Choose a reason for hiding this comment

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

Going to debug again and figure out how this works when it's in-proc (since I verified that it did...)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yuck - it only works in the local process because Project.ContainsSymbolsWithNameAsync return false for TS projects before we happen to get a Compilation. We should probably move these checks higher up, and make it clearer that they don't work for TS/F#/Xaml in the API docs.

Copy link
Member Author

Choose a reason for hiding this comment

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

Filed #20573 to follow up on this more.

@@ -16,7 +16,8 @@ internal partial class CodeAnalysisService : IRemoteDocumentHighlights
{
var solution = await GetSolutionAsync().ConfigureAwait(false);
var document = solution.GetDocument(documentId);
var documentsToSearch = ImmutableHashSet.CreateRange(documentIdsToSearch.Select(solution.GetDocument));
var documentsToSearch = ImmutableHashSet.CreateRange(
documentIdsToSearch.Select(solution.GetDocument).Where(d => d != null));
Copy link
Member

Choose a reason for hiding this comment

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

Use .WhereNotNull();

Copy link
Member Author

Choose a reason for hiding this comment

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

#resolved

@@ -31,6 +31,7 @@ internal partial class CodeAnalysisService : IRemoteSymbolFinder
}

var documents = documentArgs?.Select(solution.GetDocument)
.Where(d => d != null)
Copy link
Member

Choose a reason for hiding this comment

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

WhereNotNull

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 couldn't find WhereNotNull, but maybe it was due to the diagnostic issue Jason was looking at. I'll try again.

Copy link
Member Author

Choose a reason for hiding this comment

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

#resolved

Copy link
Member

@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.

LGTM with some code comments.

@Pilchie Pilchie changed the base branch from master to dev15.3.x June 30, 2017 00:21
Copy link
Member

@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.

Thanks for the comments!

@Pilchie
Copy link
Member Author

Pilchie commented Jun 30, 2017

retest windows_debug_vs-integration_prtest please

@Pilchie
Copy link
Member Author

Pilchie commented Jun 30, 2017

retest windows_release_vs-integration_prtest please

@Pilchie
Copy link
Member Author

Pilchie commented Jun 30, 2017

Both failed with Vsixexpinstaller error.

@Pilchie
Copy link
Member Author

Pilchie commented Jun 30, 2017

Tagging @MattGertz for approval.

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.

5 participants