nixd
Loading...
Searching...
No Matches
Utils.cpp
Go to the documentation of this file.
1/// \file
2/// \brief Implementation of shared utilities for code actions.
3
4#include "Utils.h"
5
6#include <set>
7
8namespace nixd {
9
11 llvm::StringLiteral Kind,
12 const std::string &FileURI,
13 const lspserver::Range &EditRange,
14 std::string NewText) {
15 std::vector<lspserver::TextEdit> Edits;
16 Edits.emplace_back(
17 lspserver::TextEdit{.range = EditRange, .newText = std::move(NewText)});
18 using Changes = std::map<std::string, std::vector<lspserver::TextEdit>>;
19 lspserver::WorkspaceEdit WE{.changes = Changes{{FileURI, std::move(Edits)}}};
21 .title = Title,
22 .kind = std::string(Kind),
23 .edit = std::move(WE),
24 };
25}
26
28createMultiEditAction(const std::string &Title, llvm::StringLiteral Kind,
29 const std::string &FileURI,
30 std::vector<lspserver::TextEdit> Edits) {
31 using Changes = std::map<std::string, std::vector<lspserver::TextEdit>>;
32 lspserver::WorkspaceEdit WE{.changes = Changes{{FileURI, std::move(Edits)}}};
34 .title = Title,
35 .kind = std::string(Kind),
36 .edit = std::move(WE),
37 };
38}
39
40bool isValidNixIdentifier(const std::string &S) {
41 if (S.empty())
42 return false;
43
44 // Check first character: must be letter or underscore
45 char First = S[0];
46 if (!((First >= 'a' && First <= 'z') || (First >= 'A' && First <= 'Z') ||
47 First == '_'))
48 return false;
49
50 // Check remaining characters
51 for (size_t I = 1; I < S.size(); ++I) {
52 char C = S[I];
53 if (!((C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') ||
54 (C >= '0' && C <= '9') || C == '_' || C == '-' || C == '\''))
55 return false;
56 }
57
58 // Check against Nix keywords and reserved literals
59 static const std::set<std::string> Keywords = {
60 "if", "then", "else", "assert", "with", "let", "in",
61 "rec", "inherit", "or", "true", "false", "null"};
62 return Keywords.find(S) == Keywords.end();
63}
64
65std::string escapeNixString(llvm::StringRef S) {
66 std::string Result;
67 Result.reserve(S.size() + S.size() / 4 + 2);
68 for (size_t I = 0; I < S.size(); ++I) {
69 char C = S[I];
70 switch (C) {
71 case '"':
72 Result += "\\\"";
73 break;
74 case '\\':
75 Result += "\\\\";
76 break;
77 case '\n':
78 Result += "\\n";
79 break;
80 case '\r':
81 Result += "\\r";
82 break;
83 case '\t':
84 Result += "\\t";
85 break;
86 case '$':
87 // Only escape ${ to prevent interpolation
88 if (I + 1 < S.size() && S[I + 1] == '{') {
89 Result += "\\${";
90 ++I; // Skip the '{'
91 } else {
92 Result += C;
93 }
94 break;
95 default:
96 Result += C;
97 }
98 }
99 return Result;
100}
101
102std::string quoteNixAttrKey(const std::string &Key) {
104 return Key;
105
106 return "\"" + escapeNixString(Key) + "\"";
107}
108
109} // namespace nixd
Shared utilities for code actions.
bool isValidNixIdentifier(const std::string &S)
Check if a string is a valid Nix identifier that can be unquoted.
Definition Utils.cpp:40
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::CodeAction createMultiEditAction(const std::string &Title, llvm::StringLiteral Kind, const std::string &FileURI, std::vector< lspserver::TextEdit > Edits)
Create a CodeAction with multiple text edits applied as one.
Definition Utils.cpp:28
std::string escapeNixString(llvm::StringRef S)
Escape special characters for Nix double-quoted string literals.
Definition Utils.cpp:65
std::string quoteNixAttrKey(const std::string &Key)
Quote and escape a Nix attribute key if necessary.
Definition Utils.cpp:102