diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a16f18..1b50d73a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed -- Upgrade ShiftLeft dependencies to 1.3.236 +- Upgrade ShiftLeft dependencies to 1.3.314 +- Upgrade Gradle to 7.2 - Removed `Binding` vertices - Can now handle new type arguments API of domain classes - `Extractor::project` now takes an optional boolean to disable reaching defs calculation - `Extractor::projectReachingDefs` now calculates reaching defs separately +- Removed `IDriver::getProgramStructure` as it's not used by the core extractor +- `VertexMapper` now handles new default property system ## [0.5.12] - 2021-07-30 diff --git a/cpgconv/build.gradle b/cpgconv/build.gradle index e242fbd7..c91c08cc 100644 --- a/cpgconv/build.gradle +++ b/cpgconv/build.gradle @@ -11,6 +11,7 @@ repositories { dependencies { implementation "io.shiftleft:codepropertygraph_2.13:$shiftleftVersion" implementation "io.shiftleft:semanticcpg_2.13:$shiftleftVersion" + implementation "io.shiftleft:dataflowengineoss_2.13:$shiftleftVersion" } group = "io.github.plume-oss" diff --git a/cpgconv/src/main/scala/io/github/plume/oss/Traversals.scala b/cpgconv/src/main/scala/io/github/plume/oss/Traversals.scala index 811a1ea2..3edb8f42 100644 --- a/cpgconv/src/main/scala/io/github/plume/oss/Traversals.scala +++ b/cpgconv/src/main/scala/io/github/plume/oss/Traversals.scala @@ -3,7 +3,8 @@ package io.github.plume.oss import java.util import io.shiftleft.codepropertygraph.Cpg import io.shiftleft.codepropertygraph.generated.{EdgeTypes, nodes} -import io.shiftleft.codepropertygraph.generated.nodes.{AstNode, File, MetaData, NamespaceBlock, StoredNode, TypeDecl} +import io.shiftleft.codepropertygraph.generated.nodes.{AstNode, File, MetaData, Method, NamespaceBlock, StoredNode, TypeDecl} +import io.shiftleft.dataflowengineoss.passes.reachingdef.{ReachingDefProblem, ReachingDefTransferFunction} import io.shiftleft.semanticcpg.language._ import overflowdb.{Edge, Graph} @@ -76,4 +77,13 @@ object Traversals { nodesToDelete.foreach(v => graph.remove(v)) } + def maxNumberOfDefsFromAMethod(graph: Graph): Int = { + Cpg(graph).method.map(ReachingDefProblem.create) + .map(_.transferFunction.asInstanceOf[ReachingDefTransferFunction].gen.foldLeft(0)(_ + _._2.size)) + .maxOption match { + case Some(value) => value + case None => 0 + } + } + } diff --git a/gradle.properties b/gradle.properties index f31e4ee2..d1420f80 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ neo4jDriverVersion=4.2.0 tigerGraphVersion=3.1.0 khttpVersion=1.0.0 jacksonVersion=2.12.0 -shiftleftVersion=1.3.236 +shiftleftVersion=1.3.314 sootVersion=4.2.1 lz4Version=1.7.1 cache2kVersion=2.0.0.Final diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 490fda85..e708b1c0 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index eb9a42f3..ffed3a25 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Mon Dec 21 21:42:58 CET 2020 -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 2fe81a7d..4f906e0c 100755 --- a/gradlew +++ b/gradlew @@ -82,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -129,6 +130,7 @@ fi if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath diff --git a/gradlew.bat b/gradlew.bat index 62bd9b9c..107acd32 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/plume/build.gradle b/plume/build.gradle index 05052fe8..05f86d0a 100644 --- a/plume/build.gradle +++ b/plume/build.gradle @@ -6,14 +6,12 @@ buildscript { plugins { id "java" - id "maven" id "maven-publish" id "jacoco" id "org.jetbrains.dokka" version "$dokkaVersion" id "com.eden.orchidPlugin" version "$orchidVersion" id "com.avast.gradle.docker-compose" version "$avastDockerVersion" id "org.jetbrains.kotlin.jvm" version "$kotlinVersion" - id "com.jfrog.bintray" version "$bintrayVersion" } repositories { @@ -37,13 +35,13 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxVersion" // Logging - compile "org.apache.logging.log4j:log4j-api:$log4jVersion" - compile "org.apache.logging.log4j:log4j-core:$log4jVersion" - compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" - compile "org.slf4j:jul-to-slf4j:$slf4jVersion" // JUL bridge - compile "org.slf4j:jcl-over-slf4j:$slf4jVersion" // Apache Commons Logging (JCL) bridge - compile "org.slf4j:log4j-over-slf4j:$slf4jVersion" // log4j1.2 bridge - compile "me.tongfei:progressbar:$progressBarVersion" // simple progress bar + implementation "org.apache.logging.log4j:log4j-api:$log4jVersion" + implementation "org.apache.logging.log4j:log4j-core:$log4jVersion" + implementation "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" + implementation "org.slf4j:jul-to-slf4j:$slf4jVersion" // JUL bridge + implementation "org.slf4j:jcl-over-slf4j:$slf4jVersion" // Apache Commons Logging (JCL) bridge + implementation "org.slf4j:log4j-over-slf4j:$slf4jVersion" // log4j1.2 bridge + implementation "me.tongfei:progressbar:$progressBarVersion" // simple progress bar // Core dependencies implementation "org.apache.tinkerpop:gremlin-core:$gremlinVersion" @@ -66,10 +64,10 @@ dependencies { subProject project(":cpgconv") // Orchid Docs - orchidRuntime "io.github.javaeden.orchid:OrchidDocs:$orchidVersion" - orchidRuntime "io.github.javaeden.orchid:OrchidKotlindoc:$orchidVersion" - orchidRuntime "io.github.javaeden.orchid:OrchidPluginDocs:$orchidVersion" - orchidRuntime "io.github.javaeden.orchid:OrchidGithub:$orchidVersion" + orchidRuntimeOnly "io.github.javaeden.orchid:OrchidDocs:$orchidVersion" + orchidRuntimeOnly "io.github.javaeden.orchid:OrchidKotlindoc:$orchidVersion" + orchidRuntimeOnly "io.github.javaeden.orchid:OrchidPluginDocs:$orchidVersion" + orchidRuntimeOnly "io.github.javaeden.orchid:OrchidGithub:$orchidVersion" // Testing testImplementation "org.junit.jupiter:junit-jupiter-engine:$junitVersion" @@ -202,11 +200,11 @@ jacoco { toolVersion = "$jacocoVersion" } jacocoTestReport { reports { - xml.enabled true + xml.required.set(true) xml.destination file("${buildDir}/reports/jacoco/report.xml") - html.enabled true + html.required.set(true) html.destination file("${buildDir}/reports/jacoco") - csv.enabled false + csv.required.set(false) } executionData test, extractorTest, tinkerGraphIntTest, overflowDbIntTest, janusGraphIntTest, tigerGraphIntTest, neo4jIntTest, neptuneIntTest diff --git a/plume/src/main/kotlin/io/github/plume/oss/domain/mappers/VertexMapper.kt b/plume/src/main/kotlin/io/github/plume/oss/domain/mappers/VertexMapper.kt index 34d93806..350a43d8 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/domain/mappers/VertexMapper.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/domain/mappers/VertexMapper.kt @@ -42,7 +42,7 @@ object VertexMapper { * @return a [NewNodeBuilder] represented by the information in the givennode. */ fun mapToVertex(v: Node): NewNodeBuilder { - val map = prepareListsInMap(v.propertyMap()) + mapOf("id" to v.id(), "label" to v.label()) + val map = prepareListsInMap(v.propertiesMap()) + mapOf("id" to v.id(), "label" to v.label()) return mapToVertex(map) } @@ -79,181 +79,366 @@ object VertexMapper { .version(map[VERSION] as String) .hash(Option.apply(map.getOrDefault(HASH, UNKNOWN) as String)) File.Label() -> NewFileBuilder() - .name(map[NAME] as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) .hash(Option.apply(map.getOrDefault(HASH, UNKNOWN) as String)) - .order(map[ORDER] as Int) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) Method.Label() -> NewMethodBuilder() - .astParentFullName(map[AST_PARENT_FULL_NAME] as String) - .astParentType(map[AST_PARENT_TYPE] as String) - .name(map[NAME] as String) - .code(map[CODE] as String) - .isExternal(map[IS_EXTERNAL] as Boolean) - .fullName(map[FULL_NAME] as String) - .filename(map[FILENAME] as String) - .signature(map[SIGNATURE] as String) + .astParentFullName(map.getOrDefault(AST_PARENT_FULL_NAME, getPropertyDefault(AST_PARENT_FULL_NAME)) as String) + .astParentType(map.getOrDefault(AST_PARENT_TYPE, getPropertyDefault(AST_PARENT_TYPE)) as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .isExternal(map.getOrDefault(IS_EXTERNAL, getPropertyDefault(IS_EXTERNAL)) as Boolean) + .fullName(map.getOrDefault(FULL_NAME, getPropertyDefault(NAME)) as String) + .filename(map.getOrDefault(FILENAME, getPropertyDefault(NAME)) as String) + .signature(map.getOrDefault(SIGNATURE, "") as String) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .order(map[ORDER] as Int) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .hash(Option.apply(map[HASH] as String)) MethodParameterIn.Label() -> NewMethodParameterInBuilder() - .code(map[CODE] as String) - .name(map[NAME] as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) .evaluationStrategy(map[EVALUATION_STRATEGY] as String) - .typeFullName(map[TYPE_FULL_NAME] as String) + .typeFullName(map.getOrDefault(TYPE_FULL_NAME, getPropertyDefault(TYPE_FULL_NAME)) as String) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .order(map[ORDER] as Int) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) MethodParameterOut.Label() -> NewMethodParameterOutBuilder() - .code(map[CODE] as String) - .name(map[NAME] as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) .evaluationStrategy(map[EVALUATION_STRATEGY] as String) - .typeFullName(map[TYPE_FULL_NAME] as String) + .typeFullName(map.getOrDefault(TYPE_FULL_NAME, getPropertyDefault(TYPE_FULL_NAME)) as String) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .order(map[ORDER] as Int) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) MethodReturn.Label() -> NewMethodReturnBuilder() - .code(map[CODE] as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) .evaluationStrategy(map[EVALUATION_STRATEGY] as String) - .typeFullName(map[TYPE_FULL_NAME] as String) + .typeFullName(map.getOrDefault(TYPE_FULL_NAME, getPropertyDefault(TYPE_FULL_NAME)) as String) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .order(map[ORDER] as Int) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) Modifier.Label() -> NewModifierBuilder() .modifierType(map[MODIFIER_TYPE] as String) - .order(map[ORDER] as Int) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) Type.Label() -> NewTypeBuilder() - .name(map[NAME] as String) - .fullName(map[FULL_NAME] as String) - .typeDeclFullName(map[TYPE_DECL_FULL_NAME] as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) + .fullName(map.getOrDefault(FULL_NAME, getPropertyDefault(FULL_NAME)) as String) + .typeDeclFullName(map.getOrDefault(TYPE_DECL_FULL_NAME, getPropertyDefault(TYPE_DECL_FULL_NAME)) as String) TypeDecl.Label() -> NewTypeDeclBuilder() - .astParentFullName(map[AST_PARENT_FULL_NAME] as String) - .astParentType(map[AST_PARENT_TYPE] as String) - .name(map[NAME] as String) - .filename(map[FILENAME] as String) - .fullName(map[FULL_NAME] as String) - .order(map[ORDER] as Int) - .isExternal(map[IS_EXTERNAL] as Boolean) + .astParentFullName(map.getOrDefault(AST_PARENT_FULL_NAME, getPropertyDefault(AST_PARENT_FULL_NAME)) as String) + .astParentType(map.getOrDefault(AST_PARENT_TYPE, getPropertyDefault(AST_PARENT_TYPE)) as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) + .filename(map.getOrDefault(FILENAME, getPropertyDefault(FILENAME)) as String) + .fullName(map.getOrDefault(FULL_NAME, getPropertyDefault(FULL_NAME)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) + .isExternal(map.getOrDefault(IS_EXTERNAL, getPropertyDefault(IS_EXTERNAL)) as Boolean) TypeParameter.Label() -> NewTypeParameterBuilder() - .name(map[NAME] as String) - .order(map[ORDER] as Int) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) TypeArgument.Label() -> NewTypeArgumentBuilder() - .order(map[ORDER] as Int) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) Member.Label() -> NewMemberBuilder() - .typeFullName(map[TYPE_FULL_NAME] as String) - .code(map[CODE] as String) - .name(map[NAME] as String) - .order(map[ORDER] as Int) + .typeFullName(map.getOrDefault(TYPE_FULL_NAME, getPropertyDefault(TYPE_FULL_NAME)) as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) + .lineNumber(Option.apply(map.getOrDefault(LINE_NUMBER, getPropertyDefault(LINE_NUMBER)) as Int)) + .columnNumber(Option.apply(map.getOrDefault(COLUMN_NUMBER, getPropertyDefault(COLUMN_NUMBER)) as Int)) Namespace.Label() -> NewNamespaceBuilder() - .order(map[ORDER] as Int) - .name(map[NAME] as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) NamespaceBlock.Label() -> NewNamespaceBlockBuilder() - .fullName(map[FULL_NAME] as String) - .filename(map[FILENAME] as String) - .name(map[NAME] as String) - .order(map[ORDER] as Int) + .fullName(map.getOrDefault(FULL_NAME, getPropertyDefault(FULL_NAME)) as String) + .filename(map.getOrDefault(FILENAME, getPropertyDefault(FILENAME)) as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) Literal.Label() -> NewLiteralBuilder() - .typeFullName(map[TYPE_FULL_NAME] as String) - .code(map[CODE] as String) - .order(map[ORDER] as Int) + .typeFullName(map.getOrDefault(TYPE_FULL_NAME, getPropertyDefault(TYPE_FULL_NAME)) as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .argumentIndex(map[ARGUMENT_INDEX] as Int) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) Call.Label() -> NewCallBuilder() - .code(map[CODE] as String) - .name(map[NAME] as String) - .order(map[ORDER] as Int) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .argumentIndex(map[ARGUMENT_INDEX] as Int) - .signature(map[SIGNATURE] as String) - .dispatchType(map[DISPATCH_TYPE] as String) - .methodFullName(map[METHOD_FULL_NAME] as String) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) + .signature(map.getOrDefault(SIGNATURE, "") as String) + .dispatchType(map.getOrDefault(DISPATCH_TYPE, getPropertyDefault(DISPATCH_TYPE)) as String) + .methodFullName(map.getOrDefault(METHOD_FULL_NAME, getPropertyDefault(METHOD_FULL_NAME)) as String) Local.Label() -> NewLocalBuilder() - .typeFullName(map[TYPE_FULL_NAME] as String) - .code(map[CODE] as String) - .name(map[NAME] as String) - .order(map[ORDER] as Int) + .typeFullName(map.getOrDefault(TYPE_FULL_NAME, getPropertyDefault(TYPE_FULL_NAME)) as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) Identifier.Label() -> NewIdentifierBuilder() - .typeFullName(map[TYPE_FULL_NAME] as String) - .code(map[CODE] as String) - .name(map[NAME] as String) - .order(map[ORDER] as Int) + .typeFullName(map.getOrDefault(TYPE_FULL_NAME, getPropertyDefault(TYPE_FULL_NAME)) as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .argumentIndex(map[ARGUMENT_INDEX] as Int) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) FieldIdentifier.Label() -> NewFieldIdentifierBuilder() .canonicalName(map[CANONICAL_NAME] as String) - .code(map[CODE] as String) - .order(map[ORDER] as Int) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .argumentIndex(map[ARGUMENT_INDEX] as Int) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) Return.Label() -> NewReturnBuilder() - .code(map[CODE] as String) - .order(map[ORDER] as Int) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .argumentIndex(map[ARGUMENT_INDEX] as Int) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) Block.Label() -> NewBlockBuilder() - .typeFullName(map[TYPE_FULL_NAME] as String) - .code(map[CODE] as String) - .order(map[ORDER] as Int) + .typeFullName(map.getOrDefault(TYPE_FULL_NAME, getPropertyDefault(TYPE_FULL_NAME)) as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .argumentIndex(map[ARGUMENT_INDEX] as Int) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) MethodRef.Label() -> NewMethodRefBuilder() - .code(map[CODE] as String) - .order(map[ORDER] as Int) - .methodFullName(map[METHOD_FULL_NAME] as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) + .methodFullName(map.getOrDefault(METHOD_FULL_NAME, getPropertyDefault(METHOD_FULL_NAME)) as String) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .argumentIndex(map[ARGUMENT_INDEX] as Int) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) TypeRef.Label() -> NewTypeRefBuilder() - .typeFullName(map[TYPE_FULL_NAME] as String) - .code(map[CODE] as String) - .order(map[ORDER] as Int) + .typeFullName(map.getOrDefault(TYPE_FULL_NAME, getPropertyDefault(TYPE_FULL_NAME)) as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .argumentIndex(map[ARGUMENT_INDEX] as Int) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) JumpTarget.Label() -> NewJumpTargetBuilder() - .code(map[CODE] as String) - .order(map[ORDER] as Int) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .argumentIndex(map[ARGUMENT_INDEX] as Int) - .name(map[NAME] as String) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) + .name(map.getOrDefault(NAME, getPropertyDefault(NAME)) as String) ControlStructure.Label() -> NewControlStructureBuilder() .controlStructureType(map[CONTROL_STRUCTURE_TYPE] as String) - .code(map[CODE] as String) - .order(map[ORDER] as Int) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) - .argumentIndex(map[ARGUMENT_INDEX] as Int) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) else -> NewUnknownBuilder() - .code(map[CODE] as String) - .order(map[ORDER] as Int) - .argumentIndex(map[ARGUMENT_INDEX] as Int) - .typeFullName(map[TYPE_FULL_NAME] as String) + .code(map.getOrDefault(CODE, getPropertyDefault(CODE)) as String) + .order(map.getOrDefault(ORDER, getPropertyDefault(ORDER)) as Int) + .argumentIndex(map.getOrDefault(ARGUMENT_INDEX, getPropertyDefault(ARGUMENT_INDEX)) as Int) + .typeFullName(map.getOrDefault(TYPE_FULL_NAME, getPropertyDefault(TYPE_FULL_NAME)) as String) .lineNumber(Option.apply(map[LINE_NUMBER] as Int)) .columnNumber(Option.apply(map[COLUMN_NUMBER] as Int)) }.apply { if (map.containsKey("id")) this.id(map["id"] as Long) } } /** - * Removes properties not used by Plume. + * Given a property, returns its known default. */ - fun stripUnusedProperties(label: String, map: MutableMap): MutableMap { + private fun getPropertyDefault(prop: String): Comparable<*> { + val strDefault = "" + val intDefault = -1 + val boolDefault = false + return when (prop) { + AST_PARENT_TYPE -> strDefault + AST_PARENT_FULL_NAME -> strDefault + NAME -> strDefault + CODE -> strDefault + ORDER -> intDefault + SIGNATURE -> "" + ARGUMENT_INDEX -> intDefault + FULL_NAME -> strDefault + TYPE_FULL_NAME -> strDefault + TYPE_DECL_FULL_NAME -> strDefault + TYPE_DECL -> strDefault + IS_EXTERNAL -> boolDefault + DISPATCH_TYPE -> strDefault + LINE_NUMBER -> intDefault + COLUMN_NUMBER -> intDefault + LINE_NUMBER_END -> intDefault + COLUMN_NUMBER_END -> intDefault + else -> strDefault + } + } + + /** + * Removes properties not used by Plume and explicitly adds defaults. + */ + fun handleProperties(label: String, map: MutableMap): MutableMap { return when (label) { - CONTROL_STRUCTURE -> map.apply { remove(PARSER_TYPE_NAME) } - JUMP_TARGET -> map.apply { remove(PARSER_TYPE_NAME) } - METHOD_REF -> map.apply { remove(TYPE_FULL_NAME) } - METHOD -> map.apply { remove(IS_VARIADIC) } - METHOD_PARAMETER_IN -> map.apply { remove(IS_VARIADIC) } - METHOD_PARAMETER_OUT -> map.apply { remove(IS_VARIADIC) } - NodeTypes.UNKNOWN -> map.apply { remove(CONTAINED_REF); remove(PARSER_TYPE_NAME) } + META_DATA -> map.apply { + MetaData.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(OVERLAYS) + } + FILE -> map.apply { + File.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(LINE_NUMBER) + remove(COLUMN_NUMBER) + } + METHOD -> map.apply { + Method.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(IS_VARIADIC) + } + METHOD_PARAMETER_IN -> map.apply { + MethodParameterIn.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(IS_VARIADIC) + } + METHOD_PARAMETER_OUT -> map.apply { + MethodParameterOut.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(IS_VARIADIC) + } + METHOD_RETURN -> map.apply { + MethodReturn.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + MODIFIER -> map.apply { + Modifier.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(LINE_NUMBER) + remove(COLUMN_NUMBER) + } + TYPE -> map.apply { + Type.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + TYPE_DECL -> map.apply { + TypeDecl.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(LINE_NUMBER) + remove(COLUMN_NUMBER) + } + TYPE_PARAMETER -> map.apply { + TypeParameter.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(LINE_NUMBER) + remove(COLUMN_NUMBER) + } + TYPE_ARGUMENT -> map.apply { + TypeArgument.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(LINE_NUMBER) + remove(COLUMN_NUMBER) + } + MEMBER -> map.apply { + Member.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + NAMESPACE -> map.apply { + Namespace.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(LINE_NUMBER) + remove(COLUMN_NUMBER) + } + NAMESPACE_BLOCK -> map.apply { + NamespaceBlock.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(LINE_NUMBER) + remove(COLUMN_NUMBER) + } + LITERAL -> map.apply { + Literal.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + CALL -> map.apply { + Call.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + LOCAL -> map.apply { + Local.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + IDENTIFIER -> map.apply { + Identifier.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + FIELD_IDENTIFIER -> map.apply { + FieldIdentifier.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + RETURN -> map.apply { + Return.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + BLOCK -> map.apply { + Block.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + METHOD_REF -> map.apply { + MethodRef.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(TYPE_FULL_NAME) + } + TYPE_REF -> map.apply { + TypeRef.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + } + JUMP_TARGET -> map.apply { + JumpTarget.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(PARSER_TYPE_NAME) + } + CONTROL_STRUCTURE -> map.apply { + ControlStructure.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(PARSER_TYPE_NAME) + } + NodeTypes.UNKNOWN -> map.apply { + Unknown.`PropertyNames$`.`MODULE$`.allAsJava().forEach { prop -> + if (!this.containsKey(prop)) this[prop] = getPropertyDefault(prop) + } + remove(CONTAINED_REF) + remove(PARSER_TYPE_NAME) + } else -> map + }.apply { + remove(LINE_NUMBER_END) + remove(COLUMN_NUMBER_END) + remove(DYNAMIC_TYPE_HINT_FULL_NAME) + remove(INHERITS_FROM_TYPE_FULL_NAME) + remove(ALIAS_TYPE_FULL_NAME) + remove(ARGUMENT_NAME) + remove(CLOSURE_BINDING_ID) } } diff --git a/plume/src/main/kotlin/io/github/plume/oss/drivers/GremlinDriver.kt b/plume/src/main/kotlin/io/github/plume/oss/drivers/GremlinDriver.kt index 7fc73137..c0771933 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/drivers/GremlinDriver.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/drivers/GremlinDriver.kt @@ -252,7 +252,7 @@ abstract class GremlinDriver : IDriver { protected open fun prepareVertexProperties(v: NewNodeBuilder): Map = VertexMapper.prepareListsInMap( - VertexMapper.stripUnusedProperties( + VertexMapper.handleProperties( v.build().label(), CollectionConverters.MapHasAsJava(v.build().properties()).asJava().toMutableMap() ) ).toMap() @@ -323,30 +323,6 @@ abstract class GremlinDriver : IDriver { return gremlinToPlume(methodSubgraph) } - override fun getProgramStructure(): overflowdb.Graph { - val fes: MutableList = mutableListOf() - PlumeTimer.measure(DriverTimeKey.DATABASE_READ) { - g.V().hasLabel(FILE) - .repeat(un.outE(AST).inV()).emit() - .inE() - .toList() - .toCollection(fes) - } - val graph = gremlinToPlume(fes) - PlumeTimer.measure(DriverTimeKey.DATABASE_READ) { - // Transfer type decl vertices to the result, this needs to be done with the tokens step to get all properties - // from the remote server - g.V().hasLabel(TYPE_DECL, FILE, NAMESPACE_BLOCK) - .unfold() - .valueMap() - .with(WithOptions.tokens) - .by(un.unfold()) - .toList() - .forEach { addNodeToODB(graph, VertexMapper.mapToVertex(mapVertexKeys(it))) } - } - return graph - } - override fun getNeighbours(v: NewNodeBuilder): overflowdb.Graph { val n = v.build() val neighbourSubgraph: MutableList = mutableListOf() @@ -486,7 +462,6 @@ abstract class GremlinDriver : IDriver { it.label() ) }.map { (src, dst, e) -> - val srcBuilder: NewNodeBuilder = VertexMapper.mapToVertex(mapVertexKeys(src)) Triple( addNodeToODB(overflowGraph, VertexMapper.mapToVertex(mapVertexKeys(src))), addNodeToODB(overflowGraph, VertexMapper.mapToVertex(mapVertexKeys(dst))), diff --git a/plume/src/main/kotlin/io/github/plume/oss/drivers/IDriver.kt b/plume/src/main/kotlin/io/github/plume/oss/drivers/IDriver.kt index 84c22dfe..c16984c4 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/drivers/IDriver.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/drivers/IDriver.kt @@ -102,13 +102,6 @@ interface IDriver : AutoCloseable { */ fun getMethod(fullName: String, includeBody: Boolean = false): Graph - /** - * Obtains all program structure related vertices. These are NAMESPACE_BLOCK, FILE, and TYPE_DECL vertices. - * - * @return The [Graph] containing the program structure related sub-graphs. - */ - fun getProgramStructure(): Graph - /** * Given a vertex, returns a [Graph] representation of neighbouring vertices. * diff --git a/plume/src/main/kotlin/io/github/plume/oss/drivers/Neo4jDriver.kt b/plume/src/main/kotlin/io/github/plume/oss/drivers/Neo4jDriver.kt index 8725825e..54260def 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/drivers/Neo4jDriver.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/drivers/Neo4jDriver.kt @@ -182,7 +182,7 @@ class Neo4jDriver internal constructor() : IDriver { private fun createVertexPayload(v: NewNodeBuilder, idx: Int): String { val node = v.build() - val propertyMap = VertexMapper.stripUnusedProperties( + val propertyMap = VertexMapper.handleProperties( v.build().label(), CollectionConverters.MapHasAsJava(node.properties()).asJava().toMutableMap() ) @@ -452,41 +452,6 @@ class Neo4jDriver internal constructor() : IDriver { return plumeGraph } - override fun getProgramStructure(): Graph { - val graph = newOverflowGraph() - driver.session().use { session -> - val result = session.writeTransaction { tx -> - tx.run( - """ - MATCH (n:$FILE)-[r1:$AST*0..]->(m)-[r2]->(o) - WITH DISTINCT (r1 + r2) AS coll - UNWIND coll AS e1 - WITH DISTINCT e1 - WITH [r in collect(e1) | {rel: type(r), src: startNode(r), tgt: endNode(r)} ] as e2 - UNWIND e2 as x - RETURN x - """.trimIndent() - ).list().map { it["x"] } - } - neo4jToOverflowGraph(result, graph) - val typeDecl = session.writeTransaction { tx -> - tx.run( - """ - MATCH (m:$TYPE_DECL) - MATCH (n:$FILE) - MATCH (o:$NAMESPACE_BLOCK) - RETURN m, n, o - """.trimIndent() - ).list() - } - typeDecl.flatMap { listOf(it["m"].asNode(), it["n"].asNode(), it["o"].asNode()) } - .map { mapToVertex(it.asMap() + mapOf("id" to it.id())) } - .filter { graph.node(it.id()) == null } - .forEach { addNodeToGraph(graph, it) } - } - return graph - } - override fun getNeighbours(v: NewNodeBuilder): Graph { val graph = newOverflowGraph() PlumeTimer.measure(DriverTimeKey.DATABASE_READ) { diff --git a/plume/src/main/kotlin/io/github/plume/oss/drivers/NeptuneDriver.kt b/plume/src/main/kotlin/io/github/plume/oss/drivers/NeptuneDriver.kt index a3e8df9e..c57f111b 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/drivers/NeptuneDriver.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/drivers/NeptuneDriver.kt @@ -256,7 +256,7 @@ class NeptuneDriver internal constructor() : GremlinDriver() { // This handles ODB -> Neptune override fun prepareVertexProperties(v: NewNodeBuilder): Map { val outMap = VertexMapper.prepareListsInMap( - VertexMapper.stripUnusedProperties( + VertexMapper.handleProperties( v.build().label(), CollectionConverters.MapHasAsJava(v.build().properties()).asJava().toMutableMap() ) diff --git a/plume/src/main/kotlin/io/github/plume/oss/drivers/OverflowDbDriver.kt b/plume/src/main/kotlin/io/github/plume/oss/drivers/OverflowDbDriver.kt index 5e4ff2c8..83e80fb1 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/drivers/OverflowDbDriver.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/drivers/OverflowDbDriver.kt @@ -26,7 +26,6 @@ import io.shiftleft.codepropertygraph.generated.nodes.* import org.apache.logging.log4j.LogManager import overflowdb.* import scala.jdk.CollectionConverters -import java.util.* import io.shiftleft.codepropertygraph.generated.edges.Factories as EdgeFactories import io.shiftleft.codepropertygraph.generated.nodes.Factories as NodeFactories @@ -122,7 +121,7 @@ class OverflowDbDriver internal constructor() : IDriver { private fun createVertex(v: NewNodeBuilder) { val newNode = v.build() val node = graph.addNode(newNode.label()) - VertexMapper.stripUnusedProperties( + VertexMapper.handleProperties( v.build().label(), CollectionConverters.MapHasAsJava(newNode.properties()).asJava().toMutableMap() ).forEach { (key, value) -> node.setProperty(key, value) } @@ -205,7 +204,7 @@ class OverflowDbDriver internal constructor() : IDriver { .distinct() .onEach { n -> val node = graph.addNode(n.id(), n.label()) - n.propertyMap().forEach { (key, value) -> node.setProperty(key as String?, value) } + n.propertiesMap().forEach { (key, value) -> node.setProperty(key as String?, value) } } } @@ -219,22 +218,8 @@ class OverflowDbDriver internal constructor() : IDriver { } } - override fun getProgramStructure(): Graph { - val g = deepCopyGraph(Traversals.getProgramStructure(graph)) - PlumeTimer.measure(DriverTimeKey.DATABASE_READ) { - val ns = Traversals.getFiles(graph).toMutableList() - .toCollection(Traversals.getTypeDecls(graph).toMutableList()) - .toCollection(Traversals.getNamespaceBlocks(graph).toMutableList()) - ns.filter { g.node(it.id()) == null } - .forEach { t -> - val node = g.addNode(t.id(), t.label()) - t.propertyMap().forEach { (key, value) -> node.setProperty(key, value) } - } - } - return g - } - - override fun getNeighbours(v: NewNodeBuilder): Graph = deepCopyGraph(Traversals.getNeighbours(graph, v.id())) + override fun getNeighbours(v: NewNodeBuilder): Graph = + deepCopyGraph(Traversals.getNeighbours(graph, v.id())) override fun deleteVertex(id: Long, label: String?) { PlumeTimer.measure(DriverTimeKey.DATABASE_WRITE) { @@ -308,7 +293,7 @@ class OverflowDbDriver internal constructor() : IDriver { return l } - override fun getVerticesOfType(label: String): List> { + override fun getVerticesOfType(label: String): List> { val l = mutableListOf>() PlumeTimer.measure(DriverTimeKey.DATABASE_READ) { graph.nodes(label).asSequence() diff --git a/plume/src/main/kotlin/io/github/plume/oss/drivers/TigerGraphDriver.kt b/plume/src/main/kotlin/io/github/plume/oss/drivers/TigerGraphDriver.kt index ace01e8d..71daae54 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/drivers/TigerGraphDriver.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/drivers/TigerGraphDriver.kt @@ -276,7 +276,7 @@ class TigerGraphDriver internal constructor() : IOverridenIdDriver, ISchemaSafeD payloadByType["${type}_VERT"] = ns.map { Pair( it.id(PlumeKeyProvider.getNewId(this)).id().toString(), - VertexMapper.stripUnusedProperties( + VertexMapper.handleProperties( type, CollectionConverters.MapHasAsJava(it.build().properties()).asJava().toMutableMap() ) @@ -329,7 +329,7 @@ class TigerGraphDriver internal constructor() : IOverridenIdDriver, ISchemaSafeD private fun createVertexPayload(v: NewNodeBuilder): MutableMap> { val node = v.build() - val propertyMap = VertexMapper.stripUnusedProperties( + val propertyMap = VertexMapper.handleProperties( v.build().label(), CollectionConverters.MapHasAsJava(node.properties()).asJava().toMutableMap() ) @@ -384,11 +384,6 @@ class TigerGraphDriver internal constructor() : IOverridenIdDriver, ISchemaSafeD } } - override fun getProgramStructure(): Graph { - val result = get("query/$GRAPH_NAME/getProgramStructure") - return payloadToGraph(result) - } - override fun getNeighbours(v: NewNodeBuilder): Graph { val n = v.build() if (v is NewMetaDataBuilder) return newOverflowGraph().apply { @@ -460,7 +455,6 @@ class TigerGraphDriver internal constructor() : IOverridenIdDriver, ISchemaSafeD ) ).first() as JSONObject)["result"] as JSONArray return result.map { vertexPayloadToNode(it as JSONObject) } - .filter { it.build().properties().keySet().contains(propertyKey) } } @Suppress("UNCHECKED_CAST") @@ -508,7 +502,9 @@ class TigerGraphDriver internal constructor() : IOverridenIdDriver, ISchemaSafeD val n = it.build() if (!vs.containsKey(it.id())) { val node = graph.addNode(it.id(), n.label()) - n.properties().foreachEntry { key, value -> node.setProperty(key, value) } + VertexMapper + .handleProperties(n.label(), CollectionConverters.MapHasAsJava(n.properties()).asJava().toMutableMap()) + .forEach { (key, value) -> node.setProperty(key, value) } vs[it.id()] = node } } @@ -538,7 +534,7 @@ class TigerGraphDriver internal constructor() : IOverridenIdDriver, ISchemaSafeD else Pair(it.removePrefix("_"), attributes[it]) } .forEach { vertexMap[it.first] = it.second } - return VertexMapper.mapToVertex(vertexMap) + return VertexMapper.mapToVertex(VertexMapper.handleProperties(vertexMap["label"] as String, vertexMap)) } override fun close() { @@ -879,7 +875,9 @@ CREATE VERTEX ${MEMBER}_VERT ( _$NAME STRING, _$CODE STRING, _$TYPE_FULL_NAME STRING, - _$ORDER INT + _$ORDER INT, + _$COLUMN_NUMBER INT, + _$LINE_NUMBER INT ) WITH primary_id_as_attribute="true" CREATE VERTEX ${NAMESPACE}_VERT ( @@ -1085,29 +1083,6 @@ CREATE QUERY getMethod(STRING FULL_NAME) FOR GRAPH SYNTAX v2 { PRINT @@edges; } -CREATE QUERY getProgramStructure() FOR GRAPH SYNTAX v2 { - SetAccum @@edges; - - start = {FILE_VERT.*, TYPE_DECL_VERT.*, NAMESPACE_BLOCK_VERT.*}; - namespaceBlockSeed = {NAMESPACE_BLOCK_VERT.*}; - - start = SELECT s - FROM start:s; - allVert = start; - - start = SELECT t - FROM namespaceBlockSeed:s -(_AST>*)- :t; - allVert = allVert UNION start; - - finalEdges = SELECT t - FROM allVert -(_AST>:e)- :t - WHERE t.type == "NAMESPACE_BLOCK_VERT" - ACCUM @@edges += e; - - PRINT allVert; - PRINT @@edges; -} - CREATE QUERY getNeighbours(VERTEX SOURCE) FOR GRAPH SYNTAX v2 { SetAccum @@edges; seed = {ANY}; diff --git a/plume/src/main/kotlin/io/github/plume/oss/graphio/GraphMLWriter.kt b/plume/src/main/kotlin/io/github/plume/oss/graphio/GraphMLWriter.kt index b9b6afa1..3bd5679a 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/graphio/GraphMLWriter.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/graphio/GraphMLWriter.kt @@ -65,7 +65,7 @@ object GraphMLWriter { private fun writeKeys(fw: OutputStreamWriter, vertices: MutableIterator) { val keySet = HashMap() vertices.forEach { v -> - v.propertyMap().forEach { (t, u) -> + v.propertiesMap().forEach { (t, u) -> when (u) { is String -> keySet[t] = "string" is Int -> keySet[t] = "int" @@ -90,7 +90,7 @@ object GraphMLWriter { private fun writeVertices(fw: OutputStreamWriter, vertices: MutableIterator) { vertices.forEach { v -> fw.write("") - VertexMapper.prepareListsInMap(v.propertyMap()) + VertexMapper.prepareListsInMap(v.propertiesMap()) .apply { fw.write("${v.label()}") } .forEach { (t, u) -> fw.write("${escape(u)}") } fw.write("") diff --git a/plume/src/main/kotlin/io/github/plume/oss/graphio/GraphSONWriter.kt b/plume/src/main/kotlin/io/github/plume/oss/graphio/GraphSONWriter.kt index ad2152ab..036e0616 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/graphio/GraphSONWriter.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/graphio/GraphSONWriter.kt @@ -52,7 +52,7 @@ object GraphSONWriter { private fun vertexToJSON(v: Node, graph: Graph): String { val sb = StringBuilder() - val properties = prepareListsInMap(v.propertyMap()) + val properties = prepareListsInMap(v.propertiesMap()) sb.append("{") sb.append("\"id\":{\"@type\":\"g:Int64\",\"@value\":${v.id()}},") sb.append("\"label\":\"${v.label()}\",") diff --git a/plume/src/main/kotlin/io/github/plume/oss/passes/DataFlowPass.kt b/plume/src/main/kotlin/io/github/plume/oss/passes/DataFlowPass.kt index a61c779e..d9d90ea9 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/passes/DataFlowPass.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/passes/DataFlowPass.kt @@ -15,6 +15,7 @@ */ package io.github.plume.oss.passes +import io.github.plume.oss.Traversals import io.github.plume.oss.domain.model.DeltaGraph import io.github.plume.oss.drivers.IDriver import io.github.plume.oss.store.PlumeStorage @@ -62,7 +63,8 @@ class DataFlowPass(private val driver: IDriver) { launch { Cpg.apply(g).use { cpg -> val methods = g.nodes(NodeTypes.METHOD).asSequence().toList() - runParallelPass(methods.filterIsInstance(), ReachingDefPass(cpg)) + val maxDefinitions = Traversals.maxNumberOfDefsFromAMethod(g) + runParallelPass(methods.filterIsInstance(), ReachingDefPass(cpg, maxDefinitions)) } } } diff --git a/plume/src/main/kotlin/io/github/plume/oss/passes/structure/MemberPass.kt b/plume/src/main/kotlin/io/github/plume/oss/passes/structure/MemberPass.kt index bfcff36e..35bdf246 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/passes/structure/MemberPass.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/passes/structure/MemberPass.kt @@ -105,5 +105,7 @@ class MemberPass(private val driver: IDriver) { .code(field.declaration) .typeFullName(field.type.toQuotedString()) .order(childIdx) + .lineNumber(field.javaSourceStartLineNumber) + .columnNumber(field.javaSourceStartColumnNumber) } \ No newline at end of file diff --git a/plume/src/main/kotlin/io/github/plume/oss/util/DiffGraphUtil.kt b/plume/src/main/kotlin/io/github/plume/oss/util/DiffGraphUtil.kt index 70a8cd88..c50f6147 100644 --- a/plume/src/main/kotlin/io/github/plume/oss/util/DiffGraphUtil.kt +++ b/plume/src/main/kotlin/io/github/plume/oss/util/DiffGraphUtil.kt @@ -65,7 +65,7 @@ object DiffGraphUtil { } is io.shiftleft.passes.`DiffGraph$Change$SetNodeProperty` -> { val node = change.node() - driver.updateVertexProperty(node.id(), node.label(), change.key(), change.value()) + driver.updateVertexProperty((node as Node).id(), node.label(), change.key(), change.value()) } else -> logger.warn("Unsupported DiffGraph operation ${change.javaClass} encountered.") } diff --git a/plume/src/test/kotlin/io/github/plume/oss/TestDomainResources.kt b/plume/src/test/kotlin/io/github/plume/oss/TestDomainResources.kt index a384b1e8..45eba455 100644 --- a/plume/src/test/kotlin/io/github/plume/oss/TestDomainResources.kt +++ b/plume/src/test/kotlin/io/github/plume/oss/TestDomainResources.kt @@ -44,7 +44,7 @@ class TestDomainResources { .lineNumber(Option.apply(INT_1)).columnNumber(Option.apply(INT_1)), NewLocalBuilder().code(STRING_1).typeFullName(STRING_1).name(STRING_1).order(INT_1) .lineNumber(Option.apply(INT_1)).columnNumber(Option.apply(INT_1)), - NewMemberBuilder().code(STRING_1).name(STRING_1).typeFullName(STRING_1).order(INT_1), + NewMemberBuilder().code(STRING_1).name(STRING_1).typeFullName(STRING_1).order(INT_1).lineNumber(INT_1).columnNumber(INT_2), NewMetaDataBuilder().language(STRING_1).version(STRING_1).hash(Option.apply(STRING_2)), NewMethodParameterInBuilder().code(STRING_1).evaluationStrategy(EVAL_1).typeFullName(STRING_1) .name(STRING_1).order(INT_1).lineNumber(Option.apply(INT_1)).columnNumber(Option.apply(INT_1)), diff --git a/plume/src/test/kotlin/io/github/plume/oss/drivers/JanusGraphDriverIntTest.kt b/plume/src/test/kotlin/io/github/plume/oss/drivers/JanusGraphDriverIntTest.kt index 9a708f10..7846f8f0 100644 --- a/plume/src/test/kotlin/io/github/plume/oss/drivers/JanusGraphDriverIntTest.kt +++ b/plume/src/test/kotlin/io/github/plume/oss/drivers/JanusGraphDriverIntTest.kt @@ -495,28 +495,6 @@ class JanusGraphDriverIntTest { assertTrue(identifier.out(REF).asSequence().any { it.id() == localVertex.id() }) } - @Test - fun testGetProgramStructure() { - val unknown = io.shiftleft.semanticcpg.language.types.structure.FileTraversal.UNKNOWN() - driver.addVertex(NewFileBuilder().name(unknown).order(0).hash(Option.apply(unknown))) - g = driver.getProgramStructure() - val ns = g.nodes().asSequence().toList() - val es = g.edges().asSequence().toList() - assertEquals(5, ns.size) - assertEquals(2, es.size) - - val file = g.V(fileVertex.id()).next() - val ns1 = g.V(namespaceBlockVertex1.id()).next() - // Assert program structure vertices are present - assertTrue(ns.any { it.id() == namespaceBlockVertex2.id() }) - assertTrue(ns.any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns.any { it.id() == fileVertex.id() }) - assertTrue(ns.any { it.id() == typeDeclVertex.id() }) - // Check that vertices are connected by AST edges - assertTrue(file.out(AST).asSequence().any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns1.out(AST).asSequence().any { it.id() == namespaceBlockVertex2.id() }) - } - @Test fun testGetNeighbours() { g = driver.getNeighbours(fileVertex) diff --git a/plume/src/test/kotlin/io/github/plume/oss/drivers/Neo4jDriverIntTest.kt b/plume/src/test/kotlin/io/github/plume/oss/drivers/Neo4jDriverIntTest.kt index deeec730..61e15a77 100644 --- a/plume/src/test/kotlin/io/github/plume/oss/drivers/Neo4jDriverIntTest.kt +++ b/plume/src/test/kotlin/io/github/plume/oss/drivers/Neo4jDriverIntTest.kt @@ -487,28 +487,6 @@ class Neo4jDriverIntTest { assertTrue(identifier.out(REF).asSequence().any { it.id() == localVertex.id() }) } - @Test - fun testGetProgramStructure() { - val unknown = io.shiftleft.semanticcpg.language.types.structure.FileTraversal.UNKNOWN() - driver.addVertex(NewFileBuilder().name(unknown).order(0).hash(Option.apply(unknown))) - g = driver.getProgramStructure() - val ns = g.nodes().asSequence().toList() - val es = g.edges().asSequence().toList() - assertEquals(5, ns.size) - assertEquals(2, es.size) - - val file = g.V(fileVertex.id()).next() - val ns1 = g.V(namespaceBlockVertex1.id()).next() - // Assert program structure vertices are present - assertTrue(ns.any { it.id() == namespaceBlockVertex2.id() }) - assertTrue(ns.any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns.any { it.id() == fileVertex.id() }) - assertTrue(ns.any { it.id() == typeDeclVertex.id() }) - // Check that vertices are connected by AST edges - assertTrue(file.out(AST).asSequence().any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns1.out(AST).asSequence().any { it.id() == namespaceBlockVertex2.id() }) - } - @Test fun testGetNeighbours() { g = driver.getNeighbours(fileVertex) diff --git a/plume/src/test/kotlin/io/github/plume/oss/drivers/NeptuneDriverIntTest.kt b/plume/src/test/kotlin/io/github/plume/oss/drivers/NeptuneDriverIntTest.kt index e8a0820f..3c2a20e8 100644 --- a/plume/src/test/kotlin/io/github/plume/oss/drivers/NeptuneDriverIntTest.kt +++ b/plume/src/test/kotlin/io/github/plume/oss/drivers/NeptuneDriverIntTest.kt @@ -489,28 +489,6 @@ class NeptuneDriverIntTest { assertTrue(identifier.out(REF).asSequence().any { it.id() == localVertex.id() }) } - @Test - fun testGetProgramStructure() { - val unknown = io.shiftleft.semanticcpg.language.types.structure.FileTraversal.UNKNOWN() - driver.addVertex(NewFileBuilder().name(unknown).order(0).hash(Option.apply(unknown))) - g = driver.getProgramStructure() - val ns = g.nodes().asSequence().toList() - val es = g.edges().asSequence().toList() - assertEquals(5, ns.size) - assertEquals(2, es.size) - - val file = g.V(fileVertex.id()).next() - val ns1 = g.V(namespaceBlockVertex1.id()).next() - // Assert program structure vertices are present - assertTrue(ns.any { it.id() == namespaceBlockVertex2.id() }) - assertTrue(ns.any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns.any { it.id() == fileVertex.id() }) - assertTrue(ns.any { it.id() == typeDeclVertex.id() }) - // Check that vertices are connected by AST edges - assertTrue(file.out(AST).asSequence().any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns1.out(AST).asSequence().any { it.id() == namespaceBlockVertex2.id() }) - } - @Test fun testGetNeighbours() { g = driver.getNeighbours(fileVertex) diff --git a/plume/src/test/kotlin/io/github/plume/oss/drivers/OverflowDbDriverIntTest.kt b/plume/src/test/kotlin/io/github/plume/oss/drivers/OverflowDbDriverIntTest.kt index dc322bfb..f70fe1e9 100644 --- a/plume/src/test/kotlin/io/github/plume/oss/drivers/OverflowDbDriverIntTest.kt +++ b/plume/src/test/kotlin/io/github/plume/oss/drivers/OverflowDbDriverIntTest.kt @@ -495,28 +495,6 @@ class OverflowDbDriverIntTest { assertTrue(identifier.out(REF).asSequence().any { it.id() == localVertex.id() }) } - @Test - fun testGetProgramStructure() { - val unknown = io.shiftleft.semanticcpg.language.types.structure.FileTraversal.UNKNOWN() - driver.addVertex(NewFileBuilder().name(unknown).order(0).hash(Option.apply(unknown))) - g = driver.getProgramStructure() - val ns = g.nodes().asSequence().toList() - val es = g.edges().asSequence().toList() - assertEquals(5, ns.size) - assertEquals(2, es.size) - - val file = g.V(fileVertex.id()).next() - val ns1 = g.V(namespaceBlockVertex1.id()).next() - // Assert program structure vertices are present - assertTrue(ns.any { it.id() == namespaceBlockVertex2.id() }) - assertTrue(ns.any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns.any { it.id() == fileVertex.id() }) - assertTrue(ns.any { it.id() == typeDeclVertex.id() }) - // Check that vertices are connected by AST edges - assertTrue(file.out(AST).asSequence().any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns1.out(AST).asSequence().any { it.id() == namespaceBlockVertex2.id() }) - } - @Test fun testGetNeighbours() { g = driver.getNeighbours(fileVertex) diff --git a/plume/src/test/kotlin/io/github/plume/oss/drivers/TigerGraphDriverIntTest.kt b/plume/src/test/kotlin/io/github/plume/oss/drivers/TigerGraphDriverIntTest.kt index cbeeb9b8..3331a959 100644 --- a/plume/src/test/kotlin/io/github/plume/oss/drivers/TigerGraphDriverIntTest.kt +++ b/plume/src/test/kotlin/io/github/plume/oss/drivers/TigerGraphDriverIntTest.kt @@ -489,28 +489,6 @@ class TigerGraphDriverIntTest { assertTrue(identifier.out(REF).asSequence().any { it.id() == localVertex.id() }) } - @Test - fun testGetProgramStructure() { - val unknown = io.shiftleft.semanticcpg.language.types.structure.FileTraversal.UNKNOWN() - driver.addVertex(NewFileBuilder().name(unknown).order(0).hash(Option.apply(unknown))) - g = driver.getProgramStructure() - val ns = g.nodes().asSequence().toList() - val es = g.edges().asSequence().toList() - assertEquals(5, ns.size) - assertEquals(2, es.size) - - val file = g.V(fileVertex.id()).next() - val ns1 = g.V(namespaceBlockVertex1.id()).next() - // Assert program structure vertices are present - assertTrue(ns.any { it.id() == namespaceBlockVertex2.id() }) - assertTrue(ns.any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns.any { it.id() == fileVertex.id() }) - assertTrue(ns.any { it.id() == typeDeclVertex.id() }) - // Check that vertices are connected by AST edges - assertTrue(file.out(AST).asSequence().any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns1.out(AST).asSequence().any { it.id() == namespaceBlockVertex2.id() }) - } - @Test fun testGetNeighbours() { g = driver.getNeighbours(fileVertex) diff --git a/plume/src/test/kotlin/io/github/plume/oss/drivers/TinkerGraphDriverIntTest.kt b/plume/src/test/kotlin/io/github/plume/oss/drivers/TinkerGraphDriverIntTest.kt index ff07cf56..a10ef9cf 100644 --- a/plume/src/test/kotlin/io/github/plume/oss/drivers/TinkerGraphDriverIntTest.kt +++ b/plume/src/test/kotlin/io/github/plume/oss/drivers/TinkerGraphDriverIntTest.kt @@ -547,28 +547,6 @@ class TinkerGraphDriverIntTest { assertTrue(identifier.out(REF).asSequence().any { it.id() == localVertex.id() }) } - @Test - fun testGetProgramStructure() { - val unknown = io.shiftleft.semanticcpg.language.types.structure.FileTraversal.UNKNOWN() - driver.addVertex(NewFileBuilder().name(unknown).order(0).hash(Option.apply(unknown))) - g = driver.getProgramStructure() - val ns = g.nodes().asSequence().toList() - val es = g.edges().asSequence().toList() - assertEquals(5, ns.size) - assertEquals(2, es.size) - - val file = g.V(fileVertex.id()).next() - val ns1 = g.V(namespaceBlockVertex1.id()).next() - // Assert program structure vertices are present - assertTrue(ns.any { it.id() == namespaceBlockVertex2.id() }) - assertTrue(ns.any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns.any { it.id() == fileVertex.id() }) - assertTrue(ns.any { it.id() == typeDeclVertex.id() }) - // Check that vertices are connected by AST edges - assertTrue(file.out(AST).asSequence().any { it.id() == namespaceBlockVertex1.id() }) - assertTrue(ns1.out(AST).asSequence().any { it.id() == namespaceBlockVertex2.id() }) - } - @Test fun testGetNeighbours() { g = driver.getNeighbours(fileVertex) diff --git a/plume/src/test/kotlin/io/github/plume/oss/extractor/BasicExtractorTest.kt b/plume/src/test/kotlin/io/github/plume/oss/extractor/BasicExtractorTest.kt index bfd44ae8..9b023fa5 100644 --- a/plume/src/test/kotlin/io/github/plume/oss/extractor/BasicExtractorTest.kt +++ b/plume/src/test/kotlin/io/github/plume/oss/extractor/BasicExtractorTest.kt @@ -104,7 +104,7 @@ class BasicExtractorTest { fun validDirectoryTest() { extractor.load(validDirectory) extractor.project() - g = driver.getProgramStructure() + g = driver.getWholeGraph() val ns = g.nodes().asSequence().toList() ns.filterIsInstance().let { fileList -> assertNotNull(fileList.firstOrNull { it.name() == "/extractor_tests/dir_test/Dir1.class".replace("/", sep) }) @@ -119,7 +119,6 @@ class BasicExtractorTest { extractor.load(validJarFile) extractor.project() g = driver.getWholeGraph() - g = driver.getProgramStructure() val ns = g.nodes().asSequence().toList() ns.filterIsInstance().let { fileList -> assertNotNull(fileList.firstOrNull { it.name() == "/intraprocedural/basic/Basic6.class".replace("/", sep) }) diff --git a/testing/build.gradle b/testing/build.gradle index 0c3072d5..88656a34 100644 --- a/testing/build.gradle +++ b/testing/build.gradle @@ -2,7 +2,8 @@ plugins { id 'scala' id 'java' id 'cz.alenkacz.gradle.scalafmt' version '1.14.0' - id "com.github.maiflai.scalatest" version "0.30" + id "com.github.maiflai.scalatest" version "0.31" + id "com.virgo47.ClasspathJar" version "1.0.0" } repositories { @@ -19,7 +20,7 @@ dependencies { testImplementation "org.cache2k:cache2k-core:$cache2kVersion" testImplementation "org.scalatest:scalatest_2.13:3.1.1" testImplementation "io.shiftleft:semanticcpg-tests_2.13:$shiftleftVersion:tests" - testRuntime 'com.vladsch.flexmark:flexmark-all:0.35.10' + testRuntimeOnly 'com.vladsch.flexmark:flexmark-all:0.35.10' implementation("org.scala-lang:scala-library:2.13.4") } diff --git a/testing/src/test/scala/io/github/plume/oss/querying/FileTests.scala b/testing/src/test/scala/io/github/plume/oss/querying/FileTests.scala index 6e56277a..8d58960b 100644 --- a/testing/src/test/scala/io/github/plume/oss/querying/FileTests.scala +++ b/testing/src/test/scala/io/github/plume/oss/querying/FileTests.scala @@ -24,7 +24,7 @@ class FileTests extends PlumeCodeToCpgSuite { u.name should startWith(JFile.separator) u.hash.isDefined shouldBe true v.name should startWith(JFile.separator) - v.hash.isDefined shouldBe false + v.hash.isDefined shouldBe true } "should allow traversing from file to its namespace blocks" in { diff --git a/testing/src/test/scala/io/github/plume/oss/querying/MemberTests.scala b/testing/src/test/scala/io/github/plume/oss/querying/MemberTests.scala index 505393dc..72577dfd 100644 --- a/testing/src/test/scala/io/github/plume/oss/querying/MemberTests.scala +++ b/testing/src/test/scala/io/github/plume/oss/querying/MemberTests.scala @@ -5,7 +5,7 @@ import io.shiftleft.semanticcpg.language._ class MemberTests extends PlumeCodeToCpgSuite { - override val code = + override val code: String = """ |class Foo { | int x; diff --git a/testing/src/test/scala/io/github/plume/oss/querying/MetaDataTests.scala b/testing/src/test/scala/io/github/plume/oss/querying/MetaDataTests.scala index d6b5d973..a142b554 100644 --- a/testing/src/test/scala/io/github/plume/oss/querying/MetaDataTests.scala +++ b/testing/src/test/scala/io/github/plume/oss/querying/MetaDataTests.scala @@ -5,7 +5,7 @@ import io.github.plume.oss.util.ExtractorConst import io.shiftleft.semanticcpg.language._ class MetaDataTests extends PlumeCodeToCpgSuite { - override val code = + override val code: String = """ |class Foo {} |""".stripMargin