13#include <boost/asio/post.hpp>
15#include <llvm/Support/Error.h>
21using namespace llvm::json;
27class OptionsHoverProvider {
31 OptionsHoverProvider(
AttrSetClient &Client) : Client(Client) {}
32 std::optional<OptionDescription>
33 resolveHover(
const std::vector<std::string> &Scope) {
34 std::binary_semaphore Ready(0);
35 std::optional<OptionDescription> Desc;
36 auto OnReply = [&Ready, &Desc](llvm::Expected<OptionInfoResponse> Resp) {
40 elog(
"options hover: {0}", Resp.takeError());
52class NixpkgsHoverProvider {
60 std::ostringstream OS;
64 OS <<
"`" << *
Package.Name <<
"`";
70 OS <<
"[homepage](" << *
Package.Homepage <<
")";
75 OS <<
"## Description"
92 : NixpkgsClient(NixpkgsClient) {}
94 std::optional<std::string> resolvePackage(std::vector<std::string> Scope,
96 std::binary_semaphore Ready(0);
97 std::optional<AttrPathInfoResponse> Desc;
98 auto OnReply = [&Ready, &Desc](llvm::Expected<AttrPathInfoResponse> Resp) {
102 elog(
"nixpkgs provider: {0}", Resp.takeError());
105 Scope.emplace_back(std::move(Name));
112 return mkMarkdown(Desc->PackageDesc);
119 Callback<std::optional<Hover>> Reply) {
120 using CheckTy = std::optional<Hover>;
121 auto Action = [Reply = std::move(Reply),
123 RawPos = Params.
position,
this]()
mutable {
124 return Reply([&]() -> llvm::Expected<CheckTy> {
128 const auto &N = *
CheckDefault(AST->descend({Pos, Pos}));
130 const auto Name = std::string(N.name());
131 const auto &VLA = *TU->variableLookup();
132 const auto &PM = *TU->parentMap();
135 auto NHP = NixpkgsHoverProvider(*nixpkgsClient());
137 if (std::optional<std::string> Doc = NHP.resolvePackage(Scope, Name)) {
141 .kind = MarkupKind::Markdown,
142 .value = std::move(*Doc),
149 auto Scope = std::vector<std::string>();
152 std::lock_guard
_(OptionsLock);
153 for (
const auto &[_, Client] : Options) {
155 OptionsHoverProvider OHP(*C);
156 std::optional<OptionDescription> Desc = OHP.resolveHover(Scope);
160 std::string TypeName = Desc->Type->Name.value_or(
"");
161 std::string TypeDesc = Desc->Type->Description.value_or(
"");
162 Docs += llvm::formatv(
"{0} ({1})", TypeName, TypeDesc);
164 Docs +=
"? (missing type)";
166 if (Desc->Description) {
167 Docs +=
"\n\n" + Desc->Description.value_or(
"");
172 .kind = MarkupKind::Markdown,
173 .value = std::move(Docs),
187 .kind = MarkupKind::Markdown,
188 .value =
"`" + Name +
"`",
194 boost::asio::post(Pool, std::move(Action));
This file declares some common analysis (tree walk) on the AST.
Types used in nixpkgs provider.
#define CheckDefault(x)
Variant of CheckReturn, but returns default constructed CheckTy
Convert between LSP and nixf types.
void optionInfo(const AttrPathInfoParams &Params, lspserver::Callback< OptionInfoResponse > Reply)
void attrpathInfo(const AttrPathInfoParams &Params, lspserver::Callback< AttrPathInfoResponse > Reply)
Whether current platform treats paths case insensitively.
llvm::unique_function< void(llvm::Expected< T >)> Callback
void elog(const char *Fmt, Ts &&...Vals)
FindAttrPathResult findAttrPath(const nixf::Node &N, const nixf::ParentMapAnalysis &PM, std::vector< std::string > &Path)
Heuristically find attrpath suitable for "attrpath" completion.
bool havePackageScope(const nixf::Node &N, const nixf::VariableLookupAnalysis &VLA, const nixf::ParentMapAnalysis &PM)
Determine whether or not some node has enclosed "with pkgs; [ ]".
lspserver::Range toLSPRange(llvm::StringRef Code, const nixf::LexerCursorRange &R)
std::pair< std::vector< std::string >, std::string > getScopeAndPrefix(const nixf::Node &N, const nixf::ParentMapAnalysis &PM)
get variable scope, and it's prefix name.
URIForFile uri
The text document's URI.
Position position
The position inside the text document.
TextDocumentIdentifier textDocument
The text document.
llvm::StringRef file() const
Retrieves absolute path to the file.