forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.9'
Change-Id: I7bdb6a4658c5fca1a7e1dda5adbb5613dabc6d18
This commit is contained in:
@@ -48,10 +48,11 @@ public:
|
|||||||
FilePathView outputPath = {},
|
FilePathView outputPath = {},
|
||||||
FilePathView includePchPath = {})
|
FilePathView includePchPath = {})
|
||||||
{
|
{
|
||||||
commandLine.reserve(128);
|
commandLine.reserve(1024);
|
||||||
|
|
||||||
addCompiler(projectInfo.language);
|
addCompiler(projectInfo.language);
|
||||||
addToolChainArguments(toolChainArguments);
|
addToolChainArguments(toolChainArguments);
|
||||||
|
addExtraFlags();
|
||||||
addLanguage(projectInfo, sourceType);
|
addLanguage(projectInfo, sourceType);
|
||||||
addLanguageVersion(projectInfo);
|
addLanguageVersion(projectInfo);
|
||||||
addNoStdIncAndNoStdLibInc(projectInfo.language);
|
addNoStdIncAndNoStdLibInc(projectInfo.language);
|
||||||
@@ -79,6 +80,8 @@ public:
|
|||||||
commandLine.emplace_back(argument);
|
commandLine.emplace_back(argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addExtraFlags() { commandLine.emplace_back("-DNOMINMAX"); }
|
||||||
|
|
||||||
static const char *language(const ProjectInfo &projectInfo, InputFileType sourceType)
|
static const char *language(const ProjectInfo &projectInfo, InputFileType sourceType)
|
||||||
{
|
{
|
||||||
switch (projectInfo.language) {
|
switch (projectInfo.language) {
|
||||||
|
@@ -30,9 +30,9 @@ namespace V2 {
|
|||||||
|
|
||||||
QDebug operator<<(QDebug debug, const FileContainer &container)
|
QDebug operator<<(QDebug debug, const FileContainer &container)
|
||||||
{
|
{
|
||||||
debug.nospace() << "FileContainer("
|
debug.nospace() << "FileContainer(" << container.filePath << ", "
|
||||||
<< container.filePath << ", "
|
|
||||||
<< container.commandLineArguments << ", "
|
<< container.commandLineArguments << ", "
|
||||||
|
<< container.unsavedFileContent.hasContent() << ", "
|
||||||
<< container.documentRevision;
|
<< container.documentRevision;
|
||||||
|
|
||||||
debug.nospace() << ")";
|
debug.nospace() << ")";
|
||||||
|
@@ -140,6 +140,13 @@ QTextCursor wordStartCursor(const QTextCursor &textCursor)
|
|||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString wordUnderCursor(const QTextCursor &cursor)
|
||||||
|
{
|
||||||
|
QTextCursor tc(cursor);
|
||||||
|
tc.select(QTextCursor::WordUnderCursor);
|
||||||
|
return tc.selectedText();
|
||||||
|
}
|
||||||
|
|
||||||
int utf8NthLineOffset(const QTextDocument *textDocument, const QByteArray &buffer, int line)
|
int utf8NthLineOffset(const QTextDocument *textDocument, const QByteArray &buffer, int line)
|
||||||
{
|
{
|
||||||
if (textDocument->blockCount() < line)
|
if (textDocument->blockCount() < line)
|
||||||
|
@@ -53,6 +53,7 @@ QTCREATOR_UTILS_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, u
|
|||||||
QTCREATOR_UTILS_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor);
|
QTCREATOR_UTILS_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor);
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor);
|
QTCREATOR_UTILS_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor);
|
||||||
|
QTCREATOR_UTILS_EXPORT QString wordUnderCursor(const QTextCursor &cursor);
|
||||||
|
|
||||||
QTCREATOR_UTILS_EXPORT int utf8NthLineOffset(const QTextDocument *textDocument,
|
QTCREATOR_UTILS_EXPORT int utf8NthLineOffset(const QTextDocument *textDocument,
|
||||||
const QByteArray &buffer,
|
const QByteArray &buffer,
|
||||||
|
@@ -39,9 +39,6 @@ namespace ClangFormat {
|
|||||||
static void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style,
|
static void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style,
|
||||||
ReplacementsToKeep replacementsToKeep)
|
ReplacementsToKeep replacementsToKeep)
|
||||||
{
|
{
|
||||||
if (replacementsToKeep == ReplacementsToKeep::All)
|
|
||||||
return;
|
|
||||||
|
|
||||||
style.MaxEmptyLinesToKeep = 2;
|
style.MaxEmptyLinesToKeep = 2;
|
||||||
style.SortIncludes = false;
|
style.SortIncludes = false;
|
||||||
style.SortUsingDeclarations = false;
|
style.SortUsingDeclarations = false;
|
||||||
@@ -67,9 +64,10 @@ static llvm::StringRef clearExtraNewline(llvm::StringRef text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static clang::tooling::Replacements filteredReplacements(
|
static clang::tooling::Replacements filteredReplacements(
|
||||||
|
const QByteArray &buffer,
|
||||||
const clang::tooling::Replacements &replacements,
|
const clang::tooling::Replacements &replacements,
|
||||||
int offset,
|
int utf8Offset,
|
||||||
int utf8LineLengthBeforeCursor,
|
int utf8Length,
|
||||||
int extraEmptySpaceOffset,
|
int extraEmptySpaceOffset,
|
||||||
ReplacementsToKeep replacementsToKeep)
|
ReplacementsToKeep replacementsToKeep)
|
||||||
{
|
{
|
||||||
@@ -77,14 +75,13 @@ static clang::tooling::Replacements filteredReplacements(
|
|||||||
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());
|
||||||
const bool replacementDoesNotMatchRestriction
|
const bool replacementDoesNotMatchRestriction
|
||||||
= (replacementsToKeep == ReplacementsToKeep::OnlyIndent
|
= replacementOffset >= utf8Offset + utf8Length
|
||||||
&& replacementOffset != offset - 1)
|
|| (replacementsToKeep == ReplacementsToKeep::OnlyIndent
|
||||||
|| (replacementsToKeep == ReplacementsToKeep::IndentAndBefore
|
&& (replacementOffset < utf8Offset - 1 || buffer.at(replacementOffset) != '\n'));
|
||||||
&& replacementOffset > offset + utf8LineLengthBeforeCursor - 1);
|
|
||||||
if (replacementDoesNotMatchRestriction)
|
if (replacementDoesNotMatchRestriction)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (replacementOffset >= offset - 1)
|
if (replacementOffset >= utf8Offset - 1)
|
||||||
replacementOffset += extraEmptySpaceOffset;
|
replacementOffset += extraEmptySpaceOffset;
|
||||||
|
|
||||||
llvm::StringRef text = replacementsToKeep == ReplacementsToKeep::OnlyIndent
|
llvm::StringRef text = replacementsToKeep == ReplacementsToKeep::OnlyIndent
|
||||||
@@ -151,13 +148,13 @@ 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 utf8Offset, const QTextBlock &block, bool secondTry)
|
||||||
{
|
{
|
||||||
const QString blockText = block.text();
|
const QString blockText = block.text();
|
||||||
int firstNonWhitespace = Utils::indexOf(blockText,
|
int firstNonWhitespace = Utils::indexOf(blockText,
|
||||||
[](const QChar &ch) { return !ch.isSpace(); });
|
[](const QChar &ch) { return !ch.isSpace(); });
|
||||||
if (firstNonWhitespace > 0)
|
if (firstNonWhitespace > 0)
|
||||||
offset += firstNonWhitespace;
|
utf8Offset += firstNonWhitespace;
|
||||||
|
|
||||||
const bool closingParenBlock = firstNonWhitespace >= 0
|
const bool closingParenBlock = firstNonWhitespace >= 0
|
||||||
&& blockText.at(firstNonWhitespace) == ')';
|
&& blockText.at(firstNonWhitespace) == ')';
|
||||||
@@ -176,12 +173,11 @@ static void modifyToIndentEmptyLines(
|
|||||||
if (closingParenBlock || prevBlock.text().endsWith(','))
|
if (closingParenBlock || prevBlock.text().endsWith(','))
|
||||||
dummyText = "&& a";
|
dummyText = "&& a";
|
||||||
|
|
||||||
length += dummyText.length();
|
buffer.insert(utf8Offset, dummyText);
|
||||||
buffer.insert(offset, dummyText);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (secondTry) {
|
if (secondTry) {
|
||||||
int nextLinePos = buffer.indexOf('\n', offset);
|
int nextLinePos = buffer.indexOf('\n', utf8Offset);
|
||||||
if (nextLinePos < 0)
|
if (nextLinePos < 0)
|
||||||
nextLinePos = buffer.size() - 1;
|
nextLinePos = buffer.size() - 1;
|
||||||
|
|
||||||
@@ -190,7 +186,6 @@ static void modifyToIndentEmptyLines(
|
|||||||
// unclosed parentheses.
|
// unclosed parentheses.
|
||||||
// TODO: Does it help to add different endings depending on the context?
|
// TODO: Does it help to add different endings depending on the context?
|
||||||
buffer.insert(nextLinePos, ')');
|
buffer.insert(nextLinePos, ')');
|
||||||
length += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,13 +246,13 @@ static TextEditor::Replacements utf16Replacements(const QTextBlock &block,
|
|||||||
return convertedReplacements;
|
return convertedReplacements;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void applyReplacements(const QTextBlock &block, const TextEditor::Replacements &replacements)
|
static void applyReplacements(QTextDocument *doc, const TextEditor::Replacements &replacements)
|
||||||
{
|
{
|
||||||
if (replacements.empty())
|
if (replacements.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int fullOffsetShift = 0;
|
int fullOffsetShift = 0;
|
||||||
QTextCursor editCursor(block);
|
QTextCursor editCursor(doc);
|
||||||
for (const TextEditor::Replacement &replacement : replacements) {
|
for (const TextEditor::Replacement &replacement : replacements) {
|
||||||
editCursor.beginEditBlock();
|
editCursor.beginEditBlock();
|
||||||
editCursor.setPosition(replacement.offset + fullOffsetShift);
|
editCursor.setPosition(replacement.offset + fullOffsetShift);
|
||||||
@@ -305,24 +300,12 @@ void ClangFormatBaseIndenter::indent(const QTextCursor &cursor,
|
|||||||
int cursorPositionInEditor)
|
int cursorPositionInEditor)
|
||||||
{
|
{
|
||||||
if (cursor.hasSelection()) {
|
if (cursor.hasSelection()) {
|
||||||
// Calling currentBlock.next() might be unsafe because we change the document.
|
indentBlocks(m_doc->findBlock(cursor.selectionStart()),
|
||||||
// Let's operate with block numbers instead.
|
m_doc->findBlock(cursor.selectionEnd()),
|
||||||
const int startNumber = m_doc->findBlock(cursor.selectionStart()).blockNumber();
|
typedChar,
|
||||||
const int endNumber = m_doc->findBlock(cursor.selectionEnd()).blockNumber();
|
cursorPositionInEditor);
|
||||||
for (int currentBlockNumber = startNumber; currentBlockNumber <= endNumber;
|
|
||||||
++currentBlockNumber) {
|
|
||||||
const QTextBlock currentBlock = m_doc->findBlockByNumber(currentBlockNumber);
|
|
||||||
if (currentBlock.isValid()) {
|
|
||||||
const int blocksAmount = m_doc->blockCount();
|
|
||||||
indentBlock(currentBlock, typedChar, cursorPositionInEditor);
|
|
||||||
|
|
||||||
// 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 {
|
||||||
indentBlock(cursor.block(), typedChar, cursorPositionInEditor);
|
indentBlocks(cursor.block(), cursor.block(), typedChar, cursorPositionInEditor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,70 +324,55 @@ void ClangFormatBaseIndenter::reindent(const QTextCursor &cursor,
|
|||||||
indent(cursor, QChar::Null, cursorPositionInEditor);
|
indent(cursor, QChar::Null, cursorPositionInEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditor::Replacements ClangFormatBaseIndenter::format(const QTextCursor &cursor,
|
TextEditor::Replacements ClangFormatBaseIndenter::format(
|
||||||
int cursorPositionInEditor)
|
const TextEditor::RangesInLines &rangesInLines)
|
||||||
{
|
{
|
||||||
int utf8Offset;
|
if (rangesInLines.empty())
|
||||||
int utf8Length;
|
return TextEditor::Replacements();
|
||||||
|
|
||||||
|
int utf8Offset = -1;
|
||||||
QTextBlock block;
|
QTextBlock block;
|
||||||
|
|
||||||
const QByteArray buffer = m_doc->toPlainText().toUtf8();
|
const QByteArray buffer = m_doc->toPlainText().toUtf8();
|
||||||
if (cursor.hasSelection()) {
|
std::vector<clang::tooling::Range> ranges;
|
||||||
block = m_doc->findBlock(cursor.selectionStart());
|
ranges.reserve(rangesInLines.size());
|
||||||
const QTextBlock end = m_doc->findBlock(cursor.selectionEnd());
|
|
||||||
utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
|
||||||
QTC_ASSERT(utf8Offset >= 0, return TextEditor::Replacements(););
|
|
||||||
utf8Length = selectedLines(m_doc, block, end).toUtf8().size();
|
|
||||||
} else {
|
|
||||||
block = cursor.block();
|
|
||||||
utf8Offset = Utils::Text::utf8NthLineOffset(m_doc, buffer, block.blockNumber() + 1);
|
|
||||||
QTC_ASSERT(utf8Offset >= 0, return TextEditor::Replacements(););
|
|
||||||
|
|
||||||
utf8Length = block.text().toUtf8().size();
|
for (auto &range : rangesInLines) {
|
||||||
|
const int utf8StartOffset = Utils::Text::utf8NthLineOffset(m_doc, buffer, range.startLine);
|
||||||
|
const QTextBlock end = m_doc->findBlockByNumber(range.endLine - 1);
|
||||||
|
int utf8RangeLength = end.text().toUtf8().size();
|
||||||
|
if (range.endLine > range.startLine) {
|
||||||
|
utf8RangeLength += Utils::Text::utf8NthLineOffset(m_doc, buffer, range.endLine)
|
||||||
|
- utf8StartOffset;
|
||||||
|
}
|
||||||
|
ranges.emplace_back(static_cast<unsigned int>(utf8StartOffset),
|
||||||
|
static_cast<unsigned int>(utf8RangeLength));
|
||||||
|
|
||||||
|
if (utf8Offset < 0) {
|
||||||
|
utf8Offset = utf8StartOffset;
|
||||||
|
block = m_doc->findBlockByNumber(range.startLine - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const TextEditor::Replacements toReplace = replacements(buffer,
|
clang::format::FormatStyle style = styleForFile();
|
||||||
|
clang::format::FormattingAttemptStatus status;
|
||||||
|
const clang::tooling::Replacements clangReplacements
|
||||||
|
= reformat(style, buffer.data(), ranges, m_fileName.toString().toStdString(), &status);
|
||||||
|
const TextEditor::Replacements toReplace = utf16Replacements(block,
|
||||||
utf8Offset,
|
utf8Offset,
|
||||||
utf8Length,
|
buffer,
|
||||||
block,
|
clangReplacements);
|
||||||
cursorPositionInEditor,
|
applyReplacements(m_doc, toReplace);
|
||||||
ReplacementsToKeep::All,
|
|
||||||
QChar::Null);
|
|
||||||
applyReplacements(block, toReplace);
|
|
||||||
|
|
||||||
return toReplace;
|
return toReplace;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditor::Replacements ClangFormatBaseIndenter::format(
|
|
||||||
const QTextCursor &cursor,
|
|
||||||
const TextEditor::TabSettings & /*tabSettings*/,
|
|
||||||
int cursorPositionInEditor)
|
|
||||||
{
|
|
||||||
return format(cursor, cursorPositionInEditor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void 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;);
|
|
||||||
const TextEditor::Replacements toReplace = replacements(buffer,
|
|
||||||
utf8Offset,
|
|
||||||
0,
|
|
||||||
block,
|
|
||||||
cursorPositionInEditor,
|
|
||||||
ReplacementsToKeep::IndentAndBefore,
|
|
||||||
typedChar);
|
|
||||||
applyReplacements(block, toReplace);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool doNotIndentInContext(QTextDocument *doc, int pos)
|
static bool doNotIndentInContext(QTextDocument *doc, int pos)
|
||||||
{
|
{
|
||||||
const QChar character = doc->characterAt(pos);
|
const QChar character = doc->characterAt(pos);
|
||||||
const QTextBlock currentBlock = doc->findBlock(pos);
|
const QTextBlock currentBlock = doc->findBlock(pos);
|
||||||
const QString text = currentBlock.text().left(pos - currentBlock.position());
|
const QString text = currentBlock.text().left(pos - currentBlock.position());
|
||||||
|
// NOTE: check if "<<" and ">>" always work correctly.
|
||||||
switch (character.toLatin1()) {
|
switch (character.toLatin1()) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -419,33 +387,30 @@ static bool doNotIndentInContext(QTextDocument *doc, int pos)
|
|||||||
if (pos > 0 && doc->characterAt(pos - 1) != ':')
|
if (pos > 0 && doc->characterAt(pos - 1) != ':')
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
case '<':
|
|
||||||
case '>':
|
|
||||||
// "<<" and ">>" could be problematic
|
|
||||||
if (pos > 0 && doc->characterAt(pos - 1) == character)
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
void ClangFormatBaseIndenter::indentBlocks(const QTextBlock &startBlock,
|
||||||
|
const QTextBlock &endBlock,
|
||||||
const QChar &typedChar,
|
const QChar &typedChar,
|
||||||
int cursorPositionInEditor)
|
int cursorPositionInEditor)
|
||||||
{
|
{
|
||||||
QTextBlock currentBlock = block;
|
|
||||||
const int blockPosition = currentBlock.position();
|
|
||||||
trimFirstNonEmptyBlock(currentBlock);
|
|
||||||
|
|
||||||
if (typedChar != QChar::Null && cursorPositionInEditor > 0
|
if (typedChar != QChar::Null && cursorPositionInEditor > 0
|
||||||
&& m_doc->characterAt(cursorPositionInEditor - 1) == typedChar
|
&& m_doc->characterAt(cursorPositionInEditor - 1) == typedChar
|
||||||
&& doNotIndentInContext(m_doc, cursorPositionInEditor - 1)) {
|
&& doNotIndentInContext(m_doc, cursorPositionInEditor - 1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int startBlockPosition = startBlock.position();
|
||||||
|
trimFirstNonEmptyBlock(startBlock);
|
||||||
|
if (cursorPositionInEditor >= 0)
|
||||||
|
cursorPositionInEditor += startBlock.position() - startBlockPosition;
|
||||||
|
|
||||||
|
ReplacementsToKeep replacementsToKeep = ReplacementsToKeep::OnlyIndent;
|
||||||
if (formatWhileTyping()
|
if (formatWhileTyping()
|
||||||
&& (cursorPositionInEditor == -1 || cursorPositionInEditor >= blockPosition)
|
&& (cursorPositionInEditor == -1 || cursorPositionInEditor >= startBlockPosition)
|
||||||
&& (typedChar == QChar::Null || typedChar == ';' || typedChar == '}')) {
|
&& (typedChar == QChar::Null || typedChar == ';' || typedChar == '}')) {
|
||||||
// Format before current position only in case the cursor is inside the indented block.
|
// 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
|
// So if cursor position is less then the block position then the current line is before
|
||||||
@@ -453,26 +418,23 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
|||||||
// cursorPositionInEditor == -1 means the consition matches automatically.
|
// cursorPositionInEditor == -1 means the consition matches automatically.
|
||||||
|
|
||||||
// Format only before newline or complete statement not to break code.
|
// Format only before newline or complete statement not to break code.
|
||||||
if (cursorPositionInEditor >= 0)
|
replacementsToKeep = ReplacementsToKeep::IndentAndBefore;
|
||||||
cursorPositionInEditor += currentBlock.position() - blockPosition;
|
|
||||||
else
|
|
||||||
cursorPositionInEditor = currentBlock.position();
|
|
||||||
|
|
||||||
indentBeforeCursor(currentBlock, typedChar, cursorPositionInEditor);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
startBlock.blockNumber() + 1);
|
||||||
QTC_ASSERT(utf8Offset >= 0, return;);
|
QTC_ASSERT(utf8Offset >= 0, return;);
|
||||||
|
const int utf8Length = selectedLines(m_doc, startBlock, endBlock).toUtf8().size();
|
||||||
|
|
||||||
applyReplacements(currentBlock,
|
applyReplacements(m_doc,
|
||||||
replacements(buffer,
|
replacements(buffer,
|
||||||
utf8Offset,
|
utf8Offset,
|
||||||
0,
|
utf8Length,
|
||||||
currentBlock,
|
startBlock,
|
||||||
cursorPositionInEditor,
|
endBlock,
|
||||||
ReplacementsToKeep::OnlyIndent,
|
replacementsToKeep,
|
||||||
typedChar));
|
typedChar));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,12 +443,13 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
|||||||
const TextEditor::TabSettings & /*tabSettings*/,
|
const TextEditor::TabSettings & /*tabSettings*/,
|
||||||
int cursorPositionInEditor)
|
int cursorPositionInEditor)
|
||||||
{
|
{
|
||||||
indentBlock(block, typedChar, cursorPositionInEditor);
|
indentBlocks(block, block, typedChar, cursorPositionInEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int cursorPositionInEditor)
|
int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int /*cursorPositionInEditor*/)
|
||||||
{
|
{
|
||||||
trimFirstNonEmptyBlock(block);
|
trimFirstNonEmptyBlock(block);
|
||||||
|
|
||||||
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 0;);
|
QTC_ASSERT(utf8Offset >= 0, return 0;);
|
||||||
@@ -495,7 +458,7 @@ int ClangFormatBaseIndenter::indentFor(const QTextBlock &block, int cursorPositi
|
|||||||
utf8Offset,
|
utf8Offset,
|
||||||
0,
|
0,
|
||||||
block,
|
block,
|
||||||
cursorPositionInEditor,
|
block,
|
||||||
ReplacementsToKeep::OnlyIndent);
|
ReplacementsToKeep::OnlyIndent);
|
||||||
|
|
||||||
if (toReplace.empty())
|
if (toReplace.empty())
|
||||||
@@ -535,11 +498,20 @@ void ClangFormatBaseIndenter::formatOrIndent(const QTextCursor &cursor,
|
|||||||
const TextEditor::TabSettings & /*tabSettings*/,
|
const TextEditor::TabSettings & /*tabSettings*/,
|
||||||
int cursorPositionInEditor)
|
int cursorPositionInEditor)
|
||||||
{
|
{
|
||||||
if (formatCodeInsteadOfIndent())
|
if (formatCodeInsteadOfIndent()) {
|
||||||
format(cursor, cursorPositionInEditor);
|
QTextBlock start;
|
||||||
else
|
QTextBlock end;
|
||||||
|
if (cursor.hasSelection()) {
|
||||||
|
start = m_doc->findBlock(cursor.selectionStart());
|
||||||
|
end = m_doc->findBlock(cursor.selectionEnd());
|
||||||
|
} else {
|
||||||
|
start = end = cursor.block();
|
||||||
|
}
|
||||||
|
format({{start.blockNumber() + 1, end.blockNumber() + 1}});
|
||||||
|
} else {
|
||||||
indent(cursor, QChar::Null, cursorPositionInEditor);
|
indent(cursor, QChar::Null, cursorPositionInEditor);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clang::format::FormatStyle ClangFormatBaseIndenter::styleForFile() const
|
clang::format::FormatStyle ClangFormatBaseIndenter::styleForFile() const
|
||||||
{
|
{
|
||||||
@@ -574,44 +546,39 @@ static int formattingRangeStart(const QTextBlock ¤tBlock,
|
|||||||
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 &startBlock,
|
||||||
int cursorPositionInEditor,
|
const QTextBlock &endBlock,
|
||||||
ReplacementsToKeep replacementsToKeep,
|
ReplacementsToKeep replacementsToKeep,
|
||||||
const QChar &typedChar,
|
const QChar &typedChar,
|
||||||
bool secondTry) const
|
bool secondTry) const
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(replacementsToKeep != ReplacementsToKeep::All, return TextEditor::Replacements());
|
||||||
|
|
||||||
clang::format::FormatStyle style = styleForFile();
|
clang::format::FormatStyle style = styleForFile();
|
||||||
|
|
||||||
int originalOffsetUtf8 = utf8Offset;
|
int originalOffsetUtf8 = utf8Offset;
|
||||||
int originalLengthUtf8 = utf8Length;
|
int originalLengthUtf8 = utf8Length;
|
||||||
QByteArray originalBuffer = buffer;
|
QByteArray originalBuffer = buffer;
|
||||||
|
|
||||||
int utf8LineLengthBeforeCursor = 0;
|
|
||||||
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 extraEmptySpaceOffset = 0;
|
|
||||||
int rangeStart = 0;
|
int rangeStart = 0;
|
||||||
if (replacementsToKeep != ReplacementsToKeep::All) {
|
|
||||||
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
|
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore)
|
||||||
rangeStart = formattingRangeStart(block, buffer, lastSaveRevision());
|
rangeStart = formattingRangeStart(startBlock, buffer, lastSaveRevision());
|
||||||
|
|
||||||
extraEmptySpaceOffset = previousEmptyLinesLength(block);
|
int extraEmptySpaceOffset = previousEmptyLinesLength(startBlock);
|
||||||
utf8Offset -= extraEmptySpaceOffset;
|
utf8Offset -= extraEmptySpaceOffset;
|
||||||
buffer.remove(utf8Offset, extraEmptySpaceOffset);
|
buffer.remove(utf8Offset, extraEmptySpaceOffset);
|
||||||
|
|
||||||
adjustFormatStyleForLineBreak(style, replacementsToKeep);
|
adjustFormatStyleForLineBreak(style, replacementsToKeep);
|
||||||
modifyToIndentEmptyLines(buffer, utf8Offset, utf8Length, block, secondTry);
|
if (typedChar == QChar::Null && startBlock == endBlock) {
|
||||||
|
modifyToIndentEmptyLines(buffer, utf8Offset, startBlock, secondTry);
|
||||||
|
utf8Length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) {
|
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) {
|
||||||
buffer.insert(utf8Offset - 1, " //");
|
buffer.insert(utf8Offset - 1, " //");
|
||||||
extraEmptySpaceOffset -= 3;
|
extraEmptySpaceOffset -= 3;
|
||||||
utf8Offset += 3;
|
utf8Offset += 3;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (replacementsToKeep != ReplacementsToKeep::IndentAndBefore || utf8Offset < rangeStart)
|
if (replacementsToKeep != ReplacementsToKeep::IndentAndBefore || utf8Offset < rangeStart)
|
||||||
rangeStart = utf8Offset;
|
rangeStart = utf8Offset;
|
||||||
@@ -630,9 +597,10 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
|
|||||||
|
|
||||||
clang::tooling::Replacements filtered;
|
clang::tooling::Replacements filtered;
|
||||||
if (status.FormatComplete) {
|
if (status.FormatComplete) {
|
||||||
filtered = filteredReplacements(clangReplacements,
|
filtered = filteredReplacements(buffer,
|
||||||
|
clangReplacements,
|
||||||
utf8Offset,
|
utf8Offset,
|
||||||
utf8LineLengthBeforeCursor,
|
utf8Length,
|
||||||
extraEmptySpaceOffset,
|
extraEmptySpaceOffset,
|
||||||
replacementsToKeep);
|
replacementsToKeep);
|
||||||
}
|
}
|
||||||
@@ -642,14 +610,14 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
|
|||||||
return replacements(originalBuffer,
|
return replacements(originalBuffer,
|
||||||
originalOffsetUtf8,
|
originalOffsetUtf8,
|
||||||
originalLengthUtf8,
|
originalLengthUtf8,
|
||||||
block,
|
startBlock,
|
||||||
cursorPositionInEditor,
|
endBlock,
|
||||||
replacementsToKeep,
|
replacementsToKeep,
|
||||||
typedChar,
|
typedChar,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return utf16Replacements(block, originalOffsetUtf8, originalBuffer, filtered);
|
return utf16Replacements(startBlock, originalOffsetUtf8, originalBuffer, filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ClangFormat
|
} // namespace ClangFormat
|
||||||
|
@@ -53,9 +53,8 @@ public:
|
|||||||
void formatOrIndent(const QTextCursor &cursor,
|
void formatOrIndent(const QTextCursor &cursor,
|
||||||
const TextEditor::TabSettings &tabSettings,
|
const TextEditor::TabSettings &tabSettings,
|
||||||
int cursorPositionInEditor = -1) override;
|
int cursorPositionInEditor = -1) override;
|
||||||
TextEditor::Replacements format(const QTextCursor &cursor,
|
TextEditor::Replacements format(
|
||||||
const TextEditor::TabSettings &tabSettings,
|
const TextEditor::RangesInLines &rangesInLines = TextEditor::RangesInLines()) override;
|
||||||
int cursorPositionInEditor = -1) override;
|
|
||||||
|
|
||||||
void indentBlock(const QTextBlock &block,
|
void indentBlock(const QTextBlock &block,
|
||||||
const QChar &typedChar,
|
const QChar &typedChar,
|
||||||
@@ -75,18 +74,17 @@ protected:
|
|||||||
virtual int lastSaveRevision() const { return 0; }
|
virtual int lastSaveRevision() const { return 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
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 indentBlocks(const QTextBlock &startBlock,
|
||||||
int indentFor(const QTextBlock &block, int cursorPositionInEditor);
|
const QTextBlock &endBlock,
|
||||||
void indentBeforeCursor(const QTextBlock &block,
|
|
||||||
const QChar &typedChar,
|
const QChar &typedChar,
|
||||||
int cursorPositionInEditor);
|
int cursorPositionInEditor);
|
||||||
|
int indentFor(const QTextBlock &block, 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 &startBlock,
|
||||||
int cursorPositionInEditor,
|
const QTextBlock &endBlock,
|
||||||
ReplacementsToKeep replacementsToKeep,
|
ReplacementsToKeep replacementsToKeep,
|
||||||
const QChar &typedChar = QChar::Null,
|
const QChar &typedChar = QChar::Null,
|
||||||
bool secondTry = false) const;
|
bool secondTry = false) const;
|
||||||
|
@@ -37,6 +37,9 @@
|
|||||||
#include <cpptools/compileroptionsbuilder.h>
|
#include <cpptools/compileroptionsbuilder.h>
|
||||||
#include <cpptools/projectpart.h>
|
#include <cpptools/projectpart.h>
|
||||||
#include <cpptools/headerpathfilter.h>
|
#include <cpptools/headerpathfilter.h>
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
@@ -140,8 +143,10 @@ HeaderAndSources ProjectUpdater::headerAndSourcesFromProjectPart(
|
|||||||
HeaderAndSources headerAndSources;
|
HeaderAndSources headerAndSources;
|
||||||
headerAndSources.reserve(std::size_t(projectPart->files.size()) * 3 / 2);
|
headerAndSources.reserve(std::size_t(projectPart->files.size()) * 3 / 2);
|
||||||
|
|
||||||
for (const CppTools::ProjectFile &projectFile : projectPart->files)
|
for (const CppTools::ProjectFile &projectFile : projectPart->files) {
|
||||||
|
if (projectFile.active)
|
||||||
addToHeaderAndSources(headerAndSources, projectFile);
|
addToHeaderAndSources(headerAndSources, projectFile);
|
||||||
|
}
|
||||||
|
|
||||||
std::sort(headerAndSources.sources.begin(), headerAndSources.sources.end());
|
std::sort(headerAndSources.sources.begin(), headerAndSources.sources.end());
|
||||||
std::sort(headerAndSources.headers.begin(), headerAndSources.headers.end());
|
std::sort(headerAndSources.headers.begin(), headerAndSources.headers.end());
|
||||||
@@ -231,6 +236,21 @@ ClangBackEnd::IncludeSearchPaths convertToIncludeSearchPaths(
|
|||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString projectDirectory(ProjectExplorer::Project *project)
|
||||||
|
{
|
||||||
|
if (project)
|
||||||
|
return project->rootProjectDirectory().toString();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString buildDirectory(ProjectExplorer::Project *project)
|
||||||
|
{
|
||||||
|
if (project && project->activeTarget() && project->activeTarget()->activeBuildConfiguration())
|
||||||
|
return project->activeTarget()->activeBuildConfiguration()->buildDirectory().toString();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ProjectUpdater::SystemAndProjectIncludeSearchPaths ProjectUpdater::createIncludeSearchPaths(
|
ProjectUpdater::SystemAndProjectIncludeSearchPaths ProjectUpdater::createIncludeSearchPaths(
|
||||||
@@ -239,7 +259,9 @@ ProjectUpdater::SystemAndProjectIncludeSearchPaths ProjectUpdater::createInclude
|
|||||||
CppTools::HeaderPathFilter filter(projectPart,
|
CppTools::HeaderPathFilter filter(projectPart,
|
||||||
CppTools::UseTweakedHeaderPaths::Yes,
|
CppTools::UseTweakedHeaderPaths::Yes,
|
||||||
CLANG_VERSION,
|
CLANG_VERSION,
|
||||||
CLANG_RESOURCE_DIR);
|
CLANG_RESOURCE_DIR,
|
||||||
|
projectDirectory(projectPart.project),
|
||||||
|
buildDirectory(projectPart.project));
|
||||||
filter.process();
|
filter.process();
|
||||||
|
|
||||||
return {convertToIncludeSearchPaths(filter.systemHeaderPaths, filter.builtInHeaderPaths),
|
return {convertToIncludeSearchPaths(filter.systemHeaderPaths, filter.builtInHeaderPaths),
|
||||||
@@ -277,6 +299,13 @@ ClangBackEnd::ProjectPartContainers ProjectUpdater::toProjectPartContainers(
|
|||||||
std::vector<ClangBackEnd::ProjectPartContainer> projectPartContainers;
|
std::vector<ClangBackEnd::ProjectPartContainer> projectPartContainers;
|
||||||
projectPartContainers.reserve(projectParts.size());
|
projectPartContainers.reserve(projectParts.size());
|
||||||
|
|
||||||
|
projectParts.erase(std::remove_if(projectParts.begin(),
|
||||||
|
projectParts.end(),
|
||||||
|
[](const CppTools::ProjectPart *projectPart) {
|
||||||
|
return !projectPart->selectedForBuilding;
|
||||||
|
}),
|
||||||
|
projectParts.end());
|
||||||
|
|
||||||
std::transform(projectParts.begin(),
|
std::transform(projectParts.begin(),
|
||||||
projectParts.end(),
|
projectParts.end(),
|
||||||
std::back_inserter(projectPartContainers),
|
std::back_inserter(projectPartContainers),
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "pchmanagerprojectupdater.h"
|
#include "pchmanagerprojectupdater.h"
|
||||||
|
|
||||||
#include <cpptools/cppmodelmanager.h>
|
#include <cpptools/cppmodelmanager.h>
|
||||||
|
#include <projectexplorer/extracompiler.h>
|
||||||
|
|
||||||
#include <filecontainerv2.h>
|
#include <filecontainerv2.h>
|
||||||
|
|
||||||
@@ -50,7 +51,8 @@ CLANGPCHMANAGER_EXPORT std::vector<CppTools::ProjectPart*> createProjectParts(Pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename ProjectUpdaterType>
|
template<typename ProjectUpdaterType>
|
||||||
class QtCreatorProjectUpdater : public ProjectUpdaterType
|
class QtCreatorProjectUpdater : public ProjectUpdaterType,
|
||||||
|
public ProjectExplorer::ExtraCompilerFactoryObserver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <typename ClientType>
|
template <typename ClientType>
|
||||||
@@ -90,6 +92,15 @@ public:
|
|||||||
ProjectUpdaterType::removeGeneratedFiles({ClangBackEnd::FilePath{filePath}});
|
ProjectUpdaterType::removeGeneratedFiles({ClangBackEnd::FilePath{filePath}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void newExtraCompiler(const ProjectExplorer::Project *,
|
||||||
|
const Utils::FileName &,
|
||||||
|
const Utils::FileNameList &targets) override
|
||||||
|
{
|
||||||
|
for (const Utils::FileName &target : targets)
|
||||||
|
abstractEditorUpdated(target.toString(), {});
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void connectToCppModelManager()
|
void connectToCppModelManager()
|
||||||
{
|
{
|
||||||
|
@@ -89,6 +89,10 @@ bool FixitsRefactoringFile::apply()
|
|||||||
= CppTools::CppCodeStyleSettings::currentProjectTabSettings();
|
= CppTools::CppCodeStyleSettings::currentProjectTabSettings();
|
||||||
|
|
||||||
// Apply changes
|
// Apply changes
|
||||||
|
std::unique_ptr<TextEditor::Indenter> indenter;
|
||||||
|
QString lastFilename;
|
||||||
|
ReplacementOperations operationsForFile;
|
||||||
|
|
||||||
for (int i=0; i < m_replacementOperations.size(); ++i) {
|
for (int i=0; i < m_replacementOperations.size(); ++i) {
|
||||||
ReplacementOperation &op = *m_replacementOperations[i];
|
ReplacementOperation &op = *m_replacementOperations[i];
|
||||||
if (op.apply) {
|
if (op.apply) {
|
||||||
@@ -103,15 +107,19 @@ bool FixitsRefactoringFile::apply()
|
|||||||
|
|
||||||
// Apply
|
// Apply
|
||||||
QTextDocument *doc = document(op.fileName);
|
QTextDocument *doc = document(op.fileName);
|
||||||
std::unique_ptr<TextEditor::Indenter> indenter(factory->createIndenter(doc));
|
if (lastFilename != op.fileName) {
|
||||||
|
if (indenter)
|
||||||
|
format(*indenter, doc, operationsForFile, i);
|
||||||
|
operationsForFile.clear();
|
||||||
|
indenter = std::unique_ptr<TextEditor::Indenter>(factory->createIndenter(doc));
|
||||||
indenter->setFileName(Utils::FileName::fromString(op.fileName));
|
indenter->setFileName(Utils::FileName::fromString(op.fileName));
|
||||||
|
}
|
||||||
|
|
||||||
QTextCursor cursor(doc);
|
QTextCursor cursor(doc);
|
||||||
cursor.setPosition(op.pos);
|
cursor.setPosition(op.pos);
|
||||||
cursor.setPosition(op.pos + op.length, QTextCursor::KeepAnchor);
|
cursor.setPosition(op.pos + op.length, QTextCursor::KeepAnchor);
|
||||||
cursor.insertText(op.text);
|
cursor.insertText(op.text);
|
||||||
|
operationsForFile.push_back(&op);
|
||||||
tryToFormat(*indenter, tabSettings, doc, op, i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,28 +138,29 @@ bool FixitsRefactoringFile::apply()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixitsRefactoringFile::tryToFormat(TextEditor::Indenter &indenter,
|
void FixitsRefactoringFile::format(TextEditor::Indenter &indenter,
|
||||||
const TextEditor::TabSettings &tabSettings,
|
|
||||||
QTextDocument *doc,
|
QTextDocument *doc,
|
||||||
const ReplacementOperation &op,
|
const ReplacementOperations &operationsForFile,
|
||||||
int currentIndex)
|
int firstOperationIndex)
|
||||||
{
|
{
|
||||||
QTextCursor cursor(doc);
|
if (operationsForFile.isEmpty())
|
||||||
cursor.beginEditBlock();
|
return;
|
||||||
cursor.setPosition(op.pos);
|
|
||||||
cursor.movePosition(QTextCursor::Right,
|
TextEditor::RangesInLines ranges;
|
||||||
QTextCursor::KeepAnchor,
|
for (int i = 0; i < operationsForFile.size(); ++i) {
|
||||||
op.text.length());
|
const ReplacementOperation &op = *operationsForFile.at(i);
|
||||||
const Replacements replacements = indenter.format(cursor, tabSettings);
|
const int start = doc->findBlock(op.pos).blockNumber() + 1;
|
||||||
cursor.endEditBlock();
|
const int end = doc->findBlock(op.pos + op.length).blockNumber() + 1;
|
||||||
|
ranges.push_back({start, end});
|
||||||
|
}
|
||||||
|
const Replacements replacements = indenter.format(ranges);
|
||||||
|
|
||||||
if (replacements.empty())
|
if (replacements.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (hasIntersection(op.fileName, replacements, currentIndex + 1))
|
shiftAffectedReplacements(operationsForFile.front()->fileName,
|
||||||
doc->undo(&cursor);
|
replacements,
|
||||||
else
|
firstOperationIndex + 1);
|
||||||
shiftAffectedReplacements(op.fileName, replacements, currentIndex + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextDocument *FixitsRefactoringFile::document(const QString &filePath) const
|
QTextDocument *FixitsRefactoringFile::document(const QString &filePath) const
|
||||||
|
@@ -67,11 +67,10 @@ private:
|
|||||||
QTextDocument *document(const QString &filePath) const;
|
QTextDocument *document(const QString &filePath) const;
|
||||||
void shiftAffectedReplacements(const ReplacementOperation &op, int startIndex);
|
void shiftAffectedReplacements(const ReplacementOperation &op, int startIndex);
|
||||||
|
|
||||||
void tryToFormat(TextEditor::Indenter &indenter,
|
void format(TextEditor::Indenter &indenter,
|
||||||
const TextEditor::TabSettings &tabSettings,
|
|
||||||
QTextDocument *doc,
|
QTextDocument *doc,
|
||||||
const ReplacementOperation &op,
|
const ReplacementOperations &operationsForFile,
|
||||||
int currentIndex);
|
int firstOperationIndex);
|
||||||
void shiftAffectedReplacements(const QString &fileName,
|
void shiftAffectedReplacements(const QString &fileName,
|
||||||
const TextEditor::Replacements &replacements,
|
const TextEditor::Replacements &replacements,
|
||||||
int startIndex);
|
int startIndex);
|
||||||
|
@@ -300,8 +300,8 @@ ClangTidyClazyTool::ClangTidyClazyTool()
|
|||||||
});
|
});
|
||||||
connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
|
connect(m_applyFixitsButton, &QToolButton::clicked, [this]() {
|
||||||
QVector<DiagnosticItem *> diagnosticItems;
|
QVector<DiagnosticItem *> diagnosticItems;
|
||||||
m_diagnosticModel->rootItem()->forChildrenAtLevel(2, [&](TreeItem *item){
|
m_diagnosticModel->forItemsAtLevel<2>([&](DiagnosticItem *item){
|
||||||
diagnosticItems += static_cast<DiagnosticItem *>(item);
|
diagnosticItems += item;
|
||||||
});
|
});
|
||||||
|
|
||||||
ApplyFixIts(diagnosticItems).apply(m_diagnosticModel);
|
ApplyFixIts(diagnosticItems).apply(m_diagnosticModel);
|
||||||
|
@@ -81,7 +81,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
ClangToolsDiagnosticModel::ClangToolsDiagnosticModel(QObject *parent)
|
ClangToolsDiagnosticModel::ClangToolsDiagnosticModel(QObject *parent)
|
||||||
: Utils::TreeModel<>(parent)
|
: ClangToolsDiagnosticModelBase(parent)
|
||||||
, m_filesWatcher(std::make_unique<QFileSystemWatcher>())
|
, m_filesWatcher(std::make_unique<QFileSystemWatcher>())
|
||||||
{
|
{
|
||||||
setHeader({tr("Diagnostic")});
|
setHeader({tr("Diagnostic")});
|
||||||
@@ -146,7 +146,7 @@ void ClangToolsDiagnosticModel::clear()
|
|||||||
m_filePathToItem.clear();
|
m_filePathToItem.clear();
|
||||||
m_diagnostics.clear();
|
m_diagnostics.clear();
|
||||||
clearAndSetupCache();
|
clearAndSetupCache();
|
||||||
Utils::TreeModel<>::clear();
|
ClangToolsDiagnosticModelBase::clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangToolsDiagnosticModel::updateItems(const DiagnosticItem *changedItem)
|
void ClangToolsDiagnosticModel::updateItems(const DiagnosticItem *changedItem)
|
||||||
@@ -174,10 +174,9 @@ void ClangToolsDiagnosticModel::clearAndSetupCache()
|
|||||||
|
|
||||||
void ClangToolsDiagnosticModel::onFileChanged(const QString &path)
|
void ClangToolsDiagnosticModel::onFileChanged(const QString &path)
|
||||||
{
|
{
|
||||||
rootItem()->forChildrenAtLevel(2, [&](Utils::TreeItem *item){
|
forItemsAtLevel<2>([&](DiagnosticItem *item){
|
||||||
auto diagnosticItem = static_cast<DiagnosticItem *>(item);
|
if (item->diagnostic().location.filePath == path)
|
||||||
if (diagnosticItem->diagnostic().location.filePath == path)
|
item->setFixItStatus(FixitStatus::Invalidated);
|
||||||
diagnosticItem->setFixItStatus(FixitStatus::Invalidated);
|
|
||||||
});
|
});
|
||||||
removeWatchedPath(path);
|
removeWatchedPath(path);
|
||||||
}
|
}
|
||||||
@@ -623,9 +622,10 @@ bool DiagnosticFilterModel::filterAcceptsRow(int sourceRow,
|
|||||||
|
|
||||||
// DiagnosticItem
|
// DiagnosticItem
|
||||||
Utils::TreeItem *parentItem = model->itemForIndex(sourceParent);
|
Utils::TreeItem *parentItem = model->itemForIndex(sourceParent);
|
||||||
if (auto filePathItem = dynamic_cast<FilePathItem *>(parentItem)) {
|
QTC_ASSERT(parentItem, return true);
|
||||||
auto diagnosticItem = dynamic_cast<DiagnosticItem *>(filePathItem->childAt(sourceRow));
|
if (parentItem->level() == 1) {
|
||||||
QTC_ASSERT(diagnosticItem, return false);
|
auto filePathItem = static_cast<FilePathItem *>(parentItem);
|
||||||
|
auto diagnosticItem = static_cast<DiagnosticItem *>(filePathItem->childAt(sourceRow));
|
||||||
|
|
||||||
// Is the diagnostic explicitly suppressed?
|
// Is the diagnostic explicitly suppressed?
|
||||||
const Diagnostic &diag = diagnosticItem->diagnostic();
|
const Diagnostic &diag = diagnosticItem->diagnostic();
|
||||||
@@ -651,11 +651,12 @@ bool DiagnosticFilterModel::lessThan(const QModelIndex &l, const QModelIndex &r)
|
|||||||
{
|
{
|
||||||
auto model = static_cast<ClangToolsDiagnosticModel *>(sourceModel());
|
auto model = static_cast<ClangToolsDiagnosticModel *>(sourceModel());
|
||||||
Utils::TreeItem *itemLeft = model->itemForIndex(l);
|
Utils::TreeItem *itemLeft = model->itemForIndex(l);
|
||||||
const bool isComparingDiagnostics = !dynamic_cast<FilePathItem *>(itemLeft);
|
QTC_ASSERT(itemLeft, return QSortFilterProxyModel::lessThan(l, r));
|
||||||
|
const bool isComparingDiagnostics = itemLeft->level() > 1;
|
||||||
|
|
||||||
if (sortColumn() == Debugger::DetailedErrorView::DiagnosticColumn && isComparingDiagnostics) {
|
if (sortColumn() == Debugger::DetailedErrorView::DiagnosticColumn && isComparingDiagnostics) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (dynamic_cast<DiagnosticItem *>(itemLeft)) {
|
if (itemLeft->level() == 2) {
|
||||||
using Debugger::DiagnosticLocation;
|
using Debugger::DiagnosticLocation;
|
||||||
const int role = Debugger::DetailedErrorView::LocationRole;
|
const int role = Debugger::DetailedErrorView::LocationRole;
|
||||||
|
|
||||||
@@ -669,8 +670,11 @@ bool DiagnosticFilterModel::lessThan(const QModelIndex &l, const QModelIndex &r)
|
|||||||
|
|
||||||
result = std::tie(leftLoc.line, leftLoc.column, leftText)
|
result = std::tie(leftLoc.line, leftLoc.column, leftText)
|
||||||
< std::tie(rightLoc.line, rightLoc.column, rightText);
|
< std::tie(rightLoc.line, rightLoc.column, rightText);
|
||||||
} else if (auto left = dynamic_cast<ExplainingStepItem *>(itemLeft)) {
|
} else if (itemLeft->level() == 3) {
|
||||||
const auto right = dynamic_cast<ExplainingStepItem *>(model->itemForIndex(r));
|
Utils::TreeItem *itemRight = model->itemForIndex(r);
|
||||||
|
QTC_ASSERT(itemRight, QSortFilterProxyModel::lessThan(l, r));
|
||||||
|
const auto left = static_cast<ExplainingStepItem *>(itemLeft);
|
||||||
|
const auto right = static_cast<ExplainingStepItem *>(itemRight);
|
||||||
result = left->index() < right->index();
|
result = left->index() < right->index();
|
||||||
} else {
|
} else {
|
||||||
QTC_CHECK(false && "Unexpected item");
|
QTC_CHECK(false && "Unexpected item");
|
||||||
|
@@ -100,7 +100,11 @@ private:
|
|||||||
ClangToolsDiagnosticModel *m_parentModel = nullptr;
|
ClangToolsDiagnosticModel *m_parentModel = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClangToolsDiagnosticModel : public Utils::TreeModel<>
|
class ExplainingStepItem;
|
||||||
|
|
||||||
|
using ClangToolsDiagnosticModelBase
|
||||||
|
= Utils::TreeModel<Utils::TreeItem, FilePathItem, DiagnosticItem, ExplainingStepItem>;
|
||||||
|
class ClangToolsDiagnosticModel : public ClangToolsDiagnosticModelBase
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@@ -446,47 +446,40 @@ 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)
|
bool CppEditorDocument::save(QString *errorString, const QString &fileName, bool autoSave)
|
||||||
{
|
{
|
||||||
if (indenter()->formatOnSave()) {
|
if (indenter()->formatOnSave() && !autoSave) {
|
||||||
QTextCursor cursor(document());
|
|
||||||
cursor.joinPreviousEditBlock();
|
|
||||||
auto *layout = qobject_cast<TextEditor::TextDocumentLayout *>(document()->documentLayout());
|
auto *layout = qobject_cast<TextEditor::TextDocumentLayout *>(document()->documentLayout());
|
||||||
const int documentRevision = layout->lastSaveRevision;
|
const int documentRevision = layout->lastSaveRevision;
|
||||||
|
|
||||||
std::pair<int, int> editedRange;
|
TextEditor::RangesInLines editedRanges;
|
||||||
|
TextEditor::RangeInLines lastRange{-1, -1};
|
||||||
for (int i = 0; i < document()->blockCount(); ++i) {
|
for (int i = 0; i < document()->blockCount(); ++i) {
|
||||||
const QTextBlock block = document()->findBlockByNumber(i);
|
const QTextBlock block = document()->findBlockByNumber(i);
|
||||||
if (block.revision() == documentRevision) {
|
if (block.revision() == documentRevision) {
|
||||||
if (editedRange.first != -1)
|
if (lastRange.startLine != -1)
|
||||||
i += formatRange(document(), indenter(), editedRange, tabSettings());
|
editedRanges.push_back(lastRange);
|
||||||
|
|
||||||
editedRange = std::make_pair(-1, -1);
|
lastRange.startLine = lastRange.endLine = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// block.revision() != documentRevision
|
// block.revision() != documentRevision
|
||||||
if (editedRange.first == -1)
|
if (lastRange.startLine == -1)
|
||||||
editedRange.first = block.position();
|
lastRange.startLine = block.blockNumber() + 1;
|
||||||
editedRange.second = block.position() + block.length();
|
lastRange.endLine = block.blockNumber() + 1;
|
||||||
}
|
}
|
||||||
if (editedRange.first != -1)
|
|
||||||
formatRange(document(), indenter(), editedRange, tabSettings());
|
if (lastRange.startLine != -1)
|
||||||
|
editedRanges.push_back(lastRange);
|
||||||
|
|
||||||
|
if (!editedRanges.empty()) {
|
||||||
|
QTextCursor cursor(document());
|
||||||
|
cursor.joinPreviousEditBlock();
|
||||||
|
indenter()->format(editedRanges);
|
||||||
cursor.endEditBlock();
|
cursor.endEditBlock();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return TextEditor::TextDocument::save(errorString, fileName, autoSave);
|
return TextEditor::TextDocument::save(errorString, fileName, autoSave);
|
||||||
}
|
}
|
||||||
|
@@ -48,6 +48,11 @@ void HeaderPathFilter::process()
|
|||||||
tweakHeaderPaths();
|
tweakHeaderPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HeaderPathFilter::isProjectHeaderPath(const QString &path) const
|
||||||
|
{
|
||||||
|
return path.startsWith(projectDirectory) || path.startsWith(buildDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
void HeaderPathFilter::filterHeaderPath(const ProjectExplorer::HeaderPath &headerPath)
|
void HeaderPathFilter::filterHeaderPath(const ProjectExplorer::HeaderPath &headerPath)
|
||||||
{
|
{
|
||||||
if (headerPath.path.isEmpty())
|
if (headerPath.path.isEmpty())
|
||||||
@@ -62,7 +67,10 @@ void HeaderPathFilter::filterHeaderPath(const ProjectExplorer::HeaderPath &heade
|
|||||||
systemHeaderPaths.push_back(headerPath);
|
systemHeaderPaths.push_back(headerPath);
|
||||||
break;
|
break;
|
||||||
case HeaderPathType::User:
|
case HeaderPathType::User:
|
||||||
|
if (isProjectHeaderPath(headerPath.path))
|
||||||
userHeaderPaths.push_back(headerPath);
|
userHeaderPaths.push_back(headerPath);
|
||||||
|
else
|
||||||
|
systemHeaderPaths.push_back(headerPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,4 +141,13 @@ void HeaderPathFilter::tweakHeaderPaths()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString HeaderPathFilter::ensurePathWithSlashEnding(const QString &path)
|
||||||
|
{
|
||||||
|
QString pathWithSlashEnding = path;
|
||||||
|
if (!pathWithSlashEnding.isEmpty() && *pathWithSlashEnding.rbegin() != '/')
|
||||||
|
pathWithSlashEnding.push_back('/');
|
||||||
|
|
||||||
|
return pathWithSlashEnding;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
@@ -34,11 +34,15 @@ class CPPTOOLS_EXPORT HeaderPathFilter
|
|||||||
public:
|
public:
|
||||||
HeaderPathFilter(const ProjectPart &projectPart,
|
HeaderPathFilter(const ProjectPart &projectPart,
|
||||||
UseTweakedHeaderPaths useTweakedHeaderPaths = UseTweakedHeaderPaths::Yes,
|
UseTweakedHeaderPaths useTweakedHeaderPaths = UseTweakedHeaderPaths::Yes,
|
||||||
const QString &clangVersion = QString(),
|
const QString &clangVersion = {},
|
||||||
const QString &clangResourceDirectory = QString())
|
const QString &clangResourceDirectory = {},
|
||||||
|
const QString &projectDirectory = {},
|
||||||
|
const QString &buildDirectory = {})
|
||||||
: projectPart{projectPart}
|
: projectPart{projectPart}
|
||||||
, clangVersion{clangVersion}
|
, clangVersion{clangVersion}
|
||||||
, clangResourceDirectory{clangResourceDirectory}
|
, clangResourceDirectory{clangResourceDirectory}
|
||||||
|
, projectDirectory(ensurePathWithSlashEnding(projectDirectory))
|
||||||
|
, buildDirectory(ensurePathWithSlashEnding(buildDirectory))
|
||||||
, useTweakedHeaderPaths{useTweakedHeaderPaths}
|
, useTweakedHeaderPaths{useTweakedHeaderPaths}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -49,6 +53,10 @@ private:
|
|||||||
|
|
||||||
void tweakHeaderPaths();
|
void tweakHeaderPaths();
|
||||||
|
|
||||||
|
bool isProjectHeaderPath(const QString &path) const;
|
||||||
|
|
||||||
|
static QString ensurePathWithSlashEnding(const QString &path);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ProjectExplorer::HeaderPaths builtInHeaderPaths;
|
ProjectExplorer::HeaderPaths builtInHeaderPaths;
|
||||||
ProjectExplorer::HeaderPaths systemHeaderPaths;
|
ProjectExplorer::HeaderPaths systemHeaderPaths;
|
||||||
@@ -56,6 +64,8 @@ public:
|
|||||||
const ProjectPart &projectPart;
|
const ProjectPart &projectPart;
|
||||||
const QString clangVersion;
|
const QString clangVersion;
|
||||||
const QString clangResourceDirectory;
|
const QString clangResourceDirectory;
|
||||||
|
const QString projectDirectory;
|
||||||
|
const QString buildDirectory;
|
||||||
const UseTweakedHeaderPaths useTweakedHeaderPaths;
|
const UseTweakedHeaderPaths useTweakedHeaderPaths;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1451,8 +1451,9 @@ void DebuggerPluginPrivate::updatePresetState()
|
|||||||
if (startupRunConfigName.isEmpty() && startupProject)
|
if (startupRunConfigName.isEmpty() && startupProject)
|
||||||
startupRunConfigName = startupProject->displayName();
|
startupRunConfigName = startupProject->displayName();
|
||||||
|
|
||||||
|
// Restrict width, otherwise Creator gets too wide, see QTCREATORBUG-21885
|
||||||
const QString startToolTip =
|
const QString startToolTip =
|
||||||
canRun ? tr("Start debugging of \"%1\"").arg(startupRunConfigName) : whyNot;
|
canRun ? tr("Start debugging of startup project") : whyNot;
|
||||||
|
|
||||||
m_startAction.setToolTip(startToolTip);
|
m_startAction.setToolTip(startToolTip);
|
||||||
m_startAction.setText(canRun ? startToolTip : tr("Start Debugging"));
|
m_startAction.setText(canRun ? startToolTip : tr("Start Debugging"));
|
||||||
|
@@ -52,7 +52,7 @@ namespace ProjectExplorer {
|
|||||||
|
|
||||||
Q_GLOBAL_STATIC(QThreadPool, s_extraCompilerThreadPool);
|
Q_GLOBAL_STATIC(QThreadPool, s_extraCompilerThreadPool);
|
||||||
Q_GLOBAL_STATIC(QList<ExtraCompilerFactory *>, factories);
|
Q_GLOBAL_STATIC(QList<ExtraCompilerFactory *>, factories);
|
||||||
|
Q_GLOBAL_STATIC(QVector<ExtraCompilerFactoryObserver *>, observers);
|
||||||
class ExtraCompilerPrivate
|
class ExtraCompilerPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -310,7 +310,8 @@ void ExtraCompiler::setContent(const Utils::FileName &file, const QByteArray &co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtraCompilerFactory::ExtraCompilerFactory(QObject *parent) : QObject(parent)
|
ExtraCompilerFactory::ExtraCompilerFactory(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
factories->append(this);
|
factories->append(this);
|
||||||
}
|
}
|
||||||
@@ -320,6 +321,14 @@ ExtraCompilerFactory::~ExtraCompilerFactory()
|
|||||||
factories->removeAll(this);
|
factories->removeAll(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExtraCompilerFactory::annouceCreation(const Project *project,
|
||||||
|
const Utils::FileName &source,
|
||||||
|
const Utils::FileNameList &targets)
|
||||||
|
{
|
||||||
|
for (ExtraCompilerFactoryObserver *observer : *observers)
|
||||||
|
observer->newExtraCompiler(project, source, targets);
|
||||||
|
}
|
||||||
|
|
||||||
QList<ExtraCompilerFactory *> ExtraCompilerFactory::extraCompilerFactories()
|
QList<ExtraCompilerFactory *> ExtraCompilerFactory::extraCompilerFactories()
|
||||||
{
|
{
|
||||||
return *factories();
|
return *factories();
|
||||||
@@ -455,4 +464,14 @@ void ProcessExtraCompiler::cleanUp()
|
|||||||
setCompileTime(QDateTime::currentDateTime());
|
setCompileTime(QDateTime::currentDateTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExtraCompilerFactoryObserver::ExtraCompilerFactoryObserver()
|
||||||
|
{
|
||||||
|
observers->push_back(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtraCompilerFactoryObserver::~ExtraCompilerFactoryObserver()
|
||||||
|
{
|
||||||
|
observers->removeOne(this);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -137,6 +137,20 @@ private:
|
|||||||
QFutureWatcher<FileNameToContentsHash> *m_watcher = nullptr;
|
QFutureWatcher<FileNameToContentsHash> *m_watcher = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PROJECTEXPLORER_EXPORT ExtraCompilerFactoryObserver
|
||||||
|
{
|
||||||
|
friend class ExtraCompilerFactory;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ExtraCompilerFactoryObserver();
|
||||||
|
~ExtraCompilerFactoryObserver();
|
||||||
|
|
||||||
|
virtual void newExtraCompiler(const Project *project,
|
||||||
|
const Utils::FileName &source,
|
||||||
|
const Utils::FileNameList &targets)
|
||||||
|
= 0;
|
||||||
|
};
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT ExtraCompilerFactory : public QObject
|
class PROJECTEXPLORER_EXPORT ExtraCompilerFactory : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -147,8 +161,14 @@ public:
|
|||||||
virtual FileType sourceType() const = 0;
|
virtual FileType sourceType() const = 0;
|
||||||
virtual QString sourceTag() const = 0;
|
virtual QString sourceTag() const = 0;
|
||||||
|
|
||||||
virtual ExtraCompiler *create(const Project *project, const Utils::FileName &source,
|
virtual ExtraCompiler *create(const Project *project,
|
||||||
const Utils::FileNameList &targets) = 0;
|
const Utils::FileName &source,
|
||||||
|
const Utils::FileNameList &targets)
|
||||||
|
= 0;
|
||||||
|
|
||||||
|
void annouceCreation(const Project *project,
|
||||||
|
const Utils::FileName &source,
|
||||||
|
const Utils::FileNameList &targets);
|
||||||
|
|
||||||
static QList<ExtraCompilerFactory *> extraCompilerFactories();
|
static QList<ExtraCompilerFactory *> extraCompilerFactories();
|
||||||
};
|
};
|
||||||
|
@@ -1143,14 +1143,6 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
|||||||
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
|
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
|
||||||
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
|
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
|
||||||
|
|
||||||
// unload project again, in right position
|
|
||||||
dd->m_unloadActionContextMenu = new Utils::ParameterAction(tr("Close Project"), tr("Close Project \"%1\""),
|
|
||||||
Utils::ParameterAction::EnabledWithParameter, this);
|
|
||||||
cmd = ActionManager::registerAction(dd->m_unloadActionContextMenu, Constants::UNLOADCM);
|
|
||||||
cmd->setAttribute(Command::CA_UpdateText);
|
|
||||||
cmd->setDescription(dd->m_unloadActionContextMenu->text());
|
|
||||||
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST);
|
|
||||||
|
|
||||||
dd->m_closeProjectFilesActionContextMenu = new Utils::ParameterAction(
|
dd->m_closeProjectFilesActionContextMenu = new Utils::ParameterAction(
|
||||||
tr("Close All Files"), tr("Close All Files in Project \"%1\""),
|
tr("Close All Files"), tr("Close All Files in Project \"%1\""),
|
||||||
Utils::ParameterAction::EnabledWithParameter, this);
|
Utils::ParameterAction::EnabledWithParameter, this);
|
||||||
@@ -1160,6 +1152,14 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
|
|||||||
cmd->setDescription(dd->m_closeProjectFilesActionContextMenu->text());
|
cmd->setDescription(dd->m_closeProjectFilesActionContextMenu->text());
|
||||||
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST);
|
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST);
|
||||||
|
|
||||||
|
// unload project again, in right position
|
||||||
|
dd->m_unloadActionContextMenu = new Utils::ParameterAction(tr("Close Project"), tr("Close Project \"%1\""),
|
||||||
|
Utils::ParameterAction::EnabledWithParameter, this);
|
||||||
|
cmd = ActionManager::registerAction(dd->m_unloadActionContextMenu, Constants::UNLOADCM);
|
||||||
|
cmd->setAttribute(Command::CA_UpdateText);
|
||||||
|
cmd->setDescription(dd->m_unloadActionContextMenu->text());
|
||||||
|
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_LAST);
|
||||||
|
|
||||||
// file properties action
|
// file properties action
|
||||||
dd->m_filePropertiesAction = new QAction(tr("Properties..."), this);
|
dd->m_filePropertiesAction = new QAction(tr("Properties..."), this);
|
||||||
cmd = ActionManager::registerAction(dd->m_filePropertiesAction, Constants::FILEPROPERTIES,
|
cmd = ActionManager::registerAction(dd->m_filePropertiesAction, Constants::FILEPROPERTIES,
|
||||||
@@ -1854,18 +1854,15 @@ void ProjectExplorerPluginPrivate::setStartupProject(Project *project)
|
|||||||
bool ProjectExplorerPluginPrivate::closeAllFilesInProject(const Project *project)
|
bool ProjectExplorerPluginPrivate::closeAllFilesInProject(const Project *project)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(project, return false);
|
QTC_ASSERT(project, return false);
|
||||||
const Utils::FileNameList filesInProject = project->files(Project::AllFiles);
|
|
||||||
QList<IDocument *> openFiles = DocumentModel::openedDocuments();
|
QList<IDocument *> openFiles = DocumentModel::openedDocuments();
|
||||||
Utils::erase(openFiles, [filesInProject](const IDocument *doc) {
|
Utils::erase(openFiles, [project](const IDocument *doc) {
|
||||||
return !filesInProject.contains(doc->filePath());
|
return !project->isKnownFile(doc->filePath());
|
||||||
});
|
});
|
||||||
for (const Project * const otherProject : SessionManager::projects()) {
|
for (const Project * const otherProject : SessionManager::projects()) {
|
||||||
if (otherProject == project)
|
if (otherProject == project)
|
||||||
continue;
|
continue;
|
||||||
const Utils::FileNameList filesInOtherProject
|
Utils::erase(openFiles, [otherProject](const IDocument *doc) {
|
||||||
= otherProject->files(Project::AllFiles);
|
return otherProject->isKnownFile(doc->filePath());
|
||||||
Utils::erase(openFiles, [filesInOtherProject](const IDocument *doc) {
|
|
||||||
return filesInOtherProject.contains(doc->filePath());
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return EditorManager::closeDocuments(openFiles);
|
return EditorManager::closeDocuments(openFiles);
|
||||||
|
@@ -149,6 +149,8 @@ ExtraCompiler *QScxmlcGeneratorFactory::create(
|
|||||||
const Project *project, const Utils::FileName &source,
|
const Project *project, const Utils::FileName &source,
|
||||||
const Utils::FileNameList &targets)
|
const Utils::FileNameList &targets)
|
||||||
{
|
{
|
||||||
|
annouceCreation(project, source, targets);
|
||||||
|
|
||||||
return new QScxmlcGenerator(project, source, targets, this);
|
return new QScxmlcGenerator(project, source, targets, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -100,6 +100,8 @@ ExtraCompiler *UicGeneratorFactory::create(const Project *project,
|
|||||||
const Utils::FileName &source,
|
const Utils::FileName &source,
|
||||||
const Utils::FileNameList &targets)
|
const Utils::FileNameList &targets)
|
||||||
{
|
{
|
||||||
|
annouceCreation(project, source, targets);
|
||||||
|
|
||||||
return new UicGenerator(project, source, targets, this);
|
return new UicGenerator(project, source, targets, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -203,7 +203,9 @@ void AbstractRemoteLinuxDeployService::handleDeviceSetupDone(bool success)
|
|||||||
} else {
|
} else {
|
||||||
connect(d->connection, &SshConnection::connected,
|
connect(d->connection, &SshConnection::connected,
|
||||||
this, &AbstractRemoteLinuxDeployService::handleConnected);
|
this, &AbstractRemoteLinuxDeployService::handleConnected);
|
||||||
emit progressMessage(tr("Connecting to device..."));
|
emit progressMessage(tr("Connecting to device '%1' (%2)")
|
||||||
|
.arg(deviceConfiguration()->displayName())
|
||||||
|
.arg(deviceConfiguration()->sshParameters().host()));
|
||||||
if (d->connection->state() == SshConnection::Unconnected)
|
if (d->connection->state() == SshConnection::Unconnected)
|
||||||
d->connection->connectToHost();
|
d->connection->connectToHost();
|
||||||
}
|
}
|
||||||
|
@@ -58,6 +58,15 @@ public:
|
|||||||
|
|
||||||
using Replacements = std::vector<Replacement>;
|
using Replacements = std::vector<Replacement>;
|
||||||
|
|
||||||
|
class RangeInLines
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int startLine;
|
||||||
|
int endLine;
|
||||||
|
};
|
||||||
|
|
||||||
|
using RangesInLines = std::vector<RangeInLines>;
|
||||||
|
|
||||||
class Indenter
|
class Indenter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -91,9 +100,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// By default just calls indent with default settings.
|
// By default just calls indent with default settings.
|
||||||
virtual Replacements format(const QTextCursor &/*cursor*/,
|
virtual Replacements format(const RangesInLines & /*rangesInLines*/ = RangesInLines())
|
||||||
const TabSettings &/*tabSettings*/,
|
|
||||||
int /*cursorPositionInEditor*/ = -1)
|
|
||||||
{
|
{
|
||||||
return Replacements();
|
return Replacements();
|
||||||
}
|
}
|
||||||
|
@@ -8085,11 +8085,20 @@ void BaseTextEditor::setContextHelp(const HelpItem &item)
|
|||||||
|
|
||||||
void TextEditorWidget::contextHelpItem(const IContext::HelpCallback &callback)
|
void TextEditorWidget::contextHelpItem(const IContext::HelpCallback &callback)
|
||||||
{
|
{
|
||||||
|
const QString fallbackWordUnderCursor = Text::wordUnderCursor(textCursor());
|
||||||
if (d->m_contextHelpItem.isEmpty() && !d->m_hoverHandlers.isEmpty()) {
|
if (d->m_contextHelpItem.isEmpty() && !d->m_hoverHandlers.isEmpty()) {
|
||||||
d->m_hoverHandlers.first()->contextHelpId(this,
|
d->m_hoverHandlers.first()->contextHelpId(this,
|
||||||
Text::wordStartCursor(textCursor()).position(),
|
Text::wordStartCursor(textCursor()).position(),
|
||||||
callback);
|
[fallbackWordUnderCursor, callback](const HelpItem &item) {
|
||||||
|
if (item.isEmpty())
|
||||||
|
callback(fallbackWordUnderCursor);
|
||||||
|
else
|
||||||
|
callback(item);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
|
if (d->m_contextHelpItem.isEmpty())
|
||||||
|
callback(fallbackWordUnderCursor);
|
||||||
|
else
|
||||||
callback(d->m_contextHelpItem);
|
callback(d->m_contextHelpItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -291,6 +291,9 @@ void TextMark::addToToolTipLayout(QGridLayout *target) const
|
|||||||
// Right column: action icons/button
|
// Right column: action icons/button
|
||||||
if (!m_actions.isEmpty()) {
|
if (!m_actions.isEmpty()) {
|
||||||
auto actionsLayout = new QHBoxLayout;
|
auto actionsLayout = new QHBoxLayout;
|
||||||
|
QMargins margins = actionsLayout->contentsMargins();
|
||||||
|
margins.setLeft(margins.left() + 5);
|
||||||
|
actionsLayout->setContentsMargins(margins);
|
||||||
for (QAction *action : m_actions) {
|
for (QAction *action : m_actions) {
|
||||||
QTC_ASSERT(!action->icon().isNull(), continue);
|
QTC_ASSERT(!action->icon().isNull(), continue);
|
||||||
auto button = new QToolButton;
|
auto button = new QToolButton;
|
||||||
|
@@ -119,7 +119,7 @@ IntroductionWidget::IntroductionWidget(QWidget *parent)
|
|||||||
"<tr><td>Edit:</td><td>Work with code and navigate your project.</td></tr>"
|
"<tr><td>Edit:</td><td>Work with code and navigate your project.</td></tr>"
|
||||||
"<tr><td>Design:</td><td>Work with UI designs for Qt Widgets or Qt Quick.</td></tr>"
|
"<tr><td>Design:</td><td>Work with UI designs for Qt Widgets or Qt Quick.</td></tr>"
|
||||||
"<tr><td>Debug:</td><td>Analyze your application with a debugger or other "
|
"<tr><td>Debug:</td><td>Analyze your application with a debugger or other "
|
||||||
"analyzer.</td></tr>"
|
"analyzers.</td></tr>"
|
||||||
"<tr><td>Projects:</td><td>Manage project settings.</td></tr>"
|
"<tr><td>Projects:</td><td>Manage project settings.</td></tr>"
|
||||||
"<tr><td>Help:</td><td>Browse the help database.</td></tr>"
|
"<tr><td>Help:</td><td>Browse the help database.</td></tr>"
|
||||||
"</table></p>")},
|
"</table></p>")},
|
||||||
|
Submodule src/shared/qbs updated: 6fcbc1a996...bceae1097f
@@ -246,8 +246,13 @@ struct Data // because we have a cycle dependency
|
|||||||
modifiedTimeChecker,
|
modifiedTimeChecker,
|
||||||
buildDependencyCollector,
|
buildDependencyCollector,
|
||||||
database};
|
database};
|
||||||
ClangBackEnd::PchTaskGenerator pchTaskGenerator{buildDependencyProvider, pchTaskMerger};
|
ClangBackEnd::PchTaskGenerator pchTaskGenerator{buildDependencyProvider,
|
||||||
PchManagerServer clangPchManagerServer{includeWatcher, pchTaskGenerator, projectParts, generatedFiles};
|
pchTaskMerger,
|
||||||
|
progressCounter};
|
||||||
|
PchManagerServer clangPchManagerServer{includeWatcher,
|
||||||
|
pchTaskGenerator,
|
||||||
|
projectParts,
|
||||||
|
generatedFiles};
|
||||||
TaskScheduler systemTaskScheduler{pchCreatorManager,
|
TaskScheduler systemTaskScheduler{pchCreatorManager,
|
||||||
pchTaskQueue,
|
pchTaskQueue,
|
||||||
progressCounter,
|
progressCounter,
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <clang/Tooling/Tooling.h>
|
#include <clang/Tooling/Tooling.h>
|
||||||
|
|
||||||
|
#include <clang/Basic/DiagnosticOptions.h>
|
||||||
#include <clang/Frontend/CompilerInstance.h>
|
#include <clang/Frontend/CompilerInstance.h>
|
||||||
#include <clang/Frontend/FrontendActions.h>
|
#include <clang/Frontend/FrontendActions.h>
|
||||||
#include <clang/Lex/PreprocessorOptions.h>
|
#include <clang/Lex/PreprocessorOptions.h>
|
||||||
@@ -44,6 +45,9 @@ public:
|
|||||||
bool BeginInvocation(clang::CompilerInstance &compilerInstance) override
|
bool BeginInvocation(clang::CompilerInstance &compilerInstance) override
|
||||||
{
|
{
|
||||||
compilerInstance.getPreprocessorOpts().DisablePCHValidation = true;
|
compilerInstance.getPreprocessorOpts().DisablePCHValidation = true;
|
||||||
|
compilerInstance.getPreprocessorOpts().AllowPCHWithCompilerErrors = true;
|
||||||
|
compilerInstance.getLangOpts().DelayedTemplateParsing = true;
|
||||||
|
compilerInstance.getDiagnosticOpts().ErrorLimit = 0;
|
||||||
std::unique_ptr<llvm::MemoryBuffer> Input = llvm::MemoryBuffer::getMemBuffer(m_fileContent);
|
std::unique_ptr<llvm::MemoryBuffer> Input = llvm::MemoryBuffer::getMemBuffer(m_fileContent);
|
||||||
compilerInstance.getPreprocessorOpts().addRemappedFile(m_filePath, Input.release());
|
compilerInstance.getPreprocessorOpts().addRemappedFile(m_filePath, Input.release());
|
||||||
|
|
||||||
|
@@ -76,8 +76,6 @@ bool PchCreator::generatePch(NativeFilePathView path, Utils::SmallStringView con
|
|||||||
{
|
{
|
||||||
clang::tooling::ClangTool tool = m_clangTool.createOutputTool();
|
clang::tooling::ClangTool tool = m_clangTool.createOutputTool();
|
||||||
|
|
||||||
NativeFilePath headerFilePath{m_environment.pchBuildDirectory().toStdString(), "dummy.h"};
|
|
||||||
|
|
||||||
auto action = std::make_unique<GeneratePCHActionFactory>(llvm::StringRef{path.data(),
|
auto action = std::make_unique<GeneratePCHActionFactory>(llvm::StringRef{path.data(),
|
||||||
path.size()},
|
path.size()},
|
||||||
llvm::StringRef{content.data(),
|
llvm::StringRef{content.data(),
|
||||||
@@ -138,6 +136,16 @@ const ProjectPartPch &PchCreator::projectPartPch()
|
|||||||
|
|
||||||
void PchCreator::setUnsavedFiles(const V2::FileContainers &fileContainers)
|
void PchCreator::setUnsavedFiles(const V2::FileContainers &fileContainers)
|
||||||
{
|
{
|
||||||
|
m_generatedFilePathIds.clear();
|
||||||
|
m_generatedFilePathIds.reserve(fileContainers.size());
|
||||||
|
std::transform(fileContainers.begin(),
|
||||||
|
fileContainers.end(),
|
||||||
|
std::back_inserter(m_generatedFilePathIds),
|
||||||
|
[&](const V2::FileContainer &fileContainer) {
|
||||||
|
return m_filePathCache.filePathId(fileContainer.filePath);
|
||||||
|
});
|
||||||
|
std::sort(m_generatedFilePathIds.begin(), m_generatedFilePathIds.end());
|
||||||
|
|
||||||
m_clangTool.addUnsavedFiles(fileContainers);
|
m_clangTool.addUnsavedFiles(fileContainers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +167,14 @@ void PchCreator::clear()
|
|||||||
|
|
||||||
void PchCreator::doInMainThreadAfterFinished()
|
void PchCreator::doInMainThreadAfterFinished()
|
||||||
{
|
{
|
||||||
m_clangPathwatcher.updateIdPaths({{m_projectPartPch.projectPartId, m_allInclues}});
|
FilePathIds existingIncludes;
|
||||||
|
existingIncludes.reserve(m_allInclues.size());
|
||||||
|
std::set_difference(m_allInclues.begin(),
|
||||||
|
m_allInclues.end(),
|
||||||
|
m_generatedFilePathIds.begin(),
|
||||||
|
m_generatedFilePathIds.end(),
|
||||||
|
std::back_inserter(existingIncludes));
|
||||||
|
m_clangPathwatcher.updateIdPaths({{m_projectPartPch.projectPartId, existingIncludes}});
|
||||||
m_pchManagerClient.precompiledHeadersUpdated(ProjectPartPchs{m_projectPartPch});
|
m_pchManagerClient.precompiledHeadersUpdated(ProjectPartPchs{m_projectPartPch});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -98,6 +98,7 @@ private:
|
|||||||
ProjectPartPch m_projectPartPch;
|
ProjectPartPch m_projectPartPch;
|
||||||
FilePathCaching m_filePathCache;
|
FilePathCaching m_filePathCache;
|
||||||
FilePathIds m_allInclues;
|
FilePathIds m_allInclues;
|
||||||
|
FilePathIds m_generatedFilePathIds;
|
||||||
Environment &m_environment;
|
Environment &m_environment;
|
||||||
PchManagerClientInterface &m_pchManagerClient;
|
PchManagerClientInterface &m_pchManagerClient;
|
||||||
ClangPathWatcherInterface &m_clangPathwatcher;
|
ClangPathWatcherInterface &m_clangPathwatcher;
|
||||||
|
@@ -27,9 +27,10 @@
|
|||||||
|
|
||||||
#include "builddependenciesproviderinterface.h"
|
#include "builddependenciesproviderinterface.h"
|
||||||
#include "pchtasksmergerinterface.h"
|
#include "pchtasksmergerinterface.h"
|
||||||
|
|
||||||
#include "usedmacrofilter.h"
|
#include "usedmacrofilter.h"
|
||||||
|
|
||||||
|
#include <progresscounter.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
@@ -40,6 +41,8 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
|
|||||||
PchTaskSets pchTaskSets;
|
PchTaskSets pchTaskSets;
|
||||||
pchTaskSets.reserve(projectParts.size());
|
pchTaskSets.reserve(projectParts.size());
|
||||||
|
|
||||||
|
m_progressCounter.addTotal(static_cast<int>(projectParts.size()));
|
||||||
|
|
||||||
for (auto &projectPart : projectParts) {
|
for (auto &projectPart : projectParts) {
|
||||||
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart);
|
BuildDependency buildDependency = m_buildDependenciesProvider.create(projectPart);
|
||||||
UsedMacroFilter filter{buildDependency.includes,
|
UsedMacroFilter filter{buildDependency.includes,
|
||||||
@@ -68,6 +71,7 @@ void PchTaskGenerator::addProjectParts(ProjectPartContainers &&projectParts,
|
|||||||
projectPart.language,
|
projectPart.language,
|
||||||
projectPart.languageVersion,
|
projectPart.languageVersion,
|
||||||
projectPart.languageExtension});
|
projectPart.languageExtension});
|
||||||
|
m_progressCounter.addProgress(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pchTasksMergerInterface.mergeTasks(std::move(pchTaskSets), std::move(toolChainArguments));
|
m_pchTasksMergerInterface.mergeTasks(std::move(pchTaskSets), std::move(toolChainArguments));
|
||||||
|
@@ -35,14 +35,18 @@ namespace ClangBackEnd {
|
|||||||
class PchTasksMergerInterface;
|
class PchTasksMergerInterface;
|
||||||
|
|
||||||
class BuildDependenciesProviderInterface;
|
class BuildDependenciesProviderInterface;
|
||||||
|
class ProgressCounter;
|
||||||
|
|
||||||
class PchTaskGenerator : public PchTaskGeneratorInterface
|
class PchTaskGenerator : public PchTaskGeneratorInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PchTaskGenerator(BuildDependenciesProviderInterface &buildDependenciesProvider,
|
PchTaskGenerator(BuildDependenciesProviderInterface &buildDependenciesProvider,
|
||||||
PchTasksMergerInterface &pchTasksMergerInterface)
|
PchTasksMergerInterface &pchTasksMergerInterface,
|
||||||
|
ProgressCounter &progressCounter)
|
||||||
: m_buildDependenciesProvider(buildDependenciesProvider)
|
: m_buildDependenciesProvider(buildDependenciesProvider)
|
||||||
, m_pchTasksMergerInterface(pchTasksMergerInterface)
|
, m_pchTasksMergerInterface(pchTasksMergerInterface)
|
||||||
|
, m_progressCounter(progressCounter)
|
||||||
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void addProjectParts(ProjectPartContainers &&projectParts,
|
void addProjectParts(ProjectPartContainers &&projectParts,
|
||||||
@@ -52,7 +56,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
BuildDependenciesProviderInterface &m_buildDependenciesProvider;
|
BuildDependenciesProviderInterface &m_buildDependenciesProvider;
|
||||||
PchTasksMergerInterface &m_pchTasksMergerInterface;
|
PchTasksMergerInterface &m_pchTasksMergerInterface;
|
||||||
|
ProgressCounter &m_progressCounter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -71,7 +71,7 @@ bool PchTasksMerger::hasDuplicates(const CompilerMacros &compilerMacros)
|
|||||||
return first.key == second.key;
|
return first.key == second.key;
|
||||||
});
|
});
|
||||||
|
|
||||||
return found == compilerMacros.end();
|
return found != compilerMacros.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
IncludeSearchPaths mergeIncludeSearchPaths(IncludeSearchPaths &&first, IncludeSearchPaths &&second)
|
IncludeSearchPaths mergeIncludeSearchPaths(IncludeSearchPaths &&first, IncludeSearchPaths &&second)
|
||||||
@@ -89,7 +89,8 @@ bool PchTasksMerger::mergePchTasks(PchTask &firstTask, PchTask &secondTask)
|
|||||||
|
|
||||||
CompilerMacros macros = mergeMacros(firstTask.compilerMacros, secondTask.compilerMacros);
|
CompilerMacros macros = mergeMacros(firstTask.compilerMacros, secondTask.compilerMacros);
|
||||||
|
|
||||||
secondTask.isMerged = hasDuplicates(macros);
|
secondTask.isMerged = !hasDuplicates(macros);
|
||||||
|
|
||||||
|
|
||||||
if (secondTask.isMerged && firstTask.language == secondTask.language) {
|
if (secondTask.isMerged && firstTask.language == secondTask.language) {
|
||||||
firstTask.projectPartIds = merge(std::move(firstTask.projectPartIds),
|
firstTask.projectPartIds = merge(std::move(firstTask.projectPartIds),
|
||||||
|
@@ -93,8 +93,8 @@ public:
|
|||||||
return std::tie(first.key, first.value) < std::tie(second.key, second.value);
|
return std::tie(first.key, first.value) < std::tie(second.key, second.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
systemCompilerMacros = filtercompilerMacros(indexedCompilerMacro, systemUsedMacros);
|
systemCompilerMacros = filterCompilerMacros(indexedCompilerMacro, systemUsedMacros);
|
||||||
projectCompilerMacros = filtercompilerMacros(indexedCompilerMacro, projectUsedMacros);
|
projectCompilerMacros = filterCompilerMacros(indexedCompilerMacro, projectUsedMacros);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -150,10 +150,13 @@ private:
|
|||||||
|
|
||||||
std::sort(filtertedMacros.begin(), filtertedMacros.end());
|
std::sort(filtertedMacros.begin(), filtertedMacros.end());
|
||||||
|
|
||||||
|
auto newEnd = std::unique(filtertedMacros.begin(), filtertedMacros.end());
|
||||||
|
filtertedMacros.erase(newEnd, filtertedMacros.end());
|
||||||
|
|
||||||
return filtertedMacros;
|
return filtertedMacros;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CompilerMacros filtercompilerMacros(const CompilerMacros &indexedCompilerMacro,
|
static CompilerMacros filterCompilerMacros(const CompilerMacros &indexedCompilerMacro,
|
||||||
const Utils::SmallStringVector &usedMacros)
|
const Utils::SmallStringVector &usedMacros)
|
||||||
{
|
{
|
||||||
CompilerMacros filtertedCompilerMacros;
|
CompilerMacros filtertedCompilerMacros;
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <clang/Frontend/CompilerInstance.h>
|
#include <clang/Frontend/CompilerInstance.h>
|
||||||
#include <clang/Frontend/FrontendActions.h>
|
#include <clang/Frontend/FrontendActions.h>
|
||||||
|
#include <clang/Lex/PreprocessorOptions.h>
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
@@ -100,6 +101,7 @@ newFrontendActionFactory(Factory *consumerFactory,
|
|||||||
bool BeginInvocation(clang::CompilerInstance &compilerInstance) override
|
bool BeginInvocation(clang::CompilerInstance &compilerInstance) override
|
||||||
{
|
{
|
||||||
compilerInstance.getLangOpts().DelayedTemplateParsing = false;
|
compilerInstance.getLangOpts().DelayedTemplateParsing = false;
|
||||||
|
compilerInstance.getPreprocessorOpts().AllowPCHWithCompilerErrors = true;
|
||||||
|
|
||||||
return clang::ASTFrontendAction::BeginInvocation(compilerInstance);
|
return clang::ASTFrontendAction::BeginInvocation(compilerInstance);
|
||||||
}
|
}
|
||||||
|
37
tests/unit/mockup/projectexplorer/buildconfiguration.h
Normal file
37
tests/unit/mockup/projectexplorer/buildconfiguration.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
|
class BuildConfiguration
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Utils::FileName buildDirectory() const { return {}; }
|
||||||
|
}; // namespace Target
|
||||||
|
} // namespace ProjectExplorer
|
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "target.h"
|
||||||
|
|
||||||
#include <projectexplorer/kit.h>
|
#include <projectexplorer/kit.h>
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
@@ -35,13 +37,10 @@ class Project : public QObject {
|
|||||||
public:
|
public:
|
||||||
Project() = default;
|
Project() = default;
|
||||||
|
|
||||||
Utils::FileName projectDirectory() const {
|
Utils::FileName projectDirectory() const { return {}; }
|
||||||
return Utils::FileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::FileName rootProjectDirectory() const {
|
Utils::FileName rootProjectDirectory() const { return {}; }
|
||||||
return Utils::FileName();
|
|
||||||
}
|
Target *activeTarget() const { return {}; }
|
||||||
};
|
};
|
||||||
|
} // namespace ProjectExplorer
|
||||||
}
|
|
||||||
|
39
tests/unit/mockup/projectexplorer/target.h
Normal file
39
tests/unit/mockup/projectexplorer/target.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "buildconfiguration.h"
|
||||||
|
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
|
class Target
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BuildConfiguration *activeBuildConfiguration() const { return {}; }
|
||||||
|
};
|
||||||
|
} // namespace ProjectExplorer
|
@@ -408,6 +408,60 @@ TEST_F(ClangFormat, IndentIfBodyAndFormatBeforeIt)
|
|||||||
"}"));
|
"}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangFormat, DoNotFormatAfterTheFirstColon)
|
||||||
|
{
|
||||||
|
insertLines({"{",
|
||||||
|
" Qt:",
|
||||||
|
"}"});
|
||||||
|
|
||||||
|
extendedIndenter.indentBlock(doc.findBlockByNumber(1), ':', TextEditor::TabSettings(), 9);
|
||||||
|
|
||||||
|
ASSERT_THAT(documentLines(), ElementsAre("{",
|
||||||
|
" Qt:",
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangFormat, OnlyIndentIncompleteStatementOnElectricalCharacter)
|
||||||
|
{
|
||||||
|
insertLines({"{bar();",
|
||||||
|
"foo()",
|
||||||
|
"}"});
|
||||||
|
|
||||||
|
extendedIndenter.indentBlock(doc.findBlockByNumber(1), '(', TextEditor::TabSettings(), 12);
|
||||||
|
|
||||||
|
ASSERT_THAT(documentLines(), ElementsAre("{bar();",
|
||||||
|
" foo()",
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangFormat, IndentAndFormatCompleteStatementOnSemicolon)
|
||||||
|
{
|
||||||
|
insertLines({"{bar();",
|
||||||
|
"foo();",
|
||||||
|
"}"});
|
||||||
|
|
||||||
|
extendedIndenter.indentBlock(doc.findBlockByNumber(1), ';', TextEditor::TabSettings(), 14);
|
||||||
|
|
||||||
|
ASSERT_THAT(documentLines(), ElementsAre("{",
|
||||||
|
" bar();",
|
||||||
|
" foo();",
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ClangFormat, IndentAndFormatCompleteStatementOnClosingScope)
|
||||||
|
{
|
||||||
|
insertLines({"{bar();",
|
||||||
|
"foo();",
|
||||||
|
"}"});
|
||||||
|
|
||||||
|
extendedIndenter.indentBlock(doc.findBlockByNumber(1), '}', TextEditor::TabSettings(), 16);
|
||||||
|
|
||||||
|
ASSERT_THAT(documentLines(), ElementsAre("{",
|
||||||
|
" bar();",
|
||||||
|
" foo();",
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ClangFormat, FormatBasicFile)
|
TEST_F(ClangFormat, FormatBasicFile)
|
||||||
{
|
{
|
||||||
insertLines({"int main()",
|
insertLines({"int main()",
|
||||||
@@ -415,7 +469,7 @@ TEST_F(ClangFormat, FormatBasicFile)
|
|||||||
"int a;",
|
"int a;",
|
||||||
"}"});
|
"}"});
|
||||||
|
|
||||||
indenter.format(cursor, TextEditor::TabSettings());
|
indenter.format(cursor);
|
||||||
|
|
||||||
ASSERT_THAT(documentLines(), ElementsAre("int main()",
|
ASSERT_THAT(documentLines(), ElementsAre("int main()",
|
||||||
"{",
|
"{",
|
||||||
@@ -430,7 +484,7 @@ TEST_F(ClangFormat, FormatEmptyLine)
|
|||||||
"",
|
"",
|
||||||
"}"});
|
"}"});
|
||||||
|
|
||||||
indenter.format(cursor, TextEditor::TabSettings());
|
indenter.format(cursor);
|
||||||
|
|
||||||
ASSERT_THAT(documentLines(), ElementsAre("int main() {}"));
|
ASSERT_THAT(documentLines(), ElementsAre("int main() {}"));
|
||||||
}
|
}
|
||||||
@@ -441,7 +495,7 @@ TEST_F(ClangFormat, FormatLambda)
|
|||||||
"",
|
"",
|
||||||
"});"});
|
"});"});
|
||||||
|
|
||||||
indenter.format(cursor, TextEditor::TabSettings());
|
indenter.format(cursor);
|
||||||
|
|
||||||
ASSERT_THAT(documentLines(), ElementsAre("int b = foo([]() {",
|
ASSERT_THAT(documentLines(), ElementsAre("int b = foo([]() {",
|
||||||
"",
|
"",
|
||||||
@@ -454,7 +508,7 @@ TEST_F(ClangFormat, FormatInitializerListInArguments)
|
|||||||
"args,",
|
"args,",
|
||||||
"{1, 2});"});
|
"{1, 2});"});
|
||||||
|
|
||||||
indenter.format(cursor, TextEditor::TabSettings());
|
indenter.format(cursor);
|
||||||
|
|
||||||
ASSERT_THAT(documentLines(), ElementsAre("foo(arg1, args, {1, 2});"));
|
ASSERT_THAT(documentLines(), ElementsAre("foo(arg1, args, {1, 2});"));
|
||||||
}
|
}
|
||||||
@@ -466,7 +520,7 @@ TEST_F(ClangFormat, FormatFunctionArgumentLambdaWithScope)
|
|||||||
"",
|
"",
|
||||||
"});"});
|
"});"});
|
||||||
|
|
||||||
indenter.format(cursor, TextEditor::TabSettings());
|
indenter.format(cursor);
|
||||||
|
|
||||||
ASSERT_THAT(documentLines(),
|
ASSERT_THAT(documentLines(),
|
||||||
ElementsAre("foo([]() {",
|
ElementsAre("foo([]() {",
|
||||||
@@ -481,7 +535,7 @@ TEST_F(ClangFormat, FormatScopeAsFunctionArgument)
|
|||||||
"",
|
"",
|
||||||
"});"});
|
"});"});
|
||||||
|
|
||||||
indenter.format(cursor, TextEditor::TabSettings());
|
indenter.format(cursor);
|
||||||
|
|
||||||
ASSERT_THAT(documentLines(),
|
ASSERT_THAT(documentLines(),
|
||||||
ElementsAre("foo({",
|
ElementsAre("foo({",
|
||||||
@@ -494,7 +548,7 @@ TEST_F(ClangFormat, FormatStructuredBinding)
|
|||||||
insertLines({"auto [a,",
|
insertLines({"auto [a,",
|
||||||
"b] = c;"});
|
"b] = c;"});
|
||||||
|
|
||||||
indenter.format(cursor, TextEditor::TabSettings());
|
indenter.format(cursor);
|
||||||
|
|
||||||
ASSERT_THAT(documentLines(), ElementsAre("auto [a, b] = c;"));
|
ASSERT_THAT(documentLines(), ElementsAre("auto [a, b] = c;"));
|
||||||
}
|
}
|
||||||
@@ -504,7 +558,7 @@ TEST_F(ClangFormat, FormatStringLiteralContinuation)
|
|||||||
insertLines({"foo(bar, \"foo\"",
|
insertLines({"foo(bar, \"foo\"",
|
||||||
"\"bar\");"});
|
"\"bar\");"});
|
||||||
|
|
||||||
indenter.format(cursor, TextEditor::TabSettings());
|
indenter.format(cursor);
|
||||||
|
|
||||||
ASSERT_THAT(documentLines(), ElementsAre("foo(bar,",
|
ASSERT_THAT(documentLines(), ElementsAre("foo(bar,",
|
||||||
" \"foo\"",
|
" \"foo\"",
|
||||||
@@ -517,7 +571,7 @@ TEST_F(ClangFormat, FormatTemplateparameters)
|
|||||||
"B,",
|
"B,",
|
||||||
"C>"});
|
"C>"});
|
||||||
|
|
||||||
indenter.format(cursor, TextEditor::TabSettings());
|
indenter.format(cursor);
|
||||||
|
|
||||||
ASSERT_THAT(documentLines(), ElementsAre("using Alias = Template<A, B, C>"));
|
ASSERT_THAT(documentLines(), ElementsAre("using Alias = Template<A, B, C>"));
|
||||||
}
|
}
|
||||||
|
@@ -139,6 +139,7 @@ TYPED_TEST(CommandLineBuilder, CHeader)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang",
|
ElementsAre("clang",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c-header",
|
"c-header",
|
||||||
"-std=c11",
|
"-std=c11",
|
||||||
@@ -154,7 +155,7 @@ TYPED_TEST(CommandLineBuilder, CSource)
|
|||||||
Builder<TypeParam> builder{this->emptyProjectInfo, {}, InputFileType::Source, "/source/file.c"};
|
Builder<TypeParam> builder{this->emptyProjectInfo, {}, InputFileType::Source, "/source/file.c"};
|
||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang", "-x", "c", "-std=c11", "-nostdinc", "/source/file.c"));
|
ElementsAre("clang", "-DNOMINMAX", "-x", "c", "-std=c11", "-nostdinc", "/source/file.c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST(CommandLineBuilder, ObjectiveCHeader)
|
TYPED_TEST(CommandLineBuilder, ObjectiveCHeader)
|
||||||
@@ -167,6 +168,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCHeader)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang",
|
ElementsAre("clang",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"objective-c-header",
|
"objective-c-header",
|
||||||
"-std=c11",
|
"-std=c11",
|
||||||
@@ -184,6 +186,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCSource)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang",
|
ElementsAre("clang",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"objective-c",
|
"objective-c",
|
||||||
"-std=c11",
|
"-std=c11",
|
||||||
@@ -200,6 +203,7 @@ TYPED_TEST(CommandLineBuilder, CppHeader)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
@@ -215,9 +219,15 @@ TYPED_TEST(CommandLineBuilder, CppSource)
|
|||||||
|
|
||||||
Builder<TypeParam> builder{this->emptyProjectInfo, {}, InputFileType::Source, "/source/file.cpp"};
|
Builder<TypeParam> builder{this->emptyProjectInfo, {}, InputFileType::Source, "/source/file.cpp"};
|
||||||
|
|
||||||
ASSERT_THAT(
|
ASSERT_THAT(builder.commandLine,
|
||||||
builder.commandLine,
|
ElementsAre("clang++",
|
||||||
ElementsAre("clang++", "-x", "c++", "-std=c++98", "-nostdinc", "-nostdinc++", "/source/file.cpp"));
|
"-DNOMINMAX",
|
||||||
|
"-x",
|
||||||
|
"c++",
|
||||||
|
"-std=c++98",
|
||||||
|
"-nostdinc",
|
||||||
|
"-nostdinc++",
|
||||||
|
"/source/file.cpp"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST(CommandLineBuilder, ObjectiveCppHeader)
|
TYPED_TEST(CommandLineBuilder, ObjectiveCppHeader)
|
||||||
@@ -230,6 +240,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCppHeader)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"objective-c++-header",
|
"objective-c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
@@ -248,6 +259,7 @@ TYPED_TEST(CommandLineBuilder, ObjectiveCppSource)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"objective-c++",
|
"objective-c++",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
@@ -480,6 +492,7 @@ TYPED_TEST(CommandLineBuilder, IncludesOrder)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++11",
|
"-std=c++11",
|
||||||
@@ -505,7 +518,13 @@ 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", "-nostdinc++"));
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
|
"-x",
|
||||||
|
"c++-header",
|
||||||
|
"-std=c++98",
|
||||||
|
"-nostdinc",
|
||||||
|
"-nostdinc++"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST(CommandLineBuilder, SourceFile)
|
TYPED_TEST(CommandLineBuilder, SourceFile)
|
||||||
@@ -514,6 +533,7 @@ TYPED_TEST(CommandLineBuilder, SourceFile)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
@@ -529,6 +549,7 @@ TYPED_TEST(CommandLineBuilder, EmptyOutputFile)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
@@ -547,6 +568,7 @@ TYPED_TEST(CommandLineBuilder, OutputFile)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
@@ -568,6 +590,7 @@ TYPED_TEST(CommandLineBuilder, IncludePchPath)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
@@ -590,6 +613,7 @@ TYPED_TEST(CommandLineBuilder, CompilerMacros)
|
|||||||
|
|
||||||
ASSERT_THAT(builder.commandLine,
|
ASSERT_THAT(builder.commandLine,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
|
115
tests/unit/unittest/data/clangformat/.clang-format
Normal file
115
tests/unit/unittest/data/clangformat/.clang-format
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# .clang-format for Qt Creator
|
||||||
|
#
|
||||||
|
# This is for clang-format >= 5.0.
|
||||||
|
#
|
||||||
|
# The configuration below follows the Qt Creator Coding Rules [1] as closely as
|
||||||
|
# possible. For documentation of the options, see [2].
|
||||||
|
#
|
||||||
|
# Use ../../tests/manual/clang-format-for-qtc/test.cpp for documenting problems
|
||||||
|
# or testing changes.
|
||||||
|
#
|
||||||
|
# [1] https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html
|
||||||
|
# [2] https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||||
|
#
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: DontAlign
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: Inline
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: true
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: true
|
||||||
|
AfterUnion: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: false
|
||||||
|
SplitEmptyRecord: false
|
||||||
|
SplitEmptyNamespace: false
|
||||||
|
BreakBeforeBinaryOperators: All
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 100
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- forever # avoids { wrapped to next line
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<Q.*'
|
||||||
|
Priority: 200
|
||||||
|
IncludeIsMainRegex: '(Test)?$'
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
# Do not add QT_BEGIN_NAMESPACE/QT_END_NAMESPACE as this will indent lines in between.
|
||||||
|
MacroBlockBegin: ""
|
||||||
|
MacroBlockEnd: ""
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBlockIndentWidth: 4
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 150
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 300
|
||||||
|
PenaltyBreakComment: 500
|
||||||
|
PenaltyBreakFirstLessLess: 400
|
||||||
|
PenaltyBreakString: 600
|
||||||
|
PenaltyExcessCharacter: 50
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 300
|
||||||
|
PointerAlignment: Right
|
||||||
|
ReflowComments: false
|
||||||
|
SortIncludes: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Cpp11
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
@@ -43,7 +43,7 @@ MATCHER_P(HasBuiltIn,
|
|||||||
MATCHER_P(HasSystem,
|
MATCHER_P(HasSystem,
|
||||||
path,
|
path,
|
||||||
std::string(negation ? "isn't " : "is ")
|
std::string(negation ? "isn't " : "is ")
|
||||||
+ PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::BuiltIn}))
|
+ PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::System}))
|
||||||
{
|
{
|
||||||
return arg.path == path && arg.type == HeaderPathType::System;
|
return arg.path == path && arg.type == HeaderPathType::System;
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ MATCHER_P(HasSystem,
|
|||||||
MATCHER_P(HasFramework,
|
MATCHER_P(HasFramework,
|
||||||
path,
|
path,
|
||||||
std::string(negation ? "isn't " : "is ")
|
std::string(negation ? "isn't " : "is ")
|
||||||
+ PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::BuiltIn}))
|
+ PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::Framework}))
|
||||||
{
|
{
|
||||||
return arg.path == path && arg.type == HeaderPathType::Framework;
|
return arg.path == path && arg.type == HeaderPathType::Framework;
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ MATCHER_P(HasFramework,
|
|||||||
MATCHER_P(HasUser,
|
MATCHER_P(HasUser,
|
||||||
path,
|
path,
|
||||||
std::string(negation ? "isn't " : "is ")
|
std::string(negation ? "isn't " : "is ")
|
||||||
+ PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::BuiltIn}))
|
+ PrintToString(HeaderPath{QString::fromUtf8(path), HeaderPathType::User}))
|
||||||
{
|
{
|
||||||
return arg.path == path && arg.type == HeaderPathType::User;
|
return arg.path == path && arg.type == HeaderPathType::User;
|
||||||
}
|
}
|
||||||
@@ -73,42 +73,60 @@ protected:
|
|||||||
HeaderPath{"/builtin_path", HeaderPathType::BuiltIn},
|
HeaderPath{"/builtin_path", HeaderPathType::BuiltIn},
|
||||||
HeaderPath{"/system_path", HeaderPathType::System},
|
HeaderPath{"/system_path", HeaderPathType::System},
|
||||||
HeaderPath{"/framework_path", HeaderPathType::Framework},
|
HeaderPath{"/framework_path", HeaderPathType::Framework},
|
||||||
HeaderPath{"/user_path", HeaderPathType::User}};
|
HeaderPath{"/outside_project_user_path", HeaderPathType::User},
|
||||||
|
HeaderPath{"/build/user_path", HeaderPathType::User},
|
||||||
|
HeaderPath{"/buildb/user_path", HeaderPathType::User},
|
||||||
|
HeaderPath{"/projectb/user_path", HeaderPathType::User},
|
||||||
|
HeaderPath{"/project/user_path", HeaderPathType::User}};
|
||||||
|
|
||||||
projectPart.headerPaths = headerPaths;
|
projectPart.headerPaths = headerPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CppTools::ProjectPart projectPart;
|
CppTools::ProjectPart projectPart;
|
||||||
CppTools::HeaderPathFilter filter{projectPart, CppTools::UseTweakedHeaderPaths::No};
|
CppTools::HeaderPathFilter filter{
|
||||||
|
projectPart, CppTools::UseTweakedHeaderPaths::No, {}, {}, "/project", "/build"};
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(HeaderPathFilter, BuiltIn)
|
TEST_F(HeaderPathFilter, BuiltIn)
|
||||||
{
|
{
|
||||||
filter.process();
|
filter.process();
|
||||||
|
|
||||||
ASSERT_THAT(filter.builtInHeaderPaths, Contains(HasBuiltIn("/builtin_path")));
|
ASSERT_THAT(filter.builtInHeaderPaths, ElementsAre(HasBuiltIn("/builtin_path")));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HeaderPathFilter, System)
|
TEST_F(HeaderPathFilter, System)
|
||||||
{
|
{
|
||||||
filter.process();
|
filter.process();
|
||||||
|
|
||||||
ASSERT_THAT(filter.systemHeaderPaths, Contains(HasSystem("/system_path")));
|
ASSERT_THAT(filter.systemHeaderPaths,
|
||||||
|
ElementsAre(HasSystem("/system_path"),
|
||||||
|
HasFramework("/framework_path"),
|
||||||
|
HasUser("/outside_project_user_path"),
|
||||||
|
HasUser("/buildb/user_path"),
|
||||||
|
HasUser("/projectb/user_path")));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HeaderPathFilter, User)
|
TEST_F(HeaderPathFilter, User)
|
||||||
{
|
{
|
||||||
filter.process();
|
filter.process();
|
||||||
|
|
||||||
ASSERT_THAT(filter.userHeaderPaths, Contains(HasUser("/user_path")));
|
ASSERT_THAT(filter.userHeaderPaths,
|
||||||
|
ElementsAre(HasUser("/build/user_path"), HasUser("/project/user_path")));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HeaderPathFilter, Framework)
|
TEST_F(HeaderPathFilter, NoProjectPathSet)
|
||||||
{
|
{
|
||||||
|
CppTools::HeaderPathFilter filter{projectPart, CppTools::UseTweakedHeaderPaths::No};
|
||||||
|
|
||||||
filter.process();
|
filter.process();
|
||||||
|
|
||||||
ASSERT_THAT(filter.systemHeaderPaths, Contains(HasFramework("/framework_path")));
|
ASSERT_THAT(filter.userHeaderPaths,
|
||||||
|
ElementsAre(HasUser("/outside_project_user_path"),
|
||||||
|
HasUser("/build/user_path"),
|
||||||
|
HasUser("/buildb/user_path"),
|
||||||
|
HasUser("/projectb/user_path"),
|
||||||
|
HasUser("/project/user_path")));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HeaderPathFilter, DontAddInvalidPath)
|
TEST_F(HeaderPathFilter, DontAddInvalidPath)
|
||||||
@@ -119,9 +137,13 @@ TEST_F(HeaderPathFilter, DontAddInvalidPath)
|
|||||||
AllOf(Field(&CppTools::HeaderPathFilter::builtInHeaderPaths,
|
AllOf(Field(&CppTools::HeaderPathFilter::builtInHeaderPaths,
|
||||||
ElementsAre(HasBuiltIn("/builtin_path"))),
|
ElementsAre(HasBuiltIn("/builtin_path"))),
|
||||||
Field(&CppTools::HeaderPathFilter::systemHeaderPaths,
|
Field(&CppTools::HeaderPathFilter::systemHeaderPaths,
|
||||||
ElementsAre(HasSystem("/system_path"), HasFramework("/framework_path"))),
|
ElementsAre(HasSystem("/system_path"),
|
||||||
|
HasFramework("/framework_path"),
|
||||||
|
HasUser("/outside_project_user_path"),
|
||||||
|
HasUser("/buildb/user_path"),
|
||||||
|
HasUser("/projectb/user_path"))),
|
||||||
Field(&CppTools::HeaderPathFilter::userHeaderPaths,
|
Field(&CppTools::HeaderPathFilter::userHeaderPaths,
|
||||||
ElementsAre(HasUser("/user_path")))));
|
ElementsAre(HasUser("/build/user_path"), HasUser("/project/user_path")))));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HeaderPathFilter, ClangHeadersPath)
|
TEST_F(HeaderPathFilter, ClangHeadersPath)
|
||||||
|
@@ -78,10 +78,7 @@ MATCHER_P2(HasIdAndType,
|
|||||||
class PchCreator: public ::testing::Test
|
class PchCreator: public ::testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
PchCreator()
|
PchCreator() { creator.setUnsavedFiles({generatedFile}); }
|
||||||
{
|
|
||||||
creator.setUnsavedFiles({generatedFile});
|
|
||||||
}
|
|
||||||
|
|
||||||
ClangBackEnd::FilePathId id(ClangBackEnd::FilePathView path)
|
ClangBackEnd::FilePathId id(ClangBackEnd::FilePathView path)
|
||||||
{
|
{
|
||||||
@@ -95,10 +92,9 @@ protected:
|
|||||||
FilePath main2Path = TESTDATA_DIR "/builddependencycollector/project/main2.cpp";
|
FilePath main2Path = TESTDATA_DIR "/builddependencycollector/project/main2.cpp";
|
||||||
FilePath header1Path = TESTDATA_DIR "/builddependencycollector/project/header1.h";
|
FilePath header1Path = TESTDATA_DIR "/builddependencycollector/project/header1.h";
|
||||||
FilePath header2Path = TESTDATA_DIR "/builddependencycollector/project/header2.h";
|
FilePath header2Path = TESTDATA_DIR "/builddependencycollector/project/header2.h";
|
||||||
Utils::SmallStringView generatedFileName = "builddependencycollector/project/generated_file.h";
|
|
||||||
FilePath generatedFilePath = TESTDATA_DIR "/builddependencycollector/project/generated_file.h";
|
FilePath generatedFilePath = TESTDATA_DIR "/builddependencycollector/project/generated_file.h";
|
||||||
TestEnvironment environment;
|
TestEnvironment environment;
|
||||||
FileContainer generatedFile{{TESTDATA_DIR, generatedFileName}, "#pragma once", {}};
|
FileContainer generatedFile{generatedFilePath.clone(), "#pragma once", {}};
|
||||||
NiceMock<MockPchManagerClient> mockPchManagerClient;
|
NiceMock<MockPchManagerClient> mockPchManagerClient;
|
||||||
NiceMock<MockClangPathWatcher> mockClangPathWatcher;
|
NiceMock<MockClangPathWatcher> mockClangPathWatcher;
|
||||||
ClangBackEnd::PchCreator creator{environment, database, mockPchManagerClient, mockClangPathWatcher};
|
ClangBackEnd::PchCreator creator{environment, database, mockPchManagerClient, mockClangPathWatcher};
|
||||||
@@ -107,7 +103,8 @@ protected:
|
|||||||
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")},
|
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")},
|
||||||
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
{id(generatedFilePath),
|
||||||
|
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
||||||
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
||||||
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")},
|
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")},
|
||||||
{},
|
{},
|
||||||
@@ -137,6 +134,7 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArguments)
|
|||||||
|
|
||||||
ASSERT_THAT(arguments,
|
ASSERT_THAT(arguments,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
@@ -160,6 +158,7 @@ TEST_F(PchCreator, CreateProjectPartClangCompilerArgumentsWithSystemPch)
|
|||||||
|
|
||||||
ASSERT_THAT(arguments,
|
ASSERT_THAT(arguments,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++-header",
|
"c++-header",
|
||||||
"-std=c++98",
|
"-std=c++98",
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include "mockpchtasksmerger.h"
|
#include "mockpchtasksmerger.h"
|
||||||
|
|
||||||
#include <pchtaskgenerator.h>
|
#include <pchtaskgenerator.h>
|
||||||
|
#include <progresscounter.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -50,7 +51,11 @@ class PchTaskGenerator : public testing::Test
|
|||||||
protected:
|
protected:
|
||||||
NiceMock<MockBuildDependenciesProvider> mockBuildDependenciesProvider;
|
NiceMock<MockBuildDependenciesProvider> mockBuildDependenciesProvider;
|
||||||
NiceMock<MockPchTasksMerger> mockPchTaskMerger;
|
NiceMock<MockPchTasksMerger> mockPchTaskMerger;
|
||||||
ClangBackEnd::PchTaskGenerator generator{mockBuildDependenciesProvider, mockPchTaskMerger};
|
NiceMock<MockFunction<void(int, int)>> mockProgressCounterCallback;
|
||||||
|
ClangBackEnd::ProgressCounter progressCounter{mockProgressCounterCallback.AsStdFunction()};
|
||||||
|
ClangBackEnd::PchTaskGenerator generator{mockBuildDependenciesProvider,
|
||||||
|
mockPchTaskMerger,
|
||||||
|
progressCounter};
|
||||||
ClangBackEnd::ProjectPartContainer projectPart1{
|
ClangBackEnd::ProjectPartContainer projectPart1{
|
||||||
"ProjectPart1",
|
"ProjectPart1",
|
||||||
{"--yi"},
|
{"--yi"},
|
||||||
@@ -132,6 +137,18 @@ TEST_F(PchTaskGenerator, AddProjectParts)
|
|||||||
generator.addProjectParts({projectPart1}, {"ToolChainArgument"});
|
generator.addProjectParts({projectPart1}, {"ToolChainArgument"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(PchTaskGenerator, ProgressCounter)
|
||||||
|
{
|
||||||
|
ON_CALL(mockBuildDependenciesProvider, create(_)).WillByDefault(Return(buildDependency));
|
||||||
|
|
||||||
|
EXPECT_CALL(mockProgressCounterCallback, Call(0, 3));
|
||||||
|
EXPECT_CALL(mockProgressCounterCallback, Call(1, 3));
|
||||||
|
EXPECT_CALL(mockProgressCounterCallback, Call(2, 3));
|
||||||
|
EXPECT_CALL(mockProgressCounterCallback, Call(3, 3));
|
||||||
|
|
||||||
|
generator.addProjectParts({projectPart1, projectPart1, projectPart1}, {"ToolChainArgument"});
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(PchTaskGenerator, RemoveProjectParts)
|
TEST_F(PchTaskGenerator, RemoveProjectParts)
|
||||||
{
|
{
|
||||||
ON_CALL(mockBuildDependenciesProvider, create(_)).WillByDefault(Return(buildDependency));
|
ON_CALL(mockBuildDependenciesProvider, create(_)).WillByDefault(Return(buildDependency));
|
||||||
|
@@ -173,7 +173,7 @@ TEST_F(PchTasksMerger, MacrosCanBeMerged)
|
|||||||
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"QI"}, {"SE", "4", 1}, {"SAN", "3", 3}};
|
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"QI"}, {"SE", "4", 1}, {"SAN", "3", 3}};
|
||||||
CompilerMacros compilerMacros2{{"BA"}, {"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
|
CompilerMacros compilerMacros2{{"BA"}, {"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
|
||||||
|
|
||||||
auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
|
auto canBeMerged = !Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
|
||||||
|
|
||||||
ASSERT_TRUE(canBeMerged);
|
ASSERT_TRUE(canBeMerged);
|
||||||
}
|
}
|
||||||
@@ -183,7 +183,7 @@ TEST_F(PchTasksMerger, MacrosCannotBeMergedBecauseDifferentValue)
|
|||||||
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"SAN", "3", 3}};
|
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"SAN", "3", 3}};
|
||||||
CompilerMacros compilerMacros2{{"ER", "1", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
|
CompilerMacros compilerMacros2{{"ER", "1", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
|
||||||
|
|
||||||
auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
|
auto canBeMerged = !Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
|
||||||
|
|
||||||
ASSERT_FALSE(canBeMerged);
|
ASSERT_FALSE(canBeMerged);
|
||||||
}
|
}
|
||||||
@@ -193,7 +193,7 @@ TEST_F(PchTasksMerger, MacrosCannotBeMergedBecauseUndefinedMacro)
|
|||||||
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"YI"}, {"SAN", "3", 3}};
|
CompilerMacros compilerMacros1{{"ER", "2", 2}, {"SE", "4", 1}, {"YI"}, {"SAN", "3", 3}};
|
||||||
CompilerMacros compilerMacros2{{"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
|
CompilerMacros compilerMacros2{{"ER", "2", 2}, {"YI", "1", 1}, {"SAN", "3", 3}};
|
||||||
|
|
||||||
auto canBeMerged = Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
|
auto canBeMerged = !Merger::hasDuplicates(Merger::mergeMacros(compilerMacros1, compilerMacros2));
|
||||||
|
|
||||||
ASSERT_FALSE(canBeMerged);
|
ASSERT_FALSE(canBeMerged);
|
||||||
}
|
}
|
||||||
|
@@ -86,6 +86,7 @@ protected:
|
|||||||
projectPart.files.push_back(header2ProjectFile);
|
projectPart.files.push_back(header2ProjectFile);
|
||||||
projectPart.files.push_back(source1ProjectFile);
|
projectPart.files.push_back(source1ProjectFile);
|
||||||
projectPart.files.push_back(source2ProjectFile);
|
projectPart.files.push_back(source2ProjectFile);
|
||||||
|
projectPart.files.push_back(nonActiveProjectFile);
|
||||||
projectPart.displayName = "projectb";
|
projectPart.displayName = "projectb";
|
||||||
projectPart.projectMacros = {{"FOO", "2"}, {"BAR", "1"}};
|
projectPart.projectMacros = {{"FOO", "2"}, {"BAR", "1"}};
|
||||||
projectPartId = projectPart.id();
|
projectPartId = projectPart.id();
|
||||||
@@ -94,15 +95,19 @@ protected:
|
|||||||
projectPart2.files.push_back(header1ProjectFile);
|
projectPart2.files.push_back(header1ProjectFile);
|
||||||
projectPart2.files.push_back(source2ProjectFile);
|
projectPart2.files.push_back(source2ProjectFile);
|
||||||
projectPart2.files.push_back(source1ProjectFile);
|
projectPart2.files.push_back(source1ProjectFile);
|
||||||
|
projectPart2.files.push_back(nonActiveProjectFile);
|
||||||
projectPart2.displayName = "projectaa";
|
projectPart2.displayName = "projectaa";
|
||||||
projectPart2.projectMacros = {{"BAR", "1"}, {"FOO", "2"}};
|
projectPart2.projectMacros = {{"BAR", "1"}, {"FOO", "2"}};
|
||||||
projectPartId2 = projectPart2.id();
|
projectPartId2 = projectPart2.id();
|
||||||
|
|
||||||
|
nonBuildingProjectPart.files.push_back(cannotBuildSourceProjectFile);
|
||||||
|
nonBuildingProjectPart.displayName = "nonbuilding";
|
||||||
|
nonBuildingProjectPart.selectedForBuilding = false;
|
||||||
|
|
||||||
Utils::SmallStringVector arguments{ClangPchManager::ProjectUpdater::toolChainArguments(
|
Utils::SmallStringVector arguments{
|
||||||
&projectPart)};
|
ClangPchManager::ProjectUpdater::toolChainArguments(&projectPart)};
|
||||||
Utils::SmallStringVector arguments2{ClangPchManager::ProjectUpdater::toolChainArguments(
|
Utils::SmallStringVector arguments2{
|
||||||
&projectPart2)};
|
ClangPchManager::ProjectUpdater::toolChainArguments(&projectPart2)};
|
||||||
|
|
||||||
expectedContainer = {projectPartId.clone(),
|
expectedContainer = {projectPartId.clone(),
|
||||||
arguments.clone(),
|
arguments.clone(),
|
||||||
@@ -143,9 +148,14 @@ protected:
|
|||||||
CppTools::ProjectFile header1ProjectFile{QString(headerPaths[0]), CppTools::ProjectFile::CXXHeader};
|
CppTools::ProjectFile header1ProjectFile{QString(headerPaths[0]), CppTools::ProjectFile::CXXHeader};
|
||||||
CppTools::ProjectFile header2ProjectFile{QString(headerPaths[1]), CppTools::ProjectFile::CXXHeader};
|
CppTools::ProjectFile header2ProjectFile{QString(headerPaths[1]), CppTools::ProjectFile::CXXHeader};
|
||||||
CppTools::ProjectFile source1ProjectFile{QString(sourcePaths[0]), CppTools::ProjectFile::CXXSource};
|
CppTools::ProjectFile source1ProjectFile{QString(sourcePaths[0]), CppTools::ProjectFile::CXXSource};
|
||||||
CppTools::ProjectFile source2ProjectFile{QString(sourcePaths[1]), CppTools::ProjectFile::CXXSource};
|
CppTools::ProjectFile source2ProjectFile{QString(sourcePaths[1]),
|
||||||
|
CppTools::ProjectFile::CXXSource};
|
||||||
|
CppTools::ProjectFile cannotBuildSourceProjectFile{QString("/cannot/build"),
|
||||||
|
CppTools::ProjectFile::CXXSource};
|
||||||
|
CppTools::ProjectFile nonActiveProjectFile{QString("/foo"), CppTools::ProjectFile::CXXSource, false};
|
||||||
CppTools::ProjectPart projectPart;
|
CppTools::ProjectPart projectPart;
|
||||||
CppTools::ProjectPart projectPart2;
|
CppTools::ProjectPart projectPart2;
|
||||||
|
CppTools::ProjectPart nonBuildingProjectPart;
|
||||||
ProjectPartContainer expectedContainer;
|
ProjectPartContainer expectedContainer;
|
||||||
ProjectPartContainer expectedContainer2;
|
ProjectPartContainer expectedContainer2;
|
||||||
FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}};
|
FileContainer generatedFile{{"/path/to", "header1.h"}, "content", {}};
|
||||||
@@ -240,7 +250,8 @@ TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainer)
|
|||||||
|
|
||||||
TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainersHaveSameSizeLikeProjectParts)
|
TEST_F(ProjectUpdater, ConvertProjectPartToProjectPartContainersHaveSameSizeLikeProjectParts)
|
||||||
{
|
{
|
||||||
auto containers = updater.toProjectPartContainers({&projectPart, &projectPart});
|
auto containers = updater.toProjectPartContainers(
|
||||||
|
{&projectPart, &projectPart, &nonBuildingProjectPart});
|
||||||
|
|
||||||
ASSERT_THAT(containers, SizeIs(2));
|
ASSERT_THAT(containers, SizeIs(2));
|
||||||
}
|
}
|
||||||
|
@@ -267,6 +267,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesInCollector)
|
|||||||
setFile(main1PathId,
|
setFile(main1PathId,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
"-Wno-pragma-once-outside-header",
|
"-Wno-pragma-once-outside-header",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++",
|
"c++",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
@@ -297,6 +298,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithPrecompiledHeaderInColl
|
|||||||
setFile(main1PathId,
|
setFile(main1PathId,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
"-Wno-pragma-once-outside-header",
|
"-Wno-pragma-once-outside-header",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++",
|
"c++",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
@@ -330,6 +332,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsAddFilesWithoutPrecompiledHeaderInC
|
|||||||
setFile(main1PathId,
|
setFile(main1PathId,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
"-Wno-pragma-once-outside-header",
|
"-Wno-pragma-once-outside-header",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++",
|
"c++",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
@@ -510,6 +513,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderWithoutProjectPartArtifact)
|
|||||||
setFile(main1PathId,
|
setFile(main1PathId,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
"-Wno-pragma-once-outside-header",
|
"-Wno-pragma-once-outside-header",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++",
|
"c++",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
@@ -562,6 +566,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderWithProjectPartArtifact)
|
|||||||
setFile(Eq(main1PathId),
|
setFile(Eq(main1PathId),
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
"-Wno-pragma-once-outside-header",
|
"-Wno-pragma-once-outside-header",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++",
|
"c++",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
@@ -616,6 +621,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingS
|
|||||||
setFile(main1PathId,
|
setFile(main1PathId,
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
"-Wno-pragma-once-outside-header",
|
"-Wno-pragma-once-outside-header",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++",
|
"c++",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
@@ -673,6 +679,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder)
|
|||||||
setFile(Eq(sourceFileIds[0]),
|
setFile(Eq(sourceFileIds[0]),
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
"-DFOO",
|
"-DFOO",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++",
|
"c++",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
@@ -736,6 +743,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrderButGetsAnErrorForCollectingSy
|
|||||||
setFile(Eq(sourceFileIds[0]),
|
setFile(Eq(sourceFileIds[0]),
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
"-DFOO",
|
"-DFOO",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++",
|
"c++",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
@@ -779,6 +787,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsUsingPrecompiledHeader)
|
|||||||
setFile(Eq(sourceFileIds[0]),
|
setFile(Eq(sourceFileIds[0]),
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
"-DFOO",
|
"-DFOO",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++",
|
"c++",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
@@ -814,6 +823,7 @@ TEST_F(SymbolIndexer, UpdateChangedPathIsNotUsingPrecompiledHeaderIfItNotExists)
|
|||||||
setFile(Eq(sourceFileIds[0]),
|
setFile(Eq(sourceFileIds[0]),
|
||||||
ElementsAre("clang++",
|
ElementsAre("clang++",
|
||||||
"-DFOO",
|
"-DFOO",
|
||||||
|
"-DNOMINMAX",
|
||||||
"-x",
|
"-x",
|
||||||
"c++",
|
"c++",
|
||||||
"-std=c++14",
|
"-std=c++14",
|
||||||
|
@@ -46,7 +46,15 @@ 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}, {"LIU", 2}, {"QI", 3}, {"SAN", 3}, {"SE", 4}, {"WU", 5}};
|
UsedMacros usedMacros{{"YI", 1},
|
||||||
|
{"ER", 2},
|
||||||
|
{"SE", 2},
|
||||||
|
{"LIU", 2},
|
||||||
|
{"QI", 3},
|
||||||
|
{"WU", 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},
|
||||||
|
Reference in New Issue
Block a user