Author: ibiryukov Date: Thu Apr 25 03:08:31 2019 New Revision: 359179 URL: http://llvm.org/viewvc/llvm-project?rev=359179&view=rev Log: [Testing] Move clangd::Annotations to llvm testing support
Summary: Annotations allow writing nice-looking unit test code when one needs access to locations from the source code, e.g. running code completion at particular offsets in a file. See comments in Annotations.cpp for more details on the API. Also got rid of a duplicate annotations parsing code in clang's code complete tests. Reviewers: gribozavr, sammccall Reviewed By: gribozavr Subscribers: mgorny, hiraditya, ioeric, MaskRay, jkorous, arphaman, kadircet, jdoerfert, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D59814 Modified: clang-tools-extra/trunk/unittests/clangd/Annotations.cpp clang-tools-extra/trunk/unittests/clangd/Annotations.h Modified: clang-tools-extra/trunk/unittests/clangd/Annotations.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/Annotations.cpp?rev=359179&r1=359178&r2=359179&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clangd/Annotations.cpp (original) +++ clang-tools-extra/trunk/unittests/clangd/Annotations.cpp Thu Apr 25 03:08:31 2019 @@ -12,74 +12,41 @@ namespace clang { namespace clangd { -// Crash if the assertion fails, printing the message and testcase. -// More elegant error handling isn't needed for unit tests. -static void require(bool Assertion, const char *Msg, llvm::StringRef Code) { - if (!Assertion) { - llvm::errs() << "Annotated testcase: " << Msg << "\n" << Code << "\n"; - llvm_unreachable("Annotated testcase assertion failed!"); - } +Position Annotations::point(llvm::StringRef Name) const { + return offsetToPosition(code(), Base::point(Name)); } -Annotations::Annotations(llvm::StringRef Text) { - auto Here = [this] { return offsetToPosition(Code, Code.size()); }; - auto Require = [Text](bool Assertion, const char *Msg) { - require(Assertion, Msg, Text); - }; - llvm::Optional<llvm::StringRef> Name; - llvm::SmallVector<std::pair<llvm::StringRef, Position>, 8> OpenRanges; - - Code.reserve(Text.size()); - while (!Text.empty()) { - if (Text.consume_front("^")) { - Points[Name.getValueOr("")].push_back(Here()); - Name = None; - continue; - } - if (Text.consume_front("[[")) { - OpenRanges.emplace_back(Name.getValueOr(""), Here()); - Name = None; - continue; - } - Require(!Name, "$name should be followed by ^ or [["); - if (Text.consume_front("]]")) { - Require(!OpenRanges.empty(), "unmatched ]]"); - Ranges[OpenRanges.back().first].push_back( - {OpenRanges.back().second, Here()}); - OpenRanges.pop_back(); - continue; - } - if (Text.consume_front("$")) { - Name = Text.take_while(llvm::isAlnum); - Text = Text.drop_front(Name->size()); - continue; - } - Code.push_back(Text.front()); - Text = Text.drop_front(); - } - Require(!Name, "unterminated $name"); - Require(OpenRanges.empty(), "unmatched [["); -} +std::vector<Position> Annotations::points(llvm::StringRef Name) const { + auto Offsets = Base::points(Name); -Position Annotations::point(llvm::StringRef Name) const { - auto I = Points.find(Name); - require(I != Points.end() && I->getValue().size() == 1, - "expected exactly one point", Code); - return I->getValue()[0]; + std::vector<Position> Ps; + Ps.reserve(Offsets.size()); + for (size_t O : Offsets) + Ps.push_back(offsetToPosition(code(), O)); + + return Ps; } -std::vector<Position> Annotations::points(llvm::StringRef Name) const { - auto P = Points.lookup(Name); - return {P.begin(), P.end()}; + +static clangd::Range toLSPRange(llvm::StringRef Code, Annotations::Range R) { + clangd::Range LSPRange; + LSPRange.start = offsetToPosition(Code, R.Begin); + LSPRange.end = offsetToPosition(Code, R.End); + return LSPRange; } -Range Annotations::range(llvm::StringRef Name) const { - auto I = Ranges.find(Name); - require(I != Ranges.end() && I->getValue().size() == 1, - "expected exactly one range", Code); - return I->getValue()[0]; + +clangd::Range Annotations::range(llvm::StringRef Name) const { + return toLSPRange(code(), Base::range(Name)); } -std::vector<Range> Annotations::ranges(llvm::StringRef Name) const { - auto R = Ranges.lookup(Name); - return {R.begin(), R.end()}; + +std::vector<clangd::Range> Annotations::ranges(llvm::StringRef Name) const { + auto OffsetRanges = Base::ranges(Name); + + std::vector<clangd::Range> Rs; + Rs.reserve(OffsetRanges.size()); + for (Annotations::Range R : OffsetRanges) + Rs.push_back(toLSPRange(code(), R)); + + return Rs; } } // namespace clangd Modified: clang-tools-extra/trunk/unittests/clangd/Annotations.h URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/Annotations.h?rev=359179&r1=359178&r2=359179&view=diff ============================================================================== --- clang-tools-extra/trunk/unittests/clangd/Annotations.h (original) +++ clang-tools-extra/trunk/unittests/clangd/Annotations.h Thu Apr 25 03:08:31 2019 @@ -5,64 +5,32 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -// -// Annotations lets you mark points and ranges inside source code, for tests: -// -// Annotations Example(R"cpp( -// int complete() { x.pri^ } // ^ indicates a point -// void err() { [["hello" == 42]]; } // [[this is a range]] -// $definition^class Foo{}; // points can be named: "definition" -// $fail[[static_assert(false, "")]] // ranges can be named too: "fail" -// )cpp"); -// -// StringRef Code = Example.code(); // annotations stripped. -// std::vector<Position> PP = Example.points(); // all unnamed points -// Position P = Example.point(); // there must be exactly one -// Range R = Example.range("fail"); // find named ranges -// -// Points/ranges are coordinates into `code()` which is stripped of annotations. -// -// Ranges may be nested (and points can be inside ranges), but there's no way -// to define general overlapping ranges. -// +// A clangd-specific version of llvm/Testing/Support/Annotations.h, replaces +// offsets and offset-based ranges with types from the LSP protocol. //===---------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_ANNOTATIONS_H #define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_ANNOTATIONS_H #include "Protocol.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" +#include "llvm/Testing/Support/Annotations.h" namespace clang { namespace clangd { -class Annotations { -public: - // Parses the annotations from Text. Crashes if it's malformed. - Annotations(llvm::StringRef Text); +/// Same as llvm::Annotations, but adjusts functions to LSP-specific types for +/// positions and ranges. +class Annotations : public llvm::Annotations { + using Base = llvm::Annotations; - // The input text with all annotations stripped. - // All points and ranges are relative to this stripped text. - llvm::StringRef code() const { return Code; } +public: + using llvm::Annotations::Annotations; - // Returns the position of the point marked by ^ (or $name^) in the text. - // Crashes if there isn't exactly one. Position point(llvm::StringRef Name = "") const; - // Returns the position of all points marked by ^ (or $name^) in the text. std::vector<Position> points(llvm::StringRef Name = "") const; - // Returns the location of the range marked by [[ ]] (or $name[[ ]]). - // Crashes if there isn't exactly one. - Range range(llvm::StringRef Name = "") const; - // Returns the location of all ranges marked by [[ ]] (or $name[[ ]]). - std::vector<Range> ranges(llvm::StringRef Name = "") const; - -private: - std::string Code; - llvm::StringMap<llvm::SmallVector<Position, 1>> Points; - llvm::StringMap<llvm::SmallVector<Range, 1>> Ranges; + clangd::Range range(llvm::StringRef Name = "") const; + std::vector<clangd::Range> ranges(llvm::StringRef Name = "") const; }; } // namespace clangd _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits