11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/* 21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License. 61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at 71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software 111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and 141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License. 151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#ifndef AAPT_DIAGNOSTICS_H 181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#define AAPT_DIAGNOSTICS_H 191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Source.h" 211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/StringPiece.h" 221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Util.h" 231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 24cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski#include <android-base/macros.h> 251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <iostream> 261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <sstream> 271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <string> 281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt { 301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct DiagMessageActual { 321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Source source; 331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::string message; 341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct DiagMessage { 371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiprivate: 381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Source mSource; 391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::stringstream mMessage; 401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskipublic: 421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski DiagMessage() = default; 431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski DiagMessage(const StringPiece& src) : mSource(src) { 451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski DiagMessage(const Source& src) : mSource(src) { 481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 50cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski DiagMessage(size_t line) : mSource(Source().withLine(line)) { 51cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski } 52cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 53cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski template <typename T> 54cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski DiagMessage& operator<<(const T& value) { 551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski mMessage << value; 561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return *this; 571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski DiagMessageActual build() const { 601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return DiagMessageActual{ mSource, mMessage.str() }; 611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct IDiagnostics { 651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski virtual ~IDiagnostics() = default; 661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 67cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski enum class Level { 68cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski Note, 69cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski Warn, 70cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski Error 71cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski }; 721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 73cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski virtual void log(Level level, DiagMessageActual& actualMsg) = 0; 749ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski 75cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski virtual void error(const DiagMessage& message) { 76cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski DiagMessageActual actual = message.build(); 77cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski log(Level::Error, actual); 78cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski } 79cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 80cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski virtual void warn(const DiagMessage& message) { 81cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski DiagMessageActual actual = message.build(); 82cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski log(Level::Warn, actual); 83cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski } 84cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 85cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski virtual void note(const DiagMessage& message) { 86cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski DiagMessageActual actual = message.build(); 87cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski log(Level::Note, actual); 881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 89cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski}; 901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 91cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinskiclass StdErrDiagnostics : public IDiagnostics { 92cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinskipublic: 93cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski StdErrDiagnostics() = default; 94cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 95cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski void log(Level level, DiagMessageActual& actualMsg) override { 96cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski const char* tag; 97cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 98cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski switch (level) { 99cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski case Level::Error: 100cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski mNumErrors++; 101cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski if (mNumErrors > 20) { 102cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski return; 103cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski } 104cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski tag = "error"; 105cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski break; 106cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 107cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski case Level::Warn: 108cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski tag = "warn"; 109cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski break; 110cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 111cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski case Level::Note: 112cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski tag = "note"; 113cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski break; 1149ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski } 115cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 116cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski if (!actualMsg.source.path.empty()) { 117cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski std::cerr << actualMsg.source << ": "; 118cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski } 119cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski std::cerr << tag << ": " << actualMsg.message << "." << std::endl; 1201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 122cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinskiprivate: 123cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski size_t mNumErrors = 0; 124cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 125cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski DISALLOW_COPY_AND_ASSIGN(StdErrDiagnostics); 126cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski}; 127cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 128cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinskiclass SourcePathDiagnostics : public IDiagnostics { 129cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinskipublic: 130cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski SourcePathDiagnostics(const Source& src, IDiagnostics* diag) : mSource(src), mDiag(diag) { 1311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 133cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski void log(Level level, DiagMessageActual& actualMsg) override { 134cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski actualMsg.source.path = mSource.path; 135cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski mDiag->log(level, actualMsg); 1361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 137cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 138cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinskiprivate: 139cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski Source mSource; 140cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski IDiagnostics* mDiag; 141cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski 142cc5609d8e484ec82ef1dced793af7f674f059b1cAdam Lesinski DISALLOW_COPY_AND_ASSIGN(SourcePathDiagnostics); 1431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 1441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} // namespace aapt 1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#endif /* AAPT_DIAGNOSTICS_H */ 148