diff options
21 files changed, 1273 insertions, 702 deletions
diff --git a/src/plugins/clangcodemodel/clangassistproposal.cpp b/src/plugins/clangcodemodel/clangassistproposal.cpp new file mode 100644 index 0000000000..2df9aa84f3 --- /dev/null +++ b/src/plugins/clangcodemodel/clangassistproposal.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "clangassistproposal.h" + +#include <texteditor/texteditor.h> + +namespace ClangCodeModel { +namespace Internal { + +ClangAssistProposal::ClangAssistProposal(int cursorPos, TextEditor::GenericProposalModel *model) + : GenericProposal(cursorPos, model) + , m_replaceDotForArrow(static_cast<ClangAssistProposalModel *>(model)->m_replaceDotForArrow) +{ +} + +bool ClangAssistProposal::isCorrective() const +{ + return m_replaceDotForArrow; +} + +void ClangAssistProposal::makeCorrection(TextEditor::TextEditorWidget *editorWidget) +{ + editorWidget->setCursorPosition(basePosition() - 1); + editorWidget->replace(1, QLatin1String("->")); + moveBasePosition(1); +} + +} // namespace Internal +} // namespace ClangCodeModel + diff --git a/src/plugins/clangcodemodel/clangassistproposal.h b/src/plugins/clangcodemodel/clangassistproposal.h new file mode 100644 index 0000000000..6a0ada3d79 --- /dev/null +++ b/src/plugins/clangcodemodel/clangassistproposal.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGCODEMODEL_INTERNAL_CLANGASSISTPROPOSAL_H +#define CLANGCODEMODEL_INTERNAL_CLANGASSISTPROPOSAL_H + +#include "clangassistproposalmodel.h" + +#include <texteditor/codeassist/genericproposal.h> + +namespace ClangCodeModel { +namespace Internal { + +class ClangAssistProposal : public TextEditor::GenericProposal +{ +public: + ClangAssistProposal(int cursorPos, TextEditor::GenericProposalModel *model); + + virtual bool isCorrective() const; + virtual void makeCorrection(TextEditor::TextEditorWidget *editorWidget); + +private: + bool m_replaceDotForArrow; +}; + +} // namespace Internal +} // namespace ClangCodeModel + +#endif // CLANGCODEMODEL_INTERNAL_CLANGASSISTPROPOSAL_H diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.cpp b/src/plugins/clangcodemodel/clangassistproposalitem.cpp new file mode 100644 index 0000000000..3bfff0bf98 --- /dev/null +++ b/src/plugins/clangcodemodel/clangassistproposalitem.cpp @@ -0,0 +1,225 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "clangassistproposalitem.h" + +#include <cplusplus/MatchingText.h> +#include <cplusplus/Token.h> + +#include <texteditor/completionsettings.h> +#include <texteditor/texteditor.h> +#include <texteditor/texteditorsettings.h> + +using namespace CPlusPlus; +using namespace ClangBackEnd; + +namespace ClangCodeModel { +namespace Internal { + +bool ClangAssistProposalItem::prematurelyApplies(const QChar &typedChar) const +{ + bool ok = false; + + if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) + ok = QString::fromLatin1("(,").contains(typedChar); + else if (m_completionOperator == T_STRING_LITERAL || m_completionOperator == T_ANGLE_STRING_LITERAL) + ok = (typedChar == QLatin1Char('/')) && text().endsWith(QLatin1Char('/')); + else if (!isCodeCompletion()) + ok = (typedChar == QLatin1Char('(')); /* && data().canConvert<CompleteFunctionDeclaration>()*/ //### + else if (originalItem().completionKind() == CodeCompletion::ObjCMessageCompletionKind) + ok = QString::fromLatin1(";.,").contains(typedChar); + else + ok = QString::fromLatin1(";.,:(").contains(typedChar); + + if (ok) + m_typedChar = typedChar; + + return ok; +} + +void ClangAssistProposalItem::applyContextualContent(TextEditor::TextEditorWidget *editorWidget, + int basePosition) const +{ + const CodeCompletion ccr = originalItem(); + + QString toInsert = text(); + QString extraChars; + 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 (!toInsert.endsWith(QLatin1Char('/'))) { + extraChars += QLatin1Char((m_completionOperator == T_ANGLE_STRING_LITERAL) ? '>' : '"'); + } else { + if (m_typedChar == QLatin1Char('/')) // Eat the slash + m_typedChar = QChar(); + } + } else if (!ccr.text().isEmpty()) { + const TextEditor::CompletionSettings &completionSettings = + TextEditor::TextEditorSettings::instance()->completionSettings(); + const bool autoInsertBrackets = completionSettings.m_autoInsertBrackets; + + if (autoInsertBrackets && + (ccr.completionKind() == CodeCompletion::FunctionCompletionKind + || ccr.completionKind() == CodeCompletion::DestructorCompletionKind + || ccr.completionKind() == CodeCompletion::SignalCompletionKind + || ccr.completionKind() == CodeCompletion::SlotCompletionKind)) { + // 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('('); + + if (completionSettings.m_spaceAfterFunctionName) + extraChars += QLatin1Char(' '); + extraChars += QLatin1Char('('); + if (m_typedChar == QLatin1Char('(')) + m_typedChar = 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(';')/* + || (function->returnType()->isVoidType() && m_completionOperator != T_COLON_COLON)*/; //### + const QChar semicolon = m_typedChar.isNull() ? QLatin1Char(';') : m_typedChar; + + if (endWithSemicolon && characterAtCursor == semicolon) { + endWithSemicolon = false; + m_typedChar = QChar(); + } + + // If the function takes no arguments, automatically place the closing parenthesis + if (!isOverloaded() && !ccr.hasParameters() && skipClosingParenthesis) { + extraChars += QLatin1Char(')'); + if (endWithSemicolon) { + extraChars += semicolon; + m_typedChar = QChar(); + } + } else if (autoParenthesesEnabled) { + const QChar lookAhead = editorWidget->characterAt(editorWidget->position() + 1); + if (MatchingText::shouldInsertMatchingText(lookAhead)) { + extraChars += QLatin1Char(')'); + --cursorOffset; + if (endWithSemicolon) { + extraChars += semicolon; + --cursorOffset; + m_typedChar = QChar(); + } + } + } + } + +#if 0 + if (autoInsertBrackets && data().canConvert<CompleteFunctionDeclaration>()) { + if (m_typedChar == QLatin1Char('(')) + m_typedChar = QChar(); + + // everything from the closing parenthesis on are extra chars, to + // make sure an auto-inserted ")" gets replaced by ") const" if necessary + int closingParen = toInsert.lastIndexOf(QLatin1Char(')')); + extraChars = toInsert.mid(closingParen); + toInsert.truncate(closingParen); + } +#endif + } + + // Append an unhandled typed character, adjusting cursor offset when it had been adjusted before + if (!m_typedChar.isNull()) { + extraChars += m_typedChar; + 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 = toInsert.length() - (editorWidget->position() - basePosition); + while (!existingText.startsWith(toInsert.right(existLength))) { + if (--existLength == 0) + break; + } + } + for (int i = 0; i < extraChars.length(); ++i) { + const QChar a = extraChars.at(i); + const QChar b = editorWidget->characterAt(editorWidget->position() + i + existLength); + if (a == b) + ++extraLength; + else + break; + } + toInsert += extraChars; + + // Insert the remainder of the name + const int length = editorWidget->position() - basePosition + existLength + extraLength; + editorWidget->setCursorPosition(basePosition); + editorWidget->replace(length, toInsert); + if (cursorOffset) + editorWidget->setCursorPosition(editorWidget->position() + cursorOffset); +} + +void ClangAssistProposalItem::keepCompletionOperator(unsigned compOp) +{ + m_completionOperator = compOp; +} + +bool ClangAssistProposalItem::isOverloaded() const +{ + return !m_overloads.isEmpty(); +} + +void ClangAssistProposalItem::addOverload(const CodeCompletion &ccr) +{ + m_overloads.append(ccr); +} + +CodeCompletion ClangAssistProposalItem::originalItem() const +{ + const QVariant &value = data(); + if (value.canConvert<CodeCompletion>()) + return value.value<CodeCompletion>(); + else + return CodeCompletion(); +} + +bool ClangAssistProposalItem::isCodeCompletion() const +{ + return data().canConvert<CodeCompletion>(); +} + +} // namespace Internal +} // namespace ClangCodeModel + diff --git a/src/plugins/clangcodemodel/clangassistproposalitem.h b/src/plugins/clangcodemodel/clangassistproposalitem.h new file mode 100644 index 0000000000..45cdd64652 --- /dev/null +++ b/src/plugins/clangcodemodel/clangassistproposalitem.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGCODEMODEL_INTERNAL_CLANGASSISTPROPOSALITEM_H +#define CLANGCODEMODEL_INTERNAL_CLANGASSISTPROPOSALITEM_H + +#include <codecompletion.h> + +#include <texteditor/codeassist/assistproposalitem.h> + +namespace ClangCodeModel { +namespace Internal { + +class ClangAssistProposalItem : public TextEditor::AssistProposalItem +{ + friend bool operator<(const ClangAssistProposalItem &first, const ClangAssistProposalItem &second); +public: + ClangAssistProposalItem() {} + + bool prematurelyApplies(const QChar &c) const override; + void applyContextualContent(TextEditor::TextEditorWidget *editorWidget, int basePosition) const override; + + void keepCompletionOperator(unsigned compOp); + + bool isOverloaded() const; + void addOverload(const ClangBackEnd::CodeCompletion &ccr); + + ClangBackEnd::CodeCompletion originalItem() const; + + bool isCodeCompletion() const; +private: + unsigned m_completionOperator; + mutable QChar m_typedChar; + QList<ClangBackEnd::CodeCompletion> m_overloads; +}; + +} // namespace Internal +} // namespace ClangCodeModel + +#endif // CLANGCODEMODEL_INTERNAL_CLANGASSISTPROPOSALITEM_H diff --git a/src/plugins/clangcodemodel/clangassistproposalmodel.cpp b/src/plugins/clangcodemodel/clangassistproposalmodel.cpp new file mode 100644 index 0000000000..90a2e76d2b --- /dev/null +++ b/src/plugins/clangcodemodel/clangassistproposalmodel.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "clangassistproposalitem.h" + +#include "clangassistproposalmodel.h" + +namespace ClangCodeModel { +namespace Internal { + +namespace { + +const ClangAssistProposalItem &toClangAssistProposalItem(TextEditor::AssistProposalItem *assistProposalItem) +{ + return *static_cast<ClangAssistProposalItem*>(assistProposalItem); +} + +} + +bool ClangAssistProposalModel::isSortable(const QString &/*prefix*/) const +{ + return true; +} + +} // namespace Internal +} // namespace ClangCodeModel + diff --git a/src/plugins/clangcodemodel/clangassistproposalmodel.h b/src/plugins/clangcodemodel/clangassistproposalmodel.h new file mode 100644 index 0000000000..8cab0dfaa8 --- /dev/null +++ b/src/plugins/clangcodemodel/clangassistproposalmodel.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGCODEMODEL_INTERNAL_CLANGASSISTPROPOSALMODEL_H +#define CLANGCODEMODEL_INTERNAL_CLANGASSISTPROPOSALMODEL_H + +#include <cplusplus/Token.h> + +#include <texteditor/codeassist/genericproposalmodel.h> + +namespace ClangCodeModel { +namespace Internal { + +class ClangAssistProposalModel : public TextEditor::GenericProposalModel +{ +public: + ClangAssistProposalModel() + : m_sortable(false) + , m_completionOperator(CPlusPlus::T_EOF_SYMBOL) + , m_replaceDotForArrow(false) + {} + + bool isSortable(const QString &prefix) const override; + + bool m_sortable; + unsigned m_completionOperator; + bool m_replaceDotForArrow; +}; + +} // namespace Internal +} // namespace ClangCodeModel + +#endif // CLANGCODEMODEL_INTERNAL_CLANGASSISTPROPOSALMODEL_H diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 7374cfddbf..4c41104f46 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -30,7 +30,7 @@ #include "clangbackendipcintegration.h" -#include "clangcompletion.h" +#include "clangcompletionassistprocessor.h" #include "clangmodelmanagersupport.h" #include "clangutils.h" #include "pchmanager.h" diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro index 61f92031c0..93ab1028e2 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.pro +++ b/src/plugins/clangcodemodel/clangcodemodel.pro @@ -12,101 +12,115 @@ DEFINES += "\"CLANG_RESOURCE_DIR=\\\"$${LLVM_LIBDIR}/clang/$${LLVM_VERSION}/incl unix:QMAKE_LFLAGS += -Wl,-rpath,\'$$LLVM_LIBDIR\' SOURCES += \ - $$PWD/clangcodemodelplugin.cpp \ - $$PWD/clangcompletioncontextanalyzer.cpp \ - $$PWD/clangcompletion.cpp \ - $$PWD/clangeditordocumentparser.cpp \ - $$PWD/clangeditordocumentprocessor.cpp \ - $$PWD/clangmodelmanagersupport.cpp \ - $$PWD/clangprojectsettings.cpp \ - $$PWD/clangprojectsettingspropertiespage.cpp \ - $$PWD/clangutils.cpp \ - $$PWD/clangbackendipcintegration.cpp \ - $$PWD/completionchunkstotextconverter.cpp \ - $$PWD/cppcreatemarkers.cpp \ - $$PWD/cxprettyprinter.cpp \ - $$PWD/diagnostic.cpp \ - $$PWD/fastindexer.cpp \ - $$PWD/pchinfo.cpp \ - $$PWD/pchmanager.cpp \ - $$PWD/raii/scopedclangoptions.cpp \ - $$PWD/semanticmarker.cpp \ - $$PWD/sourcelocation.cpp \ - $$PWD/sourcemarker.cpp \ - $$PWD/symbol.cpp \ - $$PWD/unit.cpp \ - $$PWD/unsavedfiledata.cpp \ - $$PWD/utils.cpp \ - $$PWD/utils_p.cpp + clangassistproposal.cpp \ + clangassistproposalitem.cpp \ + clangassistproposalmodel.cpp \ + clangbackendipcintegration.cpp \ + clangcodemodelplugin.cpp \ + clangcompletionassistinterface.cpp \ + clangcompletionassistprocessor.cpp \ + clangcompletionassistprovider.cpp \ + clangcompletioncontextanalyzer.cpp \ + clangeditordocumentparser.cpp \ + clangeditordocumentprocessor.cpp \ + clangfunctionhintmodel.cpp \ + clangmodelmanagersupport.cpp \ + clangprojectsettings.cpp \ + clangprojectsettingspropertiespage.cpp \ + clangutils.cpp \ + completionchunkstotextconverter.cpp \ + cppcreatemarkers.cpp \ + cxprettyprinter.cpp \ + diagnostic.cpp \ + fastindexer.cpp \ + pchinfo.cpp \ + pchmanager.cpp \ + raii/scopedclangoptions.cpp \ + semanticmarker.cpp \ + sourcelocation.cpp \ + sourcemarker.cpp \ + symbol.cpp \ + unit.cpp \ + unsavedfiledata.cpp \ + utils.cpp \ + utils_p.cpp + HEADERS += \ - $$PWD/clangcodemodelplugin.h \ - $$PWD/clangcompletioncontextanalyzer.h \ - $$PWD/clangcompletion.h \ - $$PWD/clangeditordocumentparser.h \ - $$PWD/clangeditordocumentprocessor.h \ - $$PWD/clang_global.h \ - $$PWD/clangmodelmanagersupport.h \ - $$PWD/clangprojectsettings.h \ - $$PWD/clangprojectsettingspropertiespage.h \ - $$PWD/clangutils.h \ - $$PWD/clangbackendipcintegration.h \ - $$PWD/completionchunkstotextconverter.h \ - $$PWD/constants.h \ - $$PWD/cppcreatemarkers.h \ - $$PWD/cxprettyprinter.h \ - $$PWD/cxraii.h \ - $$PWD/diagnostic.h \ - $$PWD/fastindexer.h \ - $$PWD/pchinfo.h \ - $$PWD/pchmanager.h \ - $$PWD/raii/scopedclangoptions.h \ - $$PWD/semanticmarker.h \ - $$PWD/sourcelocation.h \ - $$PWD/sourcemarker.h \ - $$PWD/symbol.h \ - $$PWD/unit.h \ - $$PWD/unsavedfiledata.h \ - $$PWD/utils.h \ - $$PWD/utils_p.h + clangassistproposal.h \ + clangassistproposalitem.h \ + clangassistproposalmodel.h \ + clangbackendipcintegration.h \ + clangcodemodelplugin.h \ + clangcompletionassistinterface.h \ + clangcompletionassistprocessor.h \ + clangcompletionassistprovider.h \ + clangcompletioncontextanalyzer.h \ + clangeditordocumentparser.h \ + clangeditordocumentprocessor.h \ + clangfunctionhintmodel.h \ + clang_global.h \ + clangmodelmanagersupport.h \ + clangprojectsettings.h \ + clangprojectsettingspropertiespage.h \ + clangutils.h \ + completionchunkstotextconverter.h \ + constants.h \ + cppcreatemarkers.h \ + cxprettyprinter.h \ + cxraii.h \ + diagnostic.h \ + fastindexer.h \ + pchinfo.h \ + pchmanager.h \ + raii/scopedclangoptions.h \ + semanticmarker.h \ + sourcelocation.h \ + sourcemarker.h \ + symbol.h \ + unit.h \ + unsavedfiledata.h \ + utils.h \ + utils_p.h + contains(DEFINES, CLANG_INDEXING) { HEADERS += \ - $$PWD/clangindexer.h \ - $$PWD/index.h \ - $$PWD/indexer.h -# $$PWD/dependencygraph.h \ + clangindexer.h \ + index.h \ + indexer.h +# dependencygraph.h \ SOURCES += \ - $$PWD/clangindexer.cpp \ - $$PWD/index.cpp \ - $$PWD/indexer.cpp -# $$PWD/dependencygraph.cpp \ + clangindexer.cpp \ + index.cpp \ + indexer.cpp +# dependencygraph.cpp \ } -FORMS += $$PWD/clangprojectsettingspropertiespage.ui +FORMS += clangprojectsettingspropertiespage.ui equals(TEST, 1) { RESOURCES += \ - $$PWD/test/clang_tests_database.qrc + test/clang_tests_database.qrc HEADERS += \ - $$PWD/test/clangcodecompletion_test.h \ - $$PWD/test/clangcompletioncontextanalyzertest.h + test/clangcodecompletion_test.h \ + test/clangcompletioncontextanalyzertest.h SOURCES += \ - $$PWD/test/clangcodecompletion_test.cpp \ - $$PWD/test/clangcompletioncontextanalyzertest.cpp + test/clangcodecompletion_test.cpp \ + test/clangcompletioncontextanalyzertest.cpp DISTFILES += \ - $$PWD/test/mysource.cpp \ - $$PWD/test/myheader.cpp \ - $$PWD/test/completionWithProject.cpp \ - $$PWD/test/memberCompletion.cpp \ - $$PWD/test/doxygenKeywordsCompletion.cpp \ - $$PWD/test/preprocessorKeywordsCompletion.cpp \ - $$PWD/test/includeDirectiveCompletion.cpp + test/mysource.cpp \ + test/myheader.cpp \ + test/completionWithProject.cpp \ + test/memberCompletion.cpp \ + test/doxygenKeywordsCompletion.cpp \ + test/preprocessorKeywordsCompletion.cpp \ + test/includeDirectiveCompletion.cpp } macx { diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs index 2afa813760..f254cd2157 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.qbs +++ b/src/plugins/clangcodemodel/clangcodemodel.qbs @@ -53,8 +53,20 @@ QtcPlugin { name: "Completion support" condition: product.clangCompletion files: [ - "clangcompletion.cpp", - "clangcompletion.h", + "clangassistproposal.cpp", + "clangassistproposal.h", + "clangassistproposalitem.cpp", + "clangassistproposalitem.h", + "clangassistproposalmodel.cpp", + "clangassistproposalmodel.h", + "clangcompletionassistinterface.cpp", + "clangcompletionassistinterface.h", + "clangcompletionassistprocessor.cpp", + "clangcompletionassistprocessor.h", + "clangcompletionassistprovider.cpp", + "clangcompletionassistprovider.h", + "clangfunctionhintmodel.cpp", + "clangfunctionhintmodel.h", ] } diff --git a/src/plugins/clangcodemodel/clangcompletion.h b/src/plugins/clangcodemodel/clangcompletion.h deleted file mode 100644 index efb6699e19..0000000000 --- a/src/plugins/clangcodemodel/clangcompletion.h +++ /dev/null @@ -1,199 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://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 http://www.qt.io/terms-conditions. For further information -** use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef CPPEDITOR_INTERNAL_CLANGCOMPLETION_H -#define CPPEDITOR_INTERNAL_CLANGCOMPLETION_H - -#include "clangbackendipcintegration.h" - -#include "pchinfo.h" -#include "utils.h" - -#include <cpptools/cppcompletionassistprocessor.h> -#include <cpptools/cppcompletionassistprovider.h> -#include <cpptools/cppmodelmanager.h> - -#include <texteditor/codeassist/assistinterface.h> -#include <texteditor/codeassist/assistproposalitem.h> -#include <texteditor/codeassist/completionassistprovider.h> -#include <texteditor/codeassist/ifunctionhintproposalmodel.h> - -#include <clangbackendipc/codecompletion.h> - -#include <QStringList> -#include <QTextCursor> - -namespace ClangCodeModel { -namespace Internal { - -using CodeCompletions = QVector<ClangBackEnd::CodeCompletion>; - -class ClangAssistProposalModel; - -class ClangCompletionAssistProvider : public CppTools::CppCompletionAssistProvider -{ - Q_OBJECT - -public: - ClangCompletionAssistProvider(IpcCommunicator &ipcCommunicator); - - IAssistProvider::RunType runType() const override; - - TextEditor::IAssistProcessor *createProcessor() const override; - TextEditor::AssistInterface *createAssistInterface( - const QString &filePath, - const TextEditor::TextEditorWidget *textEditorWidget, - const CPlusPlus::LanguageFeatures &languageFeatures, - int position, - TextEditor::AssistReason reason) const override; - -private: - IpcCommunicator &m_ipcCommunicator; -}; - -class ClangAssistProposalItem : public TextEditor::AssistProposalItem -{ -public: - ClangAssistProposalItem() {} - - bool prematurelyApplies(const QChar &c) const override; - void applyContextualContent(TextEditor::TextEditorWidget *editorWidget, int basePosition) const override; - - void keepCompletionOperator(unsigned compOp) { m_completionOperator = compOp; } - - bool isOverloaded() const; - void addOverload(const ClangBackEnd::CodeCompletion &ccr); - - ClangBackEnd::CodeCompletion originalItem() const; - - bool isCodeCompletion() const; - -private: - unsigned m_completionOperator; - mutable QChar m_typedChar; - QList<ClangBackEnd::CodeCompletion> m_overloads; -}; - -class ClangFunctionHintModel : public TextEditor::IFunctionHintProposalModel -{ -public: - ClangFunctionHintModel(const CodeCompletions &functionSymbols); - - void reset() override {} - int size() const override { return m_functionSymbols.size(); } - QString text(int index) const override; - int activeArgument(const QString &prefix) const override; - -private: - CodeCompletions m_functionSymbols; - mutable int m_currentArg; -}; - -class ClangCompletionAssistInterface: public TextEditor::AssistInterface -{ -public: - ClangCompletionAssistInterface(ClangCodeModel::Internal::IpcCommunicator &ipcCommunicator, - const TextEditor::TextEditorWidget *textEditorWidget, - int position, - const QString &fileName, - TextEditor::AssistReason reason, - const CppTools::ProjectPart::HeaderPaths &headerPaths, - const Internal::PchInfo::Ptr &pchInfo, - const CPlusPlus::LanguageFeatures &features); - - ClangCodeModel::Internal::IpcCommunicator &ipcCommunicator() const; - const ClangCodeModel::Internal::UnsavedFiles &unsavedFiles() const; - bool objcEnabled() const; - const CppTools::ProjectPart::HeaderPaths &headerPaths() const; - CPlusPlus::LanguageFeatures languageFeatures() const; - const TextEditor::TextEditorWidget *textEditorWidget() const; - - void setHeaderPaths(const CppTools::ProjectPart::HeaderPaths &headerPaths); // For tests - -private: - ClangCodeModel::Internal::IpcCommunicator &m_ipcCommunicator; - ClangCodeModel::Internal::UnsavedFiles m_unsavedFiles; - QStringList m_options; - CppTools::ProjectPart::HeaderPaths m_headerPaths; - Internal::PchInfo::Ptr m_savedPchPointer; - CPlusPlus::LanguageFeatures m_languageFeatures; - const TextEditor::TextEditorWidget *m_textEditorWidget; -}; - -class ClangCompletionAssistProcessor : public CppTools::CppCompletionAssistProcessor -{ - Q_DECLARE_TR_FUNCTIONS(ClangCodeModel::Internal::ClangCompletionAssistProcessor) - -public: - ClangCompletionAssistProcessor(); - ~ClangCompletionAssistProcessor(); - - TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override; - - void asyncCompletionsAvailable(const CodeCompletions &completions); - - const TextEditor::TextEditorWidget *textEditorWidget() const; - -private: - TextEditor::IAssistProposal *startCompletionHelper(); - int startOfOperator(int pos, unsigned *kind, bool wantFunctionCall) const; - int findStartOfName(int pos = -1) const; - bool accepts() const; - - TextEditor::IAssistProposal *createProposal() const; - - bool completeInclude(const QTextCursor &cursor); - bool completeInclude(int position); - void completeIncludePath(const QString &realPath, const QStringList &suffixes); - bool completePreprocessorDirectives(); - bool completeDoxygenKeywords(); - void addCompletionItem(const QString &text, - const QIcon &icon = QIcon(), - int order = 0, - const QVariant &data = QVariant()); - - void sendFileContent(const QString &projectFilePath, const QByteArray &modifiedFileContent); - void sendCompletionRequest(int position, const QByteArray &modifiedFileContent); - - void onCompletionsAvailable(const CodeCompletions &completions); - void onFunctionHintCompletionsAvailable(const CodeCompletions &completions); - -private: - QScopedPointer<const ClangCompletionAssistInterface> m_interface; - unsigned m_completionOperator; - enum CompletionRequestType { NormalCompletion, FunctionHintCompletion } m_sentRequestType; - QString m_functionName; // For type == Type::FunctionHintCompletion - bool m_addSnippets = false; // For type == Type::NormalCompletion -}; - -} // namespace Internal -} // namespace Clang - -#endif // CPPEDITOR_INTERNAL_CLANGCOMPLETION_H diff --git a/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp b/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp new file mode 100644 index 0000000000..5c7a2a2d0e --- /dev/null +++ b/src/plugins/clangcodemodel/clangcompletionassistinterface.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "clangcompletionassistinterface.h" + +#include "clangutils.h" + +#include <cpptools/cppmodelmanager.h> +#include <cpptools/cppworkingcopy.h> + +#include <texteditor/texteditor.h> + +#include <cplusplus/Token.h> + +namespace ClangCodeModel { +namespace Internal { + +ClangCompletionAssistInterface::ClangCompletionAssistInterface( + IpcCommunicator &ipcCommunicator, + const TextEditor::TextEditorWidget *textEditorWidget, + int position, + const QString &fileName, + TextEditor::AssistReason reason, + const CppTools::ProjectPart::HeaderPaths &headerPaths, + const PchInfo::Ptr &pchInfo, + const CPlusPlus::LanguageFeatures &features) + : AssistInterface(textEditorWidget->document(), position, fileName, reason) + , m_ipcCommunicator(ipcCommunicator) + , m_headerPaths(headerPaths) + , m_savedPchPointer(pchInfo) + , m_languageFeatures(features) + , m_textEditorWidget(textEditorWidget) +{ + m_unsavedFiles = Utils::createUnsavedFiles(CppTools::CppModelManager::instance()->workingCopy()); +} + +bool ClangCompletionAssistInterface::objcEnabled() const +{ + return true; // TODO: +} + +const CppTools::ProjectPart::HeaderPaths &ClangCompletionAssistInterface::headerPaths() const +{ + return m_headerPaths; +} + +CPlusPlus::LanguageFeatures ClangCompletionAssistInterface::languageFeatures() const +{ + return m_languageFeatures; +} + +void ClangCompletionAssistInterface::setHeaderPaths(const CppTools::ProjectPart::HeaderPaths &headerPaths) +{ + m_headerPaths = headerPaths; +} + +const TextEditor::TextEditorWidget *ClangCompletionAssistInterface::textEditorWidget() const +{ + return m_textEditorWidget; +} + +IpcCommunicator &ClangCompletionAssistInterface::ipcCommunicator() const +{ + return m_ipcCommunicator; +} + +const UnsavedFiles &ClangCompletionAssistInterface::unsavedFiles() const +{ + return m_unsavedFiles; +} + +} // namespace Internal +} // namespace ClangCodeModel + diff --git a/src/plugins/clangcodemodel/clangcompletionassistinterface.h b/src/plugins/clangcodemodel/clangcompletionassistinterface.h new file mode 100644 index 0000000000..21a9e8d4ab --- /dev/null +++ b/src/plugins/clangcodemodel/clangcompletionassistinterface.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTINTERFACE_H +#define CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTINTERFACE_H + +#include "clangbackendipcintegration.h" +#include "pchinfo.h" +#include "utils.h" + +#include <cpptools/cppcompletionassistprovider.h> + +#include <texteditor/codeassist/assistinterface.h> + +namespace ClangCodeModel { +namespace Internal { + +class ClangCompletionAssistInterface: public TextEditor::AssistInterface +{ +public: + ClangCompletionAssistInterface(IpcCommunicator &ipcCommunicator, + const TextEditor::TextEditorWidget *textEditorWidget, + int position, + const QString &fileName, + TextEditor::AssistReason reason, + const CppTools::ProjectPart::HeaderPaths &headerPaths, + const PchInfo::Ptr &pchInfo, + const CPlusPlus::LanguageFeatures &features); + + IpcCommunicator &ipcCommunicator() const; + const UnsavedFiles &unsavedFiles() const; + bool objcEnabled() const; + const CppTools::ProjectPart::HeaderPaths &headerPaths() const; + CPlusPlus::LanguageFeatures languageFeatures() const; + const TextEditor::TextEditorWidget *textEditorWidget() const; + + void setHeaderPaths(const CppTools::ProjectPart::HeaderPaths &headerPaths); // For tests + +private: + IpcCommunicator &m_ipcCommunicator; + UnsavedFiles m_unsavedFiles; + QStringList m_options; + CppTools::ProjectPart::HeaderPaths m_headerPaths; + Internal::PchInfo::Ptr m_savedPchPointer; + CPlusPlus::LanguageFeatures m_languageFeatures; + const TextEditor::TextEditorWidget *m_textEditorWidget; +}; + +} // namespace Internal +} // namespace ClangCodeModel + +#endif // CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTINTERFACE_H diff --git a/src/plugins/clangcodemodel/clangcompletion.cpp b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp index 25c18b905b..779c858975 100644 --- a/src/plugins/clangcodemodel/clangcompletion.cpp +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.cpp @@ -28,52 +28,38 @@ ** ****************************************************************************/ -#include "clangcompletion.h" +#include "clangassistproposalitem.h" + +#include "clangassistproposal.h" +#include "clangassistproposalmodel.h" +#include "clangcompletionassistprocessor.h" #include "clangcompletioncontextanalyzer.h" +#include "clangfunctionhintmodel.h" #include "clangutils.h" -#include "completionchunkstotextconverter.h" -#include "pchmanager.h" - -#include <coreplugin/icore.h> -#include <coreplugin/idocument.h> -#include <cplusplus/BackwardsScanner.h> -#include <cplusplus/ExpressionUnderCursor.h> -#include <cplusplus/Token.h> -#include <cplusplus/MatchingText.h> +#include <utils/qtcassert.h> -#include <cppeditor/cppeditorconstants.h> +#include <texteditor/codeassist/assistproposalitem.h> +#include <texteditor/codeassist/functionhintproposal.h> +#include <texteditor/codeassist/ifunctionhintproposalmodel.h> +#include <texteditor/convenience.h> -#include <cpptools/baseeditordocumentparser.h> #include <cpptools/cppdoxygen.h> -#include <cpptools/cppmodelmanager.h> -#include <cpptools/cppworkingcopy.h> -#include <texteditor/texteditor.h> -#include <texteditor/convenience.h> -#include <texteditor/codeassist/genericproposalmodel.h> -#include <texteditor/codeassist/assistproposalitem.h> -#include <texteditor/codeassist/functionhintproposal.h> -#include <texteditor/codeassist/genericproposal.h> -#include <texteditor/texteditorsettings.h> -#include <texteditor/completionsettings.h> +#include <cplusplus/BackwardsScanner.h> +#include <cplusplus/ExpressionUnderCursor.h> +#include <cplusplus/SimpleLexer.h> + +#include <QDirIterator> +#include <QTextBlock> +#include <filecontainer.h> -#include <utils/algorithm.h> #include <utils/mimetypes/mimedatabase.h> -#include <utils/qtcassert.h> -#include <QCoreApplication> -#include <QDirIterator> -#include <QLoggingCategory> -#include <QTextCursor> -#include <QTextDocument> +namespace ClangCodeModel { +namespace Internal { -using namespace ClangBackEnd; -using namespace ClangCodeModel; -using namespace ClangCodeModel::Internal; -using namespace CPlusPlus; -using namespace CppTools; -using namespace TextEditor; +using TextEditor::AssistProposalItem; namespace { @@ -85,6 +71,8 @@ int activationSequenceChar(const QChar &ch, unsigned *kind, bool wantFunctionCall) { + using namespace CPlusPlus; + int referencePosition = 0; int completionKind = T_EOF_SYMBOL; switch (ch.toLatin1()) { @@ -194,6 +182,9 @@ QList<AssistProposalItem *> toAssistProposalItems(const CodeCompletions &complet } // FIXME: show the effective accessebility instead of availability + using ClangBackEnd::CodeCompletion; + using CPlusPlus::Icons; + switch (ccr.completionKind()) { case CodeCompletion::ClassCompletionKind: case CodeCompletion::TemplateClassCompletionKind: @@ -293,382 +284,8 @@ QVector<CodeCompletion> matchingFunctionCompletions(const QVector<CodeCompletion } // Anonymous -namespace ClangCodeModel { -namespace Internal { - -// ----------------------------- -// ClangCompletionAssistProvider -// ----------------------------- -ClangCompletionAssistProvider::ClangCompletionAssistProvider(IpcCommunicator &ipcCommunicator) - : m_ipcCommunicator(ipcCommunicator) -{ -} - -IAssistProvider::RunType ClangCompletionAssistProvider::runType() const -{ - return Asynchronous; -} - -IAssistProcessor *ClangCompletionAssistProvider::createProcessor() const -{ - return new ClangCompletionAssistProcessor; -} - -AssistInterface *ClangCompletionAssistProvider::createAssistInterface( - const QString &filePath, - const TextEditorWidget *textEditorWidget, - const LanguageFeatures &languageFeatures, - int position, - AssistReason reason) const -{ - Q_UNUSED(languageFeatures); - const ProjectPart::Ptr part = Utils::projectPartForFile(filePath); - QTC_ASSERT(!part.isNull(), return 0); - - const PchInfo::Ptr pchInfo = PchManager::instance()->pchInfo(part); - return new ClangCompletionAssistInterface(m_ipcCommunicator, - textEditorWidget, - position, - filePath, - reason, - part->headerPaths, - pchInfo, - part->languageFeatures); -} - -// ------------------------ -// ClangAssistProposalModel -// ------------------------ -class ClangAssistProposalModel : public GenericProposalModel -{ -public: - ClangAssistProposalModel() - : m_sortable(false) - , m_completionOperator(T_EOF_SYMBOL) - , m_replaceDotForArrow(false) - {} - - virtual bool isSortable(const QString &prefix) const; - bool m_sortable; - unsigned m_completionOperator; - bool m_replaceDotForArrow; -}; - -// ------------------- -// ClangAssistProposal -// ------------------- -class ClangAssistProposal : public GenericProposal -{ -public: - ClangAssistProposal(int cursorPos, GenericProposalModel *model) - : GenericProposal(cursorPos, model) - , m_replaceDotForArrow(static_cast<ClangAssistProposalModel *>(model)->m_replaceDotForArrow) - {} - - virtual bool isCorrective() const { return m_replaceDotForArrow; } - virtual void makeCorrection(TextEditorWidget *editorWidget) - { - editorWidget->setCursorPosition(basePosition() - 1); - editorWidget->replace(1, QLatin1String("->")); - moveBasePosition(1); - } - -private: - bool m_replaceDotForArrow; -}; - -// ---------------------- -// ClangFunctionHintModel -// ---------------------- - -ClangFunctionHintModel::ClangFunctionHintModel(const CodeCompletions &functionSymbols) - : m_functionSymbols(functionSymbols) - , m_currentArg(-1) -{} - -QString ClangFunctionHintModel::text(int index) const -{ -#if 0 - // TODO: add the boldening to the result - Overview overview; - overview.setShowReturnTypes(true); - overview.setShowArgumentNames(true); - overview.setMarkedArgument(m_currentArg + 1); - Function *f = m_functionSymbols.at(index); - - const QString prettyMethod = overview(f->type(), f->name()); - const int begin = overview.markedArgumentBegin(); - const int end = overview.markedArgumentEnd(); - - QString hintText; - hintText += prettyMethod.left(begin).toHtmlEscaped()); - hintText += "<b>"; - hintText += prettyMethod.mid(begin, end - begin).toHtmlEscaped()); - hintText += "</b>"; - hintText += prettyMethod.mid(end).toHtmlEscaped()); - return hintText; -#endif - return CompletionChunksToTextConverter::convert(m_functionSymbols.at(index).chunks()); -} - -int ClangFunctionHintModel::activeArgument(const QString &prefix) const -{ - int argnr = 0; - int parcount = 0; - SimpleLexer tokenize; - Tokens tokens = tokenize(prefix); - for (int i = 0; i < tokens.count(); ++i) { - const Token &tk = tokens.at(i); - if (tk.is(T_LPAREN)) - ++parcount; - else if (tk.is(T_RPAREN)) - --parcount; - else if (! parcount && tk.is(T_COMMA)) - ++argnr; - } - - if (parcount < 0) - return -1; - - if (argnr != m_currentArg) - m_currentArg = argnr; - - return argnr; -} - -/// @return True, because clang always returns priorities for sorting -bool ClangAssistProposalModel::isSortable(const QString &prefix) const -{ - Q_UNUSED(prefix) - return true; -} - -bool ClangAssistProposalItem::prematurelyApplies(const QChar &typedChar) const -{ - bool ok = false; - - if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) - ok = QString::fromLatin1("(,").contains(typedChar); - else if (m_completionOperator == T_STRING_LITERAL || m_completionOperator == T_ANGLE_STRING_LITERAL) - ok = (typedChar == QLatin1Char('/')) && text().endsWith(QLatin1Char('/')); - else if (!isCodeCompletion()) - ok = (typedChar == QLatin1Char('(')); /* && data().canConvert<CompleteFunctionDeclaration>()*/ //### - else if (originalItem().completionKind() == CodeCompletion::ObjCMessageCompletionKind) - ok = QString::fromLatin1(";.,").contains(typedChar); - else - ok = QString::fromLatin1(";.,:(").contains(typedChar); - - if (ok) - m_typedChar = typedChar; - - return ok; -} - -void ClangAssistProposalItem::applyContextualContent(TextEditorWidget *editorWidget, - int basePosition) const -{ - const CodeCompletion ccr = originalItem(); - - QString toInsert = text(); - QString extraChars; - 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 (!toInsert.endsWith(QLatin1Char('/'))) { - extraChars += QLatin1Char((m_completionOperator == T_ANGLE_STRING_LITERAL) ? '>' : '"'); - } else { - if (m_typedChar == QLatin1Char('/')) // Eat the slash - m_typedChar = QChar(); - } - } else if (!ccr.text().isEmpty()) { - const CompletionSettings &completionSettings = - TextEditorSettings::instance()->completionSettings(); - const bool autoInsertBrackets = completionSettings.m_autoInsertBrackets; - - if (autoInsertBrackets && - (ccr.completionKind() == CodeCompletion::FunctionCompletionKind - || ccr.completionKind() == CodeCompletion::DestructorCompletionKind - || ccr.completionKind() == CodeCompletion::SignalCompletionKind - || ccr.completionKind() == CodeCompletion::SlotCompletionKind)) { - // 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('('); - - if (completionSettings.m_spaceAfterFunctionName) - extraChars += QLatin1Char(' '); - extraChars += QLatin1Char('('); - if (m_typedChar == QLatin1Char('(')) - m_typedChar = 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(';')/* - || (function->returnType()->isVoidType() && m_completionOperator != T_COLON_COLON)*/; //### - const QChar semicolon = m_typedChar.isNull() ? QLatin1Char(';') : m_typedChar; - - if (endWithSemicolon && characterAtCursor == semicolon) { - endWithSemicolon = false; - m_typedChar = QChar(); - } - - // If the function takes no arguments, automatically place the closing parenthesis - if (!isOverloaded() && !ccr.hasParameters() && skipClosingParenthesis) { - extraChars += QLatin1Char(')'); - if (endWithSemicolon) { - extraChars += semicolon; - m_typedChar = QChar(); - } - } else if (autoParenthesesEnabled) { - const QChar lookAhead = editorWidget->characterAt(editorWidget->position() + 1); - if (MatchingText::shouldInsertMatchingText(lookAhead)) { - extraChars += QLatin1Char(')'); - --cursorOffset; - if (endWithSemicolon) { - extraChars += semicolon; - --cursorOffset; - m_typedChar = QChar(); - } - } - } - } - -#if 0 - if (autoInsertBrackets && data().canConvert<CompleteFunctionDeclaration>()) { - if (m_typedChar == QLatin1Char('(')) - m_typedChar = QChar(); - - // everything from the closing parenthesis on are extra chars, to - // make sure an auto-inserted ")" gets replaced by ") const" if necessary - int closingParen = toInsert.lastIndexOf(QLatin1Char(')')); - extraChars = toInsert.mid(closingParen); - toInsert.truncate(closingParen); - } -#endif - } - - // Append an unhandled typed character, adjusting cursor offset when it had been adjusted before - if (!m_typedChar.isNull()) { - extraChars += m_typedChar; - if (cursorOffset != 0) - --cursorOffset; - } - - // Avoid inserting characters that are already there - const int endsPosition = editorWidget->position(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 = toInsert.length() - (editorWidget->position() - basePosition); - while (!existingText.startsWith(toInsert.right(existLength))) { - if (--existLength == 0) - break; - } - } - for (int i = 0; i < extraChars.length(); ++i) { - const QChar a = extraChars.at(i); - const QChar b = editorWidget->characterAt(editorWidget->position() + i + existLength); - if (a == b) - ++extraLength; - else - break; - } - toInsert += extraChars; - - // Insert the remainder of the name - const int length = editorWidget->position() - basePosition + existLength + extraLength; - editorWidget->setCursorPosition(basePosition); - editorWidget->replace(length, toInsert); - if (cursorOffset) - editorWidget->setCursorPosition(editorWidget->position() + cursorOffset); -} - -bool ClangAssistProposalItem::isOverloaded() const -{ - return !m_overloads.isEmpty(); -} - -void ClangAssistProposalItem::addOverload(const CodeCompletion &ccr) -{ - m_overloads.append(ccr); -} - -CodeCompletion ClangAssistProposalItem::originalItem() const -{ - const QVariant &value = data(); - if (value.canConvert<CodeCompletion>()) - return value.value<CodeCompletion>(); - else - return CodeCompletion(); -} - -bool ClangAssistProposalItem::isCodeCompletion() const -{ - return data().canConvert<CodeCompletion>(); -} - -bool ClangCompletionAssistInterface::objcEnabled() const -{ - return true; // TODO: -} - -const ProjectPart::HeaderPaths &ClangCompletionAssistInterface::headerPaths() const -{ - return m_headerPaths; -} - -LanguageFeatures ClangCompletionAssistInterface::languageFeatures() const -{ - return m_languageFeatures; -} - -void ClangCompletionAssistInterface::setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths) -{ - m_headerPaths = headerPaths; -} - -const TextEditor::TextEditorWidget *ClangCompletionAssistInterface::textEditorWidget() const -{ - return m_textEditorWidget; -} - -ClangCompletionAssistInterface::ClangCompletionAssistInterface( - IpcCommunicator &ipcCommunicator, - const TextEditorWidget *textEditorWidget, - int position, - const QString &fileName, - AssistReason reason, - const ProjectPart::HeaderPaths &headerPaths, - const PchInfo::Ptr &pchInfo, - const LanguageFeatures &features) - : AssistInterface(textEditorWidget->document(), position, fileName, reason) - , m_ipcCommunicator(ipcCommunicator) - , m_headerPaths(headerPaths) - , m_savedPchPointer(pchInfo) - , m_languageFeatures(features) - , m_textEditorWidget(textEditorWidget) -{ - CppModelManager *mmi = CppModelManager::instance(); - m_unsavedFiles = Utils::createUnsavedFiles(mmi->workingCopy()); -} - -IpcCommunicator &ClangCompletionAssistInterface::ipcCommunicator() const -{ - return m_ipcCommunicator; -} - -const UnsavedFiles &ClangCompletionAssistInterface::unsavedFiles() const -{ - return m_unsavedFiles; -} +using namespace CPlusPlus; +using namespace TextEditor; ClangCompletionAssistProcessor::ClangCompletionAssistProcessor() : m_completionOperator(T_EOF_SYMBOL) @@ -1006,9 +623,9 @@ bool ClangCompletionAssistProcessor::completeInclude(const QTextCursor &cursor) } // Make completion for all relevant includes - ProjectPart::HeaderPaths headerPaths = m_interface->headerPaths(); - const ProjectPart::HeaderPath currentFilePath(QFileInfo(m_interface->fileName()).path(), - ProjectPart::HeaderPath::IncludePath); + CppTools::ProjectPart::HeaderPaths headerPaths = m_interface->headerPaths(); + const CppTools::ProjectPart::HeaderPath currentFilePath(QFileInfo(m_interface->fileName()).path(), + CppTools::ProjectPart::HeaderPath::IncludePath); if (!headerPaths.contains(currentFilePath)) headerPaths.append(currentFilePath); @@ -1016,7 +633,7 @@ bool ClangCompletionAssistProcessor::completeInclude(const QTextCursor &cursor) const ::Utils::MimeType mimeType = mdb.mimeTypeForName(QLatin1String("text/x-c++hdr")); const QStringList suffixes = mimeType.suffixes(); - foreach (const ProjectPart::HeaderPath &headerPath, headerPaths) { + foreach (const CppTools::ProjectPart::HeaderPath &headerPath, headerPaths) { QString realPath = headerPath.path; if (!directoryPrefix.isEmpty()) { realPath += QLatin1Char('/'); @@ -1082,8 +699,8 @@ bool ClangCompletionAssistProcessor::completePreprocessorDirectives() bool ClangCompletionAssistProcessor::completeDoxygenKeywords() { - for (int i = 1; i < T_DOXY_LAST_TAG; ++i) - addCompletionItem(QString::fromLatin1(doxygenTagSpell(i)), m_icons.keywordIcon()); + for (int i = 1; i < CppTools::T_DOXY_LAST_TAG; ++i) + addCompletionItem(QString::fromLatin1(CppTools::doxygenTagSpell(i)), m_icons.keywordIcon()); return !m_completions.isEmpty(); } @@ -1112,7 +729,7 @@ void ClangCompletionAssistProcessor::sendFileContent(const QString &projectFileP IpcCommunicator &ipcCommunicator = m_interface->ipcCommunicator(); ipcCommunicator.registerFilesForCodeCompletion( - {FileContainer(filePath, + {ClangBackEnd::FileContainer(filePath, projectFilePath, Utf8String::fromByteArray(unsavedContent), hasUnsavedContent)}); @@ -1122,7 +739,7 @@ void ClangCompletionAssistProcessor::sendCompletionRequest(int position, const QByteArray &modifiedFileContent) { int line, column; - Convenience::convertPosition(m_interface->textDocument(), position, &line, &column); + TextEditor::Convenience::convertPosition(m_interface->textDocument(), position, &line, &column); ++column; const QString filePath = m_interface->fileName(); @@ -1156,8 +773,8 @@ void ClangCompletionAssistProcessor::onFunctionHintCompletionsAvailable( const auto relevantCompletions = matchingFunctionCompletions(completions, m_functionName); if (!relevantCompletions.isEmpty()) { - IFunctionHintProposalModel *model = new ClangFunctionHintModel(relevantCompletions); - FunctionHintProposal *proposal = new FunctionHintProposal(m_positionForProposal, model); + TextEditor::IFunctionHintProposalModel *model = new ClangFunctionHintModel(relevantCompletions); + TextEditor::FunctionHintProposal *proposal = new FunctionHintProposal(m_positionForProposal, model); setAsyncProposalAvailable(proposal); } else { @@ -1168,3 +785,4 @@ void ClangCompletionAssistProcessor::onFunctionHintCompletionsAvailable( } // namespace Internal } // namespace ClangCodeModel + diff --git a/src/plugins/clangcodemodel/clangcompletionassistprocessor.h b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h new file mode 100644 index 0000000000..f712246406 --- /dev/null +++ b/src/plugins/clangcodemodel/clangcompletionassistprocessor.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTPROCESSOR_H +#define CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTPROCESSOR_H + +#include "clangcompletionassistinterface.h" + +#include <cpptools/cppcompletionassistprocessor.h> + +#include <texteditor/texteditor.h> + +#include <QCoreApplication> + +namespace ClangBackEnd { +class CodeCompletion; +} + +namespace ClangCodeModel { +namespace Internal { + +using CodeCompletions = QVector<ClangBackEnd::CodeCompletion>; +using ClangBackEnd::CodeCompletion; + +class ClangCompletionAssistProcessor : public CppTools::CppCompletionAssistProcessor +{ + Q_DECLARE_TR_FUNCTIONS(ClangCodeModel::Internal::ClangCompletionAssistProcessor) + +public: + ClangCompletionAssistProcessor(); + ~ClangCompletionAssistProcessor(); + + TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override; + + void asyncCompletionsAvailable(const CodeCompletions &completions); + + const TextEditor::TextEditorWidget *textEditorWidget() const; + +private: + TextEditor::IAssistProposal *startCompletionHelper(); + int startOfOperator(int pos, unsigned *kind, bool wantFunctionCall) const; + int findStartOfName(int pos = -1) const; + bool accepts() const; + + TextEditor::IAssistProposal *createProposal() const; + + bool completeInclude(const QTextCursor &cursor); + bool completeInclude(int position); + void completeIncludePath(const QString &realPath, const QStringList &suffixes); + bool completePreprocessorDirectives(); + bool completeDoxygenKeywords(); + void addCompletionItem(const QString &text, + const QIcon &icon = QIcon(), + int order = 0, + const QVariant &data = QVariant()); + + void sendFileContent(const QString &projectFilePath, const QByteArray &modifiedFileContent); + void sendCompletionRequest(int position, const QByteArray &modifiedFileContent); + + void onCompletionsAvailable(const CodeCompletions &completions); + void onFunctionHintCompletionsAvailable(const CodeCompletions &completions); + +private: + QScopedPointer<const ClangCompletionAssistInterface> m_interface; + unsigned m_completionOperator; + enum CompletionRequestType { NormalCompletion, FunctionHintCompletion } m_sentRequestType; + QString m_functionName; // For type == Type::FunctionHintCompletion + bool m_addSnippets = false; // For type == Type::NormalCompletion +}; + +} // namespace Internal +} // namespace ClangCodeModel + +#endif // CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTPROCESSOR_H diff --git a/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp b/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp new file mode 100644 index 0000000000..eb0f5797ec --- /dev/null +++ b/src/plugins/clangcodemodel/clangcompletionassistprovider.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "clangcompletionassistprovider.h" + +#include "clangcompletionassistprocessor.h" +#include "clangutils.h" +#include "pchmanager.h" + +#include <cplusplus/Token.h> +#include <cpptools/cppcompletionassistprocessor.h> +#include <cpptools/cppprojects.h> + +#include <texteditor/codeassist/assistinterface.h> +#include <texteditor/codeassist/iassistprocessor.h> +#include <texteditor/codeassist/iassistprovider.h> +#include <texteditor/texteditor.h> + +#include <utils/qtcassert.h> + +namespace ClangCodeModel { +namespace Internal { + +ClangCompletionAssistProvider::ClangCompletionAssistProvider(IpcCommunicator &ipcCommunicator) + : m_ipcCommunicator(ipcCommunicator) +{ +} + +TextEditor::IAssistProvider::RunType ClangCompletionAssistProvider::runType() const +{ + return Asynchronous; +} + +TextEditor::IAssistProcessor *ClangCompletionAssistProvider::createProcessor() const +{ + return new ClangCompletionAssistProcessor; +} + +TextEditor::AssistInterface *ClangCompletionAssistProvider::createAssistInterface( + const QString &filePath, + const TextEditor::TextEditorWidget *textEditorWidget, + const CPlusPlus::LanguageFeatures &/*languageFeatures*/, + int position, + TextEditor::AssistReason reason) const +{ + const CppTools::ProjectPart::Ptr projectPart = Utils::projectPartForFile(filePath); + QTC_ASSERT(!projectPart.isNull(), return 0); + + const PchInfo::Ptr pchInfo = PchManager::instance()->pchInfo(projectPart); + return new ClangCompletionAssistInterface(m_ipcCommunicator, + textEditorWidget, + position, + filePath, + reason, + projectPart->headerPaths, + pchInfo, + projectPart->languageFeatures); +} + +} // namespace Internal +} // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clangcompletionassistprovider.h b/src/plugins/clangcodemodel/clangcompletionassistprovider.h new file mode 100644 index 0000000000..a49f7be23f --- /dev/null +++ b/src/plugins/clangcodemodel/clangcompletionassistprovider.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTPROVIDER_H +#define CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTPROVIDER_H + +#include "clangbackendipcintegration.h" + +#include <cpptools/cppcompletionassistprovider.h> + +#include <texteditor/codeassist/assistinterface.h> + +namespace ClangCodeModel { +namespace Internal { + +class ClangCompletionAssistProvider : public CppTools::CppCompletionAssistProvider +{ + Q_OBJECT + +public: + ClangCompletionAssistProvider(IpcCommunicator &ipcCommunicator); + + IAssistProvider::RunType runType() const override; + + TextEditor::IAssistProcessor *createProcessor() const override; + TextEditor::AssistInterface *createAssistInterface( + const QString &filePath, + const TextEditor::TextEditorWidget *textEditorWidget, + const CPlusPlus::LanguageFeatures &languageFeatures, + int position, + TextEditor::AssistReason reason) const override; + +private: + IpcCommunicator &m_ipcCommunicator; +}; + +} // namespace Internal +} // namespace ClangCodeModel + +#endif // CLANGCODEMODEL_INTERNAL_CLANGCOMPLETIONASSISTPROVIDER_H diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp new file mode 100644 index 0000000000..67e8048ee4 --- /dev/null +++ b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "clangfunctionhintmodel.h" + +#include "completionchunkstotextconverter.h" + +#include <cplusplus/SimpleLexer.h> + +namespace ClangCodeModel { +namespace Internal { + +using namespace CPlusPlus; + +ClangFunctionHintModel::ClangFunctionHintModel(const CodeCompletions &functionSymbols) + : m_functionSymbols(functionSymbols) + , m_currentArg(-1) +{ +} + +void ClangFunctionHintModel::reset() +{ +} + +int ClangFunctionHintModel::size() const +{ + return m_functionSymbols.size(); +} + +QString ClangFunctionHintModel::text(int index) const +{ +#if 0 + // TODO: add the boldening to the result + Overview overview; + overview.setShowReturnTypes(true); + overview.setShowArgumentNames(true); + overview.setMarkedArgument(m_currentArg + 1); + Function *f = m_functionSymbols.at(index); + + const QString prettyMethod = overview(f->type(), f->name()); + const int begin = overview.markedArgumentBegin(); + const int end = overview.markedArgumentEnd(); + + QString hintText; + hintText += prettyMethod.left(begin).toHtmlEscaped()); + hintText += "<b>"; + hintText += prettyMethod.mid(begin, end - begin).toHtmlEscaped()); + hintText += "</b>"; + hintText += prettyMethod.mid(end).toHtmlEscaped()); + return hintText; +#endif + return CompletionChunksToTextConverter::convert(m_functionSymbols.at(index).chunks()); +} + +int ClangFunctionHintModel::activeArgument(const QString &prefix) const +{ + int argnr = 0; + int parcount = 0; + SimpleLexer tokenize; + Tokens tokens = tokenize(prefix); + for (int i = 0; i < tokens.count(); ++i) { + const Token &tk = tokens.at(i); + if (tk.is(T_LPAREN)) + ++parcount; + else if (tk.is(T_RPAREN)) + --parcount; + else if (! parcount && tk.is(T_COMMA)) + ++argnr; + } + + if (parcount < 0) + return -1; + + if (argnr != m_currentArg) + m_currentArg = argnr; + + return argnr; +} + +} // namespace Internal +} // namespace ClangCodeModel + diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.h b/src/plugins/clangcodemodel/clangfunctionhintmodel.h new file mode 100644 index 0000000000..c1e9f656b3 --- /dev/null +++ b/src/plugins/clangcodemodel/clangfunctionhintmodel.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CLANGCODEMODEL_INTERNAL_CLANGFUNCTIONHINTMODEL_H +#define CLANGCODEMODEL_INTERNAL_CLANGFUNCTIONHINTMODEL_H + +#include <codecompletion.h> + +#include <texteditor/codeassist/ifunctionhintproposalmodel.h> + +namespace ClangCodeModel { +namespace Internal { + +using CodeCompletions = QVector<ClangBackEnd::CodeCompletion>; + +class ClangFunctionHintModel : public TextEditor::IFunctionHintProposalModel +{ +public: + ClangFunctionHintModel(const CodeCompletions &functionSymbols); + + void reset() override; + int size() const override; + QString text(int index) const override; + int activeArgument(const QString &prefix) const override; + +private: + CodeCompletions m_functionSymbols; + mutable int m_currentArg; +}; + +} // namespace Internal +} // namespace ClangCodeModel + +#endif // CLANGCODEMODEL_INTERNAL_CLANGFUNCTIONHINTMODEL_H diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index e3b97bed96..36bd7aebfd 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -31,7 +31,6 @@ #include "clangmodelmanagersupport.h" #include "constants.h" -#include "clangcompletion.h" #include "clangeditordocumentprocessor.h" #include "clangutils.h" diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index b885e8c11d..7269e925dc 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -31,7 +31,7 @@ #ifndef CLANGCODEMODEL_INTERNAL_CLANGMODELMANAGERSUPPORT_H #define CLANGCODEMODEL_INTERNAL_CLANGMODELMANAGERSUPPORT_H -#include "clangcompletion.h" +#include "clangcompletionassistprovider.h" #include <cpptools/cppmodelmanagersupport.h> diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp index b174c2a784..58de825850 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp @@ -31,9 +31,9 @@ #include "clangcodecompletion_test.h" #include "../clangbackendipcintegration.h" +#include "../clangcompletionassistinterface.h" #include "../clangmodelmanagersupport.h" -#include <clangcodemodel/clangcompletion.h> #include <clangcodemodel/constants.h> #include <coreplugin/editormanager/editormanager.h> @@ -45,6 +45,7 @@ #include <cpptools/cpptoolstestcase.h> #include <cpptools/modelmanagertesthelper.h> #include <texteditor/codeassist/assistinterface.h> +#include <texteditor/codeassist/assistproposalitem.h> #include <texteditor/codeassist/completionassistprovider.h> #include <texteditor/codeassist/genericproposalmodel.h> #include <texteditor/codeassist/iassistprocessor.h> |