summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@theqtcompany.com>2016-01-28 16:39:05 +0100
committerMarco Bubke <marco.bubke@theqtcompany.com>2016-02-01 14:38:31 +0000
commitecca26929214742014674f4982d2120d0e36c2dc (patch)
tree7260fd62f7df2684293290e531560307eb4b6102
parentbb3b7307ef0bc1f70b3db823829a0569f49c2cda (diff)
downloadqt-creator-ecca26929214742014674f4982d2120d0e36c2dc.tar.gz
Clang: Add ClangPreprocessorAssistProposalItem
Change-Id: Ifb27b9a21b9a2fe9a04496bbb70fa3fa07d1f89c Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
-rw-r--r--src/plugins/clangcodemodel/clangassistproposalitem.cpp67
-rw-r--r--src/plugins/clangcodemodel/clangassistproposalitem.h6
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.pro2
-rw-r--r--src/plugins/clangcodemodel/clangcodemodel.qbs2
-rw-r--r--src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp15
-rw-r--r--src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp169
-rw-r--r--src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h72
-rw-r--r--src/plugins/texteditor/codeassist/assistproposaliteminterface.h2
8 files changed, 286 insertions, 49 deletions
diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.cpp b/src/plugins/clangcodemodel/clangassistproposalitem.cpp
index e8a8e97979..57b38c8e9a 100644
--- a/src/plugins/clangcodemodel/clangassistproposalitem.cpp
+++ b/src/plugins/clangcodemodel/clangassistproposalitem.cpp
@@ -42,21 +42,21 @@ using namespace ClangBackEnd;
namespace ClangCodeModel {
namespace Internal {
-bool ClangAssistProposalItem::prematurelyApplies(const QChar &typedChar) const
+bool ClangAssistProposalItem::prematurelyApplies(const QChar &typedCharacter) const
{
bool applies = false;
if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT)
- applies = QString::fromLatin1("(,").contains(typedChar);
+ applies = QString::fromLatin1("(,").contains(typedCharacter);
else if (m_completionOperator == T_STRING_LITERAL || m_completionOperator == T_ANGLE_STRING_LITERAL)
- applies = (typedChar == QLatin1Char('/')) && text().endsWith(QLatin1Char('/'));
+ applies = (typedCharacter == QLatin1Char('/')) && text().endsWith(QLatin1Char('/'));
else if (codeCompletion().completionKind() == CodeCompletion::ObjCMessageCompletionKind)
- applies = QString::fromLatin1(";.,").contains(typedChar);
+ applies = QString::fromLatin1(";.,").contains(typedCharacter);
else
- applies = QString::fromLatin1(";.,:(").contains(typedChar);
+ applies = QString::fromLatin1(";.,:(").contains(typedCharacter);
if (applies)
- m_typedChar = typedChar;
+ m_typedCharacter = typedCharacter;
return applies;
}
@@ -87,23 +87,16 @@ void ClangAssistProposalItem::apply(TextEditor::TextEditorWidget *editorWidget,
const CodeCompletion ccr = codeCompletion();
QString textToBeInserted = text();
- QString extraChars;
+ QString extraCharacters;
int extraLength = 0;
int cursorOffset = 0;
bool autoParenthesesEnabled = true;
if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) {
- extraChars += QLatin1Char(')');
- if (m_typedChar == QLatin1Char('(')) // Eat the opening parenthesis
- m_typedChar = QChar();
- } else if (m_completionOperator == T_STRING_LITERAL || m_completionOperator == T_ANGLE_STRING_LITERAL) {
- if (!textToBeInserted.endsWith(QLatin1Char('/'))) {
- extraChars += QLatin1Char((m_completionOperator == T_ANGLE_STRING_LITERAL) ? '>' : '"');
- } else {
- if (m_typedChar == QLatin1Char('/')) // Eat the slash
- m_typedChar = QChar();
- }
- } else if (ccr.completionKind() == CodeCompletion::KeywordCompletionKind) {
+ extraCharacters += QLatin1Char(')');
+ if (m_typedCharacter == QLatin1Char('(')) // Eat the opening parenthesis
+ m_typedCharacter = QChar();
+ } else if (ccr.completionKind() == CodeCompletion::KeywordCompletionKind) {
CompletionChunksToTextConverter converter;
converter.setupForKeywords();
@@ -131,42 +124,42 @@ void ClangAssistProposalItem::apply(TextEditor::TextEditorWidget *editorWidget,
// When the user typed the opening parenthesis, he'll likely also type the closing one,
// in which case it would be annoying if we put the cursor after the already automatically
// inserted closing parenthesis.
- const bool skipClosingParenthesis = m_typedChar != QLatin1Char('(');
+ const bool skipClosingParenthesis = m_typedCharacter != QLatin1Char('(');
if (completionSettings.m_spaceAfterFunctionName)
- extraChars += QLatin1Char(' ');
- extraChars += QLatin1Char('(');
- if (m_typedChar == QLatin1Char('('))
- m_typedChar = QChar();
+ extraCharacters += QLatin1Char(' ');
+ extraCharacters += QLatin1Char('(');
+ if (m_typedCharacter == QLatin1Char('('))
+ m_typedCharacter = QChar();
// If the function doesn't return anything, automatically place the semicolon,
// unless we're doing a scope completion (then it might be function definition).
const QChar characterAtCursor = editorWidget->characterAt(editorWidget->position());
- bool endWithSemicolon = m_typedChar == QLatin1Char(';')/*
+ bool endWithSemicolon = m_typedCharacter == QLatin1Char(';')/*
|| (function->returnType()->isVoidType() && m_completionOperator != T_COLON_COLON)*/; //###
- const QChar semicolon = m_typedChar.isNull() ? QLatin1Char(';') : m_typedChar;
+ const QChar semicolon = m_typedCharacter.isNull() ? QLatin1Char(';') : m_typedCharacter;
if (endWithSemicolon && characterAtCursor == semicolon) {
endWithSemicolon = false;
- m_typedChar = QChar();
+ m_typedCharacter = QChar();
}
// If the function takes no arguments, automatically place the closing parenthesis
if (!isOverloaded() && !ccr.hasParameters() && skipClosingParenthesis) {
- extraChars += QLatin1Char(')');
+ extraCharacters += QLatin1Char(')');
if (endWithSemicolon) {
- extraChars += semicolon;
- m_typedChar = QChar();
+ extraCharacters += semicolon;
+ m_typedCharacter = QChar();
}
} else if (autoParenthesesEnabled) {
const QChar lookAhead = editorWidget->characterAt(editorWidget->position() + 1);
if (MatchingText::shouldInsertMatchingText(lookAhead)) {
- extraChars += QLatin1Char(')');
+ extraCharacters += QLatin1Char(')');
--cursorOffset;
if (endWithSemicolon) {
- extraChars += semicolon;
+ extraCharacters += semicolon;
--cursorOffset;
- m_typedChar = QChar();
+ m_typedCharacter = QChar();
}
}
}
@@ -187,8 +180,8 @@ void ClangAssistProposalItem::apply(TextEditor::TextEditorWidget *editorWidget,
}
// Append an unhandled typed character, adjusting cursor offset when it had been adjusted before
- if (!m_typedChar.isNull()) {
- extraChars += m_typedChar;
+ if (!m_typedCharacter.isNull()) {
+ extraCharacters += m_typedCharacter;
if (cursorOffset != 0)
--cursorOffset;
}
@@ -205,8 +198,8 @@ void ClangAssistProposalItem::apply(TextEditor::TextEditorWidget *editorWidget,
break;
}
}
- for (int i = 0; i < extraChars.length(); ++i) {
- const QChar a = extraChars.at(i);
+ for (int i = 0; i < extraCharacters.length(); ++i) {
+ const QChar a = extraCharacters.at(i);
const QChar b = editorWidget->characterAt(editorWidget->position() + i + existLength);
if (a == b)
++extraLength;
@@ -214,7 +207,7 @@ void ClangAssistProposalItem::apply(TextEditor::TextEditorWidget *editorWidget,
break;
}
- textToBeInserted += extraChars;
+ textToBeInserted += extraCharacters;
// Insert the remainder of the name
const int length = editorWidget->position() - basePosition + existLength + extraLength;
diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.h b/src/plugins/clangcodemodel/clangassistproposalitem.h
index 68d74ea6c2..776d7e196a 100644
--- a/src/plugins/clangcodemodel/clangassistproposalitem.h
+++ b/src/plugins/clangcodemodel/clangassistproposalitem.h
@@ -39,9 +39,7 @@ class ClangAssistProposalItem final : public TextEditor::AssistProposalItemInter
{
friend bool operator<(const ClangAssistProposalItem &first, const ClangAssistProposalItem &second);
public:
- ClangAssistProposalItem() {}
-
- bool prematurelyApplies(const QChar &c) const final;
+ bool prematurelyApplies(const QChar &typedCharacter) const final;
bool implicitlyApplies() const final;
void apply(TextEditor::TextEditorWidget *editorWidget, int basePosition) const final;
@@ -66,7 +64,7 @@ private:
QList<ClangBackEnd::CodeCompletion> m_overloads;
QString m_text;
unsigned m_completionOperator;
- mutable QChar m_typedChar;
+ mutable QChar m_typedCharacter;
};
} // namespace Internal
diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro
index cf2b1ce027..e3a3294c8a 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.pro
+++ b/src/plugins/clangcodemodel/clangcodemodel.pro
@@ -27,6 +27,7 @@ SOURCES += \
clangfunctionhintmodel.cpp \
clanghighlightingmarksreporter.cpp \
clangmodelmanagersupport.cpp \
+ clangpreprocessorassistproposalitem.cpp \
clangtextmark.cpp \
clangutils.cpp
@@ -53,6 +54,7 @@ HEADERS += \
clangfunctionhintmodel.h \
clanghighlightingmarksreporter.h \
clangmodelmanagersupport.h \
+ clangpreprocessorassistproposalitem.h \
clangtextmark.h \
clangutils.h
diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs
index 5be9afc9a0..8d72501868 100644
--- a/src/plugins/clangcodemodel/clangcodemodel.qbs
+++ b/src/plugins/clangcodemodel/clangcodemodel.qbs
@@ -79,6 +79,8 @@ QtcPlugin {
"clanghighlightingmarksreporter.h",
"clangmodelmanagersupport.cpp",
"clangmodelmanagersupport.h",
+ "clangpreprocessorassistproposalitem.cpp",
+ "clangpreprocessorassistproposalitem.h",
"clangtextmark.cpp",
"clangtextmark.h",
"clangutils.cpp",
diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
index fc4cd98619..5f3f6f6c49 100644
--- a/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp
@@ -33,6 +33,7 @@
#include "clangeditordocumentprocessor.h"
#include "clangfunctionhintmodel.h"
#include "clangcompletionchunkstotextconverter.h"
+#include "clangpreprocessorassistproposalitem.h"
#include <cpptools/cppdoxygen.h>
#include <cpptools/cppmodelmanager.h>
@@ -533,11 +534,11 @@ void ClangCompletionAssistProcessor::completeIncludePath(const QString &realPath
if (fileInfo.isDir())
text += QLatin1Char('/');
- auto *item = new ClangAssistProposalItem; // TODO: Add IncludeAssistProposalItem
+ auto *item = new ClangPreprocessorAssistProposalItem;
item->setText(text);
- //item->setDetail(hint);
- //item->setIcon(m_icons.keywordIcon());
- item->keepCompletionOperator(m_completionOperator);
+ item->setDetail(hint);
+ item->setIcon(m_icons.keywordIcon());
+ item->setCompletionOperator(m_completionOperator);
m_completions.append(item);
}
}
@@ -567,11 +568,11 @@ void ClangCompletionAssistProcessor::addCompletionItem(const QString &text,
const QIcon &icon,
int order)
{
- ClangAssistProposalItem *item = new ClangAssistProposalItem;
+ auto *item = new ClangPreprocessorAssistProposalItem;
item->setText(text);
- //item->setIcon(icon); TODO: Add item for macros and includes
+ item->setIcon(icon);
item->setOrder(order);
- item->keepCompletionOperator(m_completionOperator);
+ item->setCompletionOperator(m_completionOperator);
m_completions.append(item);
}
diff --git a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp
new file mode 100644
index 0000000000..23fcd4473b
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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.
+**
+****************************************************************************/
+
+#include "clangpreprocessorassistproposalitem.h"
+
+#include <texteditor/texteditor.h>
+
+#include <cplusplus/Token.h>
+
+namespace ClangCodeModel {
+
+bool ClangPreprocessorAssistProposalItem::prematurelyApplies(const QChar &typedCharacter) const
+{
+ bool applies = false;
+
+ if (isInclude())
+ applies = typedCharacter == QLatin1Char('/') && text().endsWith(QLatin1Char('/'));
+
+ if (applies)
+ m_typedCharacter = typedCharacter;
+
+ return applies;
+}
+
+bool ClangPreprocessorAssistProposalItem::implicitlyApplies() const
+{
+ return false;
+}
+
+void ClangPreprocessorAssistProposalItem::apply(TextEditor::TextEditorWidget *editorWidget,
+ int basePosition) const
+{
+ // TODO move in an extra class under tests
+
+ QString textToBeInserted = text();
+
+ QString extraCharacters;
+ int extraLength = 0;
+ int cursorOffset = 0;
+
+ if (isInclude()) {
+ if (!textToBeInserted.endsWith(QLatin1Char('/'))) {
+ extraCharacters += QLatin1Char((m_completionOperator == CPlusPlus::T_ANGLE_STRING_LITERAL) ? '>' : '"');
+ } else {
+ if (m_typedCharacter == QLatin1Char('/')) // Eat the slash
+ m_typedCharacter = QChar();
+ }
+ }
+
+ if (!m_typedCharacter.isNull()) {
+ extraCharacters += m_typedCharacter;
+ if (cursorOffset != 0)
+ --cursorOffset;
+ }
+
+ // Avoid inserting characters that are already there
+ const int endsPosition = editorWidget->position(TextEditor::EndOfLinePosition);
+ const QString existingText = editorWidget->textAt(editorWidget->position(), endsPosition - editorWidget->position());
+ int existLength = 0;
+ if (!existingText.isEmpty()) {
+ // Calculate the exist length in front of the extra chars
+ existLength = textToBeInserted.length() - (editorWidget->position() - basePosition);
+ while (!existingText.startsWith(textToBeInserted.right(existLength))) {
+ if (--existLength == 0)
+ break;
+ }
+ }
+ for (int i = 0; i < extraCharacters.length(); ++i) {
+ const QChar a = extraCharacters.at(i);
+ const QChar b = editorWidget->characterAt(editorWidget->position() + i + existLength);
+ if (a == b)
+ ++extraLength;
+ else
+ break;
+ }
+
+ textToBeInserted += extraCharacters;
+
+ // Insert the remainder of the name
+ const int length = editorWidget->position() - basePosition + existLength + extraLength;
+ const auto textToBeReplaced = editorWidget->textAt(basePosition, length);
+
+ if (textToBeReplaced != textToBeInserted) {
+ editorWidget->setCursorPosition(basePosition);
+ editorWidget->replace(length, textToBeInserted);
+ if (cursorOffset)
+ editorWidget->setCursorPosition(editorWidget->position() + cursorOffset);
+ }
+}
+
+void ClangPreprocessorAssistProposalItem::setText(const QString &text)
+{
+ m_text = text;
+}
+
+QString ClangPreprocessorAssistProposalItem::text() const
+{
+ return m_text;
+}
+
+void ClangPreprocessorAssistProposalItem::setIcon(const QIcon &icon)
+{
+ m_icon = icon;
+}
+
+QIcon ClangPreprocessorAssistProposalItem::icon() const
+{
+ return m_icon;
+}
+
+void ClangPreprocessorAssistProposalItem::setDetail(const QString &detail)
+{
+ m_detail = detail;
+}
+
+QString ClangPreprocessorAssistProposalItem::detail() const
+{
+ return QString();
+}
+
+bool ClangPreprocessorAssistProposalItem::isSnippet() const
+{
+ return false;
+}
+
+bool ClangPreprocessorAssistProposalItem::isValid() const
+{
+ return true;
+}
+
+quint64 ClangPreprocessorAssistProposalItem::hash() const
+{
+ return 0;
+}
+
+void ClangPreprocessorAssistProposalItem::setCompletionOperator(uint completionOperator)
+{
+ m_completionOperator = completionOperator;
+}
+
+bool ClangPreprocessorAssistProposalItem::isInclude() const
+{
+ return m_completionOperator == CPlusPlus::T_STRING_LITERAL
+ || m_completionOperator == CPlusPlus::T_ANGLE_STRING_LITERAL;
+}
+
+} // namespace ClangCodeModel
diff --git a/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h
new file mode 100644
index 0000000000..7b63d432bd
--- /dev/null
+++ b/src/plugins/clangcodemodel/clangpreprocessorassistproposalitem.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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.
+**
+****************************************************************************/
+
+#ifndef CLANGCODEMODEL_PREPROCESSORASSISTPROPOSALITEM_H
+#define CLANGCODEMODEL_PREPROCESSORASSISTPROPOSALITEM_H
+
+#include <texteditor/codeassist/assistproposaliteminterface.h>
+
+#include <QIcon>
+#include <QString>
+
+namespace ClangCodeModel {
+
+class ClangPreprocessorAssistProposalItem final : public TextEditor::AssistProposalItemInterface
+{
+public:
+ bool prematurelyApplies(const QChar &typedChar) const final;
+ virtual bool implicitlyApplies() const final;
+ void apply(TextEditor::TextEditorWidget *editorWidget, int basePosition) const final;
+
+ void setText(const QString &text);
+ QString text() const final;
+
+ void setIcon(const QIcon &icon);
+ QIcon icon() const final;
+
+ void setDetail(const QString &detail);
+ QString detail() const final;
+
+ bool isSnippet() const final;
+ bool isValid() const final;
+
+ quint64 hash() const final;
+
+ void setCompletionOperator(uint completionOperator);
+
+private:
+ bool isInclude() const;
+
+private:
+ QString m_text;
+ QString m_detail;
+ QIcon m_icon;
+ uint m_completionOperator;
+ mutable QChar m_typedCharacter;
+};
+
+} // namespace ClangCodeModel
+
+#endif // CLANGCODEMODEL_PREPROCESSORASSISTPROPOSALITEM_H
diff --git a/src/plugins/texteditor/codeassist/assistproposaliteminterface.h b/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
index 797bf78c7c..38fc4a2c73 100644
--- a/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
+++ b/src/plugins/texteditor/codeassist/assistproposaliteminterface.h
@@ -48,7 +48,7 @@ public:
virtual QString text() const = 0;
virtual bool implicitlyApplies() const = 0;
- virtual bool prematurelyApplies(const QChar &character) const = 0;
+ virtual bool prematurelyApplies(const QChar &typedCharacter) const = 0;
virtual void apply(TextEditorWidget *editorWidget, int basePosition) const = 0;
virtual QIcon icon() const = 0;
virtual QString detail() const = 0;