Skip to content

Commit

Permalink
Serialize project state from VS to project.razor.json (#1711)
Browse files Browse the repository at this point in the history
Serialize project state to project.razor.json
  • Loading branch information
ryanbrandenburg authored Mar 31, 2020
1 parent bc15615 commit fef50ba
Show file tree
Hide file tree
Showing 54 changed files with 826 additions and 192 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Serialization;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
using Newtonsoft.Json;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text;
using BenchmarkDotNet.Attributes;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.Razor.Serialization;
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
using Newtonsoft.Json;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Razor.Workspaces.Serialization;
using Newtonsoft.Json;

namespace Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,17 @@ private class DefaultJsonFileDeserializer : JsonFileDeserializer
{
public override TValue Deserialize<TValue>(string filePath) where TValue : class
{
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
using (var reader = new StreamReader(stream))
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
using var reader = new StreamReader(stream);
try
{
try
{
var deserializedValue = (TValue)Serializer.Instance.JsonSerializer.Deserialize(reader, typeof(TValue));
return deserializedValue;
}
catch
{
// Swallow deserialization exceptions. There's many reasons they can happen, all out of our control.
return null;
}
var deserializedValue = (TValue)Serializer.Instance.JsonSerializer.Deserialize(reader, typeof(TValue));
return deserializedValue;
}
catch
{
// Swallow deserialization exceptions. There's many reasons they can happen, all out of our control.
return null;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ await Task.Factory.StartNew(() =>

// Start listening for file changes. If a project configuration file changes in any way we'll notify listeners.

_watcher = new FileSystemWatcher(workspaceDirectory, LanguageServerConstants.ProjectConfigurationFile)
// If we don't trim workspaceDirectory before passing it to FileSystemWatcher then when it eventually finds
// the file it reports the path as something like C:\some\dir\/deeper/dir/project.razor.json, while we'll be
// comparing it against C:\some\dir/deeper/dir/project.razor.json, and they won't match due to the extra \.
_watcher = new FileSystemWatcher(workspaceDirectory.TrimEnd('/','\\'), LanguageServerConstants.ProjectConfigurationFile)
{
NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.CreationTime,
IncludeSubdirectories = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@

using System;
using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization;
using Microsoft.CodeAnalysis.Razor.Workspaces.Serialization;

namespace Microsoft.AspNetCore.Razor.LanguageServer
{
internal class ProjectConfigurationFileChangeEventArgs
{
private readonly JsonFileDeserializer _jsonFileDeserializer;
private FullProjectSnapshotHandle _projectSnapshotHandle;
private object _projectSnapshotHandleLock;
private readonly object _projectSnapshotHandleLock;
private bool _deserialized;

public ProjectConfigurationFileChangeEventArgs(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization;
using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Workspaces.Serialization;

namespace Microsoft.AspNetCore.Razor.LanguageServer
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Workspaces.Serialization;
using Microsoft.CodeAnalysis.Text;
using Microsoft.Extensions.Logging;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@

using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Workspaces.Serialization;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,8 @@ protected virtual void DeleteFile(string publishFilePath)
protected virtual void SerializeToFile(OmniSharpProjectSnapshot projectSnapshot, string publishFilePath)
{
var fileInfo = new FileInfo(publishFilePath);
using (var writer = fileInfo.CreateText())
{
_serializer.Serialize(writer, projectSnapshot);
}
using var writer = fileInfo.CreateText();
_serializer.Serialize(writer, projectSnapshot);
}

// Internal for testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.Serialization;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
using Newtonsoft.Json;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Language.Components;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.Serialization;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.VisualStudio.LanguageServices.Razor.Serialization;
using Newtonsoft.Json;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Microsoft.VisualStudio.LanguageServices.Razor\Serialization\TagHelperDescriptorJsonConverter.cs">
<Compile Include="..\Microsoft.CodeAnalysis.Razor.Workspaces\Serialization\TagHelperDescriptorJsonConverter.cs">
<Link>Shared\TagHelperDescriptorJsonConverter.cs</Link>
</Compile>
<Compile Include="..\Microsoft.VisualStudio.LanguageServices.Razor\Serialization\RazorDiagnosticJsonConverter.cs">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ export class ProposedApisFeature {
private logger: RazorLogger,
) {
}

public async register(vscodeType: typeof vscodeapi, localRegistrations: vscode.Disposable[]) {
const legend = await this.languageServiceClient.getSemanticTokenLegend();
const semanticTokenProvider = new RazorDocumentSemanticTokensProvider(this.documentSynchronizer, this.documentManager, this.languageServiceClient, this.logger);
if (legend) {
localRegistrations.push(vscodeType.languages.registerDocumentSemanticTokensProvider(RazorLanguage.id, semanticTokenProvider, legend));
if (vscodeType.env.appName.endsWith('Insiders')) {
const legend = await this.languageServiceClient.getSemanticTokenLegend();
const semanticTokenProvider = new RazorDocumentSemanticTokensProvider(this.documentSynchronizer, this.documentManager, this.languageServiceClient, this.logger);
if (legend) {
localRegistrations.push(vscodeType.languages.registerDocumentSemanticTokensProvider(RazorLanguage.id, semanticTokenProvider, legend));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(Tooling_MicrosoftCodeAnalysisCSharpPackageVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="$(Tooling_MicrosoftCodeAnalysisWorkspacesCommonPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.NonCapturingTimer.Sources" Version="$(MicrosoftExtensionsNonCapturingTimerSourcesPackageVersion)" PrivateAssets="all" />
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
<PackageReference Include="System.Private.Uri" Version="$(SystemPrivateUriPackageVersion)" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.AspNetCore.Razor.LanguageServer.Common
namespace Microsoft.CodeAnalysis.Razor.Workspaces
{
internal static class ProjectSerializationFormat
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal class DefaultProjectSnapshot : ProjectSnapshot
{
private readonly object _lock;

private Dictionary<string, DefaultDocumentSnapshot> _documents;
private readonly Dictionary<string, DefaultDocumentSnapshot> _documents;

public DefaultProjectSnapshot(ProjectState state)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,11 +506,7 @@ protected virtual void NotifyListeners(ProjectChangeEventArgs e)
{
_foregroundDispatcher.AssertForegroundThread();

var handler = Changed;
if (handler != null)
{
handler(this, e);
}
Changed?.Invoke(this, e);
}

private class Entry
Expand All @@ -525,7 +521,7 @@ public Entry(ProjectState state)

public ProjectSnapshot GetSnapshot()
{
return SnapshotUnsafe ?? (SnapshotUnsafe = new DefaultProjectSnapshot(State));
return SnapshotUnsafe ??= new DefaultProjectSnapshot(State);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.Host;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,8 @@ public ProjectChangeEventArgs(ProjectSnapshot older, ProjectSnapshot newer, stri
public string DocumentFilePath { get; }

public ProjectChangeKind Kind { get; }

public static ProjectChangeEventArgs CreateTestInstance(ProjectSnapshot older, ProjectSnapshot newer, string documentFilePath, ProjectChangeKind kind) =>
new ProjectChangeEventArgs(older, newer, documentFilePath, kind);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Concurrent;

namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
{
internal abstract class RazorProjectChangePublisher : ProjectSnapshotChangeTrigger
{
protected ConcurrentDictionary<string, string> PublishFilePathMappings { get; } = new ConcurrentDictionary<string, string>(FilePathComparer.Instance);

public abstract void SetPublishFilePath(string projectFilePath, string publishFilePath);

public abstract void RemovePublishFilePath(string projectFilePath);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System;

namespace Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization
namespace Microsoft.CodeAnalysis.Razor.Workspaces.Serialization
{
internal sealed class DocumentSnapshotHandle
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;

namespace Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization
namespace Microsoft.CodeAnalysis.Razor.Workspaces.Serialization
{
// FullProjectSnapshotHandle exists in order to allow ProjectSnapshots to be serialized and then deserialized.
// It has named "Full" because there's a similar concept in core Razor of a ProjectSnapshotHandle. In Razor's
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization
namespace Microsoft.CodeAnalysis.Razor.Workspaces.Serialization
{
internal class FullProjectSnapshotHandleJsonConverter : JsonConverter
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Newtonsoft.Json;

namespace Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization
namespace Microsoft.CodeAnalysis.Razor.Workspaces.Serialization
{
internal class ProjectSnapshotJsonConverter : JsonConverter
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Microsoft.VisualStudio.LanguageServices.Razor.Serialization
namespace Microsoft.CodeAnalysis.Razor.Serialization
{
internal class RazorConfigurationJsonConverter : JsonConverter
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Microsoft.VisualStudio.LanguageServices.Razor.Serialization
namespace Microsoft.CodeAnalysis.Razor.Serialization
{
internal class TagHelperDescriptorJsonConverter : JsonConverter
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal class DefaultLSPEditorFeatureDetector : LSPEditorFeatureDetector
private static readonly Guid LiveShareHostUIContextGuid = Guid.Parse("62de1aa5-70b0-4934-9324-680896466fe1");
private static readonly Guid LiveShareGuestUIContextGuid = Guid.Parse("fd93f3eb-60da-49cd-af15-acda729e357e");
private readonly ProjectHierarchyInspector _projectHierarchyInspector;
private readonly IVsUIShellOpenDocument _vsUIShellOpenDocument;
private readonly Lazy<IVsUIShellOpenDocument> _vsUIShellOpenDocument;
private readonly IVsFeatureFlags _featureFlags;

[ImportingConstructor]
Expand All @@ -31,8 +31,13 @@ public DefaultLSPEditorFeatureDetector(ProjectHierarchyInspector projectHierarch

_projectHierarchyInspector = projectHierarchyInspector;
_featureFlags = (IVsFeatureFlags)AsyncPackage.GetGlobalService(typeof(SVsFeatureFlags));
_vsUIShellOpenDocument = (IVsUIShellOpenDocument)ServiceProvider.GlobalProvider.GetService(typeof(SVsUIShellOpenDocument));
Assumes.Present(_vsUIShellOpenDocument);
_vsUIShellOpenDocument = new Lazy<IVsUIShellOpenDocument>(() =>
{
var shellOpenDocument = (IVsUIShellOpenDocument)ServiceProvider.GlobalProvider.GetService(typeof(SVsUIShellOpenDocument));
Assumes.Present(shellOpenDocument);

return shellOpenDocument;
});
}

// Test constructor
Expand Down Expand Up @@ -116,7 +121,7 @@ private protected virtual bool ProjectSupportsRazorLSPEditor(string documentMoni
{
if (hierarchy == null)
{
var hr = _vsUIShellOpenDocument.IsDocumentInAProject(documentMoniker, out var uiHierarchy, out _, out _, out _);
var hr = _vsUIShellOpenDocument.Value.IsDocumentInAProject(documentMoniker, out var uiHierarchy, out _, out _, out _);
hierarchy = uiHierarchy;
if (!ErrorHandler.Succeeded(hr) || hierarchy == null)
{
Expand Down
Loading

0 comments on commit fef50ba

Please sign in to comment.