From f25b9cab141778082982eb1c578039ada5612231 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 9 Dec 2015 18:23:31 +0100 Subject: [PATCH] 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, // Ops, no parameter emphasized } Change-Id: I2515fcbd892850b608bd90b35dd348ae522144b2 Reviewed-by: Marco Bubke --- .../clangcodemodel/clangfunctionhintmodel.cpp | 59 +++++++++++++------ .../clangcodemodel/clangfunctionhintmodel.h | 2 +- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp index 61e0b4cf9b4..03dfa6d6c99 100644 --- a/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp +++ b/src/plugins/clangcodemodel/clangfunctionhintmodel.cpp @@ -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 diff --git a/src/plugins/clangcodemodel/clangfunctionhintmodel.h b/src/plugins/clangcodemodel/clangfunctionhintmodel.h index 65a9c0affa2..3e5213f7956 100644 --- a/src/plugins/clangcodemodel/clangfunctionhintmodel.h +++ b/src/plugins/clangcodemodel/clangfunctionhintmodel.h @@ -50,7 +50,7 @@ public: private: ClangBackEnd::CodeCompletions m_functionSymbols; - mutable int m_currentArg; + mutable int m_currentArgument; }; } // namespace Internal