imports.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. // SPDX-License-Identifier: Apache-2.0
  2. use solang::file_resolver::FileResolver;
  3. use solang::Target;
  4. use std::ffi::OsStr;
  5. #[test]
  6. fn enum_import() {
  7. let mut cache = FileResolver::default();
  8. cache.set_file_contents(
  9. "a.sol",
  10. r#"
  11. import "b.sol";
  12. abstract contract foo {
  13. enum_b bar;
  14. }
  15. "#
  16. .to_string(),
  17. );
  18. cache.set_file_contents(
  19. "b.sol",
  20. r#"
  21. enum enum_b { b1 }
  22. "#
  23. .to_string(),
  24. );
  25. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  26. assert!(!ns.diagnostics.any_errors());
  27. let mut cache = FileResolver::default();
  28. cache.set_file_contents(
  29. "a.sol",
  30. r#"
  31. import { enum_b } from "b.sol";
  32. abstract contract foo {
  33. enum_b bar;
  34. }
  35. "#
  36. .to_string(),
  37. );
  38. cache.set_file_contents(
  39. "b.sol",
  40. r#"
  41. enum enum_b { b1 }
  42. "#
  43. .to_string(),
  44. );
  45. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  46. assert!(!ns.diagnostics.any_errors());
  47. let mut cache = FileResolver::default();
  48. cache.set_file_contents(
  49. "a.sol",
  50. r#"
  51. import { enum_b as foobar } from "b.sol";
  52. abstract contract foo {
  53. foobar bar;
  54. }
  55. "#
  56. .to_string(),
  57. );
  58. cache.set_file_contents(
  59. "b.sol",
  60. r#"
  61. enum enum_b { b1 }
  62. "#
  63. .to_string(),
  64. );
  65. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  66. assert!(!ns.diagnostics.any_errors());
  67. let mut cache = FileResolver::default();
  68. cache.set_file_contents(
  69. "a.sol",
  70. r#"
  71. import { enum_c } from "b.sol";
  72. "#
  73. .to_string(),
  74. );
  75. cache.set_file_contents(
  76. "b.sol",
  77. r#"
  78. enum enum_b { b1 }
  79. "#
  80. .to_string(),
  81. );
  82. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  83. assert_eq!(
  84. ns.diagnostics.first_error(),
  85. "import 'b.sol' does not export 'enum_c'"
  86. );
  87. // from has special handling to avoid making it a keyword
  88. let mut cache = FileResolver::default();
  89. cache.set_file_contents(
  90. "a.sol",
  91. r#"
  92. import { enum_c } frum "b.sol";
  93. "#
  94. .to_string(),
  95. );
  96. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  97. assert_eq!(
  98. ns.diagnostics.first_error(),
  99. "'frum' found where 'from' expected"
  100. );
  101. let mut cache = FileResolver::default();
  102. cache.set_file_contents(
  103. "a.sol",
  104. r#"
  105. import * as foo frum "b.sol";
  106. "#
  107. .to_string(),
  108. );
  109. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  110. assert_eq!(
  111. ns.diagnostics.first_error(),
  112. "'frum' found where 'from' expected"
  113. );
  114. }
  115. #[test]
  116. fn struct_import() {
  117. let mut cache = FileResolver::default();
  118. cache.set_file_contents(
  119. "a.sol",
  120. r#"
  121. import "b.sol";
  122. struct foo {
  123. struct_a bar;
  124. }
  125. "#
  126. .to_string(),
  127. );
  128. cache.set_file_contents(
  129. "b.sol",
  130. r#"
  131. struct struct_a { uint32 f1; }
  132. "#
  133. .to_string(),
  134. );
  135. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  136. assert!(!ns.diagnostics.any_errors());
  137. let mut cache = FileResolver::default();
  138. cache.set_file_contents(
  139. "a.sol",
  140. r#"
  141. import { struct_a as not_struct_a } from "b.sol";
  142. struct foo {
  143. struct_a bar;
  144. }
  145. "#
  146. .to_string(),
  147. );
  148. cache.set_file_contents(
  149. "b.sol",
  150. r#"
  151. struct struct_a { uint32 f1; }
  152. "#
  153. .to_string(),
  154. );
  155. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  156. assert_eq!(ns.diagnostics.first_error(), "type 'struct_a' not found");
  157. }
  158. #[test]
  159. fn contract_import() {
  160. let mut cache = FileResolver::default();
  161. cache.set_file_contents(
  162. "a.sol",
  163. r#"
  164. import "b.sol";
  165. contract a {
  166. function go() public {
  167. b x = new b();
  168. assert(x.test() == 102);
  169. }
  170. }
  171. "#
  172. .to_string(),
  173. );
  174. cache.set_file_contents(
  175. "b.sol",
  176. r#"
  177. contract b {
  178. function test() public returns (uint32) {
  179. return 102;
  180. }
  181. }
  182. "#
  183. .to_string(),
  184. );
  185. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  186. assert!(!ns.diagnostics.any_errors());
  187. // lets try a importing an import
  188. let mut cache = FileResolver::default();
  189. cache.set_file_contents(
  190. "a.sol",
  191. r#"
  192. import "b.sol";
  193. contract a {
  194. function go() public {
  195. c x = new c();
  196. assert(x.test() == 102);
  197. }
  198. }
  199. "#
  200. .to_string(),
  201. );
  202. cache.set_file_contents(
  203. "b.sol",
  204. r#"
  205. import "c.sol";
  206. "#
  207. .to_string(),
  208. );
  209. cache.set_file_contents(
  210. "c.sol",
  211. r#"
  212. contract c {
  213. function test() public returns (uint32) {
  214. return 102;
  215. }
  216. }
  217. "#
  218. .to_string(),
  219. );
  220. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  221. assert!(!ns.diagnostics.any_errors());
  222. // now let's rename an import in a chain
  223. let mut cache = FileResolver::default();
  224. cache.set_file_contents(
  225. "a.sol",
  226. r#"
  227. import "b.sol";
  228. contract a {
  229. function go() public {
  230. mr_c x = new mr_c();
  231. assert(x.test() == 102);
  232. }
  233. }
  234. "#
  235. .to_string(),
  236. );
  237. cache.set_file_contents(
  238. "b.sol",
  239. r#"
  240. import { c as mr_c } from "c.sol";
  241. "#
  242. .to_string(),
  243. );
  244. cache.set_file_contents(
  245. "c.sol",
  246. r#"
  247. contract c {
  248. function test() public returns (uint32) {
  249. return 102;
  250. }
  251. }
  252. "#
  253. .to_string(),
  254. );
  255. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  256. assert!(!ns.diagnostics.any_errors());
  257. }
  258. #[test]
  259. fn circular_import() {
  260. let mut cache = FileResolver::default();
  261. cache.set_file_contents(
  262. "self.sol",
  263. r#"
  264. import { foo } from "self.sol";
  265. enum foo { foo1, foo2 }
  266. contract c {
  267. foo public f1;
  268. }
  269. "#
  270. .to_string(),
  271. );
  272. let ns = solang::parse_and_resolve(
  273. OsStr::new("self.sol"),
  274. &mut cache,
  275. Target::default_polkadot(),
  276. );
  277. assert!(!ns.diagnostics.any_errors());
  278. let mut cache = FileResolver::default();
  279. cache.set_file_contents(
  280. "a.sol",
  281. r#"
  282. import "b.sol";
  283. enum enum_a { f1, f2 }
  284. contract a {
  285. function go() public {
  286. b x = new b();
  287. assert(x.test() == 102);
  288. }
  289. }
  290. "#
  291. .to_string(),
  292. );
  293. cache.set_file_contents(
  294. "b.sol",
  295. r#"
  296. import "a.sol";
  297. contract b {
  298. function test() public returns (uint32) {
  299. return 102;
  300. }
  301. function test2() public returns (enum_a) {
  302. return enum_a.f1;
  303. }
  304. }
  305. "#
  306. .to_string(),
  307. );
  308. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  309. assert!(!ns.diagnostics.any_errors());
  310. }
  311. #[test]
  312. fn import_symbol() {
  313. // import struct via import symbol
  314. let mut cache = FileResolver::default();
  315. cache.set_file_contents(
  316. "a.sol",
  317. r#"
  318. import "b.sol" as foo;
  319. contract a {
  320. function go(foo.b_struct x) public returns (uint32) {
  321. return x.f1;
  322. }
  323. }
  324. "#
  325. .to_string(),
  326. );
  327. cache.set_file_contents(
  328. "b.sol",
  329. r#"
  330. struct b_struct {
  331. uint32 f1;
  332. }
  333. "#
  334. .to_string(),
  335. );
  336. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  337. assert!(!ns.diagnostics.any_errors());
  338. // import contract via import symbol
  339. let mut cache = FileResolver::default();
  340. cache.set_file_contents(
  341. "a.sol",
  342. r#"
  343. import "b.sol" as foo;
  344. contract a {
  345. function go() public returns (uint32) {
  346. foo.b x = new foo.b();
  347. return x.test();
  348. }
  349. }
  350. "#
  351. .to_string(),
  352. );
  353. cache.set_file_contents(
  354. "b.sol",
  355. r#"
  356. contract b {
  357. function test() public returns (uint32) {
  358. return 102;
  359. }
  360. }
  361. "#
  362. .to_string(),
  363. );
  364. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  365. assert!(!ns.diagnostics.any_errors());
  366. // import enum in contract via import symbol
  367. let mut cache = FileResolver::default();
  368. cache.set_file_contents(
  369. "a.sol",
  370. r#"
  371. import "b.sol" as foo;
  372. contract a {
  373. function go(foo.b.c x) public {
  374. assert(x == foo.b.c.c2);
  375. }
  376. }
  377. "#
  378. .to_string(),
  379. );
  380. cache.set_file_contents(
  381. "b.sol",
  382. r#"
  383. contract b {
  384. enum c { c1, c2 }
  385. function test() public returns (uint32) {
  386. return 102;
  387. }
  388. }
  389. "#
  390. .to_string(),
  391. );
  392. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  393. assert!(!ns.diagnostics.any_errors());
  394. // import struct in contract via import symbol chain
  395. let mut cache = FileResolver::default();
  396. cache.set_file_contents(
  397. "a.sol",
  398. r#"
  399. import "b.sol" as foo;
  400. contract a {
  401. function go(foo.bar.c.k x) public returns (int32) {
  402. return x.f1;
  403. }
  404. }
  405. "#
  406. .to_string(),
  407. );
  408. cache.set_file_contents(
  409. "b.sol",
  410. r#"
  411. import "c.sol" as bar;
  412. "#
  413. .to_string(),
  414. );
  415. cache.set_file_contents(
  416. "c.sol",
  417. r#"
  418. contract c {
  419. struct k {
  420. int32 f1;
  421. }
  422. function test() public returns (uint32) {
  423. return 102;
  424. }
  425. }
  426. "#
  427. .to_string(),
  428. );
  429. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  430. assert!(!ns.diagnostics.any_errors());
  431. }
  432. #[test]
  433. fn enum_import_chain() {
  434. // import struct in contract via import symbol chain
  435. let mut cache = FileResolver::default();
  436. cache.set_file_contents(
  437. "a.sol",
  438. r#"
  439. import "b.sol" as foo;
  440. contract a {
  441. function go(foo.c_import.d_import.d.enum_d x) public returns (bool) {
  442. return foo.c_import.d_import.d.enum_d.d2 == x;
  443. }
  444. }
  445. "#
  446. .to_string(),
  447. );
  448. cache.set_file_contents(
  449. "b.sol",
  450. r#"
  451. import "c.sol" as c_import;
  452. "#
  453. .to_string(),
  454. );
  455. cache.set_file_contents(
  456. "c.sol",
  457. r#"
  458. import "d.sol" as d_import;
  459. "#
  460. .to_string(),
  461. );
  462. cache.set_file_contents(
  463. "d.sol",
  464. r#"
  465. abstract contract d {
  466. enum enum_d { d1, d2, d3 }
  467. }
  468. "#
  469. .to_string(),
  470. );
  471. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  472. assert!(!ns.diagnostics.any_errors());
  473. // now with error
  474. let mut cache = FileResolver::default();
  475. cache.set_file_contents(
  476. "a.sol",
  477. r#"
  478. import "b.sol" as foo;
  479. contract a {
  480. function go(foo.c_import.d_import.d.enum_d x) public returns (bool) {
  481. return foo.c_import.d_import.d.enum_d.d4 == x;
  482. }
  483. }
  484. "#
  485. .to_string(),
  486. );
  487. cache.set_file_contents(
  488. "b.sol",
  489. r#"
  490. import "c.sol" as c_import;
  491. "#
  492. .to_string(),
  493. );
  494. cache.set_file_contents(
  495. "c.sol",
  496. r#"
  497. import "d.sol" as d_import;
  498. "#
  499. .to_string(),
  500. );
  501. cache.set_file_contents(
  502. "d.sol",
  503. r#"
  504. abstract contract d {
  505. enum enum_d { d1, d2, d3 }
  506. }
  507. "#
  508. .to_string(),
  509. );
  510. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  511. assert_eq!(
  512. ns.diagnostics.first_error(),
  513. "enum d.enum_d does not have value d4"
  514. );
  515. }
  516. #[test]
  517. fn import_base_dir() {
  518. // if a imports x/b.sol then when x/b.sol imports, it should use x/ as a base
  519. let mut cache = FileResolver::default();
  520. cache.set_file_contents(
  521. "a.sol",
  522. r#"
  523. import "x/b.sol";
  524. contract a {
  525. function go() public {
  526. c x = new c();
  527. assert(x.test() == 102);
  528. }
  529. }
  530. "#
  531. .to_string(),
  532. );
  533. cache.set_file_contents(
  534. "x/b.sol",
  535. r#"
  536. import "x/c.sol";
  537. "#
  538. .to_string(),
  539. );
  540. cache.set_file_contents(
  541. "x/c.sol",
  542. r#"
  543. contract c {
  544. function test() public returns (uint32) {
  545. return 102;
  546. }
  547. }
  548. "#
  549. .to_string(),
  550. );
  551. let ns = solang::parse_and_resolve(OsStr::new("a.sol"), &mut cache, Target::default_polkadot());
  552. assert!(!ns.diagnostics.any_errors());
  553. }
  554. #[test]
  555. fn event_resolve() {
  556. let mut cache = FileResolver::default();
  557. cache.set_file_contents(
  558. "IThing.sol",
  559. r#"
  560. // SPDX-License-Identifier: MIT
  561. pragma solidity ^0.8.13;
  562. interface IThing {
  563. event Executed();
  564. function run() external;
  565. }
  566. "#
  567. .to_string(),
  568. );
  569. cache.set_file_contents(
  570. "Test.sol",
  571. r#"
  572. // SPDX-License-Identifier: MIT
  573. pragma solidity ^0.8.13;
  574. import {IThing} from "IThing.sol";
  575. contract Thing is IThing {
  576. function run() external {
  577. emit Executed();
  578. }
  579. }"#
  580. .to_string(),
  581. );
  582. let ns = solang::parse_and_resolve(
  583. OsStr::new("Test.sol"),
  584. &mut cache,
  585. Target::default_polkadot(),
  586. );
  587. assert!(!ns.diagnostics.any_errors());
  588. }