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.
This commit is contained in:
Itamar 2021-08-19 16:06:37 +03:00 committed by Andreas Kling
parent 68d895eb7c
commit 9ae98bc81b
2 changed files with 11 additions and 0 deletions

View file

@ -8,6 +8,7 @@
#include <AK/Assertions.h>
#include <AK/HashTable.h>
#include <AK/OwnPtr.h>
#include <AK/ScopeGuard.h>
#include <LibCore/DirIterator.h>
#include <LibCore/File.h>
#include <LibCpp/AST.h>
@ -44,6 +45,11 @@ const CppComprehensionEngine::DocumentData* CppComprehensionEngine::get_document
OwnPtr<CppComprehensionEngine::DocumentData> 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 {};

View file

@ -140,6 +140,11 @@ private:
void for_each_included_document_recursive(const DocumentData&, Func) const;
HashMap<String, OwnPtr<DocumentData>> 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<String> m_unfinished_documents;
};
template<typename Func>