xref: /llvm-project/clang-tools-extra/clangd/ModulesBuilder.h (revision e385e0d3e71e17da0b2023f480259c95923707bd)
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 LLVM_CLANG_TOOLS_EXTRA_CLANGD_MODULES_BUILDER_H
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   adjustHeaderSearchOptions(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