//===- ExtractAPI/Serialization/APISetVisitor.h ----------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file defines the ExtractAPI APISetVisitor interface. /// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H #define LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H #include "clang/ExtractAPI/API.h" namespace clang { namespace extractapi { // A helper macro to implement short-circuiting when recursing. It // invokes CALL_EXPR, which must be a method call, on the derived // object (s.t. a user of RecursiveASTVisitor can override the method // in CALL_EXPR). #define TRY_TO(CALL_EXPR) … /// The base interface of visitors for API information, the interface and usage /// is almost identical to RecurisveASTVistor. This class performs three /// distinct tasks: /// 1. traverse the APISet (i.e. go to every record); /// 2. at a given record, walk up the class hierarchy starting from the record's /// dynamic type until APIRecord is reached. /// 3. given a (record, class) combination where 'class' is some base class of /// the dynamic type of 'record', call a user-overridable function to actually /// visit the record. /// /// These tasks are done by three groups of methods, respectively: /// 1. traverseRecord(APIRecord *x) does task #1, it is the entry point for /// traversing the records starting from x. This method simply forwards to /// traverseFoo(Foo *x) where Foo is the dynamic type of *x, which calls /// walkUpFromFoo(x) and then recursively visits the child records of x. /// 2. walkUpFromFoo(Foo *x) does task #2. It doesn't visit children records of /// x, instead it first calls walkUpFromBar(x) where Bar is the direct parent /// class of Foo (unless Foo has no parent) and then calls visitFoo(x). /// 3. visitFoo(Foo *x) does task #3. /// /// These three method groups are tiered (traverse* > walkUpFrom* > /// visit*). A method (e.g. traverse*) may call methods from the same /// tier (e.g. other traverse*) or one tier lower (e.g. walkUpFrom*). /// It may not call methods from a higher tier. /// /// Note that since walkUpFromFoo() calls walkUpFromBar() (where Bar /// is Foo's super class) before calling visitFoo(), the result is /// that the visit*() methods for a given record are called in the /// top-down order (e.g. for a record of type ObjCInstancePropertyRecord, the /// order will be visitRecord(), visitObjCPropertyRecord(), and then /// visitObjCInstancePropertyRecord()). /// /// This scheme guarantees that all visit*() calls for the same record /// are grouped together. In other words, visit*() methods for different /// records are never interleaved. /// /// Clients of this visitor should subclass the visitor (providing /// themselves as the template argument, using the curiously recurring /// template pattern) and override any of the traverse*, walkUpFrom*, /// and visit* methods for records where the visitor should customize /// behavior. Most users only need to override visit*. Advanced /// users may override traverse* and walkUpFrom* to implement custom /// traversal strategies. Returning false from one of these overridden /// functions will abort the entire traversal. template <typename Derived> class APISetVisitor { … }; template <typename Derived> bool APISetVisitor<Derived>::traverseRecordContext( const RecordContext *Context) { … } template <typename Derived> bool APISetVisitor<Derived>::traverseAPIRecord(const APIRecord *Record) { … } } // namespace extractapi } // namespace clang #endif // LLVM_CLANG_EXTRACTAPI_SERIALIZATION_SERIALIZERBASE_H