Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
version: 2.1

orbs:
codacy: codacy/base@12.2.0
codacy_plugins_test: codacy/plugins-test@1.1.1
codacy: codacy/base@13.1.1
codacy_plugins_test: codacy/plugins-test@2.1.2

workflows:
version: 2
Expand Down Expand Up @@ -41,7 +41,7 @@ workflows:
branches:
only: master
context: CodacyAWS
no_output_timeout: "30m"
no_output_timeout: "60m"
cache_prefix: sbt-cache-15092020
requires:
- publish_docker_local
Expand Down
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ val dockerUser = "docker"

daemonUser in Docker := dockerUser

dockerBaseImage := "amazoncorretto:8-alpine3.14-jre"
dockerBaseImage := "amazoncorretto:8-alpine3.24-jre"

dockerCommands := dockerCommands.value.flatMap {
case cmd @ Cmd("ADD", _) =>
Expand Down
2 changes: 1 addition & 1 deletion core/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ name := "codacy-patterns-core"
//core dependencies
val scalaLib = "org.scala-lang" % "scala-library" % scalaV
val scalaCompiler = "org.scala-lang" % "scala-compiler" % scalaV
val scalameta = "org.scalameta" %% "scalameta" % "4.0.0" withSources ()
val scalameta = "org.scalameta" %% "scalameta" % "4.17.2" withSources ()
val scalametaContrib = "org.scalameta" %% "contrib" % "4.0.0" withSources ()

scalaVersion := scalaV
Expand Down
4 changes: 2 additions & 2 deletions core/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "2.3")
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.12.2")

addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.2")
addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1")
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,23 @@ import scala.meta._

