forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.9'
Change-Id: I966cfc1c63ccfdccb124edb44574fec1ecc5ad23
This commit is contained in:
@@ -254,5 +254,23 @@
|
|||||||
<string>@SHORT_VERSION@</string>
|
<string>@SHORT_VERSION@</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>@MACOSX_DEPLOYMENT_TARGET@</string>
|
<string>@MACOSX_DEPLOYMENT_TARGET@</string>
|
||||||
</dict>
|
<key>NSAppleEventsUsageDescription</key>
|
||||||
</plist>
|
<string>This application wants to run AppleScript.</string>
|
||||||
|
<key>NSBluetoothPeripheralUsageDescription</key>
|
||||||
|
<string>A user application wants to access bluetooth.</string>
|
||||||
|
<key>NSCalendarsUsageDescription</key>
|
||||||
|
<string>A user application wants to access calendars.</string>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>A user application wants to access the camera.</string>
|
||||||
|
<key>NSContactsUsageDescription</key>
|
||||||
|
<string>A user application wants to access contacts.</string>
|
||||||
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
|
<string>A user application wants to access location information.</string>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>A user application wants to access the microphone.</string>
|
||||||
|
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||||
|
<string>A user application wants write access to the photo library.</string>
|
||||||
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
|
<string>A user application wants to access the photo library.</string>
|
||||||
|
<key>NSRemindersUsageDescription</key>
|
||||||
|
<string>A user application wants to access the reminders.</string>
|
||||||
|
@@ -182,6 +182,13 @@ public:
|
|||||||
{
|
{
|
||||||
CompilerMacros macros = compilerMacros;
|
CompilerMacros macros = compilerMacros;
|
||||||
|
|
||||||
|
macros.erase(std::remove_if(macros.begin(),
|
||||||
|
macros.end(),
|
||||||
|
[](const auto ¯o) {
|
||||||
|
return macro.type == CompilerMacroType::NotDefined;
|
||||||
|
}),
|
||||||
|
macros.end());
|
||||||
|
|
||||||
std::sort(macros.begin(),
|
std::sort(macros.begin(),
|
||||||
macros.end(),
|
macros.end(),
|
||||||
[](const CompilerMacro &first, const CompilerMacro &second) {
|
[](const CompilerMacro &first, const CompilerMacro &second) {
|
||||||
@@ -263,7 +270,7 @@ public:
|
|||||||
void addNoStdIncAndNoStdLibInc()
|
void addNoStdIncAndNoStdLibInc()
|
||||||
{
|
{
|
||||||
commandLine.emplace_back("-nostdinc");
|
commandLine.emplace_back("-nostdinc");
|
||||||
commandLine.emplace_back("-nostdlibinc");
|
commandLine.emplace_back("-nostdinc++");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
enum class CompilerMacroType : unsigned char { Define, NotDefined };
|
||||||
|
|
||||||
class CompilerMacro
|
class CompilerMacro
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -40,39 +42,57 @@ public:
|
|||||||
: key(std::move(key))
|
: key(std::move(key))
|
||||||
, value(std::move(value))
|
, value(std::move(value))
|
||||||
, index(index)
|
, index(index)
|
||||||
|
, type(CompilerMacroType::Define)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CompilerMacro(Utils::SmallString &&key)
|
||||||
|
: key(std::move(key))
|
||||||
|
{}
|
||||||
|
|
||||||
|
CompilerMacro(const Utils::SmallString &key)
|
||||||
|
: key(key)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
friend QDataStream &operator<<(QDataStream &out, const CompilerMacro &compilerMacro)
|
friend QDataStream &operator<<(QDataStream &out, const CompilerMacro &compilerMacro)
|
||||||
{
|
{
|
||||||
out << compilerMacro.key;
|
out << compilerMacro.key;
|
||||||
out << compilerMacro.value;
|
out << compilerMacro.value;
|
||||||
|
out << compilerMacro.index;
|
||||||
|
out << static_cast<unsigned char>(compilerMacro.type);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend QDataStream &operator>>(QDataStream &in, CompilerMacro &compilerMacro)
|
friend QDataStream &operator>>(QDataStream &in, CompilerMacro &compilerMacro)
|
||||||
{
|
{
|
||||||
|
unsigned char type;
|
||||||
|
|
||||||
in >> compilerMacro.key;
|
in >> compilerMacro.key;
|
||||||
in >> compilerMacro.value;
|
in >> compilerMacro.value;
|
||||||
|
in >> compilerMacro.index;
|
||||||
|
in >> type;
|
||||||
|
|
||||||
|
compilerMacro.type = static_cast<CompilerMacroType>(type);
|
||||||
|
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator==(const CompilerMacro &first, const CompilerMacro &second)
|
friend bool operator==(const CompilerMacro &first, const CompilerMacro &second)
|
||||||
{
|
{
|
||||||
return first.key == second.key
|
return first.key == second.key && first.value == second.value && first.type == second.type;
|
||||||
&& first.value == second.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator<(const CompilerMacro &first, const CompilerMacro &second)
|
friend bool operator<(const CompilerMacro &first, const CompilerMacro &second)
|
||||||
{
|
{
|
||||||
return std::tie(first.key, first.value) < std::tie(second.key, second.value);
|
return std::tie(first.key, first.type, first.value)
|
||||||
|
< std::tie(second.key, second.type, second.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Utils::SmallString key;
|
Utils::SmallString key;
|
||||||
Utils::SmallString value;
|
Utils::SmallString value;
|
||||||
int index = 0;
|
int index = -1;
|
||||||
|
CompilerMacroType type = CompilerMacroType::NotDefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
using CompilerMacros = std::vector<CompilerMacro>;
|
using CompilerMacros = std::vector<CompilerMacro>;
|
||||||
|
@@ -161,5 +161,6 @@ public:
|
|||||||
|
|
||||||
using ProjectPartContainers = std::vector<ProjectPartContainer>;
|
using ProjectPartContainers = std::vector<ProjectPartContainer>;
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const ProjectPartContainer &container);
|
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const ProjectPartContainer &container);
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -471,7 +471,9 @@ void TestResultsPane::updateSummaryLabel()
|
|||||||
if (count)
|
if (count)
|
||||||
labelText += ", " + QString::number(count) + ' ' + tr("fatals");
|
labelText += ", " + QString::number(count) + ' ' + tr("fatals");
|
||||||
count = m_model->resultTypeCount(Result::BlacklistedFail)
|
count = m_model->resultTypeCount(Result::BlacklistedFail)
|
||||||
+ m_model->resultTypeCount(Result::BlacklistedPass);
|
+ m_model->resultTypeCount(Result::BlacklistedXFail)
|
||||||
|
+ m_model->resultTypeCount(Result::BlacklistedPass)
|
||||||
|
+ m_model->resultTypeCount(Result::BlacklistedXPass);
|
||||||
if (count)
|
if (count)
|
||||||
labelText += ", " + QString::number(count) + ' ' + tr("blacklisted");
|
labelText += ", " + QString::number(count) + ' ' + tr("blacklisted");
|
||||||
count = m_model->resultTypeCount(Result::Skip);
|
count = m_model->resultTypeCount(Result::Skip);
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <clang/Tooling/Core/Replacement.h>
|
#include <clang/Tooling/Core/Replacement.h>
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/textutils.h>
|
#include <utils/textutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
@@ -57,20 +58,29 @@ static llvm::StringRef clearExtraNewline(llvm::StringRef text)
|
|||||||
static clang::tooling::Replacements filteredReplacements(
|
static clang::tooling::Replacements filteredReplacements(
|
||||||
const clang::tooling::Replacements &replacements,
|
const clang::tooling::Replacements &replacements,
|
||||||
int offset,
|
int offset,
|
||||||
int extraOffsetToAdd,
|
int utf8LineLengthBeforeCursor,
|
||||||
bool onlyIndention)
|
int extraOffsetFromStartOfFile,
|
||||||
|
int extraEmptySpaceOffset,
|
||||||
|
ReplacementsToKeep replacementsToKeep)
|
||||||
{
|
{
|
||||||
clang::tooling::Replacements filtered;
|
clang::tooling::Replacements filtered;
|
||||||
for (const clang::tooling::Replacement &replacement : replacements) {
|
for (const clang::tooling::Replacement &replacement : replacements) {
|
||||||
int replacementOffset = static_cast<int>(replacement.getOffset());
|
int replacementOffset = static_cast<int>(replacement.getOffset());
|
||||||
if (onlyIndention && replacementOffset != offset - 1)
|
const bool replacementDoesNotMatchRestriction
|
||||||
|
= (replacementsToKeep == ReplacementsToKeep::OnlyIndent
|
||||||
|
&& replacementOffset != offset - 1)
|
||||||
|
|| (replacementsToKeep == ReplacementsToKeep::OnlyBeforeIndent
|
||||||
|
&& replacementOffset >= offset + utf8LineLengthBeforeCursor - 1);
|
||||||
|
if (replacementDoesNotMatchRestriction)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (replacementOffset + 1 >= offset)
|
if (replacementOffset >= offset - 1)
|
||||||
replacementOffset += extraOffsetToAdd;
|
replacementOffset += extraEmptySpaceOffset;
|
||||||
|
replacementOffset += extraOffsetFromStartOfFile;
|
||||||
|
|
||||||
llvm::StringRef text = onlyIndention ? clearExtraNewline(replacement.getReplacementText())
|
llvm::StringRef text = replacementsToKeep == ReplacementsToKeep::OnlyIndent
|
||||||
: replacement.getReplacementText();
|
? clearExtraNewline(replacement.getReplacementText())
|
||||||
|
: replacement.getReplacementText();
|
||||||
|
|
||||||
llvm::Error error = filtered.add(
|
llvm::Error error = filtered.add(
|
||||||
clang::tooling::Replacement(replacement.getFilePath(),
|
clang::tooling::Replacement(replacement.getFilePath(),
|
||||||
@@ -78,8 +88,14 @@ static clang::tooling::Replacements filteredReplacements(
|
|||||||
replacement.getLength(),
|
replacement.getLength(),
|
||||||
text));
|
text));
|
||||||
// Throws if error is not checked.
|
// Throws if error is not checked.
|
||||||
if (error)
|
if (error) {
|
||||||
|
error = llvm::handleErrors(std::move(error),
|
||||||
|
[](const llvm::ErrorInfoBase &) -> llvm::Error {
|
||||||
|
return llvm::Error::success();
|
||||||
|
});
|
||||||
|
QTC_CHECK(!error && "Error must be a \"success\" at this point");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
@@ -140,9 +156,16 @@ static int previousEmptyLinesLength(const QTextBlock ¤tBlock)
|
|||||||
static void modifyToIndentEmptyLines(
|
static void modifyToIndentEmptyLines(
|
||||||
QByteArray &buffer, int offset, int &length, const QTextBlock &block, bool secondTry)
|
QByteArray &buffer, int offset, int &length, const QTextBlock &block, bool secondTry)
|
||||||
{
|
{
|
||||||
const QString blockText = block.text().trimmed();
|
const QString blockText = block.text();
|
||||||
const bool closingParenBlock = blockText.startsWith(')');
|
int firstNonWhitespace = Utils::indexOf(blockText,
|
||||||
if (blockText.isEmpty() || closingParenBlock) {
|
[](const QChar &ch) { return !ch.isSpace(); });
|
||||||
|
if (firstNonWhitespace > 0)
|
||||||
|
offset += firstNonWhitespace;
|
||||||
|
|
||||||
|
const bool closingParenBlock = firstNonWhitespace >= 0
|
||||||
|
&& blockText.at(firstNonWhitespace) == ')';
|
||||||
|
|
||||||
|
if (firstNonWhitespace < 0 || closingParenBlock) {
|
||||||
//This extra text works for the most cases.
|
//This extra text works for the most cases.
|
||||||
QByteArray dummyText("a;");
|
QByteArray dummyText("a;");
|
||||||
|
|
||||||
@@ -153,15 +176,8 @@ static void modifyToIndentEmptyLines(
|
|||||||
prevBlock = prevBlock.previous();
|
prevBlock = prevBlock.previous();
|
||||||
prevBlockIsEmpty = prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty();
|
prevBlockIsEmpty = prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty();
|
||||||
}
|
}
|
||||||
if (prevBlock.text().endsWith(','))
|
if (closingParenBlock || prevBlock.text().endsWith(','))
|
||||||
dummyText = "int a";
|
dummyText = "&& a";
|
||||||
|
|
||||||
if (closingParenBlock) {
|
|
||||||
if (prevBlock.text().endsWith(','))
|
|
||||||
dummyText = "int a";
|
|
||||||
else
|
|
||||||
dummyText = "&& a";
|
|
||||||
}
|
|
||||||
|
|
||||||
length += dummyText.length();
|
length += dummyText.length();
|
||||||
buffer.insert(offset, dummyText);
|
buffer.insert(offset, dummyText);
|
||||||
@@ -169,6 +185,9 @@ static void modifyToIndentEmptyLines(
|
|||||||
|
|
||||||
if (secondTry) {
|
if (secondTry) {
|
||||||
int nextLinePos = buffer.indexOf('\n', offset);
|
int nextLinePos = buffer.indexOf('\n', offset);
|
||||||
|
if (nextLinePos < 0)
|
||||||
|
nextLinePos = buffer.size() - 1;
|
||||||
|
|
||||||
if (nextLinePos > 0) {
|
if (nextLinePos > 0) {
|
||||||
// If first try was not successful try to put ')' in the end of the line to close possibly
|
// If first try was not successful try to put ')' in the end of the line to close possibly
|
||||||
// unclosed parentheses.
|
// unclosed parentheses.
|
||||||
@@ -187,7 +206,9 @@ static Utils::LineColumn utf16LineColumn(const QTextBlock &block,
|
|||||||
int utf8Offset)
|
int utf8Offset)
|
||||||
{
|
{
|
||||||
// If lastIndexOf('\n') returns -1 then we are fine to add 1 and get 0 offset.
|
// If lastIndexOf('\n') returns -1 then we are fine to add 1 and get 0 offset.
|
||||||
const int lineStartUtf8Offset = utf8Buffer.lastIndexOf('\n', utf8Offset - 1) + 1;
|
const int lineStartUtf8Offset = utf8Offset == 0
|
||||||
|
? 0
|
||||||
|
: utf8Buffer.lastIndexOf('\n', utf8Offset - 1) + 1;
|
||||||
int line = block.blockNumber() + 1; // Init with the line corresponding the block.
|
int line = block.blockNumber() + 1; // Init with the line corresponding the block.
|
||||||
|
|
||||||
if (utf8Offset < blockOffsetUtf8) {
|
if (utf8Offset < blockOffsetUtf8) {
|
||||||
@@ -299,8 +320,10 @@ void ClangFormatBaseIndenter::indent(const QTextCursor &cursor,
|
|||||||
if (currentBlock.isValid()) {
|
if (currentBlock.isValid()) {
|
||||||
const int blocksAmount = m_doc->blockCount();
|
const int blocksAmount = m_doc->blockCount();
|
||||||
indentBlock(currentBlock, typedChar, cursorPositionInEditor);
|
indentBlock(currentBlock, typedChar, cursorPositionInEditor);
|
||||||
QTC_CHECK(blocksAmount == m_doc->blockCount()
|
|
||||||
&& "ClangFormat plugin indentation changed the amount of blocks.");
|
// Only blocks before current might be added/removed, so it's safe to modify the index.
|
||||||
|
if (blocksAmount != m_doc->blockCount())
|
||||||
|
currentBlockNumber += (m_doc->blockCount() - blocksAmount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -328,24 +351,30 @@ TextEditor::Replacements ClangFormatBaseIndenter::format(const QTextCursor &curs
|
|||||||
{
|
{
|
||||||
int utf8Offset;
|
int utf8Offset;
|
||||||
int utf8Length;
|
int utf8Length;
|
||||||
|
QTextBlock block;
|
||||||
|
|
||||||
const QByteArray buffer = m_doc->toPlainText().toUtf8();
|
const QByteArray buffer = m_doc->toPlainText().toUtf8();
|
||||||
QTextBlock block = cursor.block();
|
|
||||||
if (cursor.hasSelection()) {
|
if (cursor.hasSelection()) {
|
||||||
block = m_doc->findBlock(cursor.selectionStart());
|
block = m_doc->findBlock(cursor.selectionStart());
|
||||||
const QTextBlock end = m_doc->findBlock(cursor.selectionEnd());
|
const QTextBlock end = m_doc->findBlock(cursor.selectionEnd());
|
||||||
utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
||||||
QTC_ASSERT(utf8Offset >= 0, return TextEditor::Replacements(););
|
QTC_ASSERT(utf8Offset >= 0, return TextEditor::Replacements(););
|
||||||
utf8Length = selectedLines(m_doc, block, end).toUtf8().size();
|
utf8Length = selectedLines(m_doc, block, end).toUtf8().size();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const QTextBlock block = cursor.block();
|
block = cursor.block();
|
||||||
utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
||||||
QTC_ASSERT(utf8Offset >= 0, return TextEditor::Replacements(););
|
QTC_ASSERT(utf8Offset >= 0, return TextEditor::Replacements(););
|
||||||
|
|
||||||
utf8Length = block.text().toUtf8().size();
|
utf8Length = block.text().toUtf8().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const TextEditor::Replacements toReplace
|
const TextEditor::Replacements toReplace = replacements(buffer,
|
||||||
= replacements(buffer, utf8Offset, utf8Length, block, QChar::Null, false);
|
utf8Offset,
|
||||||
|
utf8Length,
|
||||||
|
block,
|
||||||
|
cursorPositionInEditor,
|
||||||
|
ReplacementsToKeep::All,
|
||||||
|
QChar::Null);
|
||||||
applyReplacements(block, toReplace);
|
applyReplacements(block, toReplace);
|
||||||
|
|
||||||
return toReplace;
|
return toReplace;
|
||||||
@@ -359,17 +388,62 @@ TextEditor::Replacements ClangFormatBaseIndenter::format(
|
|||||||
return format(cursor, cursorPositionInEditor);
|
return format(cursor, cursorPositionInEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ClangFormatBaseIndenter::indentBeforeCursor(const QTextBlock &block,
|
||||||
|
const QChar &typedChar,
|
||||||
|
int cursorPositionInEditor)
|
||||||
|
{
|
||||||
|
const QByteArray buffer = m_doc->toPlainText().toUtf8();
|
||||||
|
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
||||||
|
QTC_ASSERT(utf8Offset >= 0, return cursorPositionInEditor;);
|
||||||
|
const TextEditor::Replacements toReplace = replacements(buffer,
|
||||||
|
utf8Offset,
|
||||||
|
0,
|
||||||
|
block,
|
||||||
|
cursorPositionInEditor,
|
||||||
|
ReplacementsToKeep::OnlyBeforeIndent,
|
||||||
|
typedChar);
|
||||||
|
applyReplacements(block, toReplace);
|
||||||
|
for (const TextEditor::Replacement &replacement : toReplace)
|
||||||
|
cursorPositionInEditor += replacement.text.length() - replacement.length;
|
||||||
|
return cursorPositionInEditor;
|
||||||
|
}
|
||||||
|
|
||||||
void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
||||||
const QChar &typedChar,
|
const QChar &typedChar,
|
||||||
int /*cursorPositionInEditor*/)
|
int cursorPositionInEditor)
|
||||||
{
|
{
|
||||||
trimFirstNonEmptyBlock(block);
|
QTextBlock currentBlock = block;
|
||||||
trimCurrentBlock(block);
|
const int blockPosition = currentBlock.position();
|
||||||
|
trimFirstNonEmptyBlock(currentBlock);
|
||||||
|
|
||||||
|
if (formatWhileTyping()
|
||||||
|
&& (cursorPositionInEditor == -1 || cursorPositionInEditor >= blockPosition)) {
|
||||||
|
// Format before current position only in case the cursor is inside the indented block.
|
||||||
|
// So if cursor position is less then the block position then the current line is before
|
||||||
|
// the indented block - don't trigger extra formatting in this case.
|
||||||
|
// cursorPositionInEditor == -1 means the consition matches automatically.
|
||||||
|
if (cursorPositionInEditor >= 0)
|
||||||
|
cursorPositionInEditor += currentBlock.position() - blockPosition;
|
||||||
|
else
|
||||||
|
cursorPositionInEditor = currentBlock.position();
|
||||||
|
|
||||||
|
cursorPositionInEditor = indentBeforeCursor(currentBlock, typedChar, cursorPositionInEditor);
|
||||||
|
currentBlock = m_doc->findBlock(cursorPositionInEditor);
|
||||||
|
}
|
||||||
|
|
||||||
|
trimCurrentBlock(currentBlock);
|
||||||
const QByteArray buffer = m_doc->toPlainText().toUtf8();
|
const QByteArray buffer = m_doc->toPlainText().toUtf8();
|
||||||
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
||||||
QTC_ASSERT(utf8Offset >= 0, return;);
|
QTC_ASSERT(utf8Offset >= 0, return;);
|
||||||
|
|
||||||
applyReplacements(block, replacements(buffer, utf8Offset, 0, block, typedChar));
|
applyReplacements(currentBlock,
|
||||||
|
replacements(buffer,
|
||||||
|
utf8Offset,
|
||||||
|
0,
|
||||||
|
currentBlock,
|
||||||
|
cursorPositionInEditor,
|
||||||
|
ReplacementsToKeep::OnlyIndent,
|
||||||
|
typedChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
||||||
@@ -380,7 +454,7 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
|||||||
indentBlock(block, typedChar, cursorPositionInEditor);
|
indentBlock(block, typedChar, cursorPositionInEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int /*cursorPositionInEditor*/)
|
int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int cursorPositionInEditor)
|
||||||
{
|
{
|
||||||
trimFirstNonEmptyBlock(block);
|
trimFirstNonEmptyBlock(block);
|
||||||
trimCurrentBlock(block);
|
trimCurrentBlock(block);
|
||||||
@@ -388,7 +462,12 @@ int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int /*cursorPosi
|
|||||||
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
const int utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
||||||
QTC_ASSERT(utf8Offset >= 0, return 0;);
|
QTC_ASSERT(utf8Offset >= 0, return 0;);
|
||||||
|
|
||||||
const TextEditor::Replacements toReplace = replacements(buffer, utf8Offset, 0, block);
|
const TextEditor::Replacements toReplace = replacements(buffer,
|
||||||
|
utf8Offset,
|
||||||
|
0,
|
||||||
|
block,
|
||||||
|
cursorPositionInEditor,
|
||||||
|
ReplacementsToKeep::OnlyIndent);
|
||||||
|
|
||||||
if (toReplace.empty())
|
if (toReplace.empty())
|
||||||
return -1;
|
return -1;
|
||||||
@@ -447,12 +526,30 @@ clang::format::FormatStyle ClangFormatBaseIndenter::styleForFile() const
|
|||||||
return clang::format::getLLVMStyle();
|
return clang::format::getLLVMStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int formattingRangeStart(const QTextBlock ¤tBlock,
|
||||||
|
const QByteArray &buffer,
|
||||||
|
int documentRevision)
|
||||||
|
{
|
||||||
|
QTextBlock prevBlock = currentBlock.previous();
|
||||||
|
while ((prevBlock.position() > 0 || prevBlock.length() > 0)
|
||||||
|
&& prevBlock.revision() != documentRevision
|
||||||
|
&& (currentBlock.blockNumber() - prevBlock.blockNumber() < kMaxLinesFromCurrentBlock)) {
|
||||||
|
// Find the first block with not matching revision.
|
||||||
|
prevBlock = prevBlock.previous();
|
||||||
|
}
|
||||||
|
if (prevBlock.revision() == documentRevision)
|
||||||
|
prevBlock = prevBlock.next();
|
||||||
|
|
||||||
|
return Utils::Text::utf8NthLineOffset(prevBlock.document(), buffer, prevBlock.blockNumber() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer,
|
TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer,
|
||||||
int utf8Offset,
|
int utf8Offset,
|
||||||
int utf8Length,
|
int utf8Length,
|
||||||
const QTextBlock &block,
|
const QTextBlock &block,
|
||||||
|
int cursorPositionInEditor,
|
||||||
|
ReplacementsToKeep replacementsToKeep,
|
||||||
const QChar &typedChar,
|
const QChar &typedChar,
|
||||||
bool onlyIndention,
|
|
||||||
bool secondTry) const
|
bool secondTry) const
|
||||||
{
|
{
|
||||||
clang::format::FormatStyle style = styleForFile();
|
clang::format::FormatStyle style = styleForFile();
|
||||||
@@ -461,13 +558,22 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
|
|||||||
int originalLengthUtf8 = utf8Length;
|
int originalLengthUtf8 = utf8Length;
|
||||||
QByteArray originalBuffer = buffer;
|
QByteArray originalBuffer = buffer;
|
||||||
|
|
||||||
int extraOffset = 0;
|
int utf8LineLengthBeforeCursor = 0;
|
||||||
if (onlyIndention) {
|
if (cursorPositionInEditor > 0 && typedChar != QChar::Null) {
|
||||||
|
// Format starting with the electric character if it's present.
|
||||||
|
utf8LineLengthBeforeCursor
|
||||||
|
= block.text().left(cursorPositionInEditor - block.position()).toUtf8().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int extraOffsetFromStartOfFile = 0;
|
||||||
|
int extraEmptySpaceOffset = 0;
|
||||||
|
int rangeStart = 0;
|
||||||
|
if (replacementsToKeep != ReplacementsToKeep::All) {
|
||||||
if (block.blockNumber() > kMaxLinesFromCurrentBlock) {
|
if (block.blockNumber() > kMaxLinesFromCurrentBlock) {
|
||||||
extraOffset = Utils::Text::utf8NthLineOffset(block.document(),
|
extraOffsetFromStartOfFile
|
||||||
buffer,
|
= Utils::Text::utf8NthLineOffset(block.document(),
|
||||||
block.blockNumber()
|
buffer,
|
||||||
- kMaxLinesFromCurrentBlock);
|
block.blockNumber() - kMaxLinesFromCurrentBlock);
|
||||||
}
|
}
|
||||||
int endOffset = Utils::Text::utf8NthLineOffset(block.document(),
|
int endOffset = Utils::Text::utf8NthLineOffset(block.document(),
|
||||||
buffer,
|
buffer,
|
||||||
@@ -476,22 +582,30 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
|
|||||||
if (endOffset == -1)
|
if (endOffset == -1)
|
||||||
endOffset = buffer.size();
|
endOffset = buffer.size();
|
||||||
|
|
||||||
buffer = buffer.mid(extraOffset, endOffset - extraOffset);
|
|
||||||
utf8Offset -= extraOffset;
|
|
||||||
|
|
||||||
const int emptySpaceLength = previousEmptyLinesLength(block);
|
if (replacementsToKeep == ReplacementsToKeep::OnlyBeforeIndent)
|
||||||
utf8Offset -= emptySpaceLength;
|
rangeStart = formattingRangeStart(block, buffer, lastSaveRevision());
|
||||||
buffer.remove(utf8Offset, emptySpaceLength);
|
|
||||||
|
|
||||||
extraOffset += emptySpaceLength;
|
buffer = buffer.mid(extraOffsetFromStartOfFile, endOffset - extraOffsetFromStartOfFile);
|
||||||
|
utf8Offset -= extraOffsetFromStartOfFile;
|
||||||
|
rangeStart -= extraOffsetFromStartOfFile;
|
||||||
|
|
||||||
adjustFormatStyleForLineBreak(style);
|
extraEmptySpaceOffset = previousEmptyLinesLength(block);
|
||||||
if (typedChar == QChar::Null)
|
utf8Offset -= extraEmptySpaceOffset;
|
||||||
modifyToIndentEmptyLines(buffer, utf8Offset, utf8Length, block, secondTry);
|
buffer.remove(utf8Offset, extraEmptySpaceOffset);
|
||||||
|
|
||||||
|
if (replacementsToKeep == ReplacementsToKeep::OnlyIndent)
|
||||||
|
adjustFormatStyleForLineBreak(style);
|
||||||
|
modifyToIndentEmptyLines(buffer, utf8Offset, utf8Length, block, secondTry);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<clang::tooling::Range> ranges{
|
if (replacementsToKeep != ReplacementsToKeep::OnlyBeforeIndent || utf8Offset < rangeStart)
|
||||||
{static_cast<unsigned int>(utf8Offset), static_cast<unsigned int>(utf8Length)}};
|
rangeStart = utf8Offset;
|
||||||
|
|
||||||
|
unsigned int rangeLength = static_cast<unsigned int>(utf8Offset + utf8Length - rangeStart);
|
||||||
|
|
||||||
|
std::vector<clang::tooling::Range> ranges{{static_cast<unsigned int>(rangeStart), rangeLength}};
|
||||||
|
|
||||||
clang::format::FormattingAttemptStatus status;
|
clang::format::FormattingAttemptStatus status;
|
||||||
|
|
||||||
clang::tooling::Replacements clangReplacements = reformat(style,
|
clang::tooling::Replacements clangReplacements = reformat(style,
|
||||||
@@ -500,21 +614,25 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
|
|||||||
m_fileName.toString().toStdString(),
|
m_fileName.toString().toStdString(),
|
||||||
&status);
|
&status);
|
||||||
|
|
||||||
if (!status.FormatComplete)
|
clang::tooling::Replacements filtered;
|
||||||
return TextEditor::Replacements();
|
if (status.FormatComplete) {
|
||||||
|
filtered = filteredReplacements(clangReplacements,
|
||||||
const clang::tooling::Replacements filtered = filteredReplacements(clangReplacements,
|
utf8Offset,
|
||||||
utf8Offset,
|
utf8LineLengthBeforeCursor,
|
||||||
extraOffset,
|
extraOffsetFromStartOfFile,
|
||||||
onlyIndention);
|
extraEmptySpaceOffset,
|
||||||
const bool canTryAgain = onlyIndention && typedChar == QChar::Null && !secondTry;
|
replacementsToKeep);
|
||||||
|
}
|
||||||
|
const bool canTryAgain = replacementsToKeep == ReplacementsToKeep::OnlyIndent
|
||||||
|
&& typedChar == QChar::Null && !secondTry;
|
||||||
if (canTryAgain && filtered.empty()) {
|
if (canTryAgain && filtered.empty()) {
|
||||||
return replacements(originalBuffer,
|
return replacements(originalBuffer,
|
||||||
originalOffsetUtf8,
|
originalOffsetUtf8,
|
||||||
originalLengthUtf8,
|
originalLengthUtf8,
|
||||||
block,
|
block,
|
||||||
|
cursorPositionInEditor,
|
||||||
|
replacementsToKeep,
|
||||||
typedChar,
|
typedChar,
|
||||||
onlyIndention,
|
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
namespace ClangFormat {
|
namespace ClangFormat {
|
||||||
|
|
||||||
|
enum class ReplacementsToKeep { OnlyIndent, OnlyBeforeIndent, All };
|
||||||
|
|
||||||
class ClangFormatBaseIndenter : public TextEditor::Indenter
|
class ClangFormatBaseIndenter : public TextEditor::Indenter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -69,18 +71,24 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual clang::format::FormatStyle styleForFile() const;
|
virtual clang::format::FormatStyle styleForFile() const;
|
||||||
virtual bool formatCodeInsteadOfIndent() const { return false; }
|
virtual bool formatCodeInsteadOfIndent() const { return false; }
|
||||||
|
virtual bool formatWhileTyping() const { return false; }
|
||||||
|
virtual int lastSaveRevision() const { return 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextEditor::Replacements format(const QTextCursor &cursor, int cursorPositionInEditor);
|
TextEditor::Replacements format(const QTextCursor &cursor, int cursorPositionInEditor);
|
||||||
void indent(const QTextCursor &cursor, const QChar &typedChar, int cursorPositionInEditor);
|
void indent(const QTextCursor &cursor, const QChar &typedChar, int cursorPositionInEditor);
|
||||||
void indentBlock(const QTextBlock &block, const QChar &typedChar, int cursorPositionInEditor);
|
void indentBlock(const QTextBlock &block, const QChar &typedChar, int cursorPositionInEditor);
|
||||||
int indentFor(const QTextBlock &block, int cursorPositionInEditor);
|
int indentFor(const QTextBlock &block, int cursorPositionInEditor);
|
||||||
|
int indentBeforeCursor(const QTextBlock &block,
|
||||||
|
const QChar &typedChar,
|
||||||
|
int cursorPositionInEditor);
|
||||||
TextEditor::Replacements replacements(QByteArray buffer,
|
TextEditor::Replacements replacements(QByteArray buffer,
|
||||||
int utf8Offset,
|
int utf8Offset,
|
||||||
int utf8Length,
|
int utf8Length,
|
||||||
const QTextBlock &block,
|
const QTextBlock &block,
|
||||||
|
int cursorPositionInEditor,
|
||||||
|
ReplacementsToKeep replacementsToKeep,
|
||||||
const QChar &typedChar = QChar::Null,
|
const QChar &typedChar = QChar::Null,
|
||||||
bool onlyIndention = true,
|
|
||||||
bool secondTry = false) const;
|
bool secondTry = false) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -127,12 +127,31 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *proje
|
|||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangFormatConfigWidget::hideGlobalCheckboxes()
|
||||||
|
{
|
||||||
|
m_ui->formatAlways->hide();
|
||||||
|
m_ui->formatWhileTyping->hide();
|
||||||
|
m_ui->formatOnSave->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangFormatConfigWidget::showGlobalCheckboxes()
|
||||||
|
{
|
||||||
|
m_ui->formatAlways->setChecked(ClangFormatSettings::instance().formatCodeInsteadOfIndent());
|
||||||
|
m_ui->formatAlways->show();
|
||||||
|
|
||||||
|
m_ui->formatWhileTyping->setChecked(ClangFormatSettings::instance().formatWhileTyping());
|
||||||
|
m_ui->formatWhileTyping->show();
|
||||||
|
|
||||||
|
m_ui->formatOnSave->setChecked(ClangFormatSettings::instance().formatOnSave());
|
||||||
|
m_ui->formatOnSave->show();
|
||||||
|
}
|
||||||
|
|
||||||
void ClangFormatConfigWidget::initialize()
|
void ClangFormatConfigWidget::initialize()
|
||||||
{
|
{
|
||||||
m_ui->projectHasClangFormat->show();
|
m_ui->projectHasClangFormat->show();
|
||||||
m_ui->clangFormatOptionsTable->show();
|
m_ui->clangFormatOptionsTable->show();
|
||||||
m_ui->applyButton->show();
|
m_ui->applyButton->show();
|
||||||
m_ui->formatAlways->hide();
|
hideGlobalCheckboxes();
|
||||||
|
|
||||||
QLayoutItem *lastItem = m_ui->verticalLayout->itemAt(m_ui->verticalLayout->count() - 1);
|
QLayoutItem *lastItem = m_ui->verticalLayout->itemAt(m_ui->verticalLayout->count() - 1);
|
||||||
if (lastItem->spacerItem())
|
if (lastItem->spacerItem())
|
||||||
@@ -171,8 +190,7 @@ void ClangFormatConfigWidget::initialize()
|
|||||||
"and can be configured in Projects > Code Style > C++."));
|
"and can be configured in Projects > Code Style > C++."));
|
||||||
}
|
}
|
||||||
createStyleFileIfNeeded(true);
|
createStyleFileIfNeeded(true);
|
||||||
m_ui->formatAlways->setChecked(ClangFormatSettings::instance().formatCodeInsteadOfIndent());
|
showGlobalCheckboxes();
|
||||||
m_ui->formatAlways->show();
|
|
||||||
m_ui->applyButton->hide();
|
m_ui->applyButton->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +204,6 @@ void ClangFormatConfigWidget::fillTable()
|
|||||||
std::string configText = clang::format::configurationAsText(style);
|
std::string configText = clang::format::configurationAsText(style);
|
||||||
std::istringstream stream(configText);
|
std::istringstream stream(configText);
|
||||||
readTable(m_ui->clangFormatOptionsTable, stream);
|
readTable(m_ui->clangFormatOptionsTable, stream);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangFormatConfigWidget::~ClangFormatConfigWidget() = default;
|
ClangFormatConfigWidget::~ClangFormatConfigWidget() = default;
|
||||||
@@ -196,6 +213,8 @@ void ClangFormatConfigWidget::apply()
|
|||||||
if (!m_project) {
|
if (!m_project) {
|
||||||
ClangFormatSettings &settings = ClangFormatSettings::instance();
|
ClangFormatSettings &settings = ClangFormatSettings::instance();
|
||||||
settings.setFormatCodeInsteadOfIndent(m_ui->formatAlways->isChecked());
|
settings.setFormatCodeInsteadOfIndent(m_ui->formatAlways->isChecked());
|
||||||
|
settings.setFormatWhileTyping(m_ui->formatWhileTyping->isChecked());
|
||||||
|
settings.setFormatOnSave(m_ui->formatOnSave->isChecked());
|
||||||
settings.write();
|
settings.write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -51,6 +51,9 @@ private:
|
|||||||
void initialize();
|
void initialize();
|
||||||
void fillTable();
|
void fillTable();
|
||||||
|
|
||||||
|
void hideGlobalCheckboxes();
|
||||||
|
void showGlobalCheckboxes();
|
||||||
|
|
||||||
ProjectExplorer::Project *m_project;
|
ProjectExplorer::Project *m_project;
|
||||||
std::unique_ptr<Ui::ClangFormatConfigWidget> m_ui;
|
std::unique_ptr<Ui::ClangFormatConfigWidget> m_ui;
|
||||||
};
|
};
|
||||||
|
@@ -33,6 +33,20 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="formatWhileTyping">
|
||||||
|
<property name="text">
|
||||||
|
<string>Format while typing</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="formatOnSave">
|
||||||
|
<property name="text">
|
||||||
|
<string>Format edited code on file save</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="projectHasClangFormat">
|
<widget class="QLabel" name="projectHasClangFormat">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@@ -32,5 +32,7 @@ static const char SETTINGS_FILE_ALT_NAME[] = "_clang-format";
|
|||||||
static const char SAMPLE_FILE_NAME[] = "test.cpp";
|
static const char SAMPLE_FILE_NAME[] = "test.cpp";
|
||||||
static const char SETTINGS_ID[] = "ClangFormat";
|
static const char SETTINGS_ID[] = "ClangFormat";
|
||||||
static const char FORMAT_CODE_INSTEAD_OF_INDENT_ID[] = "ClangFormat.FormatCodeInsteadOfIndent";
|
static const char FORMAT_CODE_INSTEAD_OF_INDENT_ID[] = "ClangFormat.FormatCodeInsteadOfIndent";
|
||||||
|
static const char FORMAT_WHILE_TYPING_ID[] = "ClangFormat.FormatWhileTyping";
|
||||||
|
static const char FORMAT_CODE_ON_SAVE_ID[] = "ClangFormat.FormatCodeOnSave";
|
||||||
} // namespace Constants
|
} // namespace Constants
|
||||||
} // namespace ClangFormat
|
} // namespace ClangFormat
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "clangformatutils.h"
|
#include "clangformatutils.h"
|
||||||
|
|
||||||
#include <texteditor/tabsettings.h>
|
#include <texteditor/tabsettings.h>
|
||||||
|
#include <texteditor/textdocumentlayout.h>
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace format;
|
using namespace format;
|
||||||
@@ -49,6 +50,11 @@ bool ClangFormatIndenter::formatCodeInsteadOfIndent() const
|
|||||||
return ClangFormatSettings::instance().formatCodeInsteadOfIndent();
|
return ClangFormatSettings::instance().formatCodeInsteadOfIndent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClangFormatIndenter::formatWhileTyping() const
|
||||||
|
{
|
||||||
|
return ClangFormatSettings::instance().formatWhileTyping();
|
||||||
|
}
|
||||||
|
|
||||||
Utils::optional<TabSettings> ClangFormatIndenter::tabSettings() const
|
Utils::optional<TabSettings> ClangFormatIndenter::tabSettings() const
|
||||||
{
|
{
|
||||||
FormatStyle style = currentProjectStyle();
|
FormatStyle style = currentProjectStyle();
|
||||||
@@ -76,4 +82,14 @@ Utils::optional<TabSettings> ClangFormatIndenter::tabSettings() const
|
|||||||
return tabSettings;
|
return tabSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ClangFormatIndenter::lastSaveRevision() const
|
||||||
|
{
|
||||||
|
return qobject_cast<TextEditor::TextDocumentLayout *>(m_doc->documentLayout())->lastSaveRevision;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClangFormatIndenter::formatOnSave() const
|
||||||
|
{
|
||||||
|
return ClangFormatSettings::instance().formatOnSave();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ClangFormat
|
} // namespace ClangFormat
|
||||||
|
@@ -36,10 +36,13 @@ class ClangFormatIndenter final : public ClangFormatBaseIndenter
|
|||||||
public:
|
public:
|
||||||
ClangFormatIndenter(QTextDocument *doc);
|
ClangFormatIndenter(QTextDocument *doc);
|
||||||
Utils::optional<TextEditor::TabSettings> tabSettings() const override;
|
Utils::optional<TextEditor::TabSettings> tabSettings() const override;
|
||||||
|
bool formatOnSave() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool formatCodeInsteadOfIndent() const override;
|
bool formatCodeInsteadOfIndent() const override;
|
||||||
|
bool formatWhileTyping() const override;
|
||||||
clang::format::FormatStyle styleForFile() const override;
|
clang::format::FormatStyle styleForFile() const override;
|
||||||
|
int lastSaveRevision() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangFormat
|
} // namespace ClangFormat
|
||||||
|
@@ -42,6 +42,10 @@ ClangFormatSettings::ClangFormatSettings()
|
|||||||
settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
|
settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
|
||||||
m_formatCodeInsteadOfIndent
|
m_formatCodeInsteadOfIndent
|
||||||
= settings->value(QLatin1String(Constants::FORMAT_CODE_INSTEAD_OF_INDENT_ID), false).toBool();
|
= settings->value(QLatin1String(Constants::FORMAT_CODE_INSTEAD_OF_INDENT_ID), false).toBool();
|
||||||
|
m_formatWhileTyping = settings->value(QLatin1String(Constants::FORMAT_WHILE_TYPING_ID), false)
|
||||||
|
.toBool();
|
||||||
|
m_formatOnSave = settings->value(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), false)
|
||||||
|
.toBool();
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +55,8 @@ void ClangFormatSettings::write() const
|
|||||||
settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
|
settings->beginGroup(QLatin1String(Constants::SETTINGS_ID));
|
||||||
settings->setValue(QLatin1String(Constants::FORMAT_CODE_INSTEAD_OF_INDENT_ID),
|
settings->setValue(QLatin1String(Constants::FORMAT_CODE_INSTEAD_OF_INDENT_ID),
|
||||||
m_formatCodeInsteadOfIndent);
|
m_formatCodeInsteadOfIndent);
|
||||||
|
settings->setValue(QLatin1String(Constants::FORMAT_WHILE_TYPING_ID), m_formatWhileTyping);
|
||||||
|
settings->setValue(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), m_formatOnSave);
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,4 +70,24 @@ bool ClangFormatSettings::formatCodeInsteadOfIndent() const
|
|||||||
return m_formatCodeInsteadOfIndent;
|
return m_formatCodeInsteadOfIndent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangFormatSettings::setFormatWhileTyping(bool enable)
|
||||||
|
{
|
||||||
|
m_formatWhileTyping = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClangFormatSettings::formatWhileTyping() const
|
||||||
|
{
|
||||||
|
return m_formatWhileTyping;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangFormatSettings::setFormatOnSave(bool enable)
|
||||||
|
{
|
||||||
|
m_formatOnSave = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClangFormatSettings::formatOnSave() const
|
||||||
|
{
|
||||||
|
return m_formatOnSave;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ClangFormat
|
} // namespace ClangFormat
|
||||||
|
@@ -37,8 +37,16 @@ public:
|
|||||||
|
|
||||||
void setFormatCodeInsteadOfIndent(bool enable);
|
void setFormatCodeInsteadOfIndent(bool enable);
|
||||||
bool formatCodeInsteadOfIndent() const;
|
bool formatCodeInsteadOfIndent() const;
|
||||||
|
|
||||||
|
void setFormatWhileTyping(bool enable);
|
||||||
|
bool formatWhileTyping() const;
|
||||||
|
|
||||||
|
void setFormatOnSave(bool enable);
|
||||||
|
bool formatOnSave() const;
|
||||||
private:
|
private:
|
||||||
bool m_formatCodeInsteadOfIndent = false;
|
bool m_formatCodeInsteadOfIndent = false;
|
||||||
|
bool m_formatWhileTyping = false;
|
||||||
|
bool m_formatOnSave = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangFormat
|
} // namespace ClangFormat
|
||||||
|
@@ -152,35 +152,38 @@ void DiagnosticView::goBack()
|
|||||||
|
|
||||||
QModelIndex DiagnosticView::getIndex(const QModelIndex &index, Direction direction) const
|
QModelIndex DiagnosticView::getIndex(const QModelIndex &index, Direction direction) const
|
||||||
{
|
{
|
||||||
QModelIndex parentIndex = index.parent();
|
const QModelIndex parentIndex = index.parent();
|
||||||
|
QModelIndex followingTopIndex = index;
|
||||||
|
|
||||||
// Use direct sibling for level 2 and 3 items is possible
|
|
||||||
if (parentIndex.isValid()) {
|
if (parentIndex.isValid()) {
|
||||||
const QModelIndex nextIndex = index.sibling(index.row() + direction, index.column());
|
// Use direct sibling for level 2 and 3 items
|
||||||
if (nextIndex.isValid())
|
const QModelIndex followingIndex = index.sibling(index.row() + direction, 0);
|
||||||
return nextIndex;
|
if (followingIndex.isValid())
|
||||||
|
return followingIndex;
|
||||||
|
|
||||||
|
// First/Last level 3 item? Continue on level 2 item.
|
||||||
|
if (parentIndex.parent().isValid())
|
||||||
|
return direction == Previous ? parentIndex : getIndex(parentIndex, direction);
|
||||||
|
|
||||||
|
followingTopIndex = getTopLevelIndex(parentIndex, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last level 3 item? Continue on level 2 item
|
// Skip top level items without children
|
||||||
if (parentIndex.parent().isValid())
|
while (!model()->hasChildren(followingTopIndex))
|
||||||
return getIndex(parentIndex, direction);
|
followingTopIndex = getTopLevelIndex(followingTopIndex, direction);
|
||||||
|
|
||||||
// Find next/previous level 2 item
|
// Select first/last level 2 item
|
||||||
QModelIndex nextTopIndex = getTopLevelIndex(parentIndex.isValid() ? parentIndex : index,
|
const int row = direction == Next ? 0 : model()->rowCount(followingTopIndex) - 1;
|
||||||
direction);
|
return model()->index(row, 0, followingTopIndex);
|
||||||
while (!model()->hasChildren(nextTopIndex))
|
|
||||||
nextTopIndex = getTopLevelIndex(nextTopIndex, direction);
|
|
||||||
return model()->index(direction == Next ? 0 : model()->rowCount(nextTopIndex) - 1,
|
|
||||||
0,
|
|
||||||
nextTopIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex DiagnosticView::getTopLevelIndex(const QModelIndex &index, Direction direction) const
|
QModelIndex DiagnosticView::getTopLevelIndex(const QModelIndex &index, Direction direction) const
|
||||||
{
|
{
|
||||||
QModelIndex below = index.sibling(index.row() + direction, 0);
|
QModelIndex following = index.sibling(index.row() + direction, 0);
|
||||||
if (below.isValid())
|
if (following.isValid())
|
||||||
return below;
|
return following;
|
||||||
return model()->index(direction == Next ? 0 : model()->rowCount(index) - 1, 0);
|
const int row = direction == Next ? 0 : model()->rowCount() - 1;
|
||||||
|
return model()->index(row, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QAction *> DiagnosticView::customActions() const
|
QList<QAction *> DiagnosticView::customActions() const
|
||||||
|
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include "clangtoolslogfilereader.h"
|
#include "clangtoolslogfilereader.h"
|
||||||
|
|
||||||
|
#include <cpptools/cppprojectfile.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@@ -147,6 +149,10 @@ static Diagnostic buildDiagnostic(const CXDiagnostic cxDiagnostic,
|
|||||||
clang_disposeDiagnosticSet(cxChildDiagnostics);
|
clang_disposeDiagnosticSet(cxChildDiagnostics);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
using CppTools::ProjectFile;
|
||||||
|
const bool isHeaderFile = ProjectFile::isHeader(
|
||||||
|
ProjectFile::classify(diagnostic.location.filePath));
|
||||||
|
|
||||||
for (unsigned i = 0; i < clang_getNumDiagnosticsInSet(cxChildDiagnostics); ++i) {
|
for (unsigned i = 0; i < clang_getNumDiagnosticsInSet(cxChildDiagnostics); ++i) {
|
||||||
CXDiagnostic cxDiagnostic = clang_getDiagnosticInSet(cxChildDiagnostics, i);
|
CXDiagnostic cxDiagnostic = clang_getDiagnosticInSet(cxChildDiagnostics, i);
|
||||||
Utils::ExecuteOnDestruction cleanUpDiagnostic([&]() {
|
Utils::ExecuteOnDestruction cleanUpDiagnostic([&]() {
|
||||||
@@ -156,6 +162,9 @@ static Diagnostic buildDiagnostic(const CXDiagnostic cxDiagnostic,
|
|||||||
if (diagnosticStep.isValid())
|
if (diagnosticStep.isValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (isHeaderFile && diagnosticStep.message.contains("in file included from"))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (isInvalidDiagnosticLocation(diagnostic, diagnosticStep, nativeFilePath))
|
if (isInvalidDiagnosticLocation(diagnostic, diagnosticStep, nativeFilePath))
|
||||||
return diagnostic;
|
return diagnostic;
|
||||||
|
|
||||||
|
@@ -97,7 +97,7 @@ CMakeKitConfigWidget::~CMakeKitConfigWidget()
|
|||||||
|
|
||||||
QString CMakeKitConfigWidget::displayName() const
|
QString CMakeKitConfigWidget::displayName() const
|
||||||
{
|
{
|
||||||
return tr("CMake Tool:");
|
return tr("CMake Tool");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeKitConfigWidget::makeReadOnly()
|
void CMakeKitConfigWidget::makeReadOnly()
|
||||||
@@ -230,7 +230,7 @@ CMakeGeneratorKitConfigWidget::~CMakeGeneratorKitConfigWidget()
|
|||||||
|
|
||||||
QString CMakeGeneratorKitConfigWidget::displayName() const
|
QString CMakeGeneratorKitConfigWidget::displayName() const
|
||||||
{
|
{
|
||||||
return tr("CMake generator:");
|
return tr("CMake generator");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeGeneratorKitConfigWidget::makeReadOnly()
|
void CMakeGeneratorKitConfigWidget::makeReadOnly()
|
||||||
|
@@ -173,3 +173,34 @@ const QMap<QString, QUrl> &HelpItem::links() const
|
|||||||
}
|
}
|
||||||
return *m_helpLinks;
|
return *m_helpLinks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QUrl findBestLink(const QMap<QString, QUrl> &links)
|
||||||
|
{
|
||||||
|
if (links.isEmpty())
|
||||||
|
return QUrl();
|
||||||
|
if (links.size() == 1)
|
||||||
|
return links.first();
|
||||||
|
QUrl source = links.first();
|
||||||
|
// workaround to show the latest Qt version
|
||||||
|
int version = 0;
|
||||||
|
QRegExp exp("(\\d+)");
|
||||||
|
foreach (const QUrl &link, links) {
|
||||||
|
const QString &authority = link.authority();
|
||||||
|
if (authority.startsWith("com.trolltech.")
|
||||||
|
|| authority.startsWith("org.qt-project.")) {
|
||||||
|
if (exp.indexIn(authority) >= 0) {
|
||||||
|
const int tmpVersion = exp.cap(1).toInt();
|
||||||
|
if (tmpVersion > version) {
|
||||||
|
source = link;
|
||||||
|
version = tmpVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUrl HelpItem::bestLink() const
|
||||||
|
{
|
||||||
|
return findBestLink(links());
|
||||||
|
}
|
||||||
|
@@ -78,6 +78,7 @@ public:
|
|||||||
QString extractContent(bool extended) const;
|
QString extractContent(bool extended) const;
|
||||||
|
|
||||||
const QMap<QString, QUrl> &links() const;
|
const QMap<QString, QUrl> &links() const;
|
||||||
|
const QUrl bestLink() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUrl m_helpUrl;
|
QUrl m_helpUrl;
|
||||||
|
@@ -48,15 +48,15 @@ QSettings *InfoBar::m_settings = nullptr;
|
|||||||
Utils::Theme *InfoBar::m_theme = nullptr;
|
Utils::Theme *InfoBar::m_theme = nullptr;
|
||||||
|
|
||||||
InfoBarEntry::InfoBarEntry(Id _id, const QString &_infoText, GlobalSuppressionMode _globalSuppression)
|
InfoBarEntry::InfoBarEntry(Id _id, const QString &_infoText, GlobalSuppressionMode _globalSuppression)
|
||||||
: id(_id)
|
: m_id(_id)
|
||||||
, infoText(_infoText)
|
, m_infoText(_infoText)
|
||||||
, globalSuppression(_globalSuppression)
|
, m_globalSuppression(_globalSuppression)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoBarEntry::setCustomButtonInfo(const QString &_buttonText, CallBack callBack)
|
void InfoBarEntry::setCustomButtonInfo(const QString &_buttonText, CallBack callBack)
|
||||||
{
|
{
|
||||||
buttonText = _buttonText;
|
m_buttonText = _buttonText;
|
||||||
m_buttonCallBack = callBack;
|
m_buttonCallBack = callBack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,14 +69,14 @@ void InfoBarEntry::setCancelButtonInfo(CallBack callBack)
|
|||||||
void InfoBarEntry::setCancelButtonInfo(const QString &_cancelButtonText, CallBack callBack)
|
void InfoBarEntry::setCancelButtonInfo(const QString &_cancelButtonText, CallBack callBack)
|
||||||
{
|
{
|
||||||
m_useCancelButton = true;
|
m_useCancelButton = true;
|
||||||
cancelButtonText = _cancelButtonText;
|
m_cancelButtonText = _cancelButtonText;
|
||||||
m_cancelButtonCallBack = callBack;
|
m_cancelButtonCallBack = callBack;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoBarEntry::removeCancelButton()
|
void InfoBarEntry::removeCancelButton()
|
||||||
{
|
{
|
||||||
m_useCancelButton = false;
|
m_useCancelButton = false;
|
||||||
cancelButtonText.clear();
|
m_cancelButtonText.clear();
|
||||||
m_cancelButtonCallBack = nullptr;
|
m_cancelButtonCallBack = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,14 +94,14 @@ void InfoBar::addInfo(const InfoBarEntry &info)
|
|||||||
void InfoBar::removeInfo(Id id)
|
void InfoBar::removeInfo(Id id)
|
||||||
{
|
{
|
||||||
const int size = m_infoBarEntries.size();
|
const int size = m_infoBarEntries.size();
|
||||||
Utils::erase(m_infoBarEntries, Utils::equal(&InfoBarEntry::id, id));
|
Utils::erase(m_infoBarEntries, Utils::equal(&InfoBarEntry::m_id, id));
|
||||||
if (size != m_infoBarEntries.size())
|
if (size != m_infoBarEntries.size())
|
||||||
emit changed();
|
emit changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InfoBar::containsInfo(Id id) const
|
bool InfoBar::containsInfo(Id id) const
|
||||||
{
|
{
|
||||||
return Utils::anyOf(m_infoBarEntries, Utils::equal(&InfoBarEntry::id, id));
|
return Utils::anyOf(m_infoBarEntries, Utils::equal(&InfoBarEntry::m_id, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove and suppress id
|
// Remove and suppress id
|
||||||
@@ -240,7 +240,7 @@ void InfoBarDisplay::update()
|
|||||||
vbox->setMargin(0);
|
vbox->setMargin(0);
|
||||||
vbox->addLayout(hbox);
|
vbox->addLayout(hbox);
|
||||||
|
|
||||||
QLabel *infoWidgetLabel = new QLabel(info.infoText);
|
QLabel *infoWidgetLabel = new QLabel(info.m_infoText);
|
||||||
infoWidgetLabel->setWordWrap(true);
|
infoWidgetLabel->setWordWrap(true);
|
||||||
hbox->addWidget(infoWidgetLabel);
|
hbox->addWidget(infoWidgetLabel);
|
||||||
|
|
||||||
@@ -270,17 +270,17 @@ void InfoBarDisplay::update()
|
|||||||
m_isShowingDetailsWidget = false;
|
m_isShowingDetailsWidget = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info.buttonText.isEmpty()) {
|
if (!info.m_buttonText.isEmpty()) {
|
||||||
auto infoWidgetButton = new QToolButton;
|
auto infoWidgetButton = new QToolButton;
|
||||||
infoWidgetButton->setText(info.buttonText);
|
infoWidgetButton->setText(info.m_buttonText);
|
||||||
connect(infoWidgetButton, &QAbstractButton::clicked, [info]() { info.m_buttonCallBack(); });
|
connect(infoWidgetButton, &QAbstractButton::clicked, [info]() { info.m_buttonCallBack(); });
|
||||||
|
|
||||||
hbox->addWidget(infoWidgetButton);
|
hbox->addWidget(infoWidgetButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Id id = info.id;
|
const Id id = info.m_id;
|
||||||
QToolButton *infoWidgetSuppressButton = nullptr;
|
QToolButton *infoWidgetSuppressButton = nullptr;
|
||||||
if (info.globalSuppression == InfoBarEntry::GlobalSuppressionEnabled) {
|
if (info.m_globalSuppression == InfoBarEntry::GlobalSuppressionEnabled) {
|
||||||
infoWidgetSuppressButton = new QToolButton;
|
infoWidgetSuppressButton = new QToolButton;
|
||||||
infoWidgetSuppressButton->setText(tr("Do Not Show Again"));
|
infoWidgetSuppressButton->setText(tr("Do Not Show Again"));
|
||||||
connect(infoWidgetSuppressButton, &QAbstractButton::clicked, this, [this, id] {
|
connect(infoWidgetSuppressButton, &QAbstractButton::clicked, this, [this, id] {
|
||||||
@@ -301,7 +301,7 @@ void InfoBarDisplay::update()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.cancelButtonText.isEmpty()) {
|
if (info.m_cancelButtonText.isEmpty()) {
|
||||||
if (infoWidgetCloseButton) {
|
if (infoWidgetCloseButton) {
|
||||||
infoWidgetCloseButton->setAutoRaise(true);
|
infoWidgetCloseButton->setAutoRaise(true);
|
||||||
infoWidgetCloseButton->setIcon(Utils::Icons::CLOSE_FOREGROUND.icon());
|
infoWidgetCloseButton->setIcon(Utils::Icons::CLOSE_FOREGROUND.icon());
|
||||||
@@ -314,7 +314,7 @@ void InfoBarDisplay::update()
|
|||||||
if (infoWidgetCloseButton)
|
if (infoWidgetCloseButton)
|
||||||
hbox->addWidget(infoWidgetCloseButton);
|
hbox->addWidget(infoWidgetCloseButton);
|
||||||
} else {
|
} else {
|
||||||
infoWidgetCloseButton->setText(info.cancelButtonText);
|
infoWidgetCloseButton->setText(info.m_cancelButtonText);
|
||||||
hbox->addWidget(infoWidgetCloseButton);
|
hbox->addWidget(infoWidgetCloseButton);
|
||||||
if (infoWidgetSuppressButton)
|
if (infoWidgetSuppressButton)
|
||||||
hbox->addWidget(infoWidgetSuppressButton);
|
hbox->addWidget(infoWidgetSuppressButton);
|
||||||
|
@@ -67,13 +67,13 @@ public:
|
|||||||
void setDetailsWidgetCreator(const DetailsWidgetCreator &creator);
|
void setDetailsWidgetCreator(const DetailsWidgetCreator &creator);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Id id;
|
Id m_id;
|
||||||
QString infoText;
|
QString m_infoText;
|
||||||
QString buttonText;
|
QString m_buttonText;
|
||||||
CallBack m_buttonCallBack;
|
CallBack m_buttonCallBack;
|
||||||
QString cancelButtonText;
|
QString m_cancelButtonText;
|
||||||
CallBack m_cancelButtonCallBack;
|
CallBack m_cancelButtonCallBack;
|
||||||
GlobalSuppressionMode globalSuppression;
|
GlobalSuppressionMode m_globalSuppression;
|
||||||
DetailsWidgetCreator m_detailsWidgetCreator;
|
DetailsWidgetCreator m_detailsWidgetCreator;
|
||||||
bool m_useCancelButton = true;
|
bool m_useCancelButton = true;
|
||||||
friend class InfoBar;
|
friend class InfoBar;
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
|
|
||||||
#include <texteditor/icodestylepreferencesfactory.h>
|
#include <texteditor/icodestylepreferencesfactory.h>
|
||||||
|
#include <texteditor/textdocumentlayout.h>
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
@@ -447,5 +448,47 @@ TextEditor::TabSettings CppEditorDocument::tabSettings() const
|
|||||||
return indenter()->tabSettings().value_or(TextEditor::TextDocument::tabSettings());
|
return indenter()->tabSettings().value_or(TextEditor::TextDocument::tabSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int formatRange(QTextDocument *doc,
|
||||||
|
TextEditor::Indenter *indenter,
|
||||||
|
std::pair<int, int> editedRange,
|
||||||
|
const TextEditor::TabSettings &tabSettings)
|
||||||
|
{
|
||||||
|
QTextCursor cursor(doc);
|
||||||
|
cursor.setPosition(editedRange.first);
|
||||||
|
cursor.setPosition(editedRange.second, QTextCursor::KeepAnchor);
|
||||||
|
const int oldBlockCount = doc->blockCount();
|
||||||
|
indenter->format(cursor, tabSettings);
|
||||||
|
return doc->blockCount() - oldBlockCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CppEditorDocument::save(QString *errorString, const QString &fileName, bool autoSave)
|
||||||
|
{
|
||||||
|
if (indenter()->formatOnSave()) {
|
||||||
|
auto *layout = qobject_cast<TextEditor::TextDocumentLayout *>(document()->documentLayout());
|
||||||
|
const int documentRevision = layout->lastSaveRevision;
|
||||||
|
|
||||||
|
std::pair<int, int> editedRange;
|
||||||
|
for (int i = 0; i < document()->blockCount(); ++i) {
|
||||||
|
const QTextBlock block = document()->findBlockByNumber(i);
|
||||||
|
if (block.revision() == documentRevision) {
|
||||||
|
if (editedRange.first != -1)
|
||||||
|
i += formatRange(document(), indenter(), editedRange, tabSettings());
|
||||||
|
|
||||||
|
editedRange = std::make_pair(-1, -1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// block.revision() != documentRevision
|
||||||
|
if (editedRange.first == -1)
|
||||||
|
editedRange.first = block.position();
|
||||||
|
editedRange.second = block.position() + block.length();
|
||||||
|
}
|
||||||
|
if (editedRange.first != -1)
|
||||||
|
formatRange(document(), indenter(), editedRange, tabSettings());
|
||||||
|
}
|
||||||
|
|
||||||
|
return TextEditor::TextDocument::save(errorString, fileName, autoSave);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CppEditor
|
} // namespace CppEditor
|
||||||
|
@@ -69,6 +69,10 @@ public:
|
|||||||
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams ¶ms);
|
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams ¶ms);
|
||||||
TextEditor::TabSettings tabSettings() const override;
|
TextEditor::TabSettings tabSettings() const override;
|
||||||
|
|
||||||
|
bool save(QString *errorString,
|
||||||
|
const QString &fileName = QString(),
|
||||||
|
bool autoSave = false) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void codeWarningsUpdated(unsigned contentsRevision,
|
void codeWarningsUpdated(unsigned contentsRevision,
|
||||||
const QList<QTextEdit::ExtraSelection> selections,
|
const QList<QTextEdit::ExtraSelection> selections,
|
||||||
|
@@ -93,7 +93,7 @@ QString DebuggerKitConfigWidget::toolTip() const
|
|||||||
|
|
||||||
QString DebuggerKitConfigWidget::displayName() const
|
QString DebuggerKitConfigWidget::displayName() const
|
||||||
{
|
{
|
||||||
return tr("Debugger:");
|
return tr("Debugger");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebuggerKitConfigWidget::makeReadOnly()
|
void DebuggerKitConfigWidget::makeReadOnly()
|
||||||
|
@@ -620,30 +620,6 @@ HelpViewer *HelpPluginPrivate::viewerForContextHelp()
|
|||||||
return viewerForHelpViewerLocation(LocalHelpManager::contextHelpOption());
|
return viewerForHelpViewerLocation(LocalHelpManager::contextHelpOption());
|
||||||
}
|
}
|
||||||
|
|
||||||
static QUrl findBestLink(const QMap<QString, QUrl> &links)
|
|
||||||
{
|
|
||||||
if (links.isEmpty())
|
|
||||||
return QUrl();
|
|
||||||
QUrl source = links.constBegin().value();
|
|
||||||
// workaround to show the latest Qt version
|
|
||||||
int version = 0;
|
|
||||||
QRegExp exp("(\\d+)");
|
|
||||||
foreach (const QUrl &link, links) {
|
|
||||||
const QString &authority = link.authority();
|
|
||||||
if (authority.startsWith("com.trolltech.")
|
|
||||||
|| authority.startsWith("org.qt-project.")) {
|
|
||||||
if (exp.indexIn(authority) >= 0) {
|
|
||||||
const int tmpVersion = exp.cap(1).toInt();
|
|
||||||
if (tmpVersion > version) {
|
|
||||||
source = link;
|
|
||||||
version = tmpVersion;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HelpPluginPrivate::requestContextHelp()
|
void HelpPluginPrivate::requestContextHelp()
|
||||||
{
|
{
|
||||||
// Find out what to show
|
// Find out what to show
|
||||||
@@ -660,9 +636,7 @@ void HelpPluginPrivate::requestContextHelp()
|
|||||||
|
|
||||||
void HelpPluginPrivate::showContextHelp(const HelpItem &contextHelp)
|
void HelpPluginPrivate::showContextHelp(const HelpItem &contextHelp)
|
||||||
{
|
{
|
||||||
const QMap<QString, QUrl> &links = contextHelp.links();
|
const QUrl source = contextHelp.bestLink();
|
||||||
|
|
||||||
const QUrl source = findBestLink(links);
|
|
||||||
if (!source.isValid()) {
|
if (!source.isValid()) {
|
||||||
// No link found or no context object
|
// No link found or no context object
|
||||||
HelpViewer *viewer = showHelpUrl(QUrl(Help::Constants::AboutBlank),
|
HelpViewer *viewer = showHelpUrl(QUrl(Help::Constants::AboutBlank),
|
||||||
|
@@ -82,7 +82,7 @@ SysRootInformationConfigWidget::~SysRootInformationConfigWidget()
|
|||||||
|
|
||||||
QString SysRootInformationConfigWidget::displayName() const
|
QString SysRootInformationConfigWidget::displayName() const
|
||||||
{
|
{
|
||||||
return tr("Sysroot:");
|
return tr("Sysroot");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SysRootInformationConfigWidget::toolTip() const
|
QString SysRootInformationConfigWidget::toolTip() const
|
||||||
@@ -177,7 +177,7 @@ ToolChainInformationConfigWidget::~ToolChainInformationConfigWidget()
|
|||||||
|
|
||||||
QString ToolChainInformationConfigWidget::displayName() const
|
QString ToolChainInformationConfigWidget::displayName() const
|
||||||
{
|
{
|
||||||
return tr("Compiler:");
|
return tr("Compiler");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ToolChainInformationConfigWidget::toolTip() const
|
QString ToolChainInformationConfigWidget::toolTip() const
|
||||||
@@ -285,7 +285,7 @@ QWidget *DeviceTypeInformationConfigWidget::mainWidget() const
|
|||||||
|
|
||||||
QString DeviceTypeInformationConfigWidget::displayName() const
|
QString DeviceTypeInformationConfigWidget::displayName() const
|
||||||
{
|
{
|
||||||
return tr("Device type:");
|
return tr("Device type");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DeviceTypeInformationConfigWidget::toolTip() const
|
QString DeviceTypeInformationConfigWidget::toolTip() const
|
||||||
@@ -358,7 +358,7 @@ QWidget *DeviceInformationConfigWidget::mainWidget() const
|
|||||||
|
|
||||||
QString DeviceInformationConfigWidget::displayName() const
|
QString DeviceInformationConfigWidget::displayName() const
|
||||||
{
|
{
|
||||||
return tr("Device:");
|
return tr("Device");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DeviceInformationConfigWidget::toolTip() const
|
QString DeviceInformationConfigWidget::toolTip() const
|
||||||
@@ -437,7 +437,7 @@ QWidget *KitEnvironmentConfigWidget::mainWidget() const
|
|||||||
|
|
||||||
QString KitEnvironmentConfigWidget::displayName() const
|
QString KitEnvironmentConfigWidget::displayName() const
|
||||||
{
|
{
|
||||||
return tr("Environment:");
|
return tr("Environment");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString KitEnvironmentConfigWidget::toolTip() const
|
QString KitEnvironmentConfigWidget::toolTip() const
|
||||||
|
@@ -216,7 +216,7 @@ void KitManagerConfigWidget::addConfigWidget(KitConfigWidget *widget)
|
|||||||
QTC_ASSERT(widget, return);
|
QTC_ASSERT(widget, return);
|
||||||
QTC_ASSERT(!m_widgets.contains(widget), return);
|
QTC_ASSERT(!m_widgets.contains(widget), return);
|
||||||
|
|
||||||
QString name = widget->displayName();
|
const QString name = widget->displayName() + ':';
|
||||||
QString toolTip = widget->toolTip();
|
QString toolTip = widget->toolTip();
|
||||||
|
|
||||||
auto action = new QAction(tr("Mark as Mutable"), nullptr);
|
auto action = new QAction(tr("Mark as Mutable"), nullptr);
|
||||||
|
@@ -398,7 +398,7 @@ bool FlatModel::trimEmptyDirectories(WrapperNode *parent)
|
|||||||
|
|
||||||
Qt::DropActions FlatModel::supportedDragActions() const
|
Qt::DropActions FlatModel::supportedDragActions() const
|
||||||
{
|
{
|
||||||
return Qt::MoveAction;
|
return Qt::CopyAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList FlatModel::mimeTypes() const
|
QStringList FlatModel::mimeTypes() const
|
||||||
|
@@ -55,7 +55,7 @@ QWidget *QmakeKitConfigWidget::mainWidget() const
|
|||||||
|
|
||||||
QString QmakeKitConfigWidget::displayName() const
|
QString QmakeKitConfigWidget::displayName() const
|
||||||
{
|
{
|
||||||
return tr("Qt mkspec:");
|
return tr("Qt mkspec");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QmakeKitConfigWidget::toolTip() const
|
QString QmakeKitConfigWidget::toolTip() const
|
||||||
|
@@ -72,7 +72,7 @@ QtKitConfigWidget::~QtKitConfigWidget()
|
|||||||
|
|
||||||
QString QtKitConfigWidget::displayName() const
|
QString QtKitConfigWidget::displayName() const
|
||||||
{
|
{
|
||||||
return tr("Qt version:");
|
return tr("Qt version");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QtKitConfigWidget::toolTip() const
|
QString QtKitConfigWidget::toolTip() const
|
||||||
|
@@ -99,6 +99,8 @@ public:
|
|||||||
return Replacements();
|
return Replacements();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool formatOnSave() const { return false; }
|
||||||
|
|
||||||
// Expects a list of blocks in order of occurrence in the document.
|
// Expects a list of blocks in order of occurrence in the document.
|
||||||
virtual IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
|
virtual IndentationForBlock indentationForBlocks(const QVector<QTextBlock> &blocks,
|
||||||
const TabSettings &tabSettings,
|
const TabSettings &tabSettings,
|
||||||
|
@@ -692,7 +692,8 @@ public:
|
|||||||
QTextCursor m_pendingLinkUpdate;
|
QTextCursor m_pendingLinkUpdate;
|
||||||
QTextCursor m_lastLinkUpdate;
|
QTextCursor m_lastLinkUpdate;
|
||||||
|
|
||||||
QRegExp m_searchExpr;
|
QRegularExpression m_searchExpr;
|
||||||
|
QString m_findText;
|
||||||
FindFlags m_findFlags;
|
FindFlags m_findFlags;
|
||||||
void highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const;
|
void highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const;
|
||||||
QTimer m_delayedUpdateTimer;
|
QTimer m_delayedUpdateTimer;
|
||||||
@@ -3715,7 +3716,7 @@ QTextBlock TextEditorWidgetPrivate::foldedBlockAt(const QPoint &pos, QRect *box)
|
|||||||
|
|
||||||
void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const
|
void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block, const PaintEventData &data) const
|
||||||
{
|
{
|
||||||
if (m_searchExpr.isEmpty())
|
if (m_searchExpr.pattern().isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int blockPosition = block.position();
|
int blockPosition = block.position();
|
||||||
@@ -3734,10 +3735,11 @@ void TextEditorWidgetPrivate::highlightSearchResults(const QTextBlock &block, co
|
|||||||
.toTextCharFormat(C_SEARCH_RESULT).background().color().darker(120);
|
.toTextCharFormat(C_SEARCH_RESULT).background().color().darker(120);
|
||||||
|
|
||||||
while (idx < text.length()) {
|
while (idx < text.length()) {
|
||||||
idx = m_searchExpr.indexIn(text, idx + l);
|
const QRegularExpressionMatch match = m_searchExpr.match(text, idx + 1);
|
||||||
if (idx < 0)
|
if (!match.hasMatch())
|
||||||
break;
|
break;
|
||||||
l = m_searchExpr.matchedLength();
|
idx = match.capturedStart();
|
||||||
|
l = match.capturedLength();
|
||||||
if (l == 0)
|
if (l == 0)
|
||||||
break;
|
break;
|
||||||
if ((m_findFlags & FindWholeWords)
|
if ((m_findFlags & FindWholeWords)
|
||||||
@@ -4332,7 +4334,7 @@ void TextEditorWidgetPrivate::paintSearchResultOverlay(const PaintEventData &dat
|
|||||||
QPainter &painter) const
|
QPainter &painter) const
|
||||||
{
|
{
|
||||||
m_searchResultOverlay->clear();
|
m_searchResultOverlay->clear();
|
||||||
if (m_searchExpr.isEmpty())
|
if (m_searchExpr.pattern().isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const int margin = 5;
|
const int margin = 5;
|
||||||
@@ -5335,7 +5337,7 @@ void TextEditorWidgetPrivate::slotUpdateRequest(const QRect &r, int dy)
|
|||||||
m_extraArea->scroll(0, dy);
|
m_extraArea->scroll(0, dy);
|
||||||
} else if (r.width() > 4) { // wider than cursor width, not just cursor blinking
|
} else if (r.width() > 4) { // wider than cursor width, not just cursor blinking
|
||||||
m_extraArea->update(0, r.y(), m_extraArea->width(), r.height());
|
m_extraArea->update(0, r.y(), m_extraArea->width(), r.height());
|
||||||
if (!m_searchExpr.isEmpty()) {
|
if (!m_searchExpr.pattern().isEmpty()) {
|
||||||
const int m = m_searchResultOverlay->dropShadowWidth();
|
const int m = m_searchResultOverlay->dropShadowWidth();
|
||||||
q->viewport()->update(r.adjusted(-m, -m, m, m));
|
q->viewport()->update(r.adjusted(-m, -m, m, m));
|
||||||
}
|
}
|
||||||
@@ -6350,13 +6352,16 @@ void TextEditorWidgetPrivate::clearLink()
|
|||||||
|
|
||||||
void TextEditorWidgetPrivate::highlightSearchResultsSlot(const QString &txt, FindFlags findFlags)
|
void TextEditorWidgetPrivate::highlightSearchResultsSlot(const QString &txt, FindFlags findFlags)
|
||||||
{
|
{
|
||||||
if (m_searchExpr.pattern() == txt)
|
const QString pattern = (findFlags & FindRegularExpression) ? txt
|
||||||
|
: QRegularExpression::escape(txt);
|
||||||
|
const QRegularExpression::PatternOptions options
|
||||||
|
= (findFlags & FindCaseSensitively) ? QRegularExpression::NoPatternOption
|
||||||
|
: QRegularExpression::CaseInsensitiveOption;
|
||||||
|
if (m_searchExpr.pattern() == pattern && m_searchExpr.patternOptions() == options)
|
||||||
return;
|
return;
|
||||||
m_searchExpr.setPattern(txt);
|
m_searchExpr.setPattern(pattern);
|
||||||
m_searchExpr.setPatternSyntax((findFlags & FindRegularExpression) ?
|
m_searchExpr.setPatternOptions(options);
|
||||||
QRegExp::RegExp : QRegExp::FixedString);
|
m_findText = txt;
|
||||||
m_searchExpr.setCaseSensitivity((findFlags & FindCaseSensitively) ?
|
|
||||||
Qt::CaseSensitive : Qt::CaseInsensitive);
|
|
||||||
m_findFlags = findFlags;
|
m_findFlags = findFlags;
|
||||||
|
|
||||||
m_delayedUpdateTimer.start(50);
|
m_delayedUpdateTimer.start(50);
|
||||||
@@ -6414,7 +6419,7 @@ void TextEditorWidgetPrivate::highlightSearchResultsInScrollBar()
|
|||||||
m_searchWatcher = nullptr;
|
m_searchWatcher = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &txt = m_searchExpr.pattern();
|
const QString &txt = m_findText;
|
||||||
if (txt.isEmpty())
|
if (txt.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -8608,7 +8613,7 @@ void TextEditorLinkLabel::mouseMoveEvent(QMouseEvent *event)
|
|||||||
data->addFile(m_link.targetFileName, m_link.targetLine, m_link.targetColumn);
|
data->addFile(m_link.targetFileName, m_link.targetLine, m_link.targetColumn);
|
||||||
auto drag = new QDrag(this);
|
auto drag = new QDrag(this);
|
||||||
drag->setMimeData(data);
|
drag->setMimeData(data);
|
||||||
drag->exec(Qt::MoveAction);
|
drag->exec(Qt::CopyAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextEditorLinkLabel::mouseReleaseEvent(QMouseEvent *event)
|
void TextEditorLinkLabel::mouseReleaseEvent(QMouseEvent *event)
|
||||||
|
@@ -55,6 +55,7 @@
|
|||||||
#include <QTemporaryDir>
|
#include <QTemporaryDir>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
@@ -183,16 +184,6 @@ struct Data // because we have a cycle dependency
|
|||||||
PrecompiledHeaderStorage<> preCompiledHeaderStorage{database};
|
PrecompiledHeaderStorage<> preCompiledHeaderStorage{database};
|
||||||
ClangBackEnd::ProgressCounter progressCounter{
|
ClangBackEnd::ProgressCounter progressCounter{
|
||||||
[&](int progress, int total) { clangPchManagerServer.setProgress(progress, total); }};
|
[&](int progress, int total) { clangPchManagerServer.setProgress(progress, total); }};
|
||||||
TaskScheduler systemTaskScheduler{pchCreatorManager,
|
|
||||||
pchTaskQueue,
|
|
||||||
progressCounter,
|
|
||||||
std::thread::hardware_concurrency(),
|
|
||||||
ClangBackEnd::CallDoInMainThreadAfterFinished::No};
|
|
||||||
TaskScheduler projectTaskScheduler{pchCreatorManager,
|
|
||||||
pchTaskQueue,
|
|
||||||
progressCounter,
|
|
||||||
std::thread::hardware_concurrency(),
|
|
||||||
ClangBackEnd::CallDoInMainThreadAfterFinished::Yes};
|
|
||||||
ClangBackEnd::PchTaskQueue pchTaskQueue{systemTaskScheduler,
|
ClangBackEnd::PchTaskQueue pchTaskQueue{systemTaskScheduler,
|
||||||
projectTaskScheduler,
|
projectTaskScheduler,
|
||||||
progressCounter,
|
progressCounter,
|
||||||
@@ -212,10 +203,32 @@ struct Data // because we have a cycle dependency
|
|||||||
database};
|
database};
|
||||||
ClangBackEnd::PchTaskGenerator pchTaskGenerator{buildDependencyProvider, pchTaskMerger};
|
ClangBackEnd::PchTaskGenerator pchTaskGenerator{buildDependencyProvider, pchTaskMerger};
|
||||||
PchManagerServer clangPchManagerServer{includeWatcher, pchTaskGenerator, projectParts, generatedFiles};
|
PchManagerServer clangPchManagerServer{includeWatcher, pchTaskGenerator, projectParts, generatedFiles};
|
||||||
|
TaskScheduler systemTaskScheduler{pchCreatorManager,
|
||||||
|
pchTaskQueue,
|
||||||
|
progressCounter,
|
||||||
|
std::thread::hardware_concurrency(),
|
||||||
|
ClangBackEnd::CallDoInMainThreadAfterFinished::No};
|
||||||
|
TaskScheduler projectTaskScheduler{pchCreatorManager,
|
||||||
|
pchTaskQueue,
|
||||||
|
progressCounter,
|
||||||
|
std::thread::hardware_concurrency(),
|
||||||
|
ClangBackEnd::CallDoInMainThreadAfterFinished::Yes};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
static void messageOutput(QtMsgType type, const QMessageLogContext &, const QString &msg)
|
||||||
|
{
|
||||||
|
std::wcout << msg.toStdWString() << std::endl;
|
||||||
|
if (type == QtFatalMsg)
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
qInstallMessageHandler(messageOutput);
|
||||||
|
#endif
|
||||||
try {
|
try {
|
||||||
QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
|
QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
|
||||||
QCoreApplication::setOrganizationDomain(QStringLiteral("qt-project.org"));
|
QCoreApplication::setOrganizationDomain(QStringLiteral("qt-project.org"));
|
||||||
|
@@ -58,6 +58,7 @@ public:
|
|||||||
auto &preprocessor = compilerInstance.getPreprocessor();
|
auto &preprocessor = compilerInstance.getPreprocessor();
|
||||||
|
|
||||||
preprocessor.SetSuppressIncludeNotFoundError(true);
|
preprocessor.SetSuppressIncludeNotFoundError(true);
|
||||||
|
preprocessor.SetMacroExpansionOnlyInDirectives();
|
||||||
|
|
||||||
auto macroPreprocessorCallbacks = new CollectBuildDependencyPreprocessorCallbacks(
|
auto macroPreprocessorCallbacks = new CollectBuildDependencyPreprocessorCallbacks(
|
||||||
m_buildDependency,
|
m_buildDependency,
|
||||||
|
@@ -66,6 +66,8 @@ void PchManagerServer::updateProjectParts(UpdateProjectPartsMessage &&message)
|
|||||||
if (m_generatedFiles.isValid()) {
|
if (m_generatedFiles.isValid()) {
|
||||||
m_pchTaskGenerator.addProjectParts(std::move(newProjectParts),
|
m_pchTaskGenerator.addProjectParts(std::move(newProjectParts),
|
||||||
std::move(message.toolChainArguments));
|
std::move(message.toolChainArguments));
|
||||||
|
} else {
|
||||||
|
m_projectParts.updateDeferred(newProjectParts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,7 +43,7 @@ public:
|
|||||||
FilePathIds &&includes,
|
FilePathIds &&includes,
|
||||||
FilePathIds &&allIncludes,
|
FilePathIds &&allIncludes,
|
||||||
CompilerMacros &&compilerMacros,
|
CompilerMacros &&compilerMacros,
|
||||||
UsedMacros &&usedMacros,
|
Utils::SmallStringVector &&usedMacros,
|
||||||
Utils::SmallStringVector toolChainArguments,
|
Utils::SmallStringVector toolChainArguments,
|
||||||
IncludeSearchPaths systemIncludeSearchPaths,
|
IncludeSearchPaths systemIncludeSearchPaths,
|
||||||
IncludeSearchPaths projectIncludeSearchPaths,
|
IncludeSearchPaths projectIncludeSearchPaths,
|
||||||
@@ -54,7 +54,6 @@ public:
|
|||||||
, includes(includes)
|
, includes(includes)
|
||||||
, allIncludes(allIncludes)
|
, allIncludes(allIncludes)
|
||||||
, compilerMacros(compilerMacros)
|
, compilerMacros(compilerMacros)
|
||||||
, usedMacros(usedMacros)
|
|
||||||
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
|
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
|
||||||
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
|
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
|
||||||
, toolChainArguments(std::move(toolChainArguments))
|
, toolChainArguments(std::move(toolChainArguments))
|
||||||
@@ -67,7 +66,7 @@ public:
|
|||||||
FilePathIds &&includes,
|
FilePathIds &&includes,
|
||||||
FilePathIds &&allIncludes,
|
FilePathIds &&allIncludes,
|
||||||
CompilerMacros &&compilerMacros,
|
CompilerMacros &&compilerMacros,
|
||||||
UsedMacros &&usedMacros,
|
Utils::SmallStringVector &&usedMacros,
|
||||||
Utils::SmallStringVector toolChainArguments,
|
Utils::SmallStringVector toolChainArguments,
|
||||||
IncludeSearchPaths systemIncludeSearchPaths,
|
IncludeSearchPaths systemIncludeSearchPaths,
|
||||||
IncludeSearchPaths projectIncludeSearchPaths,
|
IncludeSearchPaths projectIncludeSearchPaths,
|
||||||
@@ -78,7 +77,6 @@ public:
|
|||||||
, includes(includes)
|
, includes(includes)
|
||||||
, allIncludes(allIncludes)
|
, allIncludes(allIncludes)
|
||||||
, compilerMacros(compilerMacros)
|
, compilerMacros(compilerMacros)
|
||||||
, usedMacros(usedMacros)
|
|
||||||
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
|
, systemIncludeSearchPaths(std::move(systemIncludeSearchPaths))
|
||||||
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
|
, projectIncludeSearchPaths(std::move(projectIncludeSearchPaths))
|
||||||
, toolChainArguments(std::move(toolChainArguments))
|
, toolChainArguments(std::move(toolChainArguments))
|
||||||
@@ -92,7 +90,6 @@ public:
|
|||||||
return first.systemPchPath == second.systemPchPath
|
return first.systemPchPath == second.systemPchPath
|
||||||
&& first.projectPartIds == second.projectPartIds && first.includes == second.includes
|
&& first.projectPartIds == second.projectPartIds && first.includes == second.includes
|
||||||
&& first.compilerMacros == second.compilerMacros
|
&& first.compilerMacros == second.compilerMacros
|
||||||
&& first.usedMacros == second.usedMacros
|
|
||||||
&& first.systemIncludeSearchPaths == second.systemIncludeSearchPaths
|
&& first.systemIncludeSearchPaths == second.systemIncludeSearchPaths
|
||||||
&& first.projectIncludeSearchPaths == second.projectIncludeSearchPaths
|
&& first.projectIncludeSearchPaths == second.projectIncludeSearchPaths
|
||||||
&& first.toolChainArguments == second.toolChainArguments
|
&& first.toolChainArguments == second.toolChainArguments
|
||||||
@@ -109,13 +106,13 @@ public:
|
|||||||
FilePathIds includes;
|
FilePathIds includes;
|
||||||
FilePathIds allIncludes;
|
FilePathIds allIncludes;
|
||||||
CompilerMacros compilerMacros;
|
CompilerMacros compilerMacros;
|
||||||
UsedMacros usedMacros;
|
|
||||||
IncludeSearchPaths systemIncludeSearchPaths;
|
IncludeSearchPaths systemIncludeSearchPaths;
|
||||||
IncludeSearchPaths projectIncludeSearchPaths;
|
IncludeSearchPaths projectIncludeSearchPaths;
|
||||||
Utils::SmallStringVector toolChainArguments;
|
Utils::SmallStringVector toolChainArguments;
|
||||||
Utils::Language language = Utils::Language::Cxx;
|
Utils::Language language = Utils::Language::Cxx;
|
||||||
Utils::LanguageVersion languageVersion = Utils::LanguageVersion::CXX98;
|
Utils::LanguageVersion languageVersion = Utils::LanguageVersion::CXX98;
|
||||||
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None;
|
Utils::LanguageExtension languageExtension = Utils::LanguageExtension::None;
|
||||||
|
bool isMerged = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PchTaskSet
|
class PchTaskSet
|
||||||
|
@@ -42,9 +42,9 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
|
|||||||
|
|
||||||
for (auto &projectPart : projectParts) {
|
for (auto &projectPart : projectParts) {
|
||||||
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart);
|
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart);
|
||||||
UsedMacroFilter filter{buildDependency.includes, buildDependency.usedMacros};
|
UsedMacroFilter filter{buildDependency.includes,
|
||||||
|
buildDependency.usedMacros,
|
||||||
filter.filter(projectPart.compilerMacros);
|
projectPart.compilerMacros};
|
||||||
|
|
||||||
pchTaskSets.emplace_back(PchTask{projectPart.projectPartId.clone(),
|
pchTaskSets.emplace_back(PchTask{projectPart.projectPartId.clone(),
|
||||||
std::move(filter.topSystemIncludes),
|
std::move(filter.topSystemIncludes),
|
||||||
@@ -53,7 +53,7 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
|
|||||||
std::move(filter.systemUsedMacros),
|
std::move(filter.systemUsedMacros),
|
||||||
projectPart.toolChainArguments,
|
projectPart.toolChainArguments,
|
||||||
projectPart.systemIncludeSearchPaths,
|
projectPart.systemIncludeSearchPaths,
|
||||||
projectPart.projectIncludeSearchPaths,
|
{},
|
||||||
projectPart.language,
|
projectPart.language,
|
||||||
projectPart.languageVersion,
|
projectPart.languageVersion,
|
||||||
projectPart.languageExtension},
|
projectPart.languageExtension},
|
||||||
|
@@ -30,20 +30,10 @@
|
|||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
void PchTasksMerger::mergeTasks(PchTaskSets &&taskSets,
|
void PchTasksMerger::mergeTasks(PchTaskSets &&taskSets,
|
||||||
Utils::SmallStringVector &&/*toolChainArguments*/)
|
Utils::SmallStringVector && /*toolChainArguments*/)
|
||||||
{
|
{
|
||||||
PchTasks systemTasks;
|
mergeSystemTasks(taskSets);
|
||||||
systemTasks.reserve(taskSets.size());
|
addProjectTasksToQueue(taskSets);
|
||||||
PchTasks projectTasks;
|
|
||||||
projectTasks.reserve(taskSets.size());
|
|
||||||
|
|
||||||
for (PchTaskSet &taskSet : taskSets) {
|
|
||||||
projectTasks.push_back(std::move(taskSet.project));
|
|
||||||
systemTasks.push_back(std::move(taskSet.system));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pchTaskQueue.addSystemPchTasks(std::move(systemTasks));
|
|
||||||
m_pchTaskQueue.addProjectPchTasks(std::move(projectTasks));
|
|
||||||
m_pchTaskQueue.processEntries();
|
m_pchTaskQueue.processEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,4 +42,117 @@ void PchTasksMerger::removePchTasks(const Utils::SmallStringVector &projectPartI
|
|||||||
m_pchTaskQueue.removePchTasks(projectPartIds);
|
m_pchTaskQueue.removePchTasks(projectPartIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Container, typename Result = std::remove_const_t<std::remove_reference_t<Container>>>
|
||||||
|
Result merge(Container &&first, Container &&second)
|
||||||
|
{
|
||||||
|
Result result;
|
||||||
|
result.reserve(first.size() + second.size());
|
||||||
|
|
||||||
|
std::set_union(std::make_move_iterator(first.begin()),
|
||||||
|
std::make_move_iterator(first.end()),
|
||||||
|
std::make_move_iterator(second.begin()),
|
||||||
|
std::make_move_iterator(second.end()),
|
||||||
|
std::back_inserter(result));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompilerMacros PchTasksMerger::mergeMacros(const CompilerMacros &firstCompilerMacros,
|
||||||
|
const CompilerMacros &secondCompilerMacros)
|
||||||
|
{
|
||||||
|
return merge(firstCompilerMacros, secondCompilerMacros);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PchTasksMerger::hasDuplicates(const CompilerMacros &compilerMacros)
|
||||||
|
{
|
||||||
|
auto found = std::adjacent_find(compilerMacros.begin(),
|
||||||
|
compilerMacros.end(),
|
||||||
|
[](const CompilerMacro &first, const CompilerMacro &second) {
|
||||||
|
return first.key == second.key;
|
||||||
|
});
|
||||||
|
|
||||||
|
return found == compilerMacros.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
IncludeSearchPaths mergeIncludeSearchPaths(IncludeSearchPaths &&first, IncludeSearchPaths &&second)
|
||||||
|
{
|
||||||
|
if (first.size() > second.size())
|
||||||
|
return merge(first, second);
|
||||||
|
|
||||||
|
return merge(first, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PchTasksMerger::mergePchTasks(PchTask &firstTask, PchTask &secondTask)
|
||||||
|
{
|
||||||
|
if (firstTask.language != secondTask.language || firstTask.isMerged || secondTask.isMerged)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CompilerMacros macros = mergeMacros(firstTask.compilerMacros, secondTask.compilerMacros);
|
||||||
|
|
||||||
|
secondTask.isMerged = hasDuplicates(macros);
|
||||||
|
|
||||||
|
if (secondTask.isMerged && firstTask.language == secondTask.language) {
|
||||||
|
firstTask.projectPartIds = merge(std::move(firstTask.projectPartIds),
|
||||||
|
std::move(secondTask.projectPartIds));
|
||||||
|
firstTask.includes = merge(std::move(firstTask.includes), std::move(secondTask.includes));
|
||||||
|
firstTask.allIncludes = merge(std::move(firstTask.allIncludes),
|
||||||
|
std::move(secondTask.allIncludes));
|
||||||
|
firstTask.compilerMacros = std::move(macros);
|
||||||
|
firstTask.systemIncludeSearchPaths = mergeIncludeSearchPaths(
|
||||||
|
std::move(firstTask.systemIncludeSearchPaths),
|
||||||
|
std::move(secondTask.systemIncludeSearchPaths));
|
||||||
|
|
||||||
|
firstTask.languageVersion = std::max(firstTask.languageVersion, secondTask.languageVersion);
|
||||||
|
firstTask.languageExtension = firstTask.languageExtension | secondTask.languageExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
return secondTask.isMerged;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PchTasksMerger::mergePchTasks(PchTasks &tasks)
|
||||||
|
{
|
||||||
|
auto begin = tasks.begin();
|
||||||
|
|
||||||
|
while (begin != tasks.end()) {
|
||||||
|
begin = std::find_if(begin, tasks.end(), [](const auto &task) { return !task.isMerged; });
|
||||||
|
if (begin != tasks.end()) {
|
||||||
|
PchTask &baseTask = *begin;
|
||||||
|
++begin;
|
||||||
|
|
||||||
|
std::for_each(begin, tasks.end(), [&](PchTask ¤tTask) {
|
||||||
|
mergePchTasks(baseTask, currentTask);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PchTasksMerger::addProjectTasksToQueue(PchTaskSets &taskSets)
|
||||||
|
{
|
||||||
|
PchTasks projectTasks;
|
||||||
|
projectTasks.reserve(taskSets.size());
|
||||||
|
|
||||||
|
for (PchTaskSet &taskSet : taskSets)
|
||||||
|
projectTasks.push_back(std::move(taskSet.project));
|
||||||
|
|
||||||
|
m_pchTaskQueue.addProjectPchTasks(std::move(projectTasks));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PchTasksMerger::mergeSystemTasks(PchTaskSets &taskSets)
|
||||||
|
{
|
||||||
|
PchTasks systemTasks;
|
||||||
|
systemTasks.reserve(taskSets.size());
|
||||||
|
|
||||||
|
for (PchTaskSet &taskSet : taskSets)
|
||||||
|
systemTasks.push_back(std::move(taskSet.system));
|
||||||
|
|
||||||
|
mergePchTasks(systemTasks);
|
||||||
|
|
||||||
|
systemTasks.erase(std::remove_if(systemTasks.begin(),
|
||||||
|
systemTasks.end(),
|
||||||
|
[](const PchTask &task) { return task.isMerged; }),
|
||||||
|
systemTasks.end());
|
||||||
|
|
||||||
|
m_pchTaskQueue.addSystemPchTasks(std::move(systemTasks));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -32,7 +32,7 @@ namespace ClangBackEnd {
|
|||||||
|
|
||||||
class PchTaskQueueInterface;
|
class PchTaskQueueInterface;
|
||||||
|
|
||||||
class PchTasksMerger : public PchTasksMergerInterface
|
class PchTasksMerger final : public PchTasksMergerInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PchTasksMerger(PchTaskQueueInterface &pchTaskQueue)
|
PchTasksMerger(PchTaskQueueInterface &pchTaskQueue)
|
||||||
@@ -42,6 +42,18 @@ public:
|
|||||||
void mergeTasks(PchTaskSets &&taskSets, Utils::SmallStringVector &&toolChainArguments) override;
|
void mergeTasks(PchTaskSets &&taskSets, Utils::SmallStringVector &&toolChainArguments) override;
|
||||||
void removePchTasks(const Utils::SmallStringVector &projectPartIds) override;
|
void removePchTasks(const Utils::SmallStringVector &projectPartIds) override;
|
||||||
|
|
||||||
|
static CompilerMacros mergeMacros(const CompilerMacros &firstCompilerMacros,
|
||||||
|
const CompilerMacros &secondCompilerMacros);
|
||||||
|
static bool hasDuplicates(const CompilerMacros &compilerMacros);
|
||||||
|
|
||||||
|
static bool mergePchTasks(PchTask &first, PchTask &second);
|
||||||
|
|
||||||
|
static void mergePchTasks(PchTasks &tasks);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addProjectTasksToQueue(PchTaskSets &taskSets);
|
||||||
|
void mergeSystemTasks(PchTaskSets &taskSets);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PchTaskQueueInterface &m_pchTaskQueue;
|
PchTaskQueueInterface &m_pchTaskQueue;
|
||||||
};
|
};
|
||||||
|
@@ -80,6 +80,11 @@ public:
|
|||||||
, m_callDoInMainThreadAfterFinished(callDoInMainThreadAfterFinished)
|
, m_callDoInMainThreadAfterFinished(callDoInMainThreadAfterFinished)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
~TaskScheduler()
|
||||||
|
{
|
||||||
|
syncTasks();
|
||||||
|
}
|
||||||
|
|
||||||
void addTasks(std::vector<Task> &&tasks)
|
void addTasks(std::vector<Task> &&tasks)
|
||||||
{
|
{
|
||||||
for (auto &task : tasks) {
|
for (auto &task : tasks) {
|
||||||
|
@@ -32,6 +32,27 @@
|
|||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
|
template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
|
||||||
|
inline OutputIterator set_greedy_intersection(InputIterator1 first1,
|
||||||
|
InputIterator1 last1,
|
||||||
|
InputIterator2 first2,
|
||||||
|
InputIterator2 last2,
|
||||||
|
OutputIterator result,
|
||||||
|
Compare comp)
|
||||||
|
{
|
||||||
|
while (first1 != last1 && first2 != last2)
|
||||||
|
if (comp(*first1, *first2))
|
||||||
|
++first1;
|
||||||
|
else if (comp(*first2, *first1))
|
||||||
|
++first2;
|
||||||
|
else {
|
||||||
|
*result = *first1;
|
||||||
|
++first1;
|
||||||
|
++result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
class UsedMacroFilter
|
class UsedMacroFilter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -41,11 +62,14 @@ public:
|
|||||||
FilePathIds system;
|
FilePathIds system;
|
||||||
};
|
};
|
||||||
|
|
||||||
UsedMacroFilter(const SourceEntries &includes, const UsedMacros &usedMacros)
|
UsedMacroFilter(const SourceEntries &includes,
|
||||||
|
const UsedMacros &usedMacros,
|
||||||
|
const CompilerMacros &compilerMacros)
|
||||||
{
|
{
|
||||||
filterIncludes(includes);
|
filterIncludes(includes);
|
||||||
systemUsedMacros = filterUsedMarcos(usedMacros, systemIncludes);
|
systemUsedMacros = filterUsedMarcos(usedMacros, systemIncludes);
|
||||||
projectUsedMacros = filterUsedMarcos(usedMacros, projectIncludes);
|
projectUsedMacros = filterUsedMarcos(usedMacros, projectIncludes);
|
||||||
|
filter(compilerMacros);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filterIncludes(const SourceEntries &includes)
|
void filterIncludes(const SourceEntries &includes)
|
||||||
@@ -98,7 +122,8 @@ private:
|
|||||||
allIncludes.emplace_back(include.sourceId);
|
allIncludes.emplace_back(include.sourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
static UsedMacros filterUsedMarcos(const UsedMacros &usedMacros, const FilePathIds &filePathId)
|
static Utils::SmallStringVector filterUsedMarcos(const UsedMacros &usedMacros,
|
||||||
|
const FilePathIds &filePathId)
|
||||||
{
|
{
|
||||||
struct Compare
|
struct Compare
|
||||||
{
|
{
|
||||||
@@ -113,52 +138,57 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
UsedMacros filtertedMacros;
|
Utils::SmallStringVector filtertedMacros;
|
||||||
filtertedMacros.reserve(usedMacros.size());
|
filtertedMacros.reserve(usedMacros.size());
|
||||||
|
|
||||||
std::set_intersection(usedMacros.begin(),
|
set_greedy_intersection(usedMacros.begin(),
|
||||||
usedMacros.end(),
|
usedMacros.end(),
|
||||||
filePathId.begin(),
|
filePathId.begin(),
|
||||||
filePathId.end(),
|
filePathId.end(),
|
||||||
std::back_inserter(filtertedMacros),
|
std::back_inserter(filtertedMacros),
|
||||||
Compare{});
|
Compare{});
|
||||||
|
|
||||||
std::sort(filtertedMacros.begin(),
|
std::sort(filtertedMacros.begin(), filtertedMacros.end());
|
||||||
filtertedMacros.end(),
|
|
||||||
[](const UsedMacro &first, const UsedMacro &second) {
|
|
||||||
return first.macroName < second.macroName;
|
|
||||||
});
|
|
||||||
|
|
||||||
return filtertedMacros;
|
return filtertedMacros;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CompilerMacros filtercompilerMacros(const CompilerMacros &indexedCompilerMacro,
|
static CompilerMacros filtercompilerMacros(const CompilerMacros &indexedCompilerMacro,
|
||||||
const UsedMacros &usedMacros)
|
const Utils::SmallStringVector &usedMacros)
|
||||||
{
|
{
|
||||||
|
CompilerMacros filtertedCompilerMacros;
|
||||||
|
filtertedCompilerMacros.reserve(indexedCompilerMacro.size() + usedMacros.size());
|
||||||
|
|
||||||
struct Compare
|
struct Compare
|
||||||
{
|
{
|
||||||
bool operator()(const UsedMacro &usedMacro,
|
bool operator()(const CompilerMacro &compilerMacro, Utils::SmallStringView usedMacro)
|
||||||
const CompilerMacro &compileMacro)
|
|
||||||
{
|
{
|
||||||
return usedMacro.macroName < compileMacro.key;
|
return compilerMacro.key < usedMacro;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()(const CompilerMacro &compileMacro,
|
bool operator()(Utils::SmallStringView usedMacro, const CompilerMacro &compilerMacro)
|
||||||
const UsedMacro &usedMacro)
|
|
||||||
{
|
{
|
||||||
return compileMacro.key < usedMacro.macroName;
|
return usedMacro < compilerMacro.key;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CompilerMacros filtertedCompilerMacros;
|
set_greedy_intersection(indexedCompilerMacro.begin(),
|
||||||
filtertedCompilerMacros.reserve(indexedCompilerMacro.size());
|
indexedCompilerMacro.end(),
|
||||||
|
usedMacros.begin(),
|
||||||
|
usedMacros.end(),
|
||||||
|
std::back_inserter(filtertedCompilerMacros),
|
||||||
|
Compare{});
|
||||||
|
|
||||||
std::set_intersection(indexedCompilerMacro.begin(),
|
auto split = filtertedCompilerMacros.end();
|
||||||
indexedCompilerMacro.end(),
|
|
||||||
usedMacros.begin(),
|
std::set_difference(usedMacros.begin(),
|
||||||
usedMacros.end(),
|
usedMacros.end(),
|
||||||
std::back_inserter(filtertedCompilerMacros),
|
filtertedCompilerMacros.begin(),
|
||||||
Compare{});
|
filtertedCompilerMacros.end(),
|
||||||
|
std::back_inserter(filtertedCompilerMacros),
|
||||||
|
Compare{});
|
||||||
|
|
||||||
|
std::inplace_merge(filtertedCompilerMacros.begin(), split, filtertedCompilerMacros.end());
|
||||||
|
|
||||||
return filtertedCompilerMacros;
|
return filtertedCompilerMacros;
|
||||||
}
|
}
|
||||||
@@ -169,8 +199,8 @@ public:
|
|||||||
FilePathIds systemIncludes;
|
FilePathIds systemIncludes;
|
||||||
FilePathIds topProjectIncludes;
|
FilePathIds topProjectIncludes;
|
||||||
FilePathIds topSystemIncludes;
|
FilePathIds topSystemIncludes;
|
||||||
UsedMacros projectUsedMacros;
|
Utils::SmallStringVector projectUsedMacros;
|
||||||
UsedMacros systemUsedMacros;
|
Utils::SmallStringVector systemUsedMacros;
|
||||||
CompilerMacros projectCompilerMacros;
|
CompilerMacros projectCompilerMacros;
|
||||||
CompilerMacros systemCompilerMacros;
|
CompilerMacros systemCompilerMacros;
|
||||||
};
|
};
|
||||||
|
@@ -39,6 +39,7 @@
|
|||||||
#include <sqliteexception.h>
|
#include <sqliteexception.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
@@ -93,12 +94,24 @@ struct Data // because we have a cycle dependency
|
|||||||
RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
||||||
FilePathCaching filePathCache{database};
|
FilePathCaching filePathCache{database};
|
||||||
GeneratedFiles generatedFiles;
|
GeneratedFiles generatedFiles;
|
||||||
SymbolIndexing symbolIndexing{database, filePathCache, generatedFiles, [&] (int progress, int total) { clangCodeModelServer.setProgress(progress, total); }};
|
|
||||||
RefactoringServer clangCodeModelServer{symbolIndexing, filePathCache, generatedFiles};
|
RefactoringServer clangCodeModelServer{symbolIndexing, filePathCache, generatedFiles};
|
||||||
|
SymbolIndexing symbolIndexing{database, filePathCache, generatedFiles, [&] (int progress, int total) { clangCodeModelServer.setProgress(progress, total); }};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
static void messageOutput(QtMsgType type, const QMessageLogContext &, const QString &msg)
|
||||||
|
{
|
||||||
|
std::wcout << msg.toStdWString() << std::endl;
|
||||||
|
if (type == QtFatalMsg)
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
qInstallMessageHandler(messageOutput);
|
||||||
|
#endif
|
||||||
try {
|
try {
|
||||||
QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
|
QCoreApplication::setOrganizationName(QStringLiteral("QtProject"));
|
||||||
QCoreApplication::setOrganizationDomain(QStringLiteral("qt-project.org"));
|
QCoreApplication::setOrganizationDomain(QStringLiteral("qt-project.org"));
|
||||||
|
@@ -95,8 +95,6 @@ public:
|
|||||||
|
|
||||||
bool isClean() const;
|
bool isClean() const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefactoringCompilationDatabase m_compilationDatabase;
|
RefactoringCompilationDatabase m_compilationDatabase;
|
||||||
std::vector<FileContent> m_fileContents;
|
std::vector<FileContent> m_fileContents;
|
||||||
|
@@ -45,6 +45,8 @@ bool CollectMacrosSourceFileCallbacks::handleBeginSource(clang::CompilerInstance
|
|||||||
compilerInstance.getPreprocessorPtr(),
|
compilerInstance.getPreprocessorPtr(),
|
||||||
m_sourcesManager);
|
m_sourcesManager);
|
||||||
|
|
||||||
|
compilerInstance.getLangOpts().DelayedTemplateParsing = false;
|
||||||
|
compilerInstance.getPreprocessorPtr()->SetSuppressIncludeNotFoundError(true);
|
||||||
compilerInstance.getPreprocessorPtr()->addPPCallbacks(std::move(callbacks));
|
compilerInstance.getPreprocessorPtr()->addPPCallbacks(std::move(callbacks));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@@ -124,8 +124,6 @@ private:
|
|||||||
FileStatusCache m_fileStatusCache{m_filePathCache};
|
FileStatusCache m_fileStatusCache{m_filePathCache};
|
||||||
SymbolsCollectorManager m_collectorManger;
|
SymbolsCollectorManager m_collectorManger;
|
||||||
ProgressCounter m_progressCounter;
|
ProgressCounter m_progressCounter;
|
||||||
SymbolIndexerTaskScheduler m_indexerScheduler;
|
|
||||||
SymbolIndexerTaskQueue m_indexerQueue{m_indexerScheduler, m_progressCounter};
|
|
||||||
SymbolIndexer m_indexer{m_indexerQueue,
|
SymbolIndexer m_indexer{m_indexerQueue,
|
||||||
m_symbolStorage,
|
m_symbolStorage,
|
||||||
m_buildDependencyStorage,
|
m_buildDependencyStorage,
|
||||||
@@ -133,6 +131,8 @@ private:
|
|||||||
m_filePathCache,
|
m_filePathCache,
|
||||||
m_fileStatusCache,
|
m_fileStatusCache,
|
||||||
m_symbolStorage.m_database};
|
m_symbolStorage.m_database};
|
||||||
|
SymbolIndexerTaskQueue m_indexerQueue{m_indexerScheduler, m_progressCounter};
|
||||||
|
SymbolIndexerTaskScheduler m_indexerScheduler;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -341,12 +341,14 @@ public:
|
|||||||
m_database};
|
m_database};
|
||||||
mutable ReadStatement m_getProjectPartArtefactsBySourceId{
|
mutable ReadStatement m_getProjectPartArtefactsBySourceId{
|
||||||
"SELECT toolChainArguments, compilerMacros, systemIncludeSearchPaths, "
|
"SELECT toolChainArguments, compilerMacros, systemIncludeSearchPaths, "
|
||||||
"projectIncludeSearchPaths, projectPartId FROM projectParts WHERE projectPartId = (SELECT "
|
"projectIncludeSearchPaths, projectPartId, language, languageVersion, languageExtension "
|
||||||
|
"FROM projectParts WHERE projectPartId = (SELECT "
|
||||||
"projectPartId FROM projectPartsSources WHERE sourceId = ?)",
|
"projectPartId FROM projectPartsSources WHERE sourceId = ?)",
|
||||||
m_database};
|
m_database};
|
||||||
mutable ReadStatement m_getProjectPartArtefactsByProjectPartName{
|
mutable ReadStatement m_getProjectPartArtefactsByProjectPartName{
|
||||||
"SELECT toolChainArguments, compilerMacros, systemIncludeSearchPaths, "
|
"SELECT toolChainArguments, compilerMacros, systemIncludeSearchPaths, "
|
||||||
"projectIncludeSearchPaths, projectPartId FROM projectParts WHERE projectPartName = ?",
|
"projectIncludeSearchPaths, projectPartId, language, languageVersion, languageExtension "
|
||||||
|
"FROM projectParts WHERE projectPartName = ?",
|
||||||
m_database};
|
m_database};
|
||||||
mutable ReadStatement m_getPrecompiledHeader{
|
mutable ReadStatement m_getPrecompiledHeader{
|
||||||
"SELECT projectPchPath, projectPchBuildTime FROM precompiledHeaders WHERE projectPartId = ?",
|
"SELECT projectPchPath, projectPchBuildTime FROM precompiledHeaders WHERE projectPartId = ?",
|
||||||
|
@@ -68,7 +68,8 @@ public:
|
|||||||
bool isAlreadyParsed(clang::FileID fileId)
|
bool isAlreadyParsed(clang::FileID fileId)
|
||||||
{
|
{
|
||||||
const clang::FileEntry *fileEntry = m_sourceManager->getFileEntryForID(fileId);
|
const clang::FileEntry *fileEntry = m_sourceManager->getFileEntryForID(fileId);
|
||||||
|
if (!fileEntry)
|
||||||
|
return false;
|
||||||
return m_sourcesManager.alreadyParsed(filePathId(fileEntry),
|
return m_sourcesManager.alreadyParsed(filePathId(fileEntry),
|
||||||
fileEntry->getModificationTime());
|
fileEntry->getModificationTime());
|
||||||
}
|
}
|
||||||
|
@@ -62,6 +62,10 @@ public:
|
|||||||
{
|
{
|
||||||
return !(first == second);
|
return !(first == second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator Utils::SmallStringView() const { return macroName; }
|
||||||
|
operator const Utils::SmallString &() const { return macroName; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Utils::SmallString macroName;
|
Utils::SmallString macroName;
|
||||||
FilePathId filePathId;
|
FilePathId filePathId;
|
||||||
|
@@ -103,7 +103,7 @@ def performTest(workingDir, projectName, availableConfigs):
|
|||||||
compareEventsTab(model, "events_qt%s.tsv" % qtVersion)
|
compareEventsTab(model, "events_qt%s.tsv" % qtVersion)
|
||||||
test.compare(dumpItems(model, column=colPercent)[0], '100 %')
|
test.compare(dumpItems(model, column=colPercent)[0], '100 %')
|
||||||
# cannot run following test on colShortest (unstable)
|
# cannot run following test on colShortest (unstable)
|
||||||
for i in [colTotal, colMean, colMedian, colLongest]:
|
for i in [colMean, colMedian, colLongest]:
|
||||||
for item in dumpItems(model, column=i)[2:5]:
|
for item in dumpItems(model, column=i)[2:5]:
|
||||||
test.verify(item.endswith('ms'), "Verify that '%s' ends with 'ms'" % item)
|
test.verify(item.endswith('ms'), "Verify that '%s' ends with 'ms'" % item)
|
||||||
for i in [colTotal, colMean, colMedian, colLongest, colShortest]:
|
for i in [colTotal, colMean, colMedian, colLongest, colShortest]:
|
||||||
|
@@ -435,9 +435,7 @@ TEST_F(BuildDependencyCollector, CollectUsedMacrosWithExternalDefine)
|
|||||||
ElementsAre(Eq(UsedMacro{"DEFINED", fileId}),
|
ElementsAre(Eq(UsedMacro{"DEFINED", fileId}),
|
||||||
Eq(UsedMacro{"IF_DEFINE", fileId}),
|
Eq(UsedMacro{"IF_DEFINE", fileId}),
|
||||||
Eq(UsedMacro{"__clang__", fileId}),
|
Eq(UsedMacro{"__clang__", fileId}),
|
||||||
Eq(UsedMacro{"CLASS_EXPORT", fileId}),
|
|
||||||
Eq(UsedMacro{"IF_NOT_DEFINE", fileId}),
|
Eq(UsedMacro{"IF_NOT_DEFINE", fileId}),
|
||||||
Eq(UsedMacro{"MACRO_EXPANSION", fileId}),
|
|
||||||
Eq(UsedMacro{"COMPILER_ARGUMENT", fileId})));
|
Eq(UsedMacro{"COMPILER_ARGUMENT", fileId})));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,9 +450,7 @@ TEST_F(BuildDependencyCollector, CollectUsedMacrosWithoutExternalDefine)
|
|||||||
ElementsAre(Eq(UsedMacro{"DEFINED", fileId}),
|
ElementsAre(Eq(UsedMacro{"DEFINED", fileId}),
|
||||||
Eq(UsedMacro{"IF_DEFINE", fileId}),
|
Eq(UsedMacro{"IF_DEFINE", fileId}),
|
||||||
Eq(UsedMacro{"__clang__", fileId}),
|
Eq(UsedMacro{"__clang__", fileId}),
|
||||||
Eq(UsedMacro{"CLASS_EXPORT", fileId}),
|
|
||||||
Eq(UsedMacro{"IF_NOT_DEFINE", fileId}),
|
Eq(UsedMacro{"IF_NOT_DEFINE", fileId}),
|
||||||
Eq(UsedMacro{"MACRO_EXPANSION", fileId}),
|
|
||||||
Eq(UsedMacro{"COMPILER_ARGUMENT", fileId})));
|
Eq(UsedMacro{"COMPILER_ARGUMENT", fileId})));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +635,6 @@ TEST_F(BuildDependencyCollector, Create)
|
|||||||
SourceType::TopProjectInclude))),
|
SourceType::TopProjectInclude))),
|
||||||
Field(&BuildDependency::usedMacros,
|
Field(&BuildDependency::usedMacros,
|
||||||
UnorderedElementsAre(
|
UnorderedElementsAre(
|
||||||
UsedMacro{"DEFINE", id(TESTDATA_DIR "/builddependencycollector/project/macros.h")},
|
|
||||||
UsedMacro{"IFDEF", id(TESTDATA_DIR "/builddependencycollector/project/macros.h")},
|
UsedMacro{"IFDEF", id(TESTDATA_DIR "/builddependencycollector/project/macros.h")},
|
||||||
UsedMacro{"DEFINED",
|
UsedMacro{"DEFINED",
|
||||||
id(TESTDATA_DIR "/builddependencycollector/project/macros.h")})),
|
id(TESTDATA_DIR "/builddependencycollector/project/macros.h")})),
|
||||||
|
@@ -51,12 +51,27 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ClangFormatExtendedIndenter : public ClangFormatIndenter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClangFormatExtendedIndenter(QTextDocument *doc)
|
||||||
|
: ClangFormatIndenter(doc)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool formatWhileTyping() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class ClangFormat : public ::testing::Test
|
class ClangFormat : public ::testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
void SetUp() final
|
void SetUp() final
|
||||||
{
|
{
|
||||||
indenter.setFileName(Utils::FileName::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
|
indenter.setFileName(Utils::FileName::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
|
||||||
|
extendedIndenter.setFileName(
|
||||||
|
Utils::FileName::fromString(TESTDATA_DIR "/clangformat/test.cpp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertLines(const std::vector<QString> &lines)
|
void insertLines(const std::vector<QString> &lines)
|
||||||
@@ -85,6 +100,7 @@ protected:
|
|||||||
|
|
||||||
QTextDocument doc;
|
QTextDocument doc;
|
||||||
ClangFormatIndenter indenter{&doc};
|
ClangFormatIndenter indenter{&doc};
|
||||||
|
ClangFormatExtendedIndenter extendedIndenter{&doc};
|
||||||
QTextCursor cursor{&doc};
|
QTextCursor cursor{&doc};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -315,6 +331,83 @@ TEST_F(ClangFormat, NoExtraIndentAfterBraceInitialization)
|
|||||||
"return 0;"));
|
"return 0;"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangFormat, IndentFunctionBodyAndFormatBeforeIt)
|
||||||
|
{
|
||||||
|
insertLines({"int foo(int a, int b,",
|
||||||
|
" int c, int d",
|
||||||
|
" ) {",
|
||||||
|
"",
|
||||||
|
"}"});
|
||||||
|
|
||||||
|
extendedIndenter.indentBlock(doc.findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
|
||||||
|
|
||||||
|
ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b, int c, int d)",
|
||||||
|
"{",
|
||||||
|
" ",
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangFormat, IndentAfterFunctionBodyAndNotFormatBefore)
|
||||||
|
{
|
||||||
|
insertLines({"int foo(int a, int b, int c, int d)",
|
||||||
|
"{",
|
||||||
|
" ",
|
||||||
|
"}"});
|
||||||
|
|
||||||
|
extendedIndenter.indentBlock(doc.findBlockByNumber(3),
|
||||||
|
QChar::Null,
|
||||||
|
TextEditor::TabSettings(),
|
||||||
|
doc.characterCount() - 3);
|
||||||
|
|
||||||
|
ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b, int c, int d)",
|
||||||
|
"{",
|
||||||
|
" ",
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangFormat, ReformatToEmptyFunction)
|
||||||
|
{
|
||||||
|
insertLines({"int foo(int a, int b, int c, int d)",
|
||||||
|
"{",
|
||||||
|
" ",
|
||||||
|
"}",
|
||||||
|
""});
|
||||||
|
|
||||||
|
extendedIndenter.indentBlock(doc.findBlockByNumber(4), QChar::Null, TextEditor::TabSettings());
|
||||||
|
|
||||||
|
ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b, int c, int d) {}",
|
||||||
|
""));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangFormat, ReformatToNonEmptyFunction)
|
||||||
|
{
|
||||||
|
insertLines({"int foo(int a, int b) {",
|
||||||
|
"",
|
||||||
|
"}"});
|
||||||
|
|
||||||
|
extendedIndenter.indentBlock(doc.findBlockByNumber(1), QChar::Null, TextEditor::TabSettings());
|
||||||
|
|
||||||
|
ASSERT_THAT(documentLines(), ElementsAre("int foo(int a, int b)",
|
||||||
|
"{",
|
||||||
|
" ",
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangFormat, IndentIfBodyAndFormatBeforeIt)
|
||||||
|
{
|
||||||
|
insertLines({"if(a && b",
|
||||||
|
" &&c && d",
|
||||||
|
" ) {",
|
||||||
|
"",
|
||||||
|
"}"});
|
||||||
|
|
||||||
|
extendedIndenter.indentBlock(doc.findBlockByNumber(3), QChar::Null, TextEditor::TabSettings());
|
||||||
|
|
||||||
|
ASSERT_THAT(documentLines(), ElementsAre("if (a && b && c && d) {",
|
||||||
|
" ",
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ClangFormat, FormatBasicFile)
|
TEST_F(ClangFormat, FormatBasicFile)
|
||||||
{
|
{
|
||||||
insertLines({"int main()",
|
insertLines({"int main()",
|
||||||
|
@@ -136,7 +136,7 @@ TYPED_TEST(CommandLineBuilder, CTask)
|
|||||||
|
|
||||||
ASSERT_THAT(
|
ASSERT_THAT(
|
||||||
builder.commandLine,
|
builder.commandLine,
|
||||||
ElementsAre("clang", "-x", "c-header", "-std=c11", "-nostdinc", "-nostdlibinc", "/source/file.c"));
|
ElementsAre("clang", "-x", "c-header", "-std=c11", "-nostdinc", "-nostdinc++", "/source/file.c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST(CommandLineBuilder, ObjectiveCTask)
|
TYPED_TEST(CommandLineBuilder, ObjectiveCTask)
|
||||||
@@ -153,7 +153,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCTask)
|
|||||||
"objective-c-header",
|
"objective-c-header",
|
||||||
"-std=c11",
|
"-std=c11",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"/source/file.c"));
|
"/source/file.c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ TYPED_TEST(CommandLineBuilder, CppTask)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"/source/file.cpp"));
|
"/source/file.cpp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCppTask)
|
|||||||
"objective-c++-header",
|
"objective-c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"/source/file.cpp"));
|
"/source/file.cpp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,7 +420,7 @@ TYPED_TEST(CommandLineBuilder, IncludesOrder)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++11",
|
"-std=c++11",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-I",
|
"-I",
|
||||||
"/include/foo",
|
"/include/foo",
|
||||||
"-I",
|
"-I",
|
||||||
@@ -441,7 +441,7 @@ TYPED_TEST(CommandLineBuilder, EmptySourceFile)
|
|||||||
Builder<TypeParam> builder{this->emptyProjectInfo, {}, {}};
|
Builder<TypeParam> builder{this->emptyProjectInfo, {}, {}};
|
||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang++", "-x", "c++-header", "-std=c++98", "-nostdinc", "-nostdlibinc"));
|
ElementsAre("clang++", "-x", "c++-header", "-std=c++98", "-nostdinc", "-nostdinc++"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST(CommandLineBuilder, SourceFile)
|
TYPED_TEST(CommandLineBuilder, SourceFile)
|
||||||
@@ -454,7 +454,7 @@ TYPED_TEST(CommandLineBuilder, SourceFile)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"/source/file.cpp"));
|
"/source/file.cpp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,7 +469,7 @@ TYPED_TEST(CommandLineBuilder, EmptyOutputFile)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"/source/file.cpp"));
|
"/source/file.cpp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -483,7 +483,7 @@ TYPED_TEST(CommandLineBuilder, OutputFile)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-o",
|
"-o",
|
||||||
"/output/file.o",
|
"/output/file.o",
|
||||||
"/source/file.cpp"));
|
"/source/file.cpp"));
|
||||||
@@ -499,7 +499,7 @@ TYPED_TEST(CommandLineBuilder, IncludePchPath)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-Xclang",
|
"-Xclang",
|
||||||
"-include-pch",
|
"-include-pch",
|
||||||
"-Xclang",
|
"-Xclang",
|
||||||
@@ -511,7 +511,7 @@ TYPED_TEST(CommandLineBuilder, IncludePchPath)
|
|||||||
|
|
||||||
TYPED_TEST(CommandLineBuilder, CompilerMacros)
|
TYPED_TEST(CommandLineBuilder, CompilerMacros)
|
||||||
{
|
{
|
||||||
this->emptyProjectInfo.compilerMacros = {{"YI", "1", 2}, {"ER", "2", 1}};
|
this->emptyProjectInfo.compilerMacros = {{"YI", "1", 2}, {"ER", "2", 1}, {"SAN"}};
|
||||||
|
|
||||||
Builder<TypeParam> builder{this->emptyProjectInfo};
|
Builder<TypeParam> builder{this->emptyProjectInfo};
|
||||||
|
|
||||||
@@ -521,7 +521,7 @@ TYPED_TEST(CommandLineBuilder, CompilerMacros)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-DER=2",
|
"-DER=2",
|
||||||
"-DYI=1"));
|
"-DYI=1"));
|
||||||
}
|
}
|
||||||
|
@@ -1157,10 +1157,9 @@ std::ostream &operator<<(std::ostream &out, const PchCreatorIncludes &includes)
|
|||||||
std::ostream &operator<<(std::ostream &out, const PchTask &task)
|
std::ostream &operator<<(std::ostream &out, const PchTask &task)
|
||||||
{
|
{
|
||||||
return out << "(" << task.projectPartIds << ", " << task.includes << ", " << task.compilerMacros
|
return out << "(" << task.projectPartIds << ", " << task.includes << ", " << task.compilerMacros
|
||||||
<< ", " << task.usedMacros << ", " << toText(task.language) << ", "
|
<< toText(task.language) << ", " << task.systemIncludeSearchPaths << ", "
|
||||||
<< task.systemIncludeSearchPaths << ", " << task.projectIncludeSearchPaths << ", "
|
<< task.projectIncludeSearchPaths << ", " << task.toolChainArguments << ", "
|
||||||
<< task.toolChainArguments << ", " << toText(task.languageVersion) << ", "
|
<< toText(task.languageVersion) << ", " << toText(task.languageExtension) << ")";
|
||||||
<< toText(task.languageExtension) << ")";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, const PchTaskSet &taskSet)
|
std::ostream &operator<<(std::ostream &out, const PchTaskSet &taskSet)
|
||||||
|
@@ -157,7 +157,7 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArguments)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-I",
|
"-I",
|
||||||
TESTDATA_DIR "/builddependencycollector/project",
|
TESTDATA_DIR "/builddependencycollector/project",
|
||||||
"-isystem",
|
"-isystem",
|
||||||
@@ -183,7 +183,7 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArgumentsWithSystemPch)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-I",
|
"-I",
|
||||||
TESTDATA_DIR "/builddependencycollector/project",
|
TESTDATA_DIR "/builddependencycollector/project",
|
||||||
"-isystem",
|
"-isystem",
|
||||||
|
@@ -47,6 +47,7 @@ using Utils::SmallString;
|
|||||||
using ClangBackEnd::V2::FileContainer;
|
using ClangBackEnd::V2::FileContainer;
|
||||||
using ClangBackEnd::V2::FileContainers;
|
using ClangBackEnd::V2::FileContainers;
|
||||||
using ClangBackEnd::ProjectPartContainer;
|
using ClangBackEnd::ProjectPartContainer;
|
||||||
|
using ClangBackEnd::ProjectPartContainers;
|
||||||
|
|
||||||
class PchManagerServer : public ::testing::Test
|
class PchManagerServer : public ::testing::Test
|
||||||
{
|
{
|
||||||
@@ -198,8 +199,11 @@ TEST_F(PchManagerServer, DontGeneratePchIfGeneratedFilesAreNotValid)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(mockProjectParts, update(ElementsAre(projectPart1)))
|
||||||
|
.WillOnce(Return(ProjectPartContainers{projectPart1}));
|
||||||
EXPECT_CALL(mockGeneratedFiles, isValid()).WillOnce(Return(false));
|
EXPECT_CALL(mockGeneratedFiles, isValid()).WillOnce(Return(false));
|
||||||
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
|
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _)).Times(0);
|
||||||
|
EXPECT_CALL(mockProjectParts, updateDeferred(ElementsAre(projectPart1)));
|
||||||
|
|
||||||
server.updateProjectParts(
|
server.updateProjectParts(
|
||||||
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
|
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
|
||||||
@@ -209,8 +213,11 @@ TEST_F(PchManagerServer, GeneratePchIfGeneratedFilesAreValid)
|
|||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(mockProjectParts, update(ElementsAre(projectPart1)))
|
||||||
|
.WillOnce(Return(ProjectPartContainers{projectPart1}));
|
||||||
EXPECT_CALL(mockGeneratedFiles, isValid()).WillOnce(Return(true));
|
EXPECT_CALL(mockGeneratedFiles, isValid()).WillOnce(Return(true));
|
||||||
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _));
|
EXPECT_CALL(mockPchTaskGenerator, addProjectParts(_, _));
|
||||||
|
EXPECT_CALL(mockProjectParts, updateDeferred(_)).Times(0);
|
||||||
|
|
||||||
server.updateProjectParts(
|
server.updateProjectParts(
|
||||||
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
|
ClangBackEnd::UpdateProjectPartsMessage{{projectPart1}, {"toolChainArgument"}});
|
||||||
|
@@ -99,7 +99,6 @@ TEST_F(PchTaskGenerator, AddProjectParts)
|
|||||||
Field(&PchTask::allIncludes, IsEmpty()),
|
Field(&PchTask::allIncludes, IsEmpty()),
|
||||||
Field(&PchTask::compilerMacros,
|
Field(&PchTask::compilerMacros,
|
||||||
ElementsAre(CompilerMacro{"SE", "4", 4}, CompilerMacro{"WU", "5", 5})),
|
ElementsAre(CompilerMacro{"SE", "4", 4}, CompilerMacro{"WU", "5", 5})),
|
||||||
Field(&PchTask::usedMacros, ElementsAre(UsedMacro{"SE", 4}, UsedMacro{"WU", 5})),
|
|
||||||
Field(&PchTask::systemIncludeSearchPaths,
|
Field(&PchTask::systemIncludeSearchPaths,
|
||||||
ElementsAre(
|
ElementsAre(
|
||||||
IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
|
IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
|
||||||
@@ -120,7 +119,6 @@ TEST_F(PchTaskGenerator, AddProjectParts)
|
|||||||
Field(&PchTask::allIncludes, ElementsAre(1, 2, 3, 4, 5)),
|
Field(&PchTask::allIncludes, ElementsAre(1, 2, 3, 4, 5)),
|
||||||
Field(&PchTask::compilerMacros,
|
Field(&PchTask::compilerMacros,
|
||||||
ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3})),
|
ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3})),
|
||||||
Field(&PchTask::usedMacros, ElementsAre(UsedMacro{"YI", 1}, UsedMacro{"SAN", 3})),
|
|
||||||
Field(&PchTask::systemIncludeSearchPaths,
|
Field(&PchTask::systemIncludeSearchPaths,
|
||||||
ElementsAre(
|
ElementsAre(
|
||||||
IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
|
IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
|
||||||
|
@@ -31,11 +31,14 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using ClangBackEnd::CompilerMacro;
|
||||||
|
using ClangBackEnd::CompilerMacros;
|
||||||
using ClangBackEnd::IncludeSearchPath;
|
using ClangBackEnd::IncludeSearchPath;
|
||||||
using ClangBackEnd::IncludeSearchPathType;
|
using ClangBackEnd::IncludeSearchPathType;
|
||||||
using ClangBackEnd::PchTask;
|
using ClangBackEnd::PchTask;
|
||||||
using ClangBackEnd::PchTaskSet;
|
using ClangBackEnd::PchTaskSet;
|
||||||
|
using Merger = ClangBackEnd::PchTasksMerger;
|
||||||
|
using Id = ClangBackEnd::FilePathId;
|
||||||
class PchTasksMerger : public testing::Test
|
class PchTasksMerger : public testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@@ -51,48 +54,58 @@ protected:
|
|||||||
ClangBackEnd::PchTasksMerger merger{mockPchTaskQueue};
|
ClangBackEnd::PchTasksMerger merger{mockPchTaskQueue};
|
||||||
PchTask systemTask1{"ProjectPart1",
|
PchTask systemTask1{"ProjectPart1",
|
||||||
{1, 2},
|
{1, 2},
|
||||||
{1, 2},
|
{1, 2, 3},
|
||||||
{{"YI", "1", 1}, {"SAN", "3", 3}},
|
{{"YI", "1", 1}, {"SAN", "3", 3}},
|
||||||
{{"LIANG", 0}, {"YI", 1}},
|
{"YI", "LIANG"},
|
||||||
{"--yi"},
|
{"--yi"},
|
||||||
{IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
|
{{"/system/path", 2, IncludeSearchPathType::System},
|
||||||
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
|
{"/builtin/path2", 3, IncludeSearchPathType::BuiltIn},
|
||||||
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}},
|
{"/framework/path", 1, IncludeSearchPathType::System}},
|
||||||
{IncludeSearchPath{"/to/path1", 1, IncludeSearchPathType::User},
|
{{"/to/path1", 1, IncludeSearchPathType::User},
|
||||||
IncludeSearchPath{"/to/path2", 2, IncludeSearchPathType::User}}};
|
{"/to/path2", 2, IncludeSearchPathType::User}}};
|
||||||
PchTask projectTask1{"ProjectPart1",
|
PchTask projectTask1{"ProjectPart1",
|
||||||
{11, 12},
|
{11, 12},
|
||||||
{11, 12},
|
{11, 12},
|
||||||
{{"SE", "4", 4}, {"WU", "5", 5}},
|
{{"SE", "4", 4}, {"WU", "5", 5}},
|
||||||
{{"ER", 2}, {"SAN", 3}},
|
{"ER", "SAN"},
|
||||||
{"--yi"},
|
{"--yi"},
|
||||||
{IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
|
{{"/system/path", 1, IncludeSearchPathType::System},
|
||||||
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
|
{"/builtin/path", 2, IncludeSearchPathType::BuiltIn}},
|
||||||
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}},
|
{{"/to/path1", 1, IncludeSearchPathType::User},
|
||||||
{IncludeSearchPath{"/to/path1", 1, IncludeSearchPathType::User},
|
{"/to/path2", 2, IncludeSearchPathType::User}}};
|
||||||
IncludeSearchPath{"/to/path2", 2, IncludeSearchPathType::User}}};
|
|
||||||
PchTask systemTask2{"ProjectPart2",
|
PchTask systemTask2{"ProjectPart2",
|
||||||
{1, 2},
|
{11, 12},
|
||||||
{1, 2},
|
{11, 12, 13},
|
||||||
{{"YI", "1", 1}, {"SAN", "3", 3}},
|
{{"SE", "4", 4}, {"WU", "5", 5}},
|
||||||
{{"LIANG", 0}, {"YI", 1}},
|
{"ER", "SAN"},
|
||||||
{"--yi"},
|
{"--yi"},
|
||||||
{IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
|
{{"/system/path", 2, IncludeSearchPathType::System},
|
||||||
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
|
{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
|
||||||
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}},
|
{"/framework/path", 1, IncludeSearchPathType::System}},
|
||||||
{IncludeSearchPath{"/to/path1", 1, IncludeSearchPathType::User},
|
{{"/to/path1", 1, IncludeSearchPathType::User},
|
||||||
IncludeSearchPath{"/to/path2", 2, IncludeSearchPathType::User}}};
|
{"/to/path2", 2, IncludeSearchPathType::User}}};
|
||||||
PchTask projectTask2{"ProjectPart2",
|
PchTask projectTask2{"ProjectPart2",
|
||||||
{11, 12},
|
{11, 12},
|
||||||
{11, 12},
|
{11, 12},
|
||||||
{{"SE", "4", 4}, {"WU", "5", 5}},
|
{{"SE", "4", 4}, {"WU", "5", 5}},
|
||||||
{{"ER", 2}, {"SAN", 3}},
|
{"ER", "SAN"},
|
||||||
{"--yi"},
|
{"--yi"},
|
||||||
{IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
|
{{"/system/path", 2, IncludeSearchPathType::System},
|
||||||
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
|
{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
|
||||||
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}},
|
{"/framework/path", 1, IncludeSearchPathType::System}},
|
||||||
{IncludeSearchPath{"/to/path1", 1, IncludeSearchPathType::User},
|
{{"/to/path1", 1, IncludeSearchPathType::User},
|
||||||
IncludeSearchPath{"/to/path2", 2, IncludeSearchPathType::User}}};
|
{"/to/path2", 2, IncludeSearchPathType::User}}};
|
||||||
|
PchTask systemTask3{"ProjectPart3",
|
||||||
|
{1, 2},
|
||||||
|
{1, 2},
|
||||||
|
{{"YI", "2", 1}, {"SAN", "3", 3}},
|
||||||
|
{"YI", "LIANG"},
|
||||||
|
{"--yi"},
|
||||||
|
{{"/system/path", 2, IncludeSearchPathType::System},
|
||||||
|
{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
|
||||||
|
{"/framework/path", 1, IncludeSearchPathType::System}},
|
||||||
|
{{"/to/path1", 1, IncludeSearchPathType::User},
|
||||||
|
{"/to/path2", 2, IncludeSearchPathType::User}}};
|
||||||
Utils::SmallStringVector toolChainArguments = {"toolChainArguments"};
|
Utils::SmallStringVector toolChainArguments = {"toolChainArguments"};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -103,21 +116,33 @@ TEST_F(PchTasksMerger, AddProjectTasks)
|
|||||||
EXPECT_CALL(mockPchTaskQueue, addProjectPchTasks(ElementsAre(projectTask1, projectTask2)));
|
EXPECT_CALL(mockPchTaskQueue, addProjectPchTasks(ElementsAre(projectTask1, projectTask2)));
|
||||||
EXPECT_CALL(mockPchTaskQueue, processEntries());
|
EXPECT_CALL(mockPchTaskQueue, processEntries());
|
||||||
|
|
||||||
merger.mergeTasks(
|
merger.mergeTasks({{clone(systemTask1), clone(projectTask1)},
|
||||||
{{clone(systemTask1), clone(projectTask1)}, {clone(systemTask1), clone(projectTask2)}},
|
{clone(systemTask1), clone(projectTask2)}},
|
||||||
std::move(toolChainArguments));
|
std::move(toolChainArguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PchTasksMerger, AddSystemTasks)
|
TEST_F(PchTasksMerger, AddSystemTasks)
|
||||||
{
|
{
|
||||||
InSequence s;
|
InSequence s;
|
||||||
|
|
||||||
EXPECT_CALL(mockPchTaskQueue, addSystemPchTasks(ElementsAre(systemTask1, systemTask2)));
|
EXPECT_CALL(mockPchTaskQueue, addSystemPchTasks(ElementsAre(_, systemTask3)));
|
||||||
EXPECT_CALL(mockPchTaskQueue, processEntries());
|
EXPECT_CALL(mockPchTaskQueue, processEntries());
|
||||||
|
|
||||||
merger.mergeTasks(
|
merger.mergeTasks({{clone(systemTask1), clone(projectTask1)},
|
||||||
{{clone(systemTask1), clone(projectTask1)}, {clone(systemTask2), clone(projectTask2)}},
|
{clone(systemTask2), clone(projectTask2)},
|
||||||
std::move(toolChainArguments));
|
{clone(systemTask3), clone(projectTask2)}},
|
||||||
|
std::move(toolChainArguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, AddSystemOnlyOneTask)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(mockPchTaskQueue, addSystemPchTasks(ElementsAre(systemTask1)));
|
||||||
|
EXPECT_CALL(mockPchTaskQueue, processEntries());
|
||||||
|
|
||||||
|
merger.mergeTasks({{clone(systemTask1), clone(projectTask1)}},
|
||||||
|
std::move(toolChainArguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PchTasksMerger, RemoveTasks)
|
TEST_F(PchTasksMerger, RemoveTasks)
|
||||||
@@ -126,4 +151,233 @@ TEST_F(PchTasksMerger, RemoveTasks)
|
|||||||
|
|
||||||
merger.removePchTasks({"project1", "project2"});
|
merger.removePchTasks({"project1", "project2"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, MergeMacros)
|
||||||
|
{
|
||||||
|
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"YI"}, {"SAN", "3", 3}};
|
||||||
|
CompilerMacros compilerMacros2{{"BA"}, {"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
|
||||||
|
|
||||||
|
auto macros = Merger::mergeMacros(compilerMacros1, compilerMacros2);
|
||||||
|
|
||||||
|
ASSERT_THAT(macros,
|
||||||
|
ElementsAre(CompilerMacro{"BA"},
|
||||||
|
CompilerMacro{"ER", "2", 2},
|
||||||
|
CompilerMacro{"SE", "4", 1},
|
||||||
|
CompilerMacro{"YI", "1", 1},
|
||||||
|
CompilerMacro{"YI"},
|
||||||
|
CompilerMacro{"SAN", "3", 3}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, MacrosCanBeMerged)
|
||||||
|
{
|
||||||
|
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"QI"}, {"SE", "4", 1}, {"SAN", "3", 3}};
|
||||||
|
CompilerMacros compilerMacros2{{"BA"}, {"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
|
||||||
|
|
||||||
|
auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
|
||||||
|
|
||||||
|
ASSERT_TRUE(canBeMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, MacrosCannotBeMergedBecauseDifferentValue)
|
||||||
|
{
|
||||||
|
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"SAN", "3", 3}};
|
||||||
|
CompilerMacros compilerMacros2{{"ER", "1", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
|
||||||
|
|
||||||
|
auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
|
||||||
|
|
||||||
|
ASSERT_FALSE(canBeMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, MacrosCannotBeMergedBecauseUndefinedMacro)
|
||||||
|
{
|
||||||
|
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"YI"}, {"SAN", "3", 3}};
|
||||||
|
CompilerMacros compilerMacros2{{"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
|
||||||
|
|
||||||
|
auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
|
||||||
|
|
||||||
|
ASSERT_FALSE(canBeMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, CanMergePchTasks)
|
||||||
|
{
|
||||||
|
auto canBeMerged = Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_TRUE(canBeMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, CannotMergePchTasks)
|
||||||
|
{
|
||||||
|
auto canBeMerged = Merger::mergePchTasks(systemTask1, systemTask3);
|
||||||
|
|
||||||
|
ASSERT_FALSE(canBeMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, IsMergedIsSet)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_TRUE(systemTask2.isMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, IsMergedIsNotSet)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask3);
|
||||||
|
|
||||||
|
ASSERT_FALSE(systemTask3.isMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, DontMergeLanguage)
|
||||||
|
{
|
||||||
|
systemTask2.language = Utils::Language::C;
|
||||||
|
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_FALSE(systemTask2.isMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, MergeCompilerMacros)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.compilerMacros,
|
||||||
|
ElementsAre(CompilerMacro{"SE", "4", 4},
|
||||||
|
CompilerMacro{"WU", "5", 5},
|
||||||
|
CompilerMacro{"YI", "1", 1},
|
||||||
|
CompilerMacro{"SAN", "3", 3}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, DontMergeCompilerMacros)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask3);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.compilerMacros,
|
||||||
|
ElementsAre(CompilerMacro{"YI", "1", 1}, CompilerMacro{"SAN", "3", 3}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, MergeIncludes)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2, 11, 12));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, DontMergeIncludes)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask3);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, MergeAllIncludes)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.allIncludes, ElementsAre(1, 2, 3, 11, 12, 13));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, DontAllMergeIncludes)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask3);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.allIncludes, ElementsAre(1, 2, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, MergeProjectIds)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.projectPartIds, ElementsAre("ProjectPart1", "ProjectPart2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, DontMergeProjectIds)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask3);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.projectPartIds, ElementsAre("ProjectPart1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, MergeIncludeSearchPaths)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.systemIncludeSearchPaths,
|
||||||
|
ElementsAre(IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
|
||||||
|
IncludeSearchPath{"/builtin/path", 3, IncludeSearchPathType::BuiltIn},
|
||||||
|
IncludeSearchPath{"/builtin/path2", 3, IncludeSearchPathType::BuiltIn},
|
||||||
|
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, DontMergeIncludeSearchPaths)
|
||||||
|
{
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask3);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.systemIncludeSearchPaths,
|
||||||
|
ElementsAre(IncludeSearchPath{"/system/path", 2, IncludeSearchPathType::System},
|
||||||
|
IncludeSearchPath{"/builtin/path2", 3, IncludeSearchPathType::BuiltIn},
|
||||||
|
IncludeSearchPath{"/framework/path", 1, IncludeSearchPathType::System}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, ChooseLanguageVersionFromFirstTask)
|
||||||
|
{
|
||||||
|
systemTask2.languageVersion = Utils::LanguageVersion::CXX17;
|
||||||
|
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.languageVersion, Utils::LanguageVersion::CXX17);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, ChooseLanguageVersionFromSecondTask)
|
||||||
|
{
|
||||||
|
systemTask1.languageVersion = Utils::LanguageVersion::CXX17;
|
||||||
|
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.languageVersion, Utils::LanguageVersion::CXX17);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, DontChooseLanguageVersion)
|
||||||
|
{
|
||||||
|
systemTask3.languageVersion = Utils::LanguageVersion::CXX17;
|
||||||
|
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask3);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.languageVersion, Utils::LanguageVersion::CXX98);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, FirstTaskIsNotMergedAgain)
|
||||||
|
{
|
||||||
|
systemTask1.isMerged = true;
|
||||||
|
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_FALSE(systemTask2.isMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, DontMergeAlreadyMergedFirstTask)
|
||||||
|
{
|
||||||
|
systemTask1.isMerged = true;
|
||||||
|
|
||||||
|
bool isMerged = Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_FALSE(isMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, SecondTaskIsNotMergedAgain)
|
||||||
|
{
|
||||||
|
systemTask2.isMerged = true;
|
||||||
|
|
||||||
|
Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_THAT(systemTask1.includes, ElementsAre(1, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTasksMerger, DontMergeAlreadyMergedSecondTask)
|
||||||
|
{
|
||||||
|
systemTask2.isMerged = true;
|
||||||
|
|
||||||
|
bool isMerged = Merger::mergePchTasks(systemTask1, systemTask2);
|
||||||
|
|
||||||
|
ASSERT_FALSE(isMerged);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
@@ -241,12 +241,6 @@ protected:
|
|||||||
Manager collectorManger{generatedFiles};
|
Manager collectorManger{generatedFiles};
|
||||||
NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback;
|
NiceMock<MockFunction<void(int, int)>> mockSetProgressCallback;
|
||||||
ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()};
|
ClangBackEnd::ProgressCounter progressCounter{mockSetProgressCallback.AsStdFunction()};
|
||||||
Scheduler indexerScheduler{collectorManger,
|
|
||||||
indexerQueue,
|
|
||||||
progressCounter,
|
|
||||||
1,
|
|
||||||
ClangBackEnd::CallDoInMainThreadAfterFinished::Yes};
|
|
||||||
SymbolIndexerTaskQueue indexerQueue{indexerScheduler, progressCounter};
|
|
||||||
ClangBackEnd::SymbolIndexer indexer{indexerQueue,
|
ClangBackEnd::SymbolIndexer indexer{indexerQueue,
|
||||||
mockSymbolStorage,
|
mockSymbolStorage,
|
||||||
mockBuildDependenciesStorage,
|
mockBuildDependenciesStorage,
|
||||||
@@ -254,6 +248,12 @@ protected:
|
|||||||
filePathCache,
|
filePathCache,
|
||||||
fileStatusCache,
|
fileStatusCache,
|
||||||
mockSqliteTransactionBackend};
|
mockSqliteTransactionBackend};
|
||||||
|
SymbolIndexerTaskQueue indexerQueue{indexerScheduler, progressCounter};
|
||||||
|
Scheduler indexerScheduler{collectorManger,
|
||||||
|
indexerQueue,
|
||||||
|
progressCounter,
|
||||||
|
1,
|
||||||
|
ClangBackEnd::CallDoInMainThreadAfterFinished::Yes};
|
||||||
MockSymbolsCollector &mockCollector{static_cast<MockSymbolsCollector&>(collectorManger.unusedProcessor())};
|
MockSymbolsCollector &mockCollector{static_cast<MockSymbolsCollector&>(collectorManger.unusedProcessor())};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-DBAR=1",
|
"-DBAR=1",
|
||||||
"-DFOO=1",
|
"-DFOO=1",
|
||||||
"-I",
|
"-I",
|
||||||
@@ -299,7 +299,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInColl
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-DBAR=1",
|
"-DBAR=1",
|
||||||
"-DFOO=1",
|
"-DFOO=1",
|
||||||
"-I",
|
"-I",
|
||||||
@@ -332,7 +332,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithoutPrecompiledHeaderInC
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-DBAR=1",
|
"-DBAR=1",
|
||||||
"-DFOO=1",
|
"-DFOO=1",
|
||||||
"-I",
|
"-I",
|
||||||
@@ -512,7 +512,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderWithoutProjectPartArtifact)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-DBAR=1",
|
"-DBAR=1",
|
||||||
"-DFOO=1",
|
"-DFOO=1",
|
||||||
"-I",
|
"-I",
|
||||||
@@ -564,7 +564,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderWithProjectPartArtifact)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-DBAR=1",
|
"-DBAR=1",
|
||||||
"-DFOO=1",
|
"-DFOO=1",
|
||||||
"-I",
|
"-I",
|
||||||
@@ -620,7 +620,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-DBAR=1",
|
"-DBAR=1",
|
||||||
"-DFOO=1",
|
"-DFOO=1",
|
||||||
"-I",
|
"-I",
|
||||||
@@ -682,7 +682,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-DBAR=1",
|
"-DBAR=1",
|
||||||
"-DFOO=1",
|
"-DFOO=1",
|
||||||
"-I",
|
"-I",
|
||||||
@@ -717,7 +717,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsNotUsingPrecompiledHeaderIfItNotExists)
|
|||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdlibinc",
|
"-nostdinc++",
|
||||||
"-DBAR=1",
|
"-DBAR=1",
|
||||||
"-DFOO=1",
|
"-DFOO=1",
|
||||||
"-I",
|
"-I",
|
||||||
|
@@ -46,7 +46,7 @@ protected:
|
|||||||
{3, SourceType::ProjectInclude, 0},
|
{3, SourceType::ProjectInclude, 0},
|
||||||
{4, SourceType::TopSystemInclude, 0},
|
{4, SourceType::TopSystemInclude, 0},
|
||||||
{5, SourceType::TopProjectInclude, 0}};
|
{5, SourceType::TopProjectInclude, 0}};
|
||||||
UsedMacros usedMacros{{"YI", 1}, {"ER", 2}, {"SAN", 3}, {"SE", 4}, {"WU", 5}};
|
UsedMacros usedMacros{{"YI", 1}, {"ER", 2}, {"LIU", 2}, {"QI", 3}, {"SAN", 3}, {"SE", 4}, {"WU", 5}};
|
||||||
CompilerMacros compileMacros{{"YI", "1", 1},
|
CompilerMacros compileMacros{{"YI", "1", 1},
|
||||||
{"ER", "2", 2},
|
{"ER", "2", 2},
|
||||||
{"SAN", "3", 3},
|
{"SAN", "3", 3},
|
||||||
@@ -57,36 +57,35 @@ protected:
|
|||||||
|
|
||||||
TEST_F(UsedMacroFilter, SystemIncludes)
|
TEST_F(UsedMacroFilter, SystemIncludes)
|
||||||
{
|
{
|
||||||
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
|
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
|
||||||
|
|
||||||
ASSERT_THAT(filter.systemIncludes, ElementsAre(FilePathId{2}, FilePathId{4}));
|
ASSERT_THAT(filter.systemIncludes, ElementsAre(FilePathId{2}, FilePathId{4}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(UsedMacroFilter, ProjectIncludes)
|
TEST_F(UsedMacroFilter, ProjectIncludes)
|
||||||
{
|
{
|
||||||
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
|
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
|
||||||
|
|
||||||
ASSERT_THAT(filter.projectIncludes, ElementsAre(FilePathId{3}, FilePathId{5}));
|
ASSERT_THAT(filter.projectIncludes, ElementsAre(FilePathId{3}, FilePathId{5}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(UsedMacroFilter, TopSystemIncludes)
|
TEST_F(UsedMacroFilter, TopSystemIncludes)
|
||||||
{
|
{
|
||||||
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
|
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
|
||||||
|
|
||||||
ASSERT_THAT(filter.topSystemIncludes, ElementsAre(FilePathId{4}));
|
ASSERT_THAT(filter.topSystemIncludes, ElementsAre(FilePathId{4}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(UsedMacroFilter, TopProjectIncludes)
|
TEST_F(UsedMacroFilter, TopProjectIncludes)
|
||||||
{
|
{
|
||||||
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
|
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
|
||||||
|
|
||||||
ASSERT_THAT(filter.topProjectIncludes, ElementsAre(FilePathId{5}));
|
ASSERT_THAT(filter.topProjectIncludes, ElementsAre(FilePathId{5}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(UsedMacroFilter, AllIncludes)
|
TEST_F(UsedMacroFilter, AllIncludes)
|
||||||
{
|
{
|
||||||
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
|
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
|
||||||
|
|
||||||
ASSERT_THAT(filter.allIncludes,
|
ASSERT_THAT(filter.allIncludes,
|
||||||
ElementsAre(FilePathId{1}, FilePathId{2}, FilePathId{3}, FilePathId{4}, FilePathId{5}));
|
ElementsAre(FilePathId{1}, FilePathId{2}, FilePathId{3}, FilePathId{4}, FilePathId{5}));
|
||||||
@@ -94,36 +93,36 @@ TEST_F(UsedMacroFilter, AllIncludes)
|
|||||||
|
|
||||||
TEST_F(UsedMacroFilter, SystemUsedMacros)
|
TEST_F(UsedMacroFilter, SystemUsedMacros)
|
||||||
{
|
{
|
||||||
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
|
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
|
||||||
|
|
||||||
ASSERT_THAT(filter.systemUsedMacros, ElementsAre(UsedMacro{"ER", 2}, UsedMacro{"SE", 4}));
|
ASSERT_THAT(filter.systemUsedMacros, ElementsAre("ER", "SE", "LIU"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(UsedMacroFilter, ProjectUsedMacros)
|
TEST_F(UsedMacroFilter, ProjectUsedMacros)
|
||||||
{
|
{
|
||||||
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
|
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
|
||||||
|
|
||||||
ASSERT_THAT(filter.projectUsedMacros, ElementsAre(UsedMacro{"WU", 5}, UsedMacro{"SAN", 3}));
|
ASSERT_THAT(filter.projectUsedMacros, ElementsAre("QI", "WU", "SAN"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(UsedMacroFilter, SystemCompileMacros)
|
TEST_F(UsedMacroFilter, SystemCompileMacros)
|
||||||
{
|
{
|
||||||
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
|
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
|
||||||
|
|
||||||
filter.filter(compileMacros);
|
|
||||||
|
|
||||||
ASSERT_THAT(filter.systemCompilerMacros,
|
ASSERT_THAT(filter.systemCompilerMacros,
|
||||||
ElementsAre(CompilerMacro{"ER", "2", 2}, CompilerMacro{"SE", "4", 4}));
|
ElementsAre(CompilerMacro{"ER", "2", 2},
|
||||||
|
CompilerMacro{"SE", "4", 4},
|
||||||
|
CompilerMacro{"LIU"}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(UsedMacroFilter, ProjectCompileMacros)
|
TEST_F(UsedMacroFilter, ProjectCompileMacros)
|
||||||
{
|
{
|
||||||
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros);
|
ClangBackEnd::UsedMacroFilter filter(includes, usedMacros, compileMacros);
|
||||||
|
|
||||||
filter.filter(compileMacros);
|
|
||||||
|
|
||||||
ASSERT_THAT(filter.projectCompilerMacros,
|
ASSERT_THAT(filter.projectCompilerMacros,
|
||||||
ElementsAre(CompilerMacro{"WU", "5", 5}, CompilerMacro{"SAN", "3", 3}));
|
ElementsAre(CompilerMacro{"QI"},
|
||||||
|
CompilerMacro{"WU", "5", 5},
|
||||||
|
CompilerMacro{"SAN", "3", 3}));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
Reference in New Issue
Block a user