forked from Azure/bicep
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBicepRegistryCacheRequestHandler.cs
75 lines (61 loc) · 3.51 KB
/
BicepRegistryCacheRequestHandler.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Bicep.Core.Diagnostics;
using Bicep.Core.FileSystem;
using Bicep.Core.Parsing;
using Bicep.Core.Registry;
using MediatR;
using OmniSharp.Extensions.JsonRpc;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Bicep.LanguageServer.Handlers
{
[Method(BicepRegistryCacheRequestHandler.BicepCacheLspMethod, Direction.ClientToServer)]
public record BicepRegistryCacheParams(TextDocumentIdentifier TextDocument, string Target) : ITextDocumentIdentifierParams, IRequest<BicepRegistryCacheResponse>;
public record BicepRegistryCacheResponse(string Content);
/// <summary>
/// Handles textDocument/bicepCache LSP requests. These are sent by clients that are resolving contents of document URIs using the bicep-cache:// scheme.
/// The BicepDefinitionHandler returns such URIs when definitions are inside modules that reside in the local module cache.
/// </summary>
public class BicepRegistryCacheRequestHandler : IJsonRpcRequestHandler<BicepRegistryCacheParams, BicepRegistryCacheResponse>
{
public const string BicepCacheLspMethod = "textDocument/bicepCache";
private readonly IModuleDispatcher moduleDispatcher;
private readonly IFileResolver fileResolver;
public BicepRegistryCacheRequestHandler(IModuleDispatcher moduleDispatcher, IFileResolver fileResolver)
{
this.moduleDispatcher = moduleDispatcher;
this.fileResolver = fileResolver;
}
public Task<BicepRegistryCacheResponse> Handle(BicepRegistryCacheParams request, CancellationToken cancellationToken)
{
// If any of the following paths result in an exception being thrown (and surfaced client-side to the user),
// it indicates a code defect client or server-side.
// In normal operation, the user should never see them regardless of how malformed their code is.
if (!moduleDispatcher.TryGetModuleReference(request.Target, request.TextDocument.Uri.ToUri(), out var moduleReference, out _))
{
throw new InvalidOperationException($"The client specified an invalid module reference '{request.Target}'.");
}
if (!moduleReference.IsExternal)
{
throw new InvalidOperationException($"The specified module reference '{request.Target}' refers to a local module which is not supported by {BicepCacheLspMethod} requests.");
}
if (this.moduleDispatcher.GetModuleRestoreStatus(moduleReference, out _) != ModuleRestoreStatus.Succeeded)
{
throw new InvalidOperationException($"The module '{moduleReference.FullyQualifiedReference}' has not yet been successfully restored.");
}
if (!moduleDispatcher.TryGetLocalModuleEntryPointUri(moduleReference, out var uri, out _))
{
throw new InvalidOperationException($"Unable to obtain the entry point URI for module '{moduleReference.FullyQualifiedReference}'.");
}
if (!this.fileResolver.TryRead(uri, out var contents, out var failureBuilder))
{
var message = failureBuilder(DiagnosticBuilder.ForDocumentStart()).Message;
throw new InvalidOperationException($"Unable to read file '{uri}'. {message}");
}
return Task.FromResult(new BicepRegistryCacheResponse(contents));
}
}
}