Skip to content

Commit 92d6f01

Browse files
committed
feat: 完善代码填充;
1 parent 3588afc commit 92d6f01

File tree

7 files changed

+180
-83
lines changed

7 files changed

+180
-83
lines changed

CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,9 @@ set(CLASS_SRC
312312
src/class/consolehighlighanim.cpp
313313
src/class/angellsp.h
314314
src/class/angellsp.cpp
315-
src/class/lsp.h)
315+
src/class/lsp.h
316+
src/class/resettabletimer.h
317+
src/class/resettabletimer.cpp)
316318

317319
set(INTERNAL_PLG_SRC
318320
src/class/wingangelapi.h src/class/wingangelapi.cpp
@@ -492,11 +494,13 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
492494
${PROJECT_SOURCES} ${app_icon_resource_windows})
493495
else()
494496
find_package(Qt6 REQUIRED COMPONENTS Widgets)
497+
find_package(Qt6 REQUIRED COMPONENTS Core)
495498

496499
qt_add_executable(WingHexExplorer2 MANUAL_FINALIZATION
497500
${PROJECT_SOURCES})
498501

499502
target_link_libraries(WingHexExplorer2 PRIVATE Qt6::Widgets)
503+
target_link_libraries(WingHexExplorer2 PRIVATE Qt6::Core)
500504
endif()
501505
endif()
502506

src/class/angellsp.cpp

Lines changed: 5 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,7 @@
66
#include <QJsonDocument>
77
#include <QJsonObject>
88

9-
AngelLsp::AngelLsp() {
10-
// create a single timer reused for completion debounce
11-
m_completionTimer = new QTimer(this);
12-
m_completionTimer->setSingleShot(true);
13-
connect(m_completionTimer, &QTimer::timeout, this, [this]() {
14-
// before sending new completion, cancel previous pending request if any
15-
if (m_lastCompletionRequestId != 0) {
16-
sendCancelRequest(m_lastCompletionRequestId);
17-
// do not reset id here; server may already have processed it
18-
}
19-
// send actual completion request (async, id returned)
20-
QJsonObject pos;
21-
pos["line"] = m_pendingCompletion.line;
22-
pos["character"] = m_pendingCompletion.character;
23-
QJsonObject p;
24-
p["textDocument"] = QJsonObject{{"uri", m_pendingCompletion.uri}};
25-
p["position"] = pos;
26-
int id = sendRequest("textDocument/completion", p);
27-
m_lastCompletionRequestId = id;
28-
// response will be delivered to handleIncomingMessage ->
29-
// requestFinished signal
30-
});
31-
}
9+
AngelLsp::AngelLsp() {}
3210

