From 82a4b261a44afb1bdc55bf6793dc1014f3ac0479 Mon Sep 17 00:00:00 2001 From: Nikita Stroganov Date: Mon, 11 Jul 2022 10:38:39 +0300 Subject: [PATCH 1/2] Add another way to find the last line (#460) --- .../kotlin/org/utbot/sarif/DataClasses.kt | 4 +-- .../kotlin/org/utbot/sarif/SarifReport.kt | 25 +++++++++++++------ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/utbot-framework/src/main/kotlin/org/utbot/sarif/DataClasses.kt b/utbot-framework/src/main/kotlin/org/utbot/sarif/DataClasses.kt index 1a6aae7e8e..3237be507a 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/sarif/DataClasses.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/sarif/DataClasses.kt @@ -156,8 +156,8 @@ data class SarifRegion( */ fun withStartLine(text: String, startLine: Int): SarifRegion { val neededLine = text.split('\n').getOrNull(startLine - 1) // to zero-based - val startColumn = neededLine?.let { - neededLine.takeWhile { it.toString().isBlank() }.length + 1 // to one-based + val startColumn = neededLine?.run { + takeWhile { it.toString().isBlank() }.length + 1 // to one-based } return SarifRegion(startLine = startLine, startColumn = startColumn) } diff --git a/utbot-framework/src/main/kotlin/org/utbot/sarif/SarifReport.kt b/utbot-framework/src/main/kotlin/org/utbot/sarif/SarifReport.kt index de414528a4..8ad840e184 100644 --- a/utbot-framework/src/main/kotlin/org/utbot/sarif/SarifReport.kt +++ b/utbot-framework/src/main/kotlin/org/utbot/sarif/SarifReport.kt @@ -66,16 +66,13 @@ class SarifReport( */ private val relatedLocationId = 1 // for attaching link to generated test in related locations - private fun shouldProcessUncheckedException(result: UtExecutionResult) = (result is UtImplicitlyThrownException) - || ((result is UtOverflowFailure) && UtSettings.treatOverflowAsError) - private fun constructSarif(): Sarif { val sarifResults = mutableListOf() val sarifRules = mutableSetOf() for (testCase in testCases) { for (execution in testCase.executions) { - if (shouldProcessUncheckedException(execution.result)) { + if (shouldProcessExecutionResult(execution.result)) { val (sarifResult, sarifRule) = processUncheckedException( method = testCase.method, utExecution = execution, @@ -144,7 +141,7 @@ class SarifReport( if (classFqn == null) return listOf() val sourceRelativePath = sourceFinding.getSourceRelativePath(classFqn) - val startLine = extractLineNumber(utExecution) ?: defaultLineNumber + val startLine = getLastLineNumber(utExecution) ?: defaultLineNumber val sourceCode = sourceFinding.getSourceFile(classFqn)?.readText() ?: "" val sourceRegion = SarifRegion.withStartLine(sourceCode, startLine) return listOf( @@ -301,10 +298,24 @@ class SarifReport( return "..." } - private fun extractLineNumber(utExecution: UtExecution): Int? = - try { + /** + * Returns the number of the last line in the execution path. + */ + private fun getLastLineNumber(utExecution: UtExecution): Int? { + val lastPathLine = try { utExecution.path.lastOrNull()?.stmt?.javaSourceStartLineNumber } catch (t: Throwable) { null } + // if for some reason we can't extract the last line from the path + val lastCoveredInstruction = + utExecution.coverage?.coveredInstructions?.lastOrNull()?.lineNumber + return lastPathLine ?: lastCoveredInstruction + } + + private fun shouldProcessExecutionResult(result: UtExecutionResult): Boolean { + val implicitlyThrown = result is UtImplicitlyThrownException + val overflowFailure = result is UtOverflowFailure && UtSettings.treatOverflowAsError + return implicitlyThrown || overflowFailure + } } \ No newline at end of file From d495c92270b0c953873dbf73134ec275206905b7 Mon Sep 17 00:00:00 2001 From: Nikita Stroganov Date: Mon, 11 Jul 2022 10:40:49 +0300 Subject: [PATCH 2/2] Add another way to find the psi class (#470) --- .../plugin/sarif/SourceFindingStrategyIdea.kt | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/sarif/SourceFindingStrategyIdea.kt b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/sarif/SourceFindingStrategyIdea.kt index 8aba1e3158..456cc749fe 100644 --- a/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/sarif/SourceFindingStrategyIdea.kt +++ b/utbot-intellij/src/main/kotlin/org/utbot/intellij/plugin/sarif/SourceFindingStrategyIdea.kt @@ -1,41 +1,43 @@ package org.utbot.intellij.plugin.sarif +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiClass +import org.jetbrains.kotlin.idea.search.allScope import org.utbot.common.PathUtil.classFqnToPath import org.utbot.common.PathUtil.safeRelativize import org.utbot.common.PathUtil.toPath import org.utbot.sarif.SourceFindingStrategy -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiClass -import org.jetbrains.kotlin.idea.search.allScope import java.io.File /** - * The search strategy based on the information available to the PsiClass + * The search strategy based on the information available to the PsiClass. */ class SourceFindingStrategyIdea(testClass: PsiClass) : SourceFindingStrategy() { /** - * Returns the relative path (against `project.basePath`) to the file with generated tests + * Returns the relative path (against `project.basePath`) to the file with generated tests. */ override val testsRelativePath: String get() = safeRelativize(project.basePath, testsFilePath) ?: testsFilePath.toPath().fileName.toString() /** - * Returns the relative path (against `project.basePath`) to the source file containing the class [classFqn] + * Returns the relative path (against `project.basePath`) to the source file containing the class [classFqn]. */ - override fun getSourceRelativePath(classFqn: String, extension: String?): String = - JavaPsiFacade.getInstance(project) - .findClass(classFqn, project.allScope())?.let { psiClass -> - safeRelativize(project.basePath, psiClass.containingFile.virtualFile.path) - } ?: (classFqnToPath(classFqn) + (extension ?: defaultExtension)) + override fun getSourceRelativePath(classFqn: String, extension: String?): String { + val psiClass = findPsiClass(classFqn) + val absolutePath = psiClass?.containingFile?.virtualFile?.path + val relativePath = safeRelativize(project.basePath, absolutePath) + val defaultRelativePath = classFqnToPath(classFqn) + (extension ?: defaultExtension) + return relativePath ?: defaultRelativePath + } /** * Finds the source file containing the class [classFqn]. * Returns null if the file does not exist. */ override fun getSourceFile(classFqn: String, extension: String?): File? { - val psiClass = JavaPsiFacade.getInstance(project).findClass(classFqn, project.allScope()) + val psiClass = findPsiClass(classFqn) val sourceCodeFile = psiClass?.containingFile?.virtualFile?.path?.let(::File) return if (sourceCodeFile?.exists() == true) sourceCodeFile else null } @@ -48,7 +50,23 @@ class SourceFindingStrategyIdea(testClass: PsiClass) : SourceFindingStrategy() { /** * The file extension to be used in [getSourceRelativePath] if the source file - * was not found by the class qualified name and the `extension` parameter is null + * was not found by the class qualified name and the `extension` parameter is null. */ private val defaultExtension = "." + (testClass.containingFile.virtualFile.extension ?: "java") + + /** + * Returns PsiClass by given [classFqn]. + */ + private fun findPsiClass(classFqn: String): PsiClass? { + val psiFacade = JavaPsiFacade.getInstance(project) + val psiClass = psiFacade.findClass(classFqn, project.allScope()) + if (psiClass != null) + return psiClass + + // If for some reason `psiClass` was not found by the `findClass` method + val packageName = classFqn.substringBeforeLast('.') + val shortClassName = classFqn.substringAfterLast('.') + val neededPackage = psiFacade.findPackage(packageName) + return neededPackage?.classes?.firstOrNull { it.name == shortClassName } + } } \ No newline at end of file