Skip to content
Benjamin Ran edited this page Jan 6, 2019 · 19 revisions

Welcome to the Scalastyle wiki.

Most of the documentation has now moved to http://www.scalastyle.org. This wiki is just used as a list of suggestions for new rules.

Note that in addition to the resources here on GitHub, the project has a Google group for discussion.

The following pages contain a list of proposed rules for Scalastyle.

The list of rules and indeed categories are completely inspired by and stolen from the excellent Checkstyle.

Please feel free to modify the text of this pages, in particular:

  • adding new rules that you want
  • refining the rules that are here with more concrete requirements

Annotations

MissingDeprecated

Verifies that both the java.lang.Deprecated annotation is present and the @deprecated Scaladoc tag is present when either is present.

Block Checks

EmptyBlock

Checks for empty blocks.

Class Design

DesignForExtension

Checks that classes are designed for extension. More specifically, it enforces a programming style where superclasses provide empty "hooks" that can be implemented by subclasses. The exact rule is that nonprivate methods of classes that can be subclassed must either be

  • abstract or
  • final or
  • have an empty implementation
Rationale: This API design style protects superclasses against beeing broken by subclasses. The downside is that subclasses are limited in their flexibility, in particular they cannot prevent execution of code in the superclass, but that also means that subclasses cannot corrupt the state of the superclass by forgetting to call the super method.

ThrowsCount

Restricts throws statements to a specified count (default = 1). Rationale: Exceptions form part of a methods interface. Declaring a method to throw too many differently rooted exceptions makes exception handling onerous and leads to poor programming practices such as catch (Exception). This check forces developers to put exceptions into a heirachy such that in the simplest case, only one type of exception need be checked for by a caller but allows any sub-classes to be caught specifically if necessary.

Coding

EmptyStatement

Detects empty statements (standalone ;).

FinalLocalVariable

Checks that local variables that never have their values changed are declared val. The check can be configured to also check that unchanged parameters are declared val.

HiddenField

Checks that a local variable or a parameter does not shadow a field that is defined in the same class.

MissingSwitchDefault

Checks that pattern matches have "_" clause. Rationale: It's usually a good idea to introduce a default case in every pattern match statement. Even if the developer is sure that all currently possible cases are covered, this should be expressed in the default branch, e.g. by using an assertion. This way the code is protected aginst later changes, e.g. introduction of new types in an enumeration type.

RedundantThrows

Checks for redundant exceptions declared in throws clause such as duplicates, unchecked exceptions or subclasses of another declared exception.

IllegalCatch

Catching java.lang.Exception, java.lang.Error or java.lang.RuntimeException is almost never acceptable. Rationale: Junior developers often simply catch Exception in an attempt to handle multiple exception classes. This unfortunately leads to code that inadvertantly catchs NPE, OutOfMemoryErrors, etc.

IllegalThrows

This check can be used to ensure that types are not declared to be thrown. Declaring to throw java.lang.Error or java.lang.RuntimeException is almost never acceptable.

PackageDeclaration

Ensure a class has a package declaration, and (optionally) whether the package name matches the directory name for the source file. Rationale: Classes that live in the null package cannot be imported. Many novice developers are not aware of this.

DeclarationOrder

[MJF] TODO to be updated to fit in with Scala Style guide According to Code Conventions for the Java Programming Language , the parts of a class or interface declaration should appear in the following order:

  1. Class (static) variables. First the public class variables, then the protected, then package level (no access modifier), and then the private.
  2. Instance variables. First the public class variables, then the protected, then package level (no access modifier), and then the private.
  3. Constructors
  4. Methods

MultipleVariableDeclarations

[MJF] update for Scala style guide Checks that each variable declaration is in its own statement and on its own line. Rationale: the SUN Code conventions chapter 6.1 recommends that declarations should be one per line/statement.

UnnecessaryParentheses

Checks for the use of unnecessary parentheses.

OneStatementPerLine

Checks there is only one statement per line. The following line will be flagged as an error: x = 1; y = 2; // Two statements on a single line.

Imports

RedundantImport

