forked from qt-creator/qt-creator
clangbackend: Work around wrong cursor info from libclang
Alias type declarations of in-place struct definitions are not reliably getting their cursor exposed, so the surrounding context is reported instead, which causes the wrong lexical parent to be deduced. To the user, this manifests itself as a wrong hierarchy being displayed in the outline. We try to detect this condition and correct it manually. Task-number: QTCREATORBUG-24875 Change-Id: Ib4e177efa9148697eddde986a91fdd5d7b272d76 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -90,8 +90,37 @@ std::vector<Cursor> Tokens::annotate() const
|
|||||||
|
|
||||||
std::vector<CXCursor> cxCursors;
|
std::vector<CXCursor> cxCursors;
|
||||||
cxCursors.resize(m_tokens.size());
|
cxCursors.resize(m_tokens.size());
|
||||||
clang_annotateTokens(m_cxTranslationUnit, m_tokens.front().cx(),
|
|
||||||
static_cast<unsigned>(m_tokens.size()), cxCursors.data());
|
clang_annotateTokens(m_cxTranslationUnit, m_tokens.front().cx(), m_tokens.size(), cxCursors.data());
|
||||||
|
|
||||||
|
// The alias declaration "using S = struct {}" results in libclang reporting the type
|
||||||
|
// of the surrounding scope (e.g. a namespace or class) for the cursor corresponding to
|
||||||
|
// the token "S" (QTCREATORBUG-24875). We need to correct this manually.
|
||||||
|
// TODO: Investigate whether we can fix this in libclang itself.
|
||||||
|
for (int i = 1; i < int(m_tokens.size()) - 2; ++i) {
|
||||||
|
const Token &tok = m_tokens.at(i);
|
||||||
|
const Token &prevTok = m_tokens.at(i - 1);
|
||||||
|
const Token &nextTok = m_tokens.at(i + 1);
|
||||||
|
if (tok.kind() == CXToken_Identifier
|
||||||
|
&& prevTok.kind() == CXToken_Keyword
|
||||||
|
&& prevTok.spelling() == "using"
|
||||||
|
&& nextTok.spelling() == "="
|
||||||
|
&& cxCursors.at(i).kind != CXCursor_TypeAliasDecl) {
|
||||||
|
// If the surrounding scope is a namespace, the correct type is reported for the token
|
||||||
|
// after the identifier, i.e. the "=" symbol. Otherwise, it's not reported at all,
|
||||||
|
// and we have to use the cursor after that, which should be the aliased type.
|
||||||
|
// Note that we cannot use the next cursors in the cxCursors array, because
|
||||||
|
// clang_annotateTokens() reports the surrounding scope for all of these.
|
||||||
|
CXCursor nextCursor = clang_getCursor(m_cxTranslationUnit, clang_getTokenLocation(
|
||||||
|
m_cxTranslationUnit, *nextTok.cx()));
|
||||||
|
if (nextCursor.kind != CXCursor_TypeAliasDecl) {
|
||||||
|
nextCursor = clang_getCursor(m_cxTranslationUnit, clang_getTokenLocation(
|
||||||
|
m_cxTranslationUnit, *m_tokens.at(i + 2).cx()));
|
||||||
|
}
|
||||||
|
cxCursors[i] = nextCursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cursors.reserve(cxCursors.size());
|
cursors.reserve(cxCursors.size());
|
||||||
for (const CXCursor &cxCursor : cxCursors)
|
for (const CXCursor &cxCursor : cxCursors)
|
||||||
cursors.emplace_back(cxCursor);
|
cursors.emplace_back(cxCursor);
|
||||||
|
Reference in New Issue
Block a user