1 /* 2 * Copyright (C) 2016 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 AST_H_ 18 19 #define AST_H_ 20 21 #include <android-base/macros.h> 22 #include <hidl-hash/Hash.h> 23 #include <hidl-util/FQName.h> 24 #include <functional> 25 #include <map> 26 #include <set> 27 #include <string> 28 #include <vector> 29 30 #include "Scope.h" 31 #include "Type.h" 32 33 namespace android { 34 35 struct Coordinator; 36 struct ConstantExpression; 37 struct DocComment; 38 struct EnumValue; 39 struct Formatter; 40 struct Interface; 41 struct Location; 42 struct Method; 43 struct NamedType; 44 template <class T> 45 struct NamedReference; 46 struct Type; 47 48 struct ImportStatement { 49 FQName fqName; 50 Location location; 51 }; 52 53 struct AST { 54 AST(const Coordinator* coordinator, const Hash* fileHash); 55 56 bool setPackage(const char *package); 57 bool addImport(const char* import, const Location& location); 58 bool addImplicitImport(const FQName& fqName); 59 60 // package and version really. 61 FQName package() const; 62 bool isInterface() const; 63 bool definesInterfaces() const; 64 65 // Adds package, version and scope stack to local name 66 FQName makeFullName(const char* localName, Scope* scope) const; 67 68 void addScopedType(NamedType* type, Scope* scope); 69 70 const std::string& getFilename() const; 71 const Hash* getFileHash() const; 72 73 const Coordinator& getCoordinator() const; 74 75 // Look up local identifier. 76 // It could be plain identifier or enum value as described by lookupEnumValue. 77 LocalIdentifier* lookupLocalIdentifier(const Reference<LocalIdentifier>& ref, 78 const Scope* scope); 79 80 // Look up an enum value by "FQName:valueName". 81 EnumValue* lookupEnumValue(const FQName& fqName, std::string* errorMsg, const Scope* scope); 82 83 // Look up a type by FQName, "pure" names, i.e. those without package 84 // or version are first looked up in the current scope chain. 85 // After that lookup proceeds to imports. 86 Type* lookupType(const FQName& fqName, const Scope* scope); 87 88 void addImportedAST(AST *ast); 89 90 // Calls all passes after parsing required before 91 // being ready to generate output. 92 status_t postParse(); 93 94 // Recursive pass on constant expression tree 95 status_t constantExpressionRecursivePass( 96 const std::function<status_t(ConstantExpression*)>& func, bool processBeforeDependencies); 97 status_t constantExpressionRecursivePass( 98 const std::function<status_t(const ConstantExpression*)>& func, 99 bool processBeforeDependencies) const; 100 101 // Recursive tree pass that sets ParseStage of all types to newStage. 102 status_t setParseStage(Type::ParseStage oldStage, Type::ParseStage newStage); 103 104 // Recursive tree pass that looks up all referenced types 105 status_t lookupTypes(); 106 107 // Recursive tree pass that looks up all referenced local identifiers 108 // and types referenced by constant expressions 109 status_t lookupConstantExpressions(); 110 111 // Recursive tree pass that validates that all defined types 112 // have unique names in their scopes. 113 status_t validateDefinedTypesUniqueNames() const; 114 115 // Recursive tree pass that completes type declarations 116 // that depend on super types 117 status_t resolveInheritance(); 118 119 // Recursive tree pass that validates constant expressions 120 status_t validateConstantExpressions() const; 121 122 // Recursive tree pass that evaluates constant expressions 123 status_t evaluateConstantExpressions(); 124 125 // Recursive tree pass that validates all type-related 126 // syntax restrictions 127 status_t validate() const; 128 129 // Recursive tree pass that ensures that type definitions and references 130 // are acyclic and reorderes type definitions in reversed topological order. 131 status_t topologicalReorder(); 132 133 // Recursive tree pass that ensures that constant expressions 134 // are acyclic. 135 status_t checkAcyclicConstantExpressions() const; 136 137 // Recursive tree pass that checks C++ forward declaration restrictions. 138 status_t checkForwardReferenceRestrictions() const; 139 140 status_t gatherReferencedTypes(); 141 142 void generateCppSource(Formatter& out) const; 143 144 void generateInterfaceHeader(Formatter& out) const; 145 void generateHwBinderHeader(Formatter& out) const; 146 void generateStubHeader(Formatter& out) const; 147 void generateProxyHeader(Formatter& out) const; 148 void generatePassthroughHeader(Formatter& out) const; 149 150 void generateCppImplHeader(Formatter& out) const; 151 void generateCppImplSource(Formatter& out) const; 152 153 void generateJava(Formatter& out, const std::string& limitToType) const; 154 void generateJavaImpl(Formatter& out) const; 155 void generateJavaTypes(Formatter& out, const std::string& limitToType) const; 156 157 void generateVts(Formatter& out) const; 158 159 void generateDependencies(Formatter& out) const; 160 void generateInheritanceHierarchy(Formatter& out) const; 161 162 void generateFormattedHidl(Formatter& out) const; 163 164 const std::vector<ImportStatement>& getImportStatements() const; 165 void getImportedPackages(std::set<FQName> *importSet) const; 166 167 // Run getImportedPackages on this, then run getImportedPackages on 168 // each AST in each package referenced in importSet. 169 void getImportedPackagesHierarchy(std::set<FQName> *importSet) const; 170 171 bool isJavaCompatible() const; 172 173 // Warning: this only includes names explicitly referenced in code. 174 // It does not include all names which are imported. 175 // 176 // Currently, there is one valid usecase for this: importing exactly 177 // the names which need to be imported in generated code. If you import 178 // based on getAllImportedNamesGranular instead, you will import things 179 // that aren't actually used in the resultant code. 180 // 181 // Get transitive closure of imported interface/types. This will add 182 // everything exported by a package even if only a single type from 183 // that package was explicitly imported! 184 void getAllImportedNames(std::set<FQName> *allImportSet) const; 185 186 // Get imported types, this includes those explicitly imported as well 187 // as all types defined in imported packages. 188 void getAllImportedNamesGranular(std::set<FQName> *allImportSet) const; 189 190 void appendToExportedTypesVector( 191 std::vector<const Type *> *exportedTypes) const; 192 193 // used by the parser. 194 void addSyntaxError(); 195 size_t syntaxErrors() const; 196 197 bool isIBase() const; 198 199 // or nullptr if not isInterface 200 const Interface *getInterface() const; 201 202 // types or Interface base name (e.x. Foo) 203 std::string getBaseName() const; 204 205 Scope* getMutableRootScope(); 206 const Scope& getRootScope() const; 207 208 static void generateCppPackageInclude(Formatter& out, const FQName& package, 209 const std::string& klass); 210 211 void addDefinedTypes(std::set<FQName> *definedTypes) const; 212 void addReferencedTypes(std::set<FQName> *referencedTypes) const; 213 214 void addToImportedNamesGranular(const FQName &fqName); 215 216 bool addMethod(Method* method, Interface* iface); 217 bool addAllReservedMethodsToInterface(Interface* iface); 218 219 void setHeader(const DocComment* header); 220 const DocComment* getHeader() const; 221 222 // TODO: Clean up all interface usages of unhandled comments and ensure they are attached to the 223 // right element 224 void addUnhandledComment(const DocComment* docComment); 225 const std::vector<const DocComment*> getUnhandledComments() const; 226 227 private: 228 const Coordinator* mCoordinator; 229 const Hash* mFileHash; 230 231 RootScope mRootScope; 232 233 FQName mPackage; 234 235 // Header for the file 236 const DocComment* mHeader = nullptr; 237 238 // A list of trailing DocComments. 239 std::vector<const DocComment*> mUnhandledComments; 240 241 // A list of the FQNames present in the import statements 242 std::vector<ImportStatement> mImportStatements; 243 244 // A list of FQNames that are imported implicitly 245 std::vector<FQName> mImplicitImports; 246 247 // A set of all external interfaces/types that are _actually_ referenced 248 // in this AST, this is a subset of those specified in import statements. 249 // Note that this set only resolves to the granularity of either an 250 // interface type or a whole package. 251 std::set<FQName> mImportedNames; 252 253 // This is the set of actually imported types. 254 std::set<FQName> mImportedNamesGranular; 255 256 // Warning: this only includes names explicitly referenced in code. 257 // It does not include all names which are imported. 258 // 259 // A set of all ASTs we explicitly or implicitly (types.hal) import. 260 std::set<AST *> mImportedASTs; 261 262 // If a single type (instead of the whole AST) is imported, the AST will be 263 // present as a key to this map, with the value being a list of types 264 // imported from this AST. If an AST appears in mImportedASTs but not in 265 // mImportedTypes, then the whole AST is imported. 266 std::map<AST *, std::set<Type *>> mImportedTypes; 267 268 // Types keyed by full names defined in this AST. 269 std::map<FQName, Type *> mDefinedTypesByFullName; 270 271 // contains all the hidl reserved methods part of this AST 272 std::map<std::string, Method*> mAllReservedMethods; 273 274 // used by the parser. 275 size_t mSyntaxErrors = 0; 276 277 std::set<FQName> mReferencedTypeNames; 278 279 // importFQName will try to import fqName by parsing any file that might contain it 280 bool importFQName(const FQName& fqName); 281 282 // Helper functions for lookupType. 283 Type* lookupTypeLocally(const FQName& fqName, const Scope* scope); 284 status_t lookupAutofilledType(const FQName &fqName, Type **returnedType); 285 Type *lookupTypeFromImports(const FQName &fqName); 286 287 // Find a type matching fqName (which may be partial) and if found 288 // return the associated type and fill in the full "matchingName". 289 // Only types defined in this very AST are considered. 290 Type *findDefinedType(const FQName &fqName, FQName *matchingName) const; 291 292 std::string makeHeaderGuard(const std::string &baseName, 293 bool indicateGenerated = true) const; 294 void enterLeaveNamespace(Formatter &out, bool enter) const; 295 296 void generateTypeSource(Formatter& out, const std::string& ifaceName) const; 297 298 // a method, and in which interface is it originally defined. 299 // be careful of the case where method.isHidlReserved(), where interface 300 // is effectively useless. 301 using MethodGenerator = std::function<void(const Method*, const Interface*)>; 302 303 void generateTemplatizationLink(Formatter& out) const; 304 void generateCppTag(Formatter& out, const std::string& tag) const; 305 306 void generateMethods(Formatter& out, const MethodGenerator& gen, 307 bool includeParents = true) const; 308 void generateStubImplMethod(Formatter& out, const std::string& className, 309 const Method* method) const; 310 void generatePassthroughMethod(Formatter& out, const Method* method, const Interface* superInterface) const; 311 void generateStaticProxyMethodSource(Formatter& out, const std::string& className, 312 const Method* method, const Interface* superInterface) const; 313 void generateProxyMethodSource(Formatter& out, const std::string& className, 314 const Method* method, const Interface* superInterface) const; 315 void generateFetchSymbol(Formatter &out, const std::string &ifaceName) const; 316 317 void generateProxySource(Formatter& out, const FQName& fqName) const; 318 319 void generateStubSource(Formatter& out, const Interface* iface) const; 320 321 void generateStubSourceForMethod(Formatter& out, const Method* method, 322 const Interface* superInterface) const; 323 void generateStaticStubMethodSource(Formatter& out, const FQName& fqName, 324 const Method* method, const Interface* superInterface) const; 325 326 void generatePassthroughSource(Formatter& out) const; 327 328 void generateInterfaceSource(Formatter& out) const; 329 330 enum InstrumentationEvent { 331 SERVER_API_ENTRY = 0, 332 SERVER_API_EXIT, 333 CLIENT_API_ENTRY, 334 CLIENT_API_EXIT, 335 SYNC_CALLBACK_ENTRY, 336 SYNC_CALLBACK_EXIT, 337 ASYNC_CALLBACK_ENTRY, 338 ASYNC_CALLBACK_EXIT, 339 PASSTHROUGH_ENTRY, 340 PASSTHROUGH_EXIT, 341 }; 342 343 void generateCppAtraceCall( 344 Formatter &out, 345 InstrumentationEvent event, 346 const Method *method) const; 347 348 void generateCppInstrumentationCall( 349 Formatter &out, 350 InstrumentationEvent event, 351 const Method *method, 352 const Interface* superInterface) const; 353 354 void declareCppReaderLocals(Formatter& out, const std::vector<NamedReference<Type>*>& arg, 355 bool forResults) const; 356 357 void emitCppReaderWriter(Formatter& out, const std::string& parcelObj, bool parcelObjIsPointer, 358 const NamedReference<Type>* arg, bool isReader, Type::ErrorMode mode, 359 bool addPrefixToName) const; 360 361 void emitJavaReaderWriter(Formatter& out, const std::string& parcelObj, 362 const NamedReference<Type>* arg, bool isReader, 363 bool addPrefixToName) const; 364 365 void emitVtsTypeDeclarations(Formatter& out) const; 366 367 DISALLOW_COPY_AND_ASSIGN(AST); 368 }; 369 370 } // namespace android 371 372 #endif // AST_H_ 373