From 024cfda06cc4f4fb7112344ee7b27d2e1d99978d Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar <nikolai.kosjar@qt.io> Date: Tue, 22 Aug 2017 14:51:34 +0200 Subject: [PATCH] Clang: Ensure that an unparsed translation unit is not suspended Currently this might happen when registerTranslationUnitsForEditor is called with visible documents that are not the ones that are registered. Change-Id: I9ae5f75c8bbff6a11161a3387633726066001062 Reviewed-by: Marco Bubke <marco.bubke@qt.io> --- .../clangbackend/ipcsource/clangdocument.cpp | 5 ++++ .../clangbackend/ipcsource/clangdocument.h | 1 + .../clangdocumentsuspenderresumer.cpp | 3 ++- .../clangdocumentsuspenderresumer-test.cpp | 27 +++++++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/tools/clangbackend/ipcsource/clangdocument.cpp b/src/tools/clangbackend/ipcsource/clangdocument.cpp index a4f95d17b84..cbbaf51b332 100644 --- a/src/tools/clangbackend/ipcsource/clangdocument.cpp +++ b/src/tools/clangbackend/ipcsource/clangdocument.cpp @@ -150,6 +150,11 @@ bool Document::isIntact() const && !d->hasParseOrReparseFailed; } +bool Document::isParsed() const +{ + return d->translationUnits.areAllTranslationUnitsParsed(); +} + Utf8String Document::filePath() const { checkIfNull(); diff --git a/src/tools/clangbackend/ipcsource/clangdocument.h b/src/tools/clangbackend/ipcsource/clangdocument.h index 260705c1354..415deefbe9d 100644 --- a/src/tools/clangbackend/ipcsource/clangdocument.h +++ b/src/tools/clangbackend/ipcsource/clangdocument.h @@ -77,6 +77,7 @@ public: bool isNull() const; bool isIntact() const; + bool isParsed() const; Utf8String filePath() const; Utf8StringVector fileArguments() const; diff --git a/src/tools/clangbackend/ipcsource/clangdocumentsuspenderresumer.cpp b/src/tools/clangbackend/ipcsource/clangdocumentsuspenderresumer.cpp index 8edde48fd62..bae98893187 100644 --- a/src/tools/clangbackend/ipcsource/clangdocumentsuspenderresumer.cpp +++ b/src/tools/clangbackend/ipcsource/clangdocumentsuspenderresumer.cpp @@ -97,7 +97,8 @@ static bool isSuspendable(const Document &document) { return isFineDocument(document) && !document.isSuspended() - && !document.isVisibleInEditor(); + && !document.isVisibleInEditor() + && document.isParsed(); } static bool isResumable(const Document &document) diff --git a/tests/unit/unittest/clangdocumentsuspenderresumer-test.cpp b/tests/unit/unittest/clangdocumentsuspenderresumer-test.cpp index 8ab78ebded6..823a84482ca 100644 --- a/tests/unit/unittest/clangdocumentsuspenderresumer-test.cpp +++ b/tests/unit/unittest/clangdocumentsuspenderresumer-test.cpp @@ -73,6 +73,7 @@ protected: Document getDocument(const Utf8String &filePath); void categorizeDocuments(int hotDocumentsSize); SuspendResumeJobs createSuspendResumeJobs(int hotDocumentsSize = -1); + static void setParsed(Document &document); protected: ClangBackEnd::ProjectParts projects; @@ -176,6 +177,8 @@ TEST_F(DocumentSuspenderResumer, CreateSuspendJobForInvisible) Document document = documents.create({fileContainer1})[0]; document.setIsSuspended(false); document.setIsVisibleInEditor(false, Clock::now()); + setParsed(document); + const SuspendResumeJobs expectedJobs = { {document, JobRequest::Type::SuspendDocument, PreferredTranslationUnit::RecentlyParsed} }; @@ -196,12 +199,24 @@ TEST_F(DocumentSuspenderResumer, DoNotCreateSuspendJobForVisible) ASSERT_THAT(jobs, ContainerEq(SuspendResumeJobs())); } +TEST_F(DocumentSuspenderResumer, DoNotCreateSuspendJobForUnparsed) +{ + Document document = documents.create({fileContainer1})[0]; + document.setIsSuspended(false); + document.setIsVisibleInEditor(true, Clock::now()); + + const SuspendResumeJobs jobs = createSuspendResumeJobs(/*hotDocumentsSize=*/ 0); + + ASSERT_THAT(jobs, ContainerEq(SuspendResumeJobs())); +} + TEST_F(DocumentSuspenderResumer, CreateSuspendJobsForDocumentWithSupportiveTranslationUnit) { Document document = documents.create({fileContainer1})[0]; document.setIsSuspended(false); document.setIsVisibleInEditor(false, Clock::now()); document.translationUnits().createAndAppend(); // Add supportive translation unit + setParsed(document); const SuspendResumeJobs expectedJobs = { {document, JobRequest::Type::SuspendDocument, PreferredTranslationUnit::RecentlyParsed}, {document, JobRequest::Type::SuspendDocument, PreferredTranslationUnit::PreviouslyParsed}, @@ -258,6 +273,7 @@ TEST_F(DocumentSuspenderResumer, CreateSuspendAndResumeJobs) Document hotDocument = documents.create({fileContainer1})[0]; hotDocument.setIsSuspended(true); Document coldDocument = documents.create({fileContainer2})[0]; + setParsed(coldDocument); coldDocument.setIsSuspended(false); documents.setVisibleInEditors({filePath1}); const SuspendResumeJobs expectedJobs = { @@ -292,4 +308,15 @@ DocumentSuspenderResumer::createSuspendResumeJobs(int hotDocumentsSize) return ClangBackEnd::createSuspendResumeJobs(documents.documents(), hotDocumentsSize); } +void DocumentSuspenderResumer::setParsed(ClangBackEnd::Document &document) +{ + const Utf8String first = document.translationUnit().id(); + document.translationUnits().updateParseTimePoint(first, Clock::now()); + + const Utf8String second + = document.translationUnit(PreferredTranslationUnit::LastUninitialized).id(); + if (second != first) + document.translationUnits().updateParseTimePoint(second, Clock::now()); +} + } // anonymous -- GitLab