| 1 | //===----------------- ModulesBuilder.h --------------------------*- C++-*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // Experimental support for C++20 Modules. |
| 10 | // |
| 11 | // Currently we simplify the implementations by preventing reusing module files |
| 12 | // across different versions and different source files. But this is clearly a |
| 13 | // waste of time and space in the end of the day. |
| 14 | // |
| 15 | // TODO: Supporting reusing module files across different versions and |
| 16 | // different source files. |
| 17 | // |
| 18 | //===----------------------------------------------------------------------===// |
| 19 | |
| 20 | #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULES_BUILDER_H |
| 21 | #define |
| 22 | |
| 23 | #include "GlobalCompilationDatabase.h" |
| 24 | #include "ProjectModules.h" |
| 25 | #include "support/Path.h" |
| 26 | #include "support/ThreadsafeFS.h" |
| 27 | #include "clang/Frontend/CompilerInvocation.h" |
| 28 | #include "llvm/ADT/SmallString.h" |
| 29 | #include <memory> |
| 30 | |
| 31 | namespace clang { |
| 32 | namespace clangd { |
| 33 | |
| 34 | /// Store all the needed module files information to parse a single |
| 35 | /// source file. e.g., |
| 36 | /// |
| 37 | /// ``` |
| 38 | /// // a.cppm |
| 39 | /// export module a; |
| 40 | /// |
| 41 | /// // b.cppm |
| 42 | /// export module b; |
| 43 | /// import a; |
| 44 | /// |
| 45 | /// // c.cppm |
| 46 | /// export module c; |
| 47 | /// import b; |
| 48 | /// ``` |
| 49 | /// |
| 50 | /// For the source file `c.cppm`, an instance of the class will store |
| 51 | /// the module files for `a.cppm` and `b.cppm`. But the module file for `c.cppm` |
| 52 | /// won't be stored. Since it is not needed to parse `c.cppm`. |
| 53 | /// |
| 54 | /// Users should only get PrerequisiteModules from |
| 55 | /// `ModulesBuilder::buildPrerequisiteModulesFor(...)`. |
| 56 | /// |
| 57 | /// Users can detect whether the PrerequisiteModules is still up to date by |
| 58 | /// calling the `canReuse()` member function. |
| 59 | /// |
| 60 | /// The users should call `adjustHeaderSearchOptions(...)` to update the |
| 61 | /// compilation commands to select the built module files first. Before calling |
| 62 | /// `adjustHeaderSearchOptions()`, users should call `canReuse()` first to check |
| 63 | /// if all the stored module files are valid. In case they are not valid, |
| 64 | /// users should call `ModulesBuilder::buildPrerequisiteModulesFor(...)` again |
| 65 | /// to get the new PrerequisiteModules. |
| 66 | class PrerequisiteModules { |
| 67 | public: |
| 68 | /// Change commands to load the module files recorded in this |
| 69 | /// PrerequisiteModules first. |
| 70 | virtual void |
| 71 | (HeaderSearchOptions &Options) const = 0; |
| 72 | |
| 73 | /// Whether or not the built module files are up to date. |
| 74 | /// Note that this can only be used after building the module files. |
| 75 | virtual bool |
| 76 | canReuse(const CompilerInvocation &CI, |
| 77 | llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>) const = 0; |
| 78 | |
| 79 | virtual ~PrerequisiteModules() = default; |
| 80 | }; |
| 81 | |
| 82 | /// This class handles building module files for a given source file. |
| 83 | /// |
| 84 | /// In the future, we want the class to manage the module files acorss |
| 85 | /// different versions and different source files. |
| 86 | class ModulesBuilder { |
| 87 | public: |
| 88 | ModulesBuilder(const GlobalCompilationDatabase &CDB); |
| 89 | ~ModulesBuilder(); |
| 90 | |
| 91 | ModulesBuilder(const ModulesBuilder &) = delete; |
| 92 | ModulesBuilder(ModulesBuilder &&) = delete; |
| 93 | |
| 94 | ModulesBuilder &operator=(const ModulesBuilder &) = delete; |
| 95 | ModulesBuilder &operator=(ModulesBuilder &&) = delete; |
| 96 | |
| 97 | std::unique_ptr<PrerequisiteModules> |
| 98 | buildPrerequisiteModulesFor(PathRef File, const ThreadsafeFS &TFS); |
| 99 | |
| 100 | private: |
| 101 | class ModulesBuilderImpl; |
| 102 | std::unique_ptr<ModulesBuilderImpl> Impl; |
| 103 | }; |
| 104 | |
| 105 | } // namespace clangd |
| 106 | } // namespace clang |
| 107 | |
| 108 | #endif |
| 109 | |