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 <cstddef>
17 #include <cstdio>
18 #include <gtest/gtest.h>
19 #include <iostream>
20 #include <ostream>
21 #include <regex>
22 #include <string>
23 #include <vector>
24
25 #include "lsp_api_test.h"
26 #include "lsp/include/class_hierarchy.h"
27 #include "lsp/include/internal_api.h"
28
29 namespace {
30 // NOLINTBEGIN
31 using ark::es2panda::lsp::Initializer;
32
33 class LspClassHierarchiesTests : public LSPAPITests {};
34
35 std::vector<std::string> fileContents = {
36 R"(
37 interface Iaa {
38 name: number
39 name1: number
40 name2: number
41
42 hello(): void
43 hello1(): void
44 }
45
46 interface Iaaa extends Iaa {
47 name: number
48 }
49
50 interface Iaab extends Iaa {
51 name: number
52 }
53
54 interface Iaaaa extends Iaaa {
55 name: number
56 }
57
58 interface Iaaab extends Iaaa {
59 name: number
60 }
61
62 abstract class Caa implements Iaa {
63 name: number = 1
64 name1: number = 1
65 name2: number = 1
66
67 hello(): void {
68 throw new Error("Method not implemented.")
69 }
70
71 age: number = 0
72 age2: number = 0
73 age3: number = 0
74
75 abstract classHello(): void
76
77 classHello1() {
78 return 1
79 }
80 }
81
82 class Caaa extends Caa implements Iaaa {
83 age: number = 0
84 age4: number = 0
85 age5: number = 0
86
87 classHello(): void {
88 throw new Error("Method not implemented.")
89 }
90 }
91
92 class Caab extends Caa implements Iaab {
93 name: number = 2
94 }
95
96 class Caaaa extends Caaa implements Iaaaa {
97 name: number = 3
98 }
99
100 class Caaab extends Caaa implements Iaaab {
101 name: number = 4
102 }
103
104 class Caaba extends Caab implements Iaaa {
105 name: number = 5
106 }
107
108 class Caabb extends Caab implements Iaab {
109 name: number = 6
110 }
111
112 export class Test extends Caabb implements Iaab {
113 name: number = 7
114 }
115 )"};
116
TEST_F(LspClassHierarchiesTests,GetClassHierarchiesImpl_001)117 TEST_F(LspClassHierarchiesTests, GetClassHierarchiesImpl_001)
118 {
119 constexpr size_t expectedInfoCount = 5;
120 constexpr size_t tokenOffset = 600;
121
122 std::vector<std::string> fileNames = {"GetClassHierarchiesImpl_001_file1.ets"};
123
124 auto filePaths = CreateTempFile(fileNames, fileContents);
125 std::vector<ark::es2panda::SourceFile> sourceFiles;
126 for (size_t i = 0; i < filePaths.size(); ++i) {
127 sourceFiles.emplace_back(filePaths[i], fileContents[i]);
128 }
129 ASSERT_EQ(fileNames.size(), sourceFiles.size());
130 Initializer initializer;
131 size_t sourceIndex = 0;
132 auto filePath = std::string {sourceFiles[sourceIndex].filePath};
133 auto fileContent = std::string {sourceFiles[sourceIndex].source};
134 auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str());
135 std::vector<ark::es2panda::lsp::ClassHierarchyItemInfo> infos =
136 ark::es2panda::lsp::GetClassHierarchiesImpl(context, fileNames[sourceIndex], tokenOffset);
137 ASSERT_EQ(expectedInfoCount, infos.size());
138 }
139
TEST_F(LspClassHierarchiesTests,GetClassHierarchiesImpl_002)140 TEST_F(LspClassHierarchiesTests, GetClassHierarchiesImpl_002)
141 {
142 constexpr size_t expectedInfoCount = 5;
143 constexpr size_t tokenOffset = 1100;
144
145 std::vector<std::string> fileNames = {"GetClassHierarchiesImpl_002_file1.ets"};
146
147 auto filePaths = CreateTempFile(fileNames, fileContents);
148 std::vector<ark::es2panda::SourceFile> sourceFiles;
149 for (size_t i = 0; i < filePaths.size(); ++i) {
150 sourceFiles.emplace_back(filePaths[i], fileContents[i]);
151 }
152 ASSERT_EQ(fileNames.size(), sourceFiles.size());
153 Initializer initializer;
154 size_t sourceIndex = 0;
155 auto filePath = std::string {sourceFiles[sourceIndex].filePath};
156 auto fileContent = std::string {sourceFiles[sourceIndex].source};
157 auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str());
158 std::vector<ark::es2panda::lsp::ClassHierarchyItemInfo> infos =
159 ark::es2panda::lsp::GetClassHierarchiesImpl(context, fileNames[sourceIndex], tokenOffset);
160 ASSERT_EQ(expectedInfoCount, infos.size());
161 }
162
TEST_F(LspClassHierarchiesTests,GetClassHierarchiesImpl_003)163 TEST_F(LspClassHierarchiesTests, GetClassHierarchiesImpl_003)
164 {
165 constexpr size_t expectedInfoCount = 12;
166 constexpr size_t tokenOffset = 100;
167
168 std::vector<std::string> fileNames = {"GetClassHierarchiesImpl_003_file1.ets"};
169
170 auto filePaths = CreateTempFile(fileNames, fileContents);
171 std::vector<ark::es2panda::SourceFile> sourceFiles;
172 for (size_t i = 0; i < filePaths.size(); ++i) {
173 sourceFiles.emplace_back(filePaths[i], fileContents[i]);
174 }
175 ASSERT_EQ(fileNames.size(), sourceFiles.size());
176 Initializer initializer;
177 size_t sourceIndex = 0;
178 auto filePath = std::string {sourceFiles[sourceIndex].filePath};
179 auto fileContent = std::string {sourceFiles[sourceIndex].source};
180 auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str());
181 std::vector<ark::es2panda::lsp::ClassHierarchyItemInfo> infos =
182 ark::es2panda::lsp::GetClassHierarchiesImpl(context, fileNames[sourceIndex], tokenOffset);
183 ASSERT_EQ(expectedInfoCount, infos.size());
184 }
185
TEST_F(LspClassHierarchiesTests,GetClassHierarchiesImpl_004)186 TEST_F(LspClassHierarchiesTests, GetClassHierarchiesImpl_004)
187 {
188 constexpr size_t expectedInfoCount = 7;
189 constexpr size_t tokenOffset = 130;
190
191 std::vector<std::string> fileNames = {"GetClassHierarchiesImpl_004_file1.ets"};
192
193 auto filePaths = CreateTempFile(fileNames, fileContents);
194 std::vector<ark::es2panda::SourceFile> sourceFiles;
195 for (size_t i = 0; i < filePaths.size(); ++i) {
196 sourceFiles.emplace_back(filePaths[i], fileContents[i]);
197 }
198 ASSERT_EQ(fileNames.size(), sourceFiles.size());
199 Initializer initializer;
200 size_t sourceIndex = 0;
201 auto filePath = std::string {sourceFiles[sourceIndex].filePath};
202 auto fileContent = std::string {sourceFiles[sourceIndex].source};
203 auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str());
204 std::vector<ark::es2panda::lsp::ClassHierarchyItemInfo> infos =
205 ark::es2panda::lsp::GetClassHierarchiesImpl(context, fileNames[sourceIndex], tokenOffset);
206 ASSERT_EQ(expectedInfoCount, infos.size());
207 }
208
TEST_F(LspClassHierarchiesTests,GetClassHierarchiesImpl_005)209 TEST_F(LspClassHierarchiesTests, GetClassHierarchiesImpl_005)
210 {
211 constexpr size_t expectedInfoCount = 5;
212 constexpr size_t tokenOffset = 1000;
213
214 std::vector<std::string> fileNames = {"GetClassHierarchiesImpl_005_file1.ets"};
215
216 auto filePaths = CreateTempFile(fileNames, fileContents);
217 std::vector<ark::es2panda::SourceFile> sourceFiles;
218 for (size_t i = 0; i < filePaths.size(); ++i) {
219 sourceFiles.emplace_back(filePaths[i], fileContents[i]);
220 }
221 ASSERT_EQ(fileNames.size(), sourceFiles.size());
222 Initializer initializer;
223 size_t sourceIndex = 0;
224 auto filePath = std::string {sourceFiles[sourceIndex].filePath};
225 auto fileContent = std::string {sourceFiles[sourceIndex].source};
226 auto context = initializer.CreateContext(filePath.c_str(), ES2PANDA_STATE_CHECKED, fileContent.c_str());
227 std::vector<ark::es2panda::lsp::ClassHierarchyItemInfo> infos =
228 ark::es2panda::lsp::GetClassHierarchiesImpl(context, fileNames[sourceIndex], tokenOffset);
229 ASSERT_EQ(expectedInfoCount, infos.size());
230 }
231 // NOLINTEND
232 } // namespace