1 // Copyright 2020 google llc
2 //
3 // licensed under the apache license, version 2.0 (the "license");
4 // you may not use this file except in compliance with the license.
5 // you may obtain a copy of the license at
6 //
7 // http://www.apache.org/licenses/license-2.0
8 //
9 // unless required by applicable law or agreed to in writing, software
10 // distributed under the license is distributed on an "as is" basis,
11 // without warranties or conditions of any kind, either express or implied.
12 // see the license for the specific language governing permissions and
13 // limitations under the license.
14
15 #include "sandboxed_api/tools/clang_generator/frontend_action_test_util.h"
16
17 #include <algorithm>
18 #include <iterator>
19 #include <memory>
20 #include <string>
21 #include <utility>
22 #include <vector>
23
24 #include "absl/container/flat_hash_map.h"
25 #include "absl/status/status.h"
26 #include "absl/strings/ascii.h"
27 #include "absl/strings/str_cat.h"
28 #include "absl/strings/str_replace.h"
29 #include "absl/strings/string_view.h"
30 #include "clang/Basic/FileManager.h"
31 #include "clang/Basic/FileSystemOptions.h"
32 #include "clang/Frontend/FrontendAction.h"
33 #include "clang/Tooling/Tooling.h"
34 #include "llvm/ADT/IntrusiveRefCntPtr.h"
35 #include "llvm/ADT/StringRef.h"
36 #include "llvm/Config/llvm-config.h"
37 #include "llvm/Support/MemoryBuffer.h"
38 #include "llvm/Support/VirtualFileSystem.h"
39
40 namespace sapi {
41 namespace internal {
42
RunClangTool(const std::vector<std::string> & command_line,const absl::flat_hash_map<std::string,std::string> & file_contents,std::unique_ptr<clang::FrontendAction> action)43 absl::Status RunClangTool(
44 const std::vector<std::string>& command_line,
45 const absl::flat_hash_map<std::string, std::string>& file_contents,
46 std::unique_ptr<clang::FrontendAction> action) {
47 // Setup an in-memory virtual filesystem
48 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> fs(
49 new llvm::vfs::InMemoryFileSystem());
50 llvm::IntrusiveRefCntPtr<clang::FileManager> files =
51 new clang::FileManager(clang::FileSystemOptions(), fs);
52
53 for (const auto& [filename, content] : file_contents) {
54 if (!fs->addFile(filename, /*ModificationTime=*/0,
55 llvm::MemoryBuffer::getMemBuffer(content))) {
56 return absl::UnknownError(
57 absl::StrCat("Couldn't add file to in-memory VFS: ", filename));
58 }
59 }
60
61 #if LLVM_VERSION_MAJOR >= 10
62 clang::tooling::ToolInvocation invocation(command_line, std::move(action),
63 files.get());
64 #else
65 clang::tooling::ToolInvocation invocation(command_line, action.get(),
66 files.get());
67 #endif
68 if (!invocation.run()) {
69 return absl::UnknownError("Tool invocation failed");
70 }
71 return absl::OkStatus();
72 }
73
74 } // namespace internal
75
GetCommandLineFlagsForTesting(absl::string_view input_file)76 std::vector<std::string> FrontendActionTest::GetCommandLineFlagsForTesting(
77 absl::string_view input_file) {
78 return {"tool", "-fsyntax-only", "--std=c++17",
79 "-I.", "-Wno-error", std::string(input_file)};
80 }
81
Uglify(absl::string_view code)82 std::string Uglify(absl::string_view code) {
83 std::string result = absl::StrReplaceAll(code, {{"\n", " "}});
84 absl::RemoveExtraAsciiWhitespace(&result);
85 return result;
86 }
87
UglifyAll(const std::vector<std::string> & snippets)88 std::vector<std::string> UglifyAll(const std::vector<std::string>& snippets) {
89 std::vector<std::string> result;
90 result.reserve(snippets.size());
91 std::transform(snippets.cbegin(), snippets.cend(), std::back_inserter(result),
92 Uglify);
93 return result;
94 }
95
96 } // namespace sapi
97