Skip to content

Commit f662fc5

Browse files
feat: Add TypedSymbol
This symbol has information about the type of whatever it represents. Care has also been taken to support pointers, const-qualifiers and other type specifiers.
1 parent 8c0e224 commit f662fc5

File tree

9 files changed

+155
-2
lines changed

9 files changed

+155
-2
lines changed

docs/API/knut/typedsymbol.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# TypedSymbol
2+
3+
Represents a symbol with a type [More...](#detailed-description)
4+
5+
```qml
6+
import Knut
7+
```
8+
9+
## Properties
10+
11+
| | Name |
12+
|-|-|
13+
|string|**[type](#type)**|
14+
15+
## Detailed Description
16+
17+
This symbol has a type associated with it, like a variable or a member of a class.
18+
19+
## Property Documentation
20+
21+
#### <a name="type"></a>string **type**
22+
23+
The type of this symbol.
24+
25+
The type is the part of the symbol that describes what kind of value it holds. For example, the type of a variable.
26+
This symbol will extract the type as-written in the original source, but with whitespace
27+
[simplified](https://doc.qt.io/qt-6/qstring.html#simplified). So if e.g. the source code is `const string &`, it
28+
will be extracted as `const string &`. The type will **not** be resolved to a fully qualified path (like
29+
`std::string` for the previous example).
30+
31+
This property is read-only.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ nav:
5454
- QueryCapture: API/knut/querycapture.md
5555
- QueryMatch: API/knut/querymatch.md
5656
- Symbol: API/knut/symbol.md
57+
- TypedSymbol: API/knut/typedsymbol.md
5758
- CppDocument:
5859
- CppDocument: API/knut/cppdocument.md
5960
- DataExchange: API/knut/dataexchange.md

src/core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ set(PROJECT_SOURCES
9494
textdocument_p.h
9595
texteditor.h
9696
texteditor.cpp
97+
typedsymbol.h
98+
typedsymbol.cpp
9799
qtuidocument.h
98100
qtuidocument.cpp
99101
qttsdocument.h

src/core/cppdocument.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,13 @@ auto queryMemberSymbols(CodeDocument *const document) -> QList<Core::Symbol *>
120120
auto fieldIdentifier = "(field_identifier) @name @selectionRange";
121121
auto members = document->query(QString(R"EOF(
122122
(field_declaration
123-
type: (_) @type
123+
(type_qualifier)? @type @typeAndName
124+
type: (_) @type @typeAndName
124125
declarator: [
125126
%1
126127
(_ %1) @decl_type
127128
(_ (_ %1) @decl_type) @decl_type
128-
]
129+
] @typeAndName
129130
; We need to filter out functions, they are already captured
130131
; by the functionSymbols query
131132
(#not_is? @decl_type function_declarator)) @range)EOF")

src/core/symbol.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "functionsymbol.h"
1515
#include "logger.h"
1616
#include "project.h"
17+
#include "typedsymbol.h"
1718
#include "utils/log.h"
1819

1920
#include <kdalgorithms.h>
@@ -101,6 +102,9 @@ Symbol *Symbol::makeSymbol(QObject *parent, const QueryMatch &match, Kind kind)
101102
if (kind == Class || kind == Struct) {
102103
return new ClassSymbol(parent, match, kind);
103104
}
105+
if (kind == Field || kind == Variable) {
106+
return new TypedSymbol(parent, match, kind);
107+
}
104108
return new Symbol(parent, match, kind);
105109
}
106110

src/core/typedsymbol.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include "typedsymbol.h"
2+
3+
#include <kdalgorithms.h>
4+
5+
namespace Core {
6+
7+
/*!
8+
* \qmltype TypedSymbol
9+
* \brief Represents a symbol with a type
10+
* \inqmlmodule Knut
11+
* \ingroup CodeDocument
12+
*
13+
* This symbol has a type associated with it, like a variable or a member of a class.
14+
*/
15+
16+
/*!
17+
* \qmlproperty string TypedSymbol::type
18+
* The type of this symbol.
19+
*
20+
* The type is the part of the symbol that describes what kind of value it holds. For example, the type of a variable.
21+
* This symbol will extract the type as-written in the original source, but with whitespace
22+
* [simplified](https://doc.qt.io/qt-6/qstring.html#simplified). So if e.g. the source code is `const string &`, it
23+
* will be extracted as `const string &`. The type will **not** be resolved to a fully qualified path (like
24+
* `std::string` for the previous example).
25+
*
26+
* This property is read-only.
27+
*/
28+
29+
TypedSymbol::TypedSymbol(QObject *parent, const QueryMatch &match, Kind kind)
30+
: Symbol(parent, match, kind)
31+
{
32+
// C++ has a strange way of parsing, where pointer and reference specifiers are parsed as a parent
33+
// of the identifier, and not part of the type. The easiest way to remedy this is to get the whole
34+
// range spanning the type and name and then erase the name.
35+
auto typeAndName = match.getAllJoined("typeAndName");
36+
if (typeAndName.isValid()) {
37+
m_type = typeAndName.textExcept(match.get("name")).simplified();
38+
} else {
39+
m_type = kdalgorithms::transformed(match.getAll("type"), &RangeMark::text).join(" ").simplified();
40+
}
41+
}
42+
43+
QString TypedSymbol::type() const
44+
{
45+
return m_type;
46+
}
47+
48+
}

src/core/typedsymbol.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#include "symbol.h"
4+
5+
namespace Core {
6+
7+
class TypedSymbol : public Symbol
8+
{
9+
Q_OBJECT
10+
11+
Q_PROPERTY(QString type READ type CONSTANT)
12+
13+
public:
14+
QString type() const;
15+
16+
private:
17+
friend class Symbol;
18+
TypedSymbol(QObject *parent, const QueryMatch &match, Kind kind);
19+
20+
QString m_type;
21+
};
22+
23+
}

test_data/tst_symbol/typedsymbol.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
#include <string>
4+
5+
class TestClass {
6+
private:
7+
void *m_ptr;
8+
const std::string &m_lvalue_reference;
9+
std::string&& m_rvalue_reference;
10+
const class T*const m_const_ptr;
11+
};

tests/tst_symbol.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "core/knutcore.h"
1616
#include "core/project.h"
1717
#include "core/symbol.h"
18+
#include "core/typedsymbol.h"
1819

1920
#include <QTest>
2021
#include <QThread>
@@ -172,6 +173,14 @@ private slots:
172173
QCOMPARE(members.at(2)->kind(), Core::Symbol::Method);
173174
QCOMPARE(members.last()->name(), "MyObject::m_enum");
174175
QCOMPARE(members.last()->kind(), Core::Symbol::Field);
176+
177+
auto typedsymbol = qobject_cast<Core::TypedSymbol *>(members.at(8));
178+
QVERIFY(typedsymbol);
179+
QCOMPARE(typedsymbol->type(), "std::string");
180+
181+
typedsymbol = qobject_cast<Core::TypedSymbol *>(members.last());
182+
QVERIFY(typedsymbol);
183+
QCOMPARE(typedsymbol->type(), "MyEnum");
175184
}
176185

177186
void references()
@@ -225,6 +234,29 @@ private slots:
225234
}),
226235
6);
227236
}
237+
238+
void typedSymbol()
239+
{
240+
241+
Core::KnutCore core;
242+
Core::Project::instance()->setRoot(Test::testDataPath() + "/tst_symbol/");
243+
244+
auto codeDocument = qobject_cast<Core::CodeDocument *>(Core::Project::instance()->open("typedsymbol.h"));
245+
QVERIFY(codeDocument);
246+
247+
auto testTypedSymbol = [&codeDocument](const QString &symbolName, const QString &expectedType) {
248+
auto symbol = codeDocument->findSymbol(symbolName);
249+
QVERIFY(symbol);
250+
auto typedSymbol = qobject_cast<Core::TypedSymbol *>(symbol);
251+
QVERIFY(typedSymbol);
252+
QCOMPARE(typedSymbol->type(), expectedType);
253+
};
254+
255+
testTypedSymbol("TestClass::m_ptr", "void *");
256+
testTypedSymbol("TestClass::m_lvalue_reference", "const std::string &");
257+
testTypedSymbol("TestClass::m_rvalue_reference", "std::string&&");
258+
testTypedSymbol("TestClass::m_const_ptr", "const class T*const");
259+
}
228260
};
229261

230262
QTEST_MAIN(TestSymbol)

0 commit comments

Comments
 (0)