Sadly, to get this far I had to opt cohosting into FUSE, which will have untold consequences
This commit is contained in:
David Wengier 2024-10-30 17:06:58 +11:00
Родитель 76cd92a65e
Коммит 9b7ed904a7
7 изменённых файлов: 55 добавлений и 16 удалений

Просмотреть файл

@ -25,4 +25,7 @@ internal struct RemoteClientInitializationOptions
[DataMember(Order = 5)]
internal required bool ReturnCodeActionAndRenamePathsWithPrefixedSlash;
[DataMember(Order = 6)]
internal required bool ForceRuntimeCodeGeneration;
}

Просмотреть файл

@ -41,5 +41,5 @@ internal class RemoteLanguageServerFeatureOptions : LanguageServerFeatureOptions
public override bool DisableRazorLanguageServer => throw new InvalidOperationException("This option has not been synced to OOP.");
public override bool ForceRuntimeCodeGeneration => throw new InvalidOperationException("This option has not been synced to OOP.");
public override bool ForceRuntimeCodeGeneration => _options.ForceRuntimeCodeGeneration;
}

Просмотреть файл

@ -66,14 +66,29 @@ internal sealed class RemoteDocumentSnapshot : IDocumentSnapshot
bool forceDesignTimeGeneratedOutput,
CancellationToken cancellationToken)
{
// We don't cache if we're forcing, as that would break everything else
if (forceDesignTimeGeneratedOutput)
{
return new ValueTask<RazorCodeDocument>(GetRazorCodeDocumentAsync(forceRuntimeCodeGeneration: false, cancellationToken));
}
var forceRuntimeCodeGeneration = ProjectSnapshot.SolutionSnapshot.SnapshotManager.LanguageServerFeatureOptions.ForceRuntimeCodeGeneration;
// TODO: We don't need to worry about locking if we get called from the didOpen/didChange LSP requests, as CLaSP
// takes care of that for us, and blocks requests until those are complete. If that doesn't end up happening,
// then a locking mechanism here would prevent concurrent compilations.
return TryGetGeneratedOutput(out var codeDocument)
? new(codeDocument)
: new(GetGeneratedOutputCoreAsync(cancellationToken));
: new(GetGeneratedOutputCoreAsync(forceRuntimeCodeGeneration, cancellationToken));
async Task<RazorCodeDocument> GetGeneratedOutputCoreAsync(CancellationToken cancellationToken)
async Task<RazorCodeDocument> GetGeneratedOutputCoreAsync(bool forceRuntimeCodeGeneration, CancellationToken cancellationToken)
{
codeDocument = await GetRazorCodeDocumentAsync(forceRuntimeCodeGeneration, cancellationToken).ConfigureAwait(false);
return _codeDocument ??= InterlockedOperations.Initialize(ref _codeDocument, codeDocument);
}
async Task<RazorCodeDocument> GetRazorCodeDocumentAsync(bool forceRuntimeCodeGeneration, CancellationToken cancellationToken)
{
// The non-cohosted DocumentSnapshot implementation uses DocumentState to get the generated output, and we could do that too
// but most of that code is optimized around caching pre-computed results when things change that don't affect the compilation.
@ -87,14 +102,9 @@ internal sealed class RemoteDocumentSnapshot : IDocumentSnapshot
var tagHelpers = await ProjectSnapshot.GetTagHelpersAsync(cancellationToken).ConfigureAwait(false);
var imports = await DocumentState.GetImportsAsync(this, projectEngine, cancellationToken).ConfigureAwait(false);
// TODO: Get the configuration for forceRuntimeCodeGeneration
// var forceRuntimeCodeGeneration = _projectSnapshot.Configuration.LanguageServerFlags?.ForceRuntimeCodeGeneration ?? false;
codeDocument = await DocumentState
.GenerateCodeDocumentAsync(this, projectEngine, imports, tagHelpers, forceRuntimeCodeGeneration: false, cancellationToken)
return await DocumentState
.GenerateCodeDocumentAsync(this, projectEngine, imports, tagHelpers, forceRuntimeCodeGeneration: forceRuntimeCodeGeneration, cancellationToken)
.ConfigureAwait(false);
return _codeDocument ??= InterlockedOperations.Initialize(ref _codeDocument, codeDocument);
}
}

