mirror of
https://github.com/NixOS/nix.git
synced 2025-11-11 13:06:01 +01:00
nix repl: Render docs for attributes
This commit is contained in:
parent
491b9cf415
commit
d4f576b0b2
10 changed files with 237 additions and 3 deletions
|
|
@ -1415,6 +1415,22 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
|||
v = *vAttrs;
|
||||
}
|
||||
|
||||
Symbol ExprSelect::evalExceptFinalSelect(EvalState & state, Env & env, Value & attrs)
|
||||
{
|
||||
Value vTmp;
|
||||
Symbol name = getName(attrPath[attrPath.size() - 1], state, env);
|
||||
|
||||
if (attrPath.size() == 1) {
|
||||
e->eval(state, env, vTmp);
|
||||
} else {
|
||||
ExprSelect init(*this);
|
||||
init.attrPath.pop_back();
|
||||
init.eval(state, env, vTmp);
|
||||
}
|
||||
attrs = vTmp;
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
|
|
@ -2876,13 +2892,37 @@ Expr * EvalState::parse(
|
|||
const SourcePath & basePath,
|
||||
std::shared_ptr<StaticEnv> & staticEnv)
|
||||
{
|
||||
auto result = parseExprFromBuf(text, length, origin, basePath, symbols, settings, positions, rootFS, exprSymbols);
|
||||
DocCommentMap tmpDocComments; // Only used when not origin is not a SourcePath
|
||||
DocCommentMap *docComments = &tmpDocComments;
|
||||
|
||||
if (auto sourcePath = std::get_if<SourcePath>(&origin)) {
|
||||
auto [it, _] = positionToDocComment.try_emplace(*sourcePath);
|
||||
docComments = &it->second;
|
||||
}
|
||||
|
||||
auto result = parseExprFromBuf(text, length, origin, basePath, symbols, settings, positions, *docComments, rootFS, exprSymbols);
|
||||
|
||||
result->bindVars(*this, staticEnv);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DocComment EvalState::getDocCommentForPos(PosIdx pos)
|
||||
{
|
||||
auto pos2 = positions[pos];
|
||||
auto path = pos2.getSourcePath();
|
||||
if (!path)
|
||||
return {};
|
||||
|
||||
auto table = positionToDocComment.find(*path);
|
||||
if (table == positionToDocComment.end())
|
||||
return {};
|
||||
|
||||
auto it = table->second.find(pos);
|
||||
if (it == table->second.end())
|
||||
return {};
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::string ExternalValueBase::coerceToString(EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -130,6 +130,8 @@ struct Constant
|
|||
typedef std::map<std::string, Value *> ValMap;
|
||||
#endif
|
||||
|
||||
typedef std::map<PosIdx, DocComment> DocCommentMap;
|
||||
|
||||
struct Env
|
||||
{
|
||||
Env * up;
|
||||
|
|
@ -329,6 +331,12 @@ private:
|
|||
#endif
|
||||
FileEvalCache fileEvalCache;
|
||||
|
||||
/**
|
||||
* Associate source positions of certain AST nodes with their preceding doc comment, if they have one.
|
||||
* Grouped by file.
|
||||
*/
|
||||
std::map<SourcePath, DocCommentMap> positionToDocComment;
|
||||
|
||||
LookupPath lookupPath;
|
||||
|
||||
std::map<std::string, std::optional<std::string>> lookupPathResolved;
|
||||
|
|
@ -771,6 +779,8 @@ public:
|
|||
std::string_view pathArg,
|
||||
PosIdx pos);
|
||||
|
||||
DocComment getDocCommentForPos(PosIdx pos);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -202,6 +202,17 @@ struct ExprSelect : Expr
|
|||
ExprSelect(const PosIdx & pos, Expr * e, AttrPath attrPath, Expr * def) : pos(pos), e(e), def(def), attrPath(std::move(attrPath)) { };
|
||||
ExprSelect(const PosIdx & pos, Expr * e, Symbol name) : pos(pos), e(e), def(0) { attrPath.push_back(AttrName(name)); };
|
||||
PosIdx getPos() const override { return pos; }
|
||||
|
||||
/**
|
||||
* Evaluate the `a.b.c` part of `a.b.c.d`. This exists mostly for the purpose of :doc in the repl.
|
||||
*
|
||||
* @param[out] v The attribute set that should contain the last attribute name (if it exists).
|
||||
* @return The last attribute name in `attrPath`
|
||||
*
|
||||
* @note This does *not* evaluate the final attribute, and does not fail if that's the only attribute that does not exist.
|
||||
*/
|
||||
Symbol evalExceptFinalSelect(EvalState & state, Env & env, Value & attrs);
|
||||
|
||||
COMMON_METHODS
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ struct LexerState
|
|||
/**
|
||||
* @brief Maps some positions to a DocComment, where the comment is relevant to the location.
|
||||
*/
|
||||
std::map<PosIdx, DocComment> positionToDocComment;
|
||||
std::map<PosIdx, DocComment> & positionToDocComment;
|
||||
|
||||
PosTable & positions;
|
||||
PosTable::Origin origin;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
typedef std::map<PosIdx, DocComment> DocCommentMap;
|
||||
|
||||
Expr * parseExprFromBuf(
|
||||
char * text,
|
||||
size_t length,
|
||||
|
|
@ -41,6 +43,7 @@ Expr * parseExprFromBuf(
|
|||
SymbolTable & symbols,
|
||||
const EvalSettings & settings,
|
||||
PosTable & positions,
|
||||
DocCommentMap & docComments,
|
||||
const ref<SourceAccessor> rootFS,
|
||||
const Expr::AstSymbols & astSymbols);
|
||||
|
||||
|
|
@ -335,10 +338,12 @@ binds
|
|||
$$ = $1;
|
||||
|
||||
auto pos = state->at(@2);
|
||||
auto exprPos = state->at(@4);
|
||||
{
|
||||
auto it = state->lexerState.positionToDocComment.find(pos);
|
||||
if (it != state->lexerState.positionToDocComment.end()) {
|
||||
$4->setDocComment(it->second);
|
||||
state->lexerState.positionToDocComment.emplace(exprPos, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -463,11 +468,13 @@ Expr * parseExprFromBuf(
|
|||
SymbolTable & symbols,
|
||||
const EvalSettings & settings,
|
||||
PosTable & positions,
|
||||
DocCommentMap & docComments,
|
||||
const ref<SourceAccessor> rootFS,
|
||||
const Expr::AstSymbols & astSymbols)
|
||||
{
|
||||
yyscan_t scanner;
|
||||
LexerState lexerState {
|
||||
.positionToDocComment = docComments,
|
||||
.positions = positions,
|
||||
.origin = positions.addOrigin(origin, length),
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue