-
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
211 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#pragma once | ||
|
||
#include "nixd/AST/EvalAST.h" | ||
#include "nixd/AST/ParseAST.h" | ||
|
||
#include "lspserver/Protocol.h" | ||
|
||
#include <vector> | ||
|
||
namespace nixd { | ||
|
||
using CompletionResult = lspserver::CompletionList; | ||
|
||
class CompletionBuilder { | ||
CompletionResult Result; | ||
size_t Limit = 1000; | ||
|
||
public: | ||
/// { a = 1; b = 2; }.| | ||
/// ^ "a", "b" | ||
void addAttrFields(const EvalAST &AST, const lspserver::Position &Pos, | ||
nix::EvalState &State); | ||
|
||
/// Symbols from let-bindings, rec-attrs. | ||
void addSymbols(const ParseAST &AST, const nix::Expr *Node); | ||
|
||
/// | ||
/// ( | ||
/// { foo ? 1 # <-- Lambda formal | ||
/// , bar ? 2 | ||
/// }: foo + bar) { | } | ||
/// ^ "foo", "bar" | ||
void addLambdaFormals(const EvalAST &AST, nix::EvalState &State, | ||
const nix::Expr *Node); | ||
|
||
/// with pkgs; [ ] | ||
void addEnv(nix::EvalState &State, nix::Env &NixEnv); | ||
|
||
void addEnv(const EvalAST &AST, nix::EvalState &State, const nix::Expr *Node); | ||
|
||
/// builtins.* | ||
void addStaticEnv(const nix::SymbolTable &STable, const nix::StaticEnv &SEnv); | ||
|
||
CompletionResult &getResult() { return Result; } | ||
|
||
void setLimit(size_t Limit) { this->Limit = Limit; } | ||
}; | ||
|
||
} // namespace nixd |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#include "nixd/Sema/CompletionBuilder.h" | ||
#include "nixd/AST/ParseAST.h" | ||
#include "nixd/Nix/Eval.h" | ||
|
||
#include "lspserver/Protocol.h" | ||
|
||
#include <stdexcept> | ||
|
||
namespace nixd { | ||
|
||
using lspserver::CompletionItem; | ||
using lspserver::CompletionItemKind; | ||
|
||
void CompletionBuilder::addAttrFields(const EvalAST &AST, | ||
const lspserver::Position &Pos, | ||
nix::EvalState &State) { | ||
try { | ||
if (const auto *Node = AST.lookupEnd(Pos)) { | ||
auto Value = AST.getValueEval(Node, State); | ||
if (Value.type() == nix::ValueType::nAttrs) { | ||
// Traverse attribute bindings | ||
for (auto Binding : *Value.attrs) { | ||
CompletionItem R; | ||
R.label = State.symbols[Binding.name]; | ||
R.kind = CompletionItemKind::Field; | ||
Result.items.emplace_back(std::move(R)); | ||
if (Result.items.size() > Limit) { | ||
Result.isIncomplete = true; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} catch (std::out_of_range &) { | ||
} | ||
} | ||
|
||
void CompletionBuilder::addSymbols(const ParseAST &AST, const nix::Expr *Node) { | ||
std::vector<nix::Symbol> Symbols; | ||
AST.collectSymbols(Node, Symbols); | ||
// Insert symbols to our completion list. | ||
std::transform(Symbols.begin(), Symbols.end(), | ||
std::back_inserter(Result.items), [&](const nix::Symbol &V) { | ||
lspserver::CompletionItem R; | ||
R.kind = CompletionItemKind::Interface; | ||
R.label = AST.symbols()[V]; | ||
return R; | ||
}); | ||
} | ||
|
||
void CompletionBuilder::addLambdaFormals(const EvalAST &AST, | ||
nix::EvalState &State, | ||
const nix::Expr *Node) { | ||
|
||
// Nix only accepts attr set formals | ||
if (!dynamic_cast<const nix::ExprAttrs *>(Node)) | ||
return; | ||
|
||
try { | ||
const auto *Parent = AST.parent(Node); | ||
if (const auto *SomeExprCall = | ||
dynamic_cast<const nix::ExprCall *>(Parent)) { | ||
auto Value = AST.getValueEval(SomeExprCall->fun, State); | ||
if (!Value.isLambda()) | ||
return; | ||
auto *Fun = Value.lambda.fun; | ||
if (!Fun->hasFormals()) | ||
return; | ||
for (auto Formal : Fun->formals->formals) { | ||
CompletionItem R; | ||
R.label = State.symbols[Formal.name]; | ||
R.kind = CompletionItemKind::Constructor; | ||
Result.items.emplace_back(std::move(R)); | ||
} | ||
} | ||
} catch (std::out_of_range &) { | ||
} | ||
} | ||
|
||
void CompletionBuilder::addEnv(nix::EvalState &State, nix::Env &NixEnv) { | ||
if (NixEnv.type == nix::Env::HasWithExpr) { | ||
nix::Value *V = State.allocValue(); | ||
State.evalAttrs(*NixEnv.up, (nix::Expr *)NixEnv.values[0], *V, nix::noPos, | ||
"<borked>"); | ||
NixEnv.values[0] = V; | ||
NixEnv.type = nix::Env::HasWithAttrs; | ||
} | ||
if (NixEnv.type == nix::Env::HasWithAttrs) { | ||
for (const auto &SomeAttr : *NixEnv.values[0]->attrs) { | ||
std::string Name = State.symbols[SomeAttr.name]; | ||
lspserver::CompletionItem R; | ||
R.label = Name; | ||
R.kind = lspserver::CompletionItemKind::Variable; | ||
Result.items.emplace_back(std::move(R)); | ||
|
||
if (Result.items.size() > Limit) { | ||
Result.isIncomplete = true; | ||
break; | ||
} | ||
} | ||
} | ||
if (NixEnv.up) | ||
addEnv(State, *NixEnv.up); | ||
} | ||
|
||
void CompletionBuilder::addEnv(const EvalAST &AST, nix::EvalState &State, | ||
const nix::Expr *Node) { | ||
try { | ||
// Eval this node, for reaching deeper envs (e.g. with expressions). | ||
AST.getValueEval(Node, State); | ||
if (auto *ExprEnv = AST.searchUpEnv(Node)) | ||
addEnv(State, *ExprEnv); | ||
} catch (std::out_of_range &) { | ||
} | ||
} | ||
|
||
void CompletionBuilder::addStaticEnv(const nix::SymbolTable &STable, | ||
const nix::StaticEnv &SEnv) { | ||
for (auto [Symbol, Displ] : SEnv.vars) { | ||
std::string Name = STable[Symbol]; | ||
if (Name.starts_with("__")) | ||
continue; | ||
|
||
CompletionItem R; | ||
R.label = Name; | ||
R.kind = CompletionItemKind::Constant; | ||
Result.items.emplace_back(std::move(R)); | ||
} | ||
|
||
if (SEnv.up) | ||
addStaticEnv(STable, SEnv); | ||
} | ||
|
||
} // namespace nixd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
libnixdSemaDeps = [ nixd_lsp_server | ||
, nix_all | ||
, nixdAST | ||
, llvm | ||
] | ||
|
||
libnixdSema = library('nixdSema' | ||
, 'CompletionBuilder.cpp' | ||
, include_directories: nixd_inc | ||
, dependencies: libnixdSemaDeps | ||
, install: true | ||
) | ||
|
||
nixdSema = declare_dependency( include_directories: nixd_inc | ||
, link_with: libnixdSema | ||
, dependencies: libnixdSemaDeps | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
libnixdServerDeps = [ nixd_lsp_server | ||
, nix_all | ||
, nixdSema | ||
, nixdAST | ||
, nixdNix | ||
, nixdSupport | ||
|
Oops, something went wrong.