Clang: Fix determining current parameter

...for emphasis in the function signature tooltip when doing function
completion.

Braces, brackets and less/greater were not considered so that arguments
containing initializer lists, lambda captures or templates could lead to
the emphasis of no or the wrong parameter:

  void foo(VariantType t1, VariantType t2);

  void g(int x, int y)
  {
      foo({1,2, // Ops, no parameter emphasized
      foo({1,2}, // Ops, no parameter emphasized

      foo([x, y](){}, // Ops, no parameter emphasized

      foo(Bar<int, // Ops, second parameter emphasized
      foo(Bar<int, int>, // Ops, no parameter emphasized
  }

Change-Id: I2515fcbd892850b608bd90b35dd348ae522144b2
Reviewed-by: Marco Bubke <marco.bubke@theqtcompany.com>
This commit is contained in:
Nikolai Kosjar
2015-12-09 18:23:31 +01:00
parent c0e1b1581b
commit f25b9cab14
2 changed files with 43 additions and 18 deletions

View File

@@ -41,7 +41,7 @@ using namespace CPlusPlus;
ClangFunctionHintModel::ClangFunctionHintModel(const ClangBackEnd::CodeCompletions &functionSymbols)
: m_functionSymbols(functionSymbols)
, m_currentArg(-1)
, m_currentArgument(-1)
{
}
@@ -58,34 +58,59 @@ QString ClangFunctionHintModel::text(int index) const
{
const ClangBackEnd::CodeCompletionChunks chunks = m_functionSymbols.at(index).chunks();
const QString signatureWithEmphasizedCurrentParameter
= CompletionChunksToTextConverter::convertToFunctionSignature(chunks, m_currentArg + 1);
= CompletionChunksToTextConverter::convertToFunctionSignature(chunks, m_currentArgument + 1);
return signatureWithEmphasizedCurrentParameter;
}
int ClangFunctionHintModel::activeArgument(const QString &prefix) const
{
int argnr = 0;
int parcount = 0;
int activeArgumentNumber = 0;
int unbalancedParens = 0; // expressions
int unbalancedBraces = 0; // initializer lists
int unbalancedBrackets = 0; // lambda-capture
int unbalancedLessGreater = 0; // template arguments
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;
const Tokens tokens = tokenize(prefix);
for (const Token &token : tokens) {
if (token.is(T_LPAREN)) {
++unbalancedParens;
} else if (token.is(T_RPAREN)) {
--unbalancedParens;
} else if (token.is(T_LBRACE)) {
++unbalancedBraces;
} else if (token.is(T_RBRACE)) {
--unbalancedBraces;
} else if (token.is(T_LBRACKET)) {
++unbalancedBrackets;
} else if (token.is(T_RBRACKET)) {
--unbalancedBrackets;
} else if (token.is(T_LESS)) {
++unbalancedLessGreater;
} else if (token.is(T_GREATER)) {
--unbalancedLessGreater;
} else if (!unbalancedParens
&& !unbalancedBraces
&& !unbalancedBrackets
&& !unbalancedLessGreater
&& token.is(T_COMMA)) {
++activeArgumentNumber;
}
}
if (parcount < 0)
if (unbalancedParens < 0
|| unbalancedBraces < 0
|| unbalancedBrackets < 0
|| unbalancedLessGreater < 0) {
return -1;
}
if (argnr != m_currentArg)
m_currentArg = argnr;
if (activeArgumentNumber != m_currentArgument)
m_currentArgument = activeArgumentNumber;
return argnr;
return activeArgumentNumber;
}
} // namespace Internal

View File

@@ -50,7 +50,7 @@ public:
private:
ClangBackEnd::CodeCompletions m_functionSymbols;
mutable int m_currentArg;
mutable int m_currentArgument;
};
} // namespace Internal