name_scope_test.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "toolchain/sem_ir/name_scope.h"
  5. #include <gmock/gmock.h>
  6. #include <gtest/gtest.h>
  7. namespace Carbon::SemIR {
  8. namespace {
  9. using ::testing::ElementsAre;
  10. using ::testing::Field;
  11. using ::testing::Pair;
  12. // NOLINTNEXTLINE(modernize-use-trailing-return-type): From the macro.
  13. MATCHER_P(NameScopeEntryEquals, entry, "") {
  14. return ExplainMatchResult(
  15. AllOf(Field("name_id", &NameScope::Entry::name_id, entry.name_id),
  16. Field("inst_id", &NameScope::Entry::inst_id, entry.inst_id),
  17. Field("access_kind", &NameScope::Entry::access_kind,
  18. entry.access_kind)),
  19. arg, result_listener);
  20. }
  21. TEST(NameScope, Empty) {
  22. int id = 0;
  23. InstId scope_inst_id(++id);
  24. NameId scope_name_id(++id);
  25. NameScopeId parent_scope_id(++id);
  26. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  27. EXPECT_THAT(name_scope.entries(), ElementsAre());
  28. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre());
  29. EXPECT_EQ(name_scope.inst_id(), scope_inst_id);
  30. EXPECT_EQ(name_scope.name_id(), scope_name_id);
  31. EXPECT_EQ(name_scope.parent_scope_id(), parent_scope_id);
  32. EXPECT_FALSE(name_scope.has_error());
  33. EXPECT_FALSE(name_scope.is_closed_import());
  34. EXPECT_FALSE(name_scope.is_imported_package());
  35. EXPECT_THAT(name_scope.import_ir_scopes(), ElementsAre());
  36. }
  37. TEST(NameScope, Lookup) {
  38. int id = 0;
  39. InstId scope_inst_id(++id);
  40. NameId scope_name_id(++id);
  41. NameScopeId parent_scope_id(++id);
  42. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  43. NameScope::Entry entry1 = {.name_id = NameId(++id),
  44. .inst_id = InstId(++id),
  45. .access_kind = AccessKind::Public};
  46. name_scope.AddRequired(entry1);
  47. NameScope::Entry entry2 = {.name_id = NameId(++id),
  48. .inst_id = InstId(++id),
  49. .access_kind = AccessKind::Protected};
  50. name_scope.AddRequired(entry2);
  51. NameScope::Entry entry3 = {.name_id = NameId(++id),
  52. .inst_id = InstId(++id),
  53. .access_kind = AccessKind::Private};
  54. name_scope.AddRequired(entry3);
  55. auto lookup = name_scope.Lookup(entry1.name_id);
  56. ASSERT_NE(lookup, std::nullopt);
  57. EXPECT_THAT(static_cast<NameScope&>(name_scope).GetEntry(*lookup),
  58. NameScopeEntryEquals(entry1));
  59. EXPECT_THAT(static_cast<const NameScope&>(name_scope).GetEntry(*lookup),
  60. NameScopeEntryEquals(entry1));
  61. lookup = name_scope.Lookup(entry2.name_id);
  62. ASSERT_NE(lookup, std::nullopt);
  63. EXPECT_THAT(name_scope.GetEntry(*lookup), NameScopeEntryEquals(entry2));
  64. lookup = name_scope.Lookup(entry3.name_id);
  65. ASSERT_NE(lookup, std::nullopt);
  66. EXPECT_THAT(name_scope.GetEntry(*lookup), NameScopeEntryEquals(entry3));
  67. NameId unknown_name_id(++id);
  68. lookup = name_scope.Lookup(unknown_name_id);
  69. EXPECT_EQ(lookup, std::nullopt);
  70. }
  71. TEST(NameScope, LookupOrAdd) {
  72. int id = 0;
  73. InstId scope_inst_id(++id);
  74. NameId scope_name_id(++id);
  75. NameScopeId parent_scope_id(++id);
  76. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  77. NameScope::Entry entry1 = {.name_id = NameId(++id),
  78. .inst_id = InstId(++id),
  79. .access_kind = AccessKind::Public};
  80. {
  81. auto [added, entry_id] = name_scope.LookupOrAdd(
  82. entry1.name_id, entry1.inst_id, entry1.access_kind);
  83. EXPECT_TRUE(added);
  84. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry1));
  85. }
  86. NameScope::Entry entry2 = {.name_id = NameId(++id),
  87. .inst_id = InstId(++id),
  88. .access_kind = AccessKind::Protected};
  89. {
  90. auto [added, entry_id] = name_scope.LookupOrAdd(
  91. entry2.name_id, entry2.inst_id, entry2.access_kind);
  92. EXPECT_TRUE(added);
  93. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry2));
  94. }
  95. NameScope::Entry entry3 = {.name_id = NameId(++id),
  96. .inst_id = InstId(++id),
  97. .access_kind = AccessKind::Private};
  98. {
  99. auto [added, entry_id] = name_scope.LookupOrAdd(
  100. entry3.name_id, entry3.inst_id, entry3.access_kind);
  101. EXPECT_TRUE(added);
  102. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry3));
  103. }
  104. {
  105. auto [added, entry_id] = name_scope.LookupOrAdd(
  106. entry1.name_id, entry1.inst_id, entry1.access_kind);
  107. EXPECT_FALSE(added);
  108. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry1));
  109. }
  110. {
  111. auto [added, entry_id] = name_scope.LookupOrAdd(
  112. entry2.name_id, entry2.inst_id, entry2.access_kind);
  113. EXPECT_FALSE(added);
  114. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry2));
  115. }
  116. {
  117. auto [added, entry_id] = name_scope.LookupOrAdd(
  118. entry3.name_id, entry3.inst_id, entry3.access_kind);
  119. EXPECT_FALSE(added);
  120. EXPECT_THAT(name_scope.GetEntry(entry_id), NameScopeEntryEquals(entry3));
  121. }
  122. }
  123. TEST(NameScope, Poison) {
  124. int id = 0;
  125. InstId scope_inst_id(++id);
  126. NameId scope_name_id(++id);
  127. NameScopeId parent_scope_id(++id);
  128. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  129. NameId poison1(++id);
  130. name_scope.AddPoison(poison1);
  131. EXPECT_THAT(name_scope.entries(),
  132. ElementsAre(NameScopeEntryEquals(
  133. NameScope::Entry({.name_id = poison1,
  134. .inst_id = InstId::PoisonedName,
  135. .access_kind = AccessKind::Public}))));
  136. NameId poison2(++id);
  137. name_scope.AddPoison(poison2);
  138. EXPECT_THAT(name_scope.entries(),
  139. ElementsAre(NameScopeEntryEquals(NameScope::Entry(
  140. {.name_id = poison1,
  141. .inst_id = InstId::PoisonedName,
  142. .access_kind = AccessKind::Public})),
  143. NameScopeEntryEquals(NameScope::Entry(
  144. {.name_id = poison2,
  145. .inst_id = InstId::PoisonedName,
  146. .access_kind = AccessKind::Public}))));
  147. auto lookup = name_scope.Lookup(poison1);
  148. ASSERT_NE(lookup, std::nullopt);
  149. EXPECT_THAT(name_scope.GetEntry(*lookup),
  150. NameScopeEntryEquals(
  151. NameScope::Entry({.name_id = poison1,
  152. .inst_id = InstId::PoisonedName,
  153. .access_kind = AccessKind::Public})));
  154. }
  155. TEST(NameScope, ExtendedScopes) {
  156. int id = 0;
  157. InstId scope_inst_id(++id);
  158. NameId scope_name_id(++id);
  159. NameScopeId parent_scope_id = NameScopeId::Package;
  160. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  161. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre());
  162. InstId extended_scope1(++id);
  163. name_scope.AddExtendedScope(extended_scope1);
  164. EXPECT_THAT(name_scope.extended_scopes(), ElementsAre(extended_scope1));
  165. InstId extended_scope2(++id);
  166. name_scope.AddExtendedScope(extended_scope2);
  167. EXPECT_THAT(name_scope.extended_scopes(),
  168. ElementsAre(extended_scope1, extended_scope2));
  169. }
  170. TEST(NameScope, HasError) {
  171. int id = 0;
  172. InstId scope_inst_id(++id);
  173. NameId scope_name_id(++id);
  174. NameScopeId parent_scope_id(++id);
  175. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  176. EXPECT_FALSE(name_scope.has_error());
  177. name_scope.set_has_error();
  178. EXPECT_TRUE(name_scope.has_error());
  179. name_scope.set_has_error();
  180. EXPECT_TRUE(name_scope.has_error());
  181. }
  182. TEST(NameScope, IsClosedImport) {
  183. int id = 0;
  184. InstId scope_inst_id(++id);
  185. NameId scope_name_id(++id);
  186. NameScopeId parent_scope_id(++id);
  187. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  188. EXPECT_FALSE(name_scope.is_closed_import());
  189. name_scope.set_is_closed_import(true);
  190. EXPECT_TRUE(name_scope.is_closed_import());
  191. name_scope.set_is_closed_import(false);
  192. EXPECT_FALSE(name_scope.is_closed_import());
  193. }
  194. TEST(NameScope, IsImportedPackageParentNonPackageScope) {
  195. int id = 0;
  196. InstId scope_inst_id(++id);
  197. NameId scope_name_id(++id);
  198. NameScopeId parent_scope_id(++id);
  199. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  200. EXPECT_FALSE(name_scope.is_imported_package());
  201. name_scope.set_is_closed_import(true);
  202. EXPECT_FALSE(name_scope.is_imported_package());
  203. name_scope.set_is_closed_import(false);
  204. EXPECT_FALSE(name_scope.is_imported_package());
  205. }
  206. TEST(NameScope, IsImportedPackageParentPackageScope) {
  207. int id = 0;
  208. InstId scope_inst_id(++id);
  209. NameId scope_name_id(++id);
  210. NameScopeId parent_scope_id = NameScopeId::Package;
  211. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  212. EXPECT_FALSE(name_scope.is_imported_package());
  213. name_scope.set_is_closed_import(true);
  214. EXPECT_TRUE(name_scope.is_imported_package());
  215. name_scope.set_is_closed_import(false);
  216. EXPECT_FALSE(name_scope.is_imported_package());
  217. }
  218. TEST(NameScope, ImportIRScopes) {
  219. int id = 0;
  220. InstId scope_inst_id(++id);
  221. NameId scope_name_id(++id);
  222. NameScopeId parent_scope_id = NameScopeId::Package;
  223. NameScope name_scope(scope_inst_id, scope_name_id, parent_scope_id);
  224. EXPECT_THAT(name_scope.import_ir_scopes(), ElementsAre());
  225. ImportIRId import_ir_id1(++id);
  226. NameScopeId import_name_scope_id1(++id);
  227. name_scope.AddImportIRScope({import_ir_id1, import_name_scope_id1});
  228. EXPECT_THAT(name_scope.import_ir_scopes(),
  229. ElementsAre(Pair(import_ir_id1, import_name_scope_id1)));
  230. ImportIRId import_ir_id2(++id);
  231. NameScopeId import_name_scope_id2(++id);
  232. name_scope.AddImportIRScope({import_ir_id2, import_name_scope_id2});
  233. EXPECT_THAT(name_scope.import_ir_scopes(),
  234. ElementsAre(Pair(import_ir_id1, import_name_scope_id1),
  235. Pair(import_ir_id2, import_name_scope_id2)));
  236. }
  237. } // namespace
  238. } // namespace Carbon::SemIR