3311
AngelLsp &AngelLsp::instance() {
3412
static AngelLsp ins;
@@ -227,9 +205,9 @@ QJsonValue AngelLsp::requestResolve(const QJsonValue &symbol, int timeoutMs) {
227205
return sendRequestSync("completionItem/resolve", symbol, timeoutMs);
228206
}
229207

230-
int AngelLsp::sendRequest(const QString &method, const QJsonValue &params,
231-
int) {
232-
int id = m_nextId++;
208+
qint64 AngelLsp::sendRequest(const QString &method, const QJsonValue &params,
209+
int) {
210+
qint64 id = m_nextId++;
233211
QJsonObject obj;
234212
obj["jsonrpc"] = "2.0";
235213
obj["id"] = id;
@@ -261,7 +239,7 @@ void AngelLsp::changeDocument(const QString &uri, qint64 version,
261239

262240
QJsonValue AngelLsp::sendRequestSync(const QString &method,
263241
const QJsonValue &params, int timeoutMs) {
264-
int id = m_nextId++;
242+
qint64 id = m_nextId++;
265243
QJsonObject obj;
266244
obj["jsonrpc"] = "2.0";
267245
obj["id"] = id;
@@ -480,20 +458,6 @@ void AngelLsp::handleIncomingMessage(const QJsonObject &msg) {
480458
m_outstandingRequests.remove(id);
481459
}
482460

483-
// if this response is for a completion request, emit completionReceived
484-
if (!method.isEmpty() &&
485-
method == QStringLiteral("textDocument/completion")) {
486-
Q_EMIT completionReceived(payload);
487-
// if it matches the last completion id, clear it
488-
if (m_lastCompletionRequestId == id)
489-
m_lastCompletionRequestId = 0;
490-
}
491-
// if response matches lastCompletionRequestId but method mapping not
492-
// present, still check and clear
493-
if (m_lastCompletionRequestId == id) {
494-
m_lastCompletionRequestId = 0;
495-
}
496-
497461
if (m_pendingLoops.contains(id)) {
498462
QEventLoop *loop = m_pendingLoops[id];
499463
if (loop)
@@ -640,14 +604,3 @@ QJsonObject AngelLsp::jsonLSPDocLocation(const LSP::Location &loc) {
640604
r["character"] = loc.character;
641605
return r;
642606
}
643-
644-
void AngelLsp::requestCompletionDebounced(const QString &uri, int line,
645-
int character, int debounceMs) {
646-
// store latest requested position
647-
m_pendingCompletion.uri = uri;
648-
m_pendingCompletion.line = line;
649-
m_pendingCompletion.character = character;
650-
// restart debounce timer
651-
m_completionTimer->stop();
652-
m_completionTimer->start(debounceMs);
653-
}

src/class/angellsp.h

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,6 @@ class AngelLsp : public QObject {
3737

3838
void closeDocument(const QString &uri);
3939

40-
public:
41-
// Debounced completion: if user types quickly, use this so only one
42-
// completion fires after pause. debounceMs default 150ms (tweak to taste:
43-
// smaller for snappier UI, larger to reduce server load).
44-
void requestCompletionDebounced(const QString &uri, int line, int character,
45-
int debounceMs = 150);
46-
4740
public:
4841
// High-level feature wrappers (sync)
4942
QJsonValue requestDocumentSymbol(const QString &uri, int timeoutMs = 3000);
@@ -65,9 +58,9 @@ class AngelLsp : public QObject {
6558
private:
6659
// Generic request/notification
6760
// Returns request id
68-
int sendRequest(const QString &method,
69-
const QJsonValue &params = QJsonValue(),
70-
int /*timeoutMs*/ = 0);
61+
qint64 sendRequest(const QString &method,
62+
const QJsonValue &params = QJsonValue(),
63+
int /*timeoutMs*/ = 0);
7164

7265
// Blocking request
7366
QJsonValue sendRequestSync(const QString &method,
@@ -105,11 +98,6 @@ class AngelLsp : public QObject {
10598
void serverRequestReceived(const QString &method, const QJsonValue &params,
10699
int id);
107100

108-
// New: emitted when a completion response arrives from server (either
109-
// result or error). items: the "result" (or "error" if no result). For
110-
// typical successful completion, items is the completion list/array.
111-
void completionReceived(const QJsonValue &items);
112-
113101
public slots:
114102
// convenience: synchronous shutdown
115103
void shutdownAndExit();
@@ -136,23 +124,14 @@ private slots:
136124
QProcess *m_proc = nullptr;
137125
QByteArray m_stdoutBuffer;
138126

139-
int m_nextId = 1;
140-
QMap<int, QEventLoop *> m_pendingLoops;
141-
QMap<int, QJsonValue> m_pendingResponses;
127+
qint64 m_nextId = 1;
128+
QMap<qint64, QEventLoop *> m_pendingLoops;
129+
QMap<qint64, QJsonValue> m_pendingResponses;
142130

143-
QMap<int, QString> m_outstandingRequests; // map request id -> method
131+
QMap<qint64, QString> m_outstandingRequests; // map request id -> method
144132

145133
// Debounce/coalesce document change support
146134
QHash<QString, QTimer *> m_docTimers; // per-document debouncers
147-
148-
// Debounced completion support
149-
QTimer *m_completionTimer = nullptr;
150-
struct PendingCompletion {
151-
QString uri;
152-
int line = 0;
153-
int character = 0;
154-
} m_pendingCompletion;
155-
int m_lastCompletionRequestId = 0;
156135
};
157136

158137
#endif // ANGELLSP_H

src/class/ascompletion.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ AsCompletion::AsCompletion(WingCodeEdit *p) : WingCompleter(p) {
8282
});
8383

8484
p->installEventFilter(this);
85+
86+
_timer = new ResettableTimer(this);
87+
connect(_timer, &ResettableTimer::timeoutTriggered, this,
88+
&AsCompletion::onCodeComplete);
8589
}
8690

8791
AsCompletion::~AsCompletion() {}
@@ -140,6 +144,10 @@ bool AsCompletion::processTrigger(const QString &trigger,
140144
clearFunctionTip();
141145
}
142146

147+
if (!_ok) {
148+
return false;
149+
}
150+
143151
auto url = Utilities::getUrlString(editor->fileName());
144152
auto tc = editor->editor()->textCursor();
145153
auto &lsp = AngelLsp::instance();
@@ -171,10 +179,10 @@ bool AsCompletion::processTrigger(const QString &trigger,
171179

172180
auto ret = lsp.requestCompletion(url, line, character);
173181
auto nodes = parseCompletion(ret);
174-
175-
// TODO
176182
setModel(new CodeCompletionModel(nodes, this));
177183
setCompletionPrefix(prefix);
184+
_ok = false;
185+
_timer->reset(300);
178186

179187
return true;
180188
}
@@ -203,3 +211,5 @@ bool AsCompletion::eventFilter(QObject *watched, QEvent *event) {
203211
}
204212
return WingCompleter::eventFilter(watched, event);
205213
}
214+
215+
void AsCompletion::onCodeComplete() { _ok = true; }

src/class/ascompletion.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "WingCodeEdit/wingcompleter.h"
2222
#include "class/codeinfotip.h"
23+
#include "class/resettabletimer.h"
2324

2425
class AsCompletion : public WingCompleter {
2526
Q_OBJECT
@@ -50,8 +51,14 @@ class AsCompletion : public WingCompleter {
5051
public:
5152
virtual bool eventFilter(QObject *watched, QEvent *event) override;
5253

54+
private slots:
55+
void onCodeComplete();
56+
5357
private:
5458
QList<CodeInfoTip> _keywordNode;
59+
ResettableTimer *_timer;
60+
61+
bool _ok = true;
5562
};
5663

5764
#endif // _CPP_COMPLETION_H_

src/class/resettabletimer.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*==============================================================================
2+
** Copyright (C) 2024-2027 WingSummer
3+
**
4+
** This program is free software: you can redistribute it and/or modify it under
5+
** the terms of the GNU Affero General Public License as published by the Free
6+
** Software Foundation, version 3.
7+
**
8+
** This program is distributed in the hope that it will be useful, but WITHOUT
9+
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10+
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
11+
** details.
12+
**
13+
** You should have received a copy of the GNU Affero General Public License
14+
** along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
** =============================================================================
16+
*/
17+
18+
#include "resettabletimer.h"
19+
20+
#include <QDebug>
21+
22+
ResettableTimer::ResettableTimer(QObject *parent) : QObject(parent) {
23+
m_timer.setSingleShot(true);
24+
connect(&m_timer, &QTimer::timeout, this, &ResettableTimer::onTimeout);
25+
}
26+
27+
void ResettableTimer::start(int intervalMs) {
28+
if (intervalMs <= 0) {
29+
qWarning()
30+
<< "ResettableTimer::start called with non-positive interval:"
31+
<< intervalMs;
32+
return;
33+
}
34+
m_intervalMs = intervalMs;
35+
m_timer.start(m_intervalMs);
36+
}
37+
38+
void ResettableTimer::reset(int newIntervalMs) {
39+
if (newIntervalMs > 0) {
40+
m_intervalMs = newIntervalMs;
41+
}
42+
43+
if (m_intervalMs <= 0) {
44+
// nothing to start/restart
45+
qWarning() << "ResettableTimer::reset called but interval not set.";
46+
return;
47+
}
48+
49+
// restart works even if timer was about to fire
50+
m_timer.start(m_intervalMs);
51+
}
52+
53+
void ResettableTimer::stop() { m_timer.stop(); }
54+
55+
void ResettableTimer::triggerNow() {
56+
// Stop current timer (if running) then immediately call handler
57+
m_timer.stop();
58+
onTimeout();
59+
}
60+
61+
bool ResettableTimer::isActive() const { return m_timer.isActive(); }
62+
63+
int ResettableTimer::interval() const { return m_intervalMs; }
64+
65+
void ResettableTimer::setInterval(int intervalMs) {
66+
if (intervalMs <= 0) {
67+
qWarning() << "ResettableTimer::setInterval non-positive:"
68+
<< intervalMs;
69+
return;
70+
}
71+
m_intervalMs = intervalMs;
72+
if (m_timer.isActive()) {
73+
// restart with new interval
74+
m_timer.start(m_intervalMs);
75+
}
76+
}
77+
78+
void ResettableTimer::onTimeout() {
79+
// Timer single-shot -> it's stopped now.
80+
Q_EMIT timeoutTriggered();
81+
}

src/class/resettabletimer.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*==============================================================================
2+
** Copyright (C) 2024-2027 WingSummer
3+
**
4+
** This program is free software: you can redistribute it and/or modify it under
5+
** the terms of the GNU Affero General Public License as published by the Free
6+
** Software Foundation, version 3.
7+
**
8+
** This program is distributed in the hope that it will be useful, but WITHOUT
9+
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10+
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
11+
** details.
12+
**
13+
** You should have received a copy of the GNU Affero General Public License
14+
** along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
** =============================================================================
16+
*/
17+
18+
#ifndef RESETTABLETIMER_H
19+
#define RESETTABLETIMER_H
20+
21+
#include <QObject>
22+
23+
#include <QObject>
24+
#include <QTimer>
25+
26+
class ResettableTimer : public QObject {
27+
Q_OBJECT
28+
public:
29+
explicit ResettableTimer(QObject *parent = nullptr);
30+
31+
public slots:
32+
// Start with specified interval (ms). Replaces saved interval.
33+
void start(int intervalMs);
34+
35+
// Reset (restart) with previously set interval.
36+
// If newIntervalMs >= 0, update interval and restart with it.
37+
void reset(int newIntervalMs = -1);
38+
39+
// Stop the timer (no callback until start/reset again).
40+
void stop();
41+
42+
// Force immediate trigger (calls callback / emits signal).
43+
void triggerNow();
44+
45+
void setInterval(int intervalMs);
46+
47+
public:
48+
bool isActive() const;
49+
int interval() const;
50+
51+
signals:
52+
// Emitted when timeout happens.
53+
void timeoutTriggered();
54+
55+
private slots:
56+
void onTimeout();
57+
58+
private:
59+
QTimer m_timer;
60+
int m_intervalMs = 0; // last used interval in ms
61+
};
62+
63+
#endif // RESETTABLETIMER_H

0 commit comments

Comments
 (0)