Commit 979f4589 authored by Kevin Funk's avatar Kevin Funk
Browse files

Merge remote-tracking branch 'origin/5.0'

parents 4ac818af a2bf38cd
......@@ -61,7 +61,7 @@ void QtHelpQtDoc::registerDocumentations()
QProcess *p = new QProcess;
p->setProcessChannelMode(QProcess::MergedChannels);
p->setProgram(qmake);
p->setArguments(QStringList(QStringLiteral("-query QT_INSTALL_DOCS")));
p->setArguments({QLatin1String("-query"), QLatin1String("QT_INSTALL_DOCS")});
p->start();
connect(p, static_cast<void(QProcess::*)(int)>(&QProcess::finished), this, &QtHelpQtDoc::lookupDone);
}
......@@ -69,12 +69,15 @@ void QtHelpQtDoc::registerDocumentations()
void QtHelpQtDoc::lookupDone(int code)
{
if(code==0) {
QProcess* p = qobject_cast<QProcess*>(sender());
QProcess *p = qobject_cast<QProcess*>(sender());
if(code == QProcess::NormalExit) {
m_path = QDir::fromNativeSeparators(QString::fromLatin1(p->readAllStandardOutput().trimmed()));
qCDebug(QTHELP) << "Detected doc path:" << m_path;
} else {
qCCritical(QTHELP) << "qmake query returned error:" << QString::fromLatin1(p->readAllStandardError());
qCDebug(QTHELP) << "last standard output was:" << QString::fromLatin1(p->readAllStandardOutput());
}
sender()->deleteLater();
}
......
......@@ -42,11 +42,6 @@ QWidget* ClangTopDUContext::createNavigationWidget(Declaration* decl, TopDUConte
return new ClangNavigationWidget(item, TopDUContextPointer(topContext ? topContext : this->topContext()), htmlPrefix, htmlSuffix);
}
if (decl->range().isEmpty()) {
return nullptr;
}
return new ClangNavigationWidget(DeclarationPointer(decl));
}
......@@ -54,7 +49,7 @@ template<>
QWidget* ClangNormalDUContext::createNavigationWidget(Declaration* decl, TopDUContext* /*topContext*/,
const QString& /*htmlPrefix*/, const QString& /*htmlSuffix*/) const
{
if (!decl || decl->range().isEmpty()) {
if (!decl) {
clangDebug() << "no declaration, not returning navigationwidget";
return 0;
}
......
......@@ -93,6 +93,11 @@ Imports ClangHelpers::tuImports(CXTranslationUnit tu)
return imports;
}
bool importLocationLessThan(const Import& lhs, const Import& rhs)
{
return lhs.location.line < rhs.location.line;
}
ReferencedTopDUContext ClangHelpers::buildDUChain(CXFile file, const Imports& imports, const ParseSession& session,
TopDUContext::Features features, IncludeFileContexts& includedFiles,
ClangIndex* index, const std::function<bool()>& abortFunction)
......@@ -108,8 +113,11 @@ ReferencedTopDUContext ClangHelpers::buildDUChain(CXFile file, const Imports& im
// prevent recursion
includedFiles.insert(file, {});
// ensure DUChain for imports are build properly
foreach(const auto& import, imports.values(file)) {
// ensure DUChain for imports are built properly, and in correct order
QList<Import> sortedImports = imports.values(file);
std::sort(sortedImports.begin(), sortedImports.end(), importLocationLessThan);
foreach(const auto& import, sortedImports) {
buildDUChain(import.file, imports, session, features, includedFiles, index, abortFunction);
}
......@@ -161,7 +169,7 @@ ReferencedTopDUContext ClangHelpers::buildDUChain(CXFile file, const Imports& im
}
context->setFeatures(features);
foreach(const auto& import, imports.values(file)) {
foreach(const auto& import, sortedImports) {
auto ctx = includedFiles.value(import.file);
if (!ctx) {
// happens for cyclic imports
......
......@@ -34,6 +34,7 @@
#include <language/duchain/types/integraltype.h>
#include <language/duchain/types/structuretype.h>
#include <language/duchain/types/functiontype.h>
#include <language/duchain/types/typealiastype.h>
#include <language/duchain/duchainutils.h>
#include <language/duchain/classdeclaration.h>
#include <language/duchain/abstractfunctiondeclaration.h>
......@@ -1195,6 +1196,80 @@ void TestDUChain::testReparseChangeEnvironment()
}
}
void TestDUChain::testHeaderParsingOrder1()
{
TestFile header("typedef const A<int> B;\n", "h");
TestFile impl("template<class T> class A{};\n"
"#include \"" + header.url().byteArray() + "\"\n"
"B c;", "cpp", &header);
impl.parse(TopDUContext::Features(TopDUContext::AllDeclarationsContextsAndUses|TopDUContext::AST|TopDUContext::ForceUpdate));
QVERIFY(impl.waitForParsed(500000));
DUChainReadLocker lock;
TopDUContext* top = impl.topContext().data();
QVERIFY(top);
QCOMPARE(top->localDeclarations().size(), 2);
QCOMPARE(top->importedParentContexts().size(), 1);
AbstractType::Ptr type = top->localDeclarations()[1]->abstractType();
TypeAliasType* aType = dynamic_cast<TypeAliasType*>(type.data());
QVERIFY(aType);
AbstractType::Ptr targetType = aType->type();
QVERIFY(targetType);
IdentifiedType *idType = dynamic_cast<IdentifiedType*>(targetType.data());
QVERIFY(idType);
// this declaration could be resolved, because it was created with an
// indirect DeclarationId that is resolved from the perspective of 'top'
Declaration* decl = idType->declaration(top);
// NOTE: the decl. doesn't know (yet) about the template insantiation <int>
QVERIFY(decl);
QCOMPARE(decl, top->localDeclarations()[0]);
// now ensure that a use was build for 'A' in header1
TopDUContext* top2 = dynamic_cast<TopDUContext*>(top->importedParentContexts()[0].context(top));
QVERIFY(top2);
QEXPECT_FAIL("", "the use could not be created because the corresponding declaration didn't exist yet", Continue);
QCOMPARE(top2->usesCount(), 1);
// Declaration* decl2 = top2->uses()[0].usedDeclaration(top2);
// QVERIFY(decl2);
// QCOMPARE(decl, decl2);
}
void TestDUChain::testHeaderParsingOrder2()
{
TestFile header("template<class T> class A{};\n", "h");
TestFile header2("typedef const A<int> B;\n", "h");
TestFile impl("#include \"" + header.url().byteArray() + "\"\n"
"#include \"" + header2.url().byteArray() + "\"\n"
"B c;", "cpp", &header);
impl.parse(TopDUContext::Features(TopDUContext::AllDeclarationsContextsAndUses|TopDUContext::AST|TopDUContext::ForceUpdate));
QVERIFY(impl.waitForParsed(500000));
DUChainReadLocker lock;
TopDUContext* top = impl.topContext().data();
QVERIFY(top);
QCOMPARE(top->localDeclarations().size(), 1);
QCOMPARE(top->importedParentContexts().size(), 2);
AbstractType::Ptr type = top->localDeclarations()[0]->abstractType();
TypeAliasType* aType = dynamic_cast<TypeAliasType*>(type.data());
QVERIFY(aType);
AbstractType::Ptr targetType = aType->type();
QVERIFY(targetType);
IdentifiedType *idType = dynamic_cast<IdentifiedType*>(targetType.data());
QVERIFY(idType);
Declaration* decl = idType->declaration(top);
// NOTE: the decl. doesn't know (yet) about the template insantiation <int>
QVERIFY(decl);
// now ensure that a use was build for 'A' in header2
TopDUContext* top2 = dynamic_cast<TopDUContext*>(top->importedParentContexts()[1].context(top));
QVERIFY(top2);
QCOMPARE(top2->usesCount(), 1);
Declaration* decl2 = top2->uses()[0].usedDeclaration(top2);
QCOMPARE(decl, decl2);
}
void TestDUChain::testMacrosRanges()
{
TestFile file("#define FUNC_MACROS(x) struct str##x{};\nFUNC_MACROS(x);", "cpp");
......
......@@ -72,6 +72,8 @@ private slots:
void testReparseInclude();
void testReparseChangeEnvironment();
void testMacrosRanges();
void testHeaderParsingOrder1();
void testHeaderParsingOrder2();
void testNestedImports();
void testEnvironmentWithDifferentOrderOfElements();
void testReparseMacro();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment