Skip to content

Commit

Permalink
[kotlin2cpg] Round 3 of refactorings (joernio#4557)
Browse files Browse the repository at this point in the history
  • Loading branch information
max-leuthaeuser authored May 14, 2024
1 parent 78754ee commit 91614ff
Show file tree
Hide file tree
Showing 14 changed files with 75 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import io.joern.kotlin2cpg.interop.JavasrcInterop
import io.joern.kotlin2cpg.jar4import.UsesService
import io.joern.kotlin2cpg.passes.*
import io.joern.kotlin2cpg.types.{ContentSourcesPicker, DefaultTypeInfoProvider, TypeRenderer}
import io.joern.kotlin2cpg.utils.PathUtils
import io.joern.x2cpg.SourceFiles
import io.joern.x2cpg.X2CpgFrontend
import io.joern.x2cpg.X2Cpg.withNewEmptyCpg
Expand Down Expand Up @@ -228,13 +227,12 @@ class Kotlin2Cpg extends X2CpgFrontend[Config] with UsesService {
new MetaDataPass(cpg, Languages.KOTLIN, config.inputPath).createAndApply()

val typeRenderer = new TypeRenderer(config.keepTypeArguments)
val astCreator =
new AstCreationPass(sourceFiles, new DefaultTypeInfoProvider(environment, typeRenderer), cpg)(
config.schemaValidation
)
val astCreator = new AstCreationPass(sourceFiles, new DefaultTypeInfoProvider(environment, typeRenderer), cpg)(
config.schemaValidation
)
astCreator.createAndApply()

val kotlinAstCreatorTypes = astCreator.global.usedTypes.keys().asScala.toList
val kotlinAstCreatorTypes = astCreator.usedTypes()
TypeNodePass.withRegisteredTypes(kotlinAstCreatorTypes, cpg).createAndApply()

runJavasrcInterop(cpg, sourceDir, config, filesWithJavaExtension, kotlinAstCreatorTypes)
Expand Down Expand Up @@ -295,47 +293,26 @@ class Kotlin2Cpg extends X2CpgFrontend[Config] with UsesService {
}

private def entriesForSources(files: Iterable[KtFile], relativeTo: String): Iterable[KtFileWithMeta] = {
files
.flatMap { f =>
try {
val relPath = PathUtils.relativize(relativeTo, f.getVirtualFilePath)
Some(f, relPath)
} catch {
case _: Throwable => None
}
}
.map { fwp =>
KtFileWithMeta(fwp._1, fwp._2, fwp._1.getVirtualFilePath)
}
.filterNot { fwp =>
// TODO: add test for this type of filtering
// TODO: support Windows paths
val willFilter = SourceFilesPicker.shouldFilter(fwp.relativizedPath)
if (willFilter) {
logger.debug(s"Filtered file at `${fwp.f.getVirtualFilePath}`.")
}
willFilter
val filesWithMeta = for {
file <- files
relPath <- Try(SourceFiles.toRelativePath(file.getVirtualFilePath, relativeTo)).toOption
} yield KtFileWithMeta(file, relPath, file.getVirtualFilePath)
filesWithMeta.filterNot { fwp =>
// TODO: add test for this type of filtering
// TODO: support Windows paths
val willFilter = SourceFilesPicker.shouldFilter(fwp.relativizedPath)
if (willFilter) {
logger.debug(s"Filtered file at `${fwp.f.getVirtualFilePath}`.")
}
willFilter
}
}

private def entriesForConfigFiles(paths: Seq[String], relativeTo: String): Seq[FileContentAtPath] = {
paths
.flatMap { fileName =>
try {
val relPath = PathUtils.relativize(relativeTo, fileName)
Some(fileName, relPath)
} catch {
case _: Throwable => None
}
}
.map { fnm =>
val fileContents =
try {
IOUtils.readLinesInFile(Paths.get(fnm._1)).mkString("\n")
} catch {
case t: Throwable => s"$parsingError\n${t.toString}"
}
FileContentAtPath(fileContents, fnm._2, fnm._1)
}
private def entriesForConfigFiles(paths: Seq[String], sourceDir: String): Seq[FileContentAtPath] = {
for {
fileName <- paths
relPath <- Try(SourceFiles.toRelativePath(fileName, sourceDir)).toOption
fileContents <- Try(IOUtils.readEntireFile(Paths.get(fileName))).toOption
} yield FileContentAtPath(fileContents, relPath, fileName)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.joern.kotlin2cpg.ast

import io.joern.kotlin2cpg.Constants
import io.joern.kotlin2cpg.types.CallKinds
import io.joern.kotlin2cpg.types.CallKind
import io.joern.kotlin2cpg.types.TypeConstants
import io.joern.kotlin2cpg.types.TypeInfoProvider
import io.joern.x2cpg.Ast
Expand Down Expand Up @@ -285,18 +285,18 @@ trait AstForExpressionsCreator(implicit withSchemaValidation: ValidationMode) {

private def astForQualifiedExpressionWithReceiverEdge(
expr: KtQualifiedExpression,
callKind: CallKinds.CallKind,
callKind: CallKind,
argIdx: Option[Int],
argNameMaybe: Option[String]
)(implicit typeInfoProvider: TypeInfoProvider): Ast = {
val isDynamicCall = callKind == CallKinds.DynamicCall
val isStaticCall = callKind == CallKinds.StaticCall
val isDynamicCall = callKind == CallKind.DynamicCall
val isStaticCall = callKind == CallKind.StaticCall
val argIdxForReceiver =
if (isDynamicCall) 0
else if (isStaticCall) 1
else 1
val dispatchType =
if (callKind == CallKinds.DynamicCall) DispatchTypes.DYNAMIC_DISPATCH
if (callKind == CallKind.DynamicCall) DispatchTypes.DYNAMIC_DISPATCH
else DispatchTypes.STATIC_DISPATCH

val receiverAst = astsForExpression(expr.getReceiverExpression, Some(argIdxForReceiver)).headOption
Expand Down Expand Up @@ -339,7 +339,7 @@ trait AstForExpressionsCreator(implicit withSchemaValidation: ValidationMode) {
annotations: Seq[KtAnnotationEntry] = Seq()
)(implicit typeInfoProvider: TypeInfoProvider): Ast = {
val callKind = typeInfoProvider.bindingKind(expr)
val isExtensionCall = callKind == CallKinds.ExtensionCall
val isExtensionCall = callKind == CallKind.ExtensionCall

val hasThisSuperOrNameRefReceiver = expr.getReceiverExpression match {
case _: KtThisExpression => true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ object CompilerAPI {
}
}

class CompilerAPI {}

class ErrorLoggingMessageCollector extends MessageCollector {
private val logger = LoggerFactory.getLogger(getClass)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.joern.kotlin2cpg.files

import io.joern.kotlin2cpg.utils.PathUtils
import io.joern.x2cpg.SourceFiles

import org.slf4j.LoggerFactory
Expand Down Expand Up @@ -63,9 +62,7 @@ object SourceFilesPicker {
sourceFileNames
.filter(isConfigFile)
.filterNot { fileName =>
// TODO: add test for this type of filtering
// TODO: support Windows paths
val relativized = PathUtils.relativize(forDir, fileName)
val relativized = SourceFiles.toRelativePath(fileName, forDir)
val willFilter = SourceFilesPicker.shouldFilter(relativized)
if (willFilter) {
logger.debug(s"Filtered file at `$fileName`.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ import io.shiftleft.codepropertygraph.Cpg
import io.shiftleft.passes.ConcurrentWriterCpgPass
import org.slf4j.LoggerFactory

import scala.jdk.CollectionConverters.EnumerationHasAsScala

class AstCreationPass(filesWithMeta: Iterable[KtFileWithMeta], typeInfoProvider: TypeInfoProvider, cpg: Cpg)(implicit
withSchemaValidation: ValidationMode
) extends ConcurrentWriterCpgPass[KtFileWithMeta](cpg) {
val global: Global = new Global()
private val logger = LoggerFactory.getLogger(getClass)

override def generateParts(): Array[KtFileWithMeta] =
filesWithMeta.toArray
private val logger = LoggerFactory.getLogger(getClass)
private val global: Global = new Global()

def usedTypes(): List[String] = global.usedTypes.keys().asScala.toList

override def generateParts(): Array[KtFileWithMeta] = filesWithMeta.toArray

override def runOnPart(diffGraph: DiffGraphBuilder, fileWithMeta: KtFileWithMeta): Unit = {
diffGraph.absorb(new AstCreator(fileWithMeta, typeInfoProvider, global).createAst())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,16 @@ import io.shiftleft.passes.ConcurrentWriterCpgPass
import org.slf4j.LoggerFactory

class ConfigPass(fileContentsAtPath: Iterable[FileContentAtPath], cpg: Cpg)
extends ConcurrentWriterCpgPass[String](cpg) {
extends ConcurrentWriterCpgPass[FileContentAtPath](cpg) {

private val logger = LoggerFactory.getLogger(getClass)

override def generateParts(): Array[String] =
fileContentsAtPath.map { entry => entry.filename }.toArray
override def generateParts(): Array[FileContentAtPath] = fileContentsAtPath.toArray

override def runOnPart(diffGraph: DiffGraphBuilder, fileName: String): Unit = {
val contentsAtPath = fileContentsAtPath.find(_.filename == fileName)
contentsAtPath match {
case Some(fm) =>
val configNode = NewConfigFile().name(fm.relativizedPath).content(fm.content)
diffGraph.addNode(configNode)
logger.debug(s"Adding file `$fileName` as config.")
case None =>
logger.info(s"Could not find file at `$fileName`.")
}
override def runOnPart(diffGraph: DiffGraphBuilder, fileContent: FileContentAtPath): Unit = {
logger.debug(s"Adding file `${fileContent.filename}` as config.")
val configNode = NewConfigFile().name(fileContent.relativizedPath).content(fileContent.content)
diffGraph.addNode(configNode)
}

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package io.joern.kotlin2cpg.psi

import org.jetbrains.kotlin.com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.{
KtDestructuringDeclaration,
KtDestructuringDeclarationEntry,
KtElement,
KtObjectDeclaration,
KtTreeVisitorVoid
}
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtTreeVisitorVoid

import scala.jdk.CollectionConverters.CollectionHasAsScala

Expand Down Expand Up @@ -42,5 +40,3 @@ object PsiUtils {
outIdx
}
}

class PsiUtils {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.joern.kotlin2cpg.types

enum CallKind {
case Unknown, StaticCall, DynamicCall, ExtensionCall
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -497,27 +497,27 @@ class DefaultTypeInfoProvider(environment: KotlinCoreEnvironment, typeRenderer:
resolvedCallDescriptor(expr).forall(_.getDispatchReceiverParameter == null)
}

def bindingKind(expr: KtQualifiedExpression): CallKinds.CallKind = {
def bindingKind(expr: KtQualifiedExpression): CallKind = {
val isStaticBasedOnStructure = expr.getReceiverExpression.isInstanceOf[KtSuperExpression]
if (isStaticBasedOnStructure) return CallKinds.StaticCall
if (isStaticBasedOnStructure) return CallKind.StaticCall

val isDynamicBasedOnStructure = expr.getReceiverExpression match {
case _: KtArrayAccessExpression => true
case _: KtThisExpression => true
case _ => false
}
if (isDynamicBasedOnStructure) return CallKinds.DynamicCall
if (isDynamicBasedOnStructure) return CallKind.DynamicCall

resolvedCallDescriptor(expr)
.map { desc =>
val isExtension = DescriptorUtils.isExtension(desc)
val isStatic = DescriptorUtils.isStaticDeclaration(desc) || hasStaticDesc(expr)

if (isExtension) CallKinds.ExtensionCall
else if (isStatic) CallKinds.StaticCall
else CallKinds.DynamicCall
if (isExtension) CallKind.ExtensionCall
else if (isStatic) CallKind.StaticCall
else CallKind.DynamicCall
}
.getOrElse(CallKinds.Unknown)
.getOrElse(CallKind.Unknown)
}

def isExtensionFn(fn: KtNamedFunction): Boolean = {
Expand Down Expand Up @@ -879,21 +879,21 @@ class DefaultTypeInfoProvider(environment: KotlinCoreEnvironment, typeRenderer:
.getOrElse(defaultValue)
}

def nameReferenceKind(expr: KtNameReferenceExpression): NameReferenceKinds.NameReferenceKind = {
def nameReferenceKind(expr: KtNameReferenceExpression): NameReferenceKind = {
descriptorForNameReference(expr)
.collect {
case _: ValueDescriptor => NameReferenceKinds.Property
case _: LazyClassDescriptor => NameReferenceKinds.ClassName
case _: LazyJavaClassDescriptor => NameReferenceKinds.ClassName
case _: DeserializedClassDescriptor => NameReferenceKinds.ClassName
case _: EnumEntrySyntheticClassDescriptor => NameReferenceKinds.EnumEntry
case _: ValueDescriptor => NameReferenceKind.Property
case _: LazyClassDescriptor => NameReferenceKind.ClassName
case _: LazyJavaClassDescriptor => NameReferenceKind.ClassName
case _: DeserializedClassDescriptor => NameReferenceKind.ClassName
case _: EnumEntrySyntheticClassDescriptor => NameReferenceKind.EnumEntry
case unhandled: Any =>
logger.debug(
s"Unhandled class in type info fetch in `nameReferenceKind[NameReference]` for `${expr.getText}` with class `${unhandled.getClass}`."
)
NameReferenceKinds.Unknown
NameReferenceKind.Unknown
}
.getOrElse(NameReferenceKinds.Unknown)
.getOrElse(NameReferenceKind.Unknown)
}

def typeFullName(expr: KtPrimaryConstructor | KtSecondaryConstructor, defaultValue: String): String = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.joern.kotlin2cpg.types

enum NameReferenceKind {
case Unknown, ClassName, EnumEntry, LocalVariable, Property
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ trait TypeInfoProvider(val typeRenderer: TypeRenderer = new TypeRenderer()) {

def isReferenceToClass(expr: KtNameReferenceExpression): Boolean

def bindingKind(expr: KtQualifiedExpression): CallKinds.CallKind
def bindingKind(expr: KtQualifiedExpression): CallKind

def fullNameWithSignature(expr: KtQualifiedExpression, or: (String, String)): (String, String)

Expand All @@ -101,7 +101,7 @@ trait TypeInfoProvider(val typeRenderer: TypeRenderer = new TypeRenderer()) {

def hasApplyOrAlsoScopeFunctionParent(expr: KtLambdaExpression): Boolean

def nameReferenceKind(expr: KtNameReferenceExpression): NameReferenceKinds.NameReferenceKind
def nameReferenceKind(expr: KtNameReferenceExpression): NameReferenceKind

def isConstructorCall(expr: KtExpression): Option[Boolean]

Expand Down

This file was deleted.

0 comments on commit 91614ff

Please sign in to comment.