Skip to content

Commit 98e2e72

Browse files
authored
Resolve top-level Enums, Structs, Errors, and user-defined types from imports w/ various fixes (intellij-solidity#324)
1 parent cf5f455 commit 98e2e72

File tree

4 files changed

+36
-16
lines changed

4 files changed

+36
-16
lines changed

src/main/kotlin/me/serce/solidity/ide/annotation/annotator.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class SolidityAnnotator : Annotator {
4949
is SolStructDefinition -> element.identifier?.let { applyColor(holder, it, SolColor.STRUCT_NAME) }
5050
is SolEnumDefinition -> element.identifier?.let { applyColor(holder, it, SolColor.ENUM_NAME) }
5151
is SolEventDefinition -> element.identifier?.let { applyColor(holder, it, SolColor.EVENT_NAME) }
52+
is SolUserDefinedValueTypeDefinition -> element.identifier?.let { applyColor(holder, it, SolColor.USER_DEFINED_VALUE_TYPE) }
5253
is SolConstantVariableDeclaration -> applyColor(holder, element.identifier, SolColor.CONSTANT)
5354
is SolStateVariableDeclaration -> {
5455
if (element.mutationModifier?.textMatches("constant") == true) {
@@ -74,7 +75,13 @@ class SolidityAnnotator : Annotator {
7475
else -> when(SolResolver.resolveTypeNameUsingImports(element).firstOrNull()) {
7576
is SolErrorDefinition -> applyColor(holder, element.referenceNameElement, SolColor.ERROR_NAME)
7677
is SolEventDefinition -> applyColor(holder, element.referenceNameElement, SolColor.EVENT_NAME)
77-
else -> applyColor(holder, element.referenceNameElement, SolColor.FUNCTION_CALL)
78+
else -> element.firstChild.let {
79+
if (it is SolPrimaryExpression && SolResolver.resolveTypeNameUsingImports(element.firstChild).filterIsInstance<SolStructDefinition>().isNotEmpty()) {
80+
applyColor(holder, element.referenceNameElement, SolColor.STRUCT_NAME)
81+
} else {
82+
applyColor(holder, element.referenceNameElement, SolColor.FUNCTION_CALL)
83+
}
84+
}
7885
}
7986
}
8087
}

src/main/kotlin/me/serce/solidity/lang/resolve/engine.kt

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ object SolResolver {
2424
val result = if (element is SolFunctionCallElement) {
2525
resolveError(element) +
2626
resolveEvent(element) +
27-
resolveContractUsingImports(element, element.containingFile, true) +
27+
resolveContract(element) +
2828
resolveEnum(element) +
2929
resolveUserDefinedValueType(element)
3030
} else {
31-
resolveContractUsingImports(element, element.containingFile, true) +
31+
resolveContract(element) +
3232
resolveEnum(element) +
3333
resolveStruct(element) +
3434
resolveUserDefinedValueType(element)
@@ -39,17 +39,18 @@ object SolResolver {
3939
/**
4040
* @param withAliases aliases are not recursive, so count them only at the first level of recursion
4141
*/
42-
private fun resolveContractUsingImports(
42+
private fun <T: SolNamedElement>resolveUsingImports(
43+
target: Class<T>,
4344
element: PsiElement,
4445
file: PsiFile,
45-
withAliases: Boolean
46-
): Set<SolContractDefinition> =
47-
RecursionManager.doPreventingRecursion(ResolveContractKey(element.nameOrText, file), true) {
46+
withAliases: Boolean,
47+
): Set<T> =
48+
RecursionManager.doPreventingRecursion(ResolveUsingImportsKey(element.nameOrText, file), true) {
4849
if (element is SolUserDefinedTypeName && element.findIdentifiers().size > 1) {
4950
emptySet()
5051
} else {
5152
val inFile = file.children
52-
.filterIsInstance<SolContractDefinition>()
53+
.filterIsInstance(target)
5354
.filter { it.name == element.nameOrText }
5455

5556
val resolvedViaAlias = when (withAliases) {
@@ -64,36 +65,38 @@ object SolResolver {
6465
}
6566
}
6667
}.flatMap { (alias, resolvedFile) ->
67-
resolveContractUsingImports(alias, resolvedFile.containingFile, false)
68+
resolveUsingImports(target, alias, resolvedFile.containingFile, false)
6869
}
6970
else -> emptyList()
7071
}
7172

7273
val imported = file.children
7374
.filterIsInstance<SolImportDirective>()
7475
.mapNotNull { nullIfError { it.importPath?.reference?.resolve()?.containingFile } }
75-
.flatMap { resolveContractUsingImports(element, it, false) }
76+
.flatMap { resolveUsingImports(target, element, it, false) }
7677

7778
(inFile + resolvedViaAlias + imported).toSet()
7879
}
7980
} ?: emptySet()
8081

82+
private fun resolveContract(element: PsiElement): Set<SolContractDefinition> =
83+
resolveUsingImports(SolContractDefinition::class.java, element, element.containingFile, true)
8184
private fun resolveEnum(element: PsiElement): Set<SolNamedElement> =
82-
resolveInFile<SolEnumDefinition>(element) + resolveInnerType<SolEnumDefinition>(element) { it.enumDefinitionList }
85+
resolveInnerType<SolEnumDefinition>(element) { it.enumDefinitionList } + resolveUsingImports(SolEnumDefinition::class.java, element, element.containingFile, true)
8386

8487
private fun resolveStruct(element: PsiElement): Set<SolNamedElement> =
85-
resolveInFile<SolStructDefinition>(element) + resolveInnerType<SolStructDefinition>(element) { it.structDefinitionList }
88+
resolveInnerType<SolStructDefinition>(element) { it.structDefinitionList } + resolveUsingImports(SolStructDefinition::class.java, element, element.containingFile, true)
8689

8790
private fun resolveUserDefinedValueType(element: PsiElement): Set<SolNamedElement> =
88-
resolveInFile<SolUserDefinedValueTypeDefinition>(element) + resolveInnerType<SolUserDefinedValueTypeDefinition>(
91+
resolveInnerType<SolUserDefinedValueTypeDefinition>(
8992
element,
90-
{ it.userDefinedValueTypeDefinitionList })
93+
{ it.userDefinedValueTypeDefinitionList }) + resolveUsingImports(SolUserDefinedValueTypeDefinition::class.java, element, element.containingFile, true)
9194

9295
private fun resolveEvent(element: PsiElement): Set<SolNamedElement> =
9396
resolveInnerType<SolEventDefinition>(element) { it.eventDefinitionList }
9497

9598
private fun resolveError(element: PsiElement): Set<SolNamedElement> =
96-
resolveInnerType<SolErrorDefinition>(element) { it.errorDefinitionList }
99+
resolveInnerType<SolErrorDefinition>(element) { it.errorDefinitionList } + resolveUsingImports(SolErrorDefinition::class.java, element, element.containingFile, true)
97100

98101
private inline fun <reified T : SolNamedElement> resolveInFile(element: PsiElement) : Set<T> {
99102
return element.parentOfType<SolidityFile>()
@@ -343,7 +346,7 @@ object SolResolver {
343346
}
344347
}
345348

346-
data class ResolveContractKey(val name: String?, val file: PsiFile)
349+
data class ResolveUsingImportsKey(val name: String?, val file: PsiFile)
347350

348351
private fun <T> Sequence<T>.takeWhileInclusive(pred: (T) -> Boolean): Sequence<T> {
349352
var shouldContinue = true

src/main/kotlin/me/serce/solidity/lang/resolve/ref/refs.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,15 @@ class SolFunctionCallReference(element: SolFunctionCallExpression) : SolReferenc
9393
}
9494

9595
fun resolveFunctionCall(): Collection<SolCallable> {
96+
if (element.parent is SolRevertStatement) {
97+
return SolResolver.resolveTypeNameUsingImports(element).filterIsInstance<SolErrorDefinition>()
98+
}
99+
if (element.firstChild is SolPrimaryExpression) {
100+
val structs = SolResolver.resolveTypeNameUsingImports(element.firstChild).filterIsInstance<SolStructDefinition>()
101+
if (structs.isNotEmpty()) {
102+
return structs
103+
}
104+
}
96105
val resolved: Collection<SolCallable> = when (val expr = element.expression) {
97106
is SolPrimaryExpression -> {
98107
val regular = expr.varLiteral?.let { SolResolver.resolveVarLiteral(it) }

src/main/kotlin/me/serce/solidity/lang/types/inference.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ private fun getSolTypeFromUserDefinedTypeName(type: SolUserDefinedTypeName): Sol
7373
is SolContractDefinition -> SolContract(it)
7474
is SolStructDefinition -> SolStruct(it)
7575
is SolEnumDefinition -> SolEnum(it)
76+
is SolUserDefinedValueTypeDefinition -> getSolType(it.elementaryTypeName)
7677
else -> null
7778
}
7879
}

0 commit comments

Comments
 (0)