• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <gtest/gtest.h>
16 #include <cstddef>
17 #include <cstdio>
18 #include <string>
19 #include <vector>
20 
21 #include "es2panda.h"
22 #include "lsp/include/find_references.h"
23 #include "lsp/include/cancellation_token.h"
24 #include "lsp_api_test.h"
25 
26 // NOLINTBEGIN
27 using ark::es2panda::SourceFile;
28 using ark::es2panda::lexer::SourcePosition;
29 using ark::es2panda::lsp::FindReferences;
30 using std::string;
31 using std::vector;
32 
testCase(vector<SourceFile> & sourceFiles,SourceFile selectedFile,size_t tokenOffset,std::set<ark::es2panda::lsp::ReferencedNode> expected)33 static auto testCase(vector<SourceFile> &sourceFiles, SourceFile selectedFile, size_t tokenOffset,
34                      std::set<ark::es2panda::lsp::ReferencedNode> expected)
35 {
36     auto cancellationToken = ark::es2panda::lsp::CancellationToken(123, nullptr);
37     auto res = FindReferences(&cancellationToken, sourceFiles, selectedFile, tokenOffset);
38 
39     (void)res;
40 
41     ASSERT_EQ(res.size(), expected.size());
42 
43     for (const ark::es2panda::lsp::ReferencedNode &reference : res) {
44         auto found = expected.find(reference);
45         ASSERT_NE(found, expected.end());
46     }
47 }
48 
49 vector<string> fileNames = {"findReferencesOne.ets", "findReferencesTwo.ets"};
50 vector<string> fileContents = {
51     R"(
52         export function abc(x: number): void {
53         }
54 
55         export function dummy(x: number): void {
56         }
57 
58         export class Foo {
59             name: string = "unassigned";
60             x: number = 1;
61             y: number = 2;
62             z: number = 3;
63             constructor(name: string, x: number, y: number, z: number) {
64                 this.name = name;
65                 this.x = x;
66                 this.y = y;
67                 this.z = z;
68             }
69         };
70 
71         export class Oranges {
72             name: string = "unassigned";
73             x: number = 1;
74             y: number = 2;
75             z: number = 3;
76             constructor(name: string, x: number, y: number, z: number) {
77                 this.name = name;
78                 this.x = x;
79                 this.y = y;
80                 this.z = z;
81             }
82         };
83 
84         dummy(0);
85         dummy(1);
86         abc(2);
87         abc(3);
88         abc(4);
89         )",
90     R"(
91         import { dummy, abc, Foo  } from "./findReferencesOne.ets";
92 
93         dummy(4);
94         dummy(44);
95         abc(5);
96         abc(55);
97         abc(555);
98 
99         let myfoo = new Foo("apples", 1, 2, 3);
100         let otherfoo = new Foo("oranges", 4, 5, 6);
101 
102         console.log(myfoo)
103         console.log(otherfoo)
104         console.log(myfoo.name)
105     )"};
106 
107 std::set<ark::es2panda::lsp::ReferencedNode> expected_dummy = {
108     {"/tmp/findReferencesOne.ets", 83, 88, 4, true},     {"/tmp/findReferencesOne.ets", 863, 868, 33, false},
109     {"/tmp/findReferencesOne.ets", 881, 886, 34, false}, {"/tmp/findReferencesTwo.ets", 18, 23, 1, false},
110     {"/tmp/findReferencesTwo.ets", 78, 83, 3, false},    {"/tmp/findReferencesTwo.ets", 96, 101, 4, false},
111 };
112 
113 std::set<ark::es2panda::lsp::ReferencedNode> expected_abc = {
114     {"/tmp/findReferencesOne.ets", 25, 28, 1, true},     {"/tmp/findReferencesOne.ets", 899, 902, 35, false},
115     {"/tmp/findReferencesOne.ets", 915, 918, 36, false}, {"/tmp/findReferencesOne.ets", 931, 934, 37, false},
116     {"/tmp/findReferencesTwo.ets", 25, 28, 1, false},    {"/tmp/findReferencesTwo.ets", 115, 118, 5, false},
117     {"/tmp/findReferencesTwo.ets", 131, 134, 6, false},  {"/tmp/findReferencesTwo.ets", 148, 151, 7, false},
118 };
119 
120 std::set<ark::es2panda::lsp::ReferencedNode> expected_myfoo = {
121     {"/tmp/findReferencesTwo.ets", 171, 176, 9, true},
122     {"/tmp/findReferencesTwo.ets", 280, 285, 12, false},
123     {"/tmp/findReferencesTwo.ets", 337, 342, 14, false},
124 };
125 
126 std::set<ark::es2panda::lsp::ReferencedNode> expected_Foo = {
127     {"/tmp/findReferencesOne.ets", 140, 143, 7, true},
128     {"/tmp/findReferencesTwo.ets", 30, 33, 1, false},
129     {"/tmp/findReferencesTwo.ets", 183, 186, 9, false},
130     {"/tmp/findReferencesTwo.ets", 234, 237, 10, false},
131 };
132 
133 std::set<ark::es2panda::lsp::ReferencedNode> expected_name = {
134     {"/tmp/findReferencesOne.ets", 158, 162, 8, true},
135     {"/tmp/findReferencesOne.ets", 362, 366, 13, false},
136     {"/tmp/findReferencesTwo.ets", 343, 347, 14, false},
137 };
138 
139 class LspFindRefTests : public LSPAPITests {};
140 
TEST_F(LspFindRefTests,FindReferencesMethodDefinition1)141 TEST_F(LspFindRefTests, FindReferencesMethodDefinition1)
142 {
143     // Create the files
144     auto filePaths = CreateTempFile(fileNames, fileContents);
145     vector<SourceFile> sourceFiles;
146     for (size_t i = 0; i < filePaths.size(); ++i) {
147         sourceFiles.emplace_back(SourceFile {filePaths[i], fileContents[i]});
148     }
149     ASSERT_TRUE(sourceFiles.size() == fileNames.size());
150 
151     // Case 1: Search for the first occurance of "abc" within "findReferencesOne.ets" which is a method definition
152     {
153         auto srcIndex = 0;
154         size_t tokenOffset = 25;
155         testCase(sourceFiles, sourceFiles[srcIndex], tokenOffset, expected_abc);
156     }
157 }
158 
TEST_F(LspFindRefTests,FindReferencesMethodDefinition2)159 TEST_F(LspFindRefTests, FindReferencesMethodDefinition2)
160 {
161     // Create the files
162     auto filePaths = CreateTempFile(fileNames, fileContents);
163     vector<SourceFile> sourceFiles;
164     for (size_t i = 0; i < filePaths.size(); ++i) {
165         sourceFiles.emplace_back(SourceFile {filePaths[i], fileContents[i]});
166     }
167     ASSERT_TRUE(sourceFiles.size() == fileNames.size());
168 
169     // Case 2: Search for the first occurance of "dummy" within "findReferencesOne.ets" which is a method definition
170     {
171         auto srcIndex = 0;
172         size_t tokenOffset = 83;
173         testCase(sourceFiles, sourceFiles[srcIndex], tokenOffset, expected_dummy);
174     }
175 }
176 
TEST_F(LspFindRefTests,FindReferencesImportSpecifier)177 TEST_F(LspFindRefTests, FindReferencesImportSpecifier)
178 {
179     // Create the files
180     auto filePaths = CreateTempFile(fileNames, fileContents);
181     vector<SourceFile> sourceFiles;
182     for (size_t i = 0; i < filePaths.size(); ++i) {
183         sourceFiles.emplace_back(SourceFile {filePaths[i], fileContents[i]});
184     }
185     ASSERT_TRUE(sourceFiles.size() == fileNames.size());
186 
187     // Case 3: Search for the first occurance of "abc" within "findReferencesTwo.ets" which is an import specifier
188     {
189         auto srcIndex = 1;
190         size_t tokenOffset = 25;
191         testCase(sourceFiles, sourceFiles[srcIndex], tokenOffset, expected_abc);
192     }
193 }
194 
TEST_F(LspFindRefTests,FindReferencesCallExpression1)195 TEST_F(LspFindRefTests, FindReferencesCallExpression1)
196 {
197     // Create the files
198     auto filePaths = CreateTempFile(fileNames, fileContents);
199     vector<SourceFile> sourceFiles;
200     for (size_t i = 0; i < filePaths.size(); ++i) {
201         sourceFiles.emplace_back(SourceFile {filePaths[i], fileContents[i]});
202     }
203     ASSERT_TRUE(sourceFiles.size() == fileNames.size());
204 
205     // Case 4: Search for the second occurance of "abc" within "findReferencesTwo.ets" which is a function call
206     // expression
207     {
208         auto srcIndex = 1;
209         size_t tokenOffset = 115;
210         testCase(sourceFiles, sourceFiles[srcIndex], tokenOffset, expected_abc);
211     }
212 }
213 
TEST_F(LspFindRefTests,FindReferencesCallExpression2)214 TEST_F(LspFindRefTests, FindReferencesCallExpression2)
215 {
216     // Create the files
217     auto filePaths = CreateTempFile(fileNames, fileContents);
218     vector<SourceFile> sourceFiles;
219     for (size_t i = 0; i < filePaths.size(); ++i) {
220         sourceFiles.emplace_back(SourceFile {filePaths[i], fileContents[i]});
221     }
222     ASSERT_TRUE(sourceFiles.size() == fileNames.size());
223 
224     // Case 5: Search for the second occurance of "dummy" within "findReferencesTwo.ets" which is a function call
225     // expression
226     {
227         auto srcIndex = 1;
228         size_t tokenOffset = 78;
229         testCase(sourceFiles, sourceFiles[srcIndex], tokenOffset, expected_dummy);
230     }
231 }
232 
TEST_F(LspFindRefTests,FindReferencesVariableDefinition)233 TEST_F(LspFindRefTests, FindReferencesVariableDefinition)
234 {
235     // Create the files
236     auto filePaths = CreateTempFile(fileNames, fileContents);
237     vector<SourceFile> sourceFiles;
238     for (size_t i = 0; i < filePaths.size(); ++i) {
239         sourceFiles.emplace_back(SourceFile {filePaths[i], fileContents[i]});
240     }
241     ASSERT_TRUE(sourceFiles.size() == fileNames.size());
242 
243     // Case 6: Search for the first occurance of "myfoo" within "findReferencesTwo.ets" which is a variable definition
244     {
245         auto srcIndex = 1;
246         size_t tokenOffset = 171;
247         testCase(sourceFiles, sourceFiles[srcIndex], tokenOffset, expected_myfoo);
248     }
249 }
250 
TEST_F(LspFindRefTests,FindReferencesInstanceCreation)251 TEST_F(LspFindRefTests, FindReferencesInstanceCreation)
252 {
253     // Create the files
254     auto filePaths = CreateTempFile(fileNames, fileContents);
255     vector<SourceFile> sourceFiles;
256     for (size_t i = 0; i < filePaths.size(); ++i) {
257         sourceFiles.emplace_back(SourceFile {filePaths[i], fileContents[i]});
258     }
259     ASSERT_TRUE(sourceFiles.size() == fileNames.size());
260 
261     // Case 7: Search for the first occurance of "Foo" within "findReferencesTwo.ets" which is a class instance creation
262     {
263         auto srcIndex = 1;
264         size_t tokenOffset = 30;
265         testCase(sourceFiles, sourceFiles[srcIndex], tokenOffset, expected_Foo);
266     }
267 }
268 
TEST_F(LspFindRefTests,FindReferencesMemberAccess)269 TEST_F(LspFindRefTests, FindReferencesMemberAccess)
270 {
271     // Create the files
272     auto filePaths = CreateTempFile(fileNames, fileContents);
273     vector<SourceFile> sourceFiles;
274     for (size_t i = 0; i < filePaths.size(); ++i) {
275         sourceFiles.emplace_back(SourceFile {filePaths[i], fileContents[i]});
276     }
277     ASSERT_TRUE(sourceFiles.size() == fileNames.size());
278 
279     // Case 7: Search for the first occurance of "name" within "findReferencesTwo.ets" which is a reference to a member
280     {
281         auto srcIndex = 1;
282         size_t tknIndex = 343;
283 
284         testCase(sourceFiles, sourceFiles[srcIndex], tknIndex, expected_name);
285     }
286 }
287 
288 // NOLINTEND
289