diff options
author | Olivier De Cannière <olivier.decanniere@qt.io> | 2024-04-02 11:23:56 +0200 |
---|---|---|
committer | Olivier De Cannière <olivier.decanniere@qt.io> | 2024-04-17 12:27:36 +0200 |
commit | 779d60cc432c4fc1b71c41db0f73eec309e5ee14 (patch) | |
tree | c4c2955caaa9b869ce46aab7efff4b2ebd4e4d3b | |
parent | f0d265e3f52e25b1081e56b5ce811376be6f6c51 (diff) |
QQmlJS: Store method's source location and expose it in QQmlSA
This is useful for tooling like Axivion and can help with better error
messages.
Change-Id: Ic63afd2eeb4ee3627d05303c2518fa90282fb7ab
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 3 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsmetatypes_p.h | 5 | ||||
-rw-r--r-- | src/qmlcompiler/qqmlsa.cpp | 14 | ||||
-rw-r--r-- | src/qmlcompiler/qqmlsa.h | 1 | ||||
-rw-r--r-- | src/qmlcompiler/qqmlsa_p.h | 1 | ||||
-rw-r--r-- | tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml | 16 | ||||
-rw-r--r-- | tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp | 30 |
7 files changed, 70 insertions, 0 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index ff942886de..25d5944be2 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -1590,6 +1590,8 @@ bool QQmlJSImportVisitor::visit(UiPublicMember *publicMember) QQmlJSMetaMethod method; method.setMethodType(QQmlJSMetaMethodType::Signal); method.setMethodName(publicMember->name.toString()); + method.setSourceLocation(combine(publicMember->firstSourceLocation(), + publicMember->lastSourceLocation())); while (param) { method.addParameter( QQmlJSMetaParameter( @@ -1725,6 +1727,7 @@ void QQmlJSImportVisitor::visitFunctionExpressionHelper(QQmlJS::AST::FunctionExp if (!name.isEmpty()) { QQmlJSMetaMethod method(name); method.setMethodType(QQmlJSMetaMethodType::Method); + method.setSourceLocation(combine(fexpr->firstSourceLocation(), fexpr->lastSourceLocation())); if (!m_pendingMethodAnnotations.isEmpty()) { method.setAnnotations(m_pendingMethodAnnotations); diff --git a/src/qmlcompiler/qqmljsmetatypes_p.h b/src/qmlcompiler/qqmljsmetatypes_p.h index 547a814a8d..0ea7020a2d 100644 --- a/src/qmlcompiler/qqmljsmetatypes_p.h +++ b/src/qmlcompiler/qqmljsmetatypes_p.h @@ -221,6 +221,9 @@ public: QString methodName() const { return m_name; } void setMethodName(const QString &name) { m_name = name; } + QQmlJS::SourceLocation sourceLocation() const { return m_sourceLocation; } + void setSourceLocation(QQmlJS::SourceLocation location) { m_sourceLocation = location; } + QQmlJSMetaReturnType returnValue() const { return m_returnType; } void setReturnValue(const QQmlJSMetaReturnType returnValue) { m_returnType = returnValue; } QString returnTypeName() const { return m_returnType.typeName(); } @@ -338,6 +341,8 @@ public: private: QString m_name; + QQmlJS::SourceLocation m_sourceLocation; + QQmlJSMetaReturnType m_returnType; QList<QQmlJSMetaParameter> m_parameters; QList<QQmlJSAnnotation> m_annotations; diff --git a/src/qmlcompiler/qqmlsa.cpp b/src/qmlcompiler/qqmlsa.cpp index 00bb279723..d2d0e6a74e 100644 --- a/src/qmlcompiler/qqmlsa.cpp +++ b/src/qmlcompiler/qqmlsa.cpp @@ -314,6 +314,11 @@ QString MethodPrivate::methodName() const return m_method.methodName(); } +QQmlSA::SourceLocation MethodPrivate::sourceLocation() const +{ + return QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(m_method.sourceLocation()); +} + MethodType MethodPrivate::methodType() const { return m_method.methodType(); @@ -376,6 +381,15 @@ MethodType Method::methodType() const return d->methodType(); } +/*! + Returns the location in the QML code where this method is defined. + */ +QQmlSA::SourceLocation Method::sourceLocation() const +{ + Q_D(const Method); + return d->sourceLocation(); +} + bool Method::operatorEqualsImpl(const Method &lhs, const Method &rhs) { return lhs.d_func()->m_method == rhs.d_func()->m_method; diff --git a/src/qmlcompiler/qqmlsa.h b/src/qmlcompiler/qqmlsa.h index 42878031ba..e63f9ea5ab 100644 --- a/src/qmlcompiler/qqmlsa.h +++ b/src/qmlcompiler/qqmlsa.h @@ -138,6 +138,7 @@ public: ~Method(); QString methodName() const; + QQmlSA::SourceLocation sourceLocation() const; MethodType methodType() const; friend bool operator==(const Method &lhs, const Method &rhs) diff --git a/src/qmlcompiler/qqmlsa_p.h b/src/qmlcompiler/qqmlsa_p.h index 2388279551..9c9f557e22 100644 --- a/src/qmlcompiler/qqmlsa_p.h +++ b/src/qmlcompiler/qqmlsa_p.h @@ -121,6 +121,7 @@ public: MethodPrivate(Method *, const MethodPrivate &); QString methodName() const; + QQmlSA::SourceLocation sourceLocation() const; MethodType methodType() const; static QQmlSA::Method createMethod(const QQmlJSMetaMethod &); diff --git a/tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml b/tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml new file mode 100644 index 0000000000..52841e323c --- /dev/null +++ b/tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml @@ -0,0 +1,16 @@ +import QtQml + +QtObject { + function f1() { } + function f2(a) { } + function f3(a: int) { } + function f4(a, b) { } + function f5(a, b): void { } + function f6(a, b, c): void { + // Nothing + } + + signal s1() + signal s2(a: int) + signal s3(a: int, b: string) +} diff --git a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp index 60c0da78de..db81c77206 100644 --- a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp +++ b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp @@ -114,6 +114,7 @@ private Q_SLOTS: void attachedTypeResolution(); void builtinTypeResolution_data(); void builtinTypeResolution(); + void methodAndSignalSourceLocation(); public: tst_qqmljsscope() @@ -929,5 +930,34 @@ void tst_qqmljsscope::builtinTypeResolution() QCOMPARE(element.isNull(), !valid); } +void tst_qqmljsscope::methodAndSignalSourceLocation() +{ + QmlIR::Document document(false); + auto jsscope = run(u"methodAndSignalSourceLocation.qml"_s, false); + + std::array<std::array<int, 9>, 2> offsetsByLineEnding = { + std::array{ 29, 51, 74, 102, 128, 160, 219, 235, 257 }, // 1 char line endings + std::array{ 32, 55, 79, 108, 135, 168, 231, 248, 271 } // 2 char line endinds + }; + + // Try to detect the size of line endings as they lead to different source locations + auto offset1 = jsscope->methods("f1")[0].sourceLocation().offset; + QVERIFY(offset1 == 29 || offset1 == 32); + bool oneCharEndings = offset1 == 29; + std::array<int, 9> &offsets = oneCharEndings ? offsetsByLineEnding[0] : offsetsByLineEnding[1]; + + using namespace QQmlJS; + QCOMPARE(jsscope->methods("f1")[0].sourceLocation(), SourceLocation(offsets[0], 17, 4, 5)); + QCOMPARE(jsscope->methods("f2")[0].sourceLocation(), SourceLocation(offsets[1], 18, 5, 5)); + QCOMPARE(jsscope->methods("f3")[0].sourceLocation(), SourceLocation(offsets[2], 23, 6, 5)); + QCOMPARE(jsscope->methods("f4")[0].sourceLocation(), SourceLocation(offsets[3], 21, 7, 5)); + QCOMPARE(jsscope->methods("f5")[0].sourceLocation(), SourceLocation(offsets[4], 27, 8, 5)); + QCOMPARE(jsscope->methods("f6")[0].sourceLocation(), SourceLocation(offsets[5], oneCharEndings ? 53 : 55, 9, 5)); + + QCOMPARE(jsscope->methods("s1")[0].sourceLocation(), SourceLocation(offsets[6], 11, 13, 5)); + QCOMPARE(jsscope->methods("s2")[0].sourceLocation(), SourceLocation(offsets[7], 17, 14, 5)); + QCOMPARE(jsscope->methods("s3")[0].sourceLocation(), SourceLocation(offsets[8], 28, 15, 5)); +} + QTEST_MAIN(tst_qqmljsscope) #include "tst_qqmljsscope.moc" |