forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/master' into 4.6
Change-Id: I5e73b7e3cc7281e66c699d03f5ab3f92915d0f21
This commit is contained in:
@@ -25,7 +25,7 @@ index 944cd775d5..6aba10e5c7 100644
|
||||
- return nullptr;
|
||||
+ auto usingDeclPtr = ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
|
||||
+ prefixAttrs);
|
||||
+ if (!usingDeclPtr)
|
||||
+ if (!usingDeclPtr || !usingDeclPtr.get().isSingleDecl())
|
||||
+ return nullptr;
|
||||
+ return usingDeclPtr.get().getSingleDecl();
|
||||
}
|
34
dist/clang/patches/030_D38615_Only-mark-CXCursors-for-explicit-attributes-with-a-type.patch
vendored
Normal file
34
dist/clang/patches/030_D38615_Only-mark-CXCursors-for-explicit-attributes-with-a-type.patch
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
--- /dev/null
|
||||
+++ b/tools/clang/test/Index/annotate-tokens-unexposed.cpp
|
||||
@@ -0,0 +1,20 @@
|
||||
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:16:1 %s -target x86_64-pc-windows-msvc | FileCheck %s
|
||||
+class Foo
|
||||
+{
|
||||
+public:
|
||||
+ void step(int v);
|
||||
+ Foo();
|
||||
+};
|
||||
+
|
||||
+void bar()
|
||||
+{
|
||||
+ // Introduce a MSInheritanceAttr node on the CXXRecordDecl for Foo. The
|
||||
+ // existence of this attribute should not mark all cursors for tokens in
|
||||
+ // Foo as UnexposedAttr.
|
||||
+ &Foo::step;
|
||||
+}
|
||||
+
|
||||
+Foo::Foo()
|
||||
+{}
|
||||
+
|
||||
+// CHECK-NOT: UnexposedAttr=
|
||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
||||
@@ -1772,7 +1772,7 @@
|
||||
|
||||
bool CursorVisitor::VisitAttributes(Decl *D) {
|
||||
for (const auto *I : D->attrs())
|
||||
- if (Visit(MakeCXCursor(I, D, TU)))
|
||||
+ if (!I->isImplicit() && Visit(MakeCXCursor(I, D, TU)))
|
||||
return true;
|
||||
|
||||
return false;
|
266
dist/clang/patches/040_D39957_Honor-TerseOutput-for-constructors.patch
vendored
Normal file
266
dist/clang/patches/040_D39957_Honor-TerseOutput-for-constructors.patch
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
--- a/tools/clang/lib/AST/DeclPrinter.cpp
|
||||
+++ b/tools/clang/lib/AST/DeclPrinter.cpp
|
||||
@@ -608,66 +608,69 @@
|
||||
}
|
||||
|
||||
if (CDecl) {
|
||||
- bool HasInitializerList = false;
|
||||
- for (const auto *BMInitializer : CDecl->inits()) {
|
||||
- if (BMInitializer->isInClassMemberInitializer())
|
||||
- continue;
|
||||
-
|
||||
- if (!HasInitializerList) {
|
||||
- Proto += " : ";
|
||||
- Out << Proto;
|
||||
- Proto.clear();
|
||||
- HasInitializerList = true;
|
||||
- } else
|
||||
- Out << ", ";
|
||||
+ if (!Policy.TerseOutput) {
|
||||
+ bool HasInitializerList = false;
|
||||
+ for (const auto *BMInitializer : CDecl->inits()) {
|
||||
+ if (BMInitializer->isInClassMemberInitializer())
|
||||
+ continue;
|
||||
|
||||
- if (BMInitializer->isAnyMemberInitializer()) {
|
||||
- FieldDecl *FD = BMInitializer->getAnyMember();
|
||||
- Out << *FD;
|
||||
- } else {
|
||||
- Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
|
||||
- }
|
||||
-
|
||||
- Out << "(";
|
||||
- if (!BMInitializer->getInit()) {
|
||||
- // Nothing to print
|
||||
- } else {
|
||||
- Expr *Init = BMInitializer->getInit();
|
||||
- if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
|
||||
- Init = Tmp->getSubExpr();
|
||||
-
|
||||
- Init = Init->IgnoreParens();
|
||||
-
|
||||
- Expr *SimpleInit = nullptr;
|
||||
- Expr **Args = nullptr;
|
||||
- unsigned NumArgs = 0;
|
||||
- if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
|
||||
- Args = ParenList->getExprs();
|
||||
- NumArgs = ParenList->getNumExprs();
|
||||
- } else if (CXXConstructExpr *Construct
|
||||
- = dyn_cast<CXXConstructExpr>(Init)) {
|
||||
- Args = Construct->getArgs();
|
||||
- NumArgs = Construct->getNumArgs();
|
||||
+ if (!HasInitializerList) {
|
||||
+ Proto += " : ";
|
||||
+ Out << Proto;
|
||||
+ Proto.clear();
|
||||
+ HasInitializerList = true;
|
||||
} else
|
||||
- SimpleInit = Init;
|
||||
-
|
||||
- if (SimpleInit)
|
||||
- SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
|
||||
- else {
|
||||
- for (unsigned I = 0; I != NumArgs; ++I) {
|
||||
- assert(Args[I] != nullptr && "Expected non-null Expr");
|
||||
- if (isa<CXXDefaultArgExpr>(Args[I]))
|
||||
- break;
|
||||
-
|
||||
- if (I)
|
||||
- Out << ", ";
|
||||
- Args[I]->printPretty(Out, nullptr, Policy, Indentation);
|
||||
+ Out << ", ";
|
||||
+
|
||||
+ if (BMInitializer->isAnyMemberInitializer()) {
|
||||
+ FieldDecl *FD = BMInitializer->getAnyMember();
|
||||
+ Out << *FD;
|
||||
+ } else {
|
||||
+ Out << QualType(BMInitializer->getBaseClass(), 0)
|
||||
+ .getAsString(Policy);
|
||||
+ }
|
||||
+
|
||||
+ Out << "(";
|
||||
+ if (!BMInitializer->getInit()) {
|
||||
+ // Nothing to print
|
||||
+ } else {
|
||||
+ Expr *Init = BMInitializer->getInit();
|
||||
+ if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
|
||||
+ Init = Tmp->getSubExpr();
|
||||
+
|
||||
+ Init = Init->IgnoreParens();
|
||||
+
|
||||
+ Expr *SimpleInit = nullptr;
|
||||
+ Expr **Args = nullptr;
|
||||
+ unsigned NumArgs = 0;
|
||||
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
|
||||
+ Args = ParenList->getExprs();
|
||||
+ NumArgs = ParenList->getNumExprs();
|
||||
+ } else if (CXXConstructExpr *Construct =
|
||||
+ dyn_cast<CXXConstructExpr>(Init)) {
|
||||
+ Args = Construct->getArgs();
|
||||
+ NumArgs = Construct->getNumArgs();
|
||||
+ } else
|
||||
+ SimpleInit = Init;
|
||||
+
|
||||
+ if (SimpleInit)
|
||||
+ SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
|
||||
+ else {
|
||||
+ for (unsigned I = 0; I != NumArgs; ++I) {
|
||||
+ assert(Args[I] != nullptr && "Expected non-null Expr");
|
||||
+ if (isa<CXXDefaultArgExpr>(Args[I]))
|
||||
+ break;
|
||||
+
|
||||
+ if (I)
|
||||
+ Out << ", ";
|
||||
+ Args[I]->printPretty(Out, nullptr, Policy, Indentation);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+ Out << ")";
|
||||
+ if (BMInitializer->isPackExpansion())
|
||||
+ Out << "...";
|
||||
}
|
||||
- Out << ")";
|
||||
- if (BMInitializer->isPackExpansion())
|
||||
- Out << "...";
|
||||
}
|
||||
} else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
|
||||
if (FT && FT->hasTrailingReturn()) {
|
||||
@@ -712,7 +715,7 @@
|
||||
if (D->getBody())
|
||||
D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
|
||||
} else {
|
||||
- if (isa<CXXConstructorDecl>(*D))
|
||||
+ if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D))
|
||||
Out << " {}";
|
||||
}
|
||||
}
|
||||
--- a/tools/clang/test/Index/comment-cplus-decls.cpp
|
||||
+++ b/tools/clang/test/Index/comment-cplus-decls.cpp
|
||||
@@ -46,7 +46,7 @@
|
||||
data* reserved;
|
||||
};
|
||||
// CHECK: <Declaration>class Test {}</Declaration>
|
||||
-// CHECK: <Declaration>Test() : reserved(new Test::data()) {}</Declaration>
|
||||
+// CHECK: <Declaration>Test()</Declaration>
|
||||
// CHECK: <Declaration>unsigned int getID() const</Declaration>
|
||||
// CHECK: <Declaration>~Test(){{( noexcept)?}}</Declaration>
|
||||
// CHECK: <Declaration>Test::data *reserved</Declaration>
|
||||
--- a/tools/clang/unittests/AST/DeclPrinterTest.cpp
|
||||
+++ b/tools/clang/unittests/AST/DeclPrinterTest.cpp
|
||||
@@ -31,18 +31,25 @@
|
||||
|
||||
namespace {
|
||||
|
||||
-void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D) {
|
||||
+using PrintingPolicyModifier = void (*)(PrintingPolicy &policy);
|
||||
+
|
||||
+void PrintDecl(raw_ostream &Out, const ASTContext *Context, const Decl *D,
|
||||
+ PrintingPolicyModifier PolicyModifier) {
|
||||
PrintingPolicy Policy = Context->getPrintingPolicy();
|
||||
Policy.TerseOutput = true;
|
||||
+ if (PolicyModifier)
|
||||
+ PolicyModifier(Policy);
|
||||
D->print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ false);
|
||||
}
|
||||
|
||||
class PrintMatch : public MatchFinder::MatchCallback {
|
||||
SmallString<1024> Printed;
|
||||
unsigned NumFoundDecls;
|
||||
+ PrintingPolicyModifier PolicyModifier;
|
||||
|
||||
public:
|
||||
- PrintMatch() : NumFoundDecls(0) {}
|
||||
+ PrintMatch(PrintingPolicyModifier PolicyModifier)
|
||||
+ : NumFoundDecls(0), PolicyModifier(PolicyModifier) {}
|
||||
|
||||
void run(const MatchFinder::MatchResult &Result) override {
|
||||
const Decl *D = Result.Nodes.getNodeAs<Decl>("id");
|
||||
@@ -53,7 +60,7 @@
|
||||
return;
|
||||
|
||||
llvm::raw_svector_ostream Out(Printed);
|
||||
- PrintDecl(Out, Result.Context, D);
|
||||
+ PrintDecl(Out, Result.Context, D, PolicyModifier);
|
||||
}
|
||||
|
||||
StringRef getPrinted() const {
|
||||
@@ -65,13 +72,12 @@
|
||||
}
|
||||
};
|
||||
|
||||
-::testing::AssertionResult PrintedDeclMatches(
|
||||
- StringRef Code,
|
||||
- const std::vector<std::string> &Args,
|
||||
- const DeclarationMatcher &NodeMatch,
|
||||
- StringRef ExpectedPrinted,
|
||||
- StringRef FileName) {
|
||||
- PrintMatch Printer;
|
||||
+::testing::AssertionResult
|
||||
+PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
|
||||
+ const DeclarationMatcher &NodeMatch,
|
||||
+ StringRef ExpectedPrinted, StringRef FileName,
|
||||
+ PrintingPolicyModifier PolicyModifier = nullptr) {
|
||||
+ PrintMatch Printer(PolicyModifier);
|
||||
MatchFinder Finder;
|
||||
Finder.addMatcher(NodeMatch, &Printer);
|
||||
std::unique_ptr<FrontendActionFactory> Factory(
|
||||
@@ -109,16 +115,17 @@
|
||||
"input.cc");
|
||||
}
|
||||
|
||||
-::testing::AssertionResult PrintedDeclCXX98Matches(
|
||||
- StringRef Code,
|
||||
- const DeclarationMatcher &NodeMatch,
|
||||
- StringRef ExpectedPrinted) {
|
||||
+::testing::AssertionResult
|
||||
+PrintedDeclCXX98Matches(StringRef Code, const DeclarationMatcher &NodeMatch,
|
||||
+ StringRef ExpectedPrinted,
|
||||
+ PrintingPolicyModifier PolicyModifier = nullptr) {
|
||||
std::vector<std::string> Args(1, "-std=c++98");
|
||||
return PrintedDeclMatches(Code,
|
||||
Args,
|
||||
NodeMatch,
|
||||
ExpectedPrinted,
|
||||
- "input.cc");
|
||||
+ "input.cc",
|
||||
+ PolicyModifier);
|
||||
}
|
||||
|
||||
::testing::AssertionResult PrintedDeclCXX11Matches(StringRef Code,
|
||||
@@ -478,6 +485,27 @@
|
||||
"A(const A &a, int = 0)"));
|
||||
}
|
||||
|
||||
+TEST(DeclPrinter, TestCXXConstructorDeclWithMemberInitializer) {
|
||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
||||
+ "struct A {"
|
||||
+ " int m;"
|
||||
+ " A() : m(2) {}"
|
||||
+ "};",
|
||||
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
|
||||
+ "A()"));
|
||||
+}
|
||||
+
|
||||
+TEST(DeclPrinter, TestCXXConstructorDeclWithMemberInitializer_NoTerseOutput) {
|
||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
||||
+ "struct A {"
|
||||
+ " int m;"
|
||||
+ " A() : m(2) {}"
|
||||
+ "};",
|
||||
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
|
||||
+ "A() : m(2) {\n}\n",
|
||||
+ [](PrintingPolicy &Policy){ Policy.TerseOutput = false; }));
|
||||
+}
|
||||
+
|
||||
TEST(DeclPrinter, TestCXXConstructorDecl5) {
|
||||
ASSERT_TRUE(PrintedDeclCXX11Matches(
|
||||
"struct A {"
|
||||
@@ -540,7 +568,7 @@
|
||||
" A(T&&... ts) : T(ts)... {}"
|
||||
"};",
|
||||
cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
|
||||
- "A<T...>(T &&...ts) : T(ts)... {}"));
|
||||
+ "A<T...>(T &&...ts)"));
|
||||
}
|
||||
|
||||
TEST(DeclPrinter, TestCXXDestructorDecl1) {
|
33
dist/clang/patches/050_D40027_Fix-cursors-for-in-class-initializer-of-field-declarations.patch
vendored
Normal file
33
dist/clang/patches/050_D40027_Fix-cursors-for-in-class-initializer-of-field-declarations.patch
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
--- a/tools/clang/test/Index/get-cursor.cpp
|
||||
+++ b/tools/clang/test/Index/get-cursor.cpp
|
||||
@@ -152,6 +152,11 @@
|
||||
void f_dynamic_noexcept() throw(int);
|
||||
void f_dynamic_noexcept_any() throw(...);
|
||||
|
||||
+enum EnumType { Enumerator };
|
||||
+struct Z {
|
||||
+ EnumType e = Enumerator;
|
||||
+};
|
||||
+
|
||||
// RUN: c-index-test -cursor-at=%s:6:4 %s | FileCheck -check-prefix=CHECK-COMPLETION-1 %s
|
||||
// CHECK-COMPLETION-1: CXXConstructor=X:6:3
|
||||
// CHECK-COMPLETION-1-NEXT: Completion string: {TypedText X}{LeftParen (}{Placeholder int}{Comma , }{Placeholder int}{RightParen )}
|
||||
@@ -275,3 +280,6 @@
|
||||
// CHECK-FORRANGE: 141:18 DeclRefExpr=coll:140:20 Extent=[141:18 - 141:22] Spelling=coll ([141:18 - 141:22])
|
||||
// CHECK-FORRANGE: 142:11 DeclRefExpr=lv:141:13 Extent=[142:11 - 142:13] Spelling=lv ([142:11 - 142:13])
|
||||
|
||||
+// RUN: c-index-test -cursor-at=%s:157:18 -std=c++11 %s | FileCheck -check-prefix=CHECK-INCLASSINITIALIZER %s
|
||||
+// CHECK-INCLASSINITIALIZER: 157:18 DeclRefExpr=Enumerator:155:17 Extent=[157:18 - 157:28] Spelling=Enumerator ([157:18 - 157:28])
|
||||
+
|
||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
||||
@@ -877,6 +877,9 @@
|
||||
if (Expr *BitWidth = D->getBitWidth())
|
||||
return Visit(MakeCXCursor(BitWidth, StmtParent, TU, RegionOfInterest));
|
||||
|
||||
+ if (Expr *Init = D->getInClassInitializer())
|
||||
+ return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest));
|
||||
+
|
||||
return false;
|
||||
}
|
||||
|
154
dist/clang/patches/060_D40072_Support-querying-whether-a-declaration-is-invalid.patch
vendored
Normal file
154
dist/clang/patches/060_D40072_Support-querying-whether-a-declaration-is-invalid.patch
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
|
||||
index 3b5ea9fa53..f2397d1b63 100644
|
||||
--- a/tools/clang/include/clang-c/Index.h
|
||||
+++ b/tools/clang/include/clang-c/Index.h
|
||||
@@ -33,6 +33,7 @@
|
||||
*/
|
||||
#define CINDEX_VERSION_MAJOR 0
|
||||
#define CINDEX_VERSION_MINOR 43
|
||||
+#define CINDEX_VERSION_HAS_ISINVALIDECL_BACKPORTED
|
||||
|
||||
#define CINDEX_VERSION_ENCODE(major, minor) ( \
|
||||
((major) * 10000) \
|
||||
@@ -2616,6 +2617,16 @@ CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
|
||||
*/
|
||||
CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
|
||||
|
||||
+/**
|
||||
+ * \brief Determine whether the given declaration is invalid.
|
||||
+ *
|
||||
+ * A declaration is invalid if it could not be parsed successfully.
|
||||
+ *
|
||||
+ * \returns non-zero if the cursor represents a declaration and it is
|
||||
+ * invalid, otherwise NULL.
|
||||
+ */
|
||||
+CINDEX_LINKAGE unsigned clang_isInvalidDeclaration(CXCursor);
|
||||
+
|
||||
/**
|
||||
* \brief Determine whether the given cursor kind represents a simple
|
||||
* reference.
|
||||
diff --git a/test/Index/opencl-types.cl b/test/Index/opencl-types.cl
|
||||
index fe0042aa20..d71893a220 100644
|
||||
--- a/tools/clang/test/Index/opencl-types.cl
|
||||
+++ b/tools/clang/test/Index/opencl-types.cl
|
||||
@@ -16,11 +16,11 @@ void kernel testFloatTypes() {
|
||||
double4 vectorDouble;
|
||||
}
|
||||
|
||||
-// CHECK: VarDecl=scalarHalf:11:8 (Definition) [type=half] [typekind=Half] [isPOD=1]
|
||||
+// CHECK: VarDecl=scalarHalf:11:8 (Definition){{( \(invalid\))?}} [type=half] [typekind=Half] [isPOD=1]
|
||||
// CHECK: VarDecl=vectorHalf:12:9 (Definition) [type=half4] [typekind=Typedef] [canonicaltype=half __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
|
||||
// CHECK: VarDecl=scalarFloat:13:9 (Definition) [type=float] [typekind=Float] [isPOD=1]
|
||||
// CHECK: VarDecl=vectorFloat:14:10 (Definition) [type=float4] [typekind=Typedef] [canonicaltype=float __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
|
||||
-// CHECK: VarDecl=scalarDouble:15:10 (Definition) [type=double] [typekind=Double] [isPOD=1]
|
||||
+// CHECK: VarDecl=scalarDouble:15:10 (Definition){{( \(invalid\))?}} [type=double] [typekind=Double] [isPOD=1]
|
||||
// CHECK: VarDecl=vectorDouble:16:11 (Definition) [type=double4] [typekind=Typedef] [canonicaltype=double __attribute__((ext_vector_type(4)))] [canonicaltypekind=Unexposed] [isPOD=1]
|
||||
|
||||
#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
|
||||
@@ -45,10 +45,10 @@ void kernel OCLImage3dROTest(read_only image3d_t scalarOCLImage3dRO);
|
||||
// CHECK: ParmDecl=scalarOCLImage2dArrayRO:32:61 (Definition) [type=__read_only image2d_array_t] [typekind=OCLImage2dArrayRO] [isPOD=1]
|
||||
// CHECK: ParmDecl=scalarOCLImage2dDepthRO:33:61 (Definition) [type=__read_only image2d_depth_t] [typekind=OCLImage2dDepthRO] [isPOD=1]
|
||||
// CHECK: ParmDecl=scalarOCLImage2dArrayDepthRO:34:72 (Definition) [type=__read_only image2d_array_depth_t] [typekind=OCLImage2dArrayDepthRO] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAARO:35:59 (Definition) [type=__read_only image2d_msaa_t] [typekind=OCLImage2dMSAARO] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARO:36:70 (Definition) [type=__read_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARO] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRO:37:70 (Definition) [type=__read_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRO] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRO:38:81 (Definition) [type=__read_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRO] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAARO:35:59 (Definition){{( \(invalid\))?}} [type=__read_only image2d_msaa_t] [typekind=OCLImage2dMSAARO] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARO:36:70 (Definition){{( \(invalid\))?}} [type=__read_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARO] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRO:37:70 (Definition){{( \(invalid\))?}} [type=__read_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRO] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRO:38:81 (Definition){{( \(invalid\))?}} [type=__read_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRO] [isPOD=1]
|
||||
// CHECK: ParmDecl=scalarOCLImage3dRO:39:50 (Definition) [type=__read_only image3d_t] [typekind=OCLImage3dRO] [isPOD=1]
|
||||
|
||||
void kernel OCLImage1dWOTest(write_only image1d_t scalarOCLImage1dWO);
|
||||
@@ -71,11 +71,11 @@ void kernel OCLImage3dWOTest(write_only image3d_t scalarOCLImage3dWO);
|
||||
// CHECK: ParmDecl=scalarOCLImage2dArrayWO:58:62 (Definition) [type=__write_only image2d_array_t] [typekind=OCLImage2dArrayWO] [isPOD=1]
|
||||
// CHECK: ParmDecl=scalarOCLImage2dDepthWO:59:62 (Definition) [type=__write_only image2d_depth_t] [typekind=OCLImage2dDepthWO] [isPOD=1]
|
||||
// CHECK: ParmDecl=scalarOCLImage2dArrayDepthWO:60:73 (Definition) [type=__write_only image2d_array_depth_t] [typekind=OCLImage2dArrayDepthWO] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAAWO:61:60 (Definition) [type=__write_only image2d_msaa_t] [typekind=OCLImage2dMSAAWO] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAAWO:62:71 (Definition) [type=__write_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAAWO] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAADepthWO:63:71 (Definition) [type=__write_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthWO] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthWO:64:82 (Definition) [type=__write_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthWO] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage3dWO:65:51 (Definition) [type=__write_only image3d_t] [typekind=OCLImage3dWO] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAAWO:61:60 (Definition){{( \(invalid\))?}} [type=__write_only image2d_msaa_t] [typekind=OCLImage2dMSAAWO] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAAWO:62:71 (Definition){{( \(invalid\))?}} [type=__write_only image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAAWO] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAADepthWO:63:71 (Definition){{( \(invalid\))?}} [type=__write_only image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthWO] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthWO:64:82 (Definition){{( \(invalid\))?}} [type=__write_only image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthWO] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage3dWO:65:51 (Definition){{( \(invalid\))?}} [type=__write_only image3d_t] [typekind=OCLImage3dWO] [isPOD=1]
|
||||
|
||||
void kernel OCLImage1dRWTest(read_write image1d_t scalarOCLImage1dRW);
|
||||
void kernel OCLImage1dArrayRWTest(read_write image1d_array_t scalarOCLImage1dArrayRW);
|
||||
@@ -97,10 +97,10 @@ void kernel OCLImage3dRWTest(read_write image3d_t scalarOCLImage3dRW);
|
||||
// CHECK: ParmDecl=scalarOCLImage2dArrayRW:84:62 (Definition) [type=__read_write image2d_array_t] [typekind=OCLImage2dArrayRW] [isPOD=1]
|
||||
// CHECK: ParmDecl=scalarOCLImage2dDepthRW:85:62 (Definition) [type=__read_write image2d_depth_t] [typekind=OCLImage2dDepthRW] [isPOD=1]
|
||||
// CHECK: ParmDecl=scalarOCLImage2dArrayDepthRW:86:73 (Definition) [type=__read_write image2d_array_depth_t] [typekind=OCLImage2dArrayDepthRW] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAARW:87:60 (Definition) [type=__read_write image2d_msaa_t] [typekind=OCLImage2dMSAARW] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARW:88:71 (Definition) [type=__read_write image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARW] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRW:89:71 (Definition) [type=__read_write image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRW] [isPOD=1]
|
||||
-// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRW:90:82 (Definition) [type=__read_write image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRW] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAARW:87:60 (Definition){{( \(invalid\))?}} [type=__read_write image2d_msaa_t] [typekind=OCLImage2dMSAARW] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAARW:88:71 (Definition){{( \(invalid\))?}} [type=__read_write image2d_array_msaa_t] [typekind=OCLImage2dArrayMSAARW] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dMSAADepthRW:89:71 (Definition){{( \(invalid\))?}} [type=__read_write image2d_msaa_depth_t] [typekind=OCLImage2dMSAADepthRW] [isPOD=1]
|
||||
+// CHECK: ParmDecl=scalarOCLImage2dArrayMSAADepthRW:90:82 (Definition){{( \(invalid\))?}} [type=__read_write image2d_array_msaa_depth_t] [typekind=OCLImage2dArrayMSAADepthRW] [isPOD=1]
|
||||
// CHECK: ParmDecl=scalarOCLImage3dRW:91:51 (Definition) [type=__read_write image3d_t] [typekind=OCLImage3dRW] [isPOD=1]
|
||||
|
||||
void kernel intPipeTestRO(read_only pipe int scalarPipe);
|
||||
diff --git a/test/Index/print-type-size.cpp b/test/Index/print-type-size.cpp
|
||||
index 45de93f308..1ea5346273 100644
|
||||
--- a/tools/clang/test/Index/print-type-size.cpp
|
||||
+++ b/tools/clang/test/Index/print-type-size.cpp
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
namespace basic {
|
||||
|
||||
-// CHECK64: VarDecl=v:[[@LINE+2]]:6 (Definition) [type=void] [typekind=Void]
|
||||
-// CHECK32: VarDecl=v:[[@LINE+1]]:6 (Definition) [type=void] [typekind=Void]
|
||||
+// CHECK64: VarDecl=v:[[@LINE+2]]:6 (Definition) (invalid) [type=void] [typekind=Void]
|
||||
+// CHECK32: VarDecl=v:[[@LINE+1]]:6 (Definition) (invalid) [type=void] [typekind=Void]
|
||||
void v;
|
||||
|
||||
// CHECK64: VarDecl=v1:[[@LINE+2]]:7 (Definition) [type=void *] [typekind=Pointer] [sizeof=8] [alignof=8]
|
||||
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
|
||||
index cf3581e259..759ed449a4 100644
|
||||
--- a/tools/clang/tools/c-index-test/c-index-test.c
|
||||
+++ b/tools/clang/tools/c-index-test/c-index-test.c
|
||||
@@ -810,6 +810,8 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
|
||||
printf(" (variadic)");
|
||||
if (clang_Cursor_isObjCOptional(Cursor))
|
||||
printf(" (@optional)");
|
||||
+ if (clang_isInvalidDeclaration(Cursor))
|
||||
+ printf(" (invalid)");
|
||||
|
||||
switch (clang_getCursorExceptionSpecificationType(Cursor))
|
||||
{
|
||||
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
|
||||
index 9ba4d5bf30..584de42e7c 100644
|
||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
||||
@@ -5346,6 +5346,15 @@ unsigned clang_isDeclaration(enum CXCursorKind K) {
|
||||
(K >= CXCursor_FirstExtraDecl && K <= CXCursor_LastExtraDecl);
|
||||
}
|
||||
|
||||
+unsigned clang_isInvalidDeclaration(CXCursor C) {
|
||||
+ if (clang_isDeclaration(C.kind)) {
|
||||
+ if (const Decl *D = getCursorDecl(C))
|
||||
+ return D->isInvalidDecl();
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
unsigned clang_isReference(enum CXCursorKind K) {
|
||||
return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
|
||||
}
|
||||
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
|
||||
index e0d178a529..7192baab6a 100644
|
||||
--- a/tools/clang/tools/libclang/libclang.exports
|
||||
+++ b/tools/clang/tools/libclang/libclang.exports
|
||||
@@ -286,6 +286,7 @@ clang_isAttribute
|
||||
clang_isConstQualifiedType
|
||||
clang_isCursorDefinition
|
||||
clang_isDeclaration
|
||||
+clang_isInvalidDeclaration
|
||||
clang_isExpression
|
||||
clang_isFileMultipleIncludeGuarded
|
||||
clang_isFunctionTypeVariadic
|
79
dist/clang/patches/070_D40561_Fix-cursors-for-functions-with-trailing-return-type.patch
vendored
Normal file
79
dist/clang/patches/070_D40561_Fix-cursors-for-functions-with-trailing-return-type.patch
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
--- a/tools/clang/test/Index/annotate-tokens.cpp
|
||||
+++ b/tools/clang/test/Index/annotate-tokens.cpp
|
||||
@@ -37,7 +37,9 @@ class C {
|
||||
~C();
|
||||
};
|
||||
|
||||
-// RUN: c-index-test -test-annotate-tokens=%s:1:1:38:1 %s -fno-delayed-template-parsing | FileCheck %s
|
||||
+auto test5(X) -> X;
|
||||
+
|
||||
+// RUN: c-index-test -test-annotate-tokens=%s:1:1:41:1 %s -std=c++14 -fno-delayed-template-parsing | FileCheck %s
|
||||
// CHECK: Keyword: "struct" [1:1 - 1:7] StructDecl=bonk:1:8 (Definition)
|
||||
// CHECK: Identifier: "bonk" [1:8 - 1:12] StructDecl=bonk:1:8 (Definition)
|
||||
// CHECK: Punctuation: "{" [1:13 - 1:14] StructDecl=bonk:1:8 (Definition)
|
||||
@@ -184,6 +186,14 @@ class C {
|
||||
// CHECK: Punctuation: "}" [29:22 - 29:23] CompoundStmt=
|
||||
// CHECK: Punctuation: "~" [37:3 - 37:4] CXXDestructor=~C:37:3
|
||||
// CHECK: Identifier: "C" [37:4 - 37:5] CXXDestructor=~C:37:3
|
||||
+// CHECK: Keyword: "auto" [40:1 - 40:5] FunctionDecl=test5:40:6
|
||||
+// CHECK: Identifier: "test5" [40:6 - 40:11] FunctionDecl=test5:40:6
|
||||
+// CHECK: Punctuation: "(" [40:11 - 40:12] FunctionDecl=test5:40:6
|
||||
+// CHECK: Identifier: "X" [40:12 - 40:13] TypeRef=struct X:7:8
|
||||
+// CHECK: Punctuation: ")" [40:13 - 40:14] FunctionDecl=test5:40:6
|
||||
+// CHECK: Punctuation: "->" [40:15 - 40:17] FunctionDecl=test5:40:6
|
||||
+// CHECK: Identifier: "X" [40:18 - 40:19] TypeRef=struct X:7:8
|
||||
+// CHECK: Punctuation: ";" [40:19 - 40:20]
|
||||
|
||||
// RUN: env LIBCLANG_DISABLE_CRASH_RECOVERY=1 c-index-test -test-annotate-tokens=%s:32:1:32:13 %s | FileCheck %s -check-prefix=CHECK2
|
||||
// CHECK2: Keyword: "if" [32:3 - 32:5] IfStmt=
|
||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
||||
@@ -783,6 +783,16 @@ bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+static bool HasTrailingReturnType(FunctionDecl *ND) {
|
||||
+ const QualType Ty = ND->getType();
|
||||
+ if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
|
||||
+ if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT))
|
||||
+ return FT->hasTrailingReturn();
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
/// \brief Compare two base or member initializers based on their source order.
|
||||
static int CompareCXXCtorInitializers(CXXCtorInitializer *const *X,
|
||||
CXXCtorInitializer *const *Y) {
|
||||
@@ -802,14 +812,16 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
|
||||
// written. This requires a bit of work.
|
||||
TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens();
|
||||
FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>();
|
||||
+ const bool HasTrailingRT = HasTrailingReturnType(ND);
|
||||
|
||||
// If we have a function declared directly (without the use of a typedef),
|
||||
// visit just the return type. Otherwise, just visit the function's type
|
||||
// now.
|
||||
- if ((FTL && !isa<CXXConversionDecl>(ND) && Visit(FTL.getReturnLoc())) ||
|
||||
+ if ((FTL && !isa<CXXConversionDecl>(ND) && !HasTrailingRT &&
|
||||
+ Visit(FTL.getReturnLoc())) ||
|
||||
(!FTL && Visit(TL)))
|
||||
return true;
|
||||
-
|
||||
+
|
||||
// Visit the nested-name-specifier, if present.
|
||||
if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc())
|
||||
if (VisitNestedNameSpecifierLoc(QualifierLoc))
|
||||
@@ -825,7 +837,11 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
|
||||
// Visit the function parameters, if we have a function type.
|
||||
if (FTL && VisitFunctionTypeLoc(FTL, true))
|
||||
return true;
|
||||
-
|
||||
+
|
||||
+ // Visit the function's trailing return type.
|
||||
+ if (FTL && HasTrailingRT && Visit(FTL.getReturnLoc()))
|
||||
+ return true;
|
||||
+
|
||||
// FIXME: Attributes?
|
||||
}
|
||||
|
78
dist/clang/patches/080_D40643_Add-function-to-get-the-buffer-for-a-file.patch
vendored
Normal file
78
dist/clang/patches/080_D40643_Add-function-to-get-the-buffer-for-a-file.patch
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
|
||||
index f2397d1b63..0f4ade266c 100644
|
||||
--- a/tools/clang/include/clang-c/Index.h
|
||||
+++ b/tools/clang/include/clang-c/Index.h
|
||||
@@ -34,6 +34,7 @@
|
||||
#define CINDEX_VERSION_MAJOR 0
|
||||
#define CINDEX_VERSION_MINOR 43
|
||||
#define CINDEX_VERSION_HAS_ISINVALIDECL_BACKPORTED
|
||||
+#define CINDEX_VERSION_HAS_GETFILECONTENTS_BACKPORTED
|
||||
|
||||
#define CINDEX_VERSION_ENCODE(major, minor) ( \
|
||||
((major) * 10000) \
|
||||
@@ -394,6 +395,21 @@ clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
|
||||
CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
|
||||
const char *file_name);
|
||||
|
||||
+/**
|
||||
+ * \brief Retrieve the buffer associated with the given file.
|
||||
+ *
|
||||
+ * \param tu the translation unit
|
||||
+ *
|
||||
+ * \param file the file for which to retrieve the buffer.
|
||||
+ *
|
||||
+ * \param size [out] if non-NULL, will be set to the size of the buffer.
|
||||
+ *
|
||||
+ * \returns a pointer to the buffer in memory that holds the contents of
|
||||
+ * \p file, or a NULL pointer when the file is not loaded.
|
||||
+ */
|
||||
+CINDEX_LINKAGE const char *clang_getFileContents(CXTranslationUnit tu,
|
||||
+ CXFile file, size_t *size);
|
||||
+
|
||||
/**
|
||||
* \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
|
||||
* or they are both NULL.
|
||||
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
|
||||
index 13599e1910..7902e8a030 100644
|
||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
||||
@@ -4148,6 +4148,27 @@ CXFile clang_getFile(CXTranslationUnit TU, const char *file_name) {
|
||||
return const_cast<FileEntry *>(FMgr.getFile(file_name));
|
||||
}
|
||||
|
||||
+const char *clang_getFileContents(CXTranslationUnit TU, CXFile file,
|
||||
+ size_t *size) {
|
||||
+ if (isNotUsableTU(TU)) {
|
||||
+ LOG_BAD_TU(TU);
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+
|
||||
+ const SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager();
|
||||
+ FileID fid = SM.translateFile(static_cast<FileEntry *>(file));
|
||||
+ bool Invalid = true;
|
||||
+ llvm::MemoryBuffer *buf = SM.getBuffer(fid, &Invalid);
|
||||
+ if (Invalid) {
|
||||
+ if (size)
|
||||
+ *size = 0;
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+ if (size)
|
||||
+ *size = buf->getBufferSize();
|
||||
+ return buf->getBufferStart();
|
||||
+}
|
||||
+
|
||||
unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit TU,
|
||||
CXFile file) {
|
||||
if (isNotUsableTU(TU)) {
|
||||
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
|
||||
index 7192baab6a..c788abb881 100644
|
||||
--- a/tools/clang/tools/libclang/libclang.exports
|
||||
+++ b/tools/clang/tools/libclang/libclang.exports
|
||||
@@ -216,6 +216,7 @@ clang_getExceptionSpecificationType
|
||||
clang_getFieldDeclBitWidth
|
||||
clang_getExpansionLocation
|
||||
clang_getFile
|
||||
+clang_getFileContents
|
||||
clang_getFileLocation
|
||||
clang_getFileName
|
||||
clang_getFileTime
|
@@ -0,0 +1,47 @@
|
||||
--- a/tools/clang/lib/Serialization/ASTReader.cpp
|
||||
+++ b/tools/clang/lib/Serialization/ASTReader.cpp
|
||||
@@ -1220,6 +1220,7 @@
|
||||
|
||||
// Parse the file names
|
||||
std::map<int, int> FileIDs;
|
||||
+ FileIDs[-1] = -1; // For unspecified filenames.
|
||||
for (unsigned I = 0; Record[Idx]; ++I) {
|
||||
// Extract the file name
|
||||
auto Filename = ReadPath(F, Record, Idx);
|
||||
--- a/tools/clang/lib/Serialization/ASTWriter.cpp
|
||||
+++ b/tools/clang/lib/Serialization/ASTWriter.cpp
|
||||
@@ -2363,12 +2363,13 @@
|
||||
|
||||
// Emit the needed file names.
|
||||
llvm::DenseMap<int, int> FilenameMap;
|
||||
+ FilenameMap[-1] = -1; // For unspecified filenames.
|
||||
for (const auto &L : LineTable) {
|
||||
if (L.first.ID < 0)
|
||||
continue;
|
||||
for (auto &LE : L.second) {
|
||||
if (FilenameMap.insert(std::make_pair(LE.FilenameID,
|
||||
- FilenameMap.size())).second)
|
||||
+ FilenameMap.size() - 1)).second)
|
||||
AddPath(LineTable.getFilename(LE.FilenameID), Record);
|
||||
}
|
||||
}
|
||||
--- a/tools/clang/test/PCH/line-directive-nofilename.h
|
||||
+++ b/tools/clang/test/PCH/line-directive-nofilename.h
|
||||
@@ -0,0 +1,5 @@
|
||||
+#line 42
|
||||
+int foo; // This should appear as at line-directive-nofilename.h:42
|
||||
+
|
||||
+#line 100 "foobar.h"
|
||||
+int bar; // This should appear as at foobar.h:100
|
||||
--- a/tools/clang/test/PCH/line-directive-nofilename.c
|
||||
+++ b/tools/clang/test/PCH/line-directive-nofilename.c
|
||||
@@ -0,0 +1,9 @@
|
||||
+// RUN: %clang_cc1 -emit-pch -o %t %S/line-directive-nofilename.h
|
||||
+// RUN: not %clang_cc1 -include-pch %t -fsyntax-only %s 2>&1 | FileCheck %s
|
||||
+
|
||||
+// This causes an "error: redefinition" diagnostic. The notes will have the
|
||||
+// locations of the declarations from the PCH file.
|
||||
+double foo, bar;
|
||||
+
|
||||
+// CHECK: line-directive-nofilename.h:42:5: note: previous definition is here
|
||||
+// CHECK: foobar.h:100:5: note: previous definition is here
|
@@ -0,0 +1,117 @@
|
||||
--- a/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
|
||||
+++ b/tools/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
|
||||
@@ -22,6 +22,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ClangSACheckers.h"
|
||||
+#include "clang/AST/ParentMap.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
|
||||
@@ -262,8 +263,19 @@
|
||||
if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) {
|
||||
// We just finished a base constructor. Now we can use the subclass's
|
||||
// type when resolving virtual calls.
|
||||
- const Decl *D = C.getLocationContext()->getDecl();
|
||||
- recordFixedType(Target, cast<CXXConstructorDecl>(D), C);
|
||||
+ const LocationContext *LCtx = C.getLocationContext();
|
||||
+
|
||||
+ // FIXME: In C++17 classes with non-virtual bases may be treated as
|
||||
+ // aggregates, and in such case no top-frame constructor will be called.
|
||||
+ // Figure out if we need to do anything in this case.
|
||||
+ // FIXME: Instead of relying on the ParentMap, we should have the
|
||||
+ // trigger-statement (InitListExpr in this case) available in this
|
||||
+ // callback, ideally as part of CallEvent.
|
||||
+ if (dyn_cast_or_null<InitListExpr>(
|
||||
+ LCtx->getParentMap().getParent(Ctor->getOriginExpr())))
|
||||
+ return;
|
||||
+
|
||||
+ recordFixedType(Target, cast<CXXConstructorDecl>(LCtx->getDecl()), C);
|
||||
}
|
||||
return;
|
||||
}
|
||||
--- a/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
|
||||
+++ b/tools/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
+#include "clang/AST/ParentMap.h"
|
||||
#include "clang/Basic/PrettyStackTrace.h"
|
||||
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
|
||||
@@ -267,6 +268,23 @@
|
||||
}
|
||||
// FALLTHROUGH
|
||||
case CXXConstructExpr::CK_NonVirtualBase:
|
||||
+ // In C++17, classes with non-virtual bases may be aggregates, so they would
|
||||
+ // be initialized as aggregates without a constructor call, so we may have
|
||||
+ // a base class constructed directly into an initializer list without
|
||||
+ // having the derived-class constructor call on the previous stack frame.
|
||||
+ // Initializer lists may be nested into more initializer lists that
|
||||
+ // correspond to surrounding aggregate initializations.
|
||||
+ // FIXME: For now this code essentially bails out. We need to find the
|
||||
+ // correct target region and set it.
|
||||
+ // FIXME: Instead of relying on the ParentMap, we should have the
|
||||
+ // trigger-statement (InitListExpr in this case) passed down from CFG or
|
||||
+ // otherwise always available during construction.
|
||||
+ if (dyn_cast_or_null<InitListExpr>(LCtx->getParentMap().getParent(CE))) {
|
||||
+ MemRegionManager &MRMgr = getSValBuilder().getRegionManager();
|
||||
+ Target = MRMgr.getCXXTempObjectRegion(CE, LCtx);
|
||||
+ break;
|
||||
+ }
|
||||
+ // FALLTHROUGH
|
||||
case CXXConstructExpr::CK_Delegating: {
|
||||
const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
|
||||
Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor,
|
||||
--- a/tools/clang/test/Analysis/initializer.cpp
|
||||
+++ a/tools/clang/test/Analysis/initializer.cpp
|
||||
@@ -1,4 +1,5 @@
|
||||
// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s
|
||||
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++17 -DCPLUSPLUS17 -verify %s
|
||||
|
||||
void clang_analyzer_eval(bool);
|
||||
|
||||
@@ -224,3 +225,42 @@
|
||||
const char(&f)[2];
|
||||
};
|
||||
}
|
||||
+
|
||||
+namespace CXX17_aggregate_construction {
|
||||
+struct A {
|
||||
+ A();
|
||||
+};
|
||||
+
|
||||
+struct B: public A {
|
||||
+};
|
||||
+
|
||||
+struct C: public B {
|
||||
+};
|
||||
+
|
||||
+struct D: public virtual A {
|
||||
+};
|
||||
+
|
||||
+// In C++17, classes B and C are aggregates, so they will be constructed
|
||||
+// without actually calling their trivial constructor. Used to crash.
|
||||
+void foo() {
|
||||
+ B b = {}; // no-crash
|
||||
+ const B &bl = {}; // no-crash
|
||||
+ B &&br = {}; // no-crash
|
||||
+
|
||||
+ C c = {}; // no-crash
|
||||
+ const C &cl = {}; // no-crash
|
||||
+ C &&cr = {}; // no-crash
|
||||
+
|
||||
+ D d = {}; // no-crash
|
||||
+
|
||||
+#ifdef CPLUSPLUS17
|
||||
+ C cd = {{}}; // no-crash
|
||||
+ const C &cdl = {{}}; // no-crash
|
||||
+ C &&cdr = {{}}; // no-crash
|
||||
+
|
||||
+ const B &bll = {{}}; // no-crash
|
||||
+ const B &bcl = C({{}}); // no-crash
|
||||
+ B &&bcr = C({{}}); // no-crash
|
||||
+#endif
|
||||
+}
|
||||
+}
|
37
dist/clang/patches/110_D41016_Fix-crash-in-unused-lambda-capture-warning-for-VLAs.patch
vendored
Normal file
37
dist/clang/patches/110_D41016_Fix-crash-in-unused-lambda-capture-warning-for-VLAs.patch
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
--- a/tools/clang/include/clang/Sema/ScopeInfo.h
|
||||
+++ b/tools/clang/include/clang/Sema/ScopeInfo.h
|
||||
@@ -560,6 +560,7 @@
|
||||
void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; }
|
||||
|
||||
VarDecl *getVariable() const {
|
||||
+ assert(isVariableCapture());
|
||||
return VarAndNestedAndThis.getPointer();
|
||||
}
|
||||
|
||||
--- a/tools/clang/lib/Sema/SemaLambda.cpp
|
||||
+++ b/tools/clang/lib/Sema/SemaLambda.cpp
|
||||
@@ -1481,6 +1481,9 @@
|
||||
if (CaptureHasSideEffects(From))
|
||||
return;
|
||||
|
||||
+ if (From.isVLATypeCapture())
|
||||
+ return;
|
||||
+
|
||||
auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture);
|
||||
if (From.isThisCapture())
|
||||
diag << "'this'";
|
||||
--- a/tools/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
|
||||
+++ b/tools/clang/test/SemaCXX/warn-unused-lambda-capture.cpp
|
||||
@@ -191,3 +191,12 @@
|
||||
void test_use_template() {
|
||||
test_templated<int>(); // expected-note{{in instantiation of function template specialization 'test_templated<int>' requested here}}
|
||||
}
|
||||
+
|
||||
+namespace pr35555 {
|
||||
+int a;
|
||||
+void b() {
|
||||
+ int c[a];
|
||||
+ auto vla_used = [&c] { return c[0]; };
|
||||
+ auto vla_unused = [&c] {}; // expected-warning{{lambda capture 'c' is not used}}
|
||||
+}
|
||||
+} // namespace pr35555
|
47
dist/clang/patches/120_D41688_Fix-crash-on-code-completion-in-comment-in-included-file.patch
vendored
Normal file
47
dist/clang/patches/120_D41688_Fix-crash-on-code-completion-in-comment-in-included-file.patch
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
--- a/tools/clang/lib/Lex/PPCaching.cpp
|
||||
+++ b/tools/clang/lib/Lex/PPCaching.cpp
|
||||
@@ -105,8 +105,10 @@
|
||||
}
|
||||
|
||||
void Preprocessor::EnterCachingLexMode() {
|
||||
- if (InCachingLexMode())
|
||||
+ if (InCachingLexMode()) {
|
||||
+ assert(CurLexerKind == CLK_CachingLexer && "Unexpected lexer kind");
|
||||
return;
|
||||
+ }
|
||||
|
||||
PushIncludeMacroStack();
|
||||
CurLexerKind = CLK_CachingLexer;
|
||||
--- a/tools/clang/lib/Lex/PPLexerChange.cpp
|
||||
+++ b/tools/clang/lib/Lex/PPLexerChange.cpp
|
||||
@@ -444,6 +444,7 @@
|
||||
}
|
||||
|
||||
CurPPLexer = nullptr;
|
||||
+ recomputeCurLexerKind();
|
||||
return true;
|
||||
}
|
||||
|
||||
--- /dev/null
|
||||
+++ b/tools/clang/test/CodeCompletion/Inputs/comments.h
|
||||
@@ -0,0 +1,4 @@
|
||||
+// PR32732
|
||||
+struct B {
|
||||
+ // <- code completion
|
||||
+};
|
||||
--- /dev/null
|
||||
+++ b/tools/clang/test/CodeCompletion/comments.cpp
|
||||
@@ -0,0 +1,13 @@
|
||||
+// Note: the run lines follow their respective tests, since line/column
|
||||
+// matter in this test.
|
||||
+
|
||||
+#include "comments.h"
|
||||
+
|
||||
+struct A {
|
||||
+ // <- code completion
|
||||
+ /* <- code completion */
|
||||
+};
|
||||
+
|
||||
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%s:7:6 %s
|
||||
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%s:8:6 %s
|
||||
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%S/Inputs/comments.h:3:6 %s
|
@@ -20,6 +20,6 @@ index 4440637820..6798d2ee8b 100644
|
||||
list(APPEND LIBS clangTidyPlugin)
|
||||
list(APPEND LIBS clangIncludeFixerPlugin)
|
||||
+ list(APPEND LIBS clazyPlugin)
|
||||
if(LLVM_ENABLE_MODULES)
|
||||
list(APPEND LLVM_COMPILE_FLAGS "-fmodules-ignore-macro=CLANG_TOOL_EXTRA_BUILD")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
find_library(DL_LIBRARY_PATH dl)
|
144
dist/clang/patches/170_D40013_DeclPrinter-Allow-printing-fully-qualified-name.patch
vendored
Normal file
144
dist/clang/patches/170_D40013_DeclPrinter-Allow-printing-fully-qualified-name.patch
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
From 363747b90f66f097fd45a6cd665adbaf7612188a Mon Sep 17 00:00:00 2001
|
||||
From: Nikolai Kosjar <nikolai.kosjar@qt.io>
|
||||
Date: Mon, 15 Jan 2018 12:51:18 +0100
|
||||
Subject: [PATCH 2/3] Backport: [DeclPrinter] Allow printing fully qualified
|
||||
name of function declaration
|
||||
|
||||
https://reviews.llvm.org/D40013
|
||||
---
|
||||
include/clang/AST/PrettyPrinter.h | 7 +++++-
|
||||
lib/AST/DeclPrinter.cpp | 16 ++++++++----
|
||||
unittests/AST/DeclPrinterTest.cpp | 51 ++++++++++++++++++++++++++++++++++++---
|
||||
3 files changed, 64 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
|
||||
index 274df220e1..edcef0ae24 100644
|
||||
--- a/tools/clang/include/clang/AST/PrettyPrinter.h
|
||||
+++ b/tools/clang/include/clang/AST/PrettyPrinter.h
|
||||
@@ -50,7 +50,8 @@ struct PrintingPolicy {
|
||||
UseVoidForZeroParams(!LO.CPlusPlus),
|
||||
TerseOutput(false), PolishForDeclaration(false),
|
||||
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
|
||||
- IncludeNewlines(true), MSVCFormatting(false) { }
|
||||
+ IncludeNewlines(true), MSVCFormatting(false),
|
||||
+ FullyQualifiedName(false) { }
|
||||
|
||||
/// \brief Adjust this printing policy for cases where it's known that
|
||||
/// we're printing C++ code (for instance, if AST dumping reaches a
|
||||
@@ -200,6 +201,10 @@ struct PrintingPolicy {
|
||||
/// prints anonymous namespaces as `anonymous namespace' and does not insert
|
||||
/// spaces after template arguments.
|
||||
bool MSVCFormatting : 1;
|
||||
+
|
||||
+ /// When true, print the fully qualified name of function declarations.
|
||||
+ /// This is the opposite of SuppressScope and thus overrules it.
|
||||
+ bool FullyQualifiedName : 1;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
|
||||
index 37f08a4985..ea37abe8f6 100644
|
||||
--- a/tools/clang/lib/AST/DeclPrinter.cpp
|
||||
+++ b/tools/clang/lib/AST/DeclPrinter.cpp
|
||||
@@ -510,13 +510,19 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
PrintingPolicy SubPolicy(Policy);
|
||||
SubPolicy.SuppressSpecifiers = false;
|
||||
std::string Proto;
|
||||
- if (!Policy.SuppressScope) {
|
||||
- if (const NestedNameSpecifier *NS = D->getQualifier()) {
|
||||
- llvm::raw_string_ostream OS(Proto);
|
||||
- NS->print(OS, Policy);
|
||||
+
|
||||
+ if (Policy.FullyQualifiedName) {
|
||||
+ Proto += D->getQualifiedNameAsString();
|
||||
+ } else {
|
||||
+ if (!Policy.SuppressScope) {
|
||||
+ if (const NestedNameSpecifier *NS = D->getQualifier()) {
|
||||
+ llvm::raw_string_ostream OS(Proto);
|
||||
+ NS->print(OS, Policy);
|
||||
+ }
|
||||
}
|
||||
+ Proto += D->getNameInfo().getAsString();
|
||||
}
|
||||
- Proto += D->getNameInfo().getAsString();
|
||||
+
|
||||
if (GuideDecl)
|
||||
Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString();
|
||||
if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) {
|
||||
diff --git a/unittests/AST/DeclPrinterTest.cpp b/unittests/AST/DeclPrinterTest.cpp
|
||||
index dc1977d876..4cf8bce20e 100644
|
||||
--- a/tools/clang/unittests/AST/DeclPrinterTest.cpp
|
||||
+++ b/tools/clang/unittests/AST/DeclPrinterTest.cpp
|
||||
@@ -104,15 +104,17 @@ PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
|
||||
return ::testing::AssertionSuccess();
|
||||
}
|
||||
|
||||
-::testing::AssertionResult PrintedDeclCXX98Matches(StringRef Code,
|
||||
- StringRef DeclName,
|
||||
- StringRef ExpectedPrinted) {
|
||||
+::testing::AssertionResult
|
||||
+PrintedDeclCXX98Matches(StringRef Code, StringRef DeclName,
|
||||
+ StringRef ExpectedPrinted,
|
||||
+ PrintingPolicyModifier PolicyModifier = nullptr) {
|
||||
std::vector<std::string> Args(1, "-std=c++98");
|
||||
return PrintedDeclMatches(Code,
|
||||
Args,
|
||||
namedDecl(hasName(DeclName)).bind("id"),
|
||||
ExpectedPrinted,
|
||||
- "input.cc");
|
||||
+ "input.cc",
|
||||
+ PolicyModifier);
|
||||
}
|
||||
|
||||
::testing::AssertionResult
|
||||
@@ -350,6 +352,47 @@ TEST(DeclPrinter, TestFunctionDecl1) {
|
||||
"void A()"));
|
||||
}
|
||||
|
||||
+TEST(DeclPrinter, TestFreeFunctionDecl_FullyQualifiedName) {
|
||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
||||
+ "void A();",
|
||||
+ "A",
|
||||
+ "void A()",
|
||||
+ [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
|
||||
+}
|
||||
+
|
||||
+TEST(DeclPrinter, TestFreeFunctionDeclInNamespace_FullyQualifiedName) {
|
||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
||||
+ "namespace X { void A(); };",
|
||||
+ "A",
|
||||
+ "void X::A()",
|
||||
+ [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
|
||||
+}
|
||||
+
|
||||
+TEST(DeclPrinter, TestMemberFunction_FullyQualifiedName) {
|
||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
||||
+ "struct X { void A(); };",
|
||||
+ "A",
|
||||
+ "void X::A()",
|
||||
+ [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
|
||||
+}
|
||||
+
|
||||
+TEST(DeclPrinter, TestMemberFunctionInNamespace_FullyQualifiedName) {
|
||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
||||
+ "namespace Z { struct X { void A(); }; }",
|
||||
+ "A",
|
||||
+ "void Z::X::A()",
|
||||
+ [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
|
||||
+}
|
||||
+
|
||||
+TEST(DeclPrinter, TestMemberFunctionOutside_FullyQualifiedName) {
|
||||
+ ASSERT_TRUE(PrintedDeclCXX98Matches(
|
||||
+ "struct X { void A(); };"
|
||||
+ "void X::A() {}",
|
||||
+ functionDecl(hasName("A"), isDefinition()).bind("id"),
|
||||
+ "void X::A()",
|
||||
+ [](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
|
||||
+}
|
||||
+
|
||||
TEST(DeclPrinter, TestFunctionDecl2) {
|
||||
ASSERT_TRUE(PrintedDeclCXX98Matches(
|
||||
"void A() {}",
|
||||
--
|
||||
2.15.1
|
||||
|
544
dist/clang/patches/180_D39903_libclang-Allow-pretty-printing-declarations.patch
vendored
Normal file
544
dist/clang/patches/180_D39903_libclang-Allow-pretty-printing-declarations.patch
vendored
Normal file
@@ -0,0 +1,544 @@
|
||||
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
|
||||
index 0f4ade266c..f188ec9d8c 100644
|
||||
--- a/tools/clang/include/clang-c/Index.h
|
||||
+++ b/tools/clang/include/clang-c/Index.h
|
||||
@@ -35,6 +35,7 @@
|
||||
#define CINDEX_VERSION_MINOR 43
|
||||
#define CINDEX_VERSION_HAS_ISINVALIDECL_BACKPORTED
|
||||
#define CINDEX_VERSION_HAS_GETFILECONTENTS_BACKPORTED
|
||||
+#define CINDEX_VERSION_HAS_PRETTYDECL_BACKPORTED
|
||||
|
||||
#define CINDEX_VERSION_ENCODE(major, minor) ( \
|
||||
((major) * 10000) \
|
||||
@@ -4066,6 +4067,90 @@ CINDEX_LINKAGE CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
|
||||
unsigned pieceIndex,
|
||||
unsigned options);
|
||||
|
||||
+/**
|
||||
+ * \brief Opaque pointer representing a policy that controls pretty printing
|
||||
+ * for \c clang_getCursorPrettyPrinted.
|
||||
+ */
|
||||
+typedef void *CXPrintingPolicy;
|
||||
+
|
||||
+/**
|
||||
+ * \brief Properties for the printing policy.
|
||||
+ *
|
||||
+ * See \c clang::PrintingPolicy for more information.
|
||||
+ */
|
||||
+enum CXPrintingPolicyProperty {
|
||||
+ CXPrintingPolicy_Indentation,
|
||||
+ CXPrintingPolicy_SuppressSpecifiers,
|
||||
+ CXPrintingPolicy_SuppressTagKeyword,
|
||||
+ CXPrintingPolicy_IncludeTagDefinition,
|
||||
+ CXPrintingPolicy_SuppressScope,
|
||||
+ CXPrintingPolicy_SuppressUnwrittenScope,
|
||||
+ CXPrintingPolicy_SuppressInitializers,
|
||||
+ CXPrintingPolicy_ConstantArraySizeAsWritten,
|
||||
+ CXPrintingPolicy_AnonymousTagLocations,
|
||||
+ CXPrintingPolicy_SuppressStrongLifetime,
|
||||
+ CXPrintingPolicy_SuppressLifetimeQualifiers,
|
||||
+ CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors,
|
||||
+ CXPrintingPolicy_Bool,
|
||||
+ CXPrintingPolicy_Restrict,
|
||||
+ CXPrintingPolicy_Alignof,
|
||||
+ CXPrintingPolicy_UnderscoreAlignof,
|
||||
+ CXPrintingPolicy_UseVoidForZeroParams,
|
||||
+ CXPrintingPolicy_TerseOutput,
|
||||
+ CXPrintingPolicy_PolishForDeclaration,
|
||||
+ CXPrintingPolicy_Half,
|
||||
+ CXPrintingPolicy_MSWChar,
|
||||
+ CXPrintingPolicy_IncludeNewlines,
|
||||
+ CXPrintingPolicy_MSVCFormatting,
|
||||
+ CXPrintingPolicy_ConstantsAsWritten, /* Ops, not yet there in clang 5.0 and we do not need it. */
|
||||
+ CXPrintingPolicy_SuppressImplicitBase, /* Ops, not yet there in clang 5.0 and we do not need it. */
|
||||
+ CXPrintingPolicy_FullyQualifiedName,
|
||||
+
|
||||
+ CXPrintingPolicy_LastProperty = CXPrintingPolicy_FullyQualifiedName
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * \brief Get a property value for the given printing policy.
|
||||
+ */
|
||||
+CINDEX_LINKAGE unsigned
|
||||
+clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
|
||||
+ enum CXPrintingPolicyProperty Property);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Set a property value for the given printing policy.
|
||||
+ */
|
||||
+CINDEX_LINKAGE void
|
||||
+clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
|
||||
+ enum CXPrintingPolicyProperty Property,
|
||||
+ unsigned Value);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Retrieve the default policy for the cursor.
|
||||
+ *
|
||||
+ * The policy should be released after use with \c
|
||||
+ * clang_PrintingPolicy_dispose.
|
||||
+ */
|
||||
+CINDEX_LINKAGE CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Release a printing policy.
|
||||
+ */
|
||||
+CINDEX_LINKAGE void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy);
|
||||
+
|
||||
+/**
|
||||
+ * \brief Pretty print declarations.
|
||||
+ *
|
||||
+ * \param Cursor The cursor representing a declaration.
|
||||
+ *
|
||||
+ * \param Policy The policy to control the entities being printed. If
|
||||
+ * NULL, a default policy is used.
|
||||
+ *
|
||||
+ * \returns The pretty printed declaration or the empty string for
|
||||
+ * other cursors.
|
||||
+ */
|
||||
+CINDEX_LINKAGE CXString clang_getCursorPrettyPrinted(CXCursor Cursor,
|
||||
+ CXPrintingPolicy Policy);
|
||||
+
|
||||
/**
|
||||
* \brief Retrieve the display name for the entity referenced by this cursor.
|
||||
*
|
||||
diff --git a/test/Index/print-display-names.cpp b/test/Index/print-display-names.cpp
|
||||
index 94fe4665e6..5ba10e43bc 100644
|
||||
--- a/tools/clang/test/Index/print-display-names.cpp
|
||||
+++ b/tools/clang/test/Index/print-display-names.cpp
|
||||
@@ -12,9 +12,20 @@ void g(ClassTmpl<T, T>);
|
||||
|
||||
template<> void g<int>(ClassTmpl<int, int>);
|
||||
|
||||
-// RUN: c-index-test -test-load-source all-display %s | FileCheck %s
|
||||
-// CHECK: print-display-names.cpp:2:7: ClassTemplate=ClassTmpl<T, typename>:2:7
|
||||
-// CHECK: print-display-names.cpp:6:16: ClassDecl=ClassTmpl<Integer, Integer>:6:16 (Definition)
|
||||
-// CHECK: print-display-names.cpp:8:6: FunctionDecl=f(ClassTmpl<float, Integer>):8:6
|
||||
-// CHECK: print-display-names.cpp:11:6: FunctionTemplate=g(ClassTmpl<T, T>):11:6
|
||||
-// CHECK: print-display-names.cpp:13:17: FunctionDecl=g<>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6]
|
||||
+// RUN: c-index-test -test-load-source all-display %s | FileCheck %s --check-prefix=DISPLAY_NAME
|
||||
+// DISPLAY_NAME: print-display-names.cpp:2:7: ClassTemplate=ClassTmpl<T, typename>:2:7
|
||||
+// DISPLAY_NAME: print-display-names.cpp:6:16: ClassDecl=ClassTmpl<Integer, Integer>:6:16 (Definition)
|
||||
+// DISPLAY_NAME: print-display-names.cpp:8:6: FunctionDecl=f(ClassTmpl<float, Integer>):8:6
|
||||
+// DISPLAY_NAME: print-display-names.cpp:11:6: FunctionTemplate=g(ClassTmpl<T, T>):11:6
|
||||
+// DISPLAY_NAME: print-display-names.cpp:13:17: FunctionDecl=g<>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6]
|
||||
+
|
||||
+// RUN: env CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT=1 c-index-test -test-load-source all-pretty %s | FileCheck %s --check-prefix=PRETTY
|
||||
+// PRETTY: print-display-names.cpp:2:7: ClassTemplate=template <typename T, typename > class ClassTmpl {}:2:7 (Definition) Extent=[1:1 - 2:20]
|
||||
+// PRETTY: print-display-names.cpp:4:13: TypedefDecl=typedef int Integer:4:13 (Definition) Extent=[4:1 - 4:20]
|
||||
+// PRETTY: print-display-names.cpp:6:16: ClassDecl=template<> class ClassTmpl<int, int> {}:6:16 (Definition) [Specialization of ClassTmpl:2:7] Extent=[6:1 - 6:43]
|
||||
+// PRETTY: print-display-names.cpp:8:6: FunctionDecl=void f(ClassTmpl<float, Integer> p):8:6 Extent=[8:1 - 8:36]
|
||||
+// PRETTY: print-display-names.cpp:8:34: ParmDecl=ClassTmpl<float, Integer> p:8:34 (Definition) Extent=[8:8 - 8:35]
|
||||
+// PRETTY: print-display-names.cpp:11:6: FunctionTemplate=template <typename T> void g(ClassTmpl<T, T>):11:6 Extent=[10:1 - 11:24]
|
||||
+// PRETTY: print-display-names.cpp:11:23: ParmDecl=ClassTmpl<T, T>:11:23 (Definition) Extent=[11:8 - 11:23]
|
||||
+// PRETTY: print-display-names.cpp:13:17: FunctionDecl=template<> void g<int>(ClassTmpl<int, int>):13:17 [Specialization of g:11:6] [Template arg 0: kind: 1, type: int] Extent=[13:1 - 13:44]
|
||||
+// PRETTY: print-display-names.cpp:13:43: ParmDecl=ClassTmpl<int, int>:13:43 (Definition) Extent=[13:24 - 13:43]
|
||||
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
|
||||
index 759ed449a4..ce2f549234 100644
|
||||
--- a/tools/clang/tools/c-index-test/c-index-test.c
|
||||
+++ b/tools/clang/tools/c-index-test/c-index-test.c
|
||||
@@ -86,6 +86,69 @@ static unsigned getDefaultParsingOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
+static void ModifyPrintingPolicyAccordingToEnv(CXPrintingPolicy Policy) {
|
||||
+ struct Mapping {
|
||||
+ const char *name;
|
||||
+ enum CXPrintingPolicyProperty property;
|
||||
+ };
|
||||
+ struct Mapping mappings[] = {
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_INDENTATION", CXPrintingPolicy_Indentation},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSPECIFIERS",
|
||||
+ CXPrintingPolicy_SuppressSpecifiers},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTAGKEYWORD",
|
||||
+ CXPrintingPolicy_SuppressTagKeyword},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_INCLUDETAGDEFINITION",
|
||||
+ CXPrintingPolicy_IncludeTagDefinition},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSCOPE",
|
||||
+ CXPrintingPolicy_SuppressScope},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSUNWRITTENSCOPE",
|
||||
+ CXPrintingPolicy_SuppressUnwrittenScope},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSINITIALIZERS",
|
||||
+ CXPrintingPolicy_SuppressInitializers},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_CONSTANTARRAYSIZEASWRITTEN",
|
||||
+ CXPrintingPolicy_ConstantArraySizeAsWritten},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_ANONYMOUSTAGLOCATIONS",
|
||||
+ CXPrintingPolicy_AnonymousTagLocations},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSSTRONGLIFETIME",
|
||||
+ CXPrintingPolicy_SuppressStrongLifetime},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSLIFETIMEQUALIFIERS",
|
||||
+ CXPrintingPolicy_SuppressLifetimeQualifiers},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSTEMPLATEARGSINCXXCONSTRUCTORS",
|
||||
+ CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_BOOL", CXPrintingPolicy_Bool},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_RESTRICT", CXPrintingPolicy_Restrict},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_ALIGNOF", CXPrintingPolicy_Alignof},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_UNDERSCOREALIGNOF",
|
||||
+ CXPrintingPolicy_UnderscoreAlignof},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_USEVOIDFORZEROPARAMS",
|
||||
+ CXPrintingPolicy_UseVoidForZeroParams},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_TERSEOUTPUT", CXPrintingPolicy_TerseOutput},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_POLISHFORDECLARATION",
|
||||
+ CXPrintingPolicy_PolishForDeclaration},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_HALF", CXPrintingPolicy_Half},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_MSWCHAR", CXPrintingPolicy_MSWChar},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_INCLUDENEWLINES",
|
||||
+ CXPrintingPolicy_IncludeNewlines},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_MSVCFORMATTING",
|
||||
+ CXPrintingPolicy_MSVCFormatting},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_CONSTANTSASWRITTEN",
|
||||
+ CXPrintingPolicy_ConstantsAsWritten},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_SUPPRESSIMPLICITBASE",
|
||||
+ CXPrintingPolicy_SuppressImplicitBase},
|
||||
+ {"CINDEXTEST_PRINTINGPOLICY_FULLYQUALIFIEDNAME",
|
||||
+ CXPrintingPolicy_FullyQualifiedName},
|
||||
+ };
|
||||
+
|
||||
+ unsigned i;
|
||||
+ for (i = 0; i < sizeof(mappings) / sizeof(struct Mapping); i++) {
|
||||
+ char *value = getenv(mappings[i].name);
|
||||
+ if (value) {
|
||||
+ clang_PrintingPolicy_setProperty(Policy, mappings[i].property,
|
||||
+ (unsigned)strtoul(value, 0L, 10));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/** \brief Returns 0 in case of success, non-zero in case of a failure. */
|
||||
static int checkForErrors(CXTranslationUnit TU);
|
||||
|
||||
@@ -356,7 +419,11 @@ static void PrintRange(CXSourceRange R, const char *str) {
|
||||
PrintExtent(stdout, begin_line, begin_column, end_line, end_column);
|
||||
}
|
||||
|
||||
-int want_display_name = 0;
|
||||
+static enum DisplayType {
|
||||
+ DisplayType_Spelling,
|
||||
+ DisplayType_DisplayName,
|
||||
+ DisplayType_Pretty
|
||||
+} wanted_display_type = DisplayType_Spelling;
|
||||
|
||||
static void printVersion(const char *Prefix, CXVersion Version) {
|
||||
if (Version.Major < 0)
|
||||
@@ -656,6 +723,24 @@ static int lineCol_cmp(const void *p1, const void *p2) {
|
||||
return (int)lhs->col - (int)rhs->col;
|
||||
}
|
||||
|
||||
+static CXString CursorToText(CXCursor Cursor) {
|
||||
+ switch (wanted_display_type) {
|
||||
+ case DisplayType_Spelling:
|
||||
+ return clang_getCursorSpelling(Cursor);
|
||||
+ case DisplayType_DisplayName:
|
||||
+ return clang_getCursorDisplayName(Cursor);
|
||||
+ case DisplayType_Pretty:
|
||||
+ default: {
|
||||
+ CXString text;
|
||||
+ CXPrintingPolicy Policy = clang_getCursorPrintingPolicy(Cursor);
|
||||
+ ModifyPrintingPolicyAccordingToEnv(Policy);
|
||||
+ text = clang_getCursorPrettyPrinted(Cursor, Policy);
|
||||
+ clang_PrintingPolicy_dispose(Policy);
|
||||
+ return text;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
|
||||
CXTranslationUnit TU = clang_Cursor_getTranslationUnit(Cursor);
|
||||
if (clang_isInvalid(Cursor.kind)) {
|
||||
@@ -682,8 +767,7 @@ static void PrintCursor(CXCursor Cursor, const char *CommentSchemaFile) {
|
||||
int I;
|
||||
|
||||
ks = clang_getCursorKindSpelling(Cursor.kind);
|
||||
- string = want_display_name? clang_getCursorDisplayName(Cursor)
|
||||
- : clang_getCursorSpelling(Cursor);
|
||||
+ string = CursorToText(Cursor);
|
||||
printf("%s=%s", clang_getCString(ks),
|
||||
clang_getCString(string));
|
||||
clang_disposeString(ks);
|
||||
@@ -1675,7 +1759,12 @@ static int perform_test_load(CXIndex Idx, CXTranslationUnit TU,
|
||||
else if (!strcmp(filter, "all-display") ||
|
||||
!strcmp(filter, "local-display")) {
|
||||
ck = NULL;
|
||||
- want_display_name = 1;
|
||||
+ wanted_display_type = DisplayType_DisplayName;
|
||||
+ }
|
||||
+ else if (!strcmp(filter, "all-pretty") ||
|
||||
+ !strcmp(filter, "local-pretty")) {
|
||||
+ ck = NULL;
|
||||
+ wanted_display_type = DisplayType_Pretty;
|
||||
}
|
||||
else if (!strcmp(filter, "none")) K = (enum CXCursorKind) ~0;
|
||||
else if (!strcmp(filter, "category")) K = CXCursor_ObjCCategoryDecl;
|
||||
@@ -1742,8 +1831,11 @@ int perform_test_load_source(int argc, const char **argv,
|
||||
unsigned I;
|
||||
|
||||
Idx = clang_createIndex(/* excludeDeclsFromPCH */
|
||||
- (!strcmp(filter, "local") ||
|
||||
- !strcmp(filter, "local-display"))? 1 : 0,
|
||||
+ (!strcmp(filter, "local") ||
|
||||
+ !strcmp(filter, "local-display") ||
|
||||
+ !strcmp(filter, "local-pretty"))
|
||||
+ ? 1
|
||||
+ : 0,
|
||||
/* displayDiagnostics=*/1);
|
||||
|
||||
if ((CommentSchemaFile = parse_comments_schema(argc, argv))) {
|
||||
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
|
||||
index 45ee9803f2..72b14fdb53 100644
|
||||
--- a/tools/clang/tools/libclang/CIndex.cpp
|
||||
+++ b/tools/clang/tools/libclang/CIndex.cpp
|
||||
@@ -4652,6 +4652,197 @@ CXStringSet *clang_Cursor_getCXXManglings(CXCursor C) {
|
||||
return cxstring::createSet(Manglings);
|
||||
}
|
||||
|
||||
+CXPrintingPolicy clang_getCursorPrintingPolicy(CXCursor C) {
|
||||
+ if (clang_Cursor_isNull(C))
|
||||
+ return 0;
|
||||
+ return new PrintingPolicy(getCursorContext(C).getPrintingPolicy());
|
||||
+}
|
||||
+
|
||||
+void clang_PrintingPolicy_dispose(CXPrintingPolicy Policy) {
|
||||
+ if (Policy)
|
||||
+ delete static_cast<PrintingPolicy *>(Policy);
|
||||
+}
|
||||
+
|
||||
+unsigned
|
||||
+clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
|
||||
+ enum CXPrintingPolicyProperty Property) {
|
||||
+ if (!Policy)
|
||||
+ return 0;
|
||||
+
|
||||
+ PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
|
||||
+ switch (Property) {
|
||||
+ case CXPrintingPolicy_Indentation:
|
||||
+ return P->Indentation;
|
||||
+ case CXPrintingPolicy_SuppressSpecifiers:
|
||||
+ return P->SuppressSpecifiers;
|
||||
+ case CXPrintingPolicy_SuppressTagKeyword:
|
||||
+ return P->SuppressTagKeyword;
|
||||
+ case CXPrintingPolicy_IncludeTagDefinition:
|
||||
+ return P->IncludeTagDefinition;
|
||||
+ case CXPrintingPolicy_SuppressScope:
|
||||
+ return P->SuppressScope;
|
||||
+ case CXPrintingPolicy_SuppressUnwrittenScope:
|
||||
+ return P->SuppressUnwrittenScope;
|
||||
+ case CXPrintingPolicy_SuppressInitializers:
|
||||
+ return P->SuppressInitializers;
|
||||
+ case CXPrintingPolicy_ConstantArraySizeAsWritten:
|
||||
+ return P->ConstantArraySizeAsWritten;
|
||||
+ case CXPrintingPolicy_AnonymousTagLocations:
|
||||
+ return P->AnonymousTagLocations;
|
||||
+ case CXPrintingPolicy_SuppressStrongLifetime:
|
||||
+ return P->SuppressStrongLifetime;
|
||||
+ case CXPrintingPolicy_SuppressLifetimeQualifiers:
|
||||
+ return P->SuppressLifetimeQualifiers;
|
||||
+ case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
|
||||
+ return P->SuppressTemplateArgsInCXXConstructors;
|
||||
+ case CXPrintingPolicy_Bool:
|
||||
+ return P->Bool;
|
||||
+ case CXPrintingPolicy_Restrict:
|
||||
+ return P->Restrict;
|
||||
+ case CXPrintingPolicy_Alignof:
|
||||
+ return P->Alignof;
|
||||
+ case CXPrintingPolicy_UnderscoreAlignof:
|
||||
+ return P->UnderscoreAlignof;
|
||||
+ case CXPrintingPolicy_UseVoidForZeroParams:
|
||||
+ return P->UseVoidForZeroParams;
|
||||
+ case CXPrintingPolicy_TerseOutput:
|
||||
+ return P->TerseOutput;
|
||||
+ case CXPrintingPolicy_PolishForDeclaration:
|
||||
+ return P->PolishForDeclaration;
|
||||
+ case CXPrintingPolicy_Half:
|
||||
+ return P->Half;
|
||||
+ case CXPrintingPolicy_MSWChar:
|
||||
+ return P->MSWChar;
|
||||
+ case CXPrintingPolicy_IncludeNewlines:
|
||||
+ return P->IncludeNewlines;
|
||||
+ case CXPrintingPolicy_MSVCFormatting:
|
||||
+ return P->MSVCFormatting;
|
||||
+ case CXPrintingPolicy_ConstantsAsWritten:
|
||||
+ // Ops, not yet there in clang 5.0 and we do not need it.
|
||||
+ return 0;
|
||||
+ case CXPrintingPolicy_SuppressImplicitBase:
|
||||
+ // Ops, not yet there in clang 5.0 and we do not need it.
|
||||
+ return 0;
|
||||
+ case CXPrintingPolicy_FullyQualifiedName:
|
||||
+ return P->FullyQualifiedName;
|
||||
+ }
|
||||
+
|
||||
+ assert(false && "Invalid CXPrintingPolicyProperty");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
|
||||
+ enum CXPrintingPolicyProperty Property,
|
||||
+ unsigned Value) {
|
||||
+ if (!Policy)
|
||||
+ return;
|
||||
+
|
||||
+ PrintingPolicy *P = static_cast<PrintingPolicy *>(Policy);
|
||||
+ switch (Property) {
|
||||
+ case CXPrintingPolicy_Indentation:
|
||||
+ P->Indentation = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_SuppressSpecifiers:
|
||||
+ P->SuppressSpecifiers = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_SuppressTagKeyword:
|
||||
+ P->SuppressTagKeyword = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_IncludeTagDefinition:
|
||||
+ P->IncludeTagDefinition = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_SuppressScope:
|
||||
+ P->SuppressScope = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_SuppressUnwrittenScope:
|
||||
+ P->SuppressUnwrittenScope = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_SuppressInitializers:
|
||||
+ P->SuppressInitializers = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_ConstantArraySizeAsWritten:
|
||||
+ P->ConstantArraySizeAsWritten = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_AnonymousTagLocations:
|
||||
+ P->AnonymousTagLocations = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_SuppressStrongLifetime:
|
||||
+ P->SuppressStrongLifetime = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_SuppressLifetimeQualifiers:
|
||||
+ P->SuppressLifetimeQualifiers = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_SuppressTemplateArgsInCXXConstructors:
|
||||
+ P->SuppressTemplateArgsInCXXConstructors = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_Bool:
|
||||
+ P->Bool = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_Restrict:
|
||||
+ P->Restrict = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_Alignof:
|
||||
+ P->Alignof = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_UnderscoreAlignof:
|
||||
+ P->UnderscoreAlignof = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_UseVoidForZeroParams:
|
||||
+ P->UseVoidForZeroParams = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_TerseOutput:
|
||||
+ P->TerseOutput = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_PolishForDeclaration:
|
||||
+ P->PolishForDeclaration = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_Half:
|
||||
+ P->Half = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_MSWChar:
|
||||
+ P->MSWChar = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_IncludeNewlines:
|
||||
+ P->IncludeNewlines = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_MSVCFormatting:
|
||||
+ P->MSVCFormatting = Value;
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_ConstantsAsWritten:
|
||||
+ // Ops, not yet there in clang 5.0 and we do not need it.
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_SuppressImplicitBase:
|
||||
+ // Ops, not yet there in clang 5.0 and we do not need it.
|
||||
+ return;
|
||||
+ case CXPrintingPolicy_FullyQualifiedName:
|
||||
+ P->FullyQualifiedName = Value;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ assert(false && "Invalid CXPrintingPolicyProperty");
|
||||
+}
|
||||
+
|
||||
+CXString clang_getCursorPrettyPrinted(CXCursor C, CXPrintingPolicy cxPolicy) {
|
||||
+ if (clang_Cursor_isNull(C))
|
||||
+ return cxstring::createEmpty();
|
||||
+
|
||||
+ if (clang_isDeclaration(C.kind)) {
|
||||
+ const Decl *D = getCursorDecl(C);
|
||||
+ if (!D)
|
||||
+ return cxstring::createEmpty();
|
||||
+
|
||||
+ SmallString<128> Str;
|
||||
+ llvm::raw_svector_ostream OS(Str);
|
||||
+ PrintingPolicy *UserPolicy = static_cast<PrintingPolicy *>(cxPolicy);
|
||||
+ D->print(OS, UserPolicy ? *UserPolicy
|
||||
+ : getCursorContext(C).getPrintingPolicy());
|
||||
+
|
||||
+ return cxstring::createDup(OS.str());
|
||||
+ }
|
||||
+
|
||||
+ return cxstring::createEmpty();
|
||||
+}
|
||||
+
|
||||
CXString clang_getCursorDisplayName(CXCursor C) {
|
||||
if (!clang_isDeclaration(C.kind))
|
||||
return clang_getCursorSpelling(C);
|
||||
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
|
||||
index c788abb881..ed4773b132 100644
|
||||
--- a/tools/clang/tools/libclang/libclang.exports
|
||||
+++ b/tools/clang/tools/libclang/libclang.exports
|
||||
@@ -175,6 +175,8 @@ clang_getCursorAvailability
|
||||
clang_getCursorCompletionString
|
||||
clang_getCursorDefinition
|
||||
clang_getCursorDisplayName
|
||||
+clang_getCursorPrintingPolicy
|
||||
+clang_getCursorPrettyPrinted
|
||||
clang_getCursorExtent
|
||||
clang_getCursorExceptionSpecificationType
|
||||
clang_getCursorKind
|
||||
@@ -355,3 +357,6 @@ clang_EvalResult_isUnsignedInt
|
||||
clang_EvalResult_getAsDouble
|
||||
clang_EvalResult_getAsStr
|
||||
clang_EvalResult_dispose
|
||||
+clang_PrintingPolicy_getProperty
|
||||
+clang_PrintingPolicy_setProperty
|
||||
+clang_PrintingPolicy_dispose
|
||||
diff --git a/unittests/libclang/LibclangTest.cpp b/unittests/libclang/LibclangTest.cpp
|
||||
index f2a96d6be6..a9f5ee1da4 100644
|
||||
--- a/tools/clang/unittests/libclang/LibclangTest.cpp
|
||||
+++ b/tools/clang/unittests/libclang/LibclangTest.cpp
|
||||
@@ -572,3 +572,33 @@ TEST_F(LibclangReparseTest, clang_parseTranslationUnit2FullArgv) {
|
||||
EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
|
||||
DisplayDiagnostics();
|
||||
}
|
||||
+
|
||||
+class LibclangPrintingPolicyTest : public LibclangParseTest {
|
||||
+public:
|
||||
+ CXPrintingPolicy Policy = nullptr;
|
||||
+
|
||||
+ void SetUp() override {
|
||||
+ LibclangParseTest::SetUp();
|
||||
+ std::string File = "file.cpp";
|
||||
+ WriteFile(File, "int i;\n");
|
||||
+ ClangTU = clang_parseTranslationUnit(Index, File.c_str(), nullptr, 0,
|
||||
+ nullptr, 0, TUFlags);
|
||||
+ CXCursor TUCursor = clang_getTranslationUnitCursor(ClangTU);
|
||||
+ Policy = clang_getCursorPrintingPolicy(TUCursor);
|
||||
+ }
|
||||
+ void TearDown() override {
|
||||
+ clang_PrintingPolicy_dispose(Policy);
|
||||
+ LibclangParseTest::TearDown();
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+TEST_F(LibclangPrintingPolicyTest, SetAndGetProperties) {
|
||||
+ for (unsigned Value = 0; Value < 2; ++Value) {
|
||||
+ for (int I = 0; I < CXPrintingPolicy_LastProperty; ++I) {
|
||||
+ auto Property = static_cast<enum CXPrintingPolicyProperty>(I);
|
||||
+
|
||||
+ clang_PrintingPolicy_setProperty(Policy, Property, Value);
|
||||
+ EXPECT_EQ(Value, clang_PrintingPolicy_getProperty(Policy, Property));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
93
dist/clang/patches/README.md
vendored
93
dist/clang/patches/README.md
vendored
@@ -9,41 +9,106 @@ The patches in this directory are applied to LLVM/Clang with:
|
||||
Backported changes
|
||||
------------------
|
||||
|
||||
##### D35355_Fix-templated-type-alias-completion-when-using-global-completion-cache.patch
|
||||
##### 110_D41016_Fix-crash-in-unused-lambda-capture-warning-for-VLAs.patch
|
||||
|
||||
* <https://reviews.llvm.org/D41016>
|
||||
|
||||
[Sema] Fix crash in unused-lambda-capture warning for VLAs
|
||||
|
||||
##### 010_D35355_Fix-templated-type-alias-completion-when-using-global-completion-cache.patch
|
||||
|
||||
* <https://reviews.llvm.org/D35355>
|
||||
|
||||
Fixes completion involving templated type alias.
|
||||
|
||||
##### D37435_Dont-show-deleted-function-constructor-candidates-for-code-completion.patch
|
||||
##### 120_D41688_Fix-crash-on-code-completion-in-comment-in-included-file.patch
|
||||
|
||||
* <https://reviews.llvm.org/D37435>
|
||||
* <https://bugs.llvm.org/show_bug.cgi?id=34402>
|
||||
* <https://reviews.llvm.org/D41688>
|
||||
|
||||
Fixes completion involving implicitly deleted copy constructors.
|
||||
[Lex] Fix crash on code completion in comment in included file.
|
||||
|
||||
##### rL310905_Avoid-PointerIntPair-of-constexpr-EvalInfo-structs.patch
|
||||
##### 100_D40841_Fix-a-crash-on-C++17-AST-for-non-trivial-construction-into-a-trivial-brace-initialize.patch
|
||||
|
||||
* <https://reviews.llvm.org/rL310905>
|
||||
* <https://bugs.llvm.org/show_bug.cgi?id=32018>
|
||||
* <https://reviews.llvm.org/D40841>
|
||||
|
||||
Fixes build/miscompilation of LLVM/Clang with MinGW, which enables generation
|
||||
of profile-guided-optimization builds for Windows.
|
||||
[analyzer] Fix a crash on C++17 AST for non-trivial construction into a trivial brace initializer.
|
||||
|
||||
##### 090_D40746_Correctly-handle-line-table-entries-without-filenames-during-AST-serialization.patch
|
||||
|
||||
* <https://reviews.llvm.org/D40746>
|
||||
|
||||
Correctly handle line table entries without filenames during AST serialization
|
||||
Fixes crash during a reparse.
|
||||
|
||||
##### 050_D40027_Fix-cursors-for-in-class-initializer-of-field-declarations.patch
|
||||
|
||||
* <https://reviews.llvm.org/D40027>
|
||||
* <https://bugs.llvm.org/show_bug.cgi?id=33745>
|
||||
|
||||
[libclang] Fix cursors for in-class initializer of field declarations
|
||||
Fixes AST access to initializers of class members. Affects mostly semantic highlighting and highlighting of local uses.
|
||||
|
||||
##### 070_D40561_Fix-cursors-for-functions-with-trailing-return-type.patch
|
||||
|
||||
* <https://reviews.llvm.org/D40561>
|
||||
|
||||
[libclang] Fix cursors for functions with trailing return type
|
||||
|
||||
##### 060_D40072_Support-querying-whether-a-declaration-is-invalid.patch
|
||||
|
||||
* <https://reviews.llvm.org/D40072>
|
||||
|
||||
[libclang] Add support for checking abstractness of records
|
||||
Would need https://codereview.qt-project.org/#/c/211497/ on Qt Creator side.
|
||||
|
||||
##### 040_D39957_Honor-TerseOutput-for-constructors.patch
|
||||
|
||||
* <https://reviews.llvm.org/D39957>
|
||||
|
||||
[DeclPrinter] Honor TerseOutput for constructors
|
||||
Avoids printing member initialization list and body for constructor.
|
||||
|
||||
##### 080_D40643_Add-function-to-get-the-buffer-for-a-file.patch
|
||||
|
||||
* <https://reviews.llvm.org/D40643>
|
||||
* <https://reviews.llvm.org/rL319881>
|
||||
|
||||
[libclang] Add function to get the buffer for a file
|
||||
Together with https://codereview.qt-project.org/#/c/212972/ fixes highlighting
|
||||
|
||||
##### 030_D38615_Only-mark-CXCursors-for-explicit-attributes-with-a-type.patch
|
||||
|
||||
* <https://reviews.llvm.org/D38615>
|
||||
|
||||
[libclang] Only mark CXCursors for explicit attributes with a type
|
||||
Some classes have totally broken highlighting (like classes inside texteditor.cpp)
|
||||
|
||||
##### 170_D40013_DeclPrinter-Allow-printing-fully-qualified-name.patch
|
||||
##### 180_D39903_libclang-Allow-pretty-printing-declarations.patch
|
||||
|
||||
* <https://reviews.llvm.org/D40013>
|
||||
* <https://reviews.llvm.org/D39903>
|
||||
|
||||
[DeclPrinter] Allow printing fully qualified name of function declaration
|
||||
[libclang] Allow pretty printing declarations
|
||||
|
||||
Improves pretty printing for tooltips.
|
||||
|
||||
Additional changes
|
||||
------------------
|
||||
|
||||
##### QTCREATORBUG-15449_Fix-files-lock-on-Windows.patch
|
||||
##### 160_QTCREATORBUG-15449_Fix-files-lock-on-Windows.patch
|
||||
|
||||
* <https://reviews.llvm.org/D35200>
|
||||
* <https://bugreports.qt.io/browse/QTCREATORBUG-15449>
|
||||
|
||||
Significantly reduces problems when saving a header file on Windows.
|
||||
|
||||
##### QTCREATORBUG-15157_Link-with-clazy.patch
|
||||
##### 150_QTCREATORBUG-15157_Link-with-clazy_llvm.patch
|
||||
##### 130_QTCREATORBUG-15157_Link-with-clazy_clang.patch
|
||||
##### 140_QTCREATORBUG-15157_Link-with-clazy_extra.patch
|
||||
|
||||
* <https://bugreports.qt.io/browse/QTCREATORBUG-15157>
|
||||
|
||||
Introduces the flag CLANG_ENABLE_CLAZY to link libclang with Clazy and forces
|
||||
link for Clazy checks and plugin registry entry.
|
||||
Builds Clazy as an LLVM part and forces link for Clazy plugin registry entry.
|
||||
|
||||
|
@@ -1,88 +0,0 @@
|
||||
diff --git a/tools/clang/lib/AST/ExprConstant.cpp b/tools/clang/lib/AST/ExprConstant.cpp
|
||||
index a26b608082..effd72c764 100644
|
||||
--- a/tools/clang/lib/AST/ExprConstant.cpp
|
||||
+++ b/tools/clang/lib/AST/ExprConstant.cpp
|
||||
@@ -537,7 +537,11 @@ namespace {
|
||||
/// rules. For example, the RHS of (0 && foo()) is not evaluated. We can
|
||||
/// evaluate the expression regardless of what the RHS is, but C only allows
|
||||
/// certain things in certain situations.
|
||||
+#ifndef _WIN32
|
||||
struct LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) EvalInfo {
|
||||
+#else
|
||||
+ struct EvalInfo {
|
||||
+#endif
|
||||
ASTContext &Ctx;
|
||||
|
||||
/// EvalStatus - Contains information about the evaluation.
|
||||
@@ -575,7 +579,21 @@ namespace {
|
||||
|
||||
/// The current array initialization index, if we're performing array
|
||||
/// initialization.
|
||||
+#ifndef _WIN32
|
||||
uint64_t ArrayInitIndex = -1;
|
||||
+#else
|
||||
+ /// uint64_t value is split into two uint32_t values as a workaround
|
||||
+ /// to deal with mingw 32-bit miscompilation
|
||||
+ uint32_t ArrayInitIndex[2] = {static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
|
||||
+ uint64_t GetArrayInitIndex() {
|
||||
+ return (static_cast<uint64_t>(ArrayInitIndex[0]) << 32)
|
||||
+ + static_cast<uint64_t>(ArrayInitIndex[1]);
|
||||
+ }
|
||||
+ void SetArrayInitIndex(uint64_t index) {
|
||||
+ ArrayInitIndex[0] = static_cast<uint32_t>(index >> 32);
|
||||
+ ArrayInitIndex[1] = static_cast<uint32_t>(index);
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
/// HasActiveDiagnostic - Was the previous diagnostic stored? If so, further
|
||||
/// notes attached to it will also be stored, otherwise they will not be.
|
||||
@@ -922,6 +940,7 @@ namespace {
|
||||
uint64_t OuterIndex;
|
||||
|
||||
public:
|
||||
+#ifndef _WIN32
|
||||
ArrayInitLoopIndex(EvalInfo &Info)
|
||||
: Info(Info), OuterIndex(Info.ArrayInitIndex) {
|
||||
Info.ArrayInitIndex = 0;
|
||||
@@ -929,6 +948,19 @@ namespace {
|
||||
~ArrayInitLoopIndex() { Info.ArrayInitIndex = OuterIndex; }
|
||||
|
||||
operator uint64_t&() { return Info.ArrayInitIndex; }
|
||||
+#else
|
||||
+ ArrayInitLoopIndex(EvalInfo &Info)
|
||||
+ : Info(Info), OuterIndex(Info.GetArrayInitIndex()) {
|
||||
+ Info.SetArrayInitIndex(0);
|
||||
+ }
|
||||
+ ~ArrayInitLoopIndex() { Info.SetArrayInitIndex(OuterIndex); }
|
||||
+
|
||||
+ operator uint64_t() { return Info.GetArrayInitIndex(); }
|
||||
+ ArrayInitLoopIndex& operator++() {
|
||||
+ Info.SetArrayInitIndex(Info.GetArrayInitIndex() + 1);
|
||||
+ return *this;
|
||||
+ }
|
||||
+#endif
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6973,13 +7005,21 @@ public:
|
||||
}
|
||||
|
||||
bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
|
||||
+#ifndef _WIN32
|
||||
if (Info.ArrayInitIndex == uint64_t(-1)) {
|
||||
+#else
|
||||
+ if (Info.GetArrayInitIndex() == uint64_t(-1)) {
|
||||
+#endif
|
||||
// We were asked to evaluate this subexpression independent of the
|
||||
// enclosing ArrayInitLoopExpr. We can't do that.
|
||||
Info.FFDiag(E);
|
||||
return false;
|
||||
}
|
||||
+#ifndef _WIN32
|
||||
return Success(Info.ArrayInitIndex, E);
|
||||
+#else
|
||||
+ return Success(Info.GetArrayInitIndex(), E);
|
||||
+#endif
|
||||
}
|
||||
|
||||
// Note, GNU defines __null as an integer, not a pointer.
|
@@ -1,10 +1,11 @@
|
||||
import qbs 1.0
|
||||
import qbs.FileInfo
|
||||
import QtcFunctions
|
||||
|
||||
QtcProduct {
|
||||
type: ["dynamiclibrary", "dynamiclibrary_symlink", "qtc.dev-module"]
|
||||
installDir: qtc.ide_library_path
|
||||
installTags: ["dynamiclibrary", "dynamiclibrary_symlink"]
|
||||
installTags: ["dynamiclibrary", "dynamiclibrary_symlink", "debuginfo_dll"]
|
||||
useNonGuiPchFile: true
|
||||
Depends {
|
||||
condition: qtc.testsEnabled
|
||||
@@ -12,7 +13,7 @@ QtcProduct {
|
||||
}
|
||||
|
||||
targetName: QtcFunctions.qtLibraryName(qbs, name)
|
||||
destinationDirectory: qtc.ide_library_path
|
||||
destinationDirectory: FileInfo.joinPaths(buildDirectory, qtc.ide_library_path)
|
||||
|
||||
cpp.linkerFlags: {
|
||||
var flags = base;
|
||||
|
@@ -5,7 +5,7 @@ import QtcFunctions
|
||||
QtcProduct {
|
||||
type: ["dynamiclibrary", "pluginSpec", "qtc.dev-module"]
|
||||
installDir: qtc.ide_plugin_path
|
||||
installTags: ["dynamiclibrary"]
|
||||
installTags: ["dynamiclibrary", "debuginfo_dll"]
|
||||
useGuiPchFile: true
|
||||
|
||||
property var pluginJsonReplacements
|
||||
@@ -13,7 +13,7 @@ QtcProduct {
|
||||
property var pluginTestDepends: []
|
||||
|
||||
targetName: QtcFunctions.qtLibraryName(qbs, name)
|
||||
destinationDirectory: qtc.ide_plugin_path
|
||||
destinationDirectory: FileInfo.joinPaths(buildDirectory, qtc.ide_plugin_path)
|
||||
|
||||
Depends { name: "ExtensionSystem" }
|
||||
Depends { name: "pluginjson" }
|
||||
|
@@ -8,7 +8,7 @@ Product {
|
||||
version: qtc.qtcreator_version
|
||||
property bool install: true
|
||||
property string installDir
|
||||
property string installSourceBase
|
||||
property string installSourceBase: destinationDirectory
|
||||
property stringList installTags: type
|
||||
property string fileName: FileInfo.fileName(sourceDirectory) + ".qbs"
|
||||
property bool useNonGuiPchFile: false
|
||||
|
@@ -5,6 +5,7 @@ QtcProduct {
|
||||
type: ["application"]
|
||||
consoleApplication: true
|
||||
installDir: qtc.ide_libexec_path
|
||||
installTags: base.concat(["debuginfo_app"])
|
||||
useNonGuiPchFile: true
|
||||
|
||||
cpp.rpaths: {
|
||||
|
@@ -22,8 +22,7 @@ QtcProduct {
|
||||
|
||||
property bool isBundle: qbs.targetOS.contains("darwin") && bundle.isBundle
|
||||
installDir: isBundle ? qtc.ide_app_path : qtc.ide_bin_path
|
||||
installTags: isBundle ? ["bundle.content"] : base
|
||||
installSourceBase: isBundle ? buildDirectory : base
|
||||
installTags: (isBundle ? ["bundle.content"] : base).concat(["debuginfo_app"])
|
||||
property bool qtcRunnable: true
|
||||
|
||||
bundle.identifier: qtc.ide_bundle_identifier
|
||||
|
89030
src/libs/3rdparty/sqlite/sqlite3.c
vendored
89030
src/libs/3rdparty/sqlite/sqlite3.c
vendored
File diff suppressed because it is too large
Load Diff
3808
src/libs/3rdparty/sqlite/sqlite3.h
vendored
3808
src/libs/3rdparty/sqlite/sqlite3.h
vendored
File diff suppressed because it is too large
Load Diff
85
src/libs/3rdparty/sqlite/sqlite3ext.h
vendored
85
src/libs/3rdparty/sqlite/sqlite3ext.h
vendored
@@ -15,12 +15,10 @@
|
||||
** as extensions by SQLite should #include this file instead of
|
||||
** sqlite3.h.
|
||||
*/
|
||||
#ifndef _SQLITE3EXT_H_
|
||||
#define _SQLITE3EXT_H_
|
||||
#ifndef SQLITE3EXT_H
|
||||
#define SQLITE3EXT_H
|
||||
#include "sqlite3.h"
|
||||
|
||||
typedef struct sqlite3_api_routines sqlite3_api_routines;
|
||||
|
||||
/*
|
||||
** The following structure holds pointers to all of the SQLite API
|
||||
** routines.
|
||||
@@ -136,7 +134,7 @@ struct sqlite3_api_routines {
|
||||
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
|
||||
const char*,const char*),void*);
|
||||
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
|
||||
char * (*snprintf)(int,char*,const char*,...);
|
||||
char * (*xsnprintf)(int,char*,const char*,...);
|
||||
int (*step)(sqlite3_stmt*);
|
||||
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
|
||||
char const**,char const**,int*,int*,int*);
|
||||
@@ -248,7 +246,7 @@ struct sqlite3_api_routines {
|
||||
int (*uri_boolean)(const char*,const char*,int);
|
||||
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
|
||||
const char *(*uri_parameter)(const char*,const char*);
|
||||
char *(*vsnprintf)(int,char*,const char*,va_list);
|
||||
char *(*xvsnprintf)(int,char*,const char*,va_list);
|
||||
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
|
||||
/* Version 3.8.7 and later */
|
||||
int (*auto_extension)(void(*)(void));
|
||||
@@ -267,8 +265,45 @@ struct sqlite3_api_routines {
|
||||
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
|
||||
void(*)(void*), unsigned char);
|
||||
int (*strglob)(const char*,const char*);
|
||||
/* Version 3.8.11 and later */
|
||||
sqlite3_value *(*value_dup)(const sqlite3_value*);
|
||||
void (*value_free)(sqlite3_value*);
|
||||
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
|
||||
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
|
||||
/* Version 3.9.0 and later */
|
||||
unsigned int (*value_subtype)(sqlite3_value*);
|
||||
void (*result_subtype)(sqlite3_context*,unsigned int);
|
||||
/* Version 3.10.0 and later */
|
||||
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
|
||||
int (*strlike)(const char*,const char*,unsigned int);
|
||||
int (*db_cacheflush)(sqlite3*);
|
||||
/* Version 3.12.0 and later */
|
||||
int (*system_errno)(sqlite3*);
|
||||
/* Version 3.14.0 and later */
|
||||
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
|
||||
char *(*expanded_sql)(sqlite3_stmt*);
|
||||
/* Version 3.18.0 and later */
|
||||
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
|
||||
/* Version 3.20.0 and later */
|
||||
int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
|
||||
sqlite3_stmt**,const char**);
|
||||
int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
|
||||
sqlite3_stmt**,const void**);
|
||||
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
|
||||
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
|
||||
void *(*value_pointer)(sqlite3_value*,const char*);
|
||||
};
|
||||
|
||||
/*
|
||||
** This is the function signature used for all extension entry points. It
|
||||
** is also defined in the file "loadext.c".
|
||||
*/
|
||||
typedef int (*sqlite3_loadext_entry)(
|
||||
sqlite3 *db, /* Handle to the database. */
|
||||
char **pzErrMsg, /* Used to set error string on failure. */
|
||||
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
|
||||
);
|
||||
|
||||
/*
|
||||
** The following macros redefine the API routines so that they are
|
||||
** redirected through the global sqlite3_api structure.
|
||||
@@ -280,7 +315,7 @@ struct sqlite3_api_routines {
|
||||
** the API. So the redefinition macros are only valid if the
|
||||
** SQLITE_CORE macros is undefined.
|
||||
*/
|
||||
#ifndef SQLITE_CORE
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
|
||||
@@ -383,7 +418,7 @@ struct sqlite3_api_routines {
|
||||
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
|
||||
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
|
||||
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
|
||||
#define sqlite3_snprintf sqlite3_api->snprintf
|
||||
#define sqlite3_snprintf sqlite3_api->xsnprintf
|
||||
#define sqlite3_step sqlite3_api->step
|
||||
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
|
||||
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
|
||||
@@ -407,6 +442,7 @@ struct sqlite3_api_routines {
|
||||
#define sqlite3_value_text16le sqlite3_api->value_text16le
|
||||
#define sqlite3_value_type sqlite3_api->value_type
|
||||
#define sqlite3_vmprintf sqlite3_api->vmprintf
|
||||
#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
|
||||
#define sqlite3_overload_function sqlite3_api->overload_function
|
||||
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
|
||||
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
|
||||
@@ -482,7 +518,7 @@ struct sqlite3_api_routines {
|
||||
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
|
||||
#define sqlite3_uri_int64 sqlite3_api->uri_int64
|
||||
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
|
||||
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
|
||||
#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
|
||||
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
|
||||
/* Version 3.8.7 and later */
|
||||
#define sqlite3_auto_extension sqlite3_api->auto_extension
|
||||
@@ -497,9 +533,34 @@ struct sqlite3_api_routines {
|
||||
#define sqlite3_result_blob64 sqlite3_api->result_blob64
|
||||
#define sqlite3_result_text64 sqlite3_api->result_text64
|
||||
#define sqlite3_strglob sqlite3_api->strglob
|
||||
#endif /* SQLITE_CORE */
|
||||
/* Version 3.8.11 and later */
|
||||
#define sqlite3_value_dup sqlite3_api->value_dup
|
||||
#define sqlite3_value_free sqlite3_api->value_free
|
||||
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
|
||||
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
|
||||
/* Version 3.9.0 and later */
|
||||
#define sqlite3_value_subtype sqlite3_api->value_subtype
|
||||
#define sqlite3_result_subtype sqlite3_api->result_subtype
|
||||
/* Version 3.10.0 and later */
|
||||
#define sqlite3_status64 sqlite3_api->status64
|
||||
#define sqlite3_strlike sqlite3_api->strlike
|
||||
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
|
||||
/* Version 3.12.0 and later */
|
||||
#define sqlite3_system_errno sqlite3_api->system_errno
|
||||
/* Version 3.14.0 and later */
|
||||
#define sqlite3_trace_v2 sqlite3_api->trace_v2
|
||||
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
|
||||
/* Version 3.18.0 and later */
|
||||
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
|
||||
/* Version 3.20.0 and later */
|
||||
#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
|
||||
#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
|
||||
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
|
||||
#define sqlite3_result_pointer sqlite3_api->result_pointer
|
||||
#define sqlite3_value_pointer sqlite3_api->value_pointer
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#ifndef SQLITE_CORE
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
/* This case when the file really is being compiled as a loadable
|
||||
** extension */
|
||||
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
|
||||
@@ -514,4 +575,4 @@ struct sqlite3_api_routines {
|
||||
# define SQLITE_EXTENSION_INIT3 /*no-op*/
|
||||
#endif
|
||||
|
||||
#endif /* _SQLITE3EXT_H_ */
|
||||
#endif /* SQLITE3EXT_H */
|
||||
|
@@ -458,7 +458,7 @@ unittest_public:
|
||||
private:
|
||||
IdCache m_idCache;
|
||||
WatcherEntries m_watchedEntries;
|
||||
ChangedFilePathCompressor<Timer> m_changedFilePathCompressor{};
|
||||
ChangedFilePathCompressor<Timer> m_changedFilePathCompressor;
|
||||
FileSystemWatcher m_fileSystemWatcher;
|
||||
FilePathCachingInterface &m_pathCache;
|
||||
ClangPathWatcherNotifier *m_notifier;
|
||||
|
@@ -31,10 +31,6 @@
|
||||
|
||||
#include <utils/smallstringfwd.h>
|
||||
|
||||
#ifdef UNIT_TESTS
|
||||
#include <gtest/gtest.h>
|
||||
#endif
|
||||
|
||||
#if defined(CLANGSUPPORT_BUILD_LIB)
|
||||
# define CLANGSUPPORT_EXPORT Q_DECL_EXPORT
|
||||
#elif defined(CLANGSUPPORT_BUILD_STATIC_LIB)
|
||||
|
@@ -45,6 +45,7 @@ public:
|
||||
createLocationsTable();
|
||||
createSourcesTable();
|
||||
createDirectoriesTable();
|
||||
createProjectPartsTable();
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
@@ -102,6 +103,19 @@ public:
|
||||
table.initialize(database);
|
||||
}
|
||||
|
||||
void createProjectPartsTable()
|
||||
{
|
||||
Sqlite::Table table;
|
||||
table.setUseIfNotExists(true);
|
||||
table.setName("projectParts");
|
||||
table.addColumn("projectPartId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
|
||||
const Sqlite::Column &projectPartNameColumn = table.addColumn("projectPartName", Sqlite::ColumnType::Text);
|
||||
table.addColumn("compilerArguments", Sqlite::ColumnType::Text);
|
||||
table.addIndex({projectPartNameColumn});
|
||||
|
||||
table.initialize(database);
|
||||
}
|
||||
|
||||
public:
|
||||
DatabaseType &database;
|
||||
};
|
||||
|
@@ -46,6 +46,7 @@ HEADERS += \
|
||||
$$PWD/sqliteindex.h \
|
||||
$$PWD/sqlitebasestatement.h
|
||||
|
||||
DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA
|
||||
DEFINES += SQLITE_THREADSAFE=2 SQLITE_ENABLE_FTS4 SQLITE_ENABLE_FTS3_PARENTHESIS \
|
||||
SQLITE_ENABLE_UNLOCK_NOTIFY SQLITE_ENABLE_COLUMN_METADATA SQLITE_ENABLE_JSON1
|
||||
|
||||
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
|
||||
|
@@ -10,7 +10,8 @@ QtcLibrary {
|
||||
"SQLITE_ENABLE_FTS4",
|
||||
"SQLITE_ENABLE_FTS3_PARENTHESIS",
|
||||
"SQLITE_ENABLE_UNLOCK_NOTIFY",
|
||||
"SQLITE_ENABLE_COLUMN_METADATA"
|
||||
"SQLITE_ENABLE_COLUMN_METADATA",
|
||||
"SQLITE_ENABLE_JSON1"
|
||||
])
|
||||
cpp.optimization: "fast"
|
||||
cpp.dynamicLibraries: base.concat((qbs.targetOS.contains("unix") && !qbs.targetOS.contains("bsd"))
|
||||
|
@@ -82,6 +82,11 @@ public:
|
||||
return m_databaseBackend.lastInsertedRowId();
|
||||
}
|
||||
|
||||
void setLastInsertedRowId(int64_t rowId)
|
||||
{
|
||||
m_databaseBackend.setLastInsertedRowId(rowId);
|
||||
}
|
||||
|
||||
int changesCount()
|
||||
{
|
||||
return m_databaseBackend.changesCount();
|
||||
|
@@ -172,6 +172,11 @@ int64_t DatabaseBackend::lastInsertedRowId() const
|
||||
return sqlite3_last_insert_rowid(sqliteDatabaseHandle());
|
||||
}
|
||||
|
||||
void DatabaseBackend::setLastInsertedRowId(int64_t rowId)
|
||||
{
|
||||
sqlite3_set_last_insert_rowid(sqliteDatabaseHandle(), rowId);
|
||||
}
|
||||
|
||||
void DatabaseBackend::execute(Utils::SmallStringView sqlStatement)
|
||||
{
|
||||
ReadWriteStatement statement(sqlStatement, m_database);
|
||||
|
@@ -72,6 +72,7 @@ public:
|
||||
int totalChangesCount() const;
|
||||
|
||||
int64_t lastInsertedRowId() const;
|
||||
void setLastInsertedRowId(int64_t rowId);
|
||||
|
||||
void execute(Utils::SmallStringView sqlStatement);
|
||||
|
||||
|
@@ -39,11 +39,6 @@ QDebug operator<<(QDebug debug, const Utf8String &text)
|
||||
return debug;
|
||||
}
|
||||
|
||||
void PrintTo(const Utf8String &text, ::std::ostream* os)
|
||||
{
|
||||
*os << "\"" << text.toByteArray().data() << "\"";
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &os, const Utf8String &utf8String)
|
||||
{
|
||||
using std::ostream;
|
||||
|
@@ -267,7 +267,6 @@ private:
|
||||
};
|
||||
|
||||
SQLITE_EXPORT QDebug operator<<(QDebug debug, const Utf8String &text);
|
||||
SQLITE_EXPORT void PrintTo(const Utf8String &text, ::std::ostream* os);
|
||||
SQLITE_EXPORT std::ostream& operator<<(std::ostream &os, const Utf8String &utf8String);
|
||||
|
||||
#define Utf8StringLiteral(str) Utf8String::fromByteArray(QByteArrayLiteral(str))
|
||||
|
@@ -381,7 +381,7 @@ TimelineRenderPass::State *TimelineItemsRenderPass::update(const TimelineAbstrac
|
||||
const TimelineRenderState *parentState,
|
||||
State *oldState, int indexFrom,
|
||||
int indexTo, bool stateChanged,
|
||||
qreal spacing) const
|
||||
float spacing) const
|
||||
{
|
||||
Q_UNUSED(stateChanged);
|
||||
const TimelineModel *model = renderer->model();
|
||||
@@ -416,8 +416,8 @@ TimelineRenderPass::State *TimelineItemsRenderPass::update(const TimelineAbstrac
|
||||
state->expandedRow(row));
|
||||
rowNode->material.setScale(
|
||||
QVector2D(spacing / parentState->scale(),
|
||||
static_cast<qreal>(model->expandedRowHeight(row))) /
|
||||
static_cast<qreal>(TimelineModel::defaultRowHeight()));
|
||||
static_cast<float>(model->expandedRowHeight(row))) /
|
||||
static_cast<float>(TimelineModel::defaultRowHeight()));
|
||||
rowNode->material.setSelectedItem(selectedItem);
|
||||
rowNode->material.setSelectionColor(selectionColor);
|
||||
}
|
||||
|
@@ -95,7 +95,7 @@ public:
|
||||
static const TimelineItemsRenderPass *instance();
|
||||
State *update(const TimelineAbstractRenderer *renderer, const TimelineRenderState *parentState,
|
||||
State *state, int firstIndex, int lastIndex, bool stateChanged,
|
||||
qreal spacing) const;
|
||||
float spacing) const;
|
||||
protected:
|
||||
TimelineItemsRenderPass();
|
||||
};
|
||||
|
@@ -415,13 +415,13 @@ float TimelineModel::relativeHeight(int index) const
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
int TimelineModel::rowMinValue(int rowNumber) const
|
||||
qint64 TimelineModel::rowMinValue(int rowNumber) const
|
||||
{
|
||||
Q_UNUSED(rowNumber);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TimelineModel::rowMaxValue(int rowNumber) const
|
||||
qint64 TimelineModel::rowMaxValue(int rowNumber) const
|
||||
{
|
||||
Q_UNUSED(rowNumber);
|
||||
return 0;
|
||||
|
@@ -102,8 +102,8 @@ public:
|
||||
Q_INVOKABLE virtual int typeId(int index) const;
|
||||
Q_INVOKABLE virtual bool handlesTypeId(int typeId) const;
|
||||
Q_INVOKABLE virtual float relativeHeight(int index) const;
|
||||
Q_INVOKABLE virtual int rowMinValue(int rowNumber) const;
|
||||
Q_INVOKABLE virtual int rowMaxValue(int rowNumber) const;
|
||||
Q_INVOKABLE virtual qint64 rowMinValue(int rowNumber) const;
|
||||
Q_INVOKABLE virtual qint64 rowMaxValue(int rowNumber) const;
|
||||
|
||||
Q_INVOKABLE int nextItemBySelectionId(int selectionId, qint64 time, int currentItem) const;
|
||||
Q_INVOKABLE int nextItemByTypeId(int typeId, qint64 time, int currentItem) const;
|
||||
|
@@ -104,7 +104,7 @@ TimelineRenderPass::State *TimelineNotesRenderPass::update(const TimelineAbstrac
|
||||
const TimelineRenderState *parentState,
|
||||
State *oldState, int firstIndex,
|
||||
int lastIndex, bool stateChanged,
|
||||
qreal spacing) const
|
||||
float spacing) const
|
||||
{
|
||||
Q_UNUSED(firstIndex);
|
||||
Q_UNUSED(lastIndex);
|
||||
|
@@ -37,7 +37,7 @@ public:
|
||||
|
||||
State *update(const TimelineAbstractRenderer *renderer, const TimelineRenderState *parentState,
|
||||
State *oldState, int firstIndex, int lastIndex, bool stateChanged,
|
||||
qreal spacing) const;
|
||||
float spacing) const;
|
||||
|
||||
private:
|
||||
TimelineNotesRenderPass();
|
||||
|
@@ -63,8 +63,9 @@ QSGNode *TimelineOverviewRenderer::updatePaintNode(QSGNode *oldNode,
|
||||
1.0, d->renderPasses.size());
|
||||
}
|
||||
|
||||
qreal xSpacing = width() / d->zoomer->traceDuration();
|
||||
qreal ySpacing = height() / (d->model->collapsedRowCount() * TimelineModel::defaultRowHeight());
|
||||
float xSpacing = static_cast<float>(width() / d->zoomer->traceDuration());
|
||||
float ySpacing = static_cast<float>(
|
||||
height() / (d->model->collapsedRowCount() * TimelineModel::defaultRowHeight()));
|
||||
|
||||
for (int i = 0; i < d->renderPasses.length(); ++i) {
|
||||
d->renderState->setPassState(i, d->renderPasses[i]->update(this, d->renderState,
|
||||
|
@@ -120,7 +120,7 @@ QSGNode *TimelineRenderer::updatePaintNode(QSGNode *node, UpdatePaintNodeData *u
|
||||
return 0;
|
||||
}
|
||||
|
||||
qreal spacing = width() / d->zoomer->windowDuration();
|
||||
float spacing = static_cast<float>(width() / d->zoomer->windowDuration());
|
||||
|
||||
if (d->modelDirty) {
|
||||
if (node)
|
||||
|
@@ -49,7 +49,7 @@ public:
|
||||
virtual State *update(const TimelineAbstractRenderer *renderer,
|
||||
const TimelineRenderState *parentState,
|
||||
State *state, int indexFrom, int indexTo, bool stateChanged,
|
||||
qreal spacing) const = 0;
|
||||
float spacing) const = 0;
|
||||
};
|
||||
|
||||
} // namespace Timeline
|
||||
|
@@ -28,7 +28,7 @@
|
||||
|
||||
namespace Timeline {
|
||||
|
||||
TimelineRenderState::TimelineRenderState(qint64 start, qint64 end, qreal scale, int numPasses) :
|
||||
TimelineRenderState::TimelineRenderState(qint64 start, qint64 end, float scale, int numPasses) :
|
||||
d_ptr(new TimelineRenderStatePrivate)
|
||||
{
|
||||
Q_D(TimelineRenderState);
|
||||
@@ -70,7 +70,7 @@ qint64 TimelineRenderState::end() const
|
||||
return d->end;
|
||||
}
|
||||
|
||||
qreal TimelineRenderState::scale() const
|
||||
float TimelineRenderState::scale() const
|
||||
{
|
||||
Q_D(const TimelineRenderState);
|
||||
return d->scale;
|
||||
|
@@ -33,12 +33,12 @@ namespace Timeline {
|
||||
|
||||
class TIMELINE_EXPORT TimelineRenderState {
|
||||
public:
|
||||
TimelineRenderState(qint64 start, qint64 end, qreal scale, int numPasses);
|
||||
TimelineRenderState(qint64 start, qint64 end, float scale, int numPasses);
|
||||
~TimelineRenderState();
|
||||
|
||||
qint64 start() const;
|
||||
qint64 end() const;
|
||||
qreal scale() const;
|
||||
float scale() const;
|
||||
|
||||
TimelineRenderPass::State *passState(int i);
|
||||
const TimelineRenderPass::State *passState(int i) const;
|
||||
|
@@ -39,7 +39,7 @@ public:
|
||||
qint64 start;
|
||||
qint64 end;
|
||||
|
||||
qreal scale; // "native" scale, this stays the same through the life time of a state
|
||||
float scale; // "native" scale, this stays the same through the life time of a state
|
||||
|
||||
QVector<TimelineRenderPass::State *> passes;
|
||||
};
|
||||
|
@@ -64,7 +64,7 @@ private:
|
||||
|
||||
TimelineRenderPass::State *TimelineSelectionRenderPass::update(
|
||||
const TimelineAbstractRenderer *renderer, const TimelineRenderState *parentState,
|
||||
State *oldState, int firstIndex, int lastIndex, bool stateChanged, qreal spacing) const
|
||||
State *oldState, int firstIndex, int lastIndex, bool stateChanged, float spacing) const
|
||||
{
|
||||
Q_UNUSED(stateChanged);
|
||||
|
||||
|
@@ -38,7 +38,7 @@ public:
|
||||
|
||||
State *update(const TimelineAbstractRenderer *renderer, const TimelineRenderState *parentState,
|
||||
State *state, int firstIndex, int lastIndex, bool stateChanged,
|
||||
qreal spacing) const;
|
||||
float spacing) const;
|
||||
|
||||
protected:
|
||||
TimelineSelectionRenderPass();
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "settingsaccessor.h"
|
||||
|
||||
#include "asconst.h"
|
||||
#include "qtcassert.h"
|
||||
|
||||
#include <QApplication>
|
||||
@@ -150,99 +151,158 @@ void trackUserStickySettings(QVariantMap &userMap, const QVariantMap &sharedMap)
|
||||
|
||||
namespace Utils {
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// BasicSettingsAccessor::Issue:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
QMessageBox::StandardButtons BasicSettingsAccessor::Issue::allButtons() const
|
||||
{
|
||||
QMessageBox::StandardButtons result = QMessageBox::NoButton;
|
||||
for (const QMessageBox::StandardButton &b : buttons.keys())
|
||||
result |= b;
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// BasicSettingsAccessor:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BasicSettingsAccessor::BasicSettingsAccessor(const FileName &baseFilePath, const QString &docType) :
|
||||
m_baseFilePath(baseFilePath),
|
||||
m_docType(docType)
|
||||
/*!
|
||||
* The BasicSettingsAccessor can be used to read/write settings in XML format.
|
||||
*/
|
||||
BasicSettingsAccessor::BasicSettingsAccessor(const QString &docType,
|
||||
const QString &displayName,
|
||||
const QString &applicationDisplayName) :
|
||||
docType(docType),
|
||||
displayName(displayName),
|
||||
applicationDisplayName(applicationDisplayName)
|
||||
{
|
||||
QTC_CHECK(!m_baseFilePath.isEmpty());
|
||||
QTC_CHECK(!m_docType.isEmpty());
|
||||
}
|
||||
|
||||
BasicSettingsAccessor::~BasicSettingsAccessor() = default;
|
||||
|
||||
QVariantMap BasicSettingsAccessor::restoreSettings(QWidget *parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return readFile(m_baseFilePath);
|
||||
}
|
||||
|
||||
bool BasicSettingsAccessor::saveSettings(const QVariantMap &data, QWidget *parent) const
|
||||
{
|
||||
return writeFile(m_baseFilePath, data, parent);
|
||||
}
|
||||
|
||||
QVariantMap BasicSettingsAccessor::readFile(const FileName &path) const
|
||||
{
|
||||
PersistentSettingsReader reader;
|
||||
if (!reader.load(path))
|
||||
return QVariantMap();
|
||||
|
||||
return reader.restoreValues();
|
||||
}
|
||||
|
||||
bool BasicSettingsAccessor::writeFile(const FileName &path, const QVariantMap &data, QWidget *parent) const
|
||||
{
|
||||
if (data.isEmpty())
|
||||
return false;
|
||||
|
||||
if (!m_writer || m_writer->fileName() != path)
|
||||
m_writer = std::make_unique<PersistentSettingsWriter>(path, m_docType);
|
||||
|
||||
return m_writer->save(data, parent);
|
||||
}
|
||||
|
||||
FileName BasicSettingsAccessor::baseFilePath() const
|
||||
{
|
||||
return m_baseFilePath;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// VersionUpgrader:
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
VersionUpgrader::VersionUpgrader(const int version, const QString &extension) :
|
||||
m_version(version), m_extension(extension)
|
||||
{ }
|
||||
|
||||
int VersionUpgrader::version() const
|
||||
{
|
||||
QTC_CHECK(m_version >= 0);
|
||||
return m_version;
|
||||
}
|
||||
|
||||
QString VersionUpgrader::backupExtension() const
|
||||
{
|
||||
QTC_CHECK(!m_extension.isEmpty());
|
||||
return m_extension;
|
||||
QTC_CHECK(!docType.isEmpty());
|
||||
QTC_CHECK(!displayName.isEmpty());
|
||||
QTC_CHECK(!applicationDisplayName.isEmpty());
|
||||
}
|
||||
|
||||
/*!
|
||||
* Performs a simple renaming of the listed keys in \a changes recursively on \a map.
|
||||
* Restore settings from disk and report any issues in a message box centered on \a parent.
|
||||
*/
|
||||
QVariantMap VersionUpgrader::renameKeys(const QList<Change> &changes, QVariantMap map) const
|
||||
QVariantMap BasicSettingsAccessor::restoreSettings(QWidget *parent) const
|
||||
{
|
||||
foreach (const Change &change, changes) {
|
||||
QVariantMap::iterator oldSetting = map.find(change.first);
|
||||
if (oldSetting != map.end()) {
|
||||
map.insert(change.second, oldSetting.value());
|
||||
map.erase(oldSetting);
|
||||
}
|
||||
QTC_ASSERT(!m_baseFilePath.isEmpty(), return QVariantMap());
|
||||
|
||||
const RestoreData result = readData(m_baseFilePath, parent);
|
||||
const ProceedInfo pi = result.issue ? reportIssues(result.issue.value(), result.path, parent) : ProceedInfo::Continue;
|
||||
return pi == ProceedInfo::DiscardAndContinue ? QVariantMap() : result.data;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Save \a data to disk and report any issues in a message box centered on \a parent.
|
||||
*/
|
||||
bool BasicSettingsAccessor::saveSettings(const QVariantMap &data, QWidget *parent) const
|
||||
{
|
||||
const optional<Issue> result = writeData(m_baseFilePath, data);
|
||||
const ProceedInfo pi = result ? reportIssues(result.value(), m_baseFilePath, parent) : ProceedInfo::Continue;
|
||||
return pi == ProceedInfo::Continue;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Read data from \a path. Do all the necessary postprocessing of the data.
|
||||
*/
|
||||
BasicSettingsAccessor::RestoreData BasicSettingsAccessor::readData(const FileName &path,
|
||||
QWidget *parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
RestoreData result = readFile(path);
|
||||
if (!result.data.isEmpty())
|
||||
result.data = preprocessReadSettings(result.data);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Store the \a data in \a path on disk. Do all the necessary preprocessing of the data.
|
||||
*/
|
||||
Utils::optional<BasicSettingsAccessor::Issue>
|
||||
BasicSettingsAccessor::writeData(const FileName &path, const QVariantMap &data) const
|
||||
{
|
||||
return writeFile(path, prepareToWriteSettings(data));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Read a file at \a path from disk and extract the data into a RestoreData set.
|
||||
*
|
||||
* This method does not do *any* processing of the file contents.
|
||||
*/
|
||||
BasicSettingsAccessor::RestoreData BasicSettingsAccessor::readFile(const FileName &path) const
|
||||
{
|
||||
PersistentSettingsReader reader;
|
||||
if (!reader.load(path)) {
|
||||
return RestoreData(Issue(QCoreApplication::translate("Utils::SettingsAccessor", "Failed to Read File"),
|
||||
QCoreApplication::translate("Utils::SettingsAccessor", "Could not open \"%1\".")
|
||||
.arg(path.toUserOutput())));
|
||||
}
|
||||
|
||||
QVariantMap::iterator i = map.begin();
|
||||
while (i != map.end()) {
|
||||
QVariant v = i.value();
|
||||
if (v.type() == QVariant::Map)
|
||||
i.value() = renameKeys(changes, v.toMap());
|
||||
return RestoreData(path, reader.restoreValues());
|
||||
}
|
||||
|
||||
++i;
|
||||
/*!
|
||||
* Write a file at \a path to disk and store the \a data in it.
|
||||
*
|
||||
* This method does not do *any* processing of the file contents.
|
||||
*/
|
||||
Utils::optional<BasicSettingsAccessor::Issue>
|
||||
BasicSettingsAccessor::writeFile(const FileName &path, const QVariantMap &data) const
|
||||
{
|
||||
if (data.isEmpty()) {
|
||||
return Issue(QCoreApplication::translate("Utils::SettingsAccessor", "Failed to Write File"),
|
||||
QCoreApplication::translate("Utils::SettingsAccessor", "There was nothing to write."));
|
||||
}
|
||||
|
||||
return map;
|
||||
QString errorMessage;
|
||||
if (!m_writer || m_writer->fileName() != path)
|
||||
m_writer = std::make_unique<PersistentSettingsWriter>(path, docType);
|
||||
|
||||
if (!m_writer->save(data, &errorMessage)) {
|
||||
return Issue(QCoreApplication::translate("Utils::SettingsAccessor", "Failed to Write File"),
|
||||
errorMessage);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
BasicSettingsAccessor::ProceedInfo
|
||||
BasicSettingsAccessor::reportIssues(const BasicSettingsAccessor::Issue &issue, const FileName &path,
|
||||
QWidget *parent) const
|
||||
{
|
||||
if (!path.exists())
|
||||
return Continue;
|
||||
|
||||
const QMessageBox::Icon icon
|
||||
= issue.buttons.count() > 1 ? QMessageBox::Question : QMessageBox::Information;
|
||||
const QMessageBox::StandardButtons buttons = issue.allButtons();
|
||||
QTC_ASSERT(buttons != QMessageBox::NoButton, return Continue);
|
||||
|
||||
QMessageBox msgBox(icon, issue.title, issue.message, buttons, parent);
|
||||
if (issue.defaultButton != QMessageBox::NoButton)
|
||||
msgBox.setDefaultButton(issue.defaultButton);
|
||||
if (issue.escapeButton != QMessageBox::NoButton)
|
||||
msgBox.setEscapeButton(issue.escapeButton);
|
||||
|
||||
int boxAction = msgBox.exec();
|
||||
return issue.buttons.value(static_cast<QMessageBox::StandardButton>(boxAction));
|
||||
}
|
||||
|
||||
/*!
|
||||
* This method is called right after reading data from disk and modifies \a data.
|
||||
*/
|
||||
QVariantMap BasicSettingsAccessor::preprocessReadSettings(const QVariantMap &data) const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/*!
|
||||
* This method is called right before writing data to disk and modifies \a data.
|
||||
*/
|
||||
QVariantMap BasicSettingsAccessor::prepareToWriteSettings(const QVariantMap &data) const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -271,16 +331,13 @@ public:
|
||||
return m_upgraders[static_cast<size_t>(pos)].get();
|
||||
return nullptr;
|
||||
}
|
||||
Settings bestSettings(const SettingsAccessor *accessor, const FileNameList &pathList);
|
||||
BasicSettingsAccessor::RestoreData bestSettings(const SettingsAccessor *accessor, const FileNameList &pathList, QWidget *parent);
|
||||
|
||||
std::vector<std::unique_ptr<VersionUpgrader>> m_upgraders;
|
||||
std::unique_ptr<PersistentSettingsWriter> m_writer;
|
||||
QByteArray m_settingsId;
|
||||
QString m_displayName;
|
||||
QString m_applicationDisplayName;
|
||||
|
||||
QString m_userSuffix;
|
||||
QString m_sharedSuffix;
|
||||
std::unique_ptr<BasicSettingsAccessor> m_sharedFile;
|
||||
};
|
||||
|
||||
// Return path to shared directory for .user files, create if necessary.
|
||||
@@ -355,16 +412,68 @@ static FileName userFilePath(const Utils::FileName &projectFilePath, const QStri
|
||||
return result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// VersionUpgrader:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
VersionUpgrader::VersionUpgrader(const int version, const QString &extension) :
|
||||
m_version(version), m_extension(extension)
|
||||
{
|
||||
QTC_CHECK(m_version >= 0);
|
||||
}
|
||||
|
||||
int VersionUpgrader::version() const
|
||||
{
|
||||
return m_version;
|
||||
}
|
||||
|
||||
QString VersionUpgrader::backupExtension() const
|
||||
{
|
||||
QTC_CHECK(!m_extension.isEmpty());
|
||||
return m_extension;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Performs a simple renaming of the listed keys in \a changes recursively on \a map.
|
||||
*/
|
||||
QVariantMap VersionUpgrader::renameKeys(const QList<Change> &changes, QVariantMap map) const
|
||||
{
|
||||
foreach (const Change &change, changes) {
|
||||
QVariantMap::iterator oldSetting = map.find(change.first);
|
||||
if (oldSetting != map.end()) {
|
||||
map.insert(change.second, oldSetting.value());
|
||||
map.erase(oldSetting);
|
||||
}
|
||||
}
|
||||
|
||||
QVariantMap::iterator i = map.begin();
|
||||
while (i != map.end()) {
|
||||
QVariant v = i.value();
|
||||
if (v.type() == QVariant::Map)
|
||||
i.value() = renameKeys(changes, v.toMap());
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SettingsAccessor:
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
SettingsAccessor::SettingsAccessor(const Utils::FileName &baseFile, const QString &docType) :
|
||||
BasicSettingsAccessor(baseFile, docType),
|
||||
SettingsAccessor::SettingsAccessor(const Utils::FileName &baseFile, const QString &docType,
|
||||
const QString &displayName, const QString &appDisplayName) :
|
||||
BasicSettingsAccessor(docType, displayName, appDisplayName),
|
||||
d(new SettingsAccessorPrivate)
|
||||
{
|
||||
d->m_userSuffix = generateSuffix(QString::fromLocal8Bit(qgetenv("QTC_EXTENSION")), ".user");
|
||||
d->m_sharedSuffix = generateSuffix(QString::fromLocal8Bit(qgetenv("QTC_SHARED_EXTENSION")), ".shared");
|
||||
Utils::FileName baseFilePath = userFilePath(baseFile, generateSuffix(QString::fromLocal8Bit(qgetenv("QTC_EXTENSION")), ".user"));
|
||||
setBaseFilePath(baseFilePath);
|
||||
|
||||
Utils::FileName sharedFilePath = baseFile;
|
||||
sharedFilePath.appendString(generateSuffix(QString::fromLocal8Bit(qgetenv("QTC_SHARED_EXTENSION")), ".shared"));
|
||||
d->m_sharedFile = std::make_unique<BasicSettingsAccessor>(docType, displayName, appDisplayName);
|
||||
d->m_sharedFile->setBaseFilePath(sharedFilePath);
|
||||
}
|
||||
|
||||
SettingsAccessor::~SettingsAccessor()
|
||||
@@ -396,19 +505,6 @@ QVariantMap SettingsAccessor::setVersionInMap(const QVariantMap &data, int versi
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Run directly after reading the \a data.
|
||||
*
|
||||
* This method is called right after reading the data before any attempt at interpreting the data
|
||||
* is made.
|
||||
*
|
||||
* Returns the prepared data.
|
||||
*/
|
||||
QVariantMap SettingsAccessor::prepareSettings(const QVariantMap &data) const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Check which of two sets of data are a better match to load.
|
||||
*
|
||||
@@ -480,102 +576,56 @@ QVariantMap SettingsAccessor::upgradeSettings(const QVariantMap &data, int targe
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Find issues with the settings file and warn the user about them.
|
||||
*
|
||||
* \a data is the data from the settings file.
|
||||
* \a path is the full path to the settings used.
|
||||
* \a parent is the widget to be set as parent of any dialogs that are opened.
|
||||
*
|
||||
* Returns \c true if the settings are not usable anymore and \c false otherwise.
|
||||
*/
|
||||
SettingsAccessor::ProceedInfo SettingsAccessor::reportIssues(const QVariantMap &data,
|
||||
const FileName &path,
|
||||
QWidget *parent) const
|
||||
{
|
||||
if (!path.exists())
|
||||
return Continue;
|
||||
|
||||
const Utils::optional<IssueInfo> issue = findIssues(data, path);
|
||||
if (!issue)
|
||||
return Continue;
|
||||
|
||||
const IssueInfo &details = issue.value();
|
||||
|
||||
const QMessageBox::Icon icon
|
||||
= details.buttons.count() > 1 ? QMessageBox::Question : QMessageBox::Information;
|
||||
const QMessageBox::StandardButtons buttons = [&details]()
|
||||
{
|
||||
QMessageBox::StandardButtons buttons = QMessageBox::NoButton;
|
||||
for (const QMessageBox::StandardButton &b : details.buttons.keys())
|
||||
buttons |= b;
|
||||
return buttons;
|
||||
}();
|
||||
QTC_ASSERT(buttons != QMessageBox::NoButton, return Continue);
|
||||
|
||||
QMessageBox msgBox(icon, details.title, details.message, buttons, parent);
|
||||
if (details.defaultButton != QMessageBox::NoButton)
|
||||
msgBox.setDefaultButton(details.defaultButton);
|
||||
if (details.escapeButton != QMessageBox::NoButton)
|
||||
msgBox.setEscapeButton(details.escapeButton);
|
||||
|
||||
int boxAction = msgBox.exec();
|
||||
return details.buttons.value(static_cast<QMessageBox::StandardButton>(boxAction));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Checks \a data located at \a path for issues to be displayed with reportIssues.
|
||||
*
|
||||
* Returns a IssueInfo object which is then used by reportIssues.
|
||||
*/
|
||||
Utils::optional<SettingsAccessor::IssueInfo>
|
||||
Utils::optional<SettingsAccessor::Issue>
|
||||
SettingsAccessor::findIssues(const QVariantMap &data, const FileName &path) const
|
||||
{
|
||||
const FileName defaultSettingsPath = userFilePath(baseFilePath(), d->m_userSuffix);
|
||||
const int version = versionFromMap(data);
|
||||
if (data.isEmpty() || version < firstSupportedVersion() || version > currentVersion()) {
|
||||
IssueInfo result;
|
||||
result.title = QApplication::translate("Utils::SettingsAccessor", "No Valid Settings Found");
|
||||
result.message = QApplication::translate("Utils::SettingsAccessor",
|
||||
"<p>No valid settings file could be found.</p>"
|
||||
"<p>All settings files found in directory \"%1\" "
|
||||
"were either too new or too old to be read.</p>")
|
||||
.arg(path.toUserOutput());
|
||||
Issue result(QApplication::translate("Utils::SettingsAccessor", "No Valid Settings Found"),
|
||||
QApplication::translate("Utils::SettingsAccessor",
|
||||
"<p>No valid settings file could be found.</p>"
|
||||
"<p>All settings files found in directory \"%1\" "
|
||||
"were either too new or too old to be read.</p>")
|
||||
.arg(path.toUserOutput()));
|
||||
result.buttons.insert(QMessageBox::Ok, DiscardAndContinue);
|
||||
return result;
|
||||
}
|
||||
if ((path != defaultSettingsPath) && (version < currentVersion())) {
|
||||
IssueInfo result;
|
||||
result.title = QApplication::translate("Utils::SettingsAccessor", "Using Old Settings");
|
||||
result.message = QApplication::translate("Utils::SettingsAccessor",
|
||||
"<p>The versioned backup \"%1\" of the settings "
|
||||
"file is used, because the non-versioned file was "
|
||||
"created by an incompatible version of %2.</p>"
|
||||
"<p>Settings changes made since the last time this "
|
||||
"version of %2 was used are ignored, and "
|
||||
"changes made now will <b>not</b> be propagated to "
|
||||
"the newer version.</p>").arg(path.toUserOutput())
|
||||
.arg(d->m_applicationDisplayName);
|
||||
if ((path != baseFilePath()) && (version < currentVersion())) {
|
||||
Issue result(QApplication::translate("Utils::SettingsAccessor", "Using Old Settings"),
|
||||
QApplication::translate("Utils::SettingsAccessor",
|
||||
"<p>The versioned backup \"%1\" of the settings "
|
||||
"file is used, because the non-versioned file was "
|
||||
"created by an incompatible version of %2.</p>"
|
||||
"<p>Settings changes made since the last time this "
|
||||
"version of %2 was used are ignored, and "
|
||||
"changes made now will <b>not</b> be propagated to "
|
||||
"the newer version.</p>")
|
||||
.arg(path.toUserOutput())
|
||||
.arg(applicationDisplayName));
|
||||
result.buttons.insert(QMessageBox::Ok, Continue);
|
||||
return result;
|
||||
}
|
||||
|
||||
const QByteArray readId = settingsIdFromMap(data);
|
||||
if (!readId.isEmpty() && readId != settingsId()) {
|
||||
IssueInfo result;
|
||||
result.title = differentEnvironmentMsg(d->m_displayName);
|
||||
result.message = QApplication::translate("Utils::EnvironmentIdAccessor",
|
||||
"<p>No .user settings file created by this instance "
|
||||
"of %1 was found.</p>"
|
||||
"<p>Did you work with this project on another machine or "
|
||||
"using a different settings path before?</p>"
|
||||
"<p>Do you still want to load the settings file \"%2\"?</p>")
|
||||
.arg(d->m_applicationDisplayName)
|
||||
.arg(path.toUserOutput());
|
||||
Issue result(differentEnvironmentMsg(displayName),
|
||||
QApplication::translate("Utils::EnvironmentIdAccessor",
|
||||
"<p>No .user settings file created by this instance "
|
||||
"of %1 was found.</p>"
|
||||
"<p>Did you work with this project on another machine or "
|
||||
"using a different settings path before?</p>"
|
||||
"<p>Do you still want to load the settings file \"%2\"?</p>")
|
||||
.arg(applicationDisplayName)
|
||||
.arg(path.toUserOutput()));
|
||||
result.defaultButton = QMessageBox::No;
|
||||
result.escapeButton = QMessageBox::No;
|
||||
result.buttons.insert(QMessageBox::Yes, SettingsAccessor::Continue);
|
||||
result.buttons.insert(QMessageBox::No, SettingsAccessor::DiscardAndContinue);
|
||||
result.buttons.insert(QMessageBox::Yes, Continue);
|
||||
result.buttons.insert(QMessageBox::No, DiscardAndContinue);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -604,16 +654,7 @@ QByteArray SettingsAccessor::settingsIdFromMap(const QVariantMap &data)
|
||||
return data.value(SETTINGS_ID_KEY).toByteArray();
|
||||
}
|
||||
|
||||
QVariantMap SettingsAccessor::restoreSettings(QWidget *parent) const
|
||||
{
|
||||
QTC_ASSERT(d->lastVersion() >= 0, return QVariantMap());
|
||||
|
||||
const QVariantMap userSettings = readUserSettings(parent);
|
||||
const QVariantMap sharedSettings = readSharedSettings(parent);
|
||||
return mergeSettings(userSettings, sharedSettings);
|
||||
}
|
||||
|
||||
QVariantMap SettingsAccessor::prepareToSaveSettings(const QVariantMap &data) const
|
||||
QVariantMap SettingsAccessor::prepareToWriteSettings(const QVariantMap &data) const
|
||||
{
|
||||
QVariantMap tmp = data;
|
||||
const QVariant &shared = retrieveSharedSettings();
|
||||
@@ -626,19 +667,6 @@ QVariantMap SettingsAccessor::prepareToSaveSettings(const QVariantMap &data) con
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool SettingsAccessor::saveSettings(const QVariantMap &map, QWidget *parent) const
|
||||
{
|
||||
if (map.isEmpty())
|
||||
return false;
|
||||
|
||||
backupUserFile();
|
||||
|
||||
QVariantMap data = prepareToSaveSettings(map);
|
||||
|
||||
FileName path = FileName::fromString(defaultFileName(d->m_userSuffix));
|
||||
return writeFile(path, data, parent);
|
||||
}
|
||||
|
||||
bool SettingsAccessor::addVersionUpgrader(std::unique_ptr<VersionUpgrader> upgrader)
|
||||
{
|
||||
QTC_ASSERT(upgrader.get(), return false);
|
||||
@@ -651,29 +679,51 @@ bool SettingsAccessor::addVersionUpgrader(std::unique_ptr<VersionUpgrader> upgra
|
||||
return true;
|
||||
}
|
||||
|
||||
BasicSettingsAccessor::RestoreData SettingsAccessor::readData(const FileName &path,
|
||||
QWidget *parent) const
|
||||
{
|
||||
Q_UNUSED(path); // FIXME: This is wrong!
|
||||
|
||||
// FIXME: Do better error handling:
|
||||
QTC_ASSERT(d->lastVersion() >= 0, return RestoreData("SETUP FAILED", "SETUP FAILED"));
|
||||
|
||||
RestoreData userSettings = readUserSettings(parent);
|
||||
if (userSettings.issue && reportIssues(userSettings.issue.value(), userSettings.path, parent) == DiscardAndContinue)
|
||||
userSettings.data.clear();
|
||||
|
||||
RestoreData sharedSettings = readSharedSettings(parent);
|
||||
if (sharedSettings.issue && reportIssues(sharedSettings.issue.value(), sharedSettings.path, parent) == DiscardAndContinue)
|
||||
sharedSettings.data.clear();
|
||||
RestoreData mergedSettings = RestoreData(userSettings.path,
|
||||
mergeSettings(userSettings.data, sharedSettings.data));
|
||||
mergedSettings.issue = findIssues(mergedSettings.data, mergedSettings.path);
|
||||
return mergedSettings;
|
||||
}
|
||||
|
||||
Utils::optional<BasicSettingsAccessor::Issue> SettingsAccessor::writeData(const FileName &path,
|
||||
const QVariantMap &data) const
|
||||
{
|
||||
if (data.isEmpty())
|
||||
return {};
|
||||
|
||||
backupUserFile();
|
||||
|
||||
return BasicSettingsAccessor::writeData(path, data);
|
||||
}
|
||||
|
||||
void SettingsAccessor::setSettingsId(const QByteArray &id)
|
||||
{
|
||||
d->m_settingsId = id;
|
||||
}
|
||||
|
||||
void SettingsAccessor::setDisplayName(const QString &dn)
|
||||
{
|
||||
d->m_displayName = dn;
|
||||
}
|
||||
|
||||
void SettingsAccessor::setApplicationDisplayName(const QString &dn)
|
||||
{
|
||||
d->m_applicationDisplayName = dn;
|
||||
}
|
||||
|
||||
/* Will always return the default name first (if applicable) */
|
||||
FileNameList SettingsAccessor::settingsFiles(const QString &suffix) const
|
||||
FileNameList SettingsAccessor::settingsFiles() const
|
||||
{
|
||||
FileNameList result;
|
||||
|
||||
QFileInfoList list;
|
||||
const QFileInfo pfi = baseFilePath().toFileInfo();
|
||||
const QStringList filter(pfi.fileName() + suffix + '*');
|
||||
const QStringList filter(pfi.fileName() + '*');
|
||||
|
||||
if (!sharedUserFileDir().isEmpty()) {
|
||||
const QString sharedPath = sharedUserFileDir() + '/' + makeRelative(pfi.absolutePath());
|
||||
@@ -684,7 +734,7 @@ FileNameList SettingsAccessor::settingsFiles(const QString &suffix) const
|
||||
foreach (const QFileInfo &fi, list) {
|
||||
const FileName path = FileName::fromString(fi.absoluteFilePath());
|
||||
if (!result.contains(path)) {
|
||||
if (path.endsWith(suffix))
|
||||
if (path == baseFilePath())
|
||||
result.prepend(path);
|
||||
else
|
||||
result.append(path);
|
||||
@@ -699,16 +749,6 @@ QByteArray SettingsAccessor::settingsId() const
|
||||
return d->m_settingsId;
|
||||
}
|
||||
|
||||
QString SettingsAccessor::displayName() const
|
||||
{
|
||||
return d->m_displayName;
|
||||
}
|
||||
|
||||
QString SettingsAccessor::defaultFileName(const QString &suffix) const
|
||||
{
|
||||
return userFilePath(baseFilePath(), suffix).toString();
|
||||
}
|
||||
|
||||
int SettingsAccessor::currentVersion() const
|
||||
{
|
||||
return d->currentVersion();
|
||||
@@ -721,7 +761,7 @@ int SettingsAccessor::firstSupportedVersion() const
|
||||
|
||||
FileName SettingsAccessor::backupName(const QVariantMap &data) const
|
||||
{
|
||||
QString backupName = defaultFileName(d->m_userSuffix);
|
||||
QString backupName = baseFilePath().toString();
|
||||
const QByteArray oldEnvironmentId = settingsIdFromMap(data);
|
||||
if (!oldEnvironmentId.isEmpty() && oldEnvironmentId != settingsId())
|
||||
backupName += '.' + QString::fromLatin1(oldEnvironmentId).mid(1, 7);
|
||||
@@ -738,89 +778,71 @@ FileName SettingsAccessor::backupName(const QVariantMap &data) const
|
||||
|
||||
void SettingsAccessor::backupUserFile() const
|
||||
{
|
||||
SettingsAccessorPrivate::Settings oldSettings;
|
||||
oldSettings.path = FileName::fromString(defaultFileName(d->m_userSuffix));
|
||||
oldSettings.map = readFile(oldSettings.path);
|
||||
if (oldSettings.map.isEmpty())
|
||||
RestoreData oldSettings = BasicSettingsAccessor::readFile(baseFilePath());
|
||||
if (oldSettings.data.isEmpty())
|
||||
return;
|
||||
|
||||
// Do we need to do a backup?
|
||||
const QString origName = oldSettings.path.toString();
|
||||
QString backupFileName = backupName(oldSettings.map).toString();
|
||||
QString backupFileName = backupName(oldSettings.data).toString();
|
||||
if (backupFileName != origName)
|
||||
QFile::copy(origName, backupFileName);
|
||||
}
|
||||
|
||||
QVariantMap SettingsAccessor::readUserSettings(QWidget *parent) const
|
||||
SettingsAccessor::RestoreData SettingsAccessor::readUserSettings(QWidget *parent) const
|
||||
{
|
||||
SettingsAccessorPrivate::Settings result;
|
||||
FileNameList fileList = settingsFiles(d->m_userSuffix);
|
||||
FileNameList fileList = settingsFiles();
|
||||
if (fileList.isEmpty()) // No settings found at all.
|
||||
return result.map;
|
||||
return RestoreData(baseFilePath(), QVariantMap());
|
||||
|
||||
result = d->bestSettings(this, fileList);
|
||||
RestoreData result = d->bestSettings(this, fileList, parent);
|
||||
if (result.path.isEmpty())
|
||||
result.path = baseFilePath().parentDir();
|
||||
|
||||
ProceedInfo proceed = reportIssues(result.map, result.path, parent);
|
||||
if (proceed == DiscardAndContinue)
|
||||
return QVariantMap();
|
||||
|
||||
return result.map;
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariantMap SettingsAccessor::readSharedSettings(QWidget *parent) const
|
||||
SettingsAccessor::RestoreData SettingsAccessor::readSharedSettings(QWidget *parent) const
|
||||
{
|
||||
SettingsAccessorPrivate::Settings sharedSettings;
|
||||
QString fn = baseFilePath().toString() + d->m_sharedSuffix;
|
||||
sharedSettings.path = FileName::fromString(fn);
|
||||
sharedSettings.map = readFile(sharedSettings.path);
|
||||
RestoreData sharedSettings = d->m_sharedFile->readData(d->m_sharedFile->baseFilePath(), parent);
|
||||
|
||||
if (versionFromMap(sharedSettings.map) > currentVersion()) {
|
||||
if (versionFromMap(sharedSettings.data) > currentVersion()) {
|
||||
// The shared file version is newer than Creator... If we have valid user
|
||||
// settings we prompt the user whether we could try an *unsupported* update.
|
||||
// This makes sense since the merging operation will only replace shared settings
|
||||
// that perfectly match corresponding user ones. If we don't have valid user
|
||||
// settings to compare against, there's nothing we can do.
|
||||
|
||||
QMessageBox msgBox(
|
||||
QMessageBox::Question,
|
||||
QApplication::translate("Utils::SettingsAccessor",
|
||||
"Unsupported Shared Settings File"),
|
||||
QApplication::translate("Utils::SettingsAccessor",
|
||||
"The version of your .shared file is not "
|
||||
"supported by %1. "
|
||||
"Do you want to try loading it anyway?")
|
||||
.arg(d->m_applicationDisplayName),
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
parent);
|
||||
msgBox.setDefaultButton(QMessageBox::No);
|
||||
msgBox.setEscapeButton(QMessageBox::No);
|
||||
if (msgBox.exec() == QMessageBox::No)
|
||||
sharedSettings.map.clear();
|
||||
else
|
||||
sharedSettings.map = setVersionInMap(sharedSettings.map, currentVersion());
|
||||
sharedSettings.issue = Issue(QApplication::translate("Utils::SettingsAccessor",
|
||||
"Unsupported Shared Settings File"),
|
||||
QApplication::translate("Utils::SettingsAccessor",
|
||||
"The version of your .shared file is not "
|
||||
"supported by %1. "
|
||||
"Do you want to try loading it anyway?"));
|
||||
sharedSettings.issue->buttons.insert(QMessageBox::Yes, Continue);
|
||||
sharedSettings.issue->buttons.insert(QMessageBox::No, DiscardAndContinue);
|
||||
sharedSettings.issue->defaultButton = QMessageBox::No;
|
||||
sharedSettings.issue->escapeButton = QMessageBox::No;
|
||||
}
|
||||
return sharedSettings.map;
|
||||
return sharedSettings;
|
||||
}
|
||||
|
||||
SettingsAccessorPrivate::Settings SettingsAccessorPrivate::bestSettings(const SettingsAccessor *accessor,
|
||||
const FileNameList &pathList)
|
||||
SettingsAccessor::RestoreData SettingsAccessorPrivate::bestSettings(const SettingsAccessor *accessor,
|
||||
const FileNameList &pathList,
|
||||
QWidget *parent)
|
||||
{
|
||||
Settings bestMatch;
|
||||
SettingsAccessor::RestoreData bestMatch;
|
||||
foreach (const FileName &path, pathList) {
|
||||
const QVariantMap tmp = accessor->prepareSettings(accessor->readFile(path));
|
||||
const SettingsAccessor::RestoreData tmp = accessor->BasicSettingsAccessor::readData(path, parent);
|
||||
|
||||
if (accessor->isBetterMatch(bestMatch.map, tmp)) {
|
||||
bestMatch.path = path;
|
||||
bestMatch.map = tmp;
|
||||
}
|
||||
if (accessor->isBetterMatch(bestMatch.data, tmp.data))
|
||||
bestMatch = tmp;
|
||||
}
|
||||
return bestMatch;
|
||||
}
|
||||
|
||||
QVariantMap SettingsAccessor::mergeSettings(const QVariantMap &userMap,
|
||||
const QVariantMap &sharedMap) const
|
||||
QVariantMap
|
||||
SettingsAccessor::mergeSettings(const QVariantMap &userMap, const QVariantMap &sharedMap) const
|
||||
{
|
||||
QVariantMap newUser = userMap;
|
||||
QVariantMap newShared = sharedMap;
|
||||
|
@@ -35,30 +35,73 @@
|
||||
#include <QMessageBox>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Utils {
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// BasicSettingsAccessor:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Read/write files incl. error handling suitable for the UI:
|
||||
class QTCREATOR_UTILS_EXPORT BasicSettingsAccessor
|
||||
{
|
||||
public:
|
||||
BasicSettingsAccessor(const Utils::FileName &baseFilePath, const QString &docType);
|
||||
virtual ~BasicSettingsAccessor();
|
||||
BasicSettingsAccessor(const QString &docType, const QString &displayName,
|
||||
const QString &applicationDisplayName);
|
||||
virtual ~BasicSettingsAccessor() = default;
|
||||
|
||||
virtual QVariantMap restoreSettings(QWidget *parent) const;
|
||||
virtual bool saveSettings(const QVariantMap &data, QWidget *parent) const;
|
||||
enum ProceedInfo { Continue, DiscardAndContinue };
|
||||
typedef QHash<QMessageBox::StandardButton, ProceedInfo> ButtonMap;
|
||||
class Issue {
|
||||
public:
|
||||
Issue(const QString &title, const QString &message) : title{title}, message{message} { }
|
||||
|
||||
QMessageBox::StandardButtons allButtons() const;
|
||||
|
||||
QString title;
|
||||
QString message;
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton;
|
||||
QMessageBox::StandardButton escapeButton = QMessageBox::Ok;
|
||||
QHash<QMessageBox::StandardButton, ProceedInfo> buttons = {{QMessageBox::Ok, ProceedInfo::Continue}};
|
||||
};
|
||||
|
||||
class RestoreData {
|
||||
public:
|
||||
RestoreData() = default;
|
||||
RestoreData(const Utils::FileName &path, const QVariantMap &data) : path{path}, data{data} { }
|
||||
RestoreData(const QString &title, const QString &message) : RestoreData(Issue(title, message)) { }
|
||||
RestoreData(const Issue &issue) : issue{issue} { }
|
||||
Utils::FileName path;
|
||||
QVariantMap data;
|
||||
Utils::optional<Issue> issue;
|
||||
};
|
||||
|
||||
QVariantMap restoreSettings(QWidget *parent) const;
|
||||
bool saveSettings(const QVariantMap &data, QWidget *parent) const;
|
||||
|
||||
const QString docType;
|
||||
const QString displayName;
|
||||
const QString applicationDisplayName;
|
||||
|
||||
void setBaseFilePath(const Utils::FileName &baseFilePath) { m_baseFilePath = baseFilePath; }
|
||||
Utils::FileName baseFilePath() const { return m_baseFilePath; }
|
||||
|
||||
virtual RestoreData readData(const Utils::FileName &path, QWidget *parent) const;
|
||||
virtual Utils::optional<Issue> writeData(const Utils::FileName &path, const QVariantMap &data) const;
|
||||
|
||||
protected:
|
||||
QVariantMap readFile(const Utils::FileName &path) const;
|
||||
bool writeFile(const Utils::FileName &path, const QVariantMap &data, QWidget *parent) const;
|
||||
// Report errors:
|
||||
ProceedInfo reportIssues(const Issue &issue, const FileName &path, QWidget *parent) const;
|
||||
|
||||
Utils::FileName baseFilePath() const;
|
||||
virtual QVariantMap preprocessReadSettings(const QVariantMap &data) const;
|
||||
virtual QVariantMap prepareToWriteSettings(const QVariantMap &data) const;
|
||||
|
||||
RestoreData readFile(const Utils::FileName &path) const;
|
||||
Utils::optional<Issue> writeFile(const Utils::FileName &path, const QVariantMap &data) const;
|
||||
|
||||
private:
|
||||
const Utils::FileName m_baseFilePath;
|
||||
const QString m_docType;
|
||||
Utils::FileName m_baseFilePath;
|
||||
mutable std::unique_ptr<PersistentSettingsWriter> m_writer;
|
||||
};
|
||||
|
||||
@@ -92,12 +135,10 @@ class SettingsAccessorPrivate;
|
||||
class QTCREATOR_UTILS_EXPORT SettingsAccessor : public BasicSettingsAccessor
|
||||
{
|
||||
public:
|
||||
explicit SettingsAccessor(const Utils::FileName &baseFile, const QString &docType);
|
||||
explicit SettingsAccessor(const Utils::FileName &baseFile, const QString &docType,
|
||||
const QString &displayName, const QString &appDisplayName);
|
||||
~SettingsAccessor() override;
|
||||
|
||||
QVariantMap restoreSettings(QWidget *parent) const override;
|
||||
bool saveSettings(const QVariantMap &data, QWidget *parent) const override;
|
||||
|
||||
static QVariantMap setVersionInMap(const QVariantMap &data, int version);
|
||||
static int versionFromMap(const QVariantMap &data);
|
||||
static int originalVersionFromMap(const QVariantMap &data);
|
||||
@@ -108,51 +149,35 @@ public:
|
||||
|
||||
bool addVersionUpgrader(std::unique_ptr<VersionUpgrader> upgrader);
|
||||
|
||||
enum ProceedInfo { Continue, DiscardAndContinue };
|
||||
typedef QHash<QMessageBox::StandardButton, ProceedInfo> ButtonMap;
|
||||
class IssueInfo {
|
||||
public:
|
||||
QString title;
|
||||
QString message;
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton;
|
||||
QMessageBox::StandardButton escapeButton = QMessageBox::NoButton;
|
||||
QHash<QMessageBox::StandardButton, ProceedInfo> buttons;
|
||||
};
|
||||
|
||||
protected:
|
||||
RestoreData readData(const Utils::FileName &path, QWidget *parent) const final;
|
||||
Utils::optional<Issue> writeData(const Utils::FileName &path, const QVariantMap &data) const final;
|
||||
|
||||
void setSettingsId(const QByteArray &id);
|
||||
void setDisplayName(const QString &dn);
|
||||
void setApplicationDisplayName(const QString &dn);
|
||||
QVariantMap upgradeSettings(const QVariantMap &data) const;
|
||||
QVariantMap upgradeSettings(const QVariantMap &data, const int targetVersion) const;
|
||||
|
||||
ProceedInfo reportIssues(const QVariantMap &data, const Utils::FileName &path, QWidget *parent) const;
|
||||
|
||||
virtual QVariantMap prepareSettings(const QVariantMap &data) const;
|
||||
virtual QVariantMap prepareToSaveSettings(const QVariantMap &data) const;
|
||||
QVariantMap prepareToWriteSettings(const QVariantMap &data) const override;
|
||||
|
||||
virtual bool isBetterMatch(const QVariantMap &origData, const QVariantMap &newData) const;
|
||||
virtual bool isValidVersionAndId(const int version, const QByteArray &id) const;
|
||||
|
||||
virtual Utils::FileName backupName(const QVariantMap &data) const;
|
||||
|
||||
virtual Utils::optional<IssueInfo> findIssues(const QVariantMap &data,
|
||||
const Utils::FileName &path) const;
|
||||
|
||||
QVariantMap mergeSettings(const QVariantMap &userMap, const QVariantMap &sharedMap) const;
|
||||
|
||||
virtual void storeSharedSettings(const QVariantMap &data) const;
|
||||
virtual QVariant retrieveSharedSettings() const;
|
||||
|
||||
QVariantMap mergeSettings(const QVariantMap &userMap, const QVariantMap &sharedMap) const;
|
||||
|
||||
Utils::optional<Issue> findIssues(const QVariantMap &data, const Utils::FileName &path) const;
|
||||
|
||||
private:
|
||||
Utils::FileNameList settingsFiles(const QString &suffix) const;
|
||||
Utils::FileNameList settingsFiles() const;
|
||||
QByteArray settingsId() const;
|
||||
QString displayName() const;
|
||||
QString defaultFileName(const QString &suffix) const;
|
||||
void backupUserFile() const;
|
||||
|
||||
QVariantMap readUserSettings(QWidget *parent) const;
|
||||
QVariantMap readSharedSettings(QWidget *parent) const;
|
||||
RestoreData readUserSettings(QWidget *parent) const;
|
||||
RestoreData readSharedSettings(QWidget *parent) const;
|
||||
|
||||
static QByteArray settingsIdFromMap(const QVariantMap &data);
|
||||
static QString differentEnvironmentMsg(const QString &projectName);
|
||||
|
@@ -33,10 +33,6 @@
|
||||
#include <iterator>
|
||||
#include <ostream>
|
||||
|
||||
#ifdef UNIT_TESTS
|
||||
#include <gtest/gtest.h>
|
||||
#endif
|
||||
|
||||
namespace Utils {
|
||||
|
||||
template <uint Size>
|
||||
@@ -235,22 +231,6 @@ QDataStream &operator>>(QDataStream &in, vector<Type> &vector)
|
||||
return in;
|
||||
}
|
||||
|
||||
#ifdef UNIT_TESTS
|
||||
template <typename T>
|
||||
ostream &operator<<(ostream &out, const vector<T> &vector)
|
||||
{
|
||||
out << "[";
|
||||
|
||||
ostream_iterator<string> outIterator(out, ", ");
|
||||
|
||||
for (const auto &entry : vector)
|
||||
outIterator = ::testing::PrintToString(entry);
|
||||
|
||||
out << "]";
|
||||
|
||||
return out;
|
||||
}
|
||||
#else
|
||||
template <typename T>
|
||||
ostream &operator<<(ostream &out, const vector<T> &vector)
|
||||
{
|
||||
@@ -262,7 +242,6 @@ ostream &operator<<(ostream &out, const vector<T> &vector)
|
||||
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace std
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "gtestresult.h"
|
||||
#include "../testtreemodel.h"
|
||||
#include "../testtreeitem.h"
|
||||
#include "utils/hostosinfo.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
@@ -47,6 +48,15 @@ GTestOutputReader::GTestOutputReader(const QFutureInterface<TestResultPtr> &futu
|
||||
, m_executable(testApplication ? testApplication->program() : QString())
|
||||
, m_projectFile(projectFile)
|
||||
{
|
||||
// on Windows abort() will result in normal termination, but exit code will be set to 3
|
||||
if (Utils::HostOsInfo::isWindowsHost()) {
|
||||
connect(m_testApplication,
|
||||
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||
this, [this] (int exitCode, QProcess::ExitStatus /*exitStatus*/) {
|
||||
if (exitCode == 3)
|
||||
reportCrash();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void GTestOutputReader::processOutput(const QByteArray &outputLine)
|
||||
@@ -92,15 +102,15 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
|
||||
}
|
||||
|
||||
if (testEnds.exactMatch(line)) {
|
||||
GTestResult *testResult = createDefaultResult();
|
||||
TestResultPtr testResult = createDefaultResult();
|
||||
testResult->setResult(Result::MessageTestCaseEnd);
|
||||
testResult->setDescription(tr("Test execution took %1").arg(testEnds.cap(2)));
|
||||
reportResult(TestResultPtr(testResult));
|
||||
reportResult(testResult);
|
||||
m_currentTestName.clear();
|
||||
m_currentTestSet.clear();
|
||||
} else if (newTestStarts.exactMatch(line)) {
|
||||
setCurrentTestName(newTestStarts.cap(1));
|
||||
TestResultPtr testResult = TestResultPtr(createDefaultResult());
|
||||
TestResultPtr testResult = createDefaultResult();
|
||||
testResult->setResult(Result::MessageTestCaseStart);
|
||||
if (m_iteration > 1) {
|
||||
testResult->setDescription(tr("Repeating test case %1 (iteration %2)")
|
||||
@@ -117,18 +127,18 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
|
||||
reportResult(testResult);
|
||||
m_description.clear();
|
||||
} else if (testSetSuccess.exactMatch(line)) {
|
||||
GTestResult *testResult = createDefaultResult();
|
||||
TestResultPtr testResult = createDefaultResult();
|
||||
testResult->setResult(Result::Pass);
|
||||
testResult->setDescription(m_description);
|
||||
reportResult(TestResultPtr(testResult));
|
||||
reportResult(testResult);
|
||||
m_description.clear();
|
||||
testResult = createDefaultResult();
|
||||
testResult->setResult(Result::MessageInternal);
|
||||
testResult->setDescription(tr("Execution took %1.").arg(testSetSuccess.cap(2)));
|
||||
reportResult(TestResultPtr(testResult));
|
||||
reportResult(testResult);
|
||||
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
|
||||
} else if (testSetFail.exactMatch(line)) {
|
||||
GTestResult *testResult = createDefaultResult();
|
||||
TestResultPtr testResult = createDefaultResult();
|
||||
testResult->setResult(Result::Fail);
|
||||
m_description.chop(1);
|
||||
testResult->setDescription(m_description);
|
||||
@@ -149,27 +159,17 @@ void GTestOutputReader::processOutput(const QByteArray &outputLine)
|
||||
}
|
||||
}
|
||||
}
|
||||
reportResult(TestResultPtr(testResult));
|
||||
reportResult(testResult);
|
||||
m_description.clear();
|
||||
testResult = createDefaultResult();
|
||||
testResult->setResult(Result::MessageInternal);
|
||||
testResult->setDescription(tr("Execution took %1.").arg(testSetFail.cap(2)));
|
||||
reportResult(TestResultPtr(testResult));
|
||||
reportResult(testResult);
|
||||
m_futureInterface.setProgressValue(m_futureInterface.progressValue() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void GTestOutputReader::setCurrentTestSet(const QString &testSet)
|
||||
{
|
||||
m_currentTestSet = testSet;
|
||||
}
|
||||
|
||||
void GTestOutputReader::setCurrentTestName(const QString &testName)
|
||||
{
|
||||
m_currentTestName = testName;
|
||||
}
|
||||
|
||||
GTestResult *GTestOutputReader::createDefaultResult() const
|
||||
TestResultPtr GTestOutputReader::createDefaultResult() const
|
||||
{
|
||||
GTestResult *result = new GTestResult(m_executable, m_projectFile, m_currentTestName);
|
||||
result->setTestSetName(m_currentTestSet);
|
||||
@@ -182,7 +182,17 @@ GTestResult *GTestOutputReader::createDefaultResult() const
|
||||
result->setLine(static_cast<int>(testItem->line()));
|
||||
}
|
||||
|
||||
return result;
|
||||
return TestResultPtr(result);
|
||||
}
|
||||
|
||||
void GTestOutputReader::setCurrentTestSet(const QString &testSet)
|
||||
{
|
||||
m_currentTestSet = testSet;
|
||||
}
|
||||
|
||||
void GTestOutputReader::setCurrentTestName(const QString &testName)
|
||||
{
|
||||
m_currentTestName = testName;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -43,14 +43,13 @@ public:
|
||||
GTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||
QProcess *testApplication, const QString &buildDirectory,
|
||||
const QString &projectFile);
|
||||
|
||||
protected:
|
||||
void processOutput(const QByteArray &outputLine) override;
|
||||
TestResultPtr createDefaultResult() const override;
|
||||
|
||||
private:
|
||||
void setCurrentTestSet(const QString &testSet);
|
||||
void setCurrentTestName(const QString &testName);
|
||||
GTestResult *createDefaultResult() const;
|
||||
|
||||
QString m_executable;
|
||||
QString m_projectFile;
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "gtesttreeitem.h"
|
||||
#include "gtestconfiguration.h"
|
||||
#include "gtestparser.h"
|
||||
#include "../testframeworkmanager.h"
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <projectexplorer/session.h>
|
||||
@@ -59,6 +60,7 @@ QVariant GTestTreeItem::data(int column, int role) const
|
||||
case Qt::CheckStateRole:
|
||||
switch (type()) {
|
||||
case Root:
|
||||
case GroupNode:
|
||||
case TestCase:
|
||||
case TestFunctionOrSet:
|
||||
return checked();
|
||||
@@ -237,6 +239,22 @@ TestTreeItem *GTestTreeItem::find(const TestParseResult *result)
|
||||
states |= GTestTreeItem::Typed;
|
||||
switch (type()) {
|
||||
case Root:
|
||||
if (TestFrameworkManager::instance()->groupingEnabled(result->frameworkId)) {
|
||||
const QFileInfo fileInfo(parseResult->fileName);
|
||||
const QFileInfo base(fileInfo.absolutePath());
|
||||
for (int row = 0; row < childCount(); ++row) {
|
||||
GTestTreeItem *group = static_cast<GTestTreeItem *>(childAt(row));
|
||||
if (group->filePath() != base.absoluteFilePath())
|
||||
continue;
|
||||
if (auto groupChild = group->findChildByNameStateAndFile(parseResult->name, states,
|
||||
parseResult->proFile)) {
|
||||
return groupChild;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return findChildByNameStateAndFile(parseResult->name, states, parseResult->proFile);
|
||||
case GroupNode:
|
||||
return findChildByNameStateAndFile(parseResult->name, states, parseResult->proFile);
|
||||
case TestCase:
|
||||
return findChildByNameAndFile(result->name, result->fileName);
|
||||
@@ -257,6 +275,13 @@ bool GTestTreeItem::modify(const TestParseResult *result)
|
||||
}
|
||||
}
|
||||
|
||||
TestTreeItem *GTestTreeItem::createParentGroupNode() const
|
||||
{
|
||||
const QFileInfo fileInfo(filePath());
|
||||
const QFileInfo base(fileInfo.absolutePath());
|
||||
return new GTestTreeItem(base.baseName(), fileInfo.absolutePath(), TestTreeItem::GroupNode);
|
||||
}
|
||||
|
||||
bool GTestTreeItem::modifyTestSetContent(const GTestParseResult *result)
|
||||
{
|
||||
bool hasBeenModified = modifyLineAndColumn(result);
|
||||
|
@@ -58,6 +58,7 @@ public:
|
||||
QList<TestConfiguration *> getSelectedTestConfigurations() const override;
|
||||
TestTreeItem *find(const TestParseResult *result) override;
|
||||
bool modify(const TestParseResult *result) override;
|
||||
TestTreeItem *createParentGroupNode() const override;
|
||||
|
||||
void setStates(TestStates states) { m_state = states; }
|
||||
void setState(TestState state) { m_state |= state; }
|
||||
|
@@ -69,6 +69,8 @@ public:
|
||||
|
||||
bool active() const { return m_active; }
|
||||
void setActive(bool active) { m_active = active; }
|
||||
bool grouping() const { return m_grouping; }
|
||||
void setGrouping(bool group) { m_grouping = group; }
|
||||
|
||||
protected:
|
||||
virtual ITestParser *createTestParser() const = 0;
|
||||
@@ -78,6 +80,7 @@ private:
|
||||
TestTreeItem *m_rootNode = 0;
|
||||
ITestParser *m_testParser = 0;
|
||||
bool m_active = false;
|
||||
bool m_grouping = false;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -39,9 +39,10 @@ CppParser::CppParser()
|
||||
s_parserInstance = this;
|
||||
}
|
||||
|
||||
void CppParser::init(const QStringList &filesToParse)
|
||||
void CppParser::init(const QStringList &filesToParse, bool fullParse)
|
||||
{
|
||||
Q_UNUSED(filesToParse);
|
||||
Q_UNUSED(fullParse);
|
||||
m_cppSnapshot = CppTools::CppModelManager::instance()->snapshot();
|
||||
m_workingCopy = CppTools::CppModelManager::instance()->workingCopy();
|
||||
}
|
||||
|
@@ -61,7 +61,7 @@ class ITestParser
|
||||
{
|
||||
public:
|
||||
virtual ~ITestParser() { }
|
||||
virtual void init(const QStringList &filesToParse) = 0;
|
||||
virtual void init(const QStringList &filesToParse, bool fullParse) = 0;
|
||||
virtual bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface,
|
||||
const QString &fileName) = 0;
|
||||
virtual void release() = 0;
|
||||
@@ -76,7 +76,7 @@ class CppParser : public ITestParser
|
||||
{
|
||||
public:
|
||||
CppParser();
|
||||
void init(const QStringList &filesToParse) override;
|
||||
void init(const QStringList &filesToParse, bool fullParse) override;
|
||||
static bool selectedForBuilding(const QString &fileName);
|
||||
static QByteArray getFileContent(const QString &filePath);
|
||||
void release() override;
|
||||
|
@@ -152,6 +152,14 @@ void QtTestOutputReader::processOutput(const QByteArray &outputLine)
|
||||
}
|
||||
}
|
||||
|
||||
TestResultPtr QtTestOutputReader::createDefaultResult() const
|
||||
{
|
||||
QtTestResult *result = new QtTestResult(m_executable, m_projectFile, m_testType, m_className);
|
||||
result->setFunctionName(m_testCase);
|
||||
result->setDataTag(m_dataTag);
|
||||
return TestResultPtr(result);
|
||||
}
|
||||
|
||||
void QtTestOutputReader::processXMLOutput(const QByteArray &outputLine)
|
||||
{
|
||||
static QStringList validEndTags = {QStringLiteral("Incident"),
|
||||
@@ -416,17 +424,9 @@ void QtTestOutputReader::processSummaryFinishOutput()
|
||||
m_lineNumber = 0;
|
||||
}
|
||||
|
||||
QtTestResult *QtTestOutputReader::createDefaultResult() const
|
||||
{
|
||||
QtTestResult *result = new QtTestResult(m_executable, m_projectFile, m_testType, m_className);
|
||||
result->setFunctionName(m_testCase);
|
||||
result->setDataTag(m_dataTag);
|
||||
return result;
|
||||
}
|
||||
|
||||
void QtTestOutputReader::sendCompleteInformation()
|
||||
{
|
||||
TestResultPtr testResult = TestResultPtr(createDefaultResult());
|
||||
TestResultPtr testResult = createDefaultResult();
|
||||
testResult->setResult(m_result);
|
||||
|
||||
if (m_lineNumber) {
|
||||
@@ -453,7 +453,7 @@ void QtTestOutputReader::sendMessageCurrentTest()
|
||||
|
||||
void QtTestOutputReader::sendStartMessage(bool isFunction)
|
||||
{
|
||||
TestResultPtr testResult = TestResultPtr(createDefaultResult());
|
||||
TestResultPtr testResult = createDefaultResult();
|
||||
testResult->setResult(Result::MessageTestCaseStart);
|
||||
testResult->setDescription(isFunction ? tr("Executing test function %1").arg(m_testCase)
|
||||
: tr("Executing test case %1").arg(m_className));
|
||||
@@ -467,7 +467,7 @@ void QtTestOutputReader::sendStartMessage(bool isFunction)
|
||||
|
||||
void QtTestOutputReader::sendFinishMessage(bool isFunction)
|
||||
{
|
||||
TestResultPtr testResult = TestResultPtr(createDefaultResult());
|
||||
TestResultPtr testResult = createDefaultResult();
|
||||
testResult->setResult(Result::MessageTestCaseEnd);
|
||||
if (!m_duration.isEmpty()) {
|
||||
testResult->setDescription(isFunction ? tr("Execution took %1 ms.").arg(m_duration)
|
||||
@@ -482,18 +482,18 @@ void QtTestOutputReader::sendFinishMessage(bool isFunction)
|
||||
// TODO factor out tr() strings to avoid duplication (see XML processing of Characters)
|
||||
void QtTestOutputReader::handleAndSendConfigMessage(const QRegExp &config)
|
||||
{
|
||||
QtTestResult *testResult = createDefaultResult();
|
||||
TestResultPtr testResult = createDefaultResult();
|
||||
testResult->setResult(Result::MessageInternal);
|
||||
testResult->setDescription(tr("Qt version: %1").arg(config.cap(3)));
|
||||
reportResult(TestResultPtr(testResult));
|
||||
reportResult(testResult);
|
||||
testResult = createDefaultResult();
|
||||
testResult->setResult(Result::MessageInternal);
|
||||
testResult->setDescription(tr("Qt build: %1").arg(config.cap(2)));
|
||||
reportResult(TestResultPtr(testResult));
|
||||
reportResult(testResult);
|
||||
testResult = createDefaultResult();
|
||||
testResult->setResult(Result::MessageInternal);
|
||||
testResult->setDescription(tr("QTest version: %1").arg(config.cap(1)));
|
||||
reportResult(TestResultPtr(testResult));
|
||||
reportResult(testResult);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -50,9 +50,9 @@ public:
|
||||
QtTestOutputReader(const QFutureInterface<TestResultPtr> &futureInterface,
|
||||
QProcess *testApplication, const QString &buildDirectory,
|
||||
const QString &projectFile, OutputMode mode, TestType type);
|
||||
|
||||
protected:
|
||||
void processOutput(const QByteArray &outputLine) override;
|
||||
TestResultPtr createDefaultResult() const override;
|
||||
|
||||
private:
|
||||
void processXMLOutput(const QByteArray &outputLine);
|
||||
@@ -61,7 +61,6 @@ private:
|
||||
void processLocationOutput(const QString &fileWithLine);
|
||||
void processSummaryFinishOutput();
|
||||
// helper functions
|
||||
QtTestResult *createDefaultResult() const;
|
||||
void sendCompleteInformation();
|
||||
void sendMessageCurrentTest();
|
||||
void sendStartMessage(bool isFunction);
|
||||
|
@@ -369,11 +369,13 @@ static bool handleQtTest(QFutureInterface<TestParseResultPtr> futureInterface,
|
||||
return false;
|
||||
}
|
||||
|
||||
void QtTestParser::init(const QStringList &filesToParse)
|
||||
void QtTestParser::init(const QStringList &filesToParse, bool fullParse)
|
||||
{
|
||||
m_testCaseNames = QTestUtils::testCaseNamesForFiles(id(), filesToParse);
|
||||
m_alternativeFiles = QTestUtils::alternativeFiles(id(), filesToParse);
|
||||
CppParser::init(filesToParse);
|
||||
if (!fullParse) { // in a full parse cached information might lead to wrong results
|
||||
m_testCaseNames = QTestUtils::testCaseNamesForFiles(id(), filesToParse);
|
||||
m_alternativeFiles = QTestUtils::alternativeFiles(id(), filesToParse);
|
||||
}
|
||||
CppParser::init(filesToParse, fullParse);
|
||||
}
|
||||
|
||||
void QtTestParser::release()
|
||||
|
@@ -44,7 +44,7 @@ private:
|
||||
class QtTestParser : public CppParser
|
||||
{
|
||||
public:
|
||||
void init(const QStringList &filesToParse) override;
|
||||
void init(const QStringList &filesToParse, bool fullParse) override;
|
||||
void release() override;
|
||||
bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface,
|
||||
const QString &fileName) override;
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "qttesttreeitem.h"
|
||||
#include "qttestconfiguration.h"
|
||||
#include "qttestparser.h"
|
||||
#include "../testframeworkmanager.h"
|
||||
|
||||
#include <projectexplorer/session.h>
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -227,6 +228,19 @@ TestTreeItem *QtTestTreeItem::find(const TestParseResult *result)
|
||||
|
||||
switch (type()) {
|
||||
case Root:
|
||||
if (TestFrameworkManager::instance()->groupingEnabled(result->frameworkId)) {
|
||||
const QString path = QFileInfo(result->fileName).absolutePath();
|
||||
for (int row = 0; row < childCount(); ++row) {
|
||||
TestTreeItem *group = childItem(row);
|
||||
if (group->filePath() != path)
|
||||
continue;
|
||||
if (auto groupChild = group->findChildByFile(result->fileName))
|
||||
return groupChild;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return findChildByFile(result->fileName);
|
||||
case GroupNode:
|
||||
return findChildByFile(result->fileName);
|
||||
case TestCase: {
|
||||
const QtTestParseResult *qtResult = static_cast<const QtTestParseResult *>(result);
|
||||
@@ -259,6 +273,13 @@ bool QtTestTreeItem::modify(const TestParseResult *result)
|
||||
}
|
||||
}
|
||||
|
||||
TestTreeItem *QtTestTreeItem::createParentGroupNode() const
|
||||
{
|
||||
const QFileInfo fileInfo(filePath());
|
||||
const QFileInfo base(fileInfo.absolutePath());
|
||||
return new QtTestTreeItem(base.baseName(), fileInfo.absolutePath(), TestTreeItem::GroupNode);
|
||||
}
|
||||
|
||||
TestTreeItem *QtTestTreeItem::findChildByNameAndInheritance(const QString &name, bool inherited) const
|
||||
{
|
||||
return findChildBy([name, inherited](const TestTreeItem *other) -> bool {
|
||||
|
@@ -48,6 +48,7 @@ public:
|
||||
bool modify(const TestParseResult *result) override;
|
||||
void setInherited(bool inherited) { m_inherited = inherited; }
|
||||
bool inherited() const { return m_inherited; }
|
||||
TestTreeItem *createParentGroupNode() const override;
|
||||
private:
|
||||
TestTreeItem *findChildByNameAndInheritance(const QString &name, bool inherited) const;
|
||||
QString nameSuffix() const;
|
||||
|
@@ -303,11 +303,12 @@ QuickTestParser::~QuickTestParser()
|
||||
{
|
||||
}
|
||||
|
||||
void QuickTestParser::init(const QStringList &filesToParse)
|
||||
void QuickTestParser::init(const QStringList &filesToParse, bool fullParse)
|
||||
{
|
||||
m_qmlSnapshot = QmlJSTools::Internal::ModelManager::instance()->snapshot();
|
||||
m_proFilesForQmlFiles = QuickTestUtils::proFilesForQmlFiles(id(), filesToParse);
|
||||
CppParser::init(filesToParse);
|
||||
if (!fullParse) // in a full parse we get the correct entry points by the respective main
|
||||
m_proFilesForQmlFiles = QuickTestUtils::proFilesForQmlFiles(id(), filesToParse);
|
||||
CppParser::init(filesToParse, fullParse);
|
||||
}
|
||||
|
||||
void QuickTestParser::release()
|
||||
|
@@ -47,7 +47,7 @@ class QuickTestParser : public QObject, public CppParser
|
||||
public:
|
||||
QuickTestParser();
|
||||
virtual ~QuickTestParser();
|
||||
void init(const QStringList &filesToParse) override;
|
||||
void init(const QStringList &filesToParse, bool fullParse) override;
|
||||
void release() override;
|
||||
bool processDocument(QFutureInterface<TestParseResultPtr> futureInterface,
|
||||
const QString &fileName) override;
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "quicktesttreeitem.h"
|
||||
#include "quicktestconfiguration.h"
|
||||
#include "quicktestparser.h"
|
||||
#include "../testframeworkmanager.h"
|
||||
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <projectexplorer/session.h>
|
||||
@@ -267,7 +268,22 @@ TestTreeItem *QuickTestTreeItem::find(const TestParseResult *result)
|
||||
|
||||
switch (type()) {
|
||||
case Root:
|
||||
return result->name.isEmpty() ? unnamedQuickTests() : findChildByFile(result->fileName);
|
||||
if (result->name.isEmpty())
|
||||
return unnamedQuickTests();
|
||||
if (TestFrameworkManager::instance()->groupingEnabled(result->frameworkId)) {
|
||||
const QString path = QFileInfo(result->fileName).absolutePath();
|
||||
for (int row = 0; row < childCount(); ++row) {
|
||||
TestTreeItem *group = childItem(row);
|
||||
if (group->filePath() != path)
|
||||
continue;
|
||||
if (auto groupChild = group->findChildByFile(result->fileName))
|
||||
return groupChild;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return findChildByFile(result->fileName);
|
||||
case GroupNode:
|
||||
return findChildByFile(result->fileName);
|
||||
case TestCase:
|
||||
return name().isEmpty() ? findChildByNameAndFile(result->name, result->fileName)
|
||||
: findChildByName(result->name);
|
||||
@@ -303,6 +319,26 @@ bool QuickTestTreeItem::lessThan(const TestTreeItem *other, TestTreeItem::SortMo
|
||||
return TestTreeItem::lessThan(other, mode);
|
||||
}
|
||||
|
||||
bool QuickTestTreeItem::isGroupNodeFor(const TestTreeItem *other) const
|
||||
{
|
||||
QTC_ASSERT(other, return false);
|
||||
if (other->name().isEmpty()) // unnamed quick tests will not get grouped
|
||||
return false;
|
||||
return TestTreeItem::isGroupNodeFor(other);
|
||||
}
|
||||
|
||||
TestTreeItem *QuickTestTreeItem::createParentGroupNode() const
|
||||
{
|
||||
if (filePath().isEmpty() || name().isEmpty())
|
||||
return nullptr;
|
||||
if (type() == TestFunctionOrSet)
|
||||
return nullptr;
|
||||
|
||||
const QFileInfo fileInfo(filePath());
|
||||
const QFileInfo base(fileInfo.absolutePath());
|
||||
return new QuickTestTreeItem(base.baseName(), fileInfo.absolutePath(), TestTreeItem::GroupNode);
|
||||
}
|
||||
|
||||
QSet<QString> QuickTestTreeItem::internalTargets() const
|
||||
{
|
||||
QSet<QString> result;
|
||||
|
@@ -47,6 +47,8 @@ public:
|
||||
TestTreeItem *find(const TestParseResult *result) override;
|
||||
bool modify(const TestParseResult *result) override;
|
||||
bool lessThan(const TestTreeItem *other, SortMode mode) const override;
|
||||
bool isGroupNodeFor(const TestTreeItem *other) const override;
|
||||
TestTreeItem *createParentGroupNode() const override;
|
||||
QSet<QString> internalTargets() const override;
|
||||
private:
|
||||
TestTreeItem *unnamedQuickTests() const;
|
||||
|
@@ -399,7 +399,7 @@ void TestCodeParser::scanForTests(const QStringList &fileList, ITestParser *pars
|
||||
codeParsers.append(m_testCodeParsers);
|
||||
qCDebug(LOG) << QDateTime::currentDateTime().toString("hh:mm:ss.zzz") << "StartParsing";
|
||||
for (ITestParser *parser : codeParsers)
|
||||
parser->init(list);
|
||||
parser->init(list, isFullParse);
|
||||
|
||||
QFuture<TestParseResultPtr> future = Utils::map(list,
|
||||
[codeParsers](QFutureInterface<TestParseResultPtr> &fi, const QString &file) {
|
||||
|
@@ -94,8 +94,10 @@ void TestFrameworkManager::activateFrameworksFromSettings(QSharedPointer<TestSet
|
||||
{
|
||||
FrameworkIterator it = m_registeredFrameworks.begin();
|
||||
FrameworkIterator end = m_registeredFrameworks.end();
|
||||
for ( ; it != end; ++it)
|
||||
for ( ; it != end; ++it) {
|
||||
it.value()->setActive(settings->frameworks.value(it.key(), false));
|
||||
it.value()->setGrouping(settings->frameworksGrouping.value(it.key(), false));
|
||||
}
|
||||
}
|
||||
|
||||
QString TestFrameworkManager::frameworkNameForId(const Core::Id &id) const
|
||||
@@ -181,6 +183,18 @@ bool TestFrameworkManager::isActive(const Core::Id &frameworkId) const
|
||||
return framework ? framework->active() : false;
|
||||
}
|
||||
|
||||
bool TestFrameworkManager::groupingEnabled(const Core::Id &frameworkId) const
|
||||
{
|
||||
ITestFramework *framework = m_registeredFrameworks.value(frameworkId);
|
||||
return framework ? framework->grouping() : false;
|
||||
}
|
||||
|
||||
void TestFrameworkManager::setGroupingEnabledFor(const Core::Id &frameworkId, bool enabled)
|
||||
{
|
||||
if (ITestFramework *framework = m_registeredFrameworks.value(frameworkId))
|
||||
framework->setGrouping(enabled);
|
||||
}
|
||||
|
||||
bool TestFrameworkManager::hasActiveFrameworks() const
|
||||
{
|
||||
for (ITestFramework *framework : m_registeredFrameworks.values()) {
|
||||
|
@@ -63,6 +63,8 @@ public:
|
||||
QSharedPointer<IFrameworkSettings> settingsForTestFramework(const Core::Id &frameworkId) const;
|
||||
void synchronizeSettings(QSettings *s);
|
||||
bool isActive(const Core::Id &frameworkId) const;
|
||||
bool groupingEnabled(const Core::Id &frameworkId) const;
|
||||
void setGroupingEnabledFor(const Core::Id &frameworkId, bool enabled);
|
||||
bool hasActiveFrameworks() const;
|
||||
|
||||
private:
|
||||
|
@@ -66,6 +66,14 @@ void TestOutputReader::processStdError(const QByteArray &output)
|
||||
qWarning() << "AutoTest.Run: Ignored plain output:" << output;
|
||||
}
|
||||
|
||||
void TestOutputReader::reportCrash()
|
||||
{
|
||||
TestResultPtr result = createDefaultResult();
|
||||
result->setDescription(tr("Test executable crashed."));
|
||||
result->setResult(Result::MessageFatal);
|
||||
m_futureInterface.reportResult(result);
|
||||
}
|
||||
|
||||
void TestOutputReader::reportResult(const TestResultPtr &result)
|
||||
{
|
||||
m_futureInterface.reportResult(result);
|
||||
|
@@ -44,11 +44,14 @@ public:
|
||||
|
||||
virtual void processOutput(const QByteArray &outputLine) = 0;
|
||||
virtual void processStdError(const QByteArray &output);
|
||||
void reportCrash();
|
||||
bool hadValidOutput() const { return m_hadValidOutput; }
|
||||
|
||||
signals:
|
||||
void newOutputAvailable(const QByteArray &output);
|
||||
protected:
|
||||
virtual TestResultPtr createDefaultResult() const = 0;
|
||||
|
||||
void reportResult(const TestResultPtr &result);
|
||||
QFutureInterface<TestResultPtr> m_futureInterface;
|
||||
QProcess *m_testApplication; // not owned
|
||||
|
@@ -253,6 +253,7 @@ static void performTestRun(QFutureInterface<TestResultPtr> &futureInterface,
|
||||
+ rcInfo(testConfiguration))));
|
||||
}
|
||||
if (testProcess.exitStatus() == QProcess::CrashExit) {
|
||||
outputReader->reportCrash();
|
||||
futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal,
|
||||
TestRunner::tr("Test for project \"%1\" crashed.")
|
||||
.arg(testConfiguration->displayName()) + processInformation(testProcess)
|
||||
|
@@ -42,6 +42,7 @@ static const char autoScrollKey[] = "AutoScrollResults";
|
||||
static const char filterScanKey[] = "FilterScan";
|
||||
static const char filtersKey[] = "WhiteListFilters";
|
||||
static const char processArgsKey[] = "ProcessArgs";
|
||||
static const char groupSuffix[] = ".group";
|
||||
|
||||
static const int defaultTimeout = 60000;
|
||||
|
||||
@@ -61,9 +62,11 @@ void TestSettings::toSettings(QSettings *s) const
|
||||
s->setValue(processArgsKey, processArgs);
|
||||
s->setValue(filterScanKey, filterScan);
|
||||
s->setValue(filtersKey, whiteListFilters);
|
||||
// store frameworks and their current active state
|
||||
for (const Core::Id &id : frameworks.keys())
|
||||
// store frameworks and their current active and grouping state
|
||||
for (const Core::Id &id : frameworks.keys()) {
|
||||
s->setValue(QLatin1String(id.name()), frameworks.value(id));
|
||||
s->setValue(QLatin1String(id.name().append(groupSuffix)), frameworksGrouping.value(id));
|
||||
}
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
@@ -82,9 +85,14 @@ void TestSettings::fromSettings(QSettings *s)
|
||||
TestFrameworkManager *frameworkManager = TestFrameworkManager::instance();
|
||||
const QList<Core::Id> ®istered = frameworkManager->registeredFrameworkIds();
|
||||
frameworks.clear();
|
||||
frameworksGrouping.clear();
|
||||
for (const Core::Id &id : registered) {
|
||||
// get their active state
|
||||
frameworks.insert(id, s->value(QLatin1String(id.name()),
|
||||
frameworkManager->isActive(id)).toBool());
|
||||
// and whether grouping is enabled
|
||||
frameworksGrouping.insert(id, s->value(QLatin1String(id.name().append(groupSuffix)),
|
||||
frameworkManager->groupingEnabled(id)).toBool());
|
||||
}
|
||||
s->endGroup();
|
||||
}
|
||||
|
@@ -50,6 +50,7 @@ struct TestSettings
|
||||
bool filterScan = false;
|
||||
bool processArgs = false;
|
||||
QHash<Core::Id, bool> frameworks;
|
||||
QHash<Core::Id, bool> frameworksGrouping;
|
||||
QStringList whiteListFilters;
|
||||
};
|
||||
|
||||
|
@@ -164,7 +164,7 @@ TestSettings TestSettingsWidget::settings() const
|
||||
result.autoScroll = m_ui.autoScrollCB->isChecked();
|
||||
result.processArgs = m_ui.processArgsCB->isChecked();
|
||||
result.filterScan = m_ui.filterGroupBox->isChecked();
|
||||
result.frameworks = frameworks();
|
||||
frameworkSettings(result);
|
||||
result.whiteListFilters = filters();
|
||||
return result;
|
||||
}
|
||||
@@ -180,6 +180,11 @@ void TestSettingsWidget::populateFrameworksListWidget(const QHash<Core::Id, bool
|
||||
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable);
|
||||
item->setCheckState(0, frameworks.value(id) ? Qt::Checked : Qt::Unchecked);
|
||||
item->setData(0, Qt::UserRole, id.toSetting());
|
||||
item->setData(1, Qt::CheckStateRole, frameworkManager->groupingEnabled(id) ? Qt::Checked
|
||||
: Qt::Unchecked);
|
||||
item->setToolTip(0, tr("Enable or disable test frameworks to be handled by the AutoTest "
|
||||
"plugin."));
|
||||
item->setToolTip(1, tr("Enable or disable grouping of test cases by folder."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,18 +194,18 @@ void TestSettingsWidget::populateFiltersWidget(const QStringList &filters)
|
||||
new QTreeWidgetItem(m_ui.filterTreeWidget, {filter} );
|
||||
}
|
||||
|
||||
QHash<Core::Id, bool> TestSettingsWidget::frameworks() const
|
||||
void TestSettingsWidget::frameworkSettings(TestSettings &settings) const
|
||||
{
|
||||
QHash<Core::Id, bool> frameworks;
|
||||
const QAbstractItemModel *model = m_ui.frameworkTreeWidget->model();
|
||||
QTC_ASSERT(model, return frameworks);
|
||||
QTC_ASSERT(model, return);
|
||||
const int itemCount = model->rowCount();
|
||||
for (int row = 0; row < itemCount; ++row) {
|
||||
const QModelIndex index = model->index(row, 0);
|
||||
frameworks.insert(Core::Id::fromSetting(index.data(Qt::UserRole)),
|
||||
index.data(Qt::CheckStateRole) == Qt::Checked);
|
||||
QModelIndex idx = model->index(row, 0);
|
||||
const Core::Id id = Core::Id::fromSetting(idx.data(Qt::UserRole));
|
||||
settings.frameworks.insert(id, idx.data(Qt::CheckStateRole) == Qt::Checked);
|
||||
idx = model->index(row, 1);
|
||||
settings.frameworksGrouping.insert(id, idx.data(Qt::CheckStateRole) == Qt::Checked);
|
||||
}
|
||||
return frameworks;
|
||||
}
|
||||
|
||||
QStringList TestSettingsWidget::filters() const
|
||||
@@ -298,13 +303,20 @@ void TestSettingsPage::apply()
|
||||
bool frameworkSyncNecessary = newSettings.frameworks != m_settings->frameworks;
|
||||
bool forceReparse = newSettings.filterScan != m_settings->filterScan ||
|
||||
newSettings.whiteListFilters.toSet() != m_settings->whiteListFilters.toSet();
|
||||
const QList<Core::Id> changedIds = Utils::filtered(newSettings.frameworksGrouping.keys(),
|
||||
[newSettings, this] (const Core::Id &id) {
|
||||
return newSettings.frameworksGrouping[id] != m_settings->frameworksGrouping[id];
|
||||
});
|
||||
*m_settings = newSettings;
|
||||
m_settings->toSettings(Core::ICore::settings());
|
||||
TestFrameworkManager::instance()->activateFrameworksFromSettings(m_settings);
|
||||
TestFrameworkManager *frameworkManager = TestFrameworkManager::instance();
|
||||
frameworkManager->activateFrameworksFromSettings(m_settings);
|
||||
if (frameworkSyncNecessary)
|
||||
TestTreeModel::instance()->syncTestFrameworks();
|
||||
else if (forceReparse)
|
||||
TestTreeModel::instance()->parser()->emitUpdateTestTree();
|
||||
else if (!changedIds.isEmpty())
|
||||
TestTreeModel::instance()->rebuild(changedIds);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -48,7 +48,7 @@ public:
|
||||
private:
|
||||
void populateFrameworksListWidget(const QHash<Core::Id, bool> &frameworks);
|
||||
void populateFiltersWidget(const QStringList &filters);
|
||||
QHash<Core::Id, bool> frameworks() const;
|
||||
void frameworkSettings(TestSettings &settings) const;
|
||||
QStringList filters() const;
|
||||
void onFrameworkItemChanged();
|
||||
void onAddFilterClicked();
|
||||
|
@@ -183,12 +183,29 @@ Warning: this is an experimental feature and might lead to failing to execute th
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>150</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Framework</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Selects the test frameworks to be handled by the AutoTest plugin.</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Group</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Enables grouping of test cases.</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <cpptools/cpptoolsreuse.h>
|
||||
#include <texteditor/texteditor.h>
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
#include <QIcon>
|
||||
|
||||
@@ -43,21 +44,31 @@ TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type ty
|
||||
m_filePath(filePath),
|
||||
m_type(type)
|
||||
{
|
||||
m_checked = (m_type == TestCase || m_type == TestFunctionOrSet || m_type == Root)
|
||||
? Qt::Checked : Qt::Unchecked;
|
||||
switch (m_type) {
|
||||
case Root:
|
||||
case GroupNode:
|
||||
case TestCase:
|
||||
case TestFunctionOrSet:
|
||||
m_checked = Qt::Checked;
|
||||
break;
|
||||
default:
|
||||
m_checked = Qt::Unchecked;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static QIcon testTreeIcon(TestTreeItem::Type type)
|
||||
{
|
||||
static QIcon icons[] = {
|
||||
QIcon(),
|
||||
Utils::Icons::OPENFILE.icon(),
|
||||
CPlusPlus::Icons::iconForType(CPlusPlus::Icons::ClassIconType),
|
||||
CPlusPlus::Icons::iconForType(CPlusPlus::Icons::SlotPrivateIconType),
|
||||
QIcon(":/images/data.png")
|
||||
};
|
||||
|
||||
if (int(type) >= int(sizeof icons / sizeof *icons))
|
||||
return icons[2];
|
||||
return icons[3];
|
||||
return icons[type];
|
||||
}
|
||||
|
||||
@@ -76,6 +87,8 @@ QVariant TestTreeItem::data(int /*column*/, int role) const
|
||||
case Qt::CheckStateRole:
|
||||
return QVariant();
|
||||
case LinkRole: {
|
||||
if (m_type == GroupNode)
|
||||
return QVariant();
|
||||
QVariant itemLink;
|
||||
itemLink.setValue(Utils::Link(m_filePath, m_line, m_column));
|
||||
return itemLink;
|
||||
@@ -105,6 +118,7 @@ Qt::ItemFlags TestTreeItem::flags(int /*column*/) const
|
||||
static const Qt::ItemFlags defaultFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
switch (m_type) {
|
||||
case Root:
|
||||
case GroupNode:
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable;
|
||||
case TestCase:
|
||||
return defaultFlags | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable;
|
||||
@@ -164,6 +178,7 @@ void TestTreeItem::setChecked(const Qt::CheckState checkState)
|
||||
break;
|
||||
}
|
||||
case Root:
|
||||
case GroupNode:
|
||||
case TestFunctionOrSet:
|
||||
case TestCase: {
|
||||
Qt::CheckState usedState = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked);
|
||||
@@ -185,6 +200,7 @@ Qt::CheckState TestTreeItem::checked() const
|
||||
{
|
||||
switch (m_type) {
|
||||
case Root:
|
||||
case GroupNode:
|
||||
case TestCase:
|
||||
case TestFunctionOrSet:
|
||||
case TestDataTag:
|
||||
@@ -268,6 +284,9 @@ bool TestTreeItem::lessThan(const TestTreeItem *other, SortMode mode) const
|
||||
return index().row() > other->index().row();
|
||||
return lhs > rhs;
|
||||
case Naturally: {
|
||||
if (m_type == GroupNode && other->type() == GroupNode)
|
||||
return m_filePath > other->filePath();
|
||||
|
||||
const Utils::Link &leftLink = data(0, LinkRole).value<Utils::Link>();
|
||||
const Utils::Link &rightLink = other->data(0, LinkRole).value<Utils::Link>();
|
||||
if (leftLink.targetFileName == rightLink.targetFileName) {
|
||||
@@ -282,6 +301,16 @@ bool TestTreeItem::lessThan(const TestTreeItem *other, SortMode mode) const
|
||||
}
|
||||
}
|
||||
|
||||
bool TestTreeItem::isGroupNodeFor(const TestTreeItem *other) const
|
||||
{
|
||||
QTC_ASSERT(other, return false);
|
||||
if (type() != TestTreeItem::GroupNode)
|
||||
return false;
|
||||
|
||||
// for now there's only the possibility to have 'Folder' nodes
|
||||
return QFileInfo(other->filePath()).absolutePath() == filePath();
|
||||
}
|
||||
|
||||
QSet<QString> TestTreeItem::internalTargets() const
|
||||
{
|
||||
auto cppMM = CppTools::CppModelManager::instance();
|
||||
@@ -301,7 +330,7 @@ QSet<QString> TestTreeItem::internalTargets() const
|
||||
void TestTreeItem::revalidateCheckState()
|
||||
{
|
||||
const Type ttiType = type();
|
||||
if (ttiType != TestCase && ttiType != TestFunctionOrSet && ttiType != Root)
|
||||
if (ttiType != TestCase && ttiType != TestFunctionOrSet && ttiType != Root && ttiType != GroupNode)
|
||||
return;
|
||||
if (childCount() == 0) // can this happen? (we're calling revalidateCS() on parentItem()
|
||||
return;
|
||||
@@ -323,13 +352,13 @@ void TestTreeItem::revalidateCheckState()
|
||||
foundPartiallyChecked |= (child->checked() == Qt::PartiallyChecked);
|
||||
if (foundPartiallyChecked || (foundChecked && foundUnchecked)) {
|
||||
m_checked = Qt::PartiallyChecked;
|
||||
if (ttiType == TestFunctionOrSet || ttiType == TestCase)
|
||||
if (ttiType == TestFunctionOrSet || ttiType == TestCase || ttiType == GroupNode)
|
||||
parentItem()->revalidateCheckState();
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_checked = (foundUnchecked ? Qt::Unchecked : Qt::Checked);
|
||||
if (ttiType == TestFunctionOrSet || ttiType == TestCase)
|
||||
if (ttiType == TestFunctionOrSet || ttiType == TestCase || ttiType == GroupNode)
|
||||
parentItem()->revalidateCheckState();
|
||||
}
|
||||
|
||||
|
@@ -55,6 +55,7 @@ public:
|
||||
enum Type
|
||||
{
|
||||
Root,
|
||||
GroupNode,
|
||||
TestCase,
|
||||
TestFunctionOrSet,
|
||||
TestDataTag,
|
||||
@@ -112,7 +113,8 @@ public:
|
||||
virtual bool lessThan(const TestTreeItem *other, SortMode mode) const;
|
||||
virtual TestTreeItem *find(const TestParseResult *result) = 0;
|
||||
virtual bool modify(const TestParseResult *result) = 0;
|
||||
|
||||
virtual bool isGroupNodeFor(const TestTreeItem *other) const;
|
||||
virtual TestTreeItem *createParentGroupNode() const = 0;
|
||||
virtual QSet<QString> internalTargets() const;
|
||||
protected:
|
||||
typedef std::function<bool(const TestTreeItem *)> CompareFunction;
|
||||
|
@@ -73,12 +73,11 @@ TestTreeModel::~TestTreeModel()
|
||||
|
||||
void TestTreeModel::setupParsingConnections()
|
||||
{
|
||||
if (!m_connectionsInitialized)
|
||||
m_parser->setDirty();
|
||||
|
||||
m_parser->setState(TestCodeParser::Idle);
|
||||
if (m_connectionsInitialized)
|
||||
static bool connectionsInitialized = false;
|
||||
if (connectionsInitialized)
|
||||
return;
|
||||
m_parser->setDirty();
|
||||
m_parser->setState(TestCodeParser::Idle);
|
||||
|
||||
ProjectExplorer::SessionManager *sm = ProjectExplorer::SessionManager::instance();
|
||||
connect(sm, &ProjectExplorer::SessionManager::startupProjectChanged,
|
||||
@@ -97,7 +96,7 @@ void TestTreeModel::setupParsingConnections()
|
||||
m_parser, &TestCodeParser::onQmlDocumentUpdated, Qt::QueuedConnection);
|
||||
connect(qmlJsMM, &QmlJS::ModelManagerInterface::aboutToRemoveFiles,
|
||||
this, &TestTreeModel::removeFiles, Qt::QueuedConnection);
|
||||
m_connectionsInitialized = true;
|
||||
connectionsInitialized = true;
|
||||
}
|
||||
|
||||
bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
@@ -111,6 +110,7 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int
|
||||
if (role == Qt::CheckStateRole) {
|
||||
switch (item->type()) {
|
||||
case TestTreeItem::Root:
|
||||
case TestTreeItem::GroupNode:
|
||||
case TestTreeItem::TestCase:
|
||||
if (item->childCount() > 0)
|
||||
emit dataChanged(index.child(0, 0), index.child(item->childCount() - 1, 0));
|
||||
@@ -175,6 +175,31 @@ void TestTreeModel::syncTestFrameworks()
|
||||
emit updatedActiveFrameworks(sortedIds.size());
|
||||
}
|
||||
|
||||
void TestTreeModel::rebuild(const QList<Core::Id> &frameworkIds)
|
||||
{
|
||||
TestFrameworkManager *frameworkManager = TestFrameworkManager::instance();
|
||||
for (const Core::Id &id : frameworkIds) {
|
||||
TestTreeItem *frameworkRoot = frameworkManager->rootNodeForTestFramework(id);
|
||||
const bool groupingEnabled = TestFrameworkManager::instance()->groupingEnabled(id);
|
||||
for (int row = frameworkRoot->childCount() - 1; row >= 0; --row) {
|
||||
auto testItem = frameworkRoot->childItem(row);
|
||||
if (!groupingEnabled && testItem->type() == TestTreeItem::GroupNode) {
|
||||
// do not re-insert the GroupNode, but process its children and delete it afterwards
|
||||
for (int childRow = testItem->childCount() - 1; childRow >= 0; --childRow) {
|
||||
// FIXME should this be done recursively until we have a non-GroupNode?
|
||||
TestTreeItem *childTestItem = testItem->childItem(childRow);
|
||||
takeItem(childTestItem);
|
||||
insertItemInParent(childTestItem, frameworkRoot, groupingEnabled);
|
||||
}
|
||||
delete takeItem(testItem);
|
||||
} else {
|
||||
takeItem(testItem);
|
||||
insertItemInParent(testItem, frameworkRoot, groupingEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TestTreeModel::removeFiles(const QStringList &files)
|
||||
{
|
||||
for (const QString &file : files)
|
||||
@@ -240,6 +265,24 @@ bool TestTreeModel::sweepChildren(TestTreeItem *item)
|
||||
return hasChanged;
|
||||
}
|
||||
|
||||
void TestTreeModel::insertItemInParent(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled)
|
||||
{
|
||||
TestTreeItem *parentNode = root;
|
||||
if (groupingEnabled) {
|
||||
parentNode = root->findChildBy([item] (const TestTreeItem *it) {
|
||||
return it->isGroupNodeFor(item);
|
||||
});
|
||||
if (!parentNode) {
|
||||
parentNode = item->createParentGroupNode();
|
||||
if (!parentNode) // we might not get a group node at all
|
||||
parentNode = root;
|
||||
else
|
||||
root->appendChild(parentNode);
|
||||
}
|
||||
}
|
||||
parentNode->appendChild(item);
|
||||
}
|
||||
|
||||
void TestTreeModel::onParseResultReady(const TestParseResultPtr result)
|
||||
{
|
||||
TestTreeItem *rootNode
|
||||
@@ -250,10 +293,19 @@ void TestTreeModel::onParseResultReady(const TestParseResultPtr result)
|
||||
|
||||
void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeItem *parentNode)
|
||||
{
|
||||
const bool groupingEnabled =
|
||||
TestFrameworkManager::instance()->groupingEnabled(result->frameworkId);
|
||||
// lookup existing items
|
||||
if (TestTreeItem *toBeModified = parentNode->find(result)) {
|
||||
// found existing item... Do not remove
|
||||
toBeModified->markForRemoval(false);
|
||||
// if it's a reparse we need to mark the group node as well to avoid purging it in sweep()
|
||||
if (groupingEnabled) {
|
||||
if (auto directParent = toBeModified->parentItem()) {
|
||||
if (directParent->type() == TestTreeItem::GroupNode)
|
||||
directParent->markForRemoval(false);
|
||||
}
|
||||
}
|
||||
// modify and when content has changed inform ui
|
||||
if (toBeModified->modify(result)) {
|
||||
const QModelIndex &idx = indexForItem(toBeModified);
|
||||
@@ -267,7 +319,8 @@ void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeIte
|
||||
// if there's no matching item, add the new one
|
||||
TestTreeItem *newItem = result->createTestTreeItem();
|
||||
QTC_ASSERT(newItem, return);
|
||||
parentNode->appendChild(newItem);
|
||||
|
||||
insertItemInParent(newItem, parentNode, groupingEnabled);
|
||||
// new items are checked by default - revalidation of parents might be necessary
|
||||
if (parentNode->checked() != Qt::Checked) {
|
||||
parentNode->revalidateCheckState();
|
||||
|
@@ -56,6 +56,7 @@ public:
|
||||
QList<TestConfiguration *> getSelectedTests() const;
|
||||
|
||||
void syncTestFrameworks();
|
||||
void rebuild(const QList<Core::Id> &frameworkIds);
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
int autoTestsCount() const;
|
||||
@@ -86,12 +87,12 @@ private:
|
||||
void removeTestRootNodes();
|
||||
void removeFiles(const QStringList &files);
|
||||
bool sweepChildren(TestTreeItem *item);
|
||||
static void insertItemInParent(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled);
|
||||
|
||||
explicit TestTreeModel(QObject *parent = 0);
|
||||
void setupParsingConnections();
|
||||
|
||||
TestCodeParser *m_parser;
|
||||
bool m_connectionsInitialized = false;
|
||||
};
|
||||
|
||||
class TestTreeSortFilterModel : public QSortFilterProxyModel
|
||||
|
@@ -274,13 +274,20 @@ void CdbEngine::init()
|
||||
|
||||
// Create local list of mappings in native separators
|
||||
m_sourcePathMappings.clear();
|
||||
const QString &packageSources = runParameters().qtPackageSourceLocation;
|
||||
if (!packageSources.isEmpty()) {
|
||||
for (const QString &buildPath : qtBuildPaths()) {
|
||||
m_sourcePathMappings.push_back({QDir::toNativeSeparators(buildPath),
|
||||
QDir::toNativeSeparators(packageSources)});
|
||||
}
|
||||
}
|
||||
|
||||
const QSharedPointer<GlobalDebuggerOptions> globalOptions = Internal::globalDebuggerOptions();
|
||||
SourcePathMap sourcePathMap = globalOptions->sourcePathMap;
|
||||
if (!sourcePathMap.isEmpty()) {
|
||||
m_sourcePathMappings.reserve(sourcePathMap.size());
|
||||
for (auto it = sourcePathMap.constBegin(), cend = sourcePathMap.constEnd(); it != cend; ++it) {
|
||||
m_sourcePathMappings.push_back(SourcePathMapping(QDir::toNativeSeparators(it.key()),
|
||||
QDir::toNativeSeparators(it.value())));
|
||||
m_sourcePathMappings.push_back({QDir::toNativeSeparators(it.key()),
|
||||
QDir::toNativeSeparators(it.value())});
|
||||
}
|
||||
}
|
||||
// update source path maps from debugger start params
|
||||
|
@@ -121,5 +121,8 @@ QAction *addAction(QMenu *menu, const QString &d1, const QString &d2, bool on,
|
||||
QAction *addCheckableAction(QMenu *menu, const QString &display, bool on, bool checked,
|
||||
const std::function<void()> &onTriggered);
|
||||
|
||||
// Qt's various build paths for unpatched versions
|
||||
QStringList qtBuildPaths();
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
@@ -139,6 +139,7 @@ public:
|
||||
QString startMessage; // First status message shown.
|
||||
QString debugInfoLocation; // Gdb "set-debug-file-directory".
|
||||
QStringList debugSourceLocation; // Gdb "directory"
|
||||
QString qtPackageSourceLocation;
|
||||
bool isSnapshot = false; // Set if created internally.
|
||||
ProjectExplorer::Abi toolChainAbi;
|
||||
|
||||
|
@@ -830,6 +830,9 @@ DebuggerRunTool::DebuggerRunTool(RunControl *runControl, Kit *kit, bool allowTer
|
||||
m_runParameters.macroExpander = kit->macroExpander();
|
||||
m_runParameters.debugger = DebuggerKitInformation::runnable(kit);
|
||||
|
||||
if (QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(kit))
|
||||
m_runParameters.qtPackageSourceLocation = qtVersion->qtPackageSourcePath().toString();
|
||||
|
||||
if (auto aspect = runConfig ? runConfig->extraAspect<DebuggerRunConfigurationAspect>() : nullptr) {
|
||||
m_runParameters.isCppDebugging = aspect->useCppDebugger();
|
||||
m_runParameters.isQmlDebugging = aspect->useQmlDebugger();
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include <utils/pathchooser.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QTreeView>
|
||||
@@ -44,20 +45,6 @@
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
// Qt's various build paths for unpatched versions.
|
||||
#if defined(Q_OS_WIN)
|
||||
static const char* qtBuildPaths[] = {
|
||||
"Q:/qt5_workdir/w/s",
|
||||
"C:/work/build/qt5_workdir/w/s",
|
||||
"c:/users/qt/work/qt",
|
||||
"c:/Users/qt/work/install"
|
||||
};
|
||||
#elif defined(Q_OS_MAC)
|
||||
static const char* qtBuildPaths[] = {};
|
||||
#else
|
||||
static const char* qtBuildPaths[] = {"/var/tmp/qt-src"};
|
||||
#endif
|
||||
|
||||
enum { SourceColumn, TargetColumn, ColumnCount };
|
||||
|
||||
namespace Debugger {
|
||||
@@ -66,6 +53,19 @@ namespace Internal {
|
||||
typedef QPair<QString, QString> Mapping;
|
||||
typedef DebuggerSourcePathMappingWidget::SourcePathMap SourcePathMap;
|
||||
|
||||
// Qt's various build paths for unpatched versions.
|
||||
QStringList qtBuildPaths()
|
||||
{
|
||||
if (HostOsInfo::isWindowsHost()) {
|
||||
return {"Q:/qt5_workdir/w/s",
|
||||
"C:/work/build/qt5_workdir/w/s",
|
||||
"c:/users/qt/work/qt",
|
||||
"c:/Users/qt/work/install"};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\class Debugger::Internal::SourcePathMappingModel
|
||||
|
||||
@@ -232,7 +232,7 @@ DebuggerSourcePathMappingWidget::DebuggerSourcePathMappingWidget(QWidget *parent
|
||||
auto buttonLayout = new QVBoxLayout;
|
||||
buttonLayout->addWidget(m_addButton);
|
||||
buttonLayout->addWidget(m_addQtButton);
|
||||
m_addQtButton->setVisible(sizeof(qtBuildPaths) > 0);
|
||||
m_addQtButton->setVisible(!qtBuildPaths().isEmpty());
|
||||
m_addQtButton->setToolTip(tr("<p>Add a mapping for Qt's source folders "
|
||||
"when using an unpatched version of Qt."));
|
||||
buttonLayout->addWidget(m_removeButton);
|
||||
@@ -364,13 +364,11 @@ void DebuggerSourcePathMappingWidget::slotAdd()
|
||||
void DebuggerSourcePathMappingWidget::slotAddQt()
|
||||
{
|
||||
// Add a mapping for various Qt build locations in case of unpatched builds.
|
||||
const QString qtSourcesPath =
|
||||
QFileDialog::getExistingDirectory(this, tr("Qt Sources"));
|
||||
const QString qtSourcesPath = QFileDialog::getExistingDirectory(this, tr("Qt Sources"));
|
||||
if (qtSourcesPath.isEmpty())
|
||||
return;
|
||||
const size_t buildPathCount = sizeof(qtBuildPaths)/sizeof(qtBuildPaths[0]);
|
||||
for (size_t i = 0; i != buildPathCount; ++i) // use != to avoid 0<0 which triggers warning on Mac
|
||||
m_model->addMapping(QString::fromLatin1(qtBuildPaths[i]), qtSourcesPath);
|
||||
for (const QString &buildPath : qtBuildPaths())
|
||||
m_model->addMapping(buildPath, qtSourcesPath);
|
||||
resizeColumns();
|
||||
setCurrentRow(m_model->rowCount() - 1);
|
||||
}
|
||||
@@ -446,13 +444,11 @@ DebuggerSourcePathMappingWidget::SourcePathMap
|
||||
// The profile could also get a function to extract the required information from
|
||||
// its information to avoid this dependency (as we do for the environment).
|
||||
const QString qtInstallPath = findQtInstallPath(qmake);
|
||||
SourcePathMap rc = in;
|
||||
const size_t buildPathCount = sizeof(qtBuildPaths)/sizeof(const char *);
|
||||
if (qtInstallPath.isEmpty() || buildPathCount == 0)
|
||||
return rc;
|
||||
if (qtInstallPath.isEmpty())
|
||||
return in;
|
||||
|
||||
for (size_t i = 0; i != buildPathCount; ++i) { // use != to avoid 0<0 which triggers warning on Mac
|
||||
const QString buildPath = QString::fromLatin1(qtBuildPaths[i]);
|
||||
SourcePathMap rc = in;
|
||||
for (const QString &buildPath : qtBuildPaths()) {
|
||||
if (!rc.contains(buildPath)) // Do not overwrite user settings.
|
||||
rc.insert(buildPath, qtInstallPath);
|
||||
}
|
||||
|
@@ -267,7 +267,7 @@ QVariantMap IosRunConfiguration::toMap() const
|
||||
|
||||
QString IosRunConfiguration::buildSystemTarget() const
|
||||
{
|
||||
return static_cast<QmakeProject *>(target()->project())->mapProFilePathToTarget(m_profilePath);
|
||||
return m_profilePath.toString();
|
||||
}
|
||||
|
||||
QString IosRunConfiguration::disabledReason() const
|
||||
|
@@ -153,11 +153,6 @@ DeployConfigurationFactory::~DeployConfigurationFactory()
|
||||
g_deployConfigurationFactories.removeOne(this);
|
||||
}
|
||||
|
||||
QList<DeployConfigurationFactory *> DeployConfigurationFactory::allDeployConfigurationFactories()
|
||||
{
|
||||
return g_deployConfigurationFactories;
|
||||
}
|
||||
|
||||
QList<Core::Id> DeployConfigurationFactory::availableCreationIds(Target *parent) const
|
||||
{
|
||||
if (!canHandle(parent))
|
||||
|
@@ -80,8 +80,6 @@ public:
|
||||
DeployConfigurationFactory();
|
||||
~DeployConfigurationFactory();
|
||||
|
||||
static QList<DeployConfigurationFactory *> allDeployConfigurationFactories();
|
||||
|
||||
// used to show the list of possible additons to a target, returns a list of types
|
||||
QList<Core::Id> availableCreationIds(Target *parent) const;
|
||||
// used to translate the types to names to display to the user
|
||||
|
@@ -128,11 +128,6 @@ Core::Id ProjectExplorer::idFromMap(const QVariantMap &map)
|
||||
return Core::Id::fromSetting(map.value(QLatin1String(CONFIGURATION_ID_KEY)));
|
||||
}
|
||||
|
||||
QString ProjectExplorer::displayNameFromMap(const QVariantMap &map)
|
||||
{
|
||||
return map.value(QLatin1String(DISPLAY_NAME_KEY), QString()).toString();
|
||||
}
|
||||
|
||||
bool StatefulProjectConfiguration::isEnabled() const
|
||||
{
|
||||
return m_isEnabled;
|
||||
|
@@ -112,8 +112,7 @@ private:
|
||||
bool m_isEnabled = false;
|
||||
};
|
||||
|
||||
// helper functions:
|
||||
// helper function:
|
||||
PROJECTEXPLORER_EXPORT Core::Id idFromMap(const QVariantMap &map);
|
||||
PROJECTEXPLORER_EXPORT QString displayNameFromMap(const QVariantMap &map);
|
||||
|
||||
} // namespace ProjectExplorer
|
||||
|
@@ -2036,8 +2036,6 @@ void ProjectExplorerPluginPrivate::executeRunConfiguration(RunConfiguration *run
|
||||
return;
|
||||
}
|
||||
|
||||
emit m_instance->aboutToExecuteProject(runConfiguration->target()->project(), runMode);
|
||||
|
||||
startRunControl(runControl);
|
||||
}
|
||||
|
||||
|
@@ -170,7 +170,6 @@ signals:
|
||||
// or the file list of a specific project has changed.
|
||||
void fileListChanged();
|
||||
|
||||
void aboutToExecuteProject(ProjectExplorer::Project *project, Core::Id runMode);
|
||||
void recentProjectsChanged();
|
||||
|
||||
void settingsChanged();
|
||||
@@ -234,10 +233,10 @@ private slots:
|
||||
void testToolChainManager_data();
|
||||
void testToolChainManager();
|
||||
|
||||
void testUserFileAccessor_prepareSettings();
|
||||
void testUserFileAccessor_prepareSettingsObsoleteVersion();
|
||||
void testUserFileAccessor_prepareSettingsObsoleteVersionNewVersion();
|
||||
void testUserFileAccessor_prepareToSaveSettings();
|
||||
void testUserFileAccessor_prepareToReadSettings();
|
||||
void testUserFileAccessor_prepareToReadSettingsObsoleteVersion();
|
||||
void testUserFileAccessor_prepareToReadSettingsObsoleteVersionNewVersion();
|
||||
void testUserFileAccessor_prepareToWriteSettings();
|
||||
void testUserFileAccessor_mergeSettings();
|
||||
void testUserFileAccessor_mergeSettingsEmptyUser();
|
||||
void testUserFileAccessor_mergeSettingsEmptyShared();
|
||||
|
@@ -262,9 +262,6 @@ void Target::addDeployConfiguration(DeployConfiguration *dc)
|
||||
QTC_ASSERT(dc && !d->m_deployConfigurations.contains(dc), return);
|
||||
Q_ASSERT(dc->target() == this);
|
||||
|
||||
if (DeployConfigurationFactory::allDeployConfigurationFactories().isEmpty())
|
||||
return;
|
||||
|
||||
// Check that we don't have a configuration with the same displayName
|
||||
QString configurationDisplayName = dc->displayName();
|
||||
QStringList displayNames = Utils::transform(d->m_deployConfigurations, &DeployConfiguration::displayName);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user