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 "clangfunctionhintmodel.h"
27 
28 #include "clangcompletionchunkstotextconverter.h"
29 
30 #include <cplusplus/SimpleLexer.h>
31 
32 namespace ClangCodeModel {
33 namespace Internal {
34 
35 using namespace CPlusPlus;
36 
ClangFunctionHintModel(const ClangBackEnd::CodeCompletions & functionSymbols)37 ClangFunctionHintModel::ClangFunctionHintModel(const ClangBackEnd::CodeCompletions &functionSymbols)
38     : m_functionSymbols(functionSymbols)
39     , m_currentArgument(-1)
40 {
41 }
42 
reset()43 void ClangFunctionHintModel::reset()
44 {
45 }
46 
size() const47 int ClangFunctionHintModel::size() const
48 {
49     return m_functionSymbols.size();
50 }
51 
text(int index) const52 QString ClangFunctionHintModel::text(int index) const
53 {
54     const ClangBackEnd::CodeCompletionChunks &chunks = m_functionSymbols.at(index).chunks;
55     const QString signatureWithEmphasizedCurrentParameter
56             = CompletionChunksToTextConverter::convertToFunctionSignatureWithHtml(
57                 chunks,
58                 m_functionSymbols.at(index).completionKind,
59                 m_currentArgument + 1);
60 
61     return signatureWithEmphasizedCurrentParameter;
62 }
63 
id(int index) const64 QString ClangFunctionHintModel::id(int index) const
65 {
66     QString chunks;
67     for (const ClangBackEnd::CodeCompletionChunk &chunk : m_functionSymbols.at(index).chunks)
68         chunks += chunk.text;
69 
70     return chunks;
71 }
72 
activeArgument(const QString & prefix) const73 int ClangFunctionHintModel::activeArgument(const QString &prefix) const
74 {
75     int activeArgumentNumber = 0;
76 
77     int unbalancedParens = 0; // expressions
78     int unbalancedBraces = 0; // initializer lists
79     int unbalancedBrackets = 0; // lambda-capture
80     int unbalancedLessGreater = 0; // template arguments
81 
82     SimpleLexer tokenize;
83     const Tokens tokens = tokenize(prefix);
84     for (const Token &token : tokens) {
85         if (token.is(T_LPAREN)) {
86             ++unbalancedParens;
87         } else if (token.is(T_RPAREN)) {
88             --unbalancedParens;
89         } else if (token.is(T_LBRACE)) {
90             ++unbalancedBraces;
91         } else if (token.is(T_RBRACE)) {
92             --unbalancedBraces;
93         } else if (token.is(T_LBRACKET)) {
94             ++unbalancedBrackets;
95         } else if (token.is(T_RBRACKET)) {
96             --unbalancedBrackets;
97         } else if (token.is(T_LESS)) {
98             ++unbalancedLessGreater;
99         } else if (token.is(T_GREATER)) {
100             --unbalancedLessGreater;
101         } else if (!unbalancedParens
102                    && !unbalancedBraces
103                    && !unbalancedBrackets
104                    && !unbalancedLessGreater
105                    && token.is(T_COMMA)) {
106             ++activeArgumentNumber;
107         }
108     }
109 
110     if (unbalancedParens < 0
111             || unbalancedBraces < 0
112             || unbalancedBrackets < 0
113             || unbalancedLessGreater < 0) {
114         return -1;
115     }
116 
117     if (activeArgumentNumber != m_currentArgument)
118         m_currentArgument = activeArgumentNumber;
119 
120     return activeArgumentNumber;
121 }
122 
123 } // namespace Internal
124 } // namespace ClangCodeModel
125 
126