Skip to content

Commit

Permalink
add remappings.txt support for foundry (intellij-solidity#331)
Browse files Browse the repository at this point in the history
  • Loading branch information
dyzz authored Nov 9, 2022
1 parent cd84374 commit 4b2bb60
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*.ipr
*.iws
gen
lib
/lib
.sandbox
.DS_Store
/out/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,50 @@ class SolImportPathReference(element: SolImportPathElement) : SolReferenceBase<S
}
}

// default lib located at: forge-std/Test.sol => lib/forge-std/src/Test.sol
private fun findFoundryImportFile(file: VirtualFile, path: String): VirtualFile? {
// apply foundry remappings to import path
private fun applyRemappings(remappings: ArrayList<Pair<String,String>>, path: String):String {
var output = path;
remappings.forEach { (prefix, target) ->
if (path.contains(prefix)) {
output = path.replace(prefix, target)
return output
}
}
return output;
}

private fun foundryDefaultFallback(file: VirtualFile, path: String): VirtualFile? {
val count = Paths.get(path).nameCount;
if (count < 2) {
if (count<2) {
return null;
}
val libName = Paths.get(path).subpath(0, 1).toString();
val libFile = Paths.get(path).subpath(1, count).toString();
val libName = Paths.get(path).subpath(0,1).toString();
val libFile = Paths.get(path).subpath(1,count).toString();
val test = file.findFileByRelativePath("lib/$libName/src/$libFile");
return test;
}

// default lib located at: forge-std/Test.sol => lib/forge-std/src/Test.sol
private fun findFoundryImportFile(file: VirtualFile, path: String): VirtualFile? {
val testRemappingFile = file.findFileByRelativePath("remappings.txt");
val remappings = arrayListOf<Pair<String, String>>();
if (testRemappingFile != null) {
val mappingsContents = testRemappingFile.contentsToByteArray().toString(Charsets.UTF_8).split("[\r\n]+".toRegex());
mappingsContents.forEach { mapping ->
val splitMapping = mapping.split("=")
if (splitMapping.size == 2) {
remappings.add(Pair(splitMapping[0].trim(),splitMapping[1].trim()))
}
}
}

val remappedPath = applyRemappings(remappings, path);
val testRemappedPath = file.findFileByRelativePath(remappedPath);
val testFoundryFallback = foundryDefaultFallback(file, path);

return when {
test != null -> test
testRemappedPath != null -> testRemappedPath
testFoundryFallback != null -> testFoundryFallback
file.parent != null -> findFoundryImportFile(file.parent, path)
else -> null
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package me.serce.solidity.lang.core.resolve

import me.serce.solidity.lang.psi.SolNamedElement

class SolImportResolveFoundryTest : SolResolveTestBase() {

fun testImportPathResolveFoundryRemappings() {
val testcases = arrayListOf<Pair<String, String>>(
Pair("lib/forge-std/src/Test.sol","contracts/ImportUsageFoundryStd.sol"),
Pair("lib/solmate/src/tokens/ERC721.sol","contracts/ImportUsageFoundrySolmate.sol"),
Pair("lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol","contracts/ImportUsageFoundryOpenzeppelin.sol"),
);
testcases.forEach { (targetFile, contractFile) ->
val file1 = myFixture.configureByFile(targetFile)
myFixture.configureByFile("remappings.txt")
myFixture.configureByFile(contractFile)
val (refElement) = findElementAndDataInEditor<SolNamedElement>("^")
val resolved = checkNotNull(refElement.reference?.resolve()) {
"Failed to resolve ${refElement.text}"
}
assertEquals(file1.name, resolved.containingFile.name)
}
}

override fun getTestDataPath() = "src/test/resources/fixtures/importRemappings/"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import "@openzeppelin/token/ERC20/ERC20.sol";
//^

contract ImportUsage {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import "@solmate/tokens/ERC721.sol";
//^

contract ImportUsage {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import "forge-std/Test.sol";
//^

contract ImportUsage {}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
contract Test {}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
contract ERC20 {}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
contract ERC721 {}
3 changes: 3 additions & 0 deletions src/test/resources/fixtures/importRemappings/remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@solmate/=lib/solmate/src/
@openzeppelin/=lib/openzeppelin-contracts/contracts/

0 comments on commit 4b2bb60

Please sign in to comment.