1 /*
2 * Copyright 2018 WebAssembly Community Group participants
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "src/error-formatter.h"
18
19 namespace wabt {
20
21 namespace {
22
FormatError(const Error & error,Location::Type location_type,const Color & color,LexerSourceLineFinder * line_finder,int source_line_max_length,int indent)23 std::string FormatError(const Error& error,
24 Location::Type location_type,
25 const Color& color,
26 LexerSourceLineFinder* line_finder,
27 int source_line_max_length,
28 int indent) {
29 std::string indent_str(indent, ' ');
30 std::string result = indent_str;
31
32 result += color.MaybeBoldCode();
33
34 const Location& loc = error.loc;
35 if (!loc.filename.empty()) {
36 result += loc.filename.to_string();
37 result += ":";
38 }
39
40 if (location_type == Location::Type::Text) {
41 result += StringPrintf("%d:%d: ", loc.line, loc.first_column);
42 } else if (loc.offset != kInvalidOffset) {
43 result += StringPrintf("%07" PRIzx ": ", loc.offset);
44 }
45
46 result += color.MaybeRedCode();
47 result += GetErrorLevelName(error.error_level);
48 result += ": ";
49 result += color.MaybeDefaultCode();
50
51 result += error.message;
52 result += '\n';
53
54 LexerSourceLineFinder::SourceLine source_line;
55 if (line_finder) {
56 line_finder->GetSourceLine(loc, source_line_max_length, &source_line);
57 }
58
59 if (!source_line.line.empty()) {
60 result += indent_str;
61 result += source_line.line;
62 result += '\n';
63 result += indent_str;
64
65 size_t num_spaces = (loc.first_column - 1) - source_line.column_offset;
66 size_t num_carets = loc.last_column - loc.first_column;
67 num_carets = std::min(num_carets, source_line.line.size() - num_spaces);
68 num_carets = std::max<size_t>(num_carets, 1);
69 result.append(num_spaces, ' ');
70 result += color.MaybeBoldCode();
71 result += color.MaybeGreenCode();
72 result.append(num_carets, '^');
73 result += color.MaybeDefaultCode();
74 result += '\n';
75 }
76
77 return result;
78 }
79
80 } // End of anonymous namespace
81
FormatErrorsToString(const Errors & errors,Location::Type location_type,LexerSourceLineFinder * line_finder,const Color & color,const std::string & header,PrintHeader print_header,int source_line_max_length)82 std::string FormatErrorsToString(const Errors& errors,
83 Location::Type location_type,
84 LexerSourceLineFinder* line_finder,
85 const Color& color,
86 const std::string& header,
87 PrintHeader print_header,
88 int source_line_max_length) {
89 std::string result;
90 for (const auto& error : errors) {
91 if (!header.empty()) {
92 switch (print_header) {
93 case PrintHeader::Never:
94 break;
95 case PrintHeader::Once:
96 print_header = PrintHeader::Never;
97 // Fallthrough.
98 case PrintHeader::Always:
99 result += header;
100 result += ":\n";
101 break;
102 }
103 }
104
105 int indent = header.empty() ? 0 : 2;
106
107 result += FormatError(error, location_type, color, line_finder,
108 source_line_max_length, indent);
109 }
110 return result;
111 }
112
FormatErrorsToFile(const Errors & errors,Location::Type location_type,LexerSourceLineFinder * line_finder,FILE * file,const std::string & header,PrintHeader print_header,int source_line_max_length)113 void FormatErrorsToFile(const Errors& errors,
114 Location::Type location_type,
115 LexerSourceLineFinder* line_finder,
116 FILE* file,
117 const std::string& header,
118 PrintHeader print_header,
119 int source_line_max_length) {
120 Color color(file);
121 std::string s =
122 FormatErrorsToString(errors, location_type, line_finder, color, header,
123 print_header, source_line_max_length);
124 fwrite(s.data(), 1, s.size(), file);
125 }
126
127 } // namespace wabt
128