Skip to content

Commit

Permalink
Add methods to scalafix api to be able to retrieve patches (#1223)
Browse files Browse the repository at this point in the history
* Add methods to scalafix api to be able to retrieve patches

* be able to apply selectives patches

* Adjust exitcode as it was in the previous MainOps.run

* Add test for applySelectivePatches

* Fix mima test and skip windows

* Add missing documentation

* Various fixes

* Various fixes 2

* Add a test to verify that withMode and withCallback are not taken into account when evaluate is called
  • Loading branch information
mlachkar authored Sep 2, 2020
1 parent be5dcc8 commit 4f113a7
Show file tree
Hide file tree
Showing 24 changed files with 864 additions and 71 deletions.
3 changes: 2 additions & 1 deletion project/Mima.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ object Mima {
Seq(
ProblemFilters.exclude[MissingTypesProblem]("scalafix.testkit.DiffAssertions"),
ProblemFilters.exclude[MissingTypesProblem]("scalafix.testkit.SemanticRuleSuite"),
ProblemFilters.exclude[Problem]("scalafix.internal.*")
ProblemFilters.exclude[Problem]("scalafix.internal.*"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("scalafix.interfaces.ScalafixArguments.evaluate")
)
}
}
5 changes: 5 additions & 0 deletions scalafix-cli/src/main/scala/scalafix/cli/ExitStatus.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,9 @@ object ExitStatus {

def merge(exit1: ExitStatus, exit2: ExitStatus): ExitStatus =
apply(exit1.code | exit2.code)

def merge(exitStatus: Seq[ExitStatus]): ExitStatus =
exitStatus.foldLeft(ExitStatus.Ok) { (status, next) =>
apply(status.code | next.code)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,21 @@ import scala.jdk.CollectionConverters._
import scala.meta.io.AbsolutePath
import scala.meta.io.Classpath
import scala.util.control.NoStackTrace
import scalafix.interfaces.ScalafixArguments
import scalafix.interfaces.ScalafixError
import scalafix.interfaces.ScalafixException
import scalafix.interfaces.ScalafixMainCallback
import scalafix.interfaces.ScalafixMainMode
import scalafix.interfaces.ScalafixRule
import scalafix.interfaces.{
ScalafixArguments,
ScalafixError,
ScalafixException,
ScalafixMainCallback,
ScalafixMainMode,
ScalafixEvaluation,
ScalafixRule
}
import scalafix.internal.v1.Args
import scalafix.internal.v1.MainOps
import scalafix.internal.v1.Rules
import scalafix.v1.RuleDecoder
import scalafix.Versions
import scalafix.cli.ExitStatus

final case class ScalafixArgumentsImpl(args: Args = Args.default)
extends ScalafixArguments {
Expand All @@ -36,6 +40,15 @@ final case class ScalafixArgumentsImpl(args: Args = Args.default)
ScalafixErrorImpl.fromScala(exit)
}

override def evaluate(): ScalafixEvaluation = {
args.validate match {
case Configured.Ok(validated) =>
MainOps.runWithResult(validated)
case Configured.NotOk(err) =>
ScalafixEvaluationImpl(ExitStatus.CommandLineError, Some(err.msg))
}
}

override def withRules(rules: util.List[String]): ScalafixArguments =
copy(args = args.copy(rules = rules.asScala.toList))

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package scalafix.internal.interfaces

import java.util.Optional

import scalafix.cli.ExitStatus
import scalafix.interfaces.{
ScalafixError,
ScalafixFileEvaluation,
ScalafixEvaluation
}
import scalafix.internal.util.OptionOps._

final case class ScalafixEvaluationImpl(
error: ExitStatus,
getMessageError: Optional[String],
fileEvaluations: Seq[ScalafixFileEvaluationImpl]
) extends ScalafixEvaluation {

override def isSuccessful: Boolean = error.isOk

override def getErrors: Array[ScalafixError] = {
ScalafixErrorImpl.fromScala(error)
}

override def getFileEvaluations: Array[ScalafixFileEvaluation] =
fileEvaluations.toArray

override def apply(): Array[ScalafixError] = {
fileEvaluations.flatMap(o => o.applyPatches()).toArray
}
}

object ScalafixEvaluationImpl {

def apply(
error: ExitStatus,
errorMessage: Option[String] = None
): ScalafixEvaluationImpl = {
new ScalafixEvaluationImpl(error, errorMessage.asJava, Nil)
}

def from(
fileEvaluations: Seq[ScalafixFileEvaluationImpl],
exitStatus: ExitStatus
): ScalafixEvaluationImpl = {
ScalafixEvaluationImpl(exitStatus, Optional.empty(), fileEvaluations)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package scalafix.internal.interfaces

import java.nio.file.Path
import java.util.Optional

import scalafix.cli.ExitStatus
import scalafix.interfaces.{
ScalafixDiagnostic,
ScalafixError,
ScalafixFileEvaluation,
ScalafixPatch,
ScalafixRule
}
import scalafix.internal.diff.DiffUtils
import scalafix.internal.v1.{MainOps, ValidatedArgs}
import scalafix.lint.RuleDiagnostic
import scalafix.internal.util.OptionOps._
import scalafix.v0
import scalafix.v0.RuleCtx

import scala.meta.io.AbsolutePath

final case class ScalafixFileEvaluationImpl(
originalPath: AbsolutePath,
fixedOpt: Option[String],
error: ExitStatus,
errorMessage: Option[String],
diagnostics: Seq[RuleDiagnostic],
patches: Seq[ScalafixPatchImpl]
)(
args: ValidatedArgs,
ctxOpt: Option[RuleCtx],
index: Option[v0.SemanticdbIndex]
) extends ScalafixFileEvaluation {
val rules: Seq[ScalafixRuleImpl] =
args.rules.rules.map(new ScalafixRuleImpl(_))
val pathToReplace = args.pathReplace(originalPath)

override def getEvaluatedFile: Path = originalPath.toNIO

override def getEvaluatedRules: Array[ScalafixRule] = rules.toArray

override def previewPatches(): Optional[String] = fixedOpt.asJava

override def previewPatchesAsUnifiedDiff: Optional[String] = {
fixedOpt
.flatMap(fixed => {
val input = args.input(originalPath).text
if (input == fixed) None
else
Some(
DiffUtils.unifiedDiff(
originalPath.toString(),
"<expected fix>",
input.linesIterator.toList,
fixed.linesIterator.toList,
3
)
)
})
.asJava
}

override def getErrors(): Array[ScalafixError] =
ScalafixErrorImpl.fromScala(error)

override def isSuccessful: Boolean = error.isOk

override def getDiagnostics: Array[ScalafixDiagnostic] =
diagnostics.map(ScalafixDiagnosticImpl.fromScala).toArray

override def getPatches: Array[ScalafixPatch] = {
patches.toArray
}

override def applyPatches(): Array[ScalafixError] = {
val exitStatus = fixedOpt.toTry
.flatMap(MainOps.applyDiff(args, file = originalPath, _))
.getOrElse(ExitStatus.UnexpectedError)
ScalafixErrorImpl.fromScala(exitStatus).toSeq.toArray
}

override def previewPatches(
selectedPatches: Array[ScalafixPatch]
): Optional[String] = {
val selectedPatchesSet =
new java.util.IdentityHashMap[ScalafixPatch, Unit](selectedPatches.length)
for (patch <- selectedPatches)
selectedPatchesSet.put(patch, ())
val filteredPatches = patches.filter(selectedPatchesSet.containsKey(_))
ctxOpt
.flatMap(ctx =>
MainOps.previewPatches(filteredPatches.map(_.patch), ctx, index)
)
.asJava
}
override def applyPatches(
selectedPatches: Array[ScalafixPatch]
): Array[ScalafixError] = {
val selectedPatchesSet =
new java.util.IdentityHashMap[ScalafixPatch, Unit](selectedPatches.length)
for (patch <- selectedPatches)
selectedPatchesSet.put(patch, ())
val filteredPatches = patches.filter(selectedPatchesSet.containsKey(_))
val exitStatus =
ctxOpt.toTry
.flatMap(ctx =>
MainOps.applyPatches(
args,
filteredPatches.map(_.patch),
ctx,
index,
pathToReplace
)
)
.getOrElse(ExitStatus.UnexpectedError)
ScalafixErrorImpl.fromScala(exitStatus)
}

}

object ScalafixFileEvaluationImpl {

def from(
originalPath: AbsolutePath,
fixed: Option[String],
exitStatus: ExitStatus,
patches: Seq[v0.Patch],
diagnostics: Seq[RuleDiagnostic]
)(
args: ValidatedArgs,
ctx: RuleCtx,
index: Option[v0.SemanticdbIndex]
): ScalafixFileEvaluationImpl = {
val scalafixPatches = patches.map(ScalafixPatchImpl)
ScalafixFileEvaluationImpl(
originalPath = originalPath,
fixedOpt = fixed,
error = exitStatus,
errorMessage = None,
diagnostics = diagnostics,
patches = scalafixPatches
)(args, Some(ctx), index)
}
def from(
originalPath: AbsolutePath,
exitStatus: ExitStatus,
errorMessage: String
)(
args: ValidatedArgs
): ScalafixFileEvaluationImpl =
ScalafixFileEvaluationImpl(
originalPath,
None,
exitStatus,
Some(errorMessage),
Nil,
Nil
)(args, None, None)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package scalafix.internal.interfaces

import scalafix.interfaces.ScalafixPatch
import scalafix.Patch

case class ScalafixPatchImpl(patch: Patch) extends ScalafixPatch
Loading

0 comments on commit 4f113a7

Please sign in to comment.