Merge remote-tracking branch 'origin/3.4'

This commit is contained in:
Eike Ziller
2015-03-16 10:27:16 +01:00
43 changed files with 615 additions and 224 deletions

View File

@@ -1706,7 +1706,10 @@ bool CreateBindings::visit(Declaration *decl)
bool CreateBindings::visit(Function *function)
{
ClassOrNamespace *previous = _currentClassOrNamespace;
_currentClassOrNamespace = lookupType(function, previous);
ClassOrNamespace *binding = lookupType(function, previous);
if (!binding)
return false;
_currentClassOrNamespace = binding;
for (unsigned i = 0, count = function->memberCount(); i < count; ++i) {
Symbol *s = function->memberAt(i);
if (Block *b = s->asBlock())

View File

@@ -900,11 +900,7 @@ void Preprocessor::skipPreprocesorDirective(PPToken *tk)
ScopedBoolSwap s(m_state.m_inPreprocessorDirective, true);
while (isContinuationToken(*tk)) {
if (tk->isComment()) {
synchronizeOutputLines(*tk);
enforceSpacing(*tk, true);
currentOutputBuffer().append(tk->tokenStart(), tk->bytes());
}
scanComment(tk);
lex(tk);
}
}
@@ -1461,6 +1457,23 @@ void Preprocessor::preprocess(const QString &fileName, const QByteArray &source,
m_state.popTokenBuffer();
}
bool Preprocessor::scanComment(Preprocessor::PPToken *tk)
{
if (!tk->isComment())
return false;
synchronizeOutputLines(*tk);
enforceSpacing(*tk, true);
currentOutputBuffer().append(tk->tokenStart(), tk->bytes());
return true;
}
bool Preprocessor::consumeComments(PPToken *tk)
{
while (scanComment(tk))
lex(tk);
return tk->isNot(T_EOF_SYMBOL);
}
bool Preprocessor::collectActualArguments(PPToken *tk, QVector<QVector<PPToken> > *actuals)
{
Q_ASSERT(tk);
@@ -1468,12 +1481,22 @@ bool Preprocessor::collectActualArguments(PPToken *tk, QVector<QVector<PPToken>
lex(tk); // consume the identifier
// consume comments
while (tk->isComment()) {
bool lastCommentIsCpp = false;
while (scanComment(tk)) {
/* After C++ comments we need to add a new line
e.g.
#define foo(a, b) int a = b
foo // comment
(x, 3);
can result in
// commentint
x = 3;
*/
lastCommentIsCpp = tk->is(T_CPP_COMMENT) || tk->is(T_CPP_DOXY_COMMENT);
lex(tk);
if (!tk)
return false;
}
if (lastCommentIsCpp)
maybeStartOutputLine();
if (tk->isNot(T_LPAREN))
//### TODO: error message
@@ -1639,6 +1662,9 @@ void Preprocessor::handleDefineDirective(PPToken *tk)
const unsigned defineOffset = tk->byteOffset;
lex(tk); // consume "define" token
if (!consumeComments(tk))
return;
if (tk->isNot(T_IDENTIFIER))
return;
@@ -1658,6 +1684,8 @@ void Preprocessor::handleDefineDirective(PPToken *tk)
macro.setFunctionLike(true);
lex(tk); // skip `('
if (!consumeComments(tk))
return;
bool hasIdentifier = false;
if (isContinuationToken(*tk) && tk->is(T_IDENTIFIER)) {
@@ -1665,13 +1693,19 @@ void Preprocessor::handleDefineDirective(PPToken *tk)
macro.addFormal(tk->asByteArrayRef().toByteArray());
lex(tk);
if (!consumeComments(tk))
return;
while (isContinuationToken(*tk) && tk->is(T_COMMA)) {
lex(tk);
if (!consumeComments(tk))
return;
if (isContinuationToken(*tk) && tk->is(T_IDENTIFIER)) {
macro.addFormal(tk->asByteArrayRef().toByteArray());
lex(tk);
if (!consumeComments(tk))
return;
} else {
hasIdentifier = false;
}
@@ -1683,6 +1717,8 @@ void Preprocessor::handleDefineDirective(PPToken *tk)
if (!hasIdentifier)
macro.addFormal("__VA_ARGS__");
lex(tk); // consume elipsis token
if (!consumeComments(tk))
return;
}
if (isContinuationToken(*tk) && tk->is(T_RPAREN))
lex(tk); // consume ")" token
@@ -1727,14 +1763,8 @@ void Preprocessor::handleDefineDirective(PPToken *tk)
previousUtf16charsOffset = tk->utf16charOffset;
previousLine = tk->lineno;
// Discard comments in macro definitions (keep comments flag doesn't apply here).
if (tk->isComment()) {
synchronizeOutputLines(*tk);
enforceSpacing(*tk, true);
currentOutputBuffer().append(tk->tokenStart(), tk->bytes());
} else {
if (!scanComment(tk))
bodyTokens.push_back(*tk);
}
lex(tk);
}

View File

@@ -218,6 +218,8 @@ private:
QVector<CPlusPlus::Token> tokenize(const QByteArray &text) const;
bool scanComment(PPToken *tk);
bool consumeComments(PPToken *tk);
bool collectActualArguments(PPToken *tk, QVector<QVector<PPToken> > *actuals);
void scanActualArgument(PPToken *tk, QVector<PPToken> *tokens);

View File

@@ -2231,7 +2231,7 @@ static bool dumpQDateTime(const SymbolGroupValue &v, std::wostream &str)
<< offset << separator
<< std::hex;
if (timeZoneString.length() > 2) {
for (int i = 1; i < timeZoneString.length() - 1; ++i) // remove '"'
for (unsigned i = 1; i < timeZoneString.length() - 1; ++i) // remove '"'
str << (int)timeZoneString.at(i);
}
str << std::dec << separator << status;

View File

@@ -326,8 +326,8 @@ void BaseTreeView::showProgressIndicator()
*/
void BaseTreeView::hideProgressIndicator()
{
QTC_ASSERT(d->m_progressIndicator, return);
d->m_progressIndicator->hide();
if (d->m_progressIndicator)
d->m_progressIndicator->hide();
}
void BaseTreeView::setSettings(QSettings *settings, const QByteArray &key)

View File

@@ -48,7 +48,7 @@ class FadingIndicatorPrivate : public QWidget
Q_OBJECT
public:
FadingIndicatorPrivate(QWidget *parent = 0)
FadingIndicatorPrivate(QWidget *parent, FadingIndicator::TextSize size)
: QWidget(parent)
{
m_effect = new QGraphicsOpacityEffect(this);
@@ -57,7 +57,7 @@ public:
m_label = new QLabel;
QFont font = m_label->font();
font.setPixelSize(45);
font.setPixelSize(size == FadingIndicator::LargeText ? 45 : 22);
m_label->setFont(font);
QPalette pal = palette();
pal.setColor(QPalette::Foreground, pal.color(QPalette::Background));
@@ -126,16 +126,16 @@ private:
namespace FadingIndicator {
void showText(QWidget *parent, const QString &text)
void showText(QWidget *parent, const QString &text, TextSize size)
{
auto indicator = new Internal::FadingIndicatorPrivate(parent);
auto indicator = new Internal::FadingIndicatorPrivate(parent, size);
indicator->setText(text);
indicator->run(1000); // deletes itself
indicator->run(2500); // deletes itself
}
void showPixmap(QWidget *parent, const QString &pixmap)
{
auto indicator = new Internal::FadingIndicatorPrivate(parent);
auto indicator = new Internal::FadingIndicatorPrivate(parent, LargeText);
indicator->setPixmap(pixmap);
indicator->run(300); // deletes itself
}

View File

@@ -40,7 +40,13 @@
namespace Utils {
namespace FadingIndicator {
QTCREATOR_UTILS_EXPORT void showText(QWidget *parent, const QString &text);
enum TextSize {
SmallText,
LargeText
};
QTCREATOR_UTILS_EXPORT void showText(QWidget *parent, const QString &text,
TextSize size = LargeText);
QTCREATOR_UTILS_EXPORT void showPixmap(QWidget *parent, const QString &pixmap);
} // FadingIndicator

View File

@@ -52,6 +52,7 @@
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h>
#include <utils/algorithm.h>
#include <utils/fancymainwindow.h>
@@ -420,6 +421,7 @@ bool AnalyzerManagerPrivate::showPromptDialog(const QString &title, const QStrin
void AnalyzerManagerPrivate::startTool()
{
QTC_ASSERT(m_currentAction, return);
TaskHub::clearTasks(Constants::ANALYZERTASK_ID);
m_currentAction->toolStarter()();
}

View File

@@ -70,6 +70,7 @@
#include <QFileDialog>
#include <QTimer>
#include <QCheckBox>
#include <QScrollArea>
#include <limits>
@@ -103,7 +104,7 @@ Project *androidProject(const Utils::FileName &fileName)
} // anonymous namespace
AndroidManifestEditorWidget::AndroidManifestEditorWidget()
: QScrollArea(),
: QStackedWidget(),
m_dirty(false),
m_stayClean(false),
m_setAppName(false),
@@ -118,8 +119,6 @@ AndroidManifestEditorWidget::AndroidManifestEditorWidget()
m_editor = new AndroidManifestEditor(this);
setWidgetResizable(true);
connect(&m_timerParseCheck, SIGNAL(timeout()),
this, SLOT(delayedParseCheck()));
@@ -129,11 +128,8 @@ AndroidManifestEditorWidget::AndroidManifestEditorWidget()
void AndroidManifestEditorWidget::initializePage()
{
m_stackedWidget = new QStackedWidget(this);
setWidget(m_stackedWidget);
Core::IContext *myContext = new Core::IContext(this);
myContext->setWidget(m_stackedWidget);
myContext->setWidget(this);
myContext->setContext(Core::Context(androidManifestEditorGeneralPaneContextId)); // where is the context used?
Core::ICore::addContextObject(myContext);
@@ -458,8 +454,12 @@ void AndroidManifestEditorWidget::initializePage()
topLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
m_stackedWidget->insertWidget(General, mainWidget);
m_stackedWidget->insertWidget(Source, m_textEditorWidget);
QScrollArea *mainWidgetScrollArea = new QScrollArea;
mainWidgetScrollArea->setWidgetResizable(true);
mainWidgetScrollArea->setWidget(mainWidget);
insertWidget(General, mainWidgetScrollArea);
insertWidget(Source, m_textEditorWidget);
}
bool AndroidManifestEditorWidget::eventFilter(QObject *obj, QEvent *event)
@@ -540,7 +540,7 @@ bool AndroidManifestEditorWidget::isModified() const
AndroidManifestEditorWidget::EditorPage AndroidManifestEditorWidget::activePage() const
{
return AndroidManifestEditorWidget::EditorPage(m_stackedWidget->currentIndex());
return AndroidManifestEditorWidget::EditorPage(currentIndex());
}
bool AndroidManifestEditorWidget::setActivePage(EditorPage page)
@@ -564,7 +564,7 @@ bool AndroidManifestEditorWidget::setActivePage(EditorPage page)
// m_packageNameLineEdit->setFocus();
}
m_stackedWidget->setCurrentIndex(page);
setCurrentIndex(page);
return true;
}

View File

@@ -35,7 +35,6 @@
#include <QAbstractListModel>
#include <QStackedWidget>
#include <QScrollArea>
#include <QTimer>
QT_BEGIN_NAMESPACE
@@ -86,7 +85,7 @@ public:
explicit AndroidManifestTextEditorWidget(AndroidManifestEditorWidget *parent);
};
class AndroidManifestEditorWidget : public QScrollArea
class AndroidManifestEditorWidget : public QStackedWidget
{
Q_OBJECT
public:
@@ -196,7 +195,6 @@ private:
QTimer m_timerParseCheck;
TextEditor::TextEditorWidget *m_textEditorWidget;
QStackedWidget *m_stackedWidget;
AndroidManifestEditor *m_editor;
};
} // namespace Internal

View File

@@ -1061,6 +1061,8 @@ int ClangCompletionAssistProcessor::startCompletionInternal(const QString fileNa
foreach (ClangAssistProposalItem *item, items.values())
m_completions.append(item);
addSnippets();
return m_startPosition;
}

View File

@@ -38,11 +38,8 @@ namespace Constants {
// Modes
const char MODE_WELCOME[] = "Welcome";
const char MODE_WELCOME_TYPE[] = "Type.Welcome";
const char MODE_EDIT[] = "Edit";
const char MODE_EDIT_TYPE[] = "Type.Edit";
const char MODE_DESIGN[] = "Design";
const char MODE_DESIGN_TYPE[] = "Type.Design";
const int P_MODE_WELCOME = 100;
const int P_MODE_EDIT = 90;
const int P_MODE_DESIGN = 89;

View File

@@ -32,6 +32,8 @@
#include <aggregation/aggregate.h>
#include <coreplugin/coreconstants.h>
#include <utils/fadingindicator.h>
#include <utils/qtcassert.h>
#include <QDebug>
@@ -134,7 +136,12 @@ bool CurrentDocumentFind::replaceStep(const QString &before, const QString &afte
int CurrentDocumentFind::replaceAll(const QString &before, const QString &after, FindFlags findFlags)
{
QTC_ASSERT(m_currentFind, return 0);
return m_currentFind->replaceAll(before, after, findFlags);
QTC_CHECK(m_currentWidget);
int count = m_currentFind->replaceAll(before, after, findFlags);
Utils::FadingIndicator::showText(m_currentWidget,
tr("%1 occurrences replaced.").arg(count),
Utils::FadingIndicator::SmallText);
return count;
}
void CurrentDocumentFind::defineFindScope()

View File

@@ -192,6 +192,9 @@ private slots:
void test_quickfix_AssignToLocalVariable_templates();
void test_quickfix_ExtractFunction_data();
void test_quickfix_ExtractFunction();
void test_quickfix_ExtractLiteralAsParameter_typeDeduction_data();
void test_quickfix_ExtractLiteralAsParameter_typeDeduction();
void test_quickfix_ExtractLiteralAsParameter_freeFunction_separateFiles();

View File

@@ -40,6 +40,8 @@
#include <QDir>
#include <utils/qtcassert.h>
using namespace CppEditor::Internal;
namespace CppEditor {
@@ -48,14 +50,34 @@ namespace Tests {
TestDocument::TestDocument(const QByteArray &fileName, const QByteArray &source, char cursorMarker)
: CppTools::Tests::TestDocument(fileName, source, cursorMarker)
, m_cursorPosition(m_source.indexOf(QLatin1Char(m_cursorMarker)))
, m_cursorPosition(-1)
, m_anchorPosition(-1)
, m_selectionStartMarker(QLatin1Char(m_cursorMarker) + QLatin1String("{start}"))
, m_selectionEndMarker(QLatin1Char(m_cursorMarker) + QLatin1String("{end}"))
, m_editor(0)
, m_editorWidget(0)
{
// Try to find selection markers
const int selectionStartIndex = m_source.indexOf(m_selectionStartMarker);
const int selectionEndIndex = m_source.indexOf(m_selectionEndMarker);
const bool bothSelectionMarkersFound = selectionStartIndex != -1 && selectionEndIndex != -1;
const bool noneSelectionMarkersFounds = selectionStartIndex == -1 && selectionEndIndex == -1;
QTC_ASSERT(bothSelectionMarkersFound || noneSelectionMarkersFounds, return);
if (selectionStartIndex != -1) {
m_cursorPosition = selectionEndIndex;
m_anchorPosition = selectionStartIndex;
// No selection markers found, so check for simple cursorMarker
} else {
m_cursorPosition = m_source.indexOf(QLatin1Char(cursorMarker));
}
}
bool TestDocument::hasCursorMarker() const { return m_cursorPosition != -1; }
bool TestDocument::hasAnchorMarker() const { return m_anchorPosition != -1; }
TestCase::TestCase(bool runGarbageCollector)
: CppTools::Tests::TestCase(runGarbageCollector)
{

View File

@@ -50,9 +50,13 @@ public:
TestDocument(const QByteArray &fileName, const QByteArray &source, char cursorMarker = '@');
bool hasCursorMarker() const;
bool hasAnchorMarker() const;
public:
int m_cursorPosition;
int m_anchorPosition;
QString m_selectionStartMarker;
QString m_selectionEndMarker;
CppEditor *m_editor;
CppEditorWidget *m_editorWidget;
};

View File

@@ -395,6 +395,78 @@ Symbol *findDefinition(Symbol *symbol, const Snapshot &snapshot, SymbolFinder *s
return symbolFinder->findMatchingDefinition(symbol, snapshot);
}
bool maybeAppendArgumentOrParameterList(QString *expression, const QTextCursor &textCursor)
{
QTC_ASSERT(expression, return false);
QTextDocument *textDocument = textCursor.document();
QTC_ASSERT(textDocument, return false);
// Skip white space
QTextCursor cursor(textCursor);
while (textDocument->characterAt(cursor.position()).isSpace()
&& cursor.movePosition(QTextCursor::NextCharacter)) {
}
// Find/Include "(arg1, arg2, ...)"
if (textDocument->characterAt(cursor.position()) == QLatin1Char('(')) {
if (TextBlockUserData::findNextClosingParenthesis(&cursor, true)) {
expression->append(cursor.selectedText());
return true;
}
}
return false;
}
bool isCursorOnTrailingReturnType(const QList<AST *> &astPath)
{
for (auto it = astPath.cend() - 1, begin = astPath.cbegin(); it >= begin; --it) {
const auto nextIt = it + 1;
const auto nextNextIt = nextIt + 1;
if (nextNextIt != astPath.cend() && (*it)->asTrailingReturnType()) {
return (*nextIt)->asNamedTypeSpecifier()
&& ((*nextNextIt)->asSimpleName()
|| (*nextNextIt)->asQualifiedName()
|| (*nextNextIt)->asTemplateId());
}
}
return false;
}
void maybeFixExpressionInTrailingReturnType(QString *expression,
const QTextCursor &textCursor,
const Document::Ptr documentFromSemanticInfo)
{
QTC_ASSERT(expression, return);
if (!documentFromSemanticInfo)
return;
const QString arrow = QLatin1String("->");
const int arrowPosition = expression->lastIndexOf(arrow);
if (arrowPosition != -1) {
ASTPath astPathFinder(documentFromSemanticInfo);
const QList<AST *> astPath = astPathFinder(textCursor);
if (isCursorOnTrailingReturnType(astPath))
*expression = expression->mid(arrowPosition + arrow.size()).trimmed();
}
}
QString expressionUnderCursorAsString(const QTextCursor &textCursor,
const Document::Ptr documentFromSemanticInfo,
const LanguageFeatures &features)
{
ExpressionUnderCursor expressionUnderCursor(features);
QString expression = expressionUnderCursor(textCursor);
if (!maybeAppendArgumentOrParameterList(&expression, textCursor))
maybeFixExpressionInTrailingReturnType(&expression, textCursor, documentFromSemanticInfo);
return expression;
}
} // anonymous namespace
FollowSymbolUnderCursor::FollowSymbolUnderCursor(CppEditorWidget *widget)
@@ -613,22 +685,9 @@ TextEditorWidget::Link FollowSymbolUnderCursor::findLink(const QTextCursor &curs
return link;
// Evaluate the type of the expression under the cursor
ExpressionUnderCursor expressionUnderCursor(features);
QString expression = expressionUnderCursor(tc);
for (int pos = tc.position();; ++pos) {
const QChar ch = document->characterAt(pos);
if (ch.isSpace())
continue;
if (ch == QLatin1Char('(') && !expression.isEmpty()) {
tc.setPosition(pos);
if (TextBlockUserData::findNextClosingParenthesis(&tc, true))
expression.append(tc.selectedText());
}
break;
}
QTC_CHECK(document == tc.document());
const QString expression = expressionUnderCursorAsString(tc, documentFromSemanticInfo,
features);
const QSharedPointer<TypeOfExpression> typeOfExpression(new TypeOfExpression);
typeOfExpression->init(doc, snapshot);
// make possible to instantiate templates

View File

@@ -73,8 +73,27 @@ QuickFixTestDocument::QuickFixTestDocument(const QByteArray &fileName,
: TestDocument(fileName, source)
, m_expectedSource(QString::fromUtf8(expectedSource))
{
if (m_cursorPosition > -1)
removeMarkers();
}
void QuickFixTestDocument::removeMarkers()
{
// Remove selection markers
if (m_anchorPosition != -1) {
if (m_anchorPosition < m_cursorPosition) {
m_source.remove(m_anchorPosition, m_selectionStartMarker.size());
m_cursorPosition -= m_selectionStartMarker.size();
m_source.remove(m_cursorPosition, m_selectionEndMarker.size());
} else {
m_source.remove(m_cursorPosition, m_selectionEndMarker.size());
m_anchorPosition -= m_selectionEndMarker.size();
m_source.remove(m_anchorPosition, m_selectionStartMarker.size());
}
// Remove simple cursor marker
} else if (m_cursorPosition != -1) {
m_source.remove(m_cursorPosition, 1);
}
const int cursorPositionInExpectedSource
= m_expectedSource.indexOf(QLatin1Char(m_cursorMarker));
@@ -135,9 +154,16 @@ BaseQuickFixTestCase::BaseQuickFixTestCase(const QList<QuickFixTestDocument::Ptr
closeEditorAtEndOfTestCase(document->m_editor);
// Set cursor position
const int cursorPosition = document->hasCursorMarker()
? document->m_cursorPosition : 0;
document->m_editor->setCursorPosition(cursorPosition);
if (document->hasCursorMarker()) {
if (document->hasAnchorMarker()) {
document->m_editor->setCursorPosition(document->m_anchorPosition);
document->m_editor->select(document->m_cursorPosition);
} else {
document->m_editor->setCursorPosition(document->m_cursorPosition);
}
} else {
document->m_editor->setCursorPosition(0);
}
// Rehighlight
waitForRehighlightedSemanticDocument(document->m_editorWidget);
@@ -4349,6 +4375,39 @@ void CppEditorPlugin::test_quickfix_AssignToLocalVariable_templates()
QuickFixOperationTest(testDocuments, &factory);
}
void CppEditorPlugin::test_quickfix_ExtractFunction_data()
{
QTest::addColumn<QByteArray>("original");
QTest::addColumn<QByteArray>("expected");
QTest::newRow("basic")
<< _("void f()\n"
"{\n"
" @{start}g();@{end}\n"
"}\n")
<< _("void extracted()\n"
"{\n"
" g();\n"
"}\n"
"\n"
"void f()\n"
"{\n"
" extracted();\n"
"}\n");
}
void CppEditorPlugin::test_quickfix_ExtractFunction()
{
QFETCH(QByteArray, original);
QFETCH(QByteArray, expected);
QList<QuickFixTestDocument::Ptr> testDocuments;
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
ExtractFunction factory([]() { return QLatin1String("extracted"); });
QuickFixOperationTest(testDocuments, &factory);
}
void CppEditorPlugin::test_quickfix_ExtractLiteralAsParameter_typeDeduction_data()
{
QTest::addColumn<QByteArray>("typeString");

View File

@@ -50,8 +50,9 @@ namespace Tests {
/// Represents a test document before and after applying the quick fix.
///
/// A TestDocument's source may contain an '@' character to denote
/// the cursor position. This marker is removed before the Editor reads
/// the document.
/// the cursor position. For selections the markers "@{start}" and
/// "@{end}" can be used. The markers are removed before the editor
/// reads the document.
///
class QuickFixTestDocument : public TestDocument
@@ -65,6 +66,9 @@ public:
static Ptr create(const QByteArray &fileName, const QByteArray &source,
const QByteArray &expectedSource);
private:
void removeMarkers();
public:
QString m_expectedSource;
};
@@ -74,7 +78,8 @@ typedef QList<QuickFixTestDocument::Ptr> QuickFixTestDocuments;
class BaseQuickFixTestCase : public TestCase
{
public:
/// Exactly one QuickFixTestDocument must contain the cursor position marker '@'.
/// Exactly one QuickFixTestDocument must contain the cursor position marker '@'
/// or "@{start}" and "@{end}"
BaseQuickFixTestCase(const QList<QuickFixTestDocument::Ptr> &testDocuments,
const CppTools::ProjectPart::HeaderPaths &headerPaths
= CppTools::ProjectPart::HeaderPaths());

View File

@@ -3118,13 +3118,16 @@ public:
int extractionEnd,
FunctionDefinitionAST *refFuncDef,
Symbol *funcReturn,
QList<QPair<QString, QString> > relevantDecls)
QList<QPair<QString, QString> > relevantDecls,
ExtractFunction::FunctionNameGetter functionNameGetter
= ExtractFunction::FunctionNameGetter())
: CppQuickFixOperation(interface)
, m_extractionStart(extractionStart)
, m_extractionEnd(extractionEnd)
, m_refFuncDef(refFuncDef)
, m_funcReturn(funcReturn)
, m_relevantDecls(relevantDecls)
, m_functionNameGetter(functionNameGetter)
{
setDescription(QCoreApplication::translate("QuickFix::ExtractFunction", "Extract Function"));
}
@@ -3135,7 +3138,7 @@ public:
CppRefactoringChanges refactoring(snapshot());
CppRefactoringFilePtr currentFile = refactoring.file(fileName());
const QString &funcName = getFunctionName();
const QString &funcName = m_functionNameGetter ? m_functionNameGetter() : getFunctionName();
if (funcName.isEmpty())
return;
@@ -3302,6 +3305,7 @@ public:
FunctionDefinitionAST *m_refFuncDef;
Symbol *m_funcReturn;
QList<QPair<QString, QString> > m_relevantDecls;
ExtractFunction::FunctionNameGetter m_functionNameGetter;
};
QPair<QString, QString> assembleDeclarationData(const QString &specifiers, DeclaratorAST *decltr,
@@ -3505,6 +3509,11 @@ public:
} // anonymous namespace
ExtractFunction::ExtractFunction(FunctionNameGetter functionNameGetter)
: m_functionNameGetter(functionNameGetter)
{
}
void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOperations &result)
{
CppRefactoringFilePtr file = interface.currentFile();
@@ -3632,7 +3641,8 @@ void ExtractFunction::match(const CppQuickFixInterface &interface, QuickFixOpera
analyser.m_extractionEnd,
refFuncDef,
funcReturn,
relevantDecls));
relevantDecls,
m_functionNameGetter));
}
namespace {

View File

@@ -34,11 +34,12 @@
#include "cppquickfix.h"
#include <cpptools/cpprefactoringchanges.h>
#include <extensionsystem/iplugin.h>
#include <QDialog>
#include <functional>
QT_BEGIN_NAMESPACE
class QByteArray;
template <class> class QList;
@@ -435,7 +436,13 @@ public:
class ExtractFunction : public CppQuickFixFactory
{
public:
typedef std::function<QString ()> FunctionNameGetter;
ExtractFunction(FunctionNameGetter functionNameGetter = FunctionNameGetter());
void match(const CppQuickFixInterface &interface, TextEditor::QuickFixOperations &result);
private:
FunctionNameGetter m_functionNameGetter; // For tests to avoid GUI pop-up.
};
/*!

View File

@@ -955,6 +955,11 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
"class Foo { void $" TEST_UNICODE_IDENTIFIER "(); };\n"
"void Foo::@" TEST_UNICODE_IDENTIFIER "() {}\n"
);
QTest::newRow("trailingReturnType") << _(
"struct $Foo {};\n"
"auto foo() -> @Foo {}\n"
);
}
void CppEditorPlugin::test_FollowSymbolUnderCursor()

View File

@@ -319,6 +319,7 @@ void CppToolsPlugin::test_completion()
QEXPECT_FAIL("enum_in_function_in_struct_in_function_anon", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_inline_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("pointer_partial_specialization", "QTCREATORBUG-14036", Abort);
QCOMPARE(actualCompletions, expectedCompletions);
}
@@ -2654,6 +2655,35 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("operator ->")
<< QLatin1String("t")
<< QLatin1String("iterator"));
QTest::newRow("pointer_partial_specialization") << _(
"template<typename T>\n"
"struct Traits { typedef typename T::pointer pointer; };\n"
"\n"
"template<typename _Tp>\n"
"struct Traits<_Tp*> { typedef _Tp *pointer; };\n"
"\n"
"template<typename T>\n"
"class Temp\n"
"{\n"
"protected:\n"
" typedef Traits<T> TraitsT;\n"
"\n"
"public:\n"
" typedef typename TraitsT::pointer pointer;\n"
" pointer p;\n"
"};\n"
"\n"
"struct Foo { int bar; };\n"
"\n"
"void func()\n"
"{\n"
" Temp<Foo *> t;\n"
" @\n"
"}\n"
) << _("t.p->") << (QStringList()
<< QLatin1String("Foo")
<< QLatin1String("bar"));
}
void CppToolsPlugin::test_completion_member_access_operator()

View File

@@ -347,7 +347,6 @@ void CdbEngine::init()
m_watchPointX = m_watchPointY = 0;
m_ignoreCdbOutput = false;
m_autoBreakPointCorrection = false;
m_watchInameToName.clear();
m_wow64State = wow64Uninitialized;
m_outputBuffer.clear();
@@ -986,14 +985,10 @@ void CdbEngine::updateWatchData(const WatchData &dataIn)
return;
// New watch item?
if (isWatchIName(dataIn.iname) && dataIn.isValueNeeded()) {
if (dataIn.isWatcher() && dataIn.isValueNeeded()) {
QByteArray args;
ByteArrayInputStream str(args);
str << dataIn.iname << " \"" << dataIn.exp << '"';
// Store the name since the CDB extension library
// does not maintain the names of watches.
if (!dataIn.name.isEmpty() && dataIn.name != QLatin1String(dataIn.exp))
m_watchInameToName.insert(dataIn.iname, dataIn.name);
postExtensionCommand("addwatch", args, 0,
[this, dataIn](const CdbResponse &r) { handleAddWatch(r, dataIn); });
return;
@@ -1866,40 +1861,25 @@ void CdbEngine::handleLocals(const CdbResponse &response, bool newFrame)
if (response.success) {
if (boolSetting(VerboseLog))
showMessage(QLatin1String("Locals: ") + QString::fromLatin1(response.extensionReply), LogDebug);
QList<WatchData> watchData;
WatchHandler *handler = watchHandler();
GdbMi all;
all.fromString(response.extensionReply);
QTC_ASSERT(all.type() == GdbMi::List, return);
QSet<QByteArray> toDelete;
if (newFrame) {
watchData.append(*handler->findData("local"));
watchData.append(*handler->findData("watch"));
foreach (WatchItem *item, handler->model()->treeLevelItems<WatchItem *>(2))
toDelete.insert(item->d.iname);
}
GdbMi root;
root.fromString(response.extensionReply);
QTC_ASSERT(root.type() == GdbMi::List, return);
if (debugLocals)
qDebug() << root.toString(true, 4);
// Courtesy of GDB engine
foreach (const GdbMi &child, root.children()) {
WatchData dummy;
dummy.iname = child["iname"].data();
dummy.name = QLatin1String(child["name"].data());
parseWatchData(dummy, child, &watchData);
}
// Fix the names of watch data.
for (int i =0; i < watchData.size(); ++i) {
if (watchData.at(i).iname.startsWith('w')) {
const QHash<QByteArray, QString>::const_iterator it
= m_watchInameToName.find(watchData.at(i).iname);
if (it != m_watchInameToName.constEnd())
watchData[i].name = it.value();
}
}
handler->insertDataList(watchData);
if (debugLocals) {
QDebug nsp = qDebug().nospace();
nsp << "Obtained " << watchData.size() << " items:\n";
foreach (const WatchData &wd, watchData)
nsp << wd.toString() <<'\n';
foreach (const GdbMi &child, all.children()) {
WatchItem *item = new WatchItem(child);
handler->insertItem(item);
toDelete.remove(item->d.iname);
}
handler->purgeOutdatedItems(toDelete);
if (newFrame) {
emit stackFrameCompleted();
DebuggerToolTipManager::updateEngine(this);

View File

@@ -293,7 +293,6 @@ private:
bool m_autoBreakPointCorrection;
QHash<QString, QString> m_fileNameModuleHash;
QMultiHash<QString, quint64> m_symbolAddressCache;
QHash<QByteArray, QString> m_watchInameToName;
bool m_ignoreCdbOutput;
QVariantList m_customSpecialStopData;
QList<SourcePathMapping> m_sourcePathMappings;

View File

@@ -69,14 +69,11 @@ namespace Internal {
// -----------------------------------------------------------------------
DebuggerKitConfigWidget::DebuggerKitConfigWidget(Kit *workingCopy, const KitInformation *ki)
: KitConfigWidget(workingCopy, ki)
: KitConfigWidget(workingCopy, ki),
m_ignoreChanges(false)
{
m_comboBox = new QComboBox;
m_comboBox->setEnabled(true);
m_comboBox->setToolTip(toolTip());
m_comboBox->addItem(tr("None"), QString());
foreach (const DebuggerItem &item, DebuggerItemManager::debuggers())
m_comboBox->addItem(item.displayName(), item.id());
refresh();
connect(m_comboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
@@ -112,8 +109,16 @@ void DebuggerKitConfigWidget::makeReadOnly()
void DebuggerKitConfigWidget::refresh()
{
m_ignoreChanges = true;
m_comboBox->clear();
m_comboBox->setToolTip(toolTip());
m_comboBox->addItem(tr("None"), QString());
foreach (const DebuggerItem &item, DebuggerItemManager::debuggers())
m_comboBox->addItem(item.displayName(), item.id());
const DebuggerItem *item = DebuggerKitInformation::debugger(m_kit);
updateComboBox(item ? item->id() : QVariant());
m_ignoreChanges = false;
}
QWidget *DebuggerKitConfigWidget::buttonWidget() const
@@ -134,6 +139,9 @@ void DebuggerKitConfigWidget::manageDebuggers()
void DebuggerKitConfigWidget::currentDebuggerChanged(int)
{
if (m_ignoreChanges)
return;
int currentIndex = m_comboBox->currentIndex();
QVariant id = m_comboBox->itemData(currentIndex);
m_kit->setValue(DebuggerKitInformation::id(), id);

View File

@@ -79,6 +79,7 @@ private:
void updateComboBox(const QVariant &id);
bool m_isReadOnly;
bool m_ignoreChanges;
QComboBox *m_comboBox;
QPushButton *m_manageButton;
};

View File

@@ -76,10 +76,11 @@ DiffEditorDocument::~DiffEditorDocument()
*/
void DiffEditorDocument::setController(DiffEditorController *controller)
{
QTC_ASSERT(isTemporary(), return);
if (m_controller == controller)
return;
QTC_ASSERT(isTemporary(), return);
if (m_controller)
m_controller->deleteLater();
m_controller = controller;

View File

@@ -126,31 +126,19 @@ void SysRootInformationConfigWidget::pathWasChanged()
// --------------------------------------------------------------------------
ToolChainInformationConfigWidget::ToolChainInformationConfigWidget(Kit *k, const KitInformation *ki) :
KitConfigWidget(k, ki)
KitConfigWidget(k, ki),
m_ignoreChanges(false)
{
m_comboBox = new QComboBox;
m_comboBox->setEnabled(false);
m_comboBox->setToolTip(toolTip());
foreach (ToolChain *tc, ToolChainManager::toolChains())
toolChainAdded(tc);
updateComboBox();
refresh();
connect(m_comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(currentToolChainChanged(int)));
m_manageButton = new QPushButton(KitConfigWidget::msgManage());
m_manageButton->setContentsMargins(0, 0, 0, 0);
connect(m_manageButton, SIGNAL(clicked()), this, SLOT(manageToolChains()));
QObject *tcm = ToolChainManager::instance();
connect(tcm, SIGNAL(toolChainAdded(ProjectExplorer::ToolChain*)),
this, SLOT(toolChainAdded(ProjectExplorer::ToolChain*)));
connect(tcm, SIGNAL(toolChainRemoved(ProjectExplorer::ToolChain*)),
this, SLOT(toolChainRemoved(ProjectExplorer::ToolChain*)));
connect(tcm, SIGNAL(toolChainUpdated(ProjectExplorer::ToolChain*)),
this, SLOT(toolChainUpdated(ProjectExplorer::ToolChain*)));
}
ToolChainInformationConfigWidget::~ToolChainInformationConfigWidget()
@@ -173,7 +161,13 @@ QString ToolChainInformationConfigWidget::toolTip() const
void ToolChainInformationConfigWidget::refresh()
{
m_ignoreChanges = true;
m_comboBox->clear();
foreach (ToolChain *tc, ToolChainManager::toolChains())
m_comboBox->addItem(tc->displayName(), tc->id());
m_comboBox->setCurrentIndex(indexOf(ToolChainKitInformation::toolChain(m_kit)));
m_ignoreChanges = false;
}
void ToolChainInformationConfigWidget::makeReadOnly()
@@ -191,28 +185,6 @@ QWidget *ToolChainInformationConfigWidget::buttonWidget() const
return m_manageButton;
}
void ToolChainInformationConfigWidget::toolChainAdded(ToolChain *tc)
{
m_comboBox->addItem(tc->displayName(), tc->id());
updateComboBox();
}
void ToolChainInformationConfigWidget::toolChainRemoved(ToolChain *tc)
{
const int pos = indexOf(tc);
if (pos < 0)
return;
m_comboBox->removeItem(pos);
updateComboBox();
}
void ToolChainInformationConfigWidget::toolChainUpdated(ToolChain *tc)
{
const int pos = indexOf(tc);
if (pos < 0)
return;
m_comboBox->setItemText(pos, tc->displayName());
}
void ToolChainInformationConfigWidget::manageToolChains()
{
ICore::showOptionsDialog(Constants::TOOLCHAIN_SETTINGS_PAGE_ID, buttonWidget());
@@ -220,6 +192,9 @@ void ToolChainInformationConfigWidget::manageToolChains()
void ToolChainInformationConfigWidget::currentToolChainChanged(int idx)
{
if (m_ignoreChanges)
return;
const QString id = m_comboBox->itemData(idx).toString();
ToolChainKitInformation::setToolChain(m_kit, ToolChainManager::findToolChain(id));
}

View File

@@ -100,9 +100,6 @@ public:
QString toolTip() const;
private slots:
void toolChainAdded(ProjectExplorer::ToolChain *tc);
void toolChainRemoved(ProjectExplorer::ToolChain *tc);
void toolChainUpdated(ProjectExplorer::ToolChain *tc);
void manageToolChains();
void currentToolChainChanged(int idx);
@@ -112,6 +109,7 @@ private:
QComboBox *m_comboBox;
QPushButton *m_manageButton;
bool m_ignoreChanges;
};
// --------------------------------------------------------------------------

View File

@@ -366,6 +366,13 @@ void KitManagerConfigWidget::kitWasUpdated(Kit *k)
updateVisibility();
}
void KitManagerConfigWidget::showEvent(QShowEvent *event)
{
Q_UNUSED(event);
foreach (KitConfigWidget *widget, m_widgets)
widget->refresh();
}
QLabel *KitManagerConfigWidget::createLabel(const QString &name, const QString &toolTip)
{
QLabel *label = new QLabel(name);

View File

@@ -93,6 +93,7 @@ private:
ButtonColumn
};
void showEvent(QShowEvent *event);
QLabel *createLabel(const QString &name, const QString &toolTip);
void paintEvent(QPaintEvent *ev);

View File

@@ -42,6 +42,7 @@
#include <QFileInfo>
#include <QFont>
#include <QMimeData>
#include <QLoggingCategory>
namespace ProjectExplorer {
@@ -241,27 +242,9 @@ QModelIndex FlatModel::parent(const QModelIndex &idx) const
QModelIndex parentIndex;
if (Node *node = nodeForIndex(idx)) {
FolderNode *parentNode = visibleFolderNode(node->parentFolderNode());
if (parentNode) {
FolderNode *grandParentNode = visibleFolderNode(parentNode->parentFolderNode());
if (grandParentNode) {
QHash<FolderNode*, QList<Node*> >::const_iterator it = m_childNodes.constFind(grandParentNode);
if (it == m_childNodes.constEnd()) {
fetchMore(grandParentNode);
it = m_childNodes.constFind(grandParentNode);
}
Q_ASSERT(it != m_childNodes.constEnd());
const int row = it.value().indexOf(parentNode);
Q_ASSERT(row >= 0);
parentIndex = createIndex(row, 0, parentNode);
} else {
// top level node, parent is session
parentIndex = index(0, 0, QModelIndex());
}
}
if (parentNode)
return indexForNode(parentNode);
}
// qDebug() << "parent of " << idx.data(Project::FilePathRole) << " is " << parentIndex.data(Project::FilePathRole);
return parentIndex;
}
@@ -444,6 +427,7 @@ void FlatModel::recursiveAddFileNodes(FolderNode *startNode, QList<Node *> *list
QList<Node*> FlatModel::childNodes(FolderNode *parentNode, const QSet<Node*> &blackList) const
{
qCDebug(logger()) << "FlatModel::childNodes for " << parentNode->displayName();
QList<Node*> nodeList;
if (parentNode->nodeType() == SessionNodeType) {
@@ -458,6 +442,7 @@ QList<Node*> FlatModel::childNodes(FolderNode *parentNode, const QSet<Node*> &bl
recursiveAddFileNodes(parentNode, &nodeList, blackList + nodeList.toSet());
}
Utils::sort(nodeList, sortNodes);
qCDebug(logger()) << " found" << nodeList.size() << "nodes";
return nodeList;
}
@@ -519,7 +504,7 @@ QMimeData *FlatModel::mimeData(const QModelIndexList &indexes) const
return data;
}
QModelIndex FlatModel::indexForNode(const Node *node_)
QModelIndex FlatModel::indexForNode(const Node *node_) const
{
// We assume that we are only called for nodes that are represented
@@ -610,6 +595,12 @@ bool FlatModel::filter(Node *node) const
return isHidden;
}
const QLoggingCategory &FlatModel::logger()
{
static QLoggingCategory logger("qtc.projectexplorer.flatmodel");
return logger;
}
bool isSorted(const QList<Node *> &nodes)
{
int size = nodes.size();
@@ -623,11 +614,21 @@ bool isSorted(const QList<Node *> &nodes)
/// slots and all the fun
void FlatModel::added(FolderNode* parentNode, const QList<Node*> &newNodeList)
{
qCDebug(logger()) << "FlatModel::added" << parentNode->path() << newNodeList.size() << "nodes";
QModelIndex parentIndex = indexForNode(parentNode);
// Old list
QHash<FolderNode*, QList<Node*> >::const_iterator it = m_childNodes.constFind(parentNode);
if (it == m_childNodes.constEnd())
if (it == m_childNodes.constEnd()) {
if (!parentIndex.isValid()) {
qCDebug(logger()) << " parent not mapped returning";
return;
}
qCDebug(logger()) << " updated m_childNodes";
beginInsertRows(parentIndex, 0, newNodeList.size() - 1);
m_childNodes.insert(parentNode, newNodeList);
endInsertRows();
return;
}
QList<Node *> oldNodeList = it.value();
// Compare lists and emit signals, and modify m_childNodes on the fly
@@ -658,6 +659,7 @@ void FlatModel::added(FolderNode* parentNode, const QList<Node*> &newNodeList)
beginInsertRows(parentIndex, 0, newNodeList.size() - 1);
m_childNodes.insert(parentNode, newNodeList);
endInsertRows();
qCDebug(logger()) << " updated m_childNodes";
return;
}
@@ -705,15 +707,19 @@ void FlatModel::added(FolderNode* parentNode, const QList<Node*> &newNodeList)
endInsertRows();
oldIter = oldNodeList.constBegin() + pos;
}
qCDebug(logger()) << " updated m_childNodes";
}
void FlatModel::removed(FolderNode* parentNode, const QList<Node*> &newNodeList)
{
qCDebug(logger()) << "FlatModel::removed" << parentNode->path() << newNodeList.size() << "nodes";
QModelIndex parentIndex = indexForNode(parentNode);
// Old list
QHash<FolderNode*, QList<Node*> >::const_iterator it = m_childNodes.constFind(parentNode);
if (it == m_childNodes.constEnd())
if (it == m_childNodes.constEnd()) {
qCDebug(logger()) << " unmapped node";
return;
}
QList<Node *> oldNodeList = it.value();
// Compare lists and emit signals, and modify m_childNodes on the fly
@@ -743,6 +749,7 @@ void FlatModel::removed(FolderNode* parentNode, const QList<Node*> &newNodeList)
beginRemoveRows(parentIndex, 0, oldNodeList.size() - 1);
m_childNodes.insert(parentNode, newNodeList);
endRemoveRows();
qCDebug(logger()) << " updated m_childNodes";
return;
}
@@ -789,6 +796,7 @@ void FlatModel::removed(FolderNode* parentNode, const QList<Node*> &newNodeList)
endRemoveRows();
oldIter = oldNodeList.constBegin() + pos;
}
qCDebug(logger()) << " updated m_childNodes";
}
void FlatModel::aboutToShowInSimpleTreeChanged(FolderNode* node)
@@ -818,6 +826,7 @@ void FlatModel::showInSimpleTreeChanged(FolderNode *node)
void FlatModel::foldersAboutToBeAdded(FolderNode *parentFolder, const QList<FolderNode*> &newFolders)
{
qCDebug(logger()) << "FlatModel::foldersAboutToBeAdded";
Q_UNUSED(newFolders)
m_parentFolderForChange = parentFolder;
}
@@ -886,6 +895,7 @@ void FlatModel::foldersRemoved()
void FlatModel::filesAboutToBeAdded(FolderNode *folder, const QList<FileNode*> &newFiles)
{
qCDebug(logger()) << "FlatModel::filesAboutToBeAdded";
Q_UNUSED(newFiles)
m_parentFolderForChange = folder;
}

View File

@@ -75,7 +75,7 @@ public:
void setStartupProject(ProjectNode *projectNode);
Node *nodeForIndex(const QModelIndex &index) const;
QModelIndex indexForNode(const Node *node);
QModelIndex indexForNode(const Node *node) const;
bool projectFilterEnabled();
bool generatedFilesFilterEnabled();
@@ -133,6 +133,8 @@ private:
FolderNode *m_parentFolderForChange;
Node *m_nodeForSortKeyChange;
static const QLoggingCategory &logger();
friend class FlatModelManager;
};

View File

@@ -178,7 +178,8 @@ bool SessionManager::isDefaultSession(const QString &session)
void SessionManager::saveActiveMode(IMode *mode)
{
setValue(QLatin1String("ActiveMode"), mode->id().toString());
if (mode->id() != Id(Core::Constants::MODE_WELCOME))
setValue(QLatin1String("ActiveMode"), mode->id().toString());
}
void SessionManager::clearProjectFileCache()

View File

@@ -630,7 +630,8 @@ int QmakeBuildConfigurationFactory::priority(const Kit *k, const QString &projec
QList<BuildInfo *> QmakeBuildConfigurationFactory::availableSetups(const Kit *k, const QString &projectPath) const
{
QList<ProjectExplorer::BuildInfo *> result;
if (!QtSupport::QtKitInformation::qtVersion(k))
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k);
if (!qtVersion || !qtVersion->isValid())
return result;
result << createBuildInfo(k, projectPath, ProjectExplorer::BuildConfiguration::Debug);
result << createBuildInfo(k, projectPath, ProjectExplorer::BuildConfiguration::Release);

View File

@@ -42,9 +42,10 @@
#include <coreplugin/find/ifindsupport.h>
#include <texteditor/texteditor.h>
#include <texteditor/refactoringchanges.h>
#include <utils/stylehelper.h>
#include <utils/qtcassert.h>
#include <utils/fadingindicator.h>
#include <utils/filesearch.h>
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>
#include <QDebug>
#include <QSettings>
@@ -208,6 +209,9 @@ void BaseFileFind::doReplace(const QString &text,
{
QStringList files = replaceAll(text, items, preserveCase);
if (!files.isEmpty()) {
Utils::FadingIndicator::showText(ICore::mainWindow(),
tr("%1 occurrences replaced.").arg(items.size()),
Utils::FadingIndicator::SmallText);
DocumentManager::notifyFilesChangedInternally(files);
SearchResultWindow::instance()->hide();
}

View File

@@ -44,7 +44,6 @@
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h>
#include <projectexplorer/toolchain.h>
#include <utils/qtcassert.h>
@@ -82,9 +81,6 @@ bool MemcheckRunControl::startEngine()
{
m_runner.setParser(&m_parser);
// Clear about-to-be-outdated tasks.
TaskHub::clearTasks(Analyzer::Constants::ANALYZERTASK_ID);
appendMessage(tr("Analyzing memory of %1").arg(executable()) + QLatin1Char('\n'),
Utils::NormalMessageFormat);
return ValgrindRunControl::startEngine();

View File

@@ -194,6 +194,8 @@ private slots:
void test_checksymbols_infiniteLoop_data();
void test_checksymbols_infiniteLoop();
void test_parentOfBlock();
};
void tst_CheckSymbols::test_checksymbols()
@@ -1774,6 +1776,19 @@ void tst_CheckSymbols::test_checksymbols_infiniteLoop()
TestCase::runCheckSymbols(document1, snapshot);
}
void tst_CheckSymbols::test_parentOfBlock()
{
const QByteArray source = "void C::f()\n"
"{\n"
" enum E { e1 };\n"
"}\n";
const Document::Ptr document = TestCase::createDocument(QLatin1String("file1.cpp"), source);
Snapshot snapshot;
snapshot.insert(document);
TestCase::runCheckSymbols(document, snapshot);
}
void tst_CheckSymbols::test_checksymbols_infiniteLoop_data()
{
QTest::addColumn<QByteArray>("source1");

View File

@@ -69,6 +69,24 @@ void saveData(const QByteArray &data, const QString &fileName)
inf.close();
}
static QByteArray stringify(QByteArray code)
{
QByteArray res = code.replace('"', "\\\"").replace("\n", "\\n\"\n\"");
if (res.endsWith("\"\n\""))
res.chop(3);
return res;
}
static bool compare(const QByteArray &actual, const QByteArray &expected)
{
if (actual == expected)
return true;
qDebug() << "Compared strings are not the same\n"
" Actual:\n" << stringify(actual)
<< " Expected:\n" << stringify(expected);
return false;
}
struct Include
{
Include(const QString &fileName, Client::IncludeType type, unsigned line)
@@ -344,7 +362,7 @@ protected:
client.sourceNeeded("data/" + fileName, nolines);
return output;
}
static QString simplified(QByteArray buf);
static QByteArray simplified(const QByteArray &buf);
private:
void compare_input_output(bool keepComments = false);
@@ -396,7 +414,7 @@ private slots:
// Remove all #... lines, and 'simplify' string, to allow easily comparing the result
// Also, remove all unneeded spaces: keep only to ensure identifiers are separated.
// NOTE: may not correctly handle underscore in identifiers
QString tst_Preprocessor::simplified(QByteArray buf)
QByteArray tst_Preprocessor::simplified(const QByteArray &buf)
{
QString out;
QList<QByteArray> lines = buf.split('\n');
@@ -417,7 +435,7 @@ QString tst_Preprocessor::simplified(QByteArray buf)
i++;
}
return out;
return out.toUtf8();
}
void tst_Preprocessor::va_args()
@@ -435,7 +453,7 @@ void tst_Preprocessor::va_args()
preprocessed = preprocessed.simplified();
// DUMP_OUTPUT(preprocessed);
QCOMPARE(simplified(preprocessed), QString("int f();int f(int a);int f(int a,int b);"));
QVERIFY(compare(simplified(preprocessed), "int f();int f(int a);int f(int a,int b);"));
}
void tst_Preprocessor::named_va_args()
@@ -452,7 +470,7 @@ void tst_Preprocessor::named_va_args()
true, false);
preprocessed = preprocessed.simplified();
QCOMPARE(simplified(preprocessed), QString("int f();int f(int a);int f(int a,int b);"));
QVERIFY(compare(simplified(preprocessed), "int f();int f(int a);int f(int a,int b);"));
}
void tst_Preprocessor::extra_va_args()
@@ -469,7 +487,7 @@ void tst_Preprocessor::extra_va_args()
true, false);
preprocessed = preprocessed.simplified();
QCOMPARE(simplified(preprocessed), QString("int f();float f(int b);long f(int b,int c);"));
QVERIFY(compare(simplified(preprocessed), "int f();float f(int b);long f(int b,int c);"));
}
void tst_Preprocessor::empty_macro_args()
@@ -489,8 +507,7 @@ void tst_Preprocessor::empty_macro_args()
preprocessed = preprocessed.simplified();
// DUMP_OUTPUT(preprocessed);
QCOMPARE(simplified(preprocessed),
QString("const int cVal;int Val;int Val2;int;int;"));
QVERIFY(compare(simplified(preprocessed), "const int cVal;int Val;int Val2;int;int;"));
}
void tst_Preprocessor::macro_args_count()
@@ -626,7 +643,7 @@ void tst_Preprocessor::macro_uses()
Preprocessor preprocess(&client, &env);
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"), buffer);
QCOMPARE(simplified(preprocessed), QString("void test(){int x=8;int y=9;}"));
QVERIFY(compare(simplified(preprocessed), "void test(){int x=8;int y=9;}"));
QCOMPARE(client.expandedMacros(), QList<QByteArray>() << QByteArray("FOO") << QByteArray("BAR"));
QCOMPARE(client.expandedMacrosOffset(), QList<unsigned>() << buffer.indexOf("FOO;") << buffer.indexOf("BAR;"));
QCOMPARE(client.definedMacros(), QList<QByteArray>() << QByteArray("FOO") << QByteArray("BAR"));
@@ -801,7 +818,7 @@ void tst_Preprocessor::unfinished_function_like_macro_call()
"# 4 \"<stdin>\"\n");
// DUMP_OUTPUT(preprocessed);
QCOMPARE(preprocessed, expected__);
QVERIFY(compare(preprocessed, expected__));
}
void tst_Preprocessor::nasty_macro_expansion()
@@ -881,7 +898,7 @@ void tst_Preprocessor::glib_attribute()
"}\n";
// DUMP_OUTPUT(preprocessed);
QCOMPARE(preprocessed, result____);
QVERIFY(compare(preprocessed, result____));
}
void tst_Preprocessor::builtin__FILE__()
@@ -898,7 +915,7 @@ void tst_Preprocessor::builtin__FILE__()
"# 1 \"some-file.c\"\n"
"const char *f = \"some-file.c\"\n";
QCOMPARE(preprocessed, result____);
QVERIFY(compare(preprocessed, result____));
}
void tst_Preprocessor::comparisons_data()
@@ -957,15 +974,12 @@ void tst_Preprocessor::comparisons()
// These weird underscores are here to make the name as long as
// "preprocessed", so the QCOMPARE error messages are nicely aligned.
QByteArray output____ = loadSource("data/" + outfile);
// QCOMPARE(preprocessed, output____);
QCOMPARE(QString::fromUtf8(preprocessed.constData()),
QString::fromUtf8(output____.constData()));
QVERIFY(compare(preprocessed, output____));
}
if (!errorfile.isEmpty()) {
QByteArray errorFileContents = loadSource("data/" + errorfile);
QCOMPARE(QString::fromUtf8(errors.constData()),
QString::fromUtf8(errorFileContents.constData()));
QVERIFY(compare(errors, errorFileContents));
}
}
@@ -1252,10 +1266,10 @@ void tst_Preprocessor::comments_within()
Preprocessor preprocess(0, &env);
preprocess.setKeepComments(false);
QByteArray prep = preprocess.run(QLatin1String("<stdin>"), input);
QCOMPARE(prep.constData(), without_comments.constData());
QVERIFY(compare(prep, without_comments));
preprocess.setKeepComments(true);
prep = preprocess.run(QLatin1String("<stdin>"), input);
QCOMPARE(prep.constData(), with_comments.constData());
QVERIFY(compare(prep, with_comments));
}
void tst_Preprocessor::comments_within_data()
@@ -1617,6 +1631,123 @@ void tst_Preprocessor::comments_within_data()
"# 12 \"<stdin>\"\n"
"int foo = 4;"
);
QTest::newRow("inside_function_like_macro") << _(
"#define /* comment */ ASSIGN1(VAR, VALUE) VAR = VALUE\n"
"#define ASSIGN2(/* comment */ VAR, VALUE) VAR = VALUE\n"
"#define ASSIGN3(VAR /* comment */, VALUE) VAR = VALUE\n"
"#define ASSIGN4(VAR, /* comment */ VALUE) VAR = VALUE\n"
"#define ASSIGN5(VAR, VALUE /* comment */) VAR = VALUE\n"
"#define ASSIGN6(VAR, VALUE) /* comment */ VAR = VALUE\n"
"#define ASSIGN7(VAR, ... /* comment */) VAR\n"
"void func()\n"
"{\n"
" int i;\n"
" ASSIGN1(i, 3);\n"
" ASSIGN2(i, 3);\n"
" ASSIGN3(i, 3);\n"
" ASSIGN4(i, 3);\n"
" ASSIGN5(i, 3);\n"
" ASSIGN6(i, 3);\n"
" ASSIGN7(i, 3);\n"
"}\n"
) << _(
"# 1 \"<stdin>\"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"\n"
"void func()\n"
"{\n"
" int i;\n"
"# expansion begin 397,7 11:12 ~1 11:15\n"
"i = 3\n"
"# expansion end\n"
"# 11 \"<stdin>\"\n"
" ;\n"
"# expansion begin 416,7 12:12 ~1 12:15\n"
"i = 3\n"
"# expansion end\n"
"# 12 \"<stdin>\"\n"
" ;\n"
"# expansion begin 435,7 13:12 ~1 13:15\n"
"i = 3\n"
"# expansion end\n"
"# 13 \"<stdin>\"\n"
" ;\n"
"# expansion begin 454,7 14:12 ~1 14:15\n"
"i = 3\n"
"# expansion end\n"
"# 14 \"<stdin>\"\n"
" ;\n"
"# expansion begin 473,7 15:12 ~1 15:15\n"
"i = 3\n"
"# expansion end\n"
"# 15 \"<stdin>\"\n"
" ;\n"
"# expansion begin 492,7 16:12 ~1 16:15\n"
"i = 3\n"
"# expansion end\n"
"# 16 \"<stdin>\"\n"
" ;\n"
"# expansion begin 511,7 17:12\n"
"i\n"
"# expansion end\n"
"# 17 \"<stdin>\"\n"
" ;\n"
"}\n"
) << _(
"# 1 \"<stdin>\"\n"
" /* comment */\n"
" /* comment */\n"
" /* comment */\n"
" /* comment */\n"
" /* comment */\n"
" /* comment */\n"
" /* comment */\n"
"void func()\n"
"{\n"
" int i;\n"
"# expansion begin 397,7 11:12 ~1 11:15\n"
"i = 3\n"
"# expansion end\n"
"# 11 \"<stdin>\"\n"
" ;\n"
"# expansion begin 416,7 12:12 ~1 12:15\n"
"i = 3\n"
"# expansion end\n"
"# 12 \"<stdin>\"\n"
" ;\n"
"# expansion begin 435,7 13:12 ~1 13:15\n"
"i = 3\n"
"# expansion end\n"
"# 13 \"<stdin>\"\n"
" ;\n"
"# expansion begin 454,7 14:12 ~1 14:15\n"
"i = 3\n"
"# expansion end\n"
"# 14 \"<stdin>\"\n"
" ;\n"
"# expansion begin 473,7 15:12 ~1 15:15\n"
"i = 3\n"
"# expansion end\n"
"# 15 \"<stdin>\"\n"
" ;\n"
"# expansion begin 492,7 16:12 ~1 16:15\n"
"i = 3\n"
"# expansion end\n"
"# 16 \"<stdin>\"\n"
" ;\n"
"# expansion begin 511,7 17:12\n"
"i\n"
"# expansion end\n"
"# 17 \"<stdin>\"\n"
" ;\n"
"}\n"
);
}
void tst_Preprocessor::comments_before_args()
@@ -1627,18 +1758,32 @@ void tst_Preprocessor::comments_before_args()
Preprocessor preprocess(client, &env);
preprocess.setKeepComments(true);
QByteArray preprocessed = preprocess.run(QLatin1String("<stdin>"),
"\n#define foo(a,b) int a = b;"
"\nfoo/*C comment*/(a,1)\n"
"\nfoo/**Doxygen comment*/(b,2)\n"
"\nfoo//C++ comment\n(c,3)\n"
"\nfoo///Doxygen C++ comment\n(d,4)\n"
"\nfoo/*multiple*///comments\n/**as well*/(e,5)\n",
"#define foo(a,b) int a = b;\n"
"foo/*C comment*/(a,1)\n"
"foo/**Doxygen comment*/(b,2)\n"
"foo//C++ comment\n"
"(c,3)\n"
"foo///Doxygen C++ comment\n"
"(d,4)\n"
"foo/*multiple*///comments\n"
"/**as well*/(e,5)\n",
true, false);
preprocessed = preprocessed.simplified();
// DUMP_OUTPUT(preprocessed);
QCOMPARE(simplified(preprocessed),
QString("int a=1;int b=2;int c=3;int d=4;int e=5;"));
QByteArray expected =
"\n"
" /*C comment*/int a = 1;\n"
" /**Doxygen comment*/int b = 2;\n"
" //C++ comment\n"
"int\n"
"c = 3;\n"
" ///Doxygen C++ comment\n"
"int\n"
"d = 4;\n"
" /*multiple*/ //comments\n"
"/**as well*/ int\n"
"e = 5;\n";
QVERIFY(compare(preprocessed, expected));
}
void tst_Preprocessor::multiline_strings()
@@ -1899,7 +2044,7 @@ void tst_Preprocessor::concat()
"# 5 \"<stdin>\"\n"
" ;\n"
);
QCOMPARE(prep.constData(), output.constData());
QVERIFY(compare(prep, output));
}
void tst_Preprocessor::excessive_nesting()
@@ -1928,7 +2073,7 @@ void tst_Preprocessor::compare_input_output(bool keepComments)
Preprocessor preprocess(0, &env);
preprocess.setKeepComments(keepComments);
QByteArray prep = preprocess.run(QLatin1String("<stdin>"), input);
QCOMPARE(prep.constData(), output.constData());
QVERIFY(compare(prep, output));
}
QTEST_APPLESS_MAIN(tst_Preprocessor)

View File

@@ -3,8 +3,4 @@ include(../../qttest.pri)
DEFINES -= QT_USE_FAST_OPERATOR_PLUS QT_USE_FAST_CONCATENATION
SOURCES += tst_stringutils.cpp \
# $$UTILS_PATH/stringutils.cpp
#HEADERS += $$UTILS_PATH/stringutils.h \
# $$UTILS_PATH/utils_global.h
SOURCES += tst_stringutils.cpp

View File

@@ -3,4 +3,4 @@ include(../../qttest.pri)
SOURCES += tst_treemodel.cpp
HEADERS += $$UTILS_PATH/treemodel.h
HEADERS += $$IDE_SOURCE_TREE/src/libs/utils/treemodel.h

View File

@@ -88,7 +88,7 @@ def main():
if current != models[0]:
selectCodeModel(current)
test.log("Testing code model: %s" % current)
openDocument("untitled.Sources.main\\.cpp")
openDocument("%s.Sources.main\\.cpp" % projectName)
editor = getEditorForFileSuffix("main.cpp")
if not editor:
test.fatal("Failed to get an editor - leaving test.")