All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jacodb.impl.JcClasspathImpl.kt Maven / Gradle / Ivy

There is a newer version: 1.4.5
Show newest version
/*
 *  Copyright 2022 UnitTestBot contributors (utbot.org)
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jacodb.impl import kotlinx.coroutines.* import org.jacodb.api.* import org.jacodb.api.JcClasspathExtFeature.JcResolvedClassResult import org.jacodb.api.JcClasspathExtFeature.JcResolvedTypeResult import org.jacodb.api.ext.toType import org.jacodb.impl.bytecode.JcClassOrInterfaceImpl import org.jacodb.impl.features.JcFeatureEventImpl import org.jacodb.impl.features.JcFeaturesChain import org.jacodb.impl.features.classpaths.AbstractJcResolvedResult.JcResolvedClassResultImpl import org.jacodb.impl.features.classpaths.AbstractJcResolvedResult.JcResolvedTypeResultImpl import org.jacodb.impl.features.classpaths.JcUnknownClass import org.jacodb.impl.features.classpaths.UnknownClasses import org.jacodb.impl.features.classpaths.isResolveAllToUnknown import org.jacodb.impl.fs.ClassSourceImpl import org.jacodb.impl.types.JcArrayTypeImpl import org.jacodb.impl.types.JcClassTypeImpl import org.jacodb.impl.types.substition.JcSubstitutor import org.jacodb.impl.vfs.ClasspathVfs import org.jacodb.impl.vfs.GlobalClassesVfs class JcClasspathImpl( private val locationsRegistrySnapshot: LocationsRegistrySnapshot, override val db: JcDatabaseImpl, override val features: List, globalClassVFS: GlobalClassesVfs ) : JcClasspath { override val locations: List = locationsRegistrySnapshot.locations.mapNotNull { it.jcLocation } override val registeredLocations: List = locationsRegistrySnapshot.locations private val classpathVfs = ClasspathVfs(globalClassVFS, locationsRegistrySnapshot) private val featuresChain = run{ val strictFeatures = features.filter { it !is UnknownClasses } val hasUnknownClasses = strictFeatures.size != features.size JcFeaturesChain(strictFeatures + listOfNotNull(JcClasspathFeatureImpl(), UnknownClasses.takeIf { hasUnknownClasses }) ) } override suspend fun refreshed(closeOld: Boolean): JcClasspath { return db.new(this).also { if (closeOld) { close() } } } override fun findClassOrNull(name: String): JcClassOrInterface? { return featuresChain.call { it.tryFindClass(this, name) }?.clazz } override fun typeOf( jcClass: JcClassOrInterface, nullability: Boolean?, annotations: List ): JcRefType { return JcClassTypeImpl( this, jcClass.name, jcClass.outerClass?.toType() as? JcClassTypeImpl, JcSubstitutor.empty, nullability, annotations ) } override fun arrayTypeOf(elementType: JcType, nullability: Boolean?, annotations: List): JcArrayType { return JcArrayTypeImpl(elementType, nullability, annotations) } override fun toJcClass(source: ClassSource): JcClassOrInterface { return JcClassOrInterfaceImpl(this, source, featuresChain) } override fun findTypeOrNull(name: String): JcType? { return featuresChain.call { it.tryFindType(this, name) }?.type } override suspend fun execute(task: T): T { val locations = registeredLocations.filter { task.shouldProcess(it) } task.before(this) withContext(Dispatchers.IO) { val parentScope = this locations.map { async { val sources = db.persistence.findClassSources(db, it) .takeIf { it.isNotEmpty() } ?: it.jcLocation?.classes?.map { entry -> ClassSourceImpl(location = it, className = entry.key, byteCode = entry.value) } ?: emptyList() sources.forEach { if (parentScope.isActive && task.shouldProcess(it)) { task.process(it, this@JcClasspathImpl) } } } }.joinAll() } task.after(this) return task } override fun findClasses(name: String): Set { return featuresChain.features.filterIsInstance().flatMap { feature -> feature.findClasses(this, name).orEmpty() }.toSet() } override fun isInstalled(feature: JcClasspathFeature): Boolean { return featuresChain.features.contains(feature) } override fun close() { locationsRegistrySnapshot.close() } private inner class JcClasspathFeatureImpl : JcClasspathExtFeature { override fun tryFindClass(classpath: JcClasspath, name: String): JcResolvedClassResult? { val source = classpathVfs.firstClassOrNull(name) val jcClass = source?.let { toJcClass(it.source) } ?: db.persistence.findClassSourceByName(classpath, name)?.let { toJcClass(it) } if (jcClass == null && isResolveAllToUnknown) { return null } return JcResolvedClassResultImpl(name, jcClass) } override fun tryFindType(classpath: JcClasspath, name: String): JcResolvedTypeResult? { if (name.endsWith("[]")) { val targetName = name.removeSuffix("[]") return JcResolvedTypeResultImpl(name, findTypeOrNull(targetName)?.let { JcArrayTypeImpl(it, true) } ) } val predefined = PredefinedPrimitives.of(name, classpath) if (predefined != null) { return JcResolvedTypeResultImpl(name, predefined) } return when (val clazz = findClassOrNull(name)) { null -> JcResolvedTypeResultImpl(name, null) is JcUnknownClass -> null // delegating to UnknownClass feature else -> JcResolvedTypeResultImpl(name, typeOf(clazz)) } } override fun findClasses(classpath: JcClasspath, name: String): List { val vfsClasses = classpathVfs.findClassNodes(name).map { toJcClass(it.source) } val persistedClasses = db.persistence.findClassSources(classpath, name).map { toJcClass(it) } return buildSet { addAll(vfsClasses) addAll(persistedClasses) }.toList() } override fun event(result: Any): JcFeatureEvent { return JcFeatureEventImpl(this, result) } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy