nixd
Loading...
Searching...
No Matches
ConvertToInherit.cpp
Go to the documentation of this file.
1/// \file
2/// \brief Implementation of convert to inherit code action.
3
4#include "ConvertToInherit.h"
5#include "Utils.h"
6
7#include "../Convert.h"
8
12
13namespace nixd {
14
17 const std::string &FileURI, llvm::StringRef Src,
18 std::vector<lspserver::CodeAction> &Actions) {
19 // Find if we're inside a Binding node
20 const nixf::Node *BindingNode = PM.upTo(N, nixf::Node::NK_Binding);
21 if (!BindingNode)
22 return;
23
24 const auto &Bind = static_cast<const nixf::Binding &>(*BindingNode);
25
26 // Must have a single-segment path
27 const auto &Names = Bind.path().names();
28 if (Names.size() != 1)
29 return;
30
31 // Path must be static (not interpolated)
32 const auto &AttrNameNode = Names[0];
33 if (!AttrNameNode || !AttrNameNode->isStatic())
34 return;
35
36 const std::string &AttrName = AttrNameNode->staticName();
37
38 // Must have a value
39 if (!Bind.value())
40 return;
41
42 const nixf::Expr &Value = *Bind.value();
43
44 // Case 1: { x = x; } -> { inherit x; }
45 if (Value.kind() == nixf::Node::NK_ExprVar) {
46 const auto &Var = static_cast<const nixf::ExprVar &>(Value);
47 if (Var.id().name() == AttrName) {
48 std::string NewText = "inherit " + quoteNixAttrKey(AttrName) + ";";
49 Actions.emplace_back(createSingleEditAction(
51 FileURI, toLSPRange(Src, Bind.range()), std::move(NewText)));
52 }
53 return;
54 }
55
56 // Case 2: { a = source.a; } -> { inherit (source) a; }
57 // Also handles { a = lib.nested.a; } -> { inherit (lib.nested) a; }
58 if (Value.kind() == nixf::Node::NK_ExprSelect) {
59 const auto &Sel = static_cast<const nixf::ExprSelect &>(Value);
60
61 // Must not have a default value
62 if (Sel.defaultExpr())
63 return;
64
65 // Must have a path
66 if (!Sel.path())
67 return;
68
69 // Selector path must have at least one segment
70 const auto &SelPath = Sel.path()->names();
71 if (SelPath.empty())
72 return;
73
74 // The last segment must be static and match the attribute name
75 const auto &LastSegment = SelPath.back();
76 if (!LastSegment || !LastSegment->isStatic())
77 return;
78
79 if (LastSegment->staticName() != AttrName)
80 return;
81
82 // Build the source expression text:
83 // - Start with the base expression (e.g., "lib" from lib.nested.x)
84 // - Add any intermediate path segments (e.g., ".nested")
85 const nixf::Expr &BaseExpr = Sel.expr();
86 std::string SourceText =
87 Src.slice(BaseExpr.lCur().offset(), BaseExpr.rCur().offset()).str();
88
89 // Add intermediate path segments (all except the last one)
90 for (size_t I = 0; I + 1 < SelPath.size(); ++I) {
91 const auto &Segment = SelPath[I];
92 if (!Segment || !Segment->isStatic())
93 return; // Bail out if any intermediate segment is dynamic
94 SourceText += ".";
95 SourceText += quoteNixAttrKey(Segment->staticName());
96 }
97
98 std::string NewText =
99 "inherit (" + SourceText + ") " + quoteNixAttrKey(AttrName) + ";";
100 Actions.emplace_back(createSingleEditAction(
101 "Convert to `inherit (" + SourceText + ")`",
103 toLSPRange(Src, Bind.range()), std::move(NewText)));
104 }
105}
106
107} // namespace nixd
Code action for converting bindings to inherit syntax.
Convert between LSP and nixf types.
Shared utilities for code actions.
const std::vector< std::shared_ptr< AttrName > > & names() const
Definition Attrs.h:100
const AttrPath & path() const
Definition Attrs.h:131
AttrPath * path() const
Definition Expr.h:31
std::size_t offset() const
Offset in the source file, starting from 0.
Definition Range.h:102
LexerCursor lCur() const
Definition Basic.h:37
LexerCursor rCur() const
Definition Basic.h:38
const Node * upTo(const Node &N, Node::NodeKind Kind) const
Search up until some kind of node is found.
Definition ParentMap.cpp:27
void addConvertToInheritAction(const nixf::Node &N, const nixf::ParentMapAnalysis &PM, const std::string &FileURI, llvm::StringRef Src, std::vector< lspserver::CodeAction > &Actions)
Add code action to convert binding to inherit syntax.
lspserver::CodeAction createSingleEditAction(const std::string &Title, llvm::StringLiteral Kind, const std::string &FileURI, const lspserver::Range &EditRange, std::string NewText)
Create a CodeAction with a single text edit.
Definition Utils.cpp:10
lspserver::Range toLSPRange(llvm::StringRef Code, const nixf::LexerCursorRange &R)
Definition Convert.cpp:40
std::string quoteNixAttrKey(const std::string &Key)
Quote and escape a Nix attribute key if necessary.
Definition Utils.cpp:89
static const llvm::StringLiteral REFACTOR_REWRITE_KIND