5#include <unordered_set>
12struct AttrPathHasDynamicError : std::exception {
13 [[nodiscard]]
const char *what() const noexcept
override {
14 return "the attrpath has dynamic attribute name";
29 std::vector<std::string> &Path) {
31 assert(Up &&
"Naked attrname!");
32 assert(Up->
kind() == Node::NK_AttrPath &&
33 "Invoked in non-attrpath name! (Slipped inherit?)");
36 Path.reserve(APath.names().size());
37 for (
const auto &Name : APath.names()) {
38 if (!Name->isStatic())
39 throw AttrPathHasDynamicError();
40 Path.emplace_back(Name->staticName());
48 std::vector<std::string> &Path) {
62 if (Up->
kind() != Node::NK_ExprAttrs)
65 std::vector<std::string_view> Basic;
68 getValueAttrPath(*Up, PM, Path);
72 assert(UpAttrs.binds() &&
"empty binds cannot nest anything!");
73 for (
const std::shared_ptr<nixf::Node> &Attr : UpAttrs.binds()->bindings()) {
75 if (Attr->kind() == Node::NK_Inherit)
77 assert(Attr->kind() == Node::NK_Binding);
84 assert(
false &&
"must have corresbonding value");
85 __builtin_unreachable();
90 std::vector<std::string> &Path) {
92 getValueAttrPath(*
Expr, PM, Path);
93 getSelectAttrPath(N, PM, Path);
116 for (; Env; Env = Env->
parent()) {
121 assert(With && With->
kind() == Node::NK_ExprWith);
127 if (WithBody->
kind() != Node::NK_ExprVar)
131 if (
static_cast<const ExprVar &
>(*WithBody).
id().
name() == idioms::Pkgs)
140using IdiomSetT = std::unordered_set<std::string_view>;
149 if (It == IdiomSet.end())
159 assert(
false &&
"Unhandled idiom iterator?");
160 __builtin_unreachable();
166 return getKnownIdiomSelector(IdiomSet.find(Var.
id().
name()));
175 case Node::NK_ExprVar:
178 case Node::NK_ExprSelect:
194 std::move(BaseSelector));
205 auto Result = VLA.
query(Var);
206 switch (Result.Kind) {
207 case ResultKind::Undefined:
208 case ResultKind::Defined:
209 return varSelector(Var);
210 case ResultKind::FromWith: {
211 assert(Result.Def &&
"FromWith variables should contains definition");
226 assert(With &&
"parent of kwWith should be the with expression");
227 assert(With->
kind() == nixf::Node::NK_ExprWith);
229 withSelector(
static_cast<const nixf::ExprWith &
>(*With), VLA, PM);
237 WithSelector.emplace_back(Var.
id().
name());
241 case ResultKind::NoSuchVar:
244 assert(
false &&
"switch fallthrough!");
245 __builtin_unreachable();
251 const auto &Names = AP.
names();
252 for (
const auto &Name : Names) {
253 if (!Name->isStatic())
255 BaseSelector.emplace_back(Name->staticName());
263 if (Sel.
expr().
kind() != Node::NK_ExprVar)
266 const auto &Var =
static_cast<ExprVar &
>(Sel.
expr());
270 return mkSelector(Sel, std::move(BaseSelector));
273std::pair<std::vector<std::string>, std::string>
275 if (N.
kind() != Node::NK_Identifier)
279 std::string Prefix =
static_cast<const Identifier &
>(N).name();
285 std::vector<std::string> &
Path) {
288 if (PM.
upTo(N, Node::NK_Inherit))
291 if (
const Node *Name = PM.
upTo(N, Node::NK_AttrName)) {
293 getNestedAttrPath(
static_cast<const AttrName &
>(*Name), PM,
Path);
294 }
catch (AttrPathHasDynamicError &E) {
295 return R::WithDynamic;
301 if (
const Node *DotNode = PM.
upTo(N, Node::NK_Dot)) {
302 const auto &D =
static_cast<const Dot &
>(*DotNode);
304 if (D.prev().kind() != Node::NK_AttrName)
305 return R::NotAttrPath;
308 getNestedAttrPath(
static_cast<const AttrName &
>(D.prev()), PM,
Path);
309 Path.emplace_back(
"");
311 }
catch (AttrPathHasDynamicError &E) {
312 return R::WithDynamic;
316 return R::NotAttrPath;
This file declares some common analysis (tree walk) on the AST.
Types used in nixpkgs provider.
const std::vector< std::shared_ptr< AttrName > > & names() const
const AttrPath & path() const
const std::shared_ptr< Expr > & value() const
const Node * syntax() const
Holds a "." in the language.
A set of variable definitions, which may inherit parent environment.
const Node * syntax() const
Where this node comes from.
const Identifier & id() const
Identifier. Variable names, attribute names, etc.
const std::string & name() const
const Node * upExpr(const Node &N) const
Search up until the node becomes a concrete expression. a ^<--— ID -> ExprVar.
static bool isRoot(const Node *Up, const Node &N)
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
const EnvNode * env(const Node *N) const
LookupResult query(const ExprVar &Var) const
Query the which name/with binds to specific varaible.
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.
constexpr std::string_view Pkgs
Hardcoded name for "pkgs.xxx", or "with pkgs;".
constexpr std::string_view Lib
Hardcoded name for nixpkgs "lib".
FindAttrPathResult findAttrPath(const nixf::Node &N, const nixf::ParentMapAnalysis &PM, std::vector< std::string > &Path)
Heuristically find attrpath suitable for "attrpath" completion.
const nixf::EnvNode * upEnv(const nixf::Node &Desc, const nixf::VariableLookupAnalysis &VLA, const nixf::ParentMapAnalysis &PM)
Search up until there are some node associated with "EnvNode".
bool havePackageScope(const nixf::Node &N, const nixf::VariableLookupAnalysis &VLA, const nixf::ParentMapAnalysis &PM)
Determine whether or not some node has enclosed "with pkgs; [ ]".
std::vector< std::string > Selector
A list of strings that "select"s into a attribute set.
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.
The attrpath has a dynamic name, thus it cannot be trivially transformed to "static" selector.
The pattern of this variable cannot be recognized by known idioms.