LLVM: lib/Support/LSP/Protocol.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
21
22using namespace llvm;
24
25
26template
32
33
34 auto *V = O->get(Prop);
35 if (!V || V->getAsNull())
36 return true;
37 return fromJSON(*V, Out, Path.field(Prop));
38}
39
40
41
42
43
45
46
47
48
49
51 return Path.size() > 1 && llvm::isAlpha(Path[0]) && Path[1] == ':';
52}
53
55 return Path.size() > 2 && Path[0] == Path[1] &&
57}
58
60
61 if ((C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') ||
63 return false;
64
65 switch (C) {
66 case '-':
67 case '_':
68 case '.':
69 case '~':
70
71 case '/':
72
73 case ':':
74 return false;
75 }
76 return true;
77}
78
79
80
81
82
84 for (unsigned char C : Content) {
86 Out.push_back('%');
89 } else {
90 Out.push_back(C);
91 }
92 }
93}
94
95
97 std::string Result;
98 for (auto I = Content.begin(), E = Content.end(); I != E; ++I) {
102 I += 2;
103 } else {
104 Result.push_back(*I);
105 }
106 }
107 return Result;
108}
109
110
112 static StringSet<> Schemes({"file", "test"});
113 return Schemes;
114}
115
116
117
118
120 if (Scheme.empty())
121 return false;
123 return false;
126 });
127}
128
131 std::string Body;
135
139
140 Body = "/";
141 }
143
144 std::string Uri = Scheme.str() + ":";
145 if (Authority.empty() && Body.empty())
146 return Uri;
147
148
149
151 Uri.append("//");
153 }
155 return Uri;
156}
157
163 "File scheme: expect body to be an absolute path starting "
164 "with '/': " +
165 Body);
167 if (!Authority.empty()) {
168
169 ("//" + Authority).toVector(Path);
171
173 }
174 Path.append(Body);
176 return std::string(Path);
177}
178
181
182
183 size_t Pos = Uri.find(':');
186 "Scheme must be provided in URI: " +
187 OrigUri);
189 std::string UriScheme = percentDecode(SchemeStr);
192 "Invalid scheme: " + SchemeStr +
193 " (decoded: " + UriScheme + ")");
194 Uri = Uri.substr(Pos + 1);
195
196
197 std::string UriAuthority;
199 Pos = Uri.find('/');
201 Uri = Uri.substr(Pos);
202 }
203
204
206
207
210 "unsupported URI scheme `" + UriScheme +
211 "' for workspace files");
212 }
214}
215
218 if (!FilePath)
220 return URIForFile(std::move(*FilePath), Uri.str());
221}
222
231
233
237
240 if (std::optional Str = Value.getAsString()) {
242 if (!ExpectedUri) {
243 Path.report("unresolvable URI");
245 return false;
246 }
247 Result = std::move(*ExpectedUri);
248 return true;
249 }
250 return false;
251}
252
254 return Value.uri();
255}
256
258 return Os << Value.uri();
259}
260
261
262
263
264
268 if (!O) {
269 Path.report("expected object");
270 return false;
271 }
272 if (const llvm::json::Object *TextDocument = O->getObject("textDocument")) {
274 TextDocument->getObject("documentSymbol")) {
275 if (std::optional HierarchicalSupport =
276 DocumentSymbol->getBoolean("hierarchicalDocumentSymbolSupport"))
277 Result.hierarchicalDocumentSymbol = *HierarchicalSupport;
278 }
279 if (auto *CodeAction = TextDocument->getObject("codeAction")) {
280 if (CodeAction->getObject("codeActionLiteralSupport"))
281 Result.codeActionStructure = true;
282 }
283 }
284 if (auto *Window = O->getObject("window")) {
285 if (std::optional WorkDoneProgressSupport =
286 Window->getBoolean("workDoneProgress"))
287 Result.workDoneProgress = *WorkDoneProgressSupport;
288 }
289 return true;
290}
291
292
293
294
295
299 if (!O || !O.map("name", Result.name))
300 return false;
301
302
303 O.map("version", Result.version);
304 return true;
305}
306
307
308
309
310
313 if (std::optional Str = Value.getAsString()) {
314 if (*Str == "off") {
316 return true;
317 }
318 if (*Str == "messages") {
320 return true;
321 }
322 if (*Str == "verbose") {
324 return true;
325 }
326 }
327 return false;
328}
329
333 if (!O)
334 return false;
335
336 O.map("capabilities", Result.capabilities);
337 O.map("trace", Result.trace);
339
340 return true;
341}
342
343
344
345
346
350 return O && O.map("uri", Result.uri) &&
351 O.map("languageId", Result.languageId) && O.map("text", Result.text) &&
352 O.map("version", Result.version);
353}
354
355
356
357
358
362
367 return O && O.map("uri", Result.uri);
368}
369
370
371
372
373
377 {"uri", Value.uri},
378 {"version", Value.version},
379 };
380}
381
386 return O && O.map("uri", Result.uri) && O.map("version", Result.version);
387}
388
389
390
391
392
396 return O && O.map("line", Result.line) &&
397 O.map("character", Result.character);
398}
399
402 {"line", Value.line},
403 {"character", Value.character},
404 };
405}
406
408 return Os << Value.line << ':' << Value.character;
409}
410
411
412
413
414
418 return O && O.map("start", Result.start) && O.map("end", Result.end);
419}
420
423 {"start", Value.start},
424 {"end", Value.end},
425 };
426}
427
429 return Os << Value.start << '-' << Value.end;
430}
431
432
433
434
435
439 return O && O.map("uri", Result.uri) && O.map("range", Result.range);
440}
441
444 {"uri", Value.uri},
445 {"range", Value.range},
446 };
447}
448
450 return Os << Value.range << '@' << Value.uri;
451}
452
453
454
455
456
461 return O && O.map("textDocument", Result.textDocument) &&
462 O.map("position", Result.position);
463}
464
465
466
467
468
472 return O && O.mapOptional("includeDeclaration", Result.includeDeclaration);
473}
474
480 O.mapOptional("context", Result.context);
481}
482
483
484
485
486
491 return O && O.map("textDocument", Result.textDocument);
492}
493
494
495
496
497
502 return O && O.map("textDocument", Result.textDocument);
503}
504
505
506
507
508
511
513 Contents = text;
515 }
516
517
521 SMRange RangeLoc = range->getAsSMRange(TmpScrMgr);
524
525 Contents.replace(RangeLoc.Start.getPointer() - Contents.data(),
529}
530
533 for (const auto &Change : Changes)
534 if (failed(Change.applyTo(Contents)))
537}
538
543 return O && O.map("range", Result.range) &&
544 O.map("rangeLength", Result.rangeLength) && O.map("text", Result.text);
545}
546
551 return O && O.map("textDocument", Result.textDocument) &&
552 O.map("contentChanges", Result.contentChanges);
553}
554
555
556
557
558
560 switch (Kind) {
562 return "plaintext";
564 return "markdown";
565 }
567}
568
572
574 if (Mc.value.empty())
575 return nullptr;
576
579 {"value", Mc.value},
580 };
581}
582
583
584
585
586
591 return std::move(Result);
592}
593
594
595
596
597
600 {"kind", static_cast<int>(Symbol.kind)},
601 {"range", Symbol.range},
602 {"selectionRange", Symbol.selectionRange}};
603
604 if (!Symbol.detail.empty())
605 Result["detail"] = Symbol.detail;
606 if (!Symbol.children.empty())
607 Result["children"] = Symbol.children;
608 return std::move(Result);
609}
610
611
612
613
614
618 return O && O.map("textDocument", Result.textDocument);
619}
620
621
622
623
624
629 return O && O.map("location", Result.location) &&
630 O.map("message", Result.message);
631}
632
635 {"location", Info.location},
636 {"message", Info.message},
637 };
638}
639
640
641
642
643
645 return static_cast<int>(Tag);
646}
647
650 if (std::optional<int64_t> I = Value.getAsInteger()) {
652 return true;
653 }
654
655 return false;
656}
657
660 {"range", Diag.range},
661 {"severity", (int)Diag.severity},
662 {"message", Diag.message},
663 };
665 Result["category"] = *Diag.category;
666 if (!Diag.source.empty())
667 Result["source"] = Diag.source;
670 if (!Diag.tags.empty())
671 Result["tags"] = Diag.tags;
672 return std::move(Result);
673}
674
678 if (!O)
679 return false;
680 int Severity = 0;
682 return false;
684
685 return O.map("range", Result.range) && O.map("message", Result.message) &&
688 mapOptOrNull(Value, "relatedInformation", Result.relatedInformation,
689 Path) &&
691}
692
693
694
695
696
699 {"uri", Params.uri},
701 {"version", Params.version},
702 };
703}
704
705
706
707
708
712 return O && O.map("range", Result.range) && O.map("newText", Result.newText);
713}
714
717 {"range", Value.range},
718 {"newText", Value.newText},
719 };
720}
721
723 Os << Value.range << " => \"";
725 return Os << '"';
726}
727
728
729
730
731
734 if (std::optional<int64_t> IntValue = Value.getAsInteger()) {
737 return false;
739 return true;
740 }
741 return false;
742}
743
747 size_t KindVal = static_cast<size_t>(Kind);
749 KindVal <= SupportedCompletionItemKinds.size() &&
750 SupportedCompletionItemKinds[KindVal])
751 return Kind;
752
753
754 switch (Kind) {
761 default:
763 }
764}
765
770 for (size_t I = 0, E = ArrayValue->size(); I < E; ++I) {
772 if (fromJSON((*ArrayValue)[I], KindOut, Path.index(I)))
773 Result.set(size_t(KindOut));
774 }
775 return true;
776 }
777 return false;
778}
779
780
781
782
783
785 assert(.label.empty() && "completion item label is required");
788 Result["kind"] = static_cast<int>(Value.kind);
789 if (.detail.empty())
790 Result["detail"] = Value.detail;
791 if (Value.documentation)
792 Result["documentation"] = Value.documentation;
793 if (.sortText.empty())
794 Result["sortText"] = Value.sortText;
795 if (.filterText.empty())
796 Result["filterText"] = Value.filterText;
797 if (.insertText.empty())
798 Result["insertText"] = Value.insertText;
800 Result["insertTextFormat"] = static_cast<int>(Value.insertTextFormat);
801 if (Value.textEdit)
802 Result["textEdit"] = *Value.textEdit;
803 if (.additionalTextEdits.empty()) {
804 Result["additionalTextEdits"] =
806 }
807 if (Value.deprecated)
808 Result["deprecated"] = Value.deprecated;
809 return std::move(Result);
810}
811
816
822
823
824
825
826
829 {"isIncomplete", Value.isIncomplete},
831 };
832}
833
834
835
836
837
841 int TriggerKind;
842 if (!O || !O.map("triggerKind", TriggerKind) ||
843 (Value, "triggerCharacter", Result.triggerCharacter, Path))
844 return false;
846 return true;
847}
848
849
850
851
852
856 return false;
858 return fromJSON(*Context, Result.context, Path.field("context"));
859 return true;
860}
861
862
863
864
865
868 "parameter information label is required");
870 if (Value.labelOffsets)
872 {Value.labelOffsets->first, Value.labelOffsets->second});
873 else
874 Result["label"] = Value.labelString;
875 if (.documentation.empty())
876 Result["documentation"] = Value.documentation;
877 return std::move(Result);
878}
879
880
881
882
883
885 assert(.label.empty() && "signature information label is required");
887 {"label", Value.label},
889 };
890 if (.documentation.empty())
891 Result["documentation"] = Value.documentation;
892 return std::move(Result);
893}
894
899
900
901
902
903
906 "Unexpected negative value for number of active signatures.");
908 "Unexpected negative value for active parameter index");
910 {"activeSignature", Value.activeSignature},
911 {"activeParameter", Value.activeParameter},
913 };
914}
915
916
917
918
919
923 return O && O.map("textDocument", Result.textDocument);
924}
925
926
927
928
929
932 {"range", Value.range},
933 {"target", Value.target},
934 };
935}
936
937
938
939
940
944 return O && O.map("textDocument", Result.textDocument) &&
945 O.map("range", Result.range);
946}
947
948
949
950
951
954 {"kind", (int)Value.kind},
955 {"label", Value.label},
956 {"paddingLeft", Value.paddingLeft},
957 {"paddingRight", Value.paddingRight}};
958}
967
972 return Os << "parameter";
974 return Os << "type";
975 }
977}
978
979
980
981
982
986 if (!O || !O.map("diagnostics", Result.diagnostics))
987 return false;
988 O.map("only", Result.only);
989 return true;
990}
991
992
993
994
995
999 return O && O.map("textDocument", Result.textDocument) &&
1000 O.map("range", Result.range) && O.map("context", Result.context);
1001}
1002
1003
1004
1005
1006
1010 return O && O.map("changes", Result.changes);
1011}
1012
1015 for (auto &Change : Value.changes)
1018}
1019
1020
1021
1022
1023
1027
1032 if (Value.diagnostics)
1034 if (Value.isPreferred)
1039}
1040
1041
1042
1043
1044
1047 {"type", static_cast<int>(Params.type)},
1048 {"message", Params.message},
1049 };
1051 Out["actions"] = *Params.actions;
1052 return Out;
1053}
1054
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file supports working with JSON data.
static bool isWindowsPath(StringRef Path)
Definition Protocol.cpp:50
static void percentEncode(StringRef Content, std::string &Out)
Encodes a string according to percent-encoding.
Definition Protocol.cpp:83
static std::string percentDecode(StringRef Content)
Decodes a string according to percent-encoding.
Definition Protocol.cpp:96
static bool isNetworkPath(StringRef Path)
Definition Protocol.cpp:54
static llvm::Expected< std::string > parseFilePathFromURI(StringRef OrigUri)
Definition Protocol.cpp:179
static bool isStructurallyValidScheme(StringRef Scheme)
Returns true if the given scheme is structurally valid, i.e.
Definition Protocol.cpp:119
static bool shouldEscapeInURI(unsigned char C)
Definition Protocol.cpp:59
static llvm::Expected< std::string > uriFromAbsolutePath(StringRef AbsolutePath, StringRef Scheme)
Definition Protocol.cpp:129
static StringSet & getSupportedSchemes()
Return the set containing the supported URI schemes.
Definition Protocol.cpp:111
static bool mapOptOrNull(const llvm::json::Value &Params, llvm::StringLiteral Prop, T &Out, llvm::json::Path Path)
Definition Protocol.cpp:27
static llvm::Expected< std::string > getAbsolutePath(StringRef Authority, StringRef Body)
Definition Protocol.cpp:158
static llvm::StringRef toTextKind(MarkupKind Kind)
Definition Protocol.cpp:559
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
StringSet - A set-like wrapper for the StringMap.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
Represents a location in source code.
constexpr const char * getPointer() const
Represents a range in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
A wrapper around a string literal that serves as a proxy for constructing global tables of StringRefs...
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
static constexpr size_t npos
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
StringSet - A wrapper for StringMap that provides set-like functionality.
std::pair< typename Base::iterator, bool > insert(StringRef key)
An Array is a JSON array, which contains heterogeneous JSON values.
Helper for mapping JSON objects onto protocol structs.
An Object is a JSON object, which maps strings to heterogenous JSON values.
A "cursor" marking a position within a Value.
A Value is an JSON value of unknown type.
const json::Object * getAsObject() const
static LLVM_ABI_FOR_TEST char ID
URI in "file" scheme for a file.
static void registerSupportedScheme(StringRef scheme)
Register a supported URI scheme.
Definition Protocol.cpp:234
static llvm::Expected< URIForFile > fromFile(StringRef absoluteFilepath, StringRef scheme="file")
Try to build a URIForFile from the given absolute file path and optional scheme.
Definition Protocol.cpp:223
static llvm::Expected< URIForFile > fromURI(StringRef uri)
Try to build a URIForFile from the given URI string.
Definition Protocol.cpp:216
StringRef scheme() const
Return the scheme of the uri.
Definition Protocol.cpp:232
StringRef uri() const
Returns the original uri of the file.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
constexpr auto kCompletionItemKindMin
MarkupKind
Describes the content type that a client supports in various result literals like Hover.
LLVM_ABI_FOR_TEST llvm::json::Value toJSON(const URIForFile &value)
Add support for JSON serialization.
Definition Protocol.cpp:253
bool operator<(const CompletionItem &lhs, const CompletionItem &rhs)
Definition Protocol.cpp:817
bool operator==(const TextEdit &lhs, const TextEdit &rhs)
raw_ostream & operator<<(raw_ostream &os, const URIForFile &value)
Definition Protocol.cpp:257
CompletionItemKind adjustKindToCapability(CompletionItemKind kind, CompletionItemKindBitset &supportedCompletionItemKinds)
Definition Protocol.cpp:744
InlayHintKind
Inlay hint kinds.
@ Parameter
An inlay hint that is for a parameter.
@ Type
An inlay hint that for a type annotation.
std::bitset< kCompletionItemKindMax+1 > CompletionItemKindBitset
CompletionItemKind
The kind of a completion entry.
LLVM_ABI_FOR_TEST bool fromJSON(const llvm::json::Value &value, URIForFile &result, llvm::json::Path path)
Definition Protocol.cpp:238
LLVM_ABI std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
LLVM_ABI StringRef root_name(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get root name.
LLVM_ABI bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
bool failed(LogicalResult Result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
LogicalResult failure(bool IsFailure=true)
Utility function to generate a LogicalResult.
LLVM_ABI void printEscapedString(StringRef Name, raw_ostream &Out)
Print each character of the specified string, escaping it if it is not printable or if it is an escap...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
bool isAlpha(char C)
Checks if character C is a valid letter as classified by "C" locale.
uint8_t hexFromNibbles(char MSB, char LSB)
Return the binary representation of the two provided values, MSB and LSB, that make up the nibbles of...
char hexdigit(unsigned X, bool LowerCase=false)
hexdigit - Return the hexadecimal character for the given number X (which should be less than 16).
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
bool isHexDigit(char C)
Checks if character C is a hexadecimal numeric character.
void consumeError(Error Err)
Consume a Error without doing anything.
This class represents an efficient way to signal success or failure.
A code action represents a change that can be performed in code, e.g.
static const llvm::StringLiteral kRefactor
static const llvm::StringLiteral kInfo
static const llvm::StringLiteral kQuickFix
std::string label
The label of this completion item.
std::string sortText
A string that should be used when comparing this item with other items.
Represents a collection of completion items to be presented in the editor.
std::vector< DiagnosticTag > tags
Additional metadata about the diagnostic.
std::string message
The diagnostic's message.
Range range
The source range where the message applies.
std::optional< std::vector< DiagnosticRelatedInformation > > relatedInformation
An array of related diagnostic information, e.g.
std::string source
A human-readable string describing the source of this diagnostic, e.g.
DiagnosticSeverity severity
The diagnostic's severity.
std::optional< std::string > category
The diagnostic's category.
Parameters for the document link request.
A range in a text document that links to an internal or external resource, like another text document...
Represents programming constructs like variables, classes, interfaces etc.
std::optional< Range > range
An optional range is a range inside a text document that is used to visualize a hover,...
MarkupContent contents
The hover's content.
InlayHintKind kind
The kind of this hint.
std::string label
The label of this hint.
Position position
The position of this hint.
A parameter literal used in inlay hint requests.
std::string title
A short title like 'Retry', 'Open Log' etc.
A single parameter of a particular signature.
URIForFile uri
The URI for which diagnostic information is reported.
int64_t version
The version number of the document the diagnostics are published for.
std::vector< Diagnostic > diagnostics
The list of reported diagnostics.
std::string message
The actual message.
std::optional< std::vector< MessageActionItem > > actions
The message action items to present.
Represents the signature of a callable.
Represents the signature of something callable.
std::optional< Range > range
The range of the document that changed.
LogicalResult applyTo(std::string &contents) const
Try to apply this change to the given contents string.
Definition Protocol.cpp:510
std::string text
The new text of the range/document.