blob: 5bc86a9fdbafef62c03eea946921ec516e96daf3 [file] [log] [blame]
Adam Lesinski1ab598f2015-08-14 14:26:04 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
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#ifndef AAPT_DIAGNOSTICS_H
18#define AAPT_DIAGNOSTICS_H
19
Adam Lesinski1ab598f2015-08-14 14:26:04 -070020#include <iostream>
21#include <sstream>
22#include <string>
23
Adam Lesinskice5e56e2016-10-21 17:56:45 -070024#include "android-base/macros.h"
25
26#include "Source.h"
27#include "util/StringPiece.h"
28#include "util/Util.h"
29
Adam Lesinski1ab598f2015-08-14 14:26:04 -070030namespace aapt {
31
32struct DiagMessageActual {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070033 Source source;
34 std::string message;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070035};
36
37struct DiagMessage {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070038 public:
39 DiagMessage() = default;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070040
Adam Lesinskice5e56e2016-10-21 17:56:45 -070041 explicit DiagMessage(const StringPiece& src) : source_(src) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -070042
Adam Lesinskice5e56e2016-10-21 17:56:45 -070043 explicit DiagMessage(const Source& src) : source_(src) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -070044
Adam Lesinskice5e56e2016-10-21 17:56:45 -070045 explicit DiagMessage(size_t line) : source_(Source().WithLine(line)) {}
Adam Lesinskicc5609d2016-04-05 12:41:07 -070046
Adam Lesinskicacb28f2016-10-19 12:18:14 -070047 template <typename T>
48 DiagMessage& operator<<(const T& value) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070049 message_ << value;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070050 return *this;
51 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070052
Adam Lesinskice5e56e2016-10-21 17:56:45 -070053 DiagMessageActual Build() const {
54 return DiagMessageActual{source_, message_.str()};
Adam Lesinskicacb28f2016-10-19 12:18:14 -070055 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -070056
57 private:
58 Source source_;
59 std::stringstream message_;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070060};
61
62struct IDiagnostics {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070063 virtual ~IDiagnostics() = default;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070064
Adam Lesinskicacb28f2016-10-19 12:18:14 -070065 enum class Level { Note, Warn, Error };
Adam Lesinskicc5609d2016-04-05 12:41:07 -070066
Adam Lesinskice5e56e2016-10-21 17:56:45 -070067 virtual void Log(Level level, DiagMessageActual& actualMsg) = 0;
Adam Lesinskicc5609d2016-04-05 12:41:07 -070068
Adam Lesinskice5e56e2016-10-21 17:56:45 -070069 virtual void Error(const DiagMessage& message) {
70 DiagMessageActual actual = message.Build();
71 Log(Level::Error, actual);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -070073
Adam Lesinskice5e56e2016-10-21 17:56:45 -070074 virtual void Warn(const DiagMessage& message) {
75 DiagMessageActual actual = message.Build();
76 Log(Level::Warn, actual);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070077 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -070078
Adam Lesinskice5e56e2016-10-21 17:56:45 -070079 virtual void Note(const DiagMessage& message) {
80 DiagMessageActual actual = message.Build();
81 Log(Level::Note, actual);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070082 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070083};
84
Adam Lesinskicc5609d2016-04-05 12:41:07 -070085class StdErrDiagnostics : public IDiagnostics {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070086 public:
87 StdErrDiagnostics() = default;
Adam Lesinskicc5609d2016-04-05 12:41:07 -070088
Adam Lesinskice5e56e2016-10-21 17:56:45 -070089 void Log(Level level, DiagMessageActual& actual_msg) override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070090 const char* tag;
Adam Lesinskicc5609d2016-04-05 12:41:07 -070091
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092 switch (level) {
93 case Level::Error:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070094 num_errors_++;
95 if (num_errors_ > 20) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070096 return;
Adam Lesinskicc5609d2016-04-05 12:41:07 -070097 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070098 tag = "error";
99 break;
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700100
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700101 case Level::Warn:
102 tag = "warn";
103 break;
104
105 case Level::Note:
106 tag = "note";
107 break;
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700108 }
109
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700110 if (!actual_msg.source.path.empty()) {
111 std::cerr << actual_msg.source << ": ";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700112 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700113 std::cerr << tag << ": " << actual_msg.message << "." << std::endl;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700114 }
Adam Lesinski9ba47d82015-10-13 11:37:10 -0700115
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700116 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700117 size_t num_errors_ = 0;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700118
119 DISALLOW_COPY_AND_ASSIGN(StdErrDiagnostics);
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700120};
121
122class SourcePathDiagnostics : public IDiagnostics {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700123 public:
124 SourcePathDiagnostics(const Source& src, IDiagnostics* diag)
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700125 : source_(src), diag_(diag) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700126
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700127 void Log(Level level, DiagMessageActual& actual_msg) override {
128 actual_msg.source.path = source_.path;
129 diag_->Log(level, actual_msg);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700130 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700131
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700132 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700133 Source source_;
134 IDiagnostics* diag_;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700135
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700136 DISALLOW_COPY_AND_ASSIGN(SourcePathDiagnostics);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700137};
138
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700139} // namespace aapt
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700140
141#endif /* AAPT_DIAGNOSTICS_H */