Skip to content

Commit

Permalink
Update README and move sarif utils into common module (#477)
Browse files Browse the repository at this point in the history
### What's done:
* Update README and move sarif utils into common module
  • Loading branch information
kgevorkyan committed Jan 13, 2023
1 parent 69b23ee commit e5ced44
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,19 @@ fun Path.parentsWithSelf() = listOf(this) + this.parents().toList()
*/
expect fun FileSystem.myDeleteRecursively(path: Path)

/**
* Find a file in any of parent directories and return this directory
*
* @param path path for which ancestors should be checked
* @param fileName a name of the file that will be searched for
* @return a path to one of parent directories or null if no directory contains [fileName]
*/
fun FileSystem.findAncestorDirContainingFile(path: Path, fileName: String): Path? = path.parents().firstOrNull { parent ->
metadata(parent).isDirectory && list(parent).any {
it.name == fileName
}
}

/**
* @return current working directory
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* Utility methods to work with SARIF files.
*/

package com.saveourtool.save.core.utils

import com.saveourtool.save.core.files.findAncestorDirContainingFile
import com.saveourtool.save.core.files.fs
import com.saveourtool.save.core.files.parents
import com.saveourtool.save.core.plugin.PluginException

import okio.FileSystem
import okio.Path

/**
* @return string with trimmed `file://` or `file:///`
*/
fun String.dropFileProtocol() = substringAfter("file://")
.let {
// It is a valid format for Windows paths to look like `file:///C:/stuff`
if (it[0] == '/' && it[2] == ':') it.drop(1) else it
}

/**
* Make all paths in [this] collection relative to [root]
*
* @param root a common root for files in [this]
* @return a list of relative paths
*/
fun List<Path>.adjustToCommonRoot(root: Path) = map {
it.relativeTo(root).normalized()
}

/**
* Find the last parent directory containing save.toml.
*
* @param path a path to start the search
* @return one of parent directories
*/
fun FileSystem.topmostTestDirectory(path: Path): Path = path.parents().last { parent ->
list(parent).any { it.name == "save.toml" }
}

/**
* Calculate the path to sarif file; we expect, that it single for the all tests and located in one of parent directories
* for evaluated test files
*
* @param sarifFileName sarif file name
* @param anchorTestFilePath anchor file for calculating corresponding sarif file;
* since .sarif file expected to be the one for all test files, it could be any of test file
* @return path to sarif
* @throws PluginException in case of absence of sarif file
*/
fun calculatePathToSarifFile(sarifFileName: String, anchorTestFilePath: Path): Path = fs.findAncestorDirContainingFile(
anchorTestFilePath, sarifFileName
)?.let {
it / sarifFileName
} ?: throw PluginException(
"Could not find SARIF file with expected warnings/fixes for file $anchorTestFilePath. " +
"Please check if correct `FarningsFormat`/`FixFormat` is set (should be SARIF) and if the file is present and called `$sarifFileName`."
)
6 changes: 6 additions & 0 deletions save-plugins/fix-plugin/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
## Save fix plugin
Plugin that runs provided executable on the initial file with a test source code and compares its output with an expected result.

Fix plugin supports two types of execution: `IN_PLACE` and `SARIF`, which could be specified by `actualFixFormat` flag.
In case of `IN_PLACE` mode, `save` will apply fixes, obtained by static analysis tool by executing it with provided configuration,
while in `SARIF` mode, it will expect the `.sarif` file, with the list of fixes, which could be provided by `actualFixSarifFileName` flag.
Plugin will extract all fixes from sarif and apply them to the test files. More information about sarif fix sections could be found [here](https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/sarif-v2.1.0-os.html#_Toc34317881).

Please note, that it is important for test resources to have specific postfixes. By the default test file it should be `Test`
, for the file with expected result - it should be `Expected`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.saveourtool.save.core.utils.ExecutionResult
import com.saveourtool.save.core.utils.PathSerializer
import com.saveourtool.save.core.utils.ProcessExecutionException
import com.saveourtool.save.core.utils.ProcessTimeoutException
import com.saveourtool.save.core.utils.calculatePathToSarifFile
import com.saveourtool.save.core.utils.singleIsInstance

import com.saveourtool.sarifutils.cli.adapter.SarifFixAdapter
Expand Down Expand Up @@ -186,10 +187,15 @@ class FixPlugin(
testsPaths: List<Path>,
testCopyToExpectedFilesMap: List<PathPair>,
): List<PathPair> {
val sarif = calculatePathToSarifFile(
sarifFileName = fixPluginConfig.actualFixSarifFileName!!,
// Since we have one .sarif file for all tests, just take the first of them as anchor for calculation of paths
anchorTestFilePath = testsPaths.first()
)
// In this case fixes weren't performed by tool into the test files directly,
// instead, there was created sarif file with list of fixes, which we will apply ourselves
val fixedFiles = SarifFixAdapter(
sarifFile = fixPluginConfig.actualFixSarifFileName!!.toPath(),
sarifFile = sarif,
targetFiles = testsPaths
).process()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,8 @@ data class FixPluginConfig(
resourceNameExpectedSuffix = resourceNameExpected,
ignoreLines = ignoreLines,
actualFixFormat = actualFixFormat ?: ActualFixFormat.IN_PLACE,
actualFixSarifFileName = calculateActualFixSarifFilePath(),
actualFixSarifFileName = (actualFixSarifFileName ?: "save-fixes.sarif"),
).also {
it.configLocation = this.configLocation
}

// we require from sarif file to be located at the same level as corresponding save.toml
private fun calculateActualFixSarifFilePath(): String? = if (actualFixFormat == ActualFixFormat.SARIF) {
(
configLocation.parent!! /
(actualFixSarifFileName ?: "save-fixes.sarif").toPath()
).toString()
} else {
null
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package com.saveourtool.save.plugin.warn.sarif

import com.saveourtool.save.core.utils.dropFileProtocol
import com.saveourtool.save.core.utils.isCurrentOsWindows
import com.saveourtool.save.plugin.warn.utils.Warning

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ package com.saveourtool.save.plugin.warn.utils
import com.saveourtool.save.core.files.readFile
import com.saveourtool.save.core.plugin.GeneralConfig
import com.saveourtool.save.core.plugin.PluginException
import com.saveourtool.save.core.utils.adjustToCommonRoot
import com.saveourtool.save.core.utils.calculatePathToSarifFile
import com.saveourtool.save.core.utils.topmostTestDirectory
import com.saveourtool.save.plugin.warn.WarnPluginConfig
import com.saveourtool.save.plugin.warn.sarif.adjustToCommonRoot
import com.saveourtool.save.plugin.warn.sarif.findAncestorDirContainingFile
import com.saveourtool.save.plugin.warn.sarif.toWarnings
import com.saveourtool.save.plugin.warn.sarif.topmostTestDirectory

import io.github.detekt.sarif4k.SarifSchema210
import okio.FileSystem
Expand Down Expand Up @@ -114,11 +114,10 @@ internal fun collectWarningsFromSarif(

// Since we have one .sarif file for all tests, just take the first of them as anchor for calculation of paths
val anchorTestFilePath = originalPaths.first()
val sarif = fs.findAncestorDirContainingFile(anchorTestFilePath, sarifFileName)?.let { it / sarifFileName }
?: throw PluginException(
"Could not find SARIF file with expected warnings for file $anchorTestFilePath. " +
"Please check if correct `expectedWarningsFormat` is set and if the file is present and called `$sarifFileName`."
)
val sarif = calculatePathToSarifFile(
sarifFileName = sarifFileName,
anchorTestFilePath = anchorTestFilePath
)
val topmostTestDirectory = fs.topmostTestDirectory(anchorTestFilePath)
return Json.decodeFromString<SarifSchema210>(
fs.readFile(sarif)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.saveourtool.save.plugin.warn.sarif

import com.saveourtool.save.core.files.getWorkingDirectory
import com.saveourtool.save.core.logging.logInfo
import com.saveourtool.save.core.utils.adjustToCommonRoot
import com.saveourtool.save.plugin.warn.utils.Warning

import io.github.detekt.sarif4k.ArtifactLocation
Expand Down

0 comments on commit e5ced44

Please sign in to comment.