Skip to content

Commit 83f433f

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

7 files changed

Lines changed: 232 additions & 83 deletions

File tree

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: 64 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() {}
@@ -107,6 +111,58 @@ QList<CodeInfoTip> AsCompletion::parseCompletion(const QJsonValue &v) {
107111
return ret;
108112
}
109113

114+
void AsCompletion::decodeTokenData(const QJsonArray &dataArray) {
115+
// int currentLine = 0;
116+
// int currentChar = 0;
117+
118+
// QHash<int, LineTokens> lineMap;
119+
120+
// // 每5个数字表示一个令牌
121+
// for (int i = 0; i < dataArray.size(); i += 5) {
122+
// if (i + 4 >= dataArray.size())
123+
// break;
124+
125+
// int deltaLine = dataArray[i].toInt();
126+
// int deltaStartChar = dataArray[i + 1].toInt();
127+
// int length = dataArray[i + 2].toInt();
128+
// int tokenType = dataArray[i + 3].toInt();
129+
// int tokenModifiers = dataArray[i + 4].toInt();
130+
131+
// // 计算绝对位置
132+
// currentLine += deltaLine;
133+
// if (deltaLine > 0) {
134+
// currentChar = deltaStartChar; // 新行,重置字符位置
135+
// } else {
136+
// currentChar += deltaStartChar; // 同一行,累加字符偏移
137+
// }
138+
139+
// // 创建令牌
140+
// SemanticToken token;
141+
// token.line = currentLine;
142+
// token.startChar = currentChar;
143+
// token.length = length;
144+
// token.tokenType = tokenType;
145+
// token.tokenModifiers = tokenModifiers;
146+
147+
// // 按行分组
148+
// if (!lineMap.contains(currentLine)) {
149+
// LineTokens lineTokens;
150+
// lineTokens.lineNumber = currentLine;
151+
// lineMap[currentLine] = lineTokens;
152+
// }
153+
154+
// lineMap[currentLine].tokens.append(token);
155+
// }
156+
157+
// // 将哈希表中的行转换为有序向量
158+
// QList<int> lineNumbers = lineMap.keys();
159+
// std::sort(lineNumbers.begin(), lineNumbers.end());
160+
161+
// for (int lineNum : lineNumbers) {
162+
// result.lines.append(lineMap[lineNum]);
163+
// }
164+
}
165+
110166
QString AsCompletion::wordSeperators() const {
111167
static QString eow(QStringLiteral("~!@$%^&*()_+{}|\"<>?,/;'[]\\-="));
112168
return eow;
@@ -140,6 +196,10 @@ bool AsCompletion::processTrigger(const QString &trigger,
140196
clearFunctionTip();
141197
}
142198

199+
if (!_ok) {
200+
return false;
201+
}
202+
143203
auto url = Utilities::getUrlString(editor->fileName());
144204
auto tc = editor->editor()->textCursor();
145205
auto &lsp = AngelLsp::instance();
@@ -171,10 +231,10 @@ bool AsCompletion::processTrigger(const QString &trigger,
171231

172232
auto ret = lsp.requestCompletion(url, line, character);
173233
auto nodes = parseCompletion(ret);
174-
175-
// TODO
176234
setModel(new CodeCompletionModel(nodes, this));
177235
setCompletionPrefix(prefix);
236+
_ok = false;
237+
_timer->reset(300);
178238

179239
return true;
180240
}
@@ -203,3 +263,5 @@ bool AsCompletion::eventFilter(QObject *watched, QEvent *event) {
203263
}
204264
return WingCompleter::eventFilter(watched, event);
205265
}
266+
267+
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+
}

0 commit comments

Comments
 (0)