From 9ae98bc81b90b97e588cd1e4f9f171030621f465 Mon Sep 17 00:00:00 2001 From: Itamar Date: Thu, 19 Aug 2021 16:06:37 +0300 Subject: [PATCH] LibCpp: Handle circular imports gracefully This patch prevents CppComprehensionEngine from endlessly looping when there's a circular #include in the code. We now keep track of the set of currently processed files, and will not re-process a file if it already exists in this set. When we're done with processing a file it is removed from this set. The pragma once directive is not yet implemented, but regardless a mechanism that prevents #include loops even in the absence of pragma once is desired. --- .../LanguageServers/Cpp/CppComprehensionEngine.cpp | 6 ++++++ .../HackStudio/LanguageServers/Cpp/CppComprehensionEngine.h | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp index 22640c3a95..6bdf8bdbf9 100644 --- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp +++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,11 @@ const CppComprehensionEngine::DocumentData* CppComprehensionEngine::get_document OwnPtr CppComprehensionEngine::create_document_data_for(const String& file) { + if (m_unfinished_documents.contains(file)) { + return {}; + } + m_unfinished_documents.set(file); + ScopeGuard mark_finished([&file, this]() { m_unfinished_documents.remove(file); }); auto document = filedb().get_or_create_from_filesystem(file); if (!document) return {}; diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.h b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.h index 742688219f..d0d83720b4 100644 --- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.h +++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.h @@ -140,6 +140,11 @@ private: void for_each_included_document_recursive(const DocumentData&, Func) const; HashMap> m_documents; + + // A document's path will be in this set if we're currently processing it. + // A document is added to this set when we start processing it (e.g because it was #included) and removed when we're done. + // We use this to prevent circular #includes from looping indefinitely. + HashTable m_unfinished_documents; }; template