Skip to content

Commit 425a871

Browse files
authored
Gracefull substitution process (#180)
1 parent 4c6c217 commit 425a871

34 files changed

+281
-120
lines changed

jacodb-api/src/main/kotlin/org/jacodb/api/JcClasspath.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ interface JcLookupExtFeature : JcClasspathFeature {
185185
fun lookup(type: JcClassType): JcLookup<JcTypedField, JcTypedMethod>
186186
}
187187

188+
interface JcGenericsSubstitutionFeature : JcClasspathFeature {
189+
190+
fun substitute(clazz: JcClassOrInterface, parameters: List<JvmType>, outer: JcSubstitutor?): JcSubstitutor
191+
}
192+
188193
@JvmDefaultWithoutCompatibility
189194
interface JcInstExtFeature : JcClasspathFeature {
190195

jacodb-core/src/main/kotlin/org/jacodb/impl/types/substition/JcSubstitutor.kt renamed to jacodb-api/src/main/kotlin/org/jacodb/api/Substitution.kt

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,21 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.jacodb.impl.types.substition
17+
package org.jacodb.api
1818

19-
import org.jacodb.api.JcClasspath
20-
import org.jacodb.api.ext.findClass
21-
import org.jacodb.impl.types.signature.JvmType
22-
import org.jacodb.impl.types.signature.JvmTypeParameterDeclaration
23-
import org.jacodb.impl.types.typeParameters
19+
interface JvmType {
20+
val displayName: String
21+
val isNullable: Boolean?
22+
val annotations: List<JcAnnotation>
23+
}
2424

25-
interface JcSubstitutor {
25+
interface JvmTypeParameterDeclaration {
26+
val symbol: String
27+
val owner: JcAccessible
28+
val bounds: List<JvmType>?
29+
}
2630

27-
companion object {
28-
val empty = JcSubstitutorImpl()
29-
}
31+
interface JcSubstitutor {
3032

3133
/**
3234
* Returns a mapping that this substitutor contains for a given type parameter.
@@ -54,16 +56,4 @@ interface JcSubstitutor {
5456

5557
val substitutions: Map<JvmTypeParameterDeclaration, JvmType>
5658

57-
}
58-
59-
fun JcClasspath.substitute(name: String, parameters: List<JvmType>, outer: JcSubstitutor?): JcSubstitutor {
60-
val clazz = findClass(name)
61-
val params = clazz.typeParameters
62-
require(params.size == parameters.size) {
63-
"Incorrect parameters specified for class $name: expected ${params.size} found ${parameters.size}"
64-
}
65-
val substitution = params.mapIndexed { index, declaration ->
66-
declaration to parameters[index]
67-
}.toMap()
68-
return (outer ?: JcSubstitutor.empty).newScope(substitution)
6959
}

jacodb-core/src/main/kotlin/org/jacodb/impl/JcClasspathImpl.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import org.jacodb.impl.features.classpaths.isResolveAllToUnknown
3232
import org.jacodb.impl.fs.ClassSourceImpl
3333
import org.jacodb.impl.types.JcArrayTypeImpl
3434
import org.jacodb.impl.types.JcClassTypeImpl
35-
import org.jacodb.impl.types.substition.JcSubstitutor
35+
import org.jacodb.impl.types.substition.JcSubstitutorImpl
3636
import org.jacodb.impl.vfs.ClasspathVfs
3737
import org.jacodb.impl.vfs.GlobalClassesVfs
3838

@@ -76,7 +76,7 @@ class JcClasspathImpl(
7676
this,
7777
jcClass.name,
7878
jcClass.outerClass?.toType() as? JcClassTypeImpl,
79-
JcSubstitutor.empty,
79+
JcSubstitutorImpl.empty,
8080
nullability,
8181
annotations
8282
)

jacodb-core/src/main/kotlin/org/jacodb/impl/features/classpaths/JcUnknownClass.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import org.jacodb.impl.features.classpaths.virtual.JcVirtualParameter
2626
import org.jacodb.impl.types.JcTypedFieldImpl
2727
import org.jacodb.impl.types.JcTypedMethodImpl
2828
import org.jacodb.impl.types.TypeNameImpl
29-
import org.jacodb.impl.types.substition.JcSubstitutor
29+
import org.jacodb.impl.types.substition.JcSubstitutorImpl
3030
import org.objectweb.asm.Type
3131

3232
class JcUnknownClass(override var classpath: JcClasspath, name: String) : JcVirtualClassImpl(
@@ -62,7 +62,7 @@ class JcUnknownMethod(
6262
return JcTypedMethodImpl(
6363
type,
6464
method(type.jcClass, name, description),
65-
JcSubstitutor.empty
65+
JcSubstitutorImpl.empty
6666
)
6767
}
6868
}
@@ -81,7 +81,7 @@ class JcUnknownField(enclosingClass: JcClassOrInterface, name: String, type: Typ
8181
return JcTypedFieldImpl(
8282
type,
8383
JcUnknownField(type.jcClass, name, fieldType),
84-
JcSubstitutor.empty
84+
JcSubstitutorImpl.empty
8585
)
8686
}
8787

jacodb-core/src/main/kotlin/org/jacodb/impl/types/JcClassTypeImpl.kt

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,19 @@ import org.jacodb.api.ext.findClass
2121
import org.jacodb.api.ext.packageName
2222
import org.jacodb.api.ext.toType
2323
import org.jacodb.impl.bytecode.TypeDelegatingLookup
24-
import org.jacodb.impl.types.signature.*
25-
import org.jacodb.impl.types.substition.JcSubstitutor
26-
import org.jacodb.impl.types.substition.substitute
24+
import org.jacodb.impl.types.signature.JvmClassRefType
25+
import org.jacodb.impl.types.signature.JvmParameterizedType
26+
import org.jacodb.impl.types.signature.TypeResolutionImpl
27+
import org.jacodb.impl.types.signature.TypeSignature
28+
import org.jacodb.impl.types.substition.JcSubstitutorImpl
29+
import org.jacodb.impl.types.substition.SafeSubstitution
2730
import kotlin.LazyThreadSafetyMode.PUBLICATION
2831

2932
class JcClassTypeImpl(
3033
override val classpath: JcClasspath,
3134
val name: String,
3235
override val outerType: JcClassTypeImpl? = null,
33-
private val substitutor: JcSubstitutor = JcSubstitutor.empty,
36+
private val substitutor: JcSubstitutor = JcSubstitutorImpl.empty,
3437
override val nullable: Boolean?,
3538
override val annotations: List<JcAnnotation>
3639
) : JcClassType {
@@ -133,7 +136,7 @@ class JcClassTypeImpl(
133136
outerMethod?.allVisibleTypeParameters() ?: outerClass?.allVisibleTypeParameters()
134137
)?.values?.toList().orEmpty()
135138
val innerSubstitutor = when {
136-
it.isStatic -> JcSubstitutor.empty.newScope(innerParameters)
139+
it.isStatic -> JcSubstitutorImpl.empty.newScope(innerParameters)
137140
else -> substitutor.newScope(innerParameters)
138141
}
139142
JcClassTypeImpl(classpath, it.name, this, innerSubstitutor, true, annotations)
@@ -247,7 +250,7 @@ class JcClassTypeImpl(
247250
val superParameters = superClass.directTypeParameters()
248251
val substitutions = (superType as? JvmParameterizedType)?.parameterTypes
249252
if (substitutions == null || superParameters.size != substitutions.size) {
250-
return JcSubstitutor.empty
253+
return JcSubstitutorImpl.empty
251254
}
252255
return substitutor.fork(superParameters.mapIndexed { index, declaration -> declaration to substitutions[index] }
253256
.toMap())
@@ -256,6 +259,15 @@ class JcClassTypeImpl(
256259

257260
}
258261

262+
private fun JcClasspath.substitute(
263+
name: String,
264+
parameters: List<JvmType>,
265+
substitutor: JcSubstitutor?
266+
): JcSubstitutor {
267+
val genericsSubstitutor = features?.firstNotNullOfOrNull { it as? JcGenericsSubstitutionFeature } ?: SafeSubstitution
268+
return genericsSubstitutor.substitute(findClass(name), parameters, substitutor)
269+
}
270+
259271
fun JvmType.isReferencesClass(name: String): Boolean {
260272
return when (val type = this) {
261273
is JvmClassRefType -> type.name == name

jacodb-core/src/main/kotlin/org/jacodb/impl/types/JcTypeBindings.kt

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,10 @@
1616

1717
package org.jacodb.impl.types
1818

19-
import org.jacodb.api.JcAccessible
20-
import org.jacodb.api.JcClasspath
21-
import org.jacodb.api.JcRefType
22-
import org.jacodb.api.JcType
23-
import org.jacodb.api.JcTypeVariableDeclaration
24-
import org.jacodb.api.PredefinedPrimitives
19+
import org.jacodb.api.*
2520
import org.jacodb.api.ext.findClass
2621
import org.jacodb.api.ext.objectType
27-
import org.jacodb.impl.types.signature.JvmArrayType
28-
import org.jacodb.impl.types.signature.JvmBoundWildcard
29-
import org.jacodb.impl.types.signature.JvmClassRefType
30-
import org.jacodb.impl.types.signature.JvmParameterizedType
31-
import org.jacodb.impl.types.signature.JvmPrimitiveType
32-
import org.jacodb.impl.types.signature.JvmType
33-
import org.jacodb.impl.types.signature.JvmTypeVariable
34-
import org.jacodb.impl.types.signature.JvmUnboundWildcard
22+
import org.jacodb.impl.types.signature.*
3523

3624
internal fun JcClasspath.typeOf(jvmType: JvmType, parameters: List<JvmType>? = null): JcType {
3725
return when (jvmType) {
@@ -88,6 +76,7 @@ internal fun JcClasspath.typeOf(jvmType: JvmType, parameters: List<JvmType>? = n
8876
is JvmBoundWildcard.JvmLowerBoundWildcard -> JcBoundedWildcardImpl(
8977
upperBounds = emptyList(), lowerBounds = listOf(typeOf(jvmType.bound) as JcRefType)
9078
)
79+
else -> throw IllegalStateException("Unsupported type")
9180
}
9281
}
9382

jacodb-core/src/main/kotlin/org/jacodb/impl/types/JcTypedFieldImpl.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,12 @@
1616

1717
package org.jacodb.impl.types
1818

19-
import org.jacodb.api.JcField
20-
import org.jacodb.api.JcRefType
21-
import org.jacodb.api.JcType
22-
import org.jacodb.api.JcTypedField
19+
import org.jacodb.api.*
2320
import org.jacodb.api.ext.isNullable
24-
import org.jacodb.api.throwClassNotFound
2521
import org.jacodb.impl.bytecode.JcAnnotationImpl
2622
import org.jacodb.impl.bytecode.JcFieldImpl
2723
import org.jacodb.impl.types.signature.FieldResolutionImpl
2824
import org.jacodb.impl.types.signature.FieldSignature
29-
import org.jacodb.impl.types.substition.JcSubstitutor
3025
import kotlin.LazyThreadSafetyMode.PUBLICATION
3126

3227
class JcTypedFieldImpl(

jacodb-core/src/main/kotlin/org/jacodb/impl/types/JcTypedMethodImpl.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import org.jacodb.impl.types.signature.FieldResolutionImpl
2626
import org.jacodb.impl.types.signature.FieldSignature
2727
import org.jacodb.impl.types.signature.MethodResolutionImpl
2828
import org.jacodb.impl.types.signature.MethodSignature
29-
import org.jacodb.impl.types.substition.JcSubstitutor
29+
import org.jacodb.impl.types.substition.JcSubstitutorImpl
3030
import org.objectweb.asm.Type
3131
import org.objectweb.asm.tree.LocalVariableNode
3232

@@ -54,7 +54,7 @@ class JcTypedMethodImpl(
5454
val substitutor = if (!method.isStatic) {
5555
parentSubstitutor.newScope(impl?.typeVariables.orEmpty())
5656
} else {
57-
JcSubstitutor.empty.newScope(impl?.typeVariables.orEmpty())
57+
JcSubstitutorImpl.empty.newScope(impl?.typeVariables.orEmpty())
5858
}
5959

6060
TypedMethodInfo(

jacodb-core/src/main/kotlin/org/jacodb/impl/types/JcTypedMethodParameterImpl.kt

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,10 @@
1616

1717
package org.jacodb.impl.types
1818

19-
import org.jacodb.api.JcParameter
20-
import org.jacodb.api.JcRefType
21-
import org.jacodb.api.JcType
22-
import org.jacodb.api.JcTypedMethod
23-
import org.jacodb.api.JcTypedMethodParameter
19+
import org.jacodb.api.*
2420
import org.jacodb.api.ext.isNullable
25-
import org.jacodb.api.throwClassNotFound
2621
import org.jacodb.impl.bytecode.JcAnnotationImpl
2722
import org.jacodb.impl.bytecode.JcMethodImpl
28-
import org.jacodb.impl.types.signature.JvmType
29-
import org.jacodb.impl.types.substition.JcSubstitutor
3023

3124
class JcTypedMethodParameterImpl(
3225
override val enclosingMethod: JcTypedMethod,

jacodb-core/src/main/kotlin/org/jacodb/impl/types/TypeParameters.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@
1717
package org.jacodb.impl.types
1818

1919
import kotlinx.collections.immutable.toPersistentMap
20-
import org.jacodb.api.JcAccessible
21-
import org.jacodb.api.JcClassOrInterface
22-
import org.jacodb.api.JcMethod
23-
import org.jacodb.api.JcRefType
24-
import org.jacodb.api.JcTypeVariableDeclaration
25-
import org.jacodb.impl.types.signature.JvmTypeParameterDeclaration
20+
import org.jacodb.api.*
2621
import org.jacodb.impl.types.signature.MethodResolutionImpl
2722
import org.jacodb.impl.types.signature.MethodSignature
2823
import org.jacodb.impl.types.signature.TypeResolutionImpl

0 commit comments

Comments
 (0)