2020-10-30 20:44:53 +00:00
|
|
|
// Copyright 2020 The Tint Authors.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2022-02-21 15:19:07 +00:00
|
|
|
#include "src/tint/source.h"
|
2020-10-30 20:44:53 +00:00
|
|
|
|
2021-04-19 19:16:12 +00:00
|
|
|
#include <algorithm>
|
2020-11-03 16:26:09 +00:00
|
|
|
#include <sstream>
|
2022-01-25 17:15:37 +00:00
|
|
|
#include <string_view>
|
2020-11-03 16:26:09 +00:00
|
|
|
#include <utility>
|
2020-10-30 20:44:53 +00:00
|
|
|
|
|
|
|
namespace tint {
|
|
|
|
namespace {
|
2022-01-25 17:15:37 +00:00
|
|
|
std::vector<std::string_view> SplitLines(std::string_view str) {
|
|
|
|
std::vector<std::string_view> lines;
|
|
|
|
|
|
|
|
size_t lineStart = 0;
|
|
|
|
for (size_t i = 0; i < str.size(); ++i) {
|
|
|
|
if (str[i] == '\n') {
|
2022-04-08 18:52:56 +00:00
|
|
|
// Handle CRLF on Windows
|
|
|
|
size_t curr = i;
|
|
|
|
if (i > 0 && str[i - 1] == '\r') {
|
|
|
|
--curr;
|
|
|
|
}
|
|
|
|
lines.push_back(str.substr(lineStart, curr - lineStart));
|
2022-01-25 17:15:37 +00:00
|
|
|
lineStart = i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lineStart < str.size()) {
|
|
|
|
lines.push_back(str.substr(lineStart));
|
2020-10-30 20:44:53 +00:00
|
|
|
}
|
2022-01-25 17:15:37 +00:00
|
|
|
|
2020-10-30 20:44:53 +00:00
|
|
|
return lines;
|
|
|
|
}
|
2022-01-25 17:15:37 +00:00
|
|
|
|
|
|
|
std::vector<std::string_view> CopyRelativeStringViews(
|
|
|
|
const std::vector<std::string_view>& src_list,
|
|
|
|
const std::string_view& src_view,
|
|
|
|
const std::string_view& dst_view) {
|
|
|
|
std::vector<std::string_view> out(src_list.size());
|
|
|
|
for (size_t i = 0; i < src_list.size(); i++) {
|
|
|
|
auto offset = static_cast<size_t>(&src_list[i].front() - &src_view.front());
|
|
|
|
auto count = src_list[i].length();
|
|
|
|
out[i] = dst_view.substr(offset, count);
|
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2020-10-30 20:44:53 +00:00
|
|
|
} // namespace
|
|
|
|
|
2021-02-18 21:40:19 +00:00
|
|
|
Source::FileContent::FileContent(const std::string& body)
|
2022-01-25 17:15:37 +00:00
|
|
|
: data(body), data_view(data), lines(SplitLines(data_view)) {}
|
|
|
|
|
|
|
|
Source::FileContent::FileContent(const FileContent& rhs)
|
|
|
|
: data(rhs.data),
|
|
|
|
data_view(data),
|
|
|
|
lines(CopyRelativeStringViews(rhs.lines, rhs.data_view, data_view)) {}
|
2021-02-18 21:40:19 +00:00
|
|
|
|
|
|
|
Source::FileContent::~FileContent() = default;
|
2020-10-30 20:44:53 +00:00
|
|
|
|
|
|
|
Source::File::~File() = default;
|
|
|
|
|
2021-04-19 19:16:12 +00:00
|
|
|
std::ostream& operator<<(std::ostream& out, const Source& source) {
|
|
|
|
auto rng = source.range;
|
|
|
|
|
2022-01-27 17:36:27 +00:00
|
|
|
if (source.file) {
|
|
|
|
out << source.file->path << ":";
|
2021-04-19 19:16:12 +00:00
|
|
|
}
|
|
|
|
if (rng.begin.line) {
|
|
|
|
out << rng.begin.line << ":";
|
|
|
|
if (rng.begin.column) {
|
|
|
|
out << rng.begin.column;
|
|
|
|
}
|
|
|
|
|
2022-01-27 17:36:27 +00:00
|
|
|
if (source.file) {
|
2021-04-19 19:16:12 +00:00
|
|
|
out << std::endl << std::endl;
|
|
|
|
|
|
|
|
auto repeat = [&](char c, size_t n) {
|
|
|
|
while (n--) {
|
|
|
|
out << c;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
for (size_t line = rng.begin.line; line <= rng.end.line; line++) {
|
2022-01-27 17:36:27 +00:00
|
|
|
if (line < source.file->content.lines.size() + 1) {
|
|
|
|
auto len = source.file->content.lines[line - 1].size();
|
2021-04-19 19:16:12 +00:00
|
|
|
|
2022-01-27 17:36:27 +00:00
|
|
|
out << source.file->content.lines[line - 1];
|
2021-04-19 19:16:12 +00:00
|
|
|
|
|
|
|
out << std::endl;
|
|
|
|
|
|
|
|
if (line == rng.begin.line && line == rng.end.line) {
|
|
|
|
// Single line
|
|
|
|
repeat(' ', rng.begin.column - 1);
|
|
|
|
repeat('^', std::max<size_t>(rng.end.column - rng.begin.column, 1));
|
|
|
|
} else if (line == rng.begin.line) {
|
|
|
|
// Start of multi-line
|
|
|
|
repeat(' ', rng.begin.column - 1);
|
|
|
|
repeat('^', len - (rng.begin.column - 1));
|
|
|
|
} else if (line == rng.end.line) {
|
|
|
|
// End of multi-line
|
|
|
|
repeat('^', rng.end.column - 1);
|
|
|
|
} else {
|
|
|
|
// Middle of multi-line
|
|
|
|
repeat('^', len);
|
|
|
|
}
|
|
|
|
|
|
|
|
out << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2020-10-30 20:44:53 +00:00
|
|
|
} // namespace tint
|