File indexing completed on 2024-05-19 05:42:11

0001 // ct_lvtmdb_objectstore.h                                            -*-C++-*-
0002 
0003 /*
0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk>
0005 // SPDX-License-Identifier: Apache-2.0
0006 //
0007 // Licensed under the Apache License, Version 2.0 (the "License");
0008 // you may not use this file except in compliance with the License.
0009 // You may obtain a copy of the License at
0010 //
0011 //     http://www.apache.org/licenses/LICENSE-2.0
0012 //
0013 // Unless required by applicable law or agreed to in writing, software
0014 // distributed under the License is distributed on an "AS IS" BASIS,
0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016 // See the License for the specific language governing permissions and
0017 // limitations under the License.
0018 */
0019 
0020 #ifndef INCLUDED_CT_LVTMDB_OBJECTSTORE
0021 #define INCLUDED_CT_LVTMDB_OBJECTSTORE
0022 
0023 //@PURPOSE: Store lvtmdb::DbObjects with fast lookup
0024 //
0025 //@CLASSES:
0026 //  lvtldr::ObjectStore: Append-only store of DbObjects with fast lookup
0027 
0028 #include <lvtmdb_export.h>
0029 
0030 #include <ct_lvtmdb_lockable.h>
0031 #include <ct_lvtmdb_util.h>
0032 
0033 #include <ct_lvtshr_graphenums.h>
0034 
0035 #include <QList>
0036 
0037 #include <result/result.hpp>
0038 
0039 #include <filesystem>
0040 #include <memory>
0041 #include <set>
0042 #include <unordered_map>
0043 
0044 namespace Codethink::lvtmdb {
0045 
0046 // FORWARD DECLARATIONS
0047 class ComponentObject;
0048 class ErrorObject;
0049 class FieldObject;
0050 class FileObject;
0051 class FunctionObject;
0052 class MethodObject;
0053 class NamespaceObject;
0054 class PackageObject;
0055 class RepositoryObject;
0056 class TypeObject;
0057 class VariableObject;
0058 
0059 // ==========================
0060 // class ObjectStore
0061 // ==========================
0062 
0063 class LVTMDB_EXPORT ObjectStore : public Lockable {
0064     // Append-only store of DbObjects with fast lookup
0065     // The caller must acquire a ROLock or RWLock before calling a const method
0066     // The caller must acquire a RWLock before calling a non-const method
0067     // These locks do not need to be held for the duration of object access
0068 
0069   private:
0070     // TYPES
0071     struct Private;
0072 
0073     // DATA
0074     std::unique_ptr<Private> d;
0075 
0076   public:
0077     // CREATORS
0078     ObjectStore();
0079 
0080     ~ObjectStore() noexcept override;
0081 
0082     ObjectStore(const ObjectStore& other) = delete;
0083 
0084     enum class State : int {
0085         // It is important this is an int so it can be stored in DbOption
0086         Error,
0087         ManuallyStopped,
0088         NoneReady,
0089         PhysicalReady, // Physical parse finished correctly
0090         PhysicalError, // Parse error, but it should still be able to visualize physical information.
0091         AllReady, // Physical and logical finished correctly.
0092         LogicalError // Physical finished correctly, and Logical finished with error.
0093     };
0094 
0095     void setState(State state);
0096     // indicates if this ObjectStorage contains partial data, error, is empty, or finished correctly.
0097 
0098     State state() const;
0099 
0100     // ACCESSORS
0101     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<ComponentObject>>& components() const;
0102     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<ErrorObject>>& errors() const;
0103     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<FieldObject>>& fields() const;
0104     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<FileObject>>& files() const;
0105     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<FunctionObject>>& functions() const;
0106     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<MethodObject>>& methods() const;
0107     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<NamespaceObject>>& namespaces() const;
0108     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<RepositoryObject>>& repositories() const;
0109     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<PackageObject>>& packages() const;
0110     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<TypeObject>>& types() const;
0111     [[nodiscard]] std::unordered_map<std::string, std::unique_ptr<VariableObject>>& variables() const;
0112 
0113     // interface to look up by qualified name:
0114     // Return a matching object or nullptr if nothing was found
0115     [[nodiscard]] FileObject *getFile(const std::string& qualifiedName) const;
0116     [[nodiscard]] ComponentObject *getComponent(const std::string& qualifiedName) const;
0117     [[nodiscard]] RepositoryObject *getRepository(const std::string& qualifiedName) const;
0118     [[nodiscard]] PackageObject *getPackage(const std::string& qualifiedName) const;
0119     [[nodiscard]] ErrorObject *
0120     getError(const std::string& qualifiedName, const std::string& errorMessage, const std::string& fileName) const;
0121     [[nodiscard]] NamespaceObject *getNamespace(const std::string& qualifiedName) const;
0122     [[nodiscard]] VariableObject *getVariable(const std::string& qualifiedName) const;
0123     [[nodiscard]] FunctionObject *getFunction(const std::string& qualifiedName,
0124                                               const std::string& signature,
0125                                               const std::string& templateParameters,
0126                                               const std::string& returnType) const;
0127     [[nodiscard]] TypeObject *getType(const std::string& qualifiedName) const;
0128     [[nodiscard]] FieldObject *getField(const std::string& qualifiedName) const;
0129     [[nodiscard]] MethodObject *getMethod(const std::string& qualifiedName,
0130                                           const std::string& signature,
0131                                           const std::string& templateParameters,
0132                                           const std::string& returnType) const;
0133 
0134     [[nodiscard]] std::vector<PackageObject *> getAllPackages() const;
0135     [[nodiscard]] std::vector<FileObject *> getAllFiles() const;
0136 
0137     // *do not* call those methods - this is extremely easy to break.
0138     // there's a correct order to be called, and currently, it all starts
0139     // with `removeFile` - removeFile will then descend and delete everything
0140     // from inside of all the other files.
0141     // return the list of deleted files, since this can propagate to more files.
0142     QList<std::string> removeFile(FileObject *file, std::set<intptr_t>& removed);
0143     void removeNamespace(NamespaceObject *nmspc);
0144     void removeType(TypeObject *type);
0145     void removeMethod(MethodObject *method);
0146     void removeField(FieldObject *field);
0147     void removeFunction(FunctionObject *func);
0148     void removeVariable(VariableObject *var);
0149     void removeComponent(ComponentObject *comp);
0150     void removePackage(PackageObject *pkg, std::set<intptr_t>& removed);
0151 
0152     // MODIFIERS
0153     // This should be used by a DataWriter - such as SociWriter,
0154     // to save the contents of this ObjectStore to disk.
0155     template<typename DatabaseAccessWriter>
0156     void writeToDatabase(DatabaseAccessWriter& writer)
0157     {
0158         writer.writeFrom(*this);
0159     }
0160 
0161     struct ReadFromDatabaseError {
0162         std::string what;
0163     };
0164 
0165     template<typename DatabaseAccessReader>
0166     cpp::result<void, ReadFromDatabaseError> readFromDatabase(DatabaseAccessReader& reader, std::string db)
0167     // DatabaseAccessReader is a class that implements readInto(ObjectStore& obj, std::string db);
0168     // db is a path in disk *or* ":memory:", so we can't use std::filesystem::path'
0169     {
0170         return reader.readInto(*this, db);
0171     }
0172     // This will call clear(). Be extremely careful there aren't any
0173     // DbObject pointers left dangling!
0174 
0175     // interface to lookup or construct new DbObjects
0176     // Returns a pointer to the new object
0177     FileObject *getOrAddFile(const std::string& qualifiedName,
0178                              std::string name,
0179                              bool isHeader,
0180                              std::string hash,
0181                              PackageObject *package,
0182                              ComponentObject *component);
0183 
0184     ComponentObject *getOrAddComponent(const std::string& qualifiedName, std::string name, PackageObject *package);
0185     RepositoryObject *getOrAddRepository(const std::string& name, const std::string& diskPath);
0186 
0187     PackageObject *getOrAddPackage(const std::string& qualifiedName,
0188                                    std::string name,
0189                                    std::string diskPath,
0190                                    PackageObject *parent,
0191                                    RepositoryObject *repository);
0192 
0193     ErrorObject *getOrAddError(lvtmdb::MdbUtil::ErrorKind errorKind,
0194                                std::string qualifiedName,
0195                                std::string errorMessage,
0196                                std::string fileName);
0197 
0198     NamespaceObject *getOrAddNamespace(const std::string& qualifiedName, std::string name, NamespaceObject *parent);
0199 
0200     VariableObject *getOrAddVariable(const std::string& qualifiedName,
0201                                      std::string name,
0202                                      std::string signature,
0203                                      bool isGlobal,
0204                                      NamespaceObject *parent);
0205 
0206     FunctionObject *getOrAddFunction(std::string qualifiedName,
0207                                      std::string name,
0208                                      std::string signature,
0209                                      std::string returnType,
0210                                      std::string templateParameters,
0211                                      NamespaceObject *parent);
0212 
0213     TypeObject *getOrAddType(const std::string& qualifiedName,
0214                              std::string name,
0215                              lvtshr::UDTKind kind,
0216                              lvtshr::AccessSpecifier access,
0217                              NamespaceObject *nmspc,
0218                              PackageObject *pkg,
0219                              TypeObject *parent);
0220 
0221     FieldObject *getOrAddField(const std::string& qualifiedName,
0222                                std::string name,
0223                                std::string signature,
0224                                lvtshr::AccessSpecifier access,
0225                                bool isStatic,
0226                                TypeObject *parent);
0227 
0228     MethodObject *getOrAddMethod(std::string qualifiedName,
0229                                  std::string name,
0230                                  std::string signature,
0231                                  std::string returnType,
0232                                  std::string templateParameters,
0233                                  lvtshr::AccessSpecifier access,
0234                                  bool isVirtual,
0235                                  bool isPure,
0236                                  bool isStatic,
0237                                  bool isConst,
0238                                  TypeObject *parent);
0239 
0240     void clear();
0241 };
0242 
0243 } // namespace Codethink::lvtmdb
0244 
0245 #endif // INCLUDED_CT_LVTMDB_OBJECTSTORE