1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2016 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of Qt Creator. 7 ** 8 ** Commercial License Usage 9 ** Licensees holding valid commercial Qt licenses may use this file in 10 ** accordance with the commercial license agreement provided with the 11 ** Software or, alternatively, in accordance with the terms contained in 12 ** a written agreement between you and The Qt Company. For licensing terms 13 ** and conditions see https://www.qt.io/terms-conditions. For further 14 ** information use the contact form at https://www.qt.io/contact-us. 15 ** 16 ** GNU General Public License Usage 17 ** Alternatively, this file may be used under the terms of the GNU 18 ** General Public License version 3 as published by the Free Software 19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT 20 ** included in the packaging of this file. Please review the following 21 ** information to ensure the GNU General Public License requirements will 22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html. 23 ** 24 ****************************************************************************/ 25 26 #include "clangpreprocessorassistproposalitem.h" 27 28 #include <texteditor/texteditor.h> 29 30 #include <cplusplus/Token.h> 31 32 namespace ClangCodeModel { 33 namespace Internal { 34 prematurelyApplies(const QChar & typedCharacter) const35bool ClangPreprocessorAssistProposalItem::prematurelyApplies(const QChar &typedCharacter) const 36 { 37 bool applies = false; 38 39 if (isInclude()) 40 applies = typedCharacter == QLatin1Char('/') && text().endsWith(QLatin1Char('/')); 41 42 if (applies) 43 m_typedCharacter = typedCharacter; 44 45 return applies; 46 } 47 implicitlyApplies() const48bool ClangPreprocessorAssistProposalItem::implicitlyApplies() const 49 { 50 return true; 51 } 52 apply(TextEditor::TextDocumentManipulatorInterface & manipulator,int basePosition) const53void ClangPreprocessorAssistProposalItem::apply(TextEditor::TextDocumentManipulatorInterface &manipulator, 54 int basePosition) const 55 { 56 // TODO move in an extra class under tests 57 58 QString textToBeInserted = text(); 59 60 QString extraCharacters; 61 int extraLength = 0; 62 63 if (isInclude()) { 64 if (!textToBeInserted.endsWith(QLatin1Char('/'))) { 65 extraCharacters += QLatin1Char((m_completionOperator == CPlusPlus::T_ANGLE_STRING_LITERAL) ? '>' : '"'); 66 } else { 67 if (m_typedCharacter == QLatin1Char('/')) // Eat the slash 68 m_typedCharacter = QChar(); 69 } 70 } 71 72 if (!m_typedCharacter.isNull()) 73 extraCharacters += m_typedCharacter; 74 75 // Avoid inserting characters that are already there 76 const int endsPosition = manipulator.positionAt(TextEditor::EndOfLinePosition); 77 const QString existingText = manipulator.textAt(manipulator.currentPosition(), endsPosition - manipulator.currentPosition()); 78 int existLength = 0; 79 if (!existingText.isEmpty()) { 80 // Calculate the exist length in front of the extra chars 81 existLength = textToBeInserted.length() - (manipulator.currentPosition() - basePosition); 82 while (!existingText.startsWith(textToBeInserted.right(existLength))) { 83 if (--existLength == 0) 84 break; 85 } 86 } 87 for (int i = 0; i < extraCharacters.length(); ++i) { 88 const QChar a = extraCharacters.at(i); 89 const QChar b = manipulator.characterAt(manipulator.currentPosition() + i + existLength); 90 if (a == b) 91 ++extraLength; 92 else 93 break; 94 } 95 96 textToBeInserted += extraCharacters; 97 98 // Insert the remainder of the name 99 const int length = manipulator.currentPosition() - basePosition + existLength + extraLength; 100 101 manipulator.replace(basePosition, length, textToBeInserted); 102 } 103 setText(const QString & text)104void ClangPreprocessorAssistProposalItem::setText(const QString &text) 105 { 106 m_text = text; 107 } 108 text() const109QString ClangPreprocessorAssistProposalItem::text() const 110 { 111 return m_text; 112 } 113 setIcon(const QIcon & icon)114void ClangPreprocessorAssistProposalItem::setIcon(const QIcon &icon) 115 { 116 m_icon = icon; 117 } 118 icon() const119QIcon ClangPreprocessorAssistProposalItem::icon() const 120 { 121 return m_icon; 122 } 123 setDetail(const QString & detail)124void ClangPreprocessorAssistProposalItem::setDetail(const QString &detail) 125 { 126 m_detail = detail; 127 } 128 detail() const129QString ClangPreprocessorAssistProposalItem::detail() const 130 { 131 return QString(); 132 } 133 detailFormat() const134Qt::TextFormat ClangPreprocessorAssistProposalItem::detailFormat() const 135 { 136 return Qt::RichText; 137 } 138 isSnippet() const139bool ClangPreprocessorAssistProposalItem::isSnippet() const 140 { 141 return false; 142 } 143 isValid() const144bool ClangPreprocessorAssistProposalItem::isValid() const 145 { 146 return true; 147 } 148 hash() const149quint64 ClangPreprocessorAssistProposalItem::hash() const 150 { 151 return 0; 152 } 153 setCompletionOperator(uint completionOperator)154void ClangPreprocessorAssistProposalItem::setCompletionOperator(uint completionOperator) 155 { 156 m_completionOperator = completionOperator; 157 } 158 isInclude() const159bool ClangPreprocessorAssistProposalItem::isInclude() const 160 { 161 return m_completionOperator == CPlusPlus::T_STRING_LITERAL 162 || m_completionOperator == CPlusPlus::T_ANGLE_STRING_LITERAL; 163 } 164 165 } // namespace Internal 166 } // namespace ClangCodeModel 167