6#include <nix/attr-path.hh>
7#include <nix/common-eval-args.hh>
8#include <nix/nixexpr.hh>
9#include <nix/store-api.hh>
17constexpr int MaxItems = 30;
19void fillString(nix::EvalState &State, nix::Value &V,
20 const std::vector<std::string_view> &AttrPath,
21 std::optional<std::string> &
Field) {
24 State.forceValue(Select, nix::noPos);
25 if (Select.type() == nix::ValueType::nString)
26 Field = Select.string_view();
27 }
catch (std::exception &E) {
45std::optional<Location> locationOf(nix::PosTable &PTable, nix::Value &V) {
46 nix::PosIdx P = V.determinePos(nix::noPos);
50 nix::Pos NixPos = PTable[P];
51 const auto *SP = std::get_if<nix::SourcePath>(&NixPos.origin);
57 .line =
static_cast<int64_t
>(NixPos.line - 1),
58 .character =
static_cast<int64_t
>(NixPos.column - 1),
63 .range = {LPos, LPos},
67ValueMeta metadataOf(nix::EvalState &State, nix::Value &V) {
70 .Location = locationOf(State.positions, V),
74void fillUnsafeGetAttrPosLocation(nix::EvalState &State, nix::Value &V,
76 State.forceValue(V, nix::noPos);
82 if (
File.type() == nix::ValueType::nString)
85 if (Line.type() == nix::ValueType::nInt &&
86 Column.type() == nix::ValueType::nInt) {
90 static_cast<int64_t
>(Column.integer()) - 1};
91 Loc.
range = {Pos, Pos};
95void fillOptionDeclarationPositions(nix::EvalState &State, nix::Value &V,
97 State.forceValue(V, nix::noPos);
98 if (V.type() != nix::ValueType::nList)
100 for (nix::Value *Item : V.listItems()) {
103 fillUnsafeGetAttrPosLocation(State, *Item, Loc);
108void fillOptionDeclarations(nix::EvalState &State, nix::Value &V,
113 State, V, State.symbols.create(
"declarationPositions"));
115 State.forceValue(DeclarationPositions, nix::noPos);
117 fillOptionDeclarationPositions(State, DeclarationPositions, R);
118 }
catch (nix::AttrPathNotFound &E) {
124void fillOptionType(nix::EvalState &State, nix::Value &VType,
OptionType &R) {
125 fillString(State, VType, {
"description"}, R.
Description);
126 fillString(State, VType, {
"name"}, R.
Name);
129void fillOptionDescription(nix::EvalState &State, nix::Value &V,
131 fillString(State, V, {
"description"}, R.
Description);
132 fillOptionDeclarations(State, V, R);
134 if (V.type() == nix::ValueType::nAttrs) [[likely]] {
136 if (
auto *It = V.attrs()->find(State.symbols.create(
"type"));
137 It != V.attrs()->end()) [[likely]] {
139 fillOptionType(State, *It->value,
Type);
143 if (
auto *It = V.attrs()->find(State.symbols.create(
"example"));
144 It != V.attrs()->end()) {
145 State.forceValue(*It->value, It->pos);
151 std::ostringstream OS;
152 It->value->print(State, OS);
162 std::unique_ptr<OutboundPort> Out)
163 :
LSPServer(std::move(In), std::move(Out)),
164 State(new
nix::EvalState({}, nix::openStore(), nix::fetchSettings,
165 nix::evalSettings)) {
178 const std::string &Name,
181 nix::Expr *AST = state().parseExprFromString(Name, state().rootPath(
"."));
182 state().eval(AST, Nixpkgs);
185 }
catch (
const nix::BaseError &Err) {
186 Reply(
error(Err.info().msg.str()));
188 }
catch (
const std::exception &Err) {
189 Reply(
error(Err.what()));
198 Reply([&]() -> llvm::Expected<RespT> {
200 if (AttrPath.empty())
201 return error(
"attrpath is empty!");
204 state().forceValue(V, nix::noPos);
206 .Meta = metadataOf(state(), V),
207 .PackageDesc = describePackage(state(), V),
209 }
catch (
const nix::BaseError &Err) {
210 return error(Err.info().msg.str());
211 }
catch (
const std::exception &Err) {
212 return error(Err.what());
223 state().forceValue(Scope, nix::noPos);
225 if (Scope.type() != nix::ValueType::nAttrs) {
226 Reply(
error(
"scope is not an attrset"));
230 std::vector<std::string> Names;
237 for (
const auto *AttrPtr :
238 Scope.attrs()->lexicographicOrder(state().symbols)) {
239 const nix::Attr &Attr = *AttrPtr;
240 const std::string_view Name = state().symbols[Attr.name];
241 if (Name.starts_with(Params.
Prefix)) {
243 Names.emplace_back(Name);
249 Reply(std::move(Names));
251 }
catch (
const nix::BaseError &Err) {
252 Reply(
error(Err.info().msg.str()));
254 }
catch (
const std::exception &Err) {
255 Reply(
error(Err.what()));
264 if (AttrPath.empty()) {
265 Reply(
error(
"attrpath is empty!"));
274 fillOptionDescription(state(), Option, R);
278 }
catch (
const nix::BaseError &Err) {
279 Reply(
error(Err.info().msg.str()));
281 }
catch (
const std::exception &Err) {
282 Reply(
error(Err.what()));
294 state().forceValue(Scope, nix::noPos);
296 if (Scope.type() != nix::ValueType::nAttrs) {
297 Reply(
error(
"scope is not an attrset"));
302 Reply(
error(
"scope is already an option"));
306 std::vector<OptionField> Response;
312 for (
const auto *AttrPtr :
313 Scope.attrs()->lexicographicOrder(state().symbols)) {
314 const nix::Attr &Attr = *AttrPtr;
315 std::string_view Name = state().symbols[Attr.name];
316 if (Name.starts_with(Params.
Prefix)) {
320 NewField.
Name = Name;
323 fillOptionDescription(state(), *Attr.value, Desc);
326 Response.emplace_back(std::move(NewField));
328 if (Response.size() >= MaxItems)
332 Reply(std::move(Response));
334 }
catch (
const nix::BaseError &Err) {
335 Reply(
error(Err.info().msg.str()));
337 }
catch (
const std::exception &Err) {
338 Reply(
error(Err.what()));
Dedicated worker for evaluating attrset.
Types used in nixpkgs provider.
void onOptionInfo(const AttrPathInfoParams &AttrPath, lspserver::Callback< OptionInfoResponse > Reply)
Provide option information on given attrpath.
void onAttrPathInfo(const AttrPathInfoParams &AttrPath, lspserver::Callback< AttrPathInfoResponse > Reply)
Query attrpath information.
void onEvalExpr(const EvalExprParams &Name, lspserver::Callback< EvalExprResponse > Reply)
Eval an expression, use it for furthur requests.
AttrSetProvider(std::unique_ptr< lspserver::InboundPort > In, std::unique_ptr< lspserver::OutboundPort > Out)
void onAttrPathComplete(const AttrPathCompleteParams &Params, lspserver::Callback< AttrPathCompleteResponse > Reply)
Complete attrpath entries.
void onOptionComplete(const AttrPathCompleteParams &Params, lspserver::Callback< OptionCompleteResponse > Reply)
Complete attrpath entries. However dive into submodules while selecting.
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)
constexpr std::string_view EvalExpr
constexpr std::string_view OptionInfo
constexpr std::string_view AttrPathInfo
constexpr std::string_view OptionComplete
constexpr std::string_view AttrPathComplete
Selector AttrPathInfoParams
std::optional< std::string_view > getFieldString(nix::EvalState &State, nix::Value &V, std::string_view Field)
bool isOption(nix::EvalState &State, nix::Value &V)
bool checkField(nix::EvalState &State, nix::Value &V, std::string_view Field, std::string_view Pred)
Check if value V is an attrset, has the field, and equals to Pred.
nix::Value & selectStrings(nix::EvalState &State, nix::Value &V, const std::vector< std::string > &AttrPath)
Given an attrpath in nix::Value V, select it.
nix::Value selectOptions(nix::EvalState &State, nix::Value &V, std::vector< nix::Symbol >::const_iterator Begin, std::vector< nix::Symbol >::const_iterator End)
Select the option declaration list, V, dive into "submodules".
std::vector< nix::Symbol > toSymbols(nix::SymbolTable &STable, const std::vector< std::string > &Names)
Transform a vector of string into a vector of nix symbols.
nix::Value & selectAttr(nix::EvalState &State, nix::Value &V, nix::Symbol Attr)
Select attribute Attr.
nix::Value & selectStringViews(nix::EvalState &State, nix::Value &V, const std::vector< std::string_view > &AttrPath)
Given an attrpath in nix::Value V, select it.
URIForFile uri
The text document's URI.
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
std::string Prefix
Search for packages prefixed with this "prefix".
std::optional< std::string > Description
std::optional< std::string > Example
std::optional< OptionType > Type
std::vector< lspserver::Location > Declarations
std::optional< OptionDescription > Description
std::optional< std::string > Description
std::optional< std::string > Name
std::optional< std::string > Name
std::optional< std::string > Version
std::optional< std::string > PName
std::optional< std::string > Description
std::optional< std::string > LongDescription
std::optional< std::string > Position
std::optional< std::string > Homepage