Home | History | Annotate | Download | only in aapt2
      1 /*
      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 
     20 #include <iostream>
     21 #include <sstream>
     22 #include <string>
     23 
     24 #include "android-base/macros.h"
     25 #include "androidfw/StringPiece.h"
     26 
     27 #include "Source.h"
     28 #include "util/Util.h"
     29 
     30 namespace aapt {
     31 
     32 struct DiagMessageActual {
     33   Source source;
     34   std::string message;
     35 };
     36 
     37 struct DiagMessage {
     38  public:
     39   DiagMessage() = default;
     40 
     41   explicit DiagMessage(const android::StringPiece& src) : source_(src) {}
     42 
     43   explicit DiagMessage(const Source& src) : source_(src) {}
     44 
     45   explicit DiagMessage(size_t line) : source_(Source().WithLine(line)) {}
     46 
     47   template <typename T>
     48   DiagMessage& operator<<(const T& value) {
     49     message_ << value;
     50     return *this;
     51   }
     52 
     53   DiagMessageActual Build() const {
     54     return DiagMessageActual{source_, message_.str()};
     55   }
     56 
     57  private:
     58   Source source_;
     59   std::stringstream message_;
     60 };
     61 
     62 template <>
     63 inline DiagMessage& DiagMessage::operator<<(const ::std::u16string& value) {
     64   message_ << android::StringPiece16(value);
     65   return *this;
     66 }
     67 
     68 struct IDiagnostics {
     69   virtual ~IDiagnostics() = default;
     70 
     71   enum class Level { Note, Warn, Error };
     72 
     73   virtual void Log(Level level, DiagMessageActual& actualMsg) = 0;
     74 
     75   virtual void Error(const DiagMessage& message) {
     76     DiagMessageActual actual = message.Build();
     77     Log(Level::Error, actual);
     78   }
     79 
     80   virtual void Warn(const DiagMessage& message) {
     81     DiagMessageActual actual = message.Build();
     82     Log(Level::Warn, actual);
     83   }
     84 
     85   virtual void Note(const DiagMessage& message) {
     86     DiagMessageActual actual = message.Build();
     87     Log(Level::Note, actual);
     88   }
     89 };
     90 
     91 class StdErrDiagnostics : public IDiagnostics {
     92  public:
     93   StdErrDiagnostics() = default;
     94 
     95   void Log(Level level, DiagMessageActual& actual_msg) override {
     96     const char* tag;
     97 
     98     switch (level) {
     99       case Level::Error:
    100         num_errors_++;
    101         if (num_errors_ > 20) {
    102           return;
    103         }
    104         tag = "error";
    105         break;
    106 
    107       case Level::Warn:
    108         tag = "warn";
    109         break;
    110 
    111       case Level::Note:
    112         tag = "note";
    113         break;
    114     }
    115 
    116     if (!actual_msg.source.path.empty()) {
    117       std::cerr << actual_msg.source << ": ";
    118     }
    119     std::cerr << tag << ": " << actual_msg.message << "." << std::endl;
    120   }
    121 
    122  private:
    123   size_t num_errors_ = 0;
    124 
    125   DISALLOW_COPY_AND_ASSIGN(StdErrDiagnostics);
    126 };
    127 
    128 class SourcePathDiagnostics : public IDiagnostics {
    129  public:
    130   SourcePathDiagnostics(const Source& src, IDiagnostics* diag)
    131       : source_(src), diag_(diag) {}
    132 
    133   void Log(Level level, DiagMessageActual& actual_msg) override {
    134     actual_msg.source.path = source_.path;
    135     diag_->Log(level, actual_msg);
    136   }
    137 
    138  private:
    139   Source source_;
    140   IDiagnostics* diag_;
    141 
    142   DISALLOW_COPY_AND_ASSIGN(SourcePathDiagnostics);
    143 };
    144 
    145 }  // namespace aapt
    146 
    147 #endif /* AAPT_DIAGNOSTICS_H */
    148