From 4572a642b29c03118e0f2037405a1ee95265e6fc Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 21 Feb 2019 13:05:28 -0800 Subject: [PATCH 01/17] [DirectoryWatcher] License, end-of-include-guard comment https://reviews.llvm.org/D58418 --- include/clang/DirectoryWatcher/DirectoryWatcher.h | 9 ++++----- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 7 +++---- lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h | 7 +++---- lib/DirectoryWatcher/DirectoryWatcher.cpp | 7 +++---- unittests/DirectoryWatcher/DirectoryWatcherTest.cpp | 7 +++---- 5 files changed, 16 insertions(+), 21 deletions(-) diff --git a/include/clang/DirectoryWatcher/DirectoryWatcher.h b/include/clang/DirectoryWatcher/DirectoryWatcher.h index 2739955a113..f99d4ffcdd6 100644 --- a/include/clang/DirectoryWatcher/DirectoryWatcher.h +++ b/include/clang/DirectoryWatcher/DirectoryWatcher.h @@ -1,9 +1,8 @@ //===- DirectoryWatcher.h - Listens for directory file changes --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file @@ -64,4 +63,4 @@ class DirectoryWatcher { } // namespace clang -#endif +#endif // LLVM_CLANG_DIRECTORYWATCHER_DIRECTORYWATCHER_H diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index ddb492ab2ff..a1452124380 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -1,9 +1,8 @@ //===- DirectoryWatcher-linux.inc.h - Linux-platform directory listening --===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h index 826e9bea4fd..0fe816ff3e3 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h @@ -1,9 +1,8 @@ //===- DirectoryWatcher-mac.inc.h - Mac-platform directory listening ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/DirectoryWatcher/DirectoryWatcher.cpp b/lib/DirectoryWatcher/DirectoryWatcher.cpp index 0feaacefe7a..cbc3b291c9b 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher.cpp +++ b/lib/DirectoryWatcher/DirectoryWatcher.cpp @@ -1,9 +1,8 @@ //===- DirectoryWatcher.cpp - Listens for directory file changes ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file diff --git a/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp b/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp index 5fec06a64d6..1b114672281 100644 --- a/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp +++ b/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp @@ -1,9 +1,8 @@ //===- unittests/DirectoryWatcher/DirectoryWatcherTest.cpp ----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// From 097b695dfa2551ff02472f0e852c208f52ff1475 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 21 Feb 2019 13:45:27 -0800 Subject: [PATCH 02/17] [DirectoryWatcher] Handle EINTR on Linux https://reviews.llvm.org/D58418 --- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index a1452124380..fee74144d12 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -98,6 +98,8 @@ static void runWatcher(std::string pathToWatch, int inotifyFD, while (1) { ssize_t numRead = read(inotifyFD, buf, EVT_BUF_LEN); if (numRead == -1) { + if (errno == EINTR) + continue; return; // watcher is stopped. } From be13d1e9210be58dd0857448dc57d581dc0cba1a Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 21 Feb 2019 13:51:35 -0800 Subject: [PATCH 03/17] [DirectoryWatcher] Add assert on bytes read when reading INotifyEvents https://reviews.llvm.org/D58418 --- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index fee74144d12..456c650546c 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -105,7 +105,8 @@ static void runWatcher(std::string pathToWatch, int inotifyFD, SmallVector iEvents; for (char *p = buf; p < buf + numRead;) { - struct inotify_event *ievt = (struct inotify_event *)p; + assert(p + sizeof(struct inotify_event) <= buf + numRead && "a whole inotify_event was read"); + struct inotify_event *ievt = dynamic_cast(p); p += sizeof(struct inotify_event) + ievt->len; if (ievt->mask & IN_DELETE_SELF) { From 587b7cd70e56e8e748771e4efd8dda03e5ea9e4d Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 21 Feb 2019 14:46:38 -0800 Subject: [PATCH 04/17] [DirectoryWatcher] Handle errors returned by close() https://reviews.llvm.org/D58418 --- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index 456c650546c..a2e8e10da9e 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -193,6 +193,10 @@ bool DirectoryWatcher::Implementation::initialize(StringRef Path, void DirectoryWatcher::Implementation::stopListening() { if (inotifyFD == -1) return; - close(inotifyFD); + while (true) { + if (close(inotifyFD) == -1 && errno == EINTR) + continue; + break; + } inotifyFD = -1; } From a6d8187fe4bd9b2897b09e88d439cdbac4e53fd9 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 28 Feb 2019 15:28:44 -0800 Subject: [PATCH 05/17] [DirectoryWatcher][NFC] clang-format # Conflicts: # lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h --- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index a2e8e10da9e..f9f26a74c63 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -92,11 +92,11 @@ struct DirectoryWatcher::Implementation { static void runWatcher(std::string pathToWatch, int inotifyFD, std::shared_ptr evtQueue) { - #define EVT_BUF_LEN (30 * (sizeof(struct inotify_event) + NAME_MAX + 1)) - char buf[EVT_BUF_LEN] __attribute__ ((aligned(8))); + constexpr size_t EventBufferLength = 30 * (sizeof(struct inotify_event) + NAME_MAX + 1); + char buf[EventBufferLength] __attribute__((aligned(8))); while (1) { - ssize_t numRead = read(inotifyFD, buf, EVT_BUF_LEN); + ssize_t numRead = read(inotifyFD, buf, EventBufferLength); if (numRead == -1) { if (errno == EINTR) continue; From 23fa92ae439aa38c1eb75f4bfe64c583e5cb46ae Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Mon, 25 Feb 2019 15:22:55 -0800 Subject: [PATCH 06/17] [DirectoryWatcher] Add assert for unknown event kinds https://reviews.llvm.org/D58418 --- .../DirectoryWatcher-linux.inc.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index f9f26a74c63..7eb692dbe75 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -116,16 +116,15 @@ static void runWatcher(std::string pathToWatch, int inotifyFD, break; } - DirectoryWatcher::EventKind K = DirectoryWatcher::EventKind::Added; - if (ievt->mask & IN_MODIFY) { - K = DirectoryWatcher::EventKind::Modified; - } - if (ievt->mask & IN_MOVED_TO) { - K = DirectoryWatcher::EventKind::Added; - } - if (ievt->mask & IN_DELETE) { - K = DirectoryWatcher::EventKind::Removed; - } + DirectoryWatcher::EventKind K = [&ievt](){ + if (ievt->mask & IN_MODIFY) + return DirectoryWatcher::EventKind::Modified; + if (ievt->mask & IN_MOVED_TO) + return DirectoryWatcher::EventKind::Added; + if (ievt->mask & IN_DELETE) + return DirectoryWatcher::EventKind::Removed; + llvm_unreachable("Unknown event type."); + }(); assert(ievt->len > 0 && "expected a filename from inotify"); SmallString<256> fullPath{pathToWatch}; From c521b8bca1362165370d35f0c4da6b62a3a944e5 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 28 Feb 2019 15:35:19 -0800 Subject: [PATCH 07/17] [DirectoryWatcher] Removed ModTime https://reviews.llvm.org/D58418 # Conflicts: # lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h # lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h # lib/DirectoryWatcher/DirectoryWatcher.cpp # unittests/DirectoryWatcher/DirectoryWatcherTest.cpp --- include/clang/DirectoryWatcher/DirectoryWatcher.h | 1 - lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 4 +--- lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h | 11 +++++------ lib/DirectoryWatcher/DirectoryWatcher.cpp | 3 ++- lib/IndexDataStore/IndexDataStore.cpp | 3 ++- unittests/DirectoryWatcher/DirectoryWatcherTest.cpp | 11 ++++------- 6 files changed, 14 insertions(+), 19 deletions(-) diff --git a/include/clang/DirectoryWatcher/DirectoryWatcher.h b/include/clang/DirectoryWatcher/DirectoryWatcher.h index f99d4ffcdd6..c3877f2d976 100644 --- a/include/clang/DirectoryWatcher/DirectoryWatcher.h +++ b/include/clang/DirectoryWatcher/DirectoryWatcher.h @@ -40,7 +40,6 @@ class DirectoryWatcher { struct Event { EventKind Kind; std::string Filename; - llvm::sys::TimePoint<> ModTime; }; typedef std::function Events, bool isInitial)> EventReceiver; diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index 7eb692dbe75..67a1d2e6494 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -28,9 +28,7 @@ class EventQueue { std::vector PendingEvents; DirectoryWatcher::Event toDirEvent(const INotifyEvent &evt) { - llvm::sys::TimePoint<> modTime{}; - if (evt.Status.hasValue()) modTime = evt.Status->getLastModificationTime(); - return DirectoryWatcher::Event{evt.K, evt.Filename, modTime}; + return DirectoryWatcher::Event{evt.K, evt.Filename}; } public: diff --git a/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h index 0fe816ff3e3..9b0cf39d072 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h @@ -56,8 +56,10 @@ static void eventStreamCallback( StringRef path = ((const char **)eventPaths)[i]; const FSEventStreamEventFlags flags = eventFlags[i]; if (!(flags & kFSEventStreamEventFlagItemIsFile)) { - if ((flags & kFSEventStreamEventFlagItemRemoved) && path == ctx->WatchedPath) { - DirectoryWatcher::Event Evt{DirectoryWatcher::EventKind::DirectoryDeleted, path, llvm::sys::TimePoint<>{} }; + if ((flags & kFSEventStreamEventFlagItemRemoved) && + path == ctx->WatchedPath) { + DirectoryWatcher::Event Evt{ + DirectoryWatcher::EventKind::DirectoryDeleted, path}; Events.push_back(Evt); break; } @@ -97,10 +99,7 @@ static void eventStreamCallback( } } - llvm::sys::TimePoint<> modTime{}; - if (statusOpt.hasValue()) - modTime = statusOpt->getLastModificationTime(); - DirectoryWatcher::Event Evt{K, path, modTime}; + DirectoryWatcher::Event Evt{K, path}; Events.push_back(Evt); } diff --git a/lib/DirectoryWatcher/DirectoryWatcher.cpp b/lib/DirectoryWatcher/DirectoryWatcher.cpp index cbc3b291c9b..0902e2fc003 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher.cpp +++ b/lib/DirectoryWatcher/DirectoryWatcher.cpp @@ -77,7 +77,8 @@ struct DirectoryScan { std::vector getAsFileEvents() const { std::vector Events; for (const auto &info : Files) { - DirectoryWatcher::Event Event{DirectoryWatcher::EventKind::Added, std::get<0>(info), std::get<1>(info)}; + DirectoryWatcher::Event Event{DirectoryWatcher::EventKind::Added, + std::get<0>(info)}; Events.push_back(std::move(Event)); } return Events; diff --git a/lib/IndexDataStore/IndexDataStore.cpp b/lib/IndexDataStore/IndexDataStore.cpp index ec7a346935c..abe27d942f3 100644 --- a/lib/IndexDataStore/IndexDataStore.cpp +++ b/lib/IndexDataStore/IndexDataStore.cpp @@ -12,6 +12,7 @@ #include "../lib/Index/IndexDataStoreUtils.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Chrono.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/Path.h" @@ -126,7 +127,7 @@ bool IndexDataStoreImpl::startEventListening(bool waitInitialSync, std::string & UnitName = StringRef(); break; } - UnitEvents.push_back(IndexDataStore::UnitEvent{K, UnitName, evt.ModTime}); + UnitEvents.push_back(IndexDataStore::UnitEvent{K, UnitName, llvm::sys::TimePoint<>{}}); } if (auto handler = localUnitEventHandlerData->getHandler()) { diff --git a/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp b/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp index 1b114672281..e7941a18eb3 100644 --- a/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp +++ b/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp @@ -47,10 +47,10 @@ class EventCollection { for (unsigned i = 0, e = filenames.size(); i < e; ++i) { StringRef fname = filenames[i]; DirectoryWatcher::EventKind kind = kinds[i]; - file_status stat = stats[i]; - auto it = std::find_if(evts.begin(), evts.end(), [&](const DirectoryWatcher::Event &evt)->bool { - return path::filename(evt.Filename) == fname; - }); + auto it = std::find_if(evts.begin(), evts.end(), + [&](const DirectoryWatcher::Event &evt) -> bool { + return path::filename(evt.Filename) == fname; + }); if (it == evts.end()) { hadError = err(Twine("expected filename '"+fname+"' not found")); continue; @@ -60,9 +60,6 @@ class EventCollection { std::to_string((int)it->Kind) + ", expected ") + std::to_string((int)kind)); } - if (it->Kind != DirectoryWatcher::EventKind::Removed && - it->ModTime != stat.getLastModificationTime()) - hadError = err(Twine("filename '"+fname+"' has different mod time")); evts.erase(it); } for (const auto &evt : evts) { From 87c4bf1544f096c6fa07223666375787d390cc1f Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Mon, 25 Feb 2019 15:34:18 -0800 Subject: [PATCH 08/17] [DirectoryWatcher] Propagating events from inotify directly Conclusion from the code review is that we won't try to workaround race conditions since file system doesn't provide means to do it properly. https://reviews.llvm.org/D58418 --- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index 67a1d2e6494..cf531a8a403 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -129,11 +129,6 @@ static void runWatcher(std::string pathToWatch, int inotifyFD, sys::path::append(fullPath, ievt->name); Optional statusOpt; - if (K != DirectoryWatcher::EventKind::Removed) { - statusOpt = getFileStatus(fullPath); - if (!statusOpt.hasValue()) - K = DirectoryWatcher::EventKind::Removed; - } INotifyEvent iEvt{K, fullPath.str(), statusOpt}; iEvents.push_back(iEvt); } From 4a1b333fe2631802ec080443403c0913f430de2b Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Tue, 26 Feb 2019 11:15:38 -0800 Subject: [PATCH 09/17] [DirectoryWatcher] Use RetryAfterSignal https://reviews.llvm.org/D58418 --- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index cf531a8a403..e58034dd261 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -94,12 +94,7 @@ static void runWatcher(std::string pathToWatch, int inotifyFD, char buf[EventBufferLength] __attribute__((aligned(8))); while (1) { - ssize_t numRead = read(inotifyFD, buf, EventBufferLength); - if (numRead == -1) { - if (errno == EINTR) - continue; - return; // watcher is stopped. - } + ssize_t numRead = RetryAfterSignal(-1, read, inotifyFD, buf, EventBufferLength); SmallVector iEvents; for (char *p = buf; p < buf + numRead;) { @@ -185,10 +180,6 @@ bool DirectoryWatcher::Implementation::initialize(StringRef Path, void DirectoryWatcher::Implementation::stopListening() { if (inotifyFD == -1) return; - while (true) { - if (close(inotifyFD) == -1 && errno == EINTR) - continue; - break; - } + RetryAfterSignal(-1, close, inotifyFD); inotifyFD = -1; } From e668336bb8af18cb76820f06fbd10ae70934814d Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 28 Feb 2019 15:36:42 -0800 Subject: [PATCH 10/17] [DirectoryWatcher] Use CMake for platform-specific dependencies check https://reviews.llvm.org/D58418 # Conflicts: # lib/DirectoryWatcher/DirectoryWatcher.cpp --- lib/DirectoryWatcher/CMakeLists.txt | 30 ++++++++++---- lib/DirectoryWatcher/Config.inc.in | 2 + lib/DirectoryWatcher/DirectoryWatcher.cpp | 48 +++++++++++------------ 3 files changed, 48 insertions(+), 32 deletions(-) create mode 100644 lib/DirectoryWatcher/Config.inc.in diff --git a/lib/DirectoryWatcher/CMakeLists.txt b/lib/DirectoryWatcher/CMakeLists.txt index 5b506166b7a..4b5ddb364b0 100644 --- a/lib/DirectoryWatcher/CMakeLists.txt +++ b/lib/DirectoryWatcher/CMakeLists.txt @@ -6,13 +6,29 @@ add_clang_library(clangDirectoryWatcher DirectoryWatcher.cpp ) -if(BUILD_SHARED_LIBS) - if(APPLE) - check_include_files("CoreServices/CoreServices.h" HAVE_CORESERVICES_H) - if(HAVE_CORESERVICES_H) - set(DIRECTORY_WATCHER_FLAGS "${DIRECTORY_WATCHER_FLAGS} -framework CoreServices") - endif() +if(APPLE) + check_include_files("CoreServices/CoreServices.h" HAVE_CORESERVICES) + if(HAVE_CORESERVICES) + set(DIRECTORY_WATCHER_FLAGS "${DIRECTORY_WATCHER_FLAGS} -framework CoreServices") set_property(TARGET clangDirectoryWatcher APPEND_STRING PROPERTY - LINK_FLAGS ${DIRECTORY_WATCHER_FLAGS}) + LINK_FLAGS ${DIRECTORY_WATCHER_FLAGS}) endif() +elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") + check_include_files("sys/inotify.h" HAVE_INOTIFY) endif() + +llvm_canonicalize_cmake_booleans( + HAVE_CORESERVICES) +llvm_canonicalize_cmake_booleans( + HAVE_INOTIFY) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/Config.inc.in + ${CMAKE_CURRENT_BINARY_DIR}/Config.inc +) + +if(BUILD_SHARED_LIBS AND APPLE AND HAVE_CORESERVICES) + set(DIRECTORY_WATCHER_FLAGS "${DIRECTORY_WATCHER_FLAGS} -framework CoreServices") + set_property(TARGET clangDirectoryWatcher APPEND_STRING PROPERTY + LINK_FLAGS ${DIRECTORY_WATCHER_FLAGS}) +endif() \ No newline at end of file diff --git a/lib/DirectoryWatcher/Config.inc.in b/lib/DirectoryWatcher/Config.inc.in new file mode 100644 index 00000000000..e01bbf4ca88 --- /dev/null +++ b/lib/DirectoryWatcher/Config.inc.in @@ -0,0 +1,2 @@ +#define HAVE_CORESERVICES @HAVE_CORESERVICES@ +#define HAVE_INOTIFY @HAVE_INOTIFY@ \ No newline at end of file diff --git a/lib/DirectoryWatcher/DirectoryWatcher.cpp b/lib/DirectoryWatcher/DirectoryWatcher.cpp index 0902e2fc003..5b457434d64 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher.cpp +++ b/lib/DirectoryWatcher/DirectoryWatcher.cpp @@ -45,11 +45,12 @@ template <> struct DenseMapInfo { std::make_pair(val.getDevice(), val.getFile())); } - static bool isEqual(const sys::fs::UniqueID &LHS, const sys::fs::UniqueID &RHS) { + static bool isEqual(const sys::fs::UniqueID &LHS, + const sys::fs::UniqueID &RHS) { return LHS == RHS; } }; -} +} // namespace llvm namespace { /// Used for initial directory scan. @@ -64,12 +65,14 @@ struct DirectoryScan { using namespace llvm::sys; std::error_code EC; - for (auto It = fs::directory_iterator(Path, EC), End = fs::directory_iterator(); - !EC && It != End; It.increment(EC)) { + for (auto It = fs::directory_iterator(Path, EC), + End = fs::directory_iterator(); + !EC && It != End; It.increment(EC)) { auto status = getFileStatus(It->path()); if (!status.hasValue()) continue; - Files.push_back(std::make_tuple(It->path(), status->getLastModificationTime())); + Files.push_back( + std::make_tuple(It->path(), status->getLastModificationTime())); FileIDSet.insert(status->getUniqueID()); } } @@ -84,23 +87,20 @@ struct DirectoryScan { return Events; } }; -} +} // namespace // Add platform-specific functionality. +#include "Config.inc" -#if !defined(__has_include) -# define __has_include(x) 0 -#endif - -#if __has_include() -# include "DirectoryWatcher-mac.inc.h" -#elif __has_include() -# include "DirectoryWatcher-linux.inc.h" +#if HAVE_CORESERVICES +#include "DirectoryWatcher-mac.inc.h" +#elif HAVE_INOTIFY +#include "DirectoryWatcher-linux.inc.h" #else struct DirectoryWatcher::Implementation { - bool initialize(StringRef Path, EventReceiver Receiver, - bool waitInitialSync, std::string &Error) { + bool initialize(StringRef Path, EventReceiver Receiver, bool waitInitialSync, + std::string &Error) { Error = "directory listening not supported for this platform"; return true; } @@ -108,16 +108,13 @@ struct DirectoryWatcher::Implementation { #endif +DirectoryWatcher::DirectoryWatcher() : Impl(*new Implementation()) {} -DirectoryWatcher::DirectoryWatcher() - : Impl(*new Implementation()) {} - -DirectoryWatcher::~DirectoryWatcher() { - delete &Impl; -} +DirectoryWatcher::~DirectoryWatcher() { delete &Impl; } -std::unique_ptr DirectoryWatcher::create(StringRef Path, - EventReceiver Receiver, bool waitInitialSync, std::string &Error) { +std::unique_ptr +DirectoryWatcher::create(StringRef Path, EventReceiver Receiver, + bool waitInitialSync, std::string &Error) { using namespace llvm::sys; if (!fs::exists(Path)) { @@ -143,7 +140,8 @@ std::unique_ptr DirectoryWatcher::create(StringRef Path, std::unique_ptr DirWatch; DirWatch.reset(new DirectoryWatcher()); auto &Impl = DirWatch->Impl; - bool hasError = Impl.initialize(Path, std::move(Receiver), waitInitialSync, Error); + bool hasError = + Impl.initialize(Path, std::move(Receiver), waitInitialSync, Error); if (hasError) return nullptr; From 652cfc1ccc0b07ea337df78be57d4411f26f77d8 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Wed, 27 Feb 2019 18:13:43 -0800 Subject: [PATCH 11/17] [DirectoryWatcher] Fix the build - qualify RetryAfterSignal with llvm:: --- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index e58034dd261..5d359af7093 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -94,7 +94,7 @@ static void runWatcher(std::string pathToWatch, int inotifyFD, char buf[EventBufferLength] __attribute__((aligned(8))); while (1) { - ssize_t numRead = RetryAfterSignal(-1, read, inotifyFD, buf, EventBufferLength); + ssize_t numRead = llvm::RetryAfterSignal(-1, read, inotifyFD, buf, EventBufferLength); SmallVector iEvents; for (char *p = buf; p < buf + numRead;) { @@ -180,6 +180,6 @@ bool DirectoryWatcher::Implementation::initialize(StringRef Path, void DirectoryWatcher::Implementation::stopListening() { if (inotifyFD == -1) return; - RetryAfterSignal(-1, close, inotifyFD); + llvm::RetryAfterSignal(-1, close, inotifyFD); inotifyFD = -1; } From c280267d991c15f58d92d4b0185d3457ffc617d3 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 28 Feb 2019 09:49:56 -0800 Subject: [PATCH 12/17] [DirectoryWatcher] Fix the build - qualify RetryAfterSignal with llvm::sys --- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index 5d359af7093..63b6f525f64 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -94,7 +94,7 @@ static void runWatcher(std::string pathToWatch, int inotifyFD, char buf[EventBufferLength] __attribute__((aligned(8))); while (1) { - ssize_t numRead = llvm::RetryAfterSignal(-1, read, inotifyFD, buf, EventBufferLength); + ssize_t numRead = llvm::sys::RetryAfterSignal(-1, read, inotifyFD, buf, EventBufferLength); SmallVector iEvents; for (char *p = buf; p < buf + numRead;) { @@ -180,6 +180,6 @@ bool DirectoryWatcher::Implementation::initialize(StringRef Path, void DirectoryWatcher::Implementation::stopListening() { if (inotifyFD == -1) return; - llvm::RetryAfterSignal(-1, close, inotifyFD); + llvm::sys::RetryAfterSignal(-1, close, inotifyFD); inotifyFD = -1; } From e7a5aca433caf189da93e19981c2307110bf66c9 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 28 Feb 2019 10:11:18 -0800 Subject: [PATCH 13/17] [DirectoryWatcher] Fix cast --- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index 63b6f525f64..a70f4012363 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -99,7 +99,7 @@ static void runWatcher(std::string pathToWatch, int inotifyFD, SmallVector iEvents; for (char *p = buf; p < buf + numRead;) { assert(p + sizeof(struct inotify_event) <= buf + numRead && "a whole inotify_event was read"); - struct inotify_event *ievt = dynamic_cast(p); + struct inotify_event *ievt = reinterpret_cast(p); p += sizeof(struct inotify_event) + ievt->len; if (ievt->mask & IN_DELETE_SELF) { From 3e02d717fef7ad5e065bda8eb8c47b5df1166129 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 28 Feb 2019 11:04:43 -0800 Subject: [PATCH 14/17] [DirectoryWatcher] Fix passing the buffer --- lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index a70f4012363..ef6f5894cfc 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -94,7 +94,7 @@ static void runWatcher(std::string pathToWatch, int inotifyFD, char buf[EventBufferLength] __attribute__((aligned(8))); while (1) { - ssize_t numRead = llvm::sys::RetryAfterSignal(-1, read, inotifyFD, buf, EventBufferLength); + ssize_t numRead = llvm::sys::RetryAfterSignal(-1, read, inotifyFD, reinterpret_cast(buf), EventBufferLength); SmallVector iEvents; for (char *p = buf; p < buf + numRead;) { From 851ed53ed4748129c5d90c6ccc3c964bd2620ba3 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 28 Feb 2019 13:30:30 -0800 Subject: [PATCH 15/17] [DirectoryWatcher][NFC] clang-format --- .../DirectoryWatcher-linux.inc.h | 33 ++++---- .../DirectoryWatcher-mac.inc.h | 77 +++++++++---------- lib/IndexDataStore/IndexDataStore.cpp | 5 +- 3 files changed, 57 insertions(+), 58 deletions(-) diff --git a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h index ef6f5894cfc..53ad9d05c1d 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-linux.inc.h @@ -7,11 +7,11 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Errno.h" -#include "llvm/Support/Path.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/Path.h" +#include #include #include -#include namespace { @@ -73,14 +73,12 @@ class EventQueue { PendingEvents.clear(); } }; -} // namespace +} // namespace struct DirectoryWatcher::Implementation { - bool initialize(StringRef Path, EventReceiver Receiver, - bool waitInitialSync, std::string &Error); - ~Implementation() { - stopListening(); - }; + bool initialize(StringRef Path, EventReceiver Receiver, bool waitInitialSync, + std::string &Error); + ~Implementation() { stopListening(); }; private: int inotifyFD = -1; @@ -90,15 +88,18 @@ struct DirectoryWatcher::Implementation { static void runWatcher(std::string pathToWatch, int inotifyFD, std::shared_ptr evtQueue) { - constexpr size_t EventBufferLength = 30 * (sizeof(struct inotify_event) + NAME_MAX + 1); + constexpr size_t EventBufferLength = + 30 * (sizeof(struct inotify_event) + NAME_MAX + 1); char buf[EventBufferLength] __attribute__((aligned(8))); while (1) { - ssize_t numRead = llvm::sys::RetryAfterSignal(-1, read, inotifyFD, reinterpret_cast(buf), EventBufferLength); + ssize_t numRead = llvm::sys::RetryAfterSignal( + -1, read, inotifyFD, reinterpret_cast(buf), EventBufferLength); SmallVector iEvents; for (char *p = buf; p < buf + numRead;) { - assert(p + sizeof(struct inotify_event) <= buf + numRead && "a whole inotify_event was read"); + assert(p + sizeof(struct inotify_event) <= buf + numRead && + "a whole inotify_event was read"); struct inotify_event *ievt = reinterpret_cast(p); p += sizeof(struct inotify_event) + ievt->len; @@ -109,7 +110,7 @@ static void runWatcher(std::string pathToWatch, int inotifyFD, break; } - DirectoryWatcher::EventKind K = [&ievt](){ + DirectoryWatcher::EventKind K = [&ievt]() { if (ievt->mask & IN_MODIFY) return DirectoryWatcher::EventKind::Modified; if (ievt->mask & IN_MOVED_TO) @@ -144,16 +145,16 @@ bool DirectoryWatcher::Implementation::initialize(StringRef Path, return true; }; - auto evtQueue = std::make_shared(std::move(Receiver)); + auto evtQueue = std::make_shared(std::move(Receiver)); inotifyFD = inotify_init(); if (inotifyFD == -1) return error("inotify_init failed"); std::string pathToWatch = Path; - int wd = inotify_add_watch( - inotifyFD, pathToWatch.c_str(), - IN_MOVED_TO | IN_DELETE | IN_MODIFY | IN_DELETE_SELF | IN_ONLYDIR); + int wd = inotify_add_watch(inotifyFD, pathToWatch.c_str(), + IN_MOVED_TO | IN_DELETE | IN_MODIFY | + IN_DELETE_SELF | IN_ONLYDIR); if (wd == -1) return error("inotify_add_watch failed"); diff --git a/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h b/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h index 9b0cf39d072..bdfb3e9a2e8 100644 --- a/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h +++ b/lib/DirectoryWatcher/DirectoryWatcher-mac.inc.h @@ -9,11 +9,10 @@ #include struct DirectoryWatcher::Implementation { - bool initialize(StringRef Path, EventReceiver Receiver, - bool waitInitialSync, std::string &Error); - ~Implementation() { - stopFSEventStream(); - }; + bool initialize(StringRef Path, EventReceiver Receiver, bool waitInitialSync, + std::string &Error); + ~Implementation() { stopFSEventStream(); }; + private: FSEventStreamRef EventStream = nullptr; @@ -29,27 +28,24 @@ struct EventStreamContextData { DirectoryWatcher::EventReceiver Receiver; std::shared_ptr InitialScan; - EventStreamContextData(std::string watchedPath, DirectoryWatcher::EventReceiver receiver, + EventStreamContextData(std::string watchedPath, + DirectoryWatcher::EventReceiver receiver, std::shared_ptr initialScanPtr) - : WatchedPath(std::move(watchedPath)), - Receiver(std::move(receiver)), - InitialScan(std::move(initialScanPtr)) { - } + : WatchedPath(std::move(watchedPath)), Receiver(std::move(receiver)), + InitialScan(std::move(initialScanPtr)) {} static void dispose(const void *ctx) { - delete static_cast(ctx); + delete static_cast(ctx); } }; -} +} // namespace -static void eventStreamCallback( - ConstFSEventStreamRef stream, - void *clientCallBackInfo, - size_t numEvents, - void *eventPaths, - const FSEventStreamEventFlags eventFlags[], - const FSEventStreamEventId eventIds[]) { - auto *ctx = static_cast(clientCallBackInfo); +static void eventStreamCallback(ConstFSEventStreamRef stream, + void *clientCallBackInfo, size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]) { + auto *ctx = static_cast(clientCallBackInfo); std::vector Events; for (size_t i = 0; i < numEvents; ++i) { @@ -111,15 +107,17 @@ static void eventStreamCallback( } } -bool DirectoryWatcher::Implementation::setupFSEventStream(StringRef path, - EventReceiver receiver, - dispatch_queue_t queue, - std::shared_ptr initialScanPtr) { +bool DirectoryWatcher::Implementation::setupFSEventStream( + StringRef path, EventReceiver receiver, dispatch_queue_t queue, + std::shared_ptr initialScanPtr) { if (path.empty()) return true; - CFMutableArrayRef pathsToWatch = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks); - CFStringRef cfPathStr = CFStringCreateWithBytes(nullptr, (const UInt8 *)path.data(), path.size(), kCFStringEncodingUTF8, false); + CFMutableArrayRef pathsToWatch = + CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks); + CFStringRef cfPathStr = + CFStringCreateWithBytes(nullptr, (const UInt8 *)path.data(), path.size(), + kCFStringEncodingUTF8, false); CFArrayAppendValue(pathsToWatch, cfPathStr); CFRelease(cfPathStr); CFAbsoluteTime latency = 0.0; // Latency in seconds. @@ -136,9 +134,8 @@ bool DirectoryWatcher::Implementation::setupFSEventStream(StringRef path, realPath = path; } - EventStreamContextData *ctxData = - new EventStreamContextData(std::move(realPath), std::move(receiver), - std::move(initialScanPtr)); + EventStreamContextData *ctxData = new EventStreamContextData( + std::move(realPath), std::move(receiver), std::move(initialScanPtr)); FSEventStreamContext context; context.version = 0; context.info = ctxData; @@ -146,14 +143,10 @@ bool DirectoryWatcher::Implementation::setupFSEventStream(StringRef path, context.release = EventStreamContextData::dispose; context.copyDescription = nullptr; - EventStream = FSEventStreamCreate(nullptr, - eventStreamCallback, - &context, - pathsToWatch, - kFSEventStreamEventIdSinceNow, - latency, - kFSEventStreamCreateFlagFileEvents | - kFSEventStreamCreateFlagNoDefer); + EventStream = FSEventStreamCreate( + nullptr, eventStreamCallback, &context, pathsToWatch, + kFSEventStreamEventIdSinceNow, latency, + kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagNoDefer); CFRelease(pathsToWatch); if (!EventStream) { return true; @@ -173,10 +166,13 @@ void DirectoryWatcher::Implementation::stopFSEventStream() { } bool DirectoryWatcher::Implementation::initialize(StringRef Path, - EventReceiver Receiver, bool waitInitialSync, std::string &Error) { + EventReceiver Receiver, + bool waitInitialSync, + std::string &Error) { auto initialScan = std::make_shared(); - dispatch_queue_t queue = dispatch_queue_create("DirectoryWatcher", DISPATCH_QUEUE_SERIAL); + dispatch_queue_t queue = + dispatch_queue_create("DirectoryWatcher", DISPATCH_QUEUE_SERIAL); dispatch_semaphore_t initScanSema = dispatch_semaphore_create(0); dispatch_semaphore_t setupFSEventsSema = dispatch_semaphore_create(0); @@ -204,7 +200,8 @@ bool DirectoryWatcher::Implementation::initialize(StringRef Path, dispatch_release(queue); if (fsErr) { - raw_string_ostream(Error) << "failed to setup FSEvents stream for path: " << Path; + raw_string_ostream(Error) + << "failed to setup FSEvents stream for path: " << Path; return true; } diff --git a/lib/IndexDataStore/IndexDataStore.cpp b/lib/IndexDataStore/IndexDataStore.cpp index abe27d942f3..6fdf64e9c7a 100644 --- a/lib/IndexDataStore/IndexDataStore.cpp +++ b/lib/IndexDataStore/IndexDataStore.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "clang/Index/IndexDataStore.h" -#include "clang/DirectoryWatcher/DirectoryWatcher.h" #include "../lib/Index/IndexDataStoreUtils.h" +#include "clang/DirectoryWatcher/DirectoryWatcher.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Chrono.h" @@ -127,7 +127,8 @@ bool IndexDataStoreImpl::startEventListening(bool waitInitialSync, std::string & UnitName = StringRef(); break; } - UnitEvents.push_back(IndexDataStore::UnitEvent{K, UnitName, llvm::sys::TimePoint<>{}}); + UnitEvents.push_back( + IndexDataStore::UnitEvent{K, UnitName, llvm::sys::TimePoint<>{}}); } if (auto handler = localUnitEventHandlerData->getHandler()) { From 26285043fe9be84c71bad28f55d1248059604294 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 14 Mar 2019 15:30:32 -0700 Subject: [PATCH 16/17] [DirectoryWatcher][NFC] Remove duplicated comment --- include/clang/DirectoryWatcher/DirectoryWatcher.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/clang/DirectoryWatcher/DirectoryWatcher.h b/include/clang/DirectoryWatcher/DirectoryWatcher.h index c3877f2d976..b052b85a4ad 100644 --- a/include/clang/DirectoryWatcher/DirectoryWatcher.h +++ b/include/clang/DirectoryWatcher/DirectoryWatcher.h @@ -3,11 +3,6 @@ // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// \file -/// \brief Utility class for listening for file system changes in a directory. -//===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_DIRECTORYWATCHER_DIRECTORYWATCHER_H #define LLVM_CLANG_DIRECTORYWATCHER_DIRECTORYWATCHER_H From 63bdba2269f92d2be3eb655bc8f1dd517ae63663 Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 14 Mar 2019 15:37:40 -0700 Subject: [PATCH 17/17] [DirectoryWatcher][NFC] Remove duplicated comment - fixup --- include/clang/DirectoryWatcher/DirectoryWatcher.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/clang/DirectoryWatcher/DirectoryWatcher.h b/include/clang/DirectoryWatcher/DirectoryWatcher.h index b052b85a4ad..a96b09ad1e4 100644 --- a/include/clang/DirectoryWatcher/DirectoryWatcher.h +++ b/include/clang/DirectoryWatcher/DirectoryWatcher.h @@ -3,6 +3,8 @@ // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_DIRECTORYWATCHER_DIRECTORYWATCHER_H #define LLVM_CLANG_DIRECTORYWATCHER_DIRECTORYWATCHER_H