From 7682b74fd4c49dca8227364291e3780621e9669f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Max=20Leuth=C3=A4user?= <1417198+max-leuthaeuser@users.noreply.github.com> Date: Wed, 6 Dec 2023 19:46:40 +0100 Subject: [PATCH] [jssrc2cpg] Fix race condition for registering types (#3900) This is for: https://github.com/joernio/joern/issues/3869 (Also applied the same for swiftsrc2cpg with this PR as it uses mostly the same mechanics) --- .../scala/io/joern/jssrc2cpg/JsSrc2Cpg.scala | 6 +-- .../jssrc2cpg/astcreation/AstCreator.scala | 7 +--- .../astcreation/AstCreatorHelper.scala | 10 +---- .../astcreation/AstForTypesCreator.scala | 10 ++--- .../astcreation/AstNodeBuilder.scala | 2 +- .../jssrc2cpg/astcreation/TypeHelper.scala | 2 +- .../jssrc2cpg/datastructures/JsGlobal.scala | 16 ++++++++ .../jssrc2cpg/passes/AstCreationPass.scala | 9 +---- .../jssrc2cpg/passes/BuiltinTypesPass.scala | 40 ------------------- ...ass.scala => JavaScriptMetaDataPass.scala} | 2 +- .../passes/JavaScriptTypeNodePass.scala | 28 +++++++++++++ .../joern/jssrc2cpg/passes/TypeNodePass.scala | 18 --------- .../jssrc2cpg/passes/AbstractPassTest.scala | 8 ++-- .../passes/BuiltinTypesPassTest.scala | 32 --------------- .../jssrc2cpg/passes/JsMetaDataPassTest.scala | 2 +- .../joern/jssrc2cpg/types/TSTypesTest.scala | 20 ++++++++-- .../io/joern/swiftsrc2cpg/SwiftSrc2Cpg.scala | 3 +- .../swiftsrc2cpg/astcreation/AstCreator.scala | 7 +--- .../astcreation/AstCreatorHelper.scala | 10 +---- .../astcreation/AstForDeclSyntaxCreator.scala | 2 +- .../astcreation/AstForSyntaxCreator.scala | 2 +- .../astcreation/AstNodeBuilder.scala | 2 +- .../datastructures/SwiftGlobal.scala | 16 ++++++++ .../swiftsrc2cpg/passes/AstCreationPass.scala | 7 +--- .../passes/SwiftInheritanceNamePass.scala | 3 +- .../passes/SwiftTypeNodePass.scala | 28 +++++++++++++ .../swiftsrc2cpg/passes/TypeNodePass.scala | 18 --------- .../passes/ast/AbstractPassTest.scala | 3 ++ .../x2cpg/passes/frontend/TypeNodePass.scala | 33 +++++++-------- 29 files changed, 156 insertions(+), 190 deletions(-) create mode 100644 joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/datastructures/JsGlobal.scala delete mode 100644 joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/BuiltinTypesPass.scala rename joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/{JsMetaDataPass.scala => JavaScriptMetaDataPass.scala} (85%) create mode 100644 joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/JavaScriptTypeNodePass.scala delete mode 100644 joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/TypeNodePass.scala delete mode 100644 joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/BuiltinTypesPassTest.scala create mode 100644 joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/datastructures/SwiftGlobal.scala create mode 100644 joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/SwiftTypeNodePass.scala delete mode 100644 joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/TypeNodePass.scala diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/JsSrc2Cpg.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/JsSrc2Cpg.scala index c092e9ac0ccb..5205471ee673 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/JsSrc2Cpg.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/JsSrc2Cpg.scala @@ -3,6 +3,7 @@ package io.joern.jssrc2cpg import better.files.File import io.joern.dataflowengineoss.layers.dataflows.{OssDataFlow, OssDataFlowOptions} import io.joern.jssrc2cpg.JsSrc2Cpg.postProcessingPasses +import io.joern.jssrc2cpg.datastructures.JsGlobal import io.joern.jssrc2cpg.passes.* import io.joern.jssrc2cpg.utils.AstGenRunner import io.joern.x2cpg.X2Cpg.withNewEmptyCpg @@ -29,9 +30,8 @@ class JsSrc2Cpg extends X2CpgFrontend[Config] { val astCreationPass = new AstCreationPass(cpg, astGenResult, config, report)(config.schemaValidation) astCreationPass.createAndApply() - new TypeNodePass(astCreationPass.allUsedTypes(), cpg).createAndApply() - new JsMetaDataPass(cpg, hash, config.inputPath).createAndApply() - new BuiltinTypesPass(cpg).createAndApply() + JavaScriptTypeNodePass.withRegisteredTypes(JsGlobal.typesSeen(), cpg).createAndApply() + new JavaScriptMetaDataPass(cpg, hash, config.inputPath).createAndApply() new DependenciesPass(cpg, config).createAndApply() new ConfigPass(cpg, config, report).createAndApply() new PrivateKeyFilePass(cpg, config, report).createAndApply() diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreator.scala index 5f98e8c51ad3..ece6a14922ce 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreator.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreator.scala @@ -20,14 +20,9 @@ import org.slf4j.{Logger, LoggerFactory} import overflowdb.BatchedUpdate.DiffGraphBuilder import ujson.Value -import java.util.concurrent.ConcurrentHashMap import scala.collection.mutable -class AstCreator( - val config: Config, - val parserResult: ParseResult, - val usedTypes: ConcurrentHashMap[(String, String), Boolean] -)(implicit withSchemaValidation: ValidationMode) +class AstCreator(val config: Config, val parserResult: ParseResult)(implicit withSchemaValidation: ValidationMode) extends AstCreatorBase(parserResult.filename) with AstForExpressionsCreator with AstForPrimitivesCreator diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreatorHelper.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreatorHelper.scala index 3d6df408f1b8..bad2597573c8 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreatorHelper.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstCreatorHelper.scala @@ -11,7 +11,6 @@ import io.shiftleft.codepropertygraph.generated.{EdgeTypes, EvaluationStrategies import ujson.Value import scala.collection.{SortedMap, mutable} -import scala.jdk.CollectionConverters.EnumerationHasAsScala import scala.util.{Success, Try} trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: AstCreator => @@ -38,13 +37,8 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As Ast(unknownNode(node, node.code)) } - protected def registerType(typeName: String, typeFullName: String): Unit = { - if (usedTypes.containsKey((typeName, typeName)) && typeName != typeFullName) { - usedTypes.put((typeName, typeFullName), true) - usedTypes.remove((typeName, typeName)) - } else if (!usedTypes.keys().asScala.exists { case (tpn, _) => tpn == typeName }) { - usedTypes.putIfAbsent((typeName, typeFullName), true) - } + protected def registerType(typeFullName: String): Unit = { + JsGlobal.usedTypes.putIfAbsent(typeFullName, true) } private def nodeType(node: Value): BabelNode = fromString(node("type").str) diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTypesCreator.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTypesCreator.scala index 12f1ec365237..463d7f685987 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTypesCreator.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstForTypesCreator.scala @@ -22,7 +22,7 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this: } else { typeFor(createBabelNodeInfo(alias.json)) } - registerType(aliasName, aliasFullName) + registerType(aliasFullName) val astParentType = methodAstParentStack.head.label val astParentFullName = methodAstParentStack.head.properties("FULL_NAME").toString @@ -43,7 +43,7 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this: astParentFullName, alias = Option(aliasFullName) ) - registerType(typeName, typeFullName) + registerType(typeFullName) diffGraph.addEdge(methodAstParentStack.head, typeDeclNode_, EdgeTypes.AST) } else { seenAliasTypes.find(t => t.name == name).foreach(_.aliasTypeFullName(aliasFullName)) @@ -217,7 +217,7 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this: protected def astForEnum(tsEnum: BabelNodeInfo): Ast = { val (typeName, typeFullName) = calcTypeNameAndFullName(tsEnum) - registerType(typeName, typeFullName) + registerType(typeFullName) val astParentType = methodAstParentStack.head.label val astParentFullName = methodAstParentStack.head.properties("FULL_NAME").toString @@ -299,7 +299,7 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this: protected def astForClass(clazz: BabelNodeInfo, shouldCreateAssignmentCall: Boolean = false): Ast = { val (typeName, typeFullName) = calcTypeNameAndFullName(clazz) - registerType(typeName, typeFullName) + registerType(typeFullName) val astParentType = methodAstParentStack.head.label val astParentFullName = methodAstParentStack.head.properties("FULL_NAME").toString @@ -452,7 +452,7 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this: protected def astForInterface(tsInterface: BabelNodeInfo): Ast = { val (typeName, typeFullName) = calcTypeNameAndFullName(tsInterface) - registerType(typeName, typeFullName) + registerType(typeFullName) val astParentType = methodAstParentStack.head.label val astParentFullName = methodAstParentStack.head.properties("FULL_NAME").toString diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstNodeBuilder.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstNodeBuilder.scala index 110f2a9759da..c42e5b7aed89 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstNodeBuilder.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/AstNodeBuilder.scala @@ -265,7 +265,7 @@ trait AstNodeBuilder(implicit withSchemaValidation: ValidationMode) { this: AstC methodFullName: String, filename: String ): Ast = { - registerType(methodName, methodFullName) + registerType(methodFullName) val astParentType = parentNode.label val astParentFullName = parentNode.properties("FULL_NAME").toString diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/TypeHelper.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/TypeHelper.scala index 012ca8e33a85..4a2d2da14287 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/TypeHelper.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/astcreation/TypeHelper.scala @@ -123,7 +123,7 @@ trait TypeHelper { this: AstCreator => case Some(key) => typeForTypeAnnotation(createBabelNodeInfo(node.json(key))) case None => typeFromTypeMap(node) } - registerType(tpe, tpe) + registerType(tpe) tpe } diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/datastructures/JsGlobal.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/datastructures/JsGlobal.scala new file mode 100644 index 000000000000..b12ff618e2ed --- /dev/null +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/datastructures/JsGlobal.scala @@ -0,0 +1,16 @@ +package io.joern.jssrc2cpg.datastructures + +import io.joern.jssrc2cpg.passes.Defines +import io.joern.x2cpg.datastructures.Global + +import scala.jdk.CollectionConverters._ + +object JsGlobal extends Global { + + def typesSeen(): List[String] = { + val types = usedTypes.keys().asScala.filterNot(_ == Defines.Any).toList + usedTypes.clear() + types + } + +} diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/AstCreationPass.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/AstCreationPass.scala index 99f1b30a18ac..fb6f6ea449ce 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/AstCreationPass.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/AstCreationPass.scala @@ -12,8 +12,6 @@ import io.shiftleft.utils.IOUtils import org.slf4j.{Logger, LoggerFactory} import java.nio.file.Paths -import java.util.concurrent.ConcurrentHashMap -import scala.jdk.CollectionConverters.EnumerationHasAsScala import scala.util.{Failure, Success, Try} class AstCreationPass(cpg: Cpg, astGenRunnerResult: AstGenRunnerResult, config: Config, report: Report = new Report())( @@ -22,13 +20,8 @@ class AstCreationPass(cpg: Cpg, astGenRunnerResult: AstGenRunnerResult, config: private val logger: Logger = LoggerFactory.getLogger(classOf[AstCreationPass]) - private val usedTypes: ConcurrentHashMap[(String, String), Boolean] = new ConcurrentHashMap() - override def generateParts(): Array[(String, String)] = astGenRunnerResult.parsedFiles.toArray - def allUsedTypes(): List[(String, String)] = - usedTypes.keys().asScala.filterNot { case (typeName, _) => typeName == Defines.Any }.toList - override def finish(): Unit = { astGenRunnerResult.skippedFiles.foreach { skippedFile => val (rootPath, fileName) = skippedFile @@ -45,7 +38,7 @@ class AstCreationPass(cpg: Cpg, astGenRunnerResult: AstGenRunnerResult, config: val fileLOC = IOUtils.readLinesInFile(Paths.get(parseResult.fullPath)).size report.addReportInfo(parseResult.filename, fileLOC, parsed = true) Try { - val localDiff = new AstCreator(config, parseResult, usedTypes).createAst() + val localDiff = new AstCreator(config, parseResult).createAst() diffGraph.absorb(localDiff) } match { case Failure(exception) => diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/BuiltinTypesPass.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/BuiltinTypesPass.scala deleted file mode 100644 index e3aa66f25281..000000000000 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/BuiltinTypesPass.scala +++ /dev/null @@ -1,40 +0,0 @@ -package io.joern.jssrc2cpg.passes - -import io.shiftleft.codepropertygraph.Cpg -import io.shiftleft.codepropertygraph.generated.nodes.{NewNamespaceBlock, NewType, NewTypeDecl} -import io.shiftleft.codepropertygraph.generated.{EdgeTypes, NodeTypes} -import io.shiftleft.passes.CpgPass - -class BuiltinTypesPass(cpg: Cpg) extends CpgPass(cpg) { - - override def run(diffGraph: DiffGraphBuilder): Unit = { - val namespaceBlock = NewNamespaceBlock() - .name(Defines.GlobalNamespace) - .fullName(Defines.GlobalNamespace) - .order(0) - .filename("builtintypes") - - diffGraph.addNode(namespaceBlock) - - Defines.JsTypes.zipWithIndex.map { case (typeName: String, index) => - val tpe = NewType() - .name(typeName) - .fullName(typeName) - .typeDeclFullName(typeName) - diffGraph.addNode(tpe) - - val typeDecl = NewTypeDecl() - .name(typeName) - .fullName(typeName) - .isExternal(true) - .astParentType(NodeTypes.NAMESPACE_BLOCK) - .astParentFullName(Defines.GlobalNamespace) - .order(index + 1) - .filename("builtintypes") - - diffGraph.addNode(typeDecl) - diffGraph.addEdge(namespaceBlock, typeDecl, EdgeTypes.AST) - } - } - -} diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/JsMetaDataPass.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/JavaScriptMetaDataPass.scala similarity index 85% rename from joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/JsMetaDataPass.scala rename to joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/JavaScriptMetaDataPass.scala index d855656b879a..471d27a358e7 100644 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/JsMetaDataPass.scala +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/JavaScriptMetaDataPass.scala @@ -6,7 +6,7 @@ import io.shiftleft.codepropertygraph.generated.nodes.NewMetaData import io.shiftleft.codepropertygraph.generated.Languages import io.shiftleft.passes.CpgPass -class JsMetaDataPass(cpg: Cpg, hash: String, inputPath: String) extends CpgPass(cpg) { +class JavaScriptMetaDataPass(cpg: Cpg, hash: String, inputPath: String) extends CpgPass(cpg) { override def run(diffGraph: DiffGraphBuilder): Unit = { val absolutePathToRoot = File(inputPath).path.toAbsolutePath.toString diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/JavaScriptTypeNodePass.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/JavaScriptTypeNodePass.scala new file mode 100644 index 000000000000..3419951e5744 --- /dev/null +++ b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/JavaScriptTypeNodePass.scala @@ -0,0 +1,28 @@ +package io.joern.jssrc2cpg.passes + +import io.joern.x2cpg.passes.frontend.TypeNodePass +import io.shiftleft.codepropertygraph.Cpg +import io.shiftleft.semanticcpg.language._ +import io.shiftleft.passes.KeyPool + +import scala.collection.mutable + +object JavaScriptTypeNodePass { + + def withRegisteredTypes(registeredTypes: List[String], cpg: Cpg, keyPool: Option[KeyPool] = None): TypeNodePass = { + new TypeNodePass(registeredTypes, cpg, keyPool, getTypesFromCpg = false) { + + override protected def typeDeclTypes: mutable.Set[String] = { + // The only difference to the default implementation in TypeNodePass.typeDeclTypes is the following: + // We do not want to add types for types being inherited as this is already handled by the JavaScriptInheritanceNamePass. + val typeDeclTypes = mutable.Set[String]() + cpg.typeDecl.foreach { typeDecl => + typeDeclTypes += typeDecl.fullName + } + typeDeclTypes + } + + } + } + +} diff --git a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/TypeNodePass.scala b/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/TypeNodePass.scala deleted file mode 100644 index dc2964d3c4ed..000000000000 --- a/joern-cli/frontends/jssrc2cpg/src/main/scala/io/joern/jssrc2cpg/passes/TypeNodePass.scala +++ /dev/null @@ -1,18 +0,0 @@ -package io.joern.jssrc2cpg.passes - -import io.shiftleft.codepropertygraph.Cpg -import io.shiftleft.codepropertygraph.generated.nodes.NewType -import io.shiftleft.passes.CpgPass - -class TypeNodePass(usedTypes: List[(String, String)], cpg: Cpg) extends CpgPass(cpg, "types") { - override def run(diffGraph: DiffGraphBuilder): Unit = { - val filteredTypes = usedTypes.filterNot { case (name, _) => - name == Defines.Any || Defines.JsTypes.contains(name) - } - - filteredTypes.sortBy(_._2).foreach { case (name, fullName) => - val typeNode = NewType().name(name).fullName(fullName).typeDeclFullName(fullName) - diffGraph.addNode(typeNode) - } - } -} diff --git a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/AbstractPassTest.scala b/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/AbstractPassTest.scala index deccbe3d98a7..deab87c9fc4a 100644 --- a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/AbstractPassTest.scala +++ b/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/AbstractPassTest.scala @@ -3,6 +3,7 @@ package io.joern.jssrc2cpg.passes import better.files.File import io.joern.jssrc2cpg.utils.AstGenRunner import io.joern.jssrc2cpg.Config +import io.joern.jssrc2cpg.datastructures.JsGlobal import io.joern.x2cpg.ValidationMode import io.joern.x2cpg.X2Cpg.newEmptyCpg import io.shiftleft.codepropertygraph.Cpg @@ -25,6 +26,7 @@ abstract class AbstractPassTest extends AnyWordSpec with Matchers with Inside { val config = Config(tsTypes = tsTypes).withInputPath(dir.toString).withOutputPath(dir.toString) val astGenResult = new AstGenRunner(config).execute(dir) new AstCreationPass(cpg, astGenResult, config).createAndApply() + JavaScriptTypeNodePass.withRegisteredTypes(JsGlobal.typesSeen(), cpg).createAndApply() f(cpg) file.delete() } @@ -41,8 +43,7 @@ abstract class AbstractPassTest extends AnyWordSpec with Matchers with Inside { val astGenResult = new AstGenRunner(config).execute(dir) val astCreationPass = new AstCreationPass(cpg, astGenResult, config) astCreationPass.createAndApply() - new TypeNodePass(astCreationPass.allUsedTypes(), cpg).createAndApply() - new BuiltinTypesPass(cpg).createAndApply() + JavaScriptTypeNodePass.withRegisteredTypes(JsGlobal.typesSeen(), cpg).createAndApply() f(cpg) file.delete() } @@ -61,8 +62,7 @@ abstract class AbstractPassTest extends AnyWordSpec with Matchers with Inside { val astGenResult = new AstGenRunner(config).execute(dir) val astCreationPass = new AstCreationPass(cpg, astGenResult, config) astCreationPass.createAndApply() - new TypeNodePass(astCreationPass.allUsedTypes(), cpg).createAndApply() - new BuiltinTypesPass(cpg).createAndApply() + JavaScriptTypeNodePass.withRegisteredTypes(JsGlobal.typesSeen(), cpg).createAndApply() f(cpg) file1.delete() file2.delete() diff --git a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/BuiltinTypesPassTest.scala b/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/BuiltinTypesPassTest.scala deleted file mode 100644 index dc18658092c7..000000000000 --- a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/BuiltinTypesPassTest.scala +++ /dev/null @@ -1,32 +0,0 @@ -package io.joern.jssrc2cpg.passes - -import io.shiftleft.codepropertygraph.Cpg -import io.shiftleft.semanticcpg.language._ - -class BuiltinTypesPassTest extends AbstractPassTest { - - "BuiltinTypesPass" should { - val cpg = Cpg.emptyCpg - new BuiltinTypesPass(cpg).createAndApply() - - "create a '' NamespaceBlock" in { - cpg.namespaceBlock.name.l shouldBe List(Defines.GlobalNamespace) - } - - "create types and type decls correctly" in { - Defines.JsTypes.foreach { (typeName: String) => - val List(typeDeclNode) = cpg.typeDecl(typeName).l - typeDeclNode.fullName shouldBe typeName - typeDeclNode.isExternal shouldBe true - typeDeclNode.filename shouldBe "builtintypes" - - cpg.namespaceBlock.astChildren.l should contain(typeDeclNode) - - val List(typeNode) = cpg.typ(typeName).l - typeNode.fullName shouldBe typeName - } - } - - } - -} diff --git a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/JsMetaDataPassTest.scala b/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/JsMetaDataPassTest.scala index ab82114ce5e6..08f9fde05895 100644 --- a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/JsMetaDataPassTest.scala +++ b/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/passes/JsMetaDataPassTest.scala @@ -10,7 +10,7 @@ class JsMetaDataPassTest extends AbstractPassTest { "MetaDataPass" should { val cpg = Cpg.emptyCpg - new JsMetaDataPass(cpg, "somehash", "").createAndApply() + new JavaScriptMetaDataPass(cpg, "somehash", "").createAndApply() "create exactly 1 node" in { cpg.graph.V.asScala.size shouldBe 1 diff --git a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/types/TSTypesTest.scala b/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/types/TSTypesTest.scala index a7e21d89f68b..2413266ce473 100644 --- a/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/types/TSTypesTest.scala +++ b/joern-cli/frontends/jssrc2cpg/src/test/scala/io/joern/jssrc2cpg/types/TSTypesTest.scala @@ -103,12 +103,26 @@ class TSTypesTest extends AbstractPassTest { p2.typeFullName shouldBe Defines.String val List(barRet) = cpg.method("bar").methodReturn.l barRet.typeFullName shouldBe "Foo" - cpg.typ.name.sorted.l shouldBe (List( + cpg.typ.name.sorted.l shouldBe List( ":program", io.joern.x2cpg.Defines.ConstructorMethodName, + "ANY", "Foo", + "Foo", + "Number", + "String", "bar" - ) ++ Defines.JsTypes).sorted + ).sorted + cpg.typ.fullName.sorted.l shouldBe List( + "ANY", + "Foo", + "__ecma.Number", + "__ecma.String", + "code.ts::program", + "code.ts::program:Foo", + "code.ts::program:Foo:", + "code.ts::program:bar" + ).sorted } "have correct types for variables" in TsAstFixture( @@ -248,7 +262,7 @@ class TSTypesTest extends AbstractPassTest { tsTypes = true ) { cpg => cpg.typeDecl("string").l shouldBe empty - cpg.typeDecl(Defines.String).size shouldBe 1 + cpg.typ.fullName(Defines.String).size shouldBe 1 inside(cpg.typeDecl("Alias").l) { case List(alias) => alias.fullName shouldBe "code.ts::program:Alias" alias.code shouldBe "type Alias = string" diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/SwiftSrc2Cpg.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/SwiftSrc2Cpg.scala index 268968cdae25..675c4197605b 100644 --- a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/SwiftSrc2Cpg.scala +++ b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/SwiftSrc2Cpg.scala @@ -2,6 +2,7 @@ package io.joern.swiftsrc2cpg import better.files.File import io.joern.dataflowengineoss.layers.dataflows.{OssDataFlow, OssDataFlowOptions} +import io.joern.swiftsrc2cpg.datastructures.SwiftGlobal import io.joern.swiftsrc2cpg.passes.* import io.joern.swiftsrc2cpg.utils.AstGenRunner import io.joern.x2cpg.X2Cpg.withNewEmptyCpg @@ -28,7 +29,7 @@ class SwiftSrc2Cpg extends X2CpgFrontend[Config] { val astCreationPass = new AstCreationPass(cpg, astGenResult, config, report)(config.schemaValidation) astCreationPass.createAndApply() - new TypeNodePass(astCreationPass.allUsedTypes(), cpg).createAndApply() + SwiftTypeNodePass.withRegisteredTypes(SwiftGlobal.typesSeen(), cpg).createAndApply() new SwiftMetaDataPass(cpg, hash, config.inputPath).createAndApply() new BuiltinTypesPass(cpg).createAndApply() new DependenciesPass(cpg, config).createAndApply() diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstCreator.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstCreator.scala index 71f2a24dcc19..2959dbe1f6e7 100644 --- a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstCreator.scala +++ b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstCreator.scala @@ -20,14 +20,9 @@ import io.shiftleft.codepropertygraph.generated.ModifierTypes import org.slf4j.{Logger, LoggerFactory} import overflowdb.BatchedUpdate.DiffGraphBuilder -import java.util.concurrent.ConcurrentHashMap import scala.collection.mutable -class AstCreator( - val config: Config, - val parserResult: ParseResult, - val usedTypes: ConcurrentHashMap[(String, String), Boolean] -)(implicit withSchemaValidation: ValidationMode) +class AstCreator(val config: Config, val parserResult: ParseResult)(implicit withSchemaValidation: ValidationMode) extends AstCreatorBase(parserResult.filename) with AstForSwiftTokenCreator with AstForSyntaxCreator diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstCreatorHelper.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstCreatorHelper.scala index f09307af633f..ad5ca2063e09 100644 --- a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstCreatorHelper.scala +++ b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstCreatorHelper.scala @@ -12,7 +12,6 @@ import io.shiftleft.codepropertygraph.generated.nodes.NewNamespaceBlock import io.shiftleft.codepropertygraph.generated.nodes.NewTypeDecl import scala.collection.mutable -import scala.jdk.CollectionConverters.EnumerationHasAsScala trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: AstCreator => @@ -28,13 +27,8 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As Ast(unknownNode(node, code(node))) } - protected def registerType(typeName: String, typeFullName: String): Unit = { - if (usedTypes.containsKey((typeName, typeName)) && typeName != typeFullName) { - usedTypes.put((typeName, typeFullName), true) - usedTypes.remove((typeName, typeName)) - } else if (!usedTypes.keys().asScala.exists { case (tpn, _) => tpn == typeName }) { - usedTypes.putIfAbsent((typeName, typeFullName), true) - } + protected def registerType(typeFullName: String): Unit = { + SwiftGlobal.usedTypes.putIfAbsent((typeFullName), true) } protected def generateUnusedVariableName( diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstForDeclSyntaxCreator.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstForDeclSyntaxCreator.scala index 35735b2c4d98..103ebf64eee9 100644 --- a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstForDeclSyntaxCreator.scala +++ b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstForDeclSyntaxCreator.scala @@ -72,7 +72,7 @@ trait AstForDeclSyntaxCreator(implicit withSchemaValidation: ValidationMode) { } val returnType = node.signature.returnClause.map(c => code(c.`type`)).getOrElse(Defines.Any) - registerType(returnType, returnType) + registerType(returnType) val signature = s"$returnType $methodFullName ${code(node.signature.parameterClause)}" diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstForSyntaxCreator.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstForSyntaxCreator.scala index e1eb242060a2..89cfcaf0c37b 100644 --- a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstForSyntaxCreator.scala +++ b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstForSyntaxCreator.scala @@ -116,7 +116,7 @@ trait AstForSyntaxCreator(implicit withSchemaValidation: ValidationMode) { this: // TODO: handle defaultValue val name = code(node.firstName) val tpe = code(node.`type`) - registerType(tpe, tpe) + registerType(tpe) val parameterNode = parameterInNode( node, diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstNodeBuilder.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstNodeBuilder.scala index f212580926a2..664a8b9f67a6 100644 --- a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstNodeBuilder.scala +++ b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/astcreation/AstNodeBuilder.scala @@ -220,7 +220,7 @@ trait AstNodeBuilder(implicit withSchemaValidation: ValidationMode) { this: AstC methodName: String, methodFullName: String ): Ast = { - registerType(methodName, methodFullName) + registerType(methodFullName) val parentNode = methodAstParentStack.head val astParentType = parentNode.label diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/datastructures/SwiftGlobal.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/datastructures/SwiftGlobal.scala new file mode 100644 index 000000000000..7d978b5d9ab0 --- /dev/null +++ b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/datastructures/SwiftGlobal.scala @@ -0,0 +1,16 @@ +package io.joern.swiftsrc2cpg.datastructures + +import io.joern.swiftsrc2cpg.passes.Defines +import io.joern.x2cpg.datastructures.Global + +import scala.jdk.CollectionConverters._ + +object SwiftGlobal extends Global { + + def typesSeen(): List[String] = { + val types = usedTypes.keys().asScala.filterNot(_ == Defines.Any).toList + usedTypes.clear() + types + } + +} diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/AstCreationPass.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/AstCreationPass.scala index ab1a9ea8f833..51d8dee86c3d 100644 --- a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/AstCreationPass.scala +++ b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/AstCreationPass.scala @@ -22,13 +22,8 @@ class AstCreationPass(cpg: Cpg, astGenRunnerResult: AstGenRunnerResult, config: private val logger: Logger = LoggerFactory.getLogger(classOf[AstCreationPass]) - private val usedTypes: ConcurrentHashMap[(String, String), Boolean] = new ConcurrentHashMap() - override def generateParts(): Array[(String, String)] = astGenRunnerResult.parsedFiles.toArray - def allUsedTypes(): List[(String, String)] = - usedTypes.keys().asScala.filterNot { case (typeName, _) => typeName == Defines.Any }.toList - override def finish(): Unit = { astGenRunnerResult.skippedFiles.foreach { skippedFile => val (rootPath, fileName) = skippedFile @@ -45,7 +40,7 @@ class AstCreationPass(cpg: Cpg, astGenRunnerResult: AstGenRunnerResult, config: val fileLOC = IOUtils.readLinesInFile(Paths.get(parseResult.fullPath)).size report.addReportInfo(parseResult.filename, fileLOC, parsed = true) Try { - val localDiff = new AstCreator(config, parseResult, usedTypes).createAst() + val localDiff = new AstCreator(config, parseResult).createAst() diffGraph.absorb(localDiff) } match { case Failure(exception) => diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/SwiftInheritanceNamePass.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/SwiftInheritanceNamePass.scala index 4669efb98f45..b8fee1255f89 100644 --- a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/SwiftInheritanceNamePass.scala +++ b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/SwiftInheritanceNamePass.scala @@ -2,6 +2,7 @@ package io.joern.swiftsrc2cpg.passes import io.joern.x2cpg.passes.frontend.XInheritanceFullNamePass import io.shiftleft.codepropertygraph.Cpg +import io.shiftleft.semanticcpg.language.types.structure.NamespaceTraversal /** Using some basic heuristics, will try to resolve type full names from types found within the CPG. Requires * ImportPass as a pre-requisite. @@ -9,7 +10,7 @@ import io.shiftleft.codepropertygraph.Cpg class SwiftInheritanceNamePass(cpg: Cpg) extends XInheritanceFullNamePass(cpg) { override val pathSep: Char = ':' - override val moduleName: String = "" + override val moduleName: String = NamespaceTraversal.globalNamespaceName override val fileExt: String = ".swift" } diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/SwiftTypeNodePass.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/SwiftTypeNodePass.scala new file mode 100644 index 000000000000..424f91f10c16 --- /dev/null +++ b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/SwiftTypeNodePass.scala @@ -0,0 +1,28 @@ +package io.joern.swiftsrc2cpg.passes + +import io.shiftleft.codepropertygraph.Cpg +import io.joern.x2cpg.passes.frontend.TypeNodePass +import io.shiftleft.semanticcpg.language._ +import io.shiftleft.passes.KeyPool + +import scala.collection.mutable + +object SwiftTypeNodePass { + + def withRegisteredTypes(registeredTypes: List[String], cpg: Cpg, keyPool: Option[KeyPool] = None): TypeNodePass = { + new TypeNodePass(registeredTypes, cpg, keyPool, getTypesFromCpg = false) { + + override protected def typeDeclTypes: mutable.Set[String] = { + // The only difference to the default implementation in TypeNodePass.typeDeclTypes is the following: + // We do not want to add types for types being inherited as this is already handled by the SwiftInheritanceNamePass. + val typeDeclTypes = mutable.Set[String]() + cpg.typeDecl.foreach { typeDecl => + typeDeclTypes += typeDecl.fullName + } + typeDeclTypes + } + + } + } + +} diff --git a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/TypeNodePass.scala b/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/TypeNodePass.scala deleted file mode 100644 index 7a78f0ac1491..000000000000 --- a/joern-cli/frontends/swiftsrc2cpg/src/main/scala/io/joern/swiftsrc2cpg/passes/TypeNodePass.scala +++ /dev/null @@ -1,18 +0,0 @@ -package io.joern.swiftsrc2cpg.passes - -import io.shiftleft.codepropertygraph.Cpg -import io.shiftleft.codepropertygraph.generated.nodes.NewType -import io.shiftleft.passes.CpgPass - -class TypeNodePass(usedTypes: List[(String, String)], cpg: Cpg) extends CpgPass(cpg, "types") { - override def run(diffGraph: DiffGraphBuilder): Unit = { - val filteredTypes = usedTypes.filterNot { case (name, _) => - name == Defines.Any || Defines.SwiftTypes.contains(name) - } - - filteredTypes.sortBy(_._2).foreach { case (name, fullName) => - val typeNode = NewType().name(name).fullName(fullName).typeDeclFullName(fullName) - diffGraph.addNode(typeNode) - } - } -} diff --git a/joern-cli/frontends/swiftsrc2cpg/src/test/scala/io/joern/swiftsrc2cpg/passes/ast/AbstractPassTest.scala b/joern-cli/frontends/swiftsrc2cpg/src/test/scala/io/joern/swiftsrc2cpg/passes/ast/AbstractPassTest.scala index c12422b0eb01..c5e30bf8dcef 100644 --- a/joern-cli/frontends/swiftsrc2cpg/src/test/scala/io/joern/swiftsrc2cpg/passes/ast/AbstractPassTest.scala +++ b/joern-cli/frontends/swiftsrc2cpg/src/test/scala/io/joern/swiftsrc2cpg/passes/ast/AbstractPassTest.scala @@ -3,7 +3,9 @@ package io.joern.swiftsrc2cpg.passes.ast import better.files.File import io.joern.swiftsrc2cpg.utils.AstGenRunner import io.joern.swiftsrc2cpg.Config +import io.joern.swiftsrc2cpg.datastructures.SwiftGlobal import io.joern.swiftsrc2cpg.passes.AstCreationPass +import io.joern.swiftsrc2cpg.passes.SwiftTypeNodePass import io.joern.x2cpg.ValidationMode import io.joern.x2cpg.X2Cpg.newEmptyCpg import io.shiftleft.codepropertygraph.Cpg @@ -26,6 +28,7 @@ abstract class AbstractPassTest extends AnyWordSpec with Matchers with Inside { val config = Config().withInputPath(dir.toString).withOutputPath(dir.toString) val astGenResult = new AstGenRunner(config).execute(dir) new AstCreationPass(cpg, astGenResult, config).createAndApply() + SwiftTypeNodePass.withRegisteredTypes(SwiftGlobal.typesSeen(), cpg).createAndApply() f(cpg) file.delete() } diff --git a/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/passes/frontend/TypeNodePass.scala b/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/passes/frontend/TypeNodePass.scala index ee9d687ed9b0..5483af0eeaa4 100644 --- a/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/passes/frontend/TypeNodePass.scala +++ b/joern-cli/frontends/x2cpg/src/main/scala/io/joern/x2cpg/passes/frontend/TypeNodePass.scala @@ -15,10 +15,14 @@ import io.shiftleft.semanticcpg.language.types.structure.NamespaceTraversal * Alternatively, set `getTypesFromCpg = true`. If this is set, the `registeredTypes` argument will be ignored. * Instead, type nodes will be created for every unique `TYPE_FULL_NAME` value in the CPG. */ -class TypeNodePass private (registeredTypes: List[String], cpg: Cpg, keyPool: Option[KeyPool], getTypesFromCpg: Boolean) - extends CpgPass(cpg, "types", keyPool) { +class TypeNodePass protected ( + registeredTypes: List[String], + cpg: Cpg, + keyPool: Option[KeyPool], + getTypesFromCpg: Boolean +) extends CpgPass(cpg, "types", keyPool) { - private def getTypeDeclTypes(): mutable.Set[String] = { + protected def typeDeclTypes: mutable.Set[String] = { val typeDeclTypes = mutable.Set[String]() cpg.typeDecl.foreach { typeDecl => typeDeclTypes += typeDecl.fullName @@ -27,7 +31,7 @@ class TypeNodePass private (registeredTypes: List[String], cpg: Cpg, keyPool: Op typeDeclTypes } - def getTypeFullNamesFromCpg(): Set[String] = { + protected def typeFullNamesFromCpg: Set[String] = { cpg.all .map(_.property(PropertyNames.TYPE_FULL_NAME)) .filter(_ != null) @@ -38,20 +42,14 @@ class TypeNodePass private (registeredTypes: List[String], cpg: Cpg, keyPool: Op override def run(diffGraph: DiffGraphBuilder): Unit = { val typeFullNameValues = if (getTypesFromCpg) - getTypeFullNamesFromCpg() + typeFullNamesFromCpg else registeredTypes.toSet - val usedTypesSet = getTypeDeclTypes() ++ typeFullNameValues + val usedTypesSet = typeDeclTypes ++ typeFullNameValues usedTypesSet.remove("") - val usedTypes = usedTypesSet.filterInPlace(!_.endsWith(NamespaceTraversal.globalNamespaceName)).toArray.sorted - - diffGraph.addNode( - NewType() - .name("ANY") - .fullName("ANY") - .typeDeclFullName("ANY") - ) + val usedTypes = + (usedTypesSet.filterInPlace(!_.endsWith(NamespaceTraversal.globalNamespaceName)).toArray :+ "ANY").toSet.sorted usedTypes.foreach { typeName => val shortName = fullToShortName(typeName) @@ -81,8 +79,11 @@ object TypeNodePass { def fullToShortName(typeName: String): String = { typeName match { - case lambdaTypeRegex(methodName) => methodName - case _ => typeName.split('.').lastOption.getOrElse(typeName) + case lambdaTypeRegex(methodName) => methodName + case name if name.endsWith(":program") => ":program" // for JavaScript only atm. + case name if name.endsWith(NamespaceTraversal.globalNamespaceName) => NamespaceTraversal.globalNamespaceName + case name if name.contains(":") => name.split(':').lastOption.getOrElse(typeName) + case _ => typeName.split('.').lastOption.getOrElse(typeName) } } }