Просмотреть файл

@ -11,10 +11,11 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
[Shared]
[Export(typeof(RemoteSnapshotManager))]
[method: ImportingConstructor]
internal sealed class RemoteSnapshotManager(IFilePathService filePathService, ITelemetryReporter telemetryReporter)
internal sealed class RemoteSnapshotManager(LanguageServerFeatureOptions languageServerFeatureOptions, IFilePathService filePathService, ITelemetryReporter telemetryReporter)
{
private static readonly ConditionalWeakTable<Solution, RemoteSolutionSnapshot> s_solutionToSnapshotMap = new();
public LanguageServerFeatureOptions LanguageServerFeatureOptions { get; } = languageServerFeatureOptions;
public IFilePathService FilePathService { get; } = filePathService;
public ITelemetryReporter TelemetryReporter { get; } = telemetryReporter;

Просмотреть файл

@ -136,6 +136,7 @@ internal sealed class RemoteServiceInvoker(
HtmlVirtualDocumentSuffix = _languageServerFeatureOptions.HtmlVirtualDocumentSuffix,
IncludeProjectKeyInGeneratedFilePath = _languageServerFeatureOptions.IncludeProjectKeyInGeneratedFilePath,
ReturnCodeActionAndRenamePathsWithPrefixedSlash = _languageServerFeatureOptions.ReturnCodeActionAndRenamePathsWithPrefixedSlash,
ForceRuntimeCodeGeneration = _languageServerFeatureOptions.ForceRuntimeCodeGeneration
};
_logger.LogDebug($"First OOP call, so initializing OOP service.");

Просмотреть файл

@ -60,6 +60,7 @@ public abstract class CohostEndpointTestBase(ITestOutputHelper testOutputHelper)
UsePreciseSemanticTokenRanges = false,
UseRazorCohostServer = true,
ReturnCodeActionAndRenamePathsWithPrefixedSlash = false,
ForceRuntimeCodeGeneration = false
};
UpdateClientInitializationOptions(c => c);

Просмотреть файл

@ -120,17 +120,36 @@ public class CohostOnAutoInsertEndpointTest(ITestOutputHelper testOutputHelper)
formatOnType: false);
}
[Fact]
public async Task CSharp_OnEnter()
[Theory]
[CombinatorialData]
public async Task CSharp_OnEnter(bool fuse)
{
await VerifyOnAutoInsertAsync(
input: """
Hello
<div>
Hello
<p>Hello</p>
<p class="@DateTime.Now.DayOfWeek">Hello</p>
</div>
Hello
@code {
void TestMethod() {
$$}
}
""",
output: """
Hello
<div>
Hello
<p>Hello</p>
<p class="@DateTime.Now.DayOfWeek">Hello</p>
</div>
Hello
@code {
void TestMethod()
{
@ -138,7 +157,8 @@ public class CohostOnAutoInsertEndpointTest(ITestOutputHelper testOutputHelper)
}
}
""",
triggerCharacter: "\n");
triggerCharacter: "\n",
fuse: fuse);
}
[Fact]
@ -194,8 +214,11 @@ public class CohostOnAutoInsertEndpointTest(ITestOutputHelper testOutputHelper)
bool insertSpaces = true,
int tabSize = 4,
bool formatOnType = true,
bool autoClosingTags = true)
{
bool autoClosingTags = true,
bool fuse = false)
{
UpdateClientInitializationOptions(opt => opt with { ForceRuntimeCodeGeneration = fuse });
var document = await CreateProjectAndRazorDocumentAsync(input.Text);
var sourceText = await document.GetTextAsync(DisposalToken);