1 /*
2  * Copyright (C) 2015, The Android Open Source Project *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #pragma once
17 
18 #include <set>
19 #include <string>
20 #include <vector>
21 
22 #include <android-base/result.h>
23 #include <android-base/strings.h>
24 
25 #include "diagnostics.h"
26 #include "logging.h"
27 
28 namespace android {
29 namespace aidl {
30 
31 using std::set;
32 using std::string;
33 using std::vector;
34 
35 // The oldest SDK version that is supported for each backend. For non-Java backends, these are the
36 // platform SDK version where the support for the backend was added. For Java backend, this is 1.
37 // TODO(b/205065703) switch back to DEFAULT_SDK_VERSION_JAVA = 23
38 constexpr uint32_t DEFAULT_SDK_VERSION_JAVA = 1;
39 constexpr uint32_t DEFAULT_SDK_VERSION_CPP = 23;
40 constexpr uint32_t DEFAULT_SDK_VERSION_NDK = 29;
41 constexpr uint32_t DEFAULT_SDK_VERSION_RUST = 31;
42 
43 constexpr uint32_t SDK_VERSION_current = 10000;
44 constexpr uint32_t SDK_VERSION_Tiramisu = 33;
45 constexpr uint32_t SDK_VERSION_UpsideDownCake = 34;
46 constexpr uint32_t SDK_VERSION_VanillaIceCream = 35;
47 
48 constexpr uint32_t JAVA_PROPAGATE_VERSION = SDK_VERSION_Tiramisu;
49 
50 // A simple wrapper around ostringstream. This is just to make Options class
51 // copiable by the implicit copy constructor. If ostingstream is not wrapped,
52 // the implcit copy constructor is not generated because ostringstream isn't
53 // copiable. This class makes the field copiable by having a copy constructor
54 // that does not copy the underlying stream.
55 class ErrorMessage {
56  public:
57   ErrorMessage() = default;
ErrorMessage(const ErrorMessage &)58   ErrorMessage(const ErrorMessage&) {}
59   std::ostringstream stream_;
60 
61   template <typename T>
62   ErrorMessage& operator<<(T& t) {
63     stream_ << t;
64     return *this;
65   }
66 
67   template <typename T>
68   ErrorMessage& operator<<(const T& t) {
69     stream_ << t;
70     return *this;
71   }
72 
73   // for "<< endl"
74   ErrorMessage& operator<<(std::ostream& (*f)(std::ostream&)) {
75     f(stream_);
76     return *this;
77   }
78 };
79 
80 // Handles warning-related options (e.g. -W, -w, ...)
81 class WarningOptions {
82  public:
83   std::vector<const char*> Parse(int argc, const char* const argv[], ErrorMessage& error_message);
84   DiagnosticMapping GetDiagnosticMapping() const;
85 
86  private:
87   bool as_errors_ = false;           // -Werror
88   bool enable_all_ = false;          // -Weverything
89   bool disable_all_ = false;         // -w
90   std::set<std::string> enabled_;    // -Wfoo
91   std::set<std::string> disabled_;   // -Wno-foo
92   std::set<std::string> no_errors_;  // -Wno-error=foo
93 };
94 
95 // Options for AIDL
96 //
97 // These are passed all throughout the compiler, but they should not affect the
98 // code which is generated. In order to avoid ODR issues, and also in order to
99 // make sure the language is orthogonal and portable, we should only generate
100 // different things based on the file contents themselves.
101 class Options final {
102  public:
103   enum class Language { UNSPECIFIED, JAVA, CPP, NDK, RUST, CPP_ANALYZER };
104 
105   enum class Task { HELP, COMPILE, PREPROCESS, DUMP_API, CHECK_API, DUMP_MAPPINGS };
106 
107   enum class CheckApiLevel { COMPATIBLE, EQUAL };
108 
109   enum class Stability { UNSPECIFIED, VINTF };
110   bool StabilityFromString(const std::string& stability, Stability* out_stability);
111 
112   Options(int argc, const char* const argv[], Language default_lang = Language::UNSPECIFIED);
113 
114   Options PlusImportDir(const std::string& import_dir) const;
115 
AsPreviousVersion()116   Options AsPreviousVersion() const {
117     Options copy(*this);
118     copy.as_previous_version_ = true;
119     return copy;
120   }
121 
WithoutVersion()122   Options WithoutVersion() const {
123     Options copy(*this);
124     copy.version_ = 0;
125     copy.hash_ = "";
126     return copy;
127   }
128 
WithNoWarnings()129   Options WithNoWarnings() const {
130     Options copy(*this);
131     copy.warning_options_ = WarningOptions();
132     return copy;
133   }
134 
135   static Options From(const string& cmdline);
136 
137   static Options From(const vector<string>& args);
138 
139   // to print in output files
RawArgs()140   std::string RawArgs() const { return raw_args_; }
141 
142   // Contain no references to unstructured data types (such as a parcelable that is
143   // implemented in Java). These interfaces aren't inherently stable but they have the
144   // capacity to be stabilized.
IsStructured()145   bool IsStructured() const { return structured_; }
146 
GetStability()147   Stability GetStability() const { return stability_; }
148 
GetMinSdkVersion()149   uint32_t GetMinSdkVersion() const { return min_sdk_version_; }
150 
TargetLanguage()151   Language TargetLanguage() const { return language_; }
IsCppOutput()152   bool IsCppOutput() const {
153     return language_ == Language::CPP || language_ == Language::NDK ||
154            language_ == Language::CPP_ANALYZER;
155   }
156 
GetTask()157   Task GetTask() const { return task_; }
158 
GetCheckApiLevel()159   CheckApiLevel GetCheckApiLevel() const { return check_api_level_; }
160 
ImportDirs()161   const set<string>& ImportDirs() const {
162     if (as_previous_version_) {
163       return previous_import_dirs_;
164     } else {
165       return import_dirs_;
166     }
167   }
168 
PreprocessedFiles()169   const vector<string>& PreprocessedFiles() const { return preprocessed_files_; }
170 
DependencyFile()171   string DependencyFile() const {
172     return dependency_file_;
173   }
174 
AutoDepFile()175   bool AutoDepFile() const { return auto_dep_file_; }
176 
GenRpc()177   bool GenRpc() const { return gen_rpc_; }
178 
GenTraces()179   bool GenTraces() const { return gen_traces_; }
180 
GenTransactionNames()181   bool GenTransactionNames() const { return gen_transaction_names_; }
182 
GenMockall()183   bool GenMockall() const { return gen_mockall_; }
184 
DependencyFileNinja()185   bool DependencyFileNinja() const { return dependency_file_ninja_; }
186 
PreviousApiDir()187   const string& PreviousApiDir() const { return previous_api_dir_; }
188 
InputFiles()189   const vector<string>& InputFiles() const { return input_files_; }
190 
191   // Path to the output file. This is used only when there is only one
192   // output file for the invocation. When there are multiple outputs
193   // (e.g. compile multiple AIDL files), output files are created under
194   // OutputDir().
OutputFile()195   const string& OutputFile() const { return output_file_; }
196 
197   // Path to the directory where output file(s) will be generated under.
OutputDir()198   const string& OutputDir() const { return output_dir_; }
199 
200   // Path to the directory where header file(s) will be generated under.
201   // Only used when TargetLanguage() == Language::CPP
OutputHeaderDir()202   const string& OutputHeaderDir() const { return output_header_dir_; }
203 
FailOnParcelable()204   bool FailOnParcelable() const { return fail_on_parcelable_; }
205 
Version()206   int Version() const { return version_; }
207 
PreviousVersion()208   int PreviousVersion() const {
209     AIDL_FATAL_IF(version_ <= 1, "This should only be called on versions greater than 1");
210     return version_ - 1;
211   }
212 
IsLatestUnfrozenVersion()213   bool IsLatestUnfrozenVersion() const { return !PreviousApiDir().empty(); }
214 
Hash()215   string Hash() const { return hash_; }
216 
PreviousHash()217   string PreviousHash() const { return previous_hash_; }
218 
GenLog()219   bool GenLog() const { return gen_log_; }
220 
DumpNoLicense()221   bool DumpNoLicense() const { return dump_no_license_; }
222 
Ok()223   bool Ok() const { return error_message_.stream_.str().empty(); }
224 
GetErrorMessage()225   string GetErrorMessage() const { return error_message_.stream_.str(); }
226 
227   string GetUsage() const;
228 
GenApiMapping()229   bool GenApiMapping() const { return task_ == Task::DUMP_MAPPINGS; }
230 
GetDiagnosticMapping()231   DiagnosticMapping GetDiagnosticMapping() const { return warning_options_.GetDiagnosticMapping(); }
232 
233   // The following are for testability, but cannot be influenced on the command line.
234   // Threshold of interface methods to enable outlining of onTransact cases.
235   size_t onTransact_outline_threshold_{275u};
236   // Number of cases to _not_ outline, if outlining is enabled.
237   size_t onTransact_non_outline_count_{275u};
238 
239  private:
240   Options() = default;
241 
242   const string myname_;
243   std::string raw_args_;
244   Language language_ = Language::UNSPECIFIED;
245   Task task_ = Task::COMPILE;
246   CheckApiLevel check_api_level_ = CheckApiLevel::COMPATIBLE;
247   set<string> import_dirs_;
248   set<string> previous_import_dirs_;
249   bool as_previous_version_ = false;
250   vector<string> preprocessed_files_;
251   string dependency_file_;
252   bool gen_rpc_ = false;
253   bool gen_traces_ = false;
254   bool gen_transaction_names_ = false;
255   bool gen_mockall_ = false;
256   bool dependency_file_ninja_ = false;
257   string previous_api_dir_;
258   bool structured_ = false;
259   Stability stability_ = Stability::UNSPECIFIED;
260   uint32_t min_sdk_version_ = 0;  // invalid version
261   string output_dir_;
262   string output_header_dir_;
263   bool fail_on_parcelable_ = false;
264   bool auto_dep_file_ = false;
265   vector<string> input_files_;
266   string output_file_;
267   int version_ = 0;
268   string hash_ = "";
269   string previous_hash_ = "";
270   bool gen_log_ = false;
271   bool dump_no_license_ = false;
272   ErrorMessage error_message_;
273   WarningOptions warning_options_;
274 };
275 
276 std::string to_string(Options::Language language);
277 android::base::Result<uint32_t> MinSdkVersionFromString(const std::string& str);
278 
279 }  // namespace aidl
280 }  // namespace android
281