6#include <QtLanguageServer/private/qlanguageserverspec_p.h>
7#include <QtQmlCompiler/private/qqmljslinter_p.h>
8#include <QtQmlCompiler/private/qqmljslogger_p.h>
9#include <QtCore/qlibraryinfo.h>
10#include <QtCore/qtimer.h>
11#include <QtCore/qdebug.h>
26 return DiagnosticSeverity::Hint;
28 return DiagnosticSeverity::Information;
30 return DiagnosticSeverity::Warning;
35 return DiagnosticSeverity::Error;
40 LSPPartialResponse<std::variant<
QList<std::variant<Command, CodeAction>>, std::nullptr_t>,
41 QList<std::variant<Command, CodeAction>>> &&response)
45 for (
const Diagnostic &diagnostic :
params.context.diagnostics) {
46 if (!diagnostic.data.has_value())
49 const auto &
data = diagnostic.
data.value();
51 int version =
data[u
"version"].toInt();
56 for (
const QJsonValue &suggestion : suggestions) {
57 QString replacement = suggestion[u
"replacement"].toString();
58 message += suggestion[u
"message"].toString() + u
"\n";
61 textEdit.range = { Position { suggestion[u
"lspBeginLine"].toInt(),
62 suggestion[u
"lspBeginCharacter"].toInt() },
63 Position { suggestion[u
"lspEndLine"].toInt(),
64 suggestion[u
"lspEndCharacter"].toInt() } };
67 TextDocumentEdit textDocEdit;
68 textDocEdit.textDocument = {
params.textDocument, version };
75 edit.documentChanges = edits;
78 action.kind = u
"refactor.rewrite"_s.toUtf8();
80 action.title =
message.toUtf8();
82 responseData.
append(action);
85 response.sendResponse(responseData);
88void QmlLintSuggestions::registerHandlers(
QLanguageServer *, QLanguageServerProtocol *protocol)
93void QmlLintSuggestions::setupCapabilities(
const QLspSpecification::InitializeParams &,
94 QLspSpecification::InitializeResult &serverInfo)
96 serverInfo.capabilities.codeActionProvider =
true;
100 : m_server(
server), m_codeModel(codeModel)
108 const int maxInvalidMsec = 4000;
109 qCDebug(lintLog) <<
"diagnose start";
112 std::optional<int> version;
118 qCDebug(lspServerLog) <<
"skipped update of " <<
url <<
"unchanged valid doc";
148 qCDebug(lintLog) <<
"has doc, do real lint";
161 linter.
lintFile(filename, &fileContents, silent,
nullptr, imports, qmltypesFiles,
163 auto addLength = [&fileContents](Position &
position,
int startOffset,
int length) {
166 if (iEnd >
int(fileContents.
size()))
167 iEnd = fileContents.
size();
169 if (fileContents.
at(
i) == u
'\n') {
172 if (
i + 1 < iEnd && fileContents.
at(
i) == u
'\r')
181 auto messageToDiagnostic = [&addLength, &version](
const Message &
message) {
182 Diagnostic diagnostic;
184 Range &
range = diagnostic.range;
193 diagnostic.message =
message.message.toUtf8();
196 auto suggestion =
message.fixSuggestion;
197 if (suggestion.has_value()) {
203 const int line =
cut.isValid() ?
cut.startLine - 1 : 0;
204 const int column =
cut.isValid() ?
cut.startColumn - 1 : 0;
207 object.insert(
"lspBeginLine"_L1,
line);
208 object.insert(
"lspBeginCharacter"_L1,
column);
214 object.
insert(
"lspEndLine"_L1,
end.line);
215 object.
insert(
"lspEndCharacter"_L1,
end.character);
217 object.
insert(
"message"_L1, suggestion->fixDescription());
218 object.
insert(
"replacement"_L1, suggestion->replacement());
220 fixedSuggestions <<
object;
222 data[u
"suggestions"] = fixedSuggestions;
225 data[u
"version"] = version.value();
227 diagnostic.data =
data;
233 Diagnostic diagnostic;
237 Range &
range = diagnostic.range;
243 diagnostic.source =
"domParsing";
245 diagnostics.
append(diagnostic);
252 for (
const auto &messages : { logger->infos(), logger->warnings(), logger->errors() }) {
257 if (diagnostics.
size() != nDiagnostics && imports.size() == 1) {
258 Diagnostic diagnostic;
259 diagnostic.severity = DiagnosticSeverity::Warning;
260 Range &
range = diagnostic.range;
264 Position &positionEnd =
range.end;
265 positionEnd.line = 1;
267 "qmlls could not find a build directory, without a build directory "
268 "containing a current build there could be spurious warnings, you might "
269 "want to pass the --build-dir <buildDir> option to qmlls, or set the "
270 "environment variable QMLLS_BUILD_DIRS.";
272 diagnostics.
append(diagnostic);
276 PublishDiagnosticsParams diagnosticParams;
277 diagnosticParams.uri =
url;
278 diagnosticParams.diagnostics = diagnostics;
279 diagnosticParams.version = version;
281 m_server->
protocol()->notifyPublishDiagnostics(diagnosticParams);
283 << diagnosticParams.diagnostics.
size() <<
"issues"
284 << QTypedJson::toJsonValue(diagnosticParams);
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString toString(const QString &defaultValue={}) const
Returns the string value stored in this QCborValue, if it is of the string type.
static QDateTime currentDateTime()
This is an overloaded member function, provided for convenience. It differs from the above function o...
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
Implements a server for the language server protocol.
QLanguageServerProtocol * protocol()
constexpr const char * data() const noexcept
constexpr qsizetype size() const noexcept
static QString path(LibraryPath p)
qsizetype size() const noexcept
void append(parameter_type t)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
const QQmlJSLogger * logger() const
LintResult lintFile(const QString &filename, const QString *fileContents, const bool silent, QJsonArray *json, const QStringList &qmlImportPaths, const QStringList &qmldirFiles, const QStringList &resourceFiles, const QList< QQmlJS::LoggerCategory > &categories)
bool iterateErrors(function_ref< bool(DomItem source, ErrorMessage msg)> visitor, bool iterate, Path inPath=Path())
QString canonicalFilePath()
DomItem field(QStringView name)
Represents an error message connected to the dom.
\macro QT_RESTRICTED_CAST_FROM_ASCII
qsizetype size() const
Returns the number of characters in this string.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
QString & insert(qsizetype i, QChar c)
QByteArray toUtf8() const &
bool singleShot
whether the timer is a single-shot timer
std::optional< int > docVersion
std::optional< int > validDocVersion
QQmlJS::Dom::DomItem validDoc
OpenDocumentSnapshot snapshotByUrl(const QByteArray &url)
QStringList buildPathsForFileUrl(const QByteArray &url)
void updatedSnapshot(const QByteArray &url)
void diagnose(const QByteArray &uri)
Combined button and popup list for selecting options.
static void codeActionHandler(const QByteArray &, const CodeActionParams ¶ms, LSPPartialResponse< std::variant< QList< std::variant< Command, CodeAction > >, std::nullptr_t >, QList< std::variant< Command, CodeAction > > > &&response)
static DiagnosticSeverity severityFromMsgType(QtMsgType t)
static jboolean cut(JNIEnv *, jobject)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage return DBusPendingCall DBusPendingCall return DBusPendingCall return dbus_int32_t return DBusServer * server
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLenum GLuint GLenum GLsizei length
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei void GLsizei void * column
GLsizei GLenum * categories
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
QUrl url("example.com")
[constructor-url-reference]
QGraphicsWidget * textEdit
std::optional< QDateTime > invalidUpdatesSince
std::optional< int > version