1 //===-- TestFS.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 // Allows setting up fake filesystem environments for tests.
10 //
11 //===----------------------------------------------------------------------===//
12 #ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTFS_H
13 #define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_TESTFS_H
14 #include "ClangdServer.h"
15 #include "GlobalCompilationDatabase.h"
16 #include "support/Path.h"
17 #include "support/ThreadsafeFS.h"
18 #include "llvm/ADT/IntrusiveRefCntPtr.h"
19 #include "llvm/ADT/None.h"
20 #include "llvm/ADT/Optional.h"
21 #include "llvm/Support/Path.h"
22 #include "llvm/Support/VirtualFileSystem.h"
23 
24 namespace clang {
25 namespace clangd {
26 
27 // Builds a VFS that provides access to the provided files, plus temporary
28 // directories.
29 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
30 buildTestFS(llvm::StringMap<std::string> const &Files,
31             llvm::StringMap<time_t> const &Timestamps = {});
32 
33 // A VFS provider that returns TestFSes containing a provided set of files.
34 class MockFS : public ThreadsafeFS {
35 public:
viewImpl()36   IntrusiveRefCntPtr<llvm::vfs::FileSystem> viewImpl() const override {
37     auto MemFS = buildTestFS(Files, Timestamps);
38     if (!OverlayRealFileSystemForModules)
39       return MemFS;
40     llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem =
41         new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem());
42     OverlayFileSystem->pushOverlay(MemFS);
43     return OverlayFileSystem;
44   }
45 
46   // If relative paths are used, they are resolved with testPath().
47   llvm::StringMap<std::string> Files;
48   llvm::StringMap<time_t> Timestamps;
49   // If true, real file system will be used as fallback for the in-memory one.
50   // This is useful for testing module support.
51   bool OverlayRealFileSystemForModules = false;
52 };
53 
54 // A Compilation database that returns a fixed set of compile flags.
55 class MockCompilationDatabase : public GlobalCompilationDatabase {
56 public:
57   /// If \p Directory is not empty, use that as the Directory field of the
58   /// CompileCommand, and as project SourceRoot.
59   ///
60   /// If \p RelPathPrefix is not empty, use that as a prefix in front of the
61   /// source file name, instead of using an absolute path.
62   MockCompilationDatabase(StringRef Directory = StringRef(),
63                           StringRef RelPathPrefix = StringRef());
64 
65   llvm::Optional<tooling::CompileCommand>
66   getCompileCommand(PathRef File) const override;
67 
68   llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const override;
69 
70   std::vector<std::string> ExtraClangFlags;
71 
72 private:
73   StringRef Directory;
74   StringRef RelPathPrefix;
75 };
76 
77 // Returns an absolute (fake) test directory for this OS.
78 const char *testRoot();
79 
80 // Returns a suitable absolute path for this OS.
81 std::string testPath(PathRef File,
82                      llvm::sys::path::Style = llvm::sys::path::Style::native);
83 
84 // unittest: is a scheme that refers to files relative to testRoot()
85 // This anchor is used to force the linker to link in the generated object file
86 // and thus register unittest: URI scheme plugin.
87 extern volatile int UnittestSchemeAnchorSource;
88 
89 } // namespace clangd
90 } // namespace clang
91 #endif
92