[Tooling/Inclusion] Add symbol mappings for `std::experimental::filesystem`
authorYounan Zhang <zyn7109@gmail.com>
Mon, 13 Feb 2023 11:17:26 +0000 (19:17 +0800)
committerYounan Zhang <zyn7109@gmail.com>
Mon, 13 Feb 2023 17:07:39 +0000 (01:07 +0800)
Clangd maintains a symbol map from standard library, in order to prevent
unexpected header/symbol leaks from internal files. (e.g. files under
`bits/` for libstdc++) This symbol map was generated by a python script
that parses pages of offline cppreference archive. The script didn't
handle the case for `std::experimental::`, where most symbols are from
TS. It works well as symbols are directly laid out in the corresponding
header under `experimental` directory for most of time.

However, libstdc++'s implementation split symbols of TS FS into a few
header files located in `experimental/bits`. This would make the code
completion provide internal headers when we simply select the symbols.

There are slightly differences between TS FS and C++17 FS. Some
functions like `system_complete` was replaced by `absolute` and
relative-related operations were introduced later by another proposal.
Even so, all mainstream implementation are based on N4100, the final
filesystem TS draft that was published in 2014 and from which symbols
we've added are exported.

This fixes https://github.com/clangd/clangd/issues/1481

Reviewed By: kadircet

Differential Revision: https://reviews.llvm.org/D142836

clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
clang/lib/Tooling/Inclusions/Stdlib/StdTsSymbolMap.inc [new file with mode: 0644]
clang/unittests/Tooling/StandardLibraryTest.cpp

index 2f85379..416b531 100644 (file)
@@ -61,8 +61,9 @@ static int countSymbols(Lang Language) {
 #include "CSymbolMap.inc"
     break;
   case Lang::CXX:
-#include "StdSymbolMap.inc"
 #include "StdSpecialSymbolMap.inc"
+#include "StdSymbolMap.inc"
+#include "StdTsSymbolMap.inc"
     break;
   }
 #undef SYMBOL
@@ -130,8 +131,9 @@ static int initialize(Lang Language) {
 #include "CSymbolMap.inc"
     break;
   case Lang::CXX:
-#include "StdSymbolMap.inc"
 #include "StdSpecialSymbolMap.inc"
+#include "StdSymbolMap.inc"
+#include "StdTsSymbolMap.inc"
     break;
   }
 #undef SYMBOL
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdTsSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/StdTsSymbolMap.inc
new file mode 100644 (file)
index 0000000..7fd17ed
--- /dev/null
@@ -0,0 +1,54 @@
+// These are derived from N4100[fs.filesystem.synopsis], final
+// draft for experimental filesystem.
+// clang-format off
+SYMBOL(absolute, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(canonical, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(copy, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(copy_file, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(copy_options, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(copy_symlink, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(create_directories, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(create_directory, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(create_directory_symlink, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(create_hard_link, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(create_symlink, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(current_path, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(directory_entry, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(directory_iterator, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(directory_options, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(equivalent, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(exists, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(file_size, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(file_status, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(file_time_type, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(file_type, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(filesystem_error, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(hard_link_count, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(is_block_file, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(is_character_file, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(is_directory, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(is_empty, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(is_fifo, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(is_other, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(is_regular_file, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(is_socket, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(is_symlink, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(last_write_time, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(path, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(permissions, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(perms, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(read_symlink, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(recursive_directory_iterator, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(remove, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(remove_all, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(rename, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(resize_file, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(space, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(space_info, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(status, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(status_known, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(symlink_status, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(system_complete, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(temp_directory_path, std::experimental::filesystem::, <experimental/filesystem>)
+SYMBOL(u8path, std::experimental::filesystem::, <experimental/filesystem>)
+// clang-format on
index c7b83aa..47d064b 100644 (file)
@@ -79,6 +79,23 @@ TEST(StdlibTest, All) {
   EXPECT_FALSE(stdlib::Header::named("<ios646.h>", stdlib::Lang::CXX));
 }
 
+TEST(StdlibTest, Experimental) {
+  EXPECT_FALSE(
+      stdlib::Header::named("<experimental/filesystem>", stdlib::Lang::C));
+  EXPECT_TRUE(
+      stdlib::Header::named("<experimental/filesystem>", stdlib::Lang::CXX));
+
+  auto Symbol = stdlib::Symbol::named("std::experimental::filesystem::",
+                                      "system_complete");
+  EXPECT_TRUE(Symbol);
+  EXPECT_EQ(Symbol->scope(), "std::experimental::filesystem::");
+  EXPECT_EQ(Symbol->name(), "system_complete");
+  EXPECT_EQ(Symbol->header(),
+            stdlib::Header::named("<experimental/filesystem>"));
+  EXPECT_EQ(Symbol->qualifiedName(),
+            "std::experimental::filesystem::system_complete");
+}
+
 TEST(StdlibTest, CCompat) {
   EXPECT_THAT(
       stdlib::Symbol::named("", "int16_t", stdlib::Lang::CXX)->headers(),