summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@qt.io>2016-04-22 15:31:49 +0200
committerNikolai Kosjar <nikolai.kosjar@qt.io>2016-04-26 12:28:16 +0000
commit7b7b1823cbfbf95589bf1f8fc07253f3f5ad7477 (patch)
tree4968b0f66b944fa7e36e436d786818ed48262087 /src
parent66e9cb0a5446c043385ab84af1cc13539c7fbe45 (diff)
downloadqt-creator-7b7b1823cbfbf95589bf1f8fc07253f3f5ad7477.tar.gz
Clang: Avoid parse loop if libclang crashed or file vanished
Remember whether clang_parseTranslationUnit() or clang_reparseTranslationUnit() failed the last time and do not trigger parse/reparse again. Also, check whether the main file exists before reparsing. Task-number: QTCREATORBUG-16051 Task-number: QTCREATORBUG-16140 Change-Id: Ied39e66a18032854911229898573941fe2ada35b Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri2
-rw-r--r--src/tools/clangbackend/ipcsource/clangtranslationunit.cpp77
-rw-r--r--src/tools/clangbackend/ipcsource/clangtranslationunit.h8
-rw-r--r--src/tools/clangbackend/ipcsource/translationunitparseerrorexception.cpp5
-rw-r--r--src/tools/clangbackend/ipcsource/translationunitreparseerrorexception.cpp68
-rw-r--r--src/tools/clangbackend/ipcsource/translationunitreparseerrorexception.h61
-rw-r--r--src/tools/clangbackend/ipcsource/translationunits.cpp4
7 files changed, 201 insertions, 24 deletions
diff --git a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri
index 344a037207..6140f1ca88 100644
--- a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri
+++ b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri
@@ -12,6 +12,7 @@ HEADERS += $$PWD/clangipcserver.h \
$$PWD/projects.h \
$$PWD/translationunits.h \
$$PWD/translationunitparseerrorexception.h \
+ $$PWD/translationunitreparseerrorexception.h \
$$PWD/projectpart.h \
$$PWD/translationunitfilenotexitexception.h \
$$PWD/translationunitdoesnotexistexception.h \
@@ -46,6 +47,7 @@ SOURCES += $$PWD/clangipcserver.cpp \
$$PWD/projects.cpp \
$$PWD/translationunits.cpp \
$$PWD/translationunitparseerrorexception.cpp \
+ $$PWD/translationunitreparseerrorexception.cpp \
$$PWD/projectpart.cpp \
$$PWD/translationunitfilenotexitexception.cpp \
$$PWD/translationunitdoesnotexistexception.cpp \
diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp
index 3460e6ff46..0644c53e3f 100644
--- a/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp
+++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.cpp
@@ -39,6 +39,7 @@
#include "translationunitfilenotexitexception.h"
#include "translationunitisnullexception.h"
#include "translationunitparseerrorexception.h"
+#include "translationunitreparseerrorexception.h"
#include "translationunits.h"
#include "unsavedfiles.h"
@@ -76,6 +77,8 @@ public:
Utf8StringVector fileArguments;
Utf8String filePath;
CXTranslationUnit translationUnit = nullptr;
+ CXErrorCode parseErrorCode = CXError_Success;
+ int reparseErrorCode = 0;
CXIndex index = nullptr;
uint documentRevision = 0;
bool needsToBeReparsed = false;
@@ -155,6 +158,16 @@ void TranslationUnit::reparse() const
reparseTranslationUnit();
}
+bool TranslationUnit::parseWasSuccessful() const
+{
+ return d->parseErrorCode == CXError_Success;
+}
+
+bool TranslationUnit::reparseWasSuccessful() const
+{
+ return d->reparseErrorCode == 0;
+}
+
CXIndex TranslationUnit::index() const
{
checkIfNull();
@@ -350,7 +363,7 @@ void TranslationUnit::checkIfNull() const
void TranslationUnit::checkIfFileExists() const
{
- if (!QFileInfo::exists(d->filePath.toString()))
+ if (!fileExists())
throw TranslationUnitFileNotExitsException(d->filePath);
}
@@ -396,16 +409,16 @@ void TranslationUnit::createTranslationUnitIfNeeded() const
if (isVerboseModeEnabled())
args.print();
- CXErrorCode errorCode = clang_parseTranslationUnit2(index(),
- NULL,
- args.data(),
- args.count(),
- unsavedFiles().cxUnsavedFiles(),
- unsavedFiles().count(),
- defaultOptions(),
- &d->translationUnit);
+ d->parseErrorCode = clang_parseTranslationUnit2(index(),
+ NULL,
+ args.data(),
+ args.count(),
+ unsavedFiles().cxUnsavedFiles(),
+ unsavedFiles().count(),
+ defaultOptions(),
+ &d->translationUnit);
- checkTranslationUnitErrorCode(errorCode);
+ checkParseErrorCode();
updateIncludeFilePaths();
@@ -413,22 +426,33 @@ void TranslationUnit::createTranslationUnitIfNeeded() const
}
}
-void TranslationUnit::checkTranslationUnitErrorCode(CXErrorCode errorCode) const
+void TranslationUnit::checkParseErrorCode() const
{
- switch (errorCode) {
- case CXError_Success: break;
- default: throw TranslationUnitParseErrorException(d->filePath,
- d->projectPart.projectPartId(),
- errorCode);
+ if (!parseWasSuccessful()) {
+ throw TranslationUnitParseErrorException(d->filePath,
+ d->projectPart.projectPartId(),
+ d->parseErrorCode);
+ }
+}
+
+void TranslationUnit::checkReparseErrorCode() const
+{
+ if (!reparseWasSuccessful()) {
+ throw TranslationUnitReparseErrorException(d->filePath,
+ d->projectPart.projectPartId(),
+ d->reparseErrorCode);
}
}
void TranslationUnit::reparseTranslationUnit() const
{
- clang_reparseTranslationUnit(d->translationUnit,
- unsavedFiles().count(),
- unsavedFiles().cxUnsavedFiles(),
- clang_defaultReparseOptions(d->translationUnit));
+ d->reparseErrorCode = clang_reparseTranslationUnit(
+ d->translationUnit,
+ unsavedFiles().count(),
+ unsavedFiles().cxUnsavedFiles(),
+ clang_defaultReparseOptions(d->translationUnit));
+
+ checkReparseErrorCode();
updateIncludeFilePaths();
@@ -474,6 +498,19 @@ void TranslationUnit::updateIncludeFilePaths() const
d->translationUnits.addWatchedFiles(d->dependedFilePaths);
}
+bool TranslationUnit::fileExists() const
+{
+ return QFileInfo::exists(d->filePath.toString());
+}
+
+bool TranslationUnit::isIntact() const
+{
+ return !isNull()
+ && fileExists()
+ && parseWasSuccessful()
+ && reparseWasSuccessful();
+}
+
CommandLineArguments TranslationUnit::commandLineArguments() const
{
return CommandLineArguments(d->filePath.constData(),
diff --git a/src/tools/clangbackend/ipcsource/clangtranslationunit.h b/src/tools/clangbackend/ipcsource/clangtranslationunit.h
index 9a311b62bf..553a3f28de 100644
--- a/src/tools/clangbackend/ipcsource/clangtranslationunit.h
+++ b/src/tools/clangbackend/ipcsource/clangtranslationunit.h
@@ -91,6 +91,8 @@ public:
void reset();
void reparse() const;
+ bool isIntact() const;
+
CXIndex index() const;
CXTranslationUnit cxTranslationUnit() const;
CXTranslationUnit cxTranslationUnitWithoutReparsing() const;
@@ -150,10 +152,14 @@ private:
bool projectPartIsOutdated() const;
bool isMainFileAndExistsOrIsOtherFile(const Utf8String &filePath) const;
void createTranslationUnitIfNeeded() const;
- void checkTranslationUnitErrorCode(CXErrorCode errorCode) const;
+ void checkParseErrorCode() const;
+ void checkReparseErrorCode() const;
void reparseTranslationUnit() const;
void reparseTranslationUnitIfFilesAreChanged() const;
+ bool parseWasSuccessful() const;
+ bool reparseWasSuccessful() const;
void updateIncludeFilePaths() const;
+ bool fileExists() const;
static void includeCallback(CXFile included_file,
CXSourceLocation * /*inclusion_stack*/,
unsigned /*include_len*/,
diff --git a/src/tools/clangbackend/ipcsource/translationunitparseerrorexception.cpp b/src/tools/clangbackend/ipcsource/translationunitparseerrorexception.cpp
index 3cd99c53e8..27f1799e09 100644
--- a/src/tools/clangbackend/ipcsource/translationunitparseerrorexception.cpp
+++ b/src/tools/clangbackend/ipcsource/translationunitparseerrorexception.cpp
@@ -65,12 +65,13 @@ static const char *errorCodeToText(CXErrorCode errorCode)
const char *TranslationUnitParseErrorException::what() const Q_DECL_NOEXCEPT
{
if (what_.isEmpty()) {
- what_ += Utf8StringLiteral("Parse error for file ")
+ what_ += Utf8StringLiteral("clang_parseTranslationUnit() failed for file ")
+ filePath()
+ Utf8StringLiteral(" in project ")
+ projectPartId()
+ Utf8StringLiteral(": ")
- + Utf8String::fromUtf8(errorCodeToText(errorCode_));
+ + Utf8String::fromUtf8(errorCodeToText(errorCode_))
+ + Utf8StringLiteral(".");
}
return what_.constData();
diff --git a/src/tools/clangbackend/ipcsource/translationunitreparseerrorexception.cpp b/src/tools/clangbackend/ipcsource/translationunitreparseerrorexception.cpp
new file mode 100644
index 0000000000..6f1e7f0d7d
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/translationunitreparseerrorexception.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "translationunitreparseerrorexception.h"
+
+#include <QString>
+
+namespace ClangBackEnd {
+
+TranslationUnitReparseErrorException::TranslationUnitReparseErrorException(
+ const Utf8String &filePath,
+ const Utf8String &projectPartId,
+ int errorCode)
+ : filePath_(filePath),
+ projectPartId_(projectPartId),
+ errorCode_(errorCode)
+{
+}
+
+const Utf8String &TranslationUnitReparseErrorException::filePath() const
+{
+ return filePath_;
+}
+
+const Utf8String &TranslationUnitReparseErrorException::projectPartId() const
+{
+ return projectPartId_;
+}
+
+const char *TranslationUnitReparseErrorException::what() const Q_DECL_NOEXCEPT
+{
+ if (what_.isEmpty()) {
+ what_ += Utf8StringLiteral("clang_reparseTranslationUnit() failed for file ")
+ + filePath()
+ + Utf8StringLiteral(" in project ")
+ + projectPartId()
+ + Utf8StringLiteral(": ")
+ + Utf8String::fromString(QString::number(errorCode_))
+ + Utf8StringLiteral(".");
+ }
+
+ return what_.constData();
+}
+
+} // namespace ClangBackEnd
+
diff --git a/src/tools/clangbackend/ipcsource/translationunitreparseerrorexception.h b/src/tools/clangbackend/ipcsource/translationunitreparseerrorexception.h
new file mode 100644
index 0000000000..126a24c7e9
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/translationunitreparseerrorexception.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <utf8string.h>
+
+#include <clang-c/Index.h>
+
+#include <exception>
+
+namespace ClangBackEnd {
+
+class TranslationUnitReparseErrorException : public std::exception
+{
+public:
+ TranslationUnitReparseErrorException(const Utf8String &filePath,
+ const Utf8String &projectPartId,
+ int errorCode);
+
+ const Utf8String &filePath() const;
+ const Utf8String &projectPartId() const;
+
+ const char *what() const Q_DECL_NOEXCEPT override;
+
+#if defined(__GNUC__) && !defined(__clang__)
+# if !__GNUC_PREREQ(4,8)
+ ~TranslationUnitReparseErrorException() noexcept {}
+# endif
+#endif
+
+private:
+ Utf8String filePath_;
+ Utf8String projectPartId_;
+ int errorCode_;
+ mutable Utf8String what_;
+};
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/translationunits.cpp b/src/tools/clangbackend/ipcsource/translationunits.cpp
index 5b118a9652..6f9defc356 100644
--- a/src/tools/clangbackend/ipcsource/translationunits.cpp
+++ b/src/tools/clangbackend/ipcsource/translationunits.cpp
@@ -199,7 +199,9 @@ namespace {
bool translationUnitHasNewDocumentAnnotations(const TranslationUnit &translationUnit)
{
- return translationUnit.hasNewDiagnostics() || translationUnit.hasNewHighlightingInformations();
+ return translationUnit.isIntact()
+ && (translationUnit.hasNewDiagnostics()
+ || translationUnit.hasNewHighlightingInformations());
}
}