forked from qt-creator/qt-creator
Clang: Add ClangPreprocessorAssistProposalItem
Change-Id: Ifb27b9a21b9a2fe9a04496bbb70fa3fa07d1f89c Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -79,6 +79,8 @@ QtcPlugin {
|
||||
"clanghighlightingmarksreporter.h",
|
||||
"clangmodelmanagersupport.cpp",
|
||||
"clangmodelmanagersupport.h",
|
||||
"clangpreprocessorassistproposalitem.cpp",
|
||||
"clangpreprocessorassistproposalitem.h",
|
||||
"clangtextmark.cpp",
|
||||
"clangtextmark.h",
|
||||
"clangutils.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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user