blob: c9e5076366ce344efd45feb38a7bd8c0d57a0db5 [file] [log] [blame]
Ben Clayton5bee67f2020-10-30 20:44:53 +00001// Copyright 2020 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
dan sinclaird5fd7e02020-11-03 16:26:09 +000015#include "src/source.h"
Ben Clayton5bee67f2020-10-30 20:44:53 +000016
Ben Clayton6fcefe42021-04-19 19:16:12 +000017#include <algorithm>
dan sinclaird5fd7e02020-11-03 16:26:09 +000018#include <sstream>
19#include <utility>
Ben Clayton5bee67f2020-10-30 20:44:53 +000020
21namespace tint {
22namespace {
23std::vector<std::string> split_lines(const std::string& str) {
24 std::stringstream stream(str);
25 std::string line;
26 std::vector<std::string> lines;
27 while (std::getline(stream, line, '\n')) {
28 lines.emplace_back(std::move(line));
29 }
30 return lines;
31}
32} // namespace
33
Ben Clayton1d982362021-02-18 21:40:19 +000034Source::FileContent::FileContent(const std::string& body)
35 : data(body), lines(split_lines(body)) {}
36
37Source::FileContent::~FileContent() = default;
Ben Clayton5bee67f2020-10-30 20:44:53 +000038
39Source::File::~File() = default;
40
Ben Clayton6fcefe42021-04-19 19:16:12 +000041std::ostream& operator<<(std::ostream& out, const Source& source) {
42 auto rng = source.range;
43
44 if (!source.file_path.empty()) {
45 out << source.file_path << ":";
46 }
47 if (rng.begin.line) {
48 out << rng.begin.line << ":";
49 if (rng.begin.column) {
50 out << rng.begin.column;
51 }
52
53 if (source.file_content) {
54 out << std::endl << std::endl;
55
56 auto repeat = [&](char c, size_t n) {
57 while (n--) {
58 out << c;
59 }
60 };
61
62 for (size_t line = rng.begin.line; line <= rng.end.line; line++) {
63 if (line < source.file_content->lines.size() + 1) {
64 auto len = source.file_content->lines[line - 1].size();
65
66 out << source.file_content->lines[line - 1];
67
68 out << std::endl;
69
70 if (line == rng.begin.line && line == rng.end.line) {
71 // Single line
72 repeat(' ', rng.begin.column - 1);
73 repeat('^', std::max<size_t>(rng.end.column - rng.begin.column, 1));
74 } else if (line == rng.begin.line) {
75 // Start of multi-line
76 repeat(' ', rng.begin.column - 1);
77 repeat('^', len - (rng.begin.column - 1));
78 } else if (line == rng.end.line) {
79 // End of multi-line
80 repeat('^', rng.end.column - 1);
81 } else {
82 // Middle of multi-line
83 repeat('^', len);
84 }
85
86 out << std::endl;
87 }
88 }
89 }
90 }
91 return out;
92}
93
Ben Clayton5bee67f2020-10-30 20:44:53 +000094} // namespace tint