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') ||

62 (C >= '0' && C <= '9'))

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(Value.label.empty() && "completion item label is required");

788 Result["kind"] = static_cast<int>(Value.kind);

789 if (Value.detail.empty())

790 Result["detail"] = Value.detail;

791 if (Value.documentation)

792 Result["documentation"] = Value.documentation;

793 if (Value.sortText.empty())

794 Result["sortText"] = Value.sortText;

795 if (Value.filterText.empty())

796 Result["filterText"] = Value.filterText;

797 if (Value.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 (Value.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 mapOptOrNull(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 (Value.documentation.empty())

876 Result["documentation"] = Value.documentation;

877 return std::move(Result);

878}

879

880

881

882

883

885 assert(Value.label.empty() && "signature information label is required");

887 {"label", Value.label},

889 };

890 if (Value.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.