diff options
-rw-r--r-- | src/qmlcompiler/qqmljslinter.cpp | 1 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljslogger.cpp | 60 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljslogger_p.h | 18 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstypepropagator.cpp | 13 |
4 files changed, 68 insertions, 24 deletions
diff --git a/src/qmlcompiler/qqmljslinter.cpp b/src/qmlcompiler/qqmljslinter.cpp index 91182e8f60..4d3eb8e9b5 100644 --- a/src/qmlcompiler/qqmljslinter.cpp +++ b/src/qmlcompiler/qqmljslinter.cpp @@ -221,6 +221,7 @@ bool QQmlJSLinter::lintFile(const QString &filename, const QString *fileContents jsonFix[u"charOffset"_qs] = static_cast<int>(fix.cutLocation.offset); jsonFix[u"length"_qs] = static_cast<int>(fix.cutLocation.length); jsonFix[u"replacement"_qs] = fix.replacementString; + jsonFix[u"isHint"] = fix.isHint; suggestions << jsonFix; } } diff --git a/src/qmlcompiler/qqmljslogger.cpp b/src/qmlcompiler/qqmljslogger.cpp index cba6a24d60..ce2f559c1a 100644 --- a/src/qmlcompiler/qqmljslogger.cpp +++ b/src/qmlcompiler/qqmljslogger.cpp @@ -28,6 +28,9 @@ #include "qqmljslogger_p.h" +#include <QtCore/qfile.h> +#include <QtCore/qfileinfo.h> + QT_BEGIN_NAMESPACE const QMap<QString, QQmlJSLogger::Option> &QQmlJSLogger::options() { @@ -133,7 +136,8 @@ static bool isMsgTypeLess(QtMsgType a, QtMsgType b) void QQmlJSLogger::log(const QString &message, QQmlJSLoggerCategory category, const QQmlJS::SourceLocation &srcLocation, QtMsgType type, bool showContext, - bool showFileName, const std::optional<FixSuggestion> &suggestion) + bool showFileName, const std::optional<FixSuggestion> &suggestion, + const QString overrideFileName) { if (isCategoryIgnored(category)) return; @@ -145,8 +149,9 @@ void QQmlJSLogger::log(const QString &message, QQmlJSLoggerCategory category, QString prefix; - if (!m_fileName.isEmpty() && showFileName) - prefix = m_fileName + QStringLiteral(":"); + if ((!overrideFileName.isEmpty() || !m_fileName.isEmpty()) && showFileName) + prefix = + (!overrideFileName.isEmpty() ? overrideFileName : m_fileName) + QStringLiteral(":"); if (srcLocation.isValid()) prefix += QStringLiteral("%1:%2:").arg(srcLocation.startLine).arg(srcLocation.startColumn); @@ -176,7 +181,7 @@ void QQmlJSLogger::log(const QString &message, QQmlJSLoggerCategory category, } if (srcLocation.isValid() && !m_code.isEmpty() && showContext) - printContext(srcLocation); + printContext(overrideFileName, srcLocation); if (suggestion.has_value()) printFix(suggestion.value()); @@ -198,9 +203,19 @@ void QQmlJSLogger::processMessages(const QList<QQmlJS::DiagnosticMessage> &messa m_output.write(QStringLiteral("---\n\n")); } -void QQmlJSLogger::printContext(const QQmlJS::SourceLocation &location) +void QQmlJSLogger::printContext(const QString &overrideFileName, + const QQmlJS::SourceLocation &location) { - IssueLocationWithContext issueLocationWithContext { m_code, location }; + QString code = m_code; + + if (!overrideFileName.isEmpty() && overrideFileName != QFileInfo(m_fileName).absolutePath()) { + QFile file(overrideFileName); + const bool success = file.open(QFile::ReadOnly); + Q_ASSERT(success); + code = QString::fromUtf8(file.readAll()); + } + + IssueLocationWithContext issueLocationWithContext { code, location }; if (const QStringView beforeText = issueLocationWithContext.beforeText(); !beforeText.isEmpty()) m_output.write(beforeText); @@ -224,33 +239,56 @@ void QQmlJSLogger::printContext(const QQmlJS::SourceLocation &location) void QQmlJSLogger::printFix(const FixSuggestion &fix) { + const QString currentFileAbsPath = QFileInfo(m_fileName).absolutePath(); + QString code = m_code; + QString currentFile; for (const auto &fixItem : fix.fixes) { m_output.writePrefixedMessage(fixItem.message, QtInfoMsg); if (!fixItem.cutLocation.isValid()) continue; - IssueLocationWithContext issueLocationWithContext { m_code, fixItem.cutLocation }; + if (fixItem.fileName == currentFile) { + // Nothing to do in this case, we've already read the code + } else if (fixItem.fileName.isEmpty() || fixItem.fileName == currentFileAbsPath) { + code = m_code; + } else { + QFile file(fixItem.fileName); + const bool success = file.open(QFile::ReadOnly); + Q_ASSERT(success); + code = QString::fromUtf8(file.readAll()); + currentFile = fixItem.fileName; + } + + IssueLocationWithContext issueLocationWithContext { code, fixItem.cutLocation }; if (const QStringView beforeText = issueLocationWithContext.beforeText(); !beforeText.isEmpty()) { m_output.write(beforeText); } - m_output.write(fixItem.replacementString, QtDebugMsg); + // The replacement string can be empty if we're only pointing something out to the user + QStringView replacementString = fixItem.replacementString.isEmpty() + ? issueLocationWithContext.issueText() + : fixItem.replacementString; + + // But if there's nothing to change it has to be a hint + if (fixItem.replacementString.isEmpty()) + Q_ASSERT(fixItem.isHint); + + m_output.write(replacementString, QtDebugMsg); m_output.write(issueLocationWithContext.afterText().toString() + u'\n'); int tabCount = issueLocationWithContext.beforeText().count(u'\t'); // Do not draw location indicator for multiline replacement strings - if (fixItem.replacementString.contains(u'\n')) + if (replacementString.contains(u'\n')) continue; m_output.write(u" "_qs.repeated( issueLocationWithContext.beforeText().length() - tabCount) + u"\t"_qs.repeated(tabCount) - + u"^"_qs.repeated(fixItem.replacementString.length()) - + u'\n'); + + u"^"_qs.repeated(fixItem.replacementString.length()) + u'\n'); } } diff --git a/src/qmlcompiler/qqmljslogger_p.h b/src/qmlcompiler/qqmljslogger_p.h index 462854225f..2ddcb2ac5a 100644 --- a/src/qmlcompiler/qqmljslogger_p.h +++ b/src/qmlcompiler/qqmljslogger_p.h @@ -122,6 +122,10 @@ struct FixSuggestion QString message; QQmlJS::SourceLocation cutLocation = QQmlJS::SourceLocation(); QString replacementString = QString(); + QString fileName = QString(); + // A Fix is a hint if it can not be automatically applied to fix an issue or only points out + // its origin + bool isHint = true; }; QList<Fix> fixes; }; @@ -233,10 +237,11 @@ public: */ void log(const QString &message, QQmlJSLoggerCategory category, const QQmlJS::SourceLocation &srcLocation, bool showContext = true, - bool showFileName = true, const std::optional<FixSuggestion> &suggestion = {}) + bool showFileName = true, const std::optional<FixSuggestion> &suggestion = {}, + const QString overrideFileName = QString()) { log(message, category, srcLocation, m_categoryLevels[category], showContext, showFileName, - suggestion); + suggestion, overrideFileName); } void processMessages(const QList<QQmlJS::DiagnosticMessage> &messages, @@ -257,12 +262,13 @@ public: QString fileName() const { return m_fileName; } private: - void printContext(const QQmlJS::SourceLocation &location); + void printContext(const QString &overrideFileName, const QQmlJS::SourceLocation &location); void printFix(const FixSuggestion &fix); - void log(const QString &message, QQmlJSLoggerCategory category, const QQmlJS::SourceLocation &, - QtMsgType type, bool showContext, bool showFileName, - const std::optional<FixSuggestion> &suggestion); + void log(const QString &message, QQmlJSLoggerCategory category, + const QQmlJS::SourceLocation &srcLocation, QtMsgType type, bool showContext, + bool showFileName, const std::optional<FixSuggestion> &suggestion, + const QString overrideFileName); QString m_fileName; QString m_code; diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index 52dd8df72f..fb7c40cf7a 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -340,7 +340,7 @@ void QQmlJSTypePropagator::handleUnqualifiedAccess(const QString &name, bool isM "function instead.\n") .arg(id.location.startLine) .arg(id.location.startColumn), - fixLocation, fixString + fixLocation, fixString, QString(), false }; } break; @@ -360,7 +360,7 @@ void QQmlJSTypePropagator::handleUnqualifiedAccess(const QString &name, bool isM name + QLatin1String(" is a member of a parent element\n") + QLatin1String(" You can qualify the access with its id " "to avoid this warning:\n"), - fixLocation, (id.isEmpty() ? u"<id>."_qs : (id + u'.')) + fixLocation, (id.isEmpty() ? u"<id>."_qs : (id + u'.')), QString(), id.isEmpty() }; if (id.isEmpty()) { @@ -677,11 +677,10 @@ void QQmlJSTypePropagator::propagatePropertyLookup(const QString &propertyName) QQmlJS::SourceLocation fixLocation = getCurrentSourceLocation(); fixLocation.length = 0; - suggestion.fixes << FixSuggestion::Fix { - u"Reference it by id instead:"_qs, - fixLocation, - id.isEmpty() ? u"<id>."_qs : (id + u'.') - }; + suggestion.fixes << FixSuggestion::Fix { u"Reference it by id instead:"_qs, + fixLocation, + id.isEmpty() ? u"<id>."_qs : (id + u'.'), + QString(), id.isEmpty() }; fixLocation = scope->sourceLocation(); fixLocation.length = 0; |