Skip to content

Commit f956e66

Browse files
authored
Port cold start fixes to 17.9 P1 (#9529)
* Whitespace Just a couple of error list issues * Null enable project snapshot manager * Prevent a missing project from bringing down the language server * Don't use the fallback manager if we know about real info now * Allow documents to be found in the misc files project This is a regression from pre-multi-targeting. I incorrectly assumed that if we got project context info, it must mean the project was known, but that isn't true at start up necessarily. * Use a null namespace, don't hardcode the default This felt wrong, but I doubt it meaningfully changes things. * Rename action class to match the rest (and fix typo) * Thank you Visual Studio for not telling me about these possible null references, I was not mentally prepared to handle them.
1 parent d98785e commit f956e66

File tree

11 files changed

+42
-24
lines changed

11 files changed

+42
-24
lines changed

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultDocumentContextFactory.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Diagnostics.CodeAnalysis;
77
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
88
using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem;
9+
using Microsoft.AspNetCore.Razor.Utilities;
910
using Microsoft.CodeAnalysis.Razor;
1011
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
1112
using Microsoft.CodeAnalysis.Razor.Workspaces;
@@ -100,12 +101,24 @@ private bool TryResolveDocument(string filePath, VSProjectContext? projectContex
100101
}
101102

102103
var project = _projectSnapshotManagerAccessor.Instance.GetLoadedProject(projectContext.ToProjectKey());
103-
if (project.GetDocument(filePath) is { } document)
104+
if (project?.GetDocument(filePath) is { } document)
104105
{
105106
documentSnapshot = document;
106107
return true;
107108
}
108109

110+
// Couldn't find the document in a real project. Maybe the language server doesn't yet know about the project
111+
// that the IDE is asking us about. In that case, we might have the document in our misc files project, and we'll
112+
// move it to the real project when/if we find out about it.
113+
var miscellaneousProject = _snapshotResolver.GetMiscellaneousProject();
114+
var normalizedDocumentPath = FilePathNormalizer.Normalize(filePath);
115+
if (miscellaneousProject.GetDocument(normalizedDocumentPath) is { } miscDocument)
116+
{
117+
_logger.LogDebug("Found document {document} in the misc files project, but was asked for project context {context}", filePath, projectContext);
118+
documentSnapshot = miscDocument;
119+
return true;
120+
}
121+
109122
documentSnapshot = null;
110123
return false;
111124
}

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/CSharpFormattingPassBase.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ bool IsSingleLineExplicitExpression()
526526
{
527527
return true;
528528
}
529+
529530
return owner.AncestorsAndSelf().Any(n => n is CSharpImplicitExpressionSyntax);
530531
}
531532

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/OpenDocumentGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ private void ProjectSnapshotManager_Changed(object? sender, ProjectChangeEventAr
164164

165165
void TryEnqueue(IDocumentSnapshot document)
166166
{
167-
if (!ProjectManager.IsDocumentOpen(document.FilePath) && !_languageServerFeatureOptions.UpdateBuffersForClosedDocuments)
167+
if (!ProjectManager.IsDocumentOpen(document.FilePath.AssumeNotNull()) && !_languageServerFeatureOptions.UpdateBuffersForClosedDocuments)
168168
{
169169
return;
170170
}

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/DefaultRazorProjectService.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ public override void UpdateProject(
270270
{
271271
_projectSnapshotManagerDispatcher.AssertDispatcherThread();
272272

273-
var project = (ProjectSnapshot)_projectSnapshotManagerAccessor.Instance.GetLoadedProject(projectKey);
273+
var project = (ProjectSnapshot?)_projectSnapshotManagerAccessor.Instance.GetLoadedProject(projectKey);
274274

275275
if (project is null)
276276
{
@@ -323,7 +323,7 @@ private void UpdateProjectDocuments(ImmutableArray<DocumentSnapshotHandle> docum
323323
{
324324
_logger.LogDebug("UpdateProjectDocuments for {projectKey} with {documentCount} documents.", projectKey, documents.Length);
325325

326-
var project = (ProjectSnapshot)_projectSnapshotManagerAccessor.Instance.GetLoadedProject(projectKey);
326+
var project = (ProjectSnapshot)_projectSnapshotManagerAccessor.Instance.GetLoadedProject(projectKey).AssumeNotNull();
327327
var currentHostProject = project.HostProject;
328328
var projectDirectory = FilePathNormalizer.GetNormalizedDirectoryName(project.FilePath);
329329
var documentMap = documents.ToDictionary(document => EnsureFullPath(document.FilePath, projectDirectory), FilePathComparer.Instance);
@@ -343,7 +343,7 @@ private void UpdateProjectDocuments(ImmutableArray<DocumentSnapshotHandle> docum
343343
MoveDocument(documentFilePath, project, miscellaneousProject);
344344
}
345345

346-
project = (ProjectSnapshot)_projectSnapshotManagerAccessor.Instance.GetLoadedProject(projectKey);
346+
project = (ProjectSnapshot)_projectSnapshotManagerAccessor.Instance.GetLoadedProject(projectKey).AssumeNotNull();
347347

348348
// Update existing documents
349349
foreach (var documentFilePath in project.DocumentFilePaths)
@@ -379,7 +379,7 @@ private void UpdateProjectDocuments(ImmutableArray<DocumentSnapshotHandle> docum
379379
_projectSnapshotManagerAccessor.Instance.DocumentAdded(currentHostProject.Key, newHostDocument, remoteTextLoader);
380380
}
381381

382-
project = (ProjectSnapshot)_projectSnapshotManagerAccessor.Instance.GetLoadedProject(project.Key);
382+
project = (ProjectSnapshot)_projectSnapshotManagerAccessor.Instance.GetLoadedProject(project.Key).AssumeNotNull();
383383
miscellaneousProject = (ProjectSnapshot)_snapshotResolver.GetMiscellaneousProject();
384384

385385
// Add (or migrate from misc) any new documents

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/SnapshotResolver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public IProjectSnapshot GetMiscellaneousProject()
6464
if (miscellaneousProject is null)
6565
{
6666
_projectSnapshotManagerAccessor.Instance.ProjectAdded(MiscellaneousHostProject);
67-
miscellaneousProject = _projectSnapshotManagerAccessor.Instance.GetLoadedProject(MiscellaneousHostProject.Key);
67+
miscellaneousProject = _projectSnapshotManagerAccessor.Instance.GetLoadedProject(MiscellaneousHostProject.Key).AssumeNotNull();
6868
}
6969

7070
return miscellaneousProject;

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManager.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public DefaultProjectSnapshotManager(
5757
}
5858
}
5959

60-
foreach (var trigger in triggers)
60+
foreach (var trigger in triggers)
6161
{
6262
if (trigger is not IPriorityProjectSnapshotChangeTrigger)
6363
{
@@ -310,7 +310,7 @@ internal override void ProjectWorkspaceStateChanged(ProjectKey projectKey, Proje
310310
if (TryChangeEntry_UsesLock(
311311
projectKey,
312312
documentFilePath: null,
313-
new ProjectWorkspaceStateChanged(projectWorkspaceState),
313+
new ProjectWorkspaceStateChangedAction(projectWorkspaceState),
314314
out var oldSnapshot,
315315
out var newSnapshot))
316316
{
@@ -590,8 +590,8 @@ private bool TryChangeEntry_UsesLock(
590590
case ProjectRemovedAction:
591591
return null;
592592

593-
case ProjectWorkspaceStateChanged worskapceStateChangedAction:
594-
return new Entry(originalEntry.State.WithProjectWorkspaceState(worskapceStateChangedAction.WorkspaceState));
593+
case ProjectWorkspaceStateChangedAction workspaceStateChangedAction:
594+
return new Entry(originalEntry.State.WithProjectWorkspaceState(workspaceStateChangedAction.WorkspaceState));
595595

596596
case HostProjectUpdatedAction hostProjectUpdatedAction:
597597
return new Entry(originalEntry.State.WithHostProject(hostProjectUpdatedAction.HostProject));

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/FallbackHostProject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem;
77

88
internal class FallbackHostProject : HostProject
99
{
10-
public FallbackHostProject(string projectFilePath, string intermediateOutputPath, RazorConfiguration razorConfiguration, string rootNamespace, string displayName)
10+
public FallbackHostProject(string projectFilePath, string intermediateOutputPath, RazorConfiguration razorConfiguration, string? rootNamespace, string displayName)
1111
: base(projectFilePath, intermediateOutputPath, razorConfiguration, rootNamespace, displayName)
1212
{
1313
}

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/FallbackProjectManager.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,19 @@ public FallbackProjectManager(
3737

3838
internal void DynamicFileAdded(ProjectId projectId, ProjectKey razorProjectKey, string projectFilePath, string filePath)
3939
{
40+
var project = _projectSnapshotManagerAccessor.Instance.GetLoadedProject(razorProjectKey);
4041
if (_fallbackProjectIds.Contains(projectId))
4142
{
42-
// If this is a fallback project, then Roslyn may not track documents in the project, so these dynamic file notifications
43-
// are the only way to know about files in the project.
44-
AddFallbackDocument(razorProjectKey, filePath, projectFilePath);
43+
// The project might have started as a fallback project, but it might have been upgraded by our getting CPS info
44+
// about it. In that case, leave the CPS bits to do the work
45+
if (project is ProjectSnapshot { HostProject: FallbackHostProject })
46+
{
47+
// If this is a fallback project, then Roslyn may not track documents in the project, so these dynamic file notifications
48+
// are the only way to know about files in the project.
49+
AddFallbackDocument(razorProjectKey, filePath, projectFilePath);
50+
}
4551
}
46-
else if (_projectSnapshotManagerAccessor.Instance.GetLoadedProject(razorProjectKey) is null)
52+
else if (project is null)
4753
{
4854
// We have been asked to provide dynamic file info, which means there is a .razor or .cshtml file in the project
4955
// but for some reason our project system doesn't know about the project. In these cases (often when people don't
@@ -81,7 +87,7 @@ private void AddFallbackProject(ProjectId projectId, string filePath)
8187
return;
8288
}
8389

84-
var rootNamespace = project.DefaultNamespace ?? "ASP";
90+
var rootNamespace = project.DefaultNamespace;
8591

8692
// We create this as a fallback project so that other parts of the system can reason about them - eg we don't do code
8793
// generation for closed files for documents in these projects. If these projects become "real", either because capabilities

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectSnapshotManager.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT license. See License.txt in the project root for license information.
33

4-
#nullable disable
5-
64
using System;
75
using System.Collections.Immutable;
86
using Microsoft.CodeAnalysis.Host;
@@ -17,7 +15,7 @@ internal abstract class ProjectSnapshotManager : ILanguageService
1715

1816
public abstract bool IsDocumentOpen(string documentFilePath);
1917

20-
public abstract IProjectSnapshot GetLoadedProject(ProjectKey projectKey);
18+
public abstract IProjectSnapshot? GetLoadedProject(ProjectKey projectKey);
2119

2220
public abstract ImmutableArray<ProjectKey> GetAllProjectKeys(string projectFileName);
2321
}

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/UpdateProjectAction.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,4 @@ internal record ProjectRemovedAction(ProjectKey ProjectKey) : IUpdateProjectActi
3333

3434
internal record HostProjectUpdatedAction(HostProject HostProject) : IUpdateProjectAction;
3535

36-
internal record ProjectWorkspaceStateChanged(ProjectWorkspaceState WorkspaceState) : IUpdateProjectAction;
36+
internal record ProjectWorkspaceStateChangedAction(ProjectWorkspaceState WorkspaceState) : IUpdateProjectAction;

0 commit comments

Comments
 (0)