case object Custom_Scala_DuplicatedCase extends Pattern {
override def apply(tree: Tree): Iterable[Result] = {
def checkDup(cases: List[Case]): Iterable[Result] = {
def checkDup(cases: Seq[Case]): Iterable[Result] = {
cases.groupBy(_.pat.structure).collect {
case (x, ys) if ys.lengthCompare(1) > 0 =>
Result(message(ys.head), ys.head)
}
}

tree.collect {
case q"$_ match { ..case $cases }" => checkDup(cases)
case q"try $_ catch { ..case $cases } finally $_" => checkDup(cases)
case q"{ ..case $cases }" => checkDup(cases)
case expr: Term.Match =>
checkDup(expr.cases)
case expr: Term.Try =>
checkDup(expr.catchp)
case block: Term.Block =>
block.stats.flatMap {
case cases: Term.CasesBlock => checkDup(cases.cases)
case _ => Iterable.empty
}
}.flatten
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ case object Custom_Scala_EnforceMinimumVisibility extends Pattern {
private[this] def isInner(tree: Defn) = tree match {
case t @ (_: Defn.Trait | _: Defn.Class | _: Defn.Object) =>
t.parent.exists {
case q"package $_ { ..$_ }" => false
case _: Pkg => false
case _: Pkg.Object => false
case _ => true
}
case _ => true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,28 @@
tree
.collect {
//val definitions
case t @ q"..$_ val ..$patsnel: $tpe = $expr"
if configuration.includeEnums || !isEnumValDefRegexOrDecl(t.parent, Option(expr), tpe) =>
conflictingNames(patsnel)
//val declarations
case t @ q"..$_ val ..$pnamesnel: $tpe"
if configuration.includeEnums || !isEnumValDefRegexOrDecl(t.parent, tpe = Option(tpe)) =>
conflictingNames(pnamesnel)
case defn: Defn.Val =>
if (configuration.includeEnums || !isEnumValDefRegexOrDecl(defn.parent, Some(defn.rhs), defn.decltpe))
conflictingNames(defn.pats)
else
Iterable.empty
//var definitions
case t @ q"..$_ var ..$patsnel: $tpe = $expr"
if configuration.includeEnums || !isEnumValDefRegexOrDecl(t.parent, expr, tpe) =>
conflictingNames(patsnel)
//var declarations
case t @ q"..$_ var ..$pnamesnel: $tpe"
if configuration.includeEnums || !isEnumValDefRegexOrDecl(t.parent, tpe = Option(tpe)) =>
conflictingNames(pnamesnel)
//parameter values
case t @ param"..$mods $paramname: $atpeopt = $expropt" if isConflictingName(paramname) =>
List(paramname)
case defn: Defn.Var =>
if (configuration.includeEnums || !isEnumValDefRegexOrDecl(defn.parent, defn.rhs, defn.decltpe))
conflictingNames(defn.pats)
else
Iterable.empty
//class parameters
case defn: Defn.Class =>
defn.ctor.paramss.flatMap { params =>
params.collect {
case param if isConflictingName(param.name) =>
param.name
}
}
//parameter values (method parameters)
case param: Term.Param if isConflictingName(param.name) =>
List(param.name)
}
.flatten
.map { tree =>
Expand All @@ -39,7 +43,7 @@
.toSet
}

private[this] def isEnumValDefRegexOrDecl(parent: Option[Tree], expr: Option[Tree] = None, tpe: Option[Type]) = {
private[this] def isEnumValDefRegexOrDecl(parent: Option[Tree], expr: Option[Tree], tpe: Option[Type]) = {

Check warning on line 46 in patterns-base/src/main/scala/codacy/patterns/Custom_Scala_FieldNamesChecker.scala

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

patterns-base/src/main/scala/codacy/patterns/Custom_Scala_FieldNamesChecker.scala#L46

Method isEnumValDefRegexOrDecl has a cyclomatic complexity of 14 (limit is 8)
val extendsEnumeration: Boolean = parent
.collect {
case template"{ ..$stats } with ..${ctorcalls: Seq[Init]} { $param => ..$stats2 }" =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ case object Custom_Scala_GetInMethodName extends Pattern {

override def apply(tree: Tree) = {
tree.collect {
case t @ q"..$mods def ${name: Term.Name}[..$tparams](...$paramss): $tpeopt = $expr"
if name.value != "get" && name.value.startsWith("get") =>
Result(message(t), t)
case defn: Defn.Def
if defn.name.value != "get" && defn.name.value.startsWith("get") =>
Result(message(defn), defn)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,37 @@ case object Custom_Scala_GroupImports extends Pattern {
tree
.collect {
case t: Template =>
t.stats
imports(t.stats)
case q"package $ref { ..$stats }" =>
stats
imports(stats)
case t: Term.Block =>
t.stats
imports(t.stats)
}
.map(imports)
.flatMap(duplicatedImporters)
.map { tree =>
Result(message(tree), tree)
}
}

private[this] def duplicatedImporters(imports: Seq[Tree]) = {
private[this] def duplicatedImporters(imports: Seq[Tree]): Seq[Tree] = {
val tupled = imports.collect { case t @ importer"$ref.{..$importeesnel}" => (ref, t) }

tupled
.groupBy { case (ref, _) => ref.toString }
.collect {
.flatMap {
case (_, importers) if importers.length > 1 =>
importers
.map { case (_, importer) => importer }
.sortBy { importer: Tree =>
(importer.pos.startLine, importer.pos.startColumn)
}
.take(1)
case _ => Seq.empty
}
.flatten
.toSeq
}

private[this] def imports(body: Seq[Tree]) = {
private[this] def imports(body: Seq[Tree]): Seq[Tree] = {
body.collect { case t @ q"import ..$importersnel" => importersnel }.flatten
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ case object Custom_Scala_IndexOfPositive extends Pattern {

override def apply(tree: Tree): List[Result] = {
tree.collect {
case t @ q"$_.indexOf( ..${args: Seq[Term]}) > ${lit: Lit}" if isNaturalNumber(lit) =>
case t @ q"$_.indexOf( ..${args: Term.ArgClause}) > ${lit: Lit}" if isNaturalNumber(lit) =>
Result(message(t), t)
case t @ q"${lit: Lit} < $_.indexOf( ..${args: Seq[Term]})" if isNaturalNumber(lit) =>
case t @ q"${lit: Lit} < $_.indexOf( ..${args: Term.ArgClause})" if isNaturalNumber(lit) =>
Result(message(t), t)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ case object Custom_Scala_IndexOfStartPosition extends Pattern {

override def apply(tree: Tree) = {
tree.collect {
case t @ q"$expr.indexOf( ..${args: Seq[Term]} )" if args.length == 1 =>
case t @ q"$expr.indexOf( ..${args: Term.ArgClause} )" if args.values.length == 1 =>
Result(message(t), t)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,35 @@ case object Custom_Scala_LowerCasePatternMatching extends Pattern {

override def apply(tree: Tree) = {
tree.collect {
case t @ p"case ${pat: Pat.Var} => $expr" if isOffender(t, pat) =>
case t @ Case(pat: Pat.Var, _, _) if isOffender(t, pat) =>
Result(message(t), t)
}
}

private[this] def isOffender(tree: Tree, pat: Pat) = {
!hasDeclaredType(pat) && !isCaseFromCollect(tree) && !isCaseFromPartialFunction(tree) && isLowerCase(pat)
!hasDeclaredType(pat) &&
!isCaseFromCollect(tree) &&
!isCaseFromPartialFunction(tree) &&
!isCaseFromCatch(tree) &&
isLowerCase(pat)
}

private[this] def isPartialApplication(tpe: Term.Name) = tpe.toString match {
case "orElse" | "andThen" => true
case _ => false
}

private[this] def isCaseFromPartialFunction(tree: Tree): Boolean = {
tree.parent.flatMap(_.parent).exists {
case q"..$mods val ..$patsnel: $tpeopt = { ..case $casesnel }" => true
case q"$expr $tpe { ..case $casesnel}" if isPartialApplication(tpe) => true
case q"$expr.$tpe { ..case $casesnel }" if isPartialApplication(tpe) => true
case q"$expr $tpe[..$tpesnel] { ..case $casesnel }" if isPartialApplication(tpe) => true
case q"$expr.$tpe[..$tpesnel] { ..case $casesnel }" if isPartialApplication(tpe) => true
case _: Defn.Val => true
case block: Term.Block =>
block.stats.exists {
case _: Term.CasesBlock => true
case _ => false
}
case _ => false
}
}

private[this] def isCaseFromCollect(tree: Tree): Boolean = {
tree.parent.flatMap(_.parent).exists {
case q"$_.collect(..$_)" => true
case q"$_.collect[..$_](..$_)" => true
case q"$_ collect $_" => true
case Term.Apply(Term.Select(_, Term.Name("collect")), _) => true
case _ => false
}
}
Expand All @@ -55,5 +54,12 @@ case object Custom_Scala_LowerCasePatternMatching extends Pattern {
pat.collect { case t @ p"$expr: $tpe" => t }.nonEmpty
}

private[this] def isCaseFromCatch(tree: Tree): Boolean = {
tree.parent.exists {
case t: Term.Try => t.catchp.exists(_ == tree)
case _ => false
}
}

private[this] def message(tree: Tree) = Message("Lower case pattern matching.")
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ case object Custom_Scala_NonFatal extends Pattern {

override def apply(tree: Tree) = {
tree.collect {
case t @ q"try $expr catch { ..case $cases } finally $expropt" =>
cases.collect {
case t: Term.Try =>
t.catchp.collect {
case cs if isNonFatalCatch(cs) =>
Result(message(cs), cs)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,17 @@ case object Custom_Scala_ProhibitObjectName extends Pattern {
tree.collect {
case t: Defn.Class =>
defsWithNameIn(t, t.name.toString)
case t @ q"..$mods trait $tname[..$tparams] extends $template" =>
defsWithNameIn(t, tname.toString)
case t @ q"..$mods object $name extends $template" =>
defsWithNameIn(t, name.toString)
case t: Defn.Trait =>
defsWithNameIn(t, t.name.toString)
case t: Defn.Object =>
defsWithNameIn(t, t.name.toString)

}.flatten
}

private[this] def defsWithNameIn(tree: Tree, cName: String) = {
tree.collect {
case t @ q"..$mods def $name[..$tparams](...$paramss): $tpeopt = $expr" if name.toString.endsWith(cName) =>
Result(message(t), t)
case t @ q"..$mods def $name[..$tparams](...$paramss): $tpe" if name.toString.endsWith(cName) =>
case t: Defn.Def if t.name.toString.endsWith(cName) =>
Result(message(t), t)
}
}
Expand Down
Loading