aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2020-11-18 18:04:21 +0100
committerChristian Kandeler <christian.kandeler@qt.io>2020-11-23 10:07:20 +0000
commitd3fafcde0fd4f74112d20228ac7175a02ffcb821 (patch)
treed053af9a59ced07acc03384154b3ffc410185a2c
parentb0dd6b748f68af8b53d5c3fc470e5758ddf969de (diff)
CppEditor: Support decl/def switch for conversion operators
Fixes: QTCREATORBUG-21168 Change-Id: I515fe146a679e007c96fa8d23f1457dadf07db3c Reviewed-by: Christian Stenger <christian.stenger@qt.io>
-rw-r--r--src/libs/3rdparty/cplusplus/Control.cpp9
-rw-r--r--src/libs/3rdparty/cplusplus/Control.h1
-rw-r--r--src/libs/3rdparty/cplusplus/Scope.cpp21
-rw-r--r--src/libs/3rdparty/cplusplus/Scope.h1
-rw-r--r--src/libs/cplusplus/LookupContext.cpp22
-rw-r--r--src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp13
-rw-r--r--src/plugins/cpptools/symbolfinder.cpp26
7 files changed, 81 insertions, 12 deletions
diff --git a/src/libs/3rdparty/cplusplus/Control.cpp b/src/libs/3rdparty/cplusplus/Control.cpp
index 4033b16028..1c0994604a 100644
--- a/src/libs/3rdparty/cplusplus/Control.cpp
+++ b/src/libs/3rdparty/cplusplus/Control.cpp
@@ -579,6 +579,15 @@ const OperatorNameId *Control::findOperatorNameId(OperatorNameId::Kind operatorI
return &*i;
}
+const ConversionNameId *Control::findConversionNameId(const FullySpecifiedType &type) const
+{
+ for (const ConversionNameId &id : d->conversionNameIds) {
+ if (type.match(id.type()))
+ return &id;
+ }
+ return nullptr;
+}
+
const Identifier *Control::findIdentifier(const char *chars, int size) const
{ return d->identifiers.findLiteral(chars, size); }
diff --git a/src/libs/3rdparty/cplusplus/Control.h b/src/libs/3rdparty/cplusplus/Control.h
index 59b3cf4ad9..4a2388f726 100644
--- a/src/libs/3rdparty/cplusplus/Control.h
+++ b/src/libs/3rdparty/cplusplus/Control.h
@@ -186,6 +186,7 @@ public:
const Identifier *cpp11Final() const;
const OperatorNameId *findOperatorNameId(OperatorNameId::Kind operatorId) const;
+ const ConversionNameId *findConversionNameId(const FullySpecifiedType &type) const;
const Identifier *findIdentifier(const char *chars, int size) const;
const Identifier *identifier(const char *chars, int size);
diff --git a/src/libs/3rdparty/cplusplus/Scope.cpp b/src/libs/3rdparty/cplusplus/Scope.cpp
index 43d8c98965..dcafc0c066 100644
--- a/src/libs/3rdparty/cplusplus/Scope.cpp
+++ b/src/libs/3rdparty/cplusplus/Scope.cpp
@@ -71,6 +71,7 @@ public:
Symbol *lookat(const Identifier *id) const;
Symbol *lookat(OperatorNameId::Kind operatorId) const;
+ Symbol *lookat(const ConversionNameId *convId) const;
private:
/// Returns the hash value for the given Symbol.
@@ -181,6 +182,23 @@ Symbol *SymbolTable::lookat(OperatorNameId::Kind operatorId) const
return symbol;
}
+Symbol *SymbolTable::lookat(const ConversionNameId *convId) const
+{
+ if (!_hash)
+ return nullptr;
+
+ Symbol *symbol = _hash[0]; // See Symbol::HashCode
+ for (; symbol; symbol = symbol->_next) {
+ if (const Name *identity = symbol->unqualifiedName()) {
+ if (const ConversionNameId * const id = identity->asConversionNameId()) {
+ if (id->type().match(convId->type()))
+ break;
+ }
+ }
+ }
+ return symbol;
+}
+
void SymbolTable::rehash()
{
_hashSize <<= 1;
@@ -281,6 +299,9 @@ Symbol *Scope::find(const Identifier *id) const
Symbol *Scope::find(OperatorNameId::Kind operatorId) const
{ return _members ? _members->lookat(operatorId) : nullptr; }
+Symbol *Scope::find(const ConversionNameId *conv) const
+{ return _members ? _members->lookat(conv) : nullptr; }
+
/// Set the start offset of the scope
int Scope::startOffset() const
{ return _startOffset; }
diff --git a/src/libs/3rdparty/cplusplus/Scope.h b/src/libs/3rdparty/cplusplus/Scope.h
index c3b2a6ca37..39a10696a1 100644
--- a/src/libs/3rdparty/cplusplus/Scope.h
+++ b/src/libs/3rdparty/cplusplus/Scope.h
@@ -55,6 +55,7 @@ public:
Symbol *find(const Identifier *id) const;
Symbol *find(OperatorNameId::Kind operatorId) const;
+ Symbol *find(const ConversionNameId *conv) const;
/// Set the start offset of the scope
int startOffset() const;
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index 2658b87b32..abd9852884 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -765,10 +765,10 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
const TemplateNameId *templateId,
ClassOrNamespace *binding)
{
- if (! name) {
+ if (!name)
return;
- } else if (const OperatorNameId *op = name->asOperatorNameId()) {
+ if (const OperatorNameId *op = name->asOperatorNameId()) {
for (Symbol *s = scope->find(op->kind()); s; s = s->next()) {
if (! s->name())
continue;
@@ -786,8 +786,24 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
result->append(item);
}
+ return;
+ }
+
+ if (const ConversionNameId * const conv = name->asConversionNameId()) {
+ if (Symbol * const s = scope->find(conv)) {
+ LookupItem item;
+ item.setDeclaration(s);
+ item.setBinding(binding);
+
+ if (Symbol *inst = instantiateTemplateFunction(name, s->asTemplate()))
+ item.setType(inst->type());
+
+ result->append(item);
+ }
+ return;
+ }
- } else if (const Identifier *id = name->identifier()) {
+ if (const Identifier *id = name->identifier()) {
for (Symbol *s = scope->find(id); s; s = s->next()) {
if (s->isFriend())
continue; // skip friends
diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
index 7532b77e8d..5cf1e31d29 100644
--- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
+++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
@@ -579,6 +579,19 @@ void CppEditorPlugin::test_SwitchMethodDeclarationDefinition_data()
"float Test::var;\n"
"int Test::$var;\n"
"}\n");
+
+ QTest::newRow("conversionOperatorDecl2Def")
+ << _("struct Foo {\n"
+ " operator @int() const;\n"
+ "};\n")
+ << _("#include \"file.h\"\n"
+ "Foo::$operator int() const { return {}; }\n");
+ QTest::newRow("conversionOperatorDef2Decl")
+ << _("struct Foo {\n"
+ " $operator int() const;\n"
+ "};\n")
+ << _("#include \"file.h\"\n"
+ "Foo::@operator int() const { return {}; }\n");
}
void CppEditorPlugin::test_SwitchMethodDeclarationDefinition()
diff --git a/src/plugins/cpptools/symbolfinder.cpp b/src/plugins/cpptools/symbolfinder.cpp
index 6ee966161c..0c0c1f3d15 100644
--- a/src/plugins/cpptools/symbolfinder.cpp
+++ b/src/plugins/cpptools/symbolfinder.cpp
@@ -58,6 +58,7 @@ class FindMatchingDefinition: public SymbolVisitor
{
Symbol *_declaration = nullptr;
const OperatorNameId *_oper = nullptr;
+ const ConversionNameId *_conv = nullptr;
const bool _strict;
QList<Hit> _result;
@@ -65,8 +66,10 @@ public:
explicit FindMatchingDefinition(Symbol *declaration, bool strict)
: _declaration(declaration), _strict(strict)
{
- if (_declaration->name())
+ if (_declaration->name()) {
_oper = _declaration->name()->asOperatorNameId();
+ _conv = _declaration->name()->asConversionNameId();
+ }
}
const QList<Hit> result() const { return _result; }
@@ -75,10 +78,10 @@ public:
bool visit(Function *fun) override
{
- if (_oper) {
+ if (_oper || _conv) {
if (const Name *name = fun->unqualifiedName()) {
- if (_oper->match(name))
- _result.append({fun, true});
+ if ((_oper && _oper->match(name)) || (_conv && _conv->match(name)))
+ _result.append({fun, true});
}
} else if (Function *decl = _declaration->type()->asFunctionType()) {
if (fun->match(decl)) {
@@ -181,13 +184,18 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration,
continue;
if (!id) {
- if (!declaration->name())
- continue;
- const OperatorNameId *oper = declaration->name()->asOperatorNameId();
- if (!oper)
+ const Name * const name = declaration->name();
+ if (!name)
continue;
- if (!doc->control()->findOperatorNameId(oper->kind()))
+ if (const OperatorNameId * const oper = name->asOperatorNameId()) {
+ if (!doc->control()->findOperatorNameId(oper->kind()))
+ continue;
+ } else if (const ConversionNameId * const conv = name->asConversionNameId()) {
+ if (!doc->control()->findConversionNameId(conv->type()))
+ continue;
+ } else {
continue;
+ }
}
FindMatchingDefinition candidates(declaration, strict);