15#include <boost/asio/post.hpp>
17#include <llvm/Support/Error.h>
18#include <llvm/Support/JSON.h>
50 if (Parent && Parent->
kind() == Node::NK_AttrName)
51 return VLA.
toDef(*Parent);
61 if (
const Node *
Up = PMA.
upTo(
N, Node::NK_Inherit)) {
65 const auto &
Inh =
static_cast<const Inherit &
>(*Up);
66 const auto &
AN =
static_cast<const AttrName &
>(*UpAn);
97 return static_cast<const ExprVar *
>(PMA.
upTo(
N, Node::NK_ExprVar));
104 if (
Result.Kind == ResultKind::Undefined)
107 if (
Result.Kind == ResultKind::NoSuchVar)
127struct NoLocationsFoundInNixpkgsException : std::exception {
128 [[
nodiscard]]
const char *what()
const noexcept override {
129 return "no locations found in nixpkgs";
133class WorkerReportedException : std::exception {
137 WorkerReportedException(llvm::Error E) : E(std::move(E)){};
139 llvm::Error takeError() {
return std::move(E); }
140 [[
nodiscard]]
const char *what()
const noexcept override {
141 return "worker reported some error";
150class NixpkgsDefinitionProvider {
156 auto Pos =
Position.find_first_of(
':');
157 if (Pos == std::string_view::npos) {
160 .range = {{0, 0}, {0, 0}},
163 int PosL = std::stoi(std::string(
Position.substr(Pos + 1)));
174 : NixpkgsClient(NixpkgsClient) {}
177 std::binary_semaphore Ready(0);
179 auto OnReply = [&Ready, &
Desc](llvm::Expected<AttrPathInfoResponse>
Resp) {
190 throw WorkerReportedException(
Desc.takeError());
197 if (
const auto &
Loc =
Desc->Meta.Location)
200 throw NoLocationsFoundInNixpkgsException();
205class OptionsDefinitionProvider {
209 OptionsDefinitionProvider(
AttrSetClient &Client) : Client(Client) {}
212 std::binary_semaphore Ready(0);
215 auto OnReply = [&Ready, &
Info](llvm::Expected<OptionInfoResponse>
Resp) {
225 elog(
"getting locations: {0}",
Info.takeError());
229 for (
const auto &
Decl :
Info->Declarations)
238 std::mutex &OptionsLock,
241 std::vector<std::string> Scope;
244 if (R == PathResult::OK) {
245 std::lock_guard _(OptionsLock);
247 for (
const auto &[_, Client] : Options) {
249 OptionsDefinitionProvider
ODP(*
C);
250 ODP.resolveLocations(Scope,
Locs);
262 NixpkgsDefinitionProvider
NDP(NixpkgsClient);
263 return NDP.resolveSelector(
Sel);
264 }
catch (NoLocationsFoundInNixpkgsException &E) {
265 elog(
"definition/idiom: {0}", E.what());
266 }
catch (WorkerReportedException &E) {
267 elog(
"definition/idiom/worker: {0}", E.takeError());
281 elog(
"defintion/idiom/selector: {0}", E.what());
293std::vector<T>
mergeVec(std::vector<T>
A,
const std::vector<T> &
B) {
294 A.insert(
A.end(),
B.begin(),
B.end());
298llvm::Expected<Locations>
310 }
catch (std::exception &E) {
311 elog(
"definition/idiom/selector: {0}", E.what());
314 }
catch (std::exception &E) {
315 elog(
"definition/static: {0}", E.what());
318 return error(
"unreachable code! Please submit an issue");
322template <
class T> llvm::json::Value
squash(std::vector<T>
List) {
323 std::size_t Size =
List.size();
328 return std::move(
List.back());
332 return std::move(
List);
336llvm::Expected<llvm::json::Value>
squash(llvm::Expected<std::vector<T>>
List) {
338 return List.takeError();
363 if (std::shared_ptr<Node> AST = getAST(*
TU,
Reply)) [[
likely]] {
368 Reply(
error(
"cannot find AST node on given position"));
380 return Reply(
squash([&]() -> llvm::Expected<Locations> {
386 case Node::NK_ExprVar: {
390 case Node::NK_ExprSelect: {
394 case Node::NK_ExprAttrs:
399 return error(
"unknown node type for definition");
404 boost::asio::post(Pool, std::move(
Action));
This file declares some common analysis (tree walk) on the AST.
Types used in nixpkgs provider.
Convert between LSP and nixf types.
std::vector< Location > Locations
Lookup variable names, from it's parent scope.
void optionInfo(const AttrPathInfoParams &Params, lspserver::Callback< OptionInfoResponse > Reply)
void attrpathInfo(const AttrPathInfoParams &Params, lspserver::Callback< AttrPathInfoResponse > Reply)
std::map< std::string, std::unique_ptr< AttrSetClientProc > > OptionMapTy
const Node * syntax() const
const SemaAttrs & sema() const
const Node * descend(PositionRange Range) const
Descendant node that contains the given range.
LexerCursorRange range() const
const Node * upTo(const Node &N, Node::NodeKind Kind) const
Search up until some kind of node is found.
const Node * query(const Node &N) const
Attribute set after deduplication.
const std::map< std::string, Attribute > & staticAttrs() const
Static attributes, do not require evaluation to get the key.
const Definition * toDef(const Node &N) const
Get definition record for some name.
LookupResult query(const ExprVar &Var) const
Query the which name/with binds to specific varaible.
Whether current platform treats paths case insensitively.
llvm::unique_function< void(llvm::Expected< T >)> Callback
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&...Vals)
@ Info
An information message.
void elog(const char *Fmt, Ts &&...Vals)
Selector mkVarSelector(const nixf::ExprVar &Var, const nixf::VariableLookupAnalysis &VLA, const nixf::ParentMapAnalysis &PM)
Construct a nixd::Selector from Var.
Selector mkSelector(const nixf::AttrPath &AP, Selector BaseSelector)
Construct a nixd::Selector from AP.
bool fromJSON(const llvm::json::Value &Params, Configuration::Diagnostic &R, llvm::json::Path P)
FindAttrPathResult findAttrPath(const nixf::Node &N, const nixf::ParentMapAnalysis &PM, std::vector< std::string > &Path)
Heuristically find attrpath suitable for "attrpath" completion.
std::vector< std::string > Selector
A list of strings that "select"s into a attribute set.
nixf::Position toNixfPosition(const lspserver::Position &P)
const nixf::Definition & findDefinition(const nixf::Node &N, const nixf::ParentMapAnalysis &PMA, const nixf::VariableLookupAnalysis &VLA)
Heuristically find definition on some node.
lspserver::Range toLSPRange(llvm::StringRef Code, const nixf::LexerCursorRange &R)
std::vector< OptionField > OptionCompleteResponse
URIForFile uri
The text document's URI.
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Exceptions scoped in nixd::mkIdiomSelector.