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/StringRef.h"
35 #include "llvm/Support/MemoryBuffer.h"
36 #include "llvm/Support/VirtualFileSystem.h"
37
38 namespace sapi {
39 namespace internal {
40
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)41 absl::Status RunClangTool(
42 const std::vector<std::string> command_line,
43 const absl::flat_hash_map<std::string, std::string> file_contents,
44 std::unique_ptr<clang::FrontendAction> action) {
45 // Setup an in-memory virtual filesystem
46 llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> fs(
47 new llvm::vfs::InMemoryFileSystem());
48 llvm::IntrusiveRefCntPtr<clang::FileManager> files =
49 new clang::FileManager(clang::FileSystemOptions(), fs);
50
51 for (const auto& [filename, content] : file_contents) {
52 if (!fs->addFile(filename, /*ModificationTime=*/0,
53 llvm::MemoryBuffer::getMemBuffer(content))) {
54 return absl::UnknownError(
55 absl::StrCat("Couldn't add file to in-memory VFS: ", filename));
56 }
57 }
58
59 #if LLVM_VERSION_MAJOR >= 10
60 clang::tooling::ToolInvocation invocation(command_line, std::move(action),
61 files.get());
62 #else
63 clang::tooling::ToolInvocation invocation(command_line, action.get(),
64 files.get());
65 #endif
66 if (!invocation.run()) {
67 return absl::UnknownError("Tool invocation failed");
68 }
69 return absl::OkStatus();
70 }
71
72 } // namespace internal
73
GetCommandLineFlagsForTesting(absl::string_view input_file)74 std::vector<std::string> FrontendActionTest::GetCommandLineFlagsForTesting(
75 absl::string_view input_file) {
76 return {"tool", "-fsyntax-only", "--std=c++17",
77 "-I.", "-Wno-error", std::string(input_file)};
78 }
79
Uglify(absl::string_view code)80 std::string Uglify(absl::string_view code) {
81 std::string result = absl::StrReplaceAll(code, {{"\n", " "}});
82 absl::RemoveExtraAsciiWhitespace(&result);
83 return result;
84 }
85
UglifyAll(const std::vector<std::string> & snippets)86 std::vector<std::string> UglifyAll(const std::vector<std::string>& snippets) {
87 std::vector<std::string> result;
88 result.reserve(snippets.size());
89 std::transform(snippets.cbegin(), snippets.cend(), std::back_inserter(result),
90 Uglify);
91 return result;
92 }
93
94 } // namespace sapi
95