• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Source.h"
21 #include "util/StringPiece.h"
22 #include "util/Util.h"
23 
24 #include <android-base/macros.h>
25 #include <iostream>
26 #include <sstream>
27 #include <string>
28 
29 namespace aapt {
30 
31 struct DiagMessageActual {
32     Source source;
33     std::string message;
34 };
35 
36 struct DiagMessage {
37 private:
38     Source mSource;
39     std::stringstream mMessage;
40 
41 public:
42     DiagMessage() = default;
43 
DiagMessageDiagMessage44     DiagMessage(const StringPiece& src) : mSource(src) {
45     }
46 
DiagMessageDiagMessage47     DiagMessage(const Source& src) : mSource(src) {
48     }
49 
DiagMessageDiagMessage50     DiagMessage(size_t line) : mSource(Source().withLine(line)) {
51     }
52 
53     template <typename T>
54     DiagMessage& operator<<(const T& value) {
55         mMessage << value;
56         return *this;
57     }
58 
buildDiagMessage59     DiagMessageActual build() const {
60         return DiagMessageActual{ mSource, mMessage.str() };
61     }
62 };
63 
64 struct IDiagnostics {
65     virtual ~IDiagnostics() = default;
66 
67     enum class Level {
68         Note,
69         Warn,
70         Error
71     };
72 
73     virtual void log(Level level, DiagMessageActual& actualMsg) = 0;
74 
errorIDiagnostics75     virtual void error(const DiagMessage& message) {
76         DiagMessageActual actual = message.build();
77         log(Level::Error, actual);
78     }
79 
warnIDiagnostics80     virtual void warn(const DiagMessage& message) {
81         DiagMessageActual actual = message.build();
82         log(Level::Warn, actual);
83     }
84 
noteIDiagnostics85     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 
log(Level level,DiagMessageActual & actualMsg)95     void log(Level level, DiagMessageActual& actualMsg) override {
96         const char* tag;
97 
98         switch (level) {
99         case Level::Error:
100             mNumErrors++;
101             if (mNumErrors > 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 (!actualMsg.source.path.empty()) {
117             std::cerr << actualMsg.source << ": ";
118         }
119         std::cerr << tag << ": " << actualMsg.message << "." << std::endl;
120     }
121 
122 private:
123     size_t mNumErrors = 0;
124 
125     DISALLOW_COPY_AND_ASSIGN(StdErrDiagnostics);
126 };
127 
128 class SourcePathDiagnostics : public IDiagnostics {
129 public:
SourcePathDiagnostics(const Source & src,IDiagnostics * diag)130     SourcePathDiagnostics(const Source& src, IDiagnostics* diag) : mSource(src), mDiag(diag) {
131     }
132 
log(Level level,DiagMessageActual & actualMsg)133     void log(Level level, DiagMessageActual& actualMsg) override {
134         actualMsg.source.path = mSource.path;
135         mDiag->log(level, actualMsg);
136     }
137 
138 private:
139     Source mSource;
140     IDiagnostics* mDiag;
141 
142     DISALLOW_COPY_AND_ASSIGN(SourcePathDiagnostics);
143 };
144 
145 } // namespace aapt
146 
147 #endif /* AAPT_DIAGNOSTICS_H */
148