Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Keeps your code fresh smelling: generate bad code smells specs2 specifications for any source language.


sniff is available via the Maven Central repository and current supports Scala 2.9.1, 2.9.2 and 2.10.0.


libraryDependencies ++= Seq(
  "net.rosien" %% "sniff" % "0.10" % "test"



Build Status


import org.specs2.Specification

class SniffSpec extends Specification { 
  import net.rosien.sniff._
  def is = "Scala code shouldn't smell" ^ Language.Scala.snippets.sniff("src/main/scala", "src/test/scala")

Running this spec in sbt scans the directories src/main/scala and src/test/scala for bad code smells described by regular expressions:

> test
[info] Compiling 1 Scala source to /Users/arosien/asr/sniff/target/
[info] SniffSpec
[info] Code shouldn't smell
[info] + /Users/arosien/asr/sniff/src/main/scala/sniff.scala smells ok
[info] + /Users/arosien/asr/sniff/src/test/scala/SniffSpec.scala smells ok
[info] Total for specification SniffSpec
[info] Finished in 504 ms
[info] 2 examples, 0 failure, 0 error
[info] Passed: : Total 2, Failed 0, Errors 0, Passed 2, Skipped 0
[success] Total time: 4 s, completed Jan 22, 2012 7:13:31 PM

If I add the string "" to the above code (to make the smell spec fail) I get:

> test
[info] SniffSpec
[info] Code shouldn't smell
[info] + /Users/arosien/asr/sniff/src/main/scala/sniff.scala smells ok
[error] x /Users/arosien/asr/sniff/src/test/scala/SniffSpec.scala smells ok
[error]     /Users/arosien/asr/sniff/src/test/scala/SniffSpec.scala:8: failed snippet 'java\.net\.URL' (URL actually resolves hostnames over the network, use instead) '  //' matches '.*java\.net\.URL.*' (sniff.scala:40)
[info] Total for specification SniffSpec
[info] Finished in 277 ms
[info] 2 examples, 1 failure, 0 error
[error] Failed: : Total 2, Failed 1, Errors 0, Passed 1, Skipped 0
[error] Failed tests:
[error]   net.rosien.sniff.SniffSpec
[error] {file:/Users/arosien/asr/sniff/}default-28e91d/test:test: Tests unsuccessful
[error] Total time: 1 s, completed Jan 23, 2012 9:46:05 AM

If there are bad smells that you temporarily want to ignore you can define an implicit Ignores value:

// snippets.sniff() uses this implicit
implicit val ignore = Ignores(
      Ignore('NoURL, "src/test/scala/SniffSpec.scala"),

Defining your own smells

import org.specs2.Specification
import net.rosien.sniff._
val mySmells = 
  Smell('NoMutableCollections, """scala\.collection\.mutable""".r, rationale = "Immutable is better than mutable. - El Jefe", Scala, 'movieReferences) ::
  // more smells

class SniffSpec extends Specification { 
  def is = "Die smells die" ^ CodeSnippets(Language.Scala, mySmells: _*).sniff("src/main/scala", "src/test/scala")

There is a growing list of default smells for various languages defined at Please fork and send me a pull request to have yours included.

To define a new language just create a singleton object extending net.rosien.sniff.Language.

Regular Expressions? WTF!?

There are lots of ways to model "bad code smells", from simple rules to deep language parsing. sniff emphasizes:

  • smells as regular expressions, because they are easy to write and test for any source language
  • broadly scoped smells rather than complex predicates ("never use X")
  • a simple exception mechanism to ignore false positives

For more complex rules and deeper analysis, try these great tools:



  • Magic token to ignore smells on a line or in a region, e.g., for use in commented-out code.
  • Executable jar to sniff stuff from the command-line, e.g., for use in continuous integration systems.
  • Sniff helper method for maven-style paths (src/main/scala, etc.)


The license is Apache 2.0, see LICENSE-2.0.txt.


Keep your code fresh smelling: generate "bad code smells" specs2 specifications for any source language.






No packages published