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 <regex>
20 #include <string>
21 #include <vector>
22
23 #include "lsp_api_test.h"
24 #include "lsp/include/class_hierarchy.h"
25 #include "lsp/include/internal_api.h"
26
27 namespace {
28
29 class LspClassHierarchyTests : public LSPAPITests {};
30
TEST_F(LspClassHierarchyTests,GetTypeHierarchiesImpl_001)31 TEST_F(LspClassHierarchyTests, GetTypeHierarchiesImpl_001)
32 {
33 std::vector<std::string> fileNames = {"aa1.ets", "bb1.ets", "cc1.ets", "ii1.ets", "mm1.ets", "nn1.ets", "pp1.ets"};
34 std::vector<std::string> fileContents = {
35 R"(
36 export class AAA {}
37 )",
38 R"(
39 import { AAA } from "./aa1"
40 export class BBB extends AAA {}
41 )",
42 R"(import { BBB } from "./bb1"
43 import { NNN } from "./nn1"
44 import { PPP } from "./pp1"
45 class CCC extends BBB implements NNN, PPP {}
46 )",
47 R"(export interface III {}
48 )",
49 R"(
50 export interface MMM {}
51 )",
52 R"(import { III } from "./ii1"
53 import { MMM } from "./mm1"
54 export interface NNN extends III, MMM {}
55 export interface NNN2 extends III {}
56 export interface NNN3 extends NNN2 {}
57 export interface NNN4 extends NNN2 {}
58 )",
59 R"(export interface PPP {}
60 )"};
61 auto filePaths = CreateTempFile(fileNames, fileContents);
62 ASSERT_TRUE(filePaths.size() == fileContents.size());
63 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
64 const int position = 120;
65 const int fileIndex = 2;
66 auto context = initializer.CreateContext(filePaths[fileIndex].c_str(), ES2PANDA_STATE_CHECKED);
67 auto node = ark::es2panda::lsp::GetTouchingToken(context, position, false);
68 auto tokenId = ark::es2panda::lsp::GetOwnerId(node);
69 auto tokenName = ark::es2panda::lsp::GetIdentifierName(node);
70 auto res = ark::es2panda::lsp::GetTypeHierarchiesImpl(context, position);
71 initializer.DestroyContext(context);
72 const size_t parentNum1 = 3;
73 const size_t parentNum2 = 1;
74 ASSERT_EQ(res.superHierarchies.subOrSuper.size(), parentNum1);
75 ASSERT_EQ(res.superHierarchies.subOrSuper[0].subOrSuper.size(), parentNum2);
76 }
77
TEST_F(LspClassHierarchyTests,GetTypeHierarchiesImpl_002)78 TEST_F(LspClassHierarchyTests, GetTypeHierarchiesImpl_002)
79 {
80 std::vector<std::string> fileNames = {"aa2.ets", "bb2.ets", "cc2.ets", "ii2.ets", "mm2.ets", "nn2.ets", "pp2.ets"};
81 std::vector<std::string> fileContents = {
82 R"(
83 export class AAA {}
84 )",
85 R"(
86 import { AAA } from "./aa2"
87 export class BBB extends AAA {}
88 )",
89 R"(import { BBB } from "./bb2"
90 import { NNN } from "./nn2"
91 import { PPP } from "./pp2"
92 class CCC extends BBB implements NNN, PPP {}
93 )",
94 R"(export interface III {}
95 )",
96 R"(
97 export interface MMM {}
98 )",
99 R"(import { III } from "./ii2"
100 import { MMM } from "./mm2"
101 export interface NNN extends III, MMM {}
102 export interface NNN2 extends III {}
103 export interface NNN3 extends NNN2 {}
104 export interface NNN4 extends NNN2 {}
105 )",
106 R"(export interface PPP {}
107 )"};
108 auto filePaths = CreateTempFile(fileNames, fileContents);
109 ASSERT_TRUE(filePaths.size() == fileContents.size());
110 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
111 const int position = 94;
112 const int fileIndex = 5;
113 auto context = initializer.CreateContext(filePaths[fileIndex].c_str(), ES2PANDA_STATE_CHECKED);
114 auto node = ark::es2panda::lsp::GetTouchingToken(context, position, false);
115 auto tokenId = ark::es2panda::lsp::GetOwnerId(node);
116 auto tokenName = ark::es2panda::lsp::GetIdentifierName(node);
117 auto res = ark::es2panda::lsp::GetTypeHierarchiesImpl(context, position);
118 initializer.DestroyContext(context);
119 const size_t parentNum1 = 2;
120 ASSERT_EQ(res.superHierarchies.subOrSuper.size(), parentNum1);
121 }
122
TEST_F(LspClassHierarchyTests,GetTypeHierarchiesImpl_003)123 TEST_F(LspClassHierarchyTests, GetTypeHierarchiesImpl_003)
124 {
125 std::vector<std::string> fileNames = {"aa3.ets", "bb3.ets", "cc3.ets", "ii3.ets", "mm3.ets", "nn3.ets", "pp3.ets"};
126 std::vector<std::string> fileContents = {
127 R"(
128 export class AAA {}
129 )",
130 R"(
131 import { AAA } from "./aa3"
132 export class BBB extends AAA {}
133 )",
134 R"(import { BBB } from "./bb3"
135 import { NNN } from "./nn3"
136 import { PPP } from "./pp3"
137 class CCC extends BBB implements NNN, PPP {}
138 )",
139 R"(export interface III {}
140 )",
141 R"(
142 export interface MMM {}
143 )",
144 R"(import { III } from "./ii3"
145 import { MMM } from "./mm3"
146 export interface NNN extends III, MMM {}
147 export interface NNN2 extends III {}
148 export interface NNN3 extends NNN2 {}
149 export interface NNN4 extends NNN2 {}
150 )",
151 R"(export interface PPP {}
152 )"};
153 auto filePaths = CreateTempFile(fileNames, fileContents);
154 ASSERT_TRUE(filePaths.size() == fileContents.size());
155 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
156 const int position = 20;
157 const int fileIndex = 3;
158 auto context = initializer.CreateContext(filePaths[fileIndex].c_str(), ES2PANDA_STATE_CHECKED);
159 auto node = ark::es2panda::lsp::GetTargetDeclarationNodeByPosition(context, position);
160 auto tokenId = ark::es2panda::lsp::GetOwnerId(node);
161 auto tokenName = ark::es2panda::lsp::GetIdentifierName(node);
162 const int fileIndex5 = 5;
163 auto context5 = initializer.CreateContext(filePaths[fileIndex5].c_str(), ES2PANDA_STATE_CHECKED);
164 auto res = ark::es2panda::lsp::GetTypeHierarchiesImpl(context5, position, node);
165 initializer.DestroyContext(context);
166 const size_t childNum1 = 2;
167 const size_t childNum2 = 2;
168 ASSERT_EQ(res.subHierarchies.subOrSuper.size(), childNum1);
169 ASSERT_EQ(res.subHierarchies.subOrSuper[1].subOrSuper.size(), childNum2);
170 }
171
TEST_F(LspClassHierarchyTests,GetTypeHierarchiesImpl_004)172 TEST_F(LspClassHierarchyTests, GetTypeHierarchiesImpl_004)
173 {
174 std::vector<std::string> fileNames = {"aa4.ets", "bb4.ets", "cc4.ets", "dd4.ets"};
175 std::vector<std::string> fileContents = {
176 R"(
177 export class AAA {}
178 )",
179 R"(
180 import { AAA } from "./aa4"
181 export class BBB extends AAA {}
182 )",
183 R"(import { AAA } from "./aa4"
184 class CCC extends AAA {}
185 )",
186 R"(import { BBB } from "./bb4"
187 class DDD extends BBB {}
188 )"};
189 auto filePaths = CreateTempFile(fileNames, fileContents);
190 ASSERT_TRUE(filePaths.size() == fileContents.size());
191 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
192 const int position = 26;
193 const int fileIndex = 0;
194 auto context = initializer.CreateContext(filePaths[fileIndex].c_str(), ES2PANDA_STATE_CHECKED);
195 auto node = ark::es2panda::lsp::GetTargetDeclarationNodeByPosition(context, position);
196 auto tokenId = ark::es2panda::lsp::GetOwnerId(node);
197 auto tokenName = ark::es2panda::lsp::GetIdentifierName(node);
198 const int fileIndex5 = 1;
199 auto context5 = initializer.CreateContext(filePaths[fileIndex5].c_str(), ES2PANDA_STATE_CHECKED);
200 auto res = ark::es2panda::lsp::GetTypeHierarchiesImpl(context5, position, node);
201 initializer.DestroyContext(context);
202 const size_t childNum1 = 1;
203 ASSERT_EQ(res.subHierarchies.subOrSuper.size(), childNum1);
204 }
205 } // namespace