brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.7 KiB · 1e68526 Raw
179 lines · cpp
1//===--- Annotations.cpp - Annotated source code for unit tests --*- C++-*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Testing/Annotations/Annotations.h"10 11#include "llvm/ADT/StringExtras.h"12#include "llvm/Support/FormatVariadic.h"13#include "llvm/Support/raw_ostream.h"14 15using namespace llvm;16 17// Crash if the assertion fails, printing the message and testcase.18// More elegant error handling isn't needed for unit tests.19static void require(bool Assertion, const char *Msg, llvm::StringRef Code) {20  if (!Assertion) {21    llvm::errs() << "Annotated testcase: " << Msg << "\n" << Code << "\n";22    llvm_unreachable("Annotated testcase assertion failed!");23  }24}25 26Annotations::Annotations(llvm::StringRef Text) {27  auto Require = [Text](bool Assertion, const char *Msg) {28    require(Assertion, Msg, Text);29  };30  std::optional<llvm::StringRef> Name;31  std::optional<llvm::StringRef> Payload;32  llvm::SmallVector<Annotation, 8> OpenRanges;33 34  Code.reserve(Text.size());35  while (!Text.empty()) {36    if (Text.consume_front("^")) {37      All.push_back(38          {Code.size(), size_t(-1), Name.value_or(""), Payload.value_or("")});39      Points[Name.value_or("")].push_back(All.size() - 1);40      Name = std::nullopt;41      Payload = std::nullopt;42      continue;43    }44    if (Text.consume_front("[[")) {45      OpenRanges.push_back(46          {Code.size(), size_t(-1), Name.value_or(""), Payload.value_or("")});47      Name = std::nullopt;48      Payload = std::nullopt;49      continue;50    }51    Require(!Name, "$name should be followed by ^ or [[");52    if (Text.consume_front("]]")) {53      Require(!OpenRanges.empty(), "unmatched ]]");54 55      const Annotation &NewRange = OpenRanges.back();56      All.push_back(57          {NewRange.Begin, Code.size(), NewRange.Name, NewRange.Payload});58      Ranges[NewRange.Name].push_back(All.size() - 1);59 60      OpenRanges.pop_back();61      continue;62    }63    if (Text.consume_front("$")) {64      Name =65          Text.take_while([](char C) { return llvm::isAlnum(C) || C == '_'; });66      Text = Text.drop_front(Name->size());67 68      if (Text.consume_front("(")) {69        Payload = Text.take_while([](char C) { return C != ')'; });70        Require(Text.size() > Payload->size(), "unterminated payload");71        Text = Text.drop_front(Payload->size() + 1);72      }73 74      continue;75    }76    Code.push_back(Text.front());77    Text = Text.drop_front();78  }79  Require(!Name, "unterminated $name");80  Require(OpenRanges.empty(), "unmatched [[");81}82 83size_t Annotations::point(llvm::StringRef Name) const {84  return pointWithPayload(Name).first;85}86 87std::pair<size_t, llvm::StringRef>88Annotations::pointWithPayload(llvm::StringRef Name) const {89  auto I = Points.find(Name);90  require(I != Points.end() && I->getValue().size() == 1,91          "expected exactly one point", Code);92  const Annotation &P = All[I->getValue()[0]];93  return {P.Begin, P.Payload};94}95 96std::vector<size_t> Annotations::points(llvm::StringRef Name) const {97  auto Pts = pointsWithPayload(Name);98  std::vector<size_t> Positions;99  Positions.reserve(Pts.size());100  for (const auto &[Point, Payload] : Pts)101    Positions.push_back(Point);102  return Positions;103}104 105std::vector<std::pair<size_t, llvm::StringRef>>106Annotations::pointsWithPayload(llvm::StringRef Name) const {107  auto Iter = Points.find(Name);108  if (Iter == Points.end())109    return {};110 111  std::vector<std::pair<size_t, llvm::StringRef>> Res;112  Res.reserve(Iter->getValue().size());113  for (size_t I : Iter->getValue())114    Res.push_back({All[I].Begin, All[I].Payload});115 116  return Res;117}118 119llvm::StringMap<llvm::SmallVector<size_t, 1>> Annotations::all_points() const {120  llvm::StringMap<llvm::SmallVector<size_t, 1>> Result;121  for (const auto &Name : Points.keys()) {122    auto Pts = points(Name);123    Result[Name] = {Pts.begin(), Pts.end()};124  }125  return Result;126}127 128Annotations::Range Annotations::range(llvm::StringRef Name) const {129  return rangeWithPayload(Name).first;130}131 132std::pair<Annotations::Range, llvm::StringRef>133Annotations::rangeWithPayload(llvm::StringRef Name) const {134  auto I = Ranges.find(Name);135  require(I != Ranges.end() && I->getValue().size() == 1,136          "expected exactly one range", Code);137  const Annotation &R = All[I->getValue()[0]];138  return {{R.Begin, R.End}, R.Payload};139}140 141std::vector<Annotations::Range>142Annotations::ranges(llvm::StringRef Name) const {143  auto WithPayload = rangesWithPayload(Name);144  std::vector<Annotations::Range> Res;145  Res.reserve(WithPayload.size());146  for (const auto &[Range, Payload] : WithPayload)147    Res.push_back(Range);148  return Res;149}150std::vector<std::pair<Annotations::Range, llvm::StringRef>>151Annotations::rangesWithPayload(llvm::StringRef Name) const {152  auto Iter = Ranges.find(Name);153  if (Iter == Ranges.end())154    return {};155 156  std::vector<std::pair<Annotations::Range, llvm::StringRef>> Res;157  Res.reserve(Iter->getValue().size());158  for (size_t I : Iter->getValue())159    Res.emplace_back(Annotations::Range{All[I].Begin, All[I].End},160                     All[I].Payload);161 162  return Res;163}164 165llvm::StringMap<llvm::SmallVector<Annotations::Range, 1>>166Annotations::all_ranges() const {167  llvm::StringMap<llvm::SmallVector<Annotations::Range, 1>> Res;168  for (const llvm::StringRef &Name : Ranges.keys()) {169    auto R = ranges(Name);170    Res[Name] = {R.begin(), R.end()};171  }172  return Res;173}174 175llvm::raw_ostream &llvm::operator<<(llvm::raw_ostream &O,176                                    const llvm::Annotations::Range &R) {177  return O << llvm::formatv("[{0}, {1})", R.Begin, R.End);178}179