Checks for redundant import statements. An import statement is considered redundant if:

  • It is a duplicate of another import. This is, when a class is imported more than once.
  • The class imported is from the scala package, e.g. importing scala.String.
  • The class imported is from the same package.

ImportOrder

Checks the ordering/grouping of imports. Features are:

  • groups imports: ensures that groups of imports come in a specific order (e.g., scala. comes first, then everything else)
  • adds a separation between groups : ensures that a blank line sit between each group
  • sorts imports inside each group: ensures that imports within each group are in lexicographic order
  • sorts according to case: ensures that the comparison between imports is case sensitive
  • groups static imports: ensures the relative order between regular imports and static imports (see import orders)

Syntax

Checks syntax of imports. Features are:

  • full imports: ensures that imports declare the full package (some exceptions should be possible when it is common, e.g. allow import scalaz._; import Scalaz._)

Metrics

BooleanExpressionComplexity

Restrict the number of number of &&, ||, &, | and ^ in an expression. Rationale: Too many conditions leads to code that is difficult to read and hence debug and maintain. Note that the operators & and | are not only integer bitwise operators, they are also the non-shortcut versions of the boolean operators && and ||.

ClassFanOutComplexity

The number of other classes a given class relies on. Also the square of this has been shown to indicate the amount of maintenence required in functional programs (on a file basis) at least.

Miscellaneous

TodoComment

A check for TODO: comments. Actually it is a generic regular expression matcher on Scala comments. To check for other patterns in Scala comments, set property format.

TrailingComment

The check to ensure that requires that comments be the only thing on a line. For the case of // comments that means that the only thing that should precede it is whitespace. It doesn't check comments if they do not end line, i.e. it accepts the following:

Thread.sleep( 10 /*some comment here*/ ).

Rationale: Steve McConnel in "Code Complete" suggests that endline comments are a bad practice. An end line comment would be one that is on the same line as actual code. For example:

a = b + c; // Some insightful comment
d = e / f; // Another comment for this line

Quoting "Code Complete" for the justfication:

  • "The comments have to be aligned so that they do not interfere with the visual structure of the code. If you don't align them neatly, they'll make your listing look like it's been through a washing machine."
  • "Endline comments tend to be hard to format...It takes time to align them. Such time is not spent learning more about the code; it's dedicated solely to the tedious task of pressing the spacebar or tab key."
  • "Endline comments are also hard to maintain. If the code on any line containing an endline comment grows, it bumps the comment farther out, and all the other endline comments will have to bumped out to match. Styles that are hard to maintain aren't maintained...."
  • "Endline comments also tend to be cryptic. The right side of the line doesn't offer much room and the desire to keep the comment on one line means the comment must be short. Work then goes into making the line as short as possible instead of as clear as possible. The comment usually ends up as cryptic as possible...."
  • "A systemic problem with endline comments is that it's hard to write a meaningful comment for one line of code. Most endline comments just repeat the line of code, which hurts more than it helps."
  • His comments on being hard to maintain when the size of the line changes are even more important in the age of automated refactorings.

OuterTypeFilename

Checks that the outer type name and the file name match. For example, the class Foo must be in a file named Foo.scala.

PackageNameEqualsFSName

Checks that the package name and the path to the filesystem match. Even though Scala let a package declaration can differ in its value from the path of the current file (� la Java), it could still be a good practice to enforce this symmetry. Some tools require it and it make it easier to browse into the project.

Possible Incorrect Semicolon Inference

Checks if a semicolon is inferred at a position where it should not be inferred.

def f = 10
  +3

In this example +3 is dead code because a semicolon in inferred after 10.

Allow Early Return Without Return Value

Early return statements should be allowed when their only sense is to halt method execution. All other return statements should raise an error.

def f(i: Int) {
  if (isInvalid(i)) return
  ...
}

Modifiers

ModifierOrder

Checks that the order of modifiers conforms to the suggestions in the Scala style guide. The correct order is: to be defined.

RedundantModifier

Checks for redundant modifiers in:

  • trait definitions (such as abstract trait T)
  • the final modifier on methods of final classes (final class Foo { final def foo() = 4 })

Rationale: It adds needless code to files.

Variables in interfaces and annotations are automatically public, static and final, so these modifiers are redundant as well.

As annotations are a form of interface, their fields are also automatically public, static and final just as their annotation fields are automatically public and abstract. Final classes by definition can not be extended so the final modifier on the method of a final class is redundant.

Naming Conventions

FieldNames

Checks that the field names follow the regular expression [a-z][a-zA-Z]*

Parameters

  • regex: the regular expression to use

VariableNames

Checks that the variable names follow the regular expression [a-z][a-zA-Z]*

Parameters

  • regex: the regular expression to use

Scaladoc Comments

ScaladocPackage

Checks that each Scaladoc package has a Scaladoc file (package.html) used for commenting.

ScaladocType

Checks Scaladoc comments for class and interface definitions.

ScaladocVariable

Checks that variables have Scaladoc comments.

ScaladocStyle

Validates Scaladoc comments to help ensure they are well formed. The following checks are performed:

  • Ensures the first sentence ends with proper punctuation (That is a period, question mark, or exclamation mark, by default). Scaladoc automatically places the first sentence in the method summary table and index. With out proper punctuation the Scaladoc may be malformed. All items eligible for the {@inheritDoc} tag are exempt from this requirement.
  • Check text for Scaladoc statements that do not have any description. This includes both completely empty Scaladoc, and Scaladoc with only tags such as @param and @return.
  • Check text for incomplete HTML tags. Verifies that HTML tags have corresponding end tags and issues an "Unclosed HTML tag found:" error if not. An "Extra HTML tag found:" error is issued if an end tag is found without a previous open tag.
  • Check that a package Scaladoc comment is well-formed (as described above) and NOT missing from any package-info.java files.
  • Check for allowed HTML tags. The list of allowed HTML tags is "a", "abbr", "acronym", "address", "area", "b", "bdo", "big", "blockquote", "br", "caption", "cite", "code", "colgroup", "del", "div", "dfn", "dl", "em", "fieldset", "h1" to "h6", "hr", "i", "img", "ins", "kbd", "li", "ol", "p", "pre", "q", "samp", "small", "span", "strong", "sub", "sup", "table", "tbody", "td", "tfoot", "th", "thread", "tr", "tt", "ul".

These checks were patterned after the checks made by the DocCheck doclet available from Sun.

Size Violations

ExecutableStatementCount

Restricts the number of executable statements to a specified limit.

AnonInnerLength

Checks for long anonymous inner classes. Rationale: If an anonymous inner class becomes very long it is hard to understand and to see the flow of the method where the class is defined. Therefore long anonymous inner classes should usually be refactored into a named inner class.

Types

Type Annotation

Checks that types are annotated with the colon in the correct place This passes: def method(): Int = 1 This fails def method() : Int = 1 Rationale: This is standard behaviour in the scala library, and avoids confusion in certain circumstances.

Type Parameter Shadowing

Checks that a type parameter does not shadow another one:

def meth[A](a: A, f: A => A): List[A] = {
  val as = List(f(a))
  def inner[A](a: A) = f(a)
  inner(a) :: as
}

This code example does not compile and fails with the following cryptic error message:

<console>:10: error: type mismatch;
 found   : a.type (with underlying type A)
 required: A
         def inner[A](a: A) = f(a)
                                ^

Scalastyle can do a better job and raise a warning on the declaration of the type parameter of inner.

Whitespace

MethodParamPad

Checks the padding between the identifier of a method definition, constructor definition, method call, or constructor invocation; and the left parenthesis of the parameter list. That is, if the identifier and left parenthesis are on the same line, checks whether a space is required immediately after the identifier or such a space is forbidden. If they are not on the same line, reports an error, unless configured to allow line breaks. To allow linebreaks after the identifier, set property allowLineBreaks to true.

ParenPad

Checks the policy on the padding of parentheses; i.e. whether a space is required after a left parenthesis and before a right parenthesis, or such spaces are forbidden.