1 /**
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <gtest/gtest.h>
17
18 #include "lsp_api_test.h"
19 #include "lsp/include/internal_api.h"
20 #include "lsp/include/todo_comments.h"
21
22 namespace {
23 // NOLINTBEGIN
24 using ark::es2panda::lsp::Initializer;
25
26 class TodoCommentsTest : public LSPAPITests {};
27
TEST_F(TodoCommentsTest,GetTodoCommentsSimpleTodo)28 TEST_F(TodoCommentsTest, GetTodoCommentsSimpleTodo)
29 {
30 const time_t kDesignatedThrottleTime = 123;
31 const int kDescriptorPriority = 1;
32 const int kExpectedSize = 1;
33 const char *const kTodoTag = "TODO";
34 const char *const kFileName = "simple-todo.sts";
35 const char *const kFileContent = "// TODO: Fix this";
36 const char *const kExpectedMessage = "TODO: Fix this";
37
38 using ark::es2panda::ir::AstNode;
39 using ark::es2panda::public_lib::Context;
40 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
41
42 Initializer initializer = Initializer();
43 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
44
45 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
46 ark::es2panda::lsp::TodoCommentDescriptor(kTodoTag, kDescriptorPriority)};
47
48 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
49
50 ASSERT_EQ(comments.size(), kExpectedSize);
51 EXPECT_EQ(comments[0].GetCommentDescriptor().GetText(), kTodoTag);
52 EXPECT_EQ(comments[0].GetMessage(), kExpectedMessage);
53
54 initializer.DestroyContext(ctx);
55 }
56
TEST_F(TodoCommentsTest,GetTodoCommentsSimpleTodoWithName)57 TEST_F(TodoCommentsTest, GetTodoCommentsSimpleTodoWithName)
58 {
59 const time_t kDesignatedThrottleTime = 123;
60 const int kDescriptorPriority = 1;
61 const int kExpectedSize = 1;
62 const char *const kTodoTag = "TODO";
63 const char *const kFileName = "simple-todo-name.sts";
64 const char *const kFileContent = "// TODO(name): Fix this";
65 const char *const kExpectedMessage = "TODO(name): Fix this";
66
67 using ark::es2panda::ir::AstNode;
68 using ark::es2panda::public_lib::Context;
69 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
70
71 Initializer initializer = Initializer();
72 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
73
74 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
75 ark::es2panda::lsp::TodoCommentDescriptor(kTodoTag, kDescriptorPriority)};
76
77 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
78
79 ASSERT_EQ(comments.size(), kExpectedSize);
80 EXPECT_EQ(comments[0].GetCommentDescriptor().GetText(), kTodoTag);
81 EXPECT_EQ(comments[0].GetMessage(), kExpectedMessage);
82
83 initializer.DestroyContext(ctx);
84 }
85
TEST_F(TodoCommentsTest,GetTodoCommentsSimpleHack)86 TEST_F(TodoCommentsTest, GetTodoCommentsSimpleHack)
87 {
88 const time_t kDesignatedThrottleTime = 123;
89 const int kDescriptorPriority = 1;
90 const int kExpectedSize = 1;
91 const char *const kHackTag = "HACK";
92 const char *const kFileName = "simple-hack.sts";
93 const char *const kFileContent = "// HACK: Needs work";
94 const char *const kExpectedMessage = "HACK: Needs work";
95
96 using ark::es2panda::ir::AstNode;
97 using ark::es2panda::public_lib::Context;
98 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
99
100 Initializer initializer = Initializer();
101 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
102
103 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
104 ark::es2panda::lsp::TodoCommentDescriptor(kHackTag, kDescriptorPriority)};
105
106 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
107
108 ASSERT_EQ(comments.size(), kExpectedSize);
109 EXPECT_EQ(comments[0].GetCommentDescriptor().GetText(), kHackTag);
110 EXPECT_EQ(comments[0].GetMessage(), kExpectedMessage);
111
112 initializer.DestroyContext(ctx);
113 }
114
TEST_F(TodoCommentsTest,GetTodoCommentsBlockCommentTodo)115 TEST_F(TodoCommentsTest, GetTodoCommentsBlockCommentTodo)
116 {
117 const time_t kDesignatedThrottleTime = 123;
118 const int kDescriptorPriority = 1;
119 const int kExpectedSize = 1;
120 const char *const kTodoTag = "TODO";
121 const char *const kFileName = "block-comment.sts";
122 const char *const kFileContent = "/* TODO: Fix this */";
123 const char *const kExpectedMessage = "TODO: Fix this ";
124
125 using ark::es2panda::ir::AstNode;
126 using ark::es2panda::public_lib::Context;
127 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
128
129 Initializer initializer = Initializer();
130 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
131
132 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
133 ark::es2panda::lsp::TodoCommentDescriptor(kTodoTag, kDescriptorPriority)};
134
135 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
136
137 ASSERT_EQ(comments.size(), kExpectedSize);
138 EXPECT_EQ(comments[0].GetCommentDescriptor().GetText(), kTodoTag);
139 EXPECT_EQ(comments[0].GetMessage(), kExpectedMessage);
140
141 initializer.DestroyContext(ctx);
142 }
143
TEST_F(TodoCommentsTest,GetTodoCommentsMultiLineBlockComment)144 TEST_F(TodoCommentsTest, GetTodoCommentsMultiLineBlockComment)
145 {
146 const time_t kDesignatedThrottleTime = 123;
147 const int kDescriptorPriority = 1;
148 const int kExpectedSize = 1;
149 const char *const kTodoTag = "TODO";
150 const char *const kFileName = "multiline-block-comment.sts";
151 const char *const kFileContent = "/*\n * TODO: Multi-line fix\n */";
152 const char *const kExpectedMessage = "TODO: Multi-line fix";
153
154 using ark::es2panda::ir::AstNode;
155 using ark::es2panda::public_lib::Context;
156 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
157
158 Initializer initializer = Initializer();
159 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
160
161 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
162 ark::es2panda::lsp::TodoCommentDescriptor(kTodoTag, kDescriptorPriority)};
163
164 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
165
166 ASSERT_EQ(comments.size(), kExpectedSize);
167 EXPECT_EQ(comments[0].GetCommentDescriptor().GetText(), kTodoTag);
168 EXPECT_EQ(comments[0].GetMessage(), kExpectedMessage);
169
170 initializer.DestroyContext(ctx);
171 }
172
TEST_F(TodoCommentsTest,GetTodoCommentsIgnoresNonComments)173 TEST_F(TodoCommentsTest, GetTodoCommentsIgnoresNonComments)
174 {
175 const time_t kDesignatedThrottleTime = 123;
176 const int kDescriptorPriority = 1;
177 const char *const kTodoTag = "TODO";
178 const char *const kFileName = "non-comment.sts";
179 const char *const kFileContent = "let s = \"TODO: not a comment\"";
180
181 using ark::es2panda::ir::AstNode;
182 using ark::es2panda::public_lib::Context;
183
184 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
185
186 Initializer initializer = Initializer();
187 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
188
189 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
190 ark::es2panda::lsp::TodoCommentDescriptor(kTodoTag, kDescriptorPriority)};
191
192 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
193
194 ASSERT_TRUE(comments.empty());
195
196 initializer.DestroyContext(ctx);
197 }
198
TEST_F(TodoCommentsTest,GetTodoCommentsMultiLineCodeMultiComments)199 TEST_F(TodoCommentsTest, GetTodoCommentsMultiLineCodeMultiComments)
200 {
201 const time_t kDesignatedThrottleTime = 123;
202 const int kDescriptorPriority = 1;
203 const int kExpectedSize = 2;
204 const char *const kTodoTag = "TODO";
205 const char *const kHackTag = "HACK";
206 const char *const kFileName = "multiline-multicomment.sts";
207 const char *const kFileContent =
208 R"(export function A(a:number): number {return a;}
209 // TODO: this is a todo comment
210
211 // HACK: fix me
212 export function B(a:number, b:number): number {return a + b;})";
213 const char *const kExpectedTodoMessage = "TODO: this is a todo comment";
214 const char *const kExpectedHackMessage = "HACK: fix me";
215 const int kExpectedTodoPosition = 52;
216 const int kExpectedHackPosition = 87;
217
218 using ark::es2panda::ir::AstNode;
219 using ark::es2panda::public_lib::Context;
220
221 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
222
223 Initializer initializer = Initializer();
224 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
225
226 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
227 ark::es2panda::lsp::TodoCommentDescriptor(kTodoTag, kDescriptorPriority),
228 ark::es2panda::lsp::TodoCommentDescriptor(kHackTag, kDescriptorPriority)};
229
230 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
231
232 ASSERT_EQ(comments.size(), kExpectedSize);
233 EXPECT_EQ(comments[0].GetCommentDescriptor().GetText(), kTodoTag);
234 EXPECT_EQ(comments[0].GetMessage(), kExpectedTodoMessage);
235 EXPECT_EQ(comments[0].GetPosition(), kExpectedTodoPosition);
236 EXPECT_EQ(comments[1].GetCommentDescriptor().GetText(), kHackTag);
237 EXPECT_EQ(comments[1].GetMessage(), kExpectedHackMessage);
238 EXPECT_EQ(comments[1].GetPosition(), kExpectedHackPosition);
239
240 initializer.DestroyContext(ctx);
241 }
242
TEST_F(TodoCommentsTest,GetTodoCommentsMultiLineCodeSameComments)243 TEST_F(TodoCommentsTest, GetTodoCommentsMultiLineCodeSameComments)
244 {
245 const time_t kDesignatedThrottleTime = 123;
246 const int kDescriptorPriority = 1;
247 const int kExpectedSize = 2;
248 const char *const kTodoTag = "TODO";
249 const char *const kFileName = "multiline-duplicate.sts";
250 const char *const kFileContent =
251 R"(export function A(a:number): number {return a;}
252 // TODO: this is a duplicate todo comment
253
254 // TODO: this is a duplicate todo comment
255 export function B(a:number, b:number): number {return a + b;})";
256 const char *const kExpectedMessage = "TODO: this is a duplicate todo comment";
257 const int kExpectedFirstPosition = 52;
258 const int kExpectedSecondPosition = 97;
259
260 using ark::es2panda::ir::AstNode;
261 using ark::es2panda::public_lib::Context;
262
263 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
264
265 Initializer initializer = Initializer();
266 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
267
268 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
269 ark::es2panda::lsp::TodoCommentDescriptor(kTodoTag, kDescriptorPriority)};
270
271 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
272
273 ASSERT_EQ(comments.size(), kExpectedSize);
274 EXPECT_EQ(comments[0].GetCommentDescriptor().GetText(), kTodoTag);
275 EXPECT_EQ(comments[1].GetCommentDescriptor().GetText(), kTodoTag);
276 EXPECT_EQ(comments[0].GetMessage(), kExpectedMessage);
277 EXPECT_EQ(comments[1].GetMessage(), kExpectedMessage);
278 EXPECT_EQ(comments[0].GetPosition(), kExpectedFirstPosition);
279 EXPECT_EQ(comments[1].GetPosition(), kExpectedSecondPosition);
280
281 initializer.DestroyContext(ctx);
282 }
283
TEST_F(TodoCommentsTest,GetTodoCommentsNotTodoComment)284 TEST_F(TodoCommentsTest, GetTodoCommentsNotTodoComment)
285 {
286 const time_t kDesignatedThrottleTime = 123;
287 const int kDescriptorPriority = 1;
288 const char *const kTodoTag = "TODO";
289 const char *const kFileName = "non-comment.sts";
290 const char *const kFileContent = "// TODOX not a todo comment";
291
292 using ark::es2panda::ir::AstNode;
293 using ark::es2panda::public_lib::Context;
294
295 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
296
297 Initializer initializer = Initializer();
298 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
299
300 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
301 ark::es2panda::lsp::TodoCommentDescriptor(kTodoTag, kDescriptorPriority)};
302
303 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
304
305 ASSERT_TRUE(comments.empty());
306
307 initializer.DestroyContext(ctx);
308 }
309
TEST_F(TodoCommentsTest,GetTodoCommentsBlockCommentFixMe)310 TEST_F(TodoCommentsTest, GetTodoCommentsBlockCommentFixMe)
311 {
312 const time_t kDesignatedThrottleTime = 123;
313 const int kDescriptorPriority = 1;
314 const int kExpectedSize = 1;
315 const char *const kTodoTag = "FIXME";
316 const char *const kFileName = "block-comment-fixme.sts";
317 const char *const kFileContent = "/* FIXME: Fix this */";
318 const char *const kExpectedMessage = "FIXME: Fix this ";
319
320 using ark::es2panda::ir::AstNode;
321 using ark::es2panda::public_lib::Context;
322 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
323
324 Initializer initializer = Initializer();
325 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
326
327 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
328 ark::es2panda::lsp::TodoCommentDescriptor(kTodoTag, kDescriptorPriority)};
329
330 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
331
332 ASSERT_EQ(comments.size(), kExpectedSize);
333 EXPECT_EQ(comments[0].GetCommentDescriptor().GetText(), kTodoTag);
334 EXPECT_EQ(comments[0].GetMessage(), kExpectedMessage);
335
336 initializer.DestroyContext(ctx);
337 }
338
TEST_F(TodoCommentsTest,GetTodoCommentsSimpleFix)339 TEST_F(TodoCommentsTest, GetTodoCommentsSimpleFix)
340 {
341 const time_t kDesignatedThrottleTime = 123;
342 const int kDescriptorPriority = 1;
343 const int kExpectedSize = 1;
344 const char *const kHackTag = "FIX";
345 const char *const kFileName = "simple-comment-fix.sts";
346 const char *const kFileContent = "// FIX: Needs to be fixed";
347 const char *const kExpectedMessage = "FIX: Needs to be fixed";
348
349 using ark::es2panda::ir::AstNode;
350 using ark::es2panda::public_lib::Context;
351 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
352
353 Initializer initializer = Initializer();
354 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
355
356 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
357 ark::es2panda::lsp::TodoCommentDescriptor(kHackTag, kDescriptorPriority)};
358
359 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
360
361 ASSERT_EQ(comments.size(), kExpectedSize);
362 EXPECT_EQ(comments[0].GetCommentDescriptor().GetText(), kHackTag);
363 EXPECT_EQ(comments[0].GetMessage(), kExpectedMessage);
364
365 initializer.DestroyContext(ctx);
366 }
367
TEST_F(TodoCommentsTest,GetTodoCommentsNoteMultiLineCodeSameComments)368 TEST_F(TodoCommentsTest, GetTodoCommentsNoteMultiLineCodeSameComments)
369 {
370 const time_t kDesignatedThrottleTime = 123;
371 const int kDescriptorPriority = 1;
372 const int kExpectedSize = 2;
373 const char *const kTodoTag = "NOTE";
374 const char *const kFileName = "multiline-duplicate-note.sts";
375 const char *const kFileContent =
376 R"(export function A(b:number): number {return c;}
377 // NOTE: this is a duplicate note comment
378
379 // Comment line
380
381 // NOTE: this is a duplicate note comment
382 export function B(a:number, b:number): number {return a + b;})";
383 const char *const kExpectedMessage = "NOTE: this is a duplicate note comment";
384 const int kExpectedFirstPosition = 52;
385 const int kExpectedSecondPosition = 115;
386
387 using ark::es2panda::ir::AstNode;
388 using ark::es2panda::public_lib::Context;
389
390 auto cancellationToken = ark::es2panda::lsp::CancellationToken(kDesignatedThrottleTime, nullptr);
391
392 Initializer initializer = Initializer();
393 es2panda_Context *ctx = initializer.CreateContext(kFileName, ES2PANDA_STATE_CHECKED, kFileContent);
394
395 std::vector<ark::es2panda::lsp::TodoCommentDescriptor> descriptors = {
396 ark::es2panda::lsp::TodoCommentDescriptor(kTodoTag, kDescriptorPriority)};
397
398 auto comments = ark::es2panda::lsp::GetTodoCommentsImpl(ctx, descriptors, &cancellationToken);
399
400 ASSERT_EQ(comments.size(), kExpectedSize);
401 EXPECT_EQ(comments[0].GetCommentDescriptor().GetText(), kTodoTag);
402 EXPECT_EQ(comments[1].GetCommentDescriptor().GetText(), kTodoTag);
403 EXPECT_EQ(comments[0].GetMessage(), kExpectedMessage);
404 EXPECT_EQ(comments[1].GetMessage(), kExpectedMessage);
405 EXPECT_EQ(comments[0].GetPosition(), kExpectedFirstPosition);
406 EXPECT_EQ(comments[1].GetPosition(), kExpectedSecondPosition);
407
408 initializer.DestroyContext(ctx);
409 }
410 // NOLINTEND
411 } // namespace