Scala

Scala

Made by DeepSource
Detected unreachable code SC-W1006
Bug risk
Major

Unreachable code is usually a result of programming error - usually when statements like 'return' are misplaced. This causes some part of the code to not execute at all, thus affecting the overall control-flow and behaviour of the program.

Empty interpolated string SC-W1011
Bug risk
Critical

Empty interpolated string is usually a result of human error - either that the programmer forgot to specify the required arguments, or that the string wasn't meant to be interpolated. Such strings can critically alter the behaviour and control-flow of the program if the program relies on it.

Consider using None instead of Some(null) SC-A1002
Anti-pattern
Minor

It is more idiomatic in scala to use Option, i.e. Some and None instead of null. Using Some(null) instead of None defeats the entire purpose of Option. However, there might be certain scenarios where this is a legitimate approach, such as when dealing with Java-based libraries, to improve compatibility.

Carefully consider whether using Option with null is necessary before doing so.

Usage of wildcard imports SC-C1001
Style
Minor

It is suggested that you do not use wildcards in the import statements. This defeats the entire purpose of properly packing the code into different classes and packages. Rather, import only what you need.

Consider grouping imports from same package together SC-R1011
Anti-pattern
Minor

Scala allows you to import entities from same package in separate statements. However, it is generally recommended that you group such imports together. Doing so makes the code more readable and easier to navigate.

Methods returning Option should only return Some or None SC-T1005
Type check
Major

Methods with return type Option should either return Some if a suitable value exists or None if not. Returning null from such methods can have unintended side effects.

Exception naming does not follow the recommended style SC-C1000
Style
Minor

Exceptions usually follow the AbcDefException nomenclature. Some examples are - NullPointerException, RuntimeException, etc. This allows the person reading/viewing the code understand that the entity being dealt with is an Exception rather than having to rely on the context.

Replace find() [==/!=] None with exists() SC-R1009
Anti-pattern
Minor

find() allows you to look for elements in a collection that satisfy the provided condition/predicate. However, if you only need to determine whether elements matching your predicate exist, it is suggested that you directly use exists() as it is slightly more efficient, readable, and easy to maintain.

Duplicate case in pattern-matching SC-W1007
Bug risk
Major

Duplicate cases in pattern matching are unreachable and are usually the result of human error. Because such cases are unreachable, they have the potential to affect the overall control-flow and the behaviour of the program. It is suggested that you remove such duplicate cases.

Using .deep to compare Arrays is deprecated SC-W1051
Bug risk
Critical

Comparing two Arrays using .deep is deprecated and is not supported beyond Scala version 2.12. To avoid compilation errors when moving to version 2.13 and above, consider switching to a more well supported alternative.

Methods with single statement in body may follow single-line convention SC-C1006
Style
Minor

Any Scala method with a single statement in the body maybe refactored to follow the single-line convention. If the statement is more than 30 chars but less than 70, it is suggested that you move it to the next line and indent it with 2 spaces.

Use .lastOption to access the last element SC-P1001
Performance
Major

Certain Scala structures such as List implement methods such as .reverse that allows you to reverse the contents of a structure. This however can be an expensive operation and depends upon the kind of structure and the number of elements in it. Therefore, directly accessing the last element via .lastOption is more concise and performant than reversing an entire collection and then accessing the first element.

Use .isEmpty or .nonEmpty to check if structure is empty SC-P1002
Performance
Major

Scala allows you to use comparison operators such as == and != against List() and Set() to check if a structure is empty or not. However, this method is considered to be in-efficient as doing so instantiates a new and empty structure which is only disposed off by the GC when deemed appropriate, thus causing an additional overhead. Therefore, it is suggested that you use the structures' .isEmpty and .nonEmpty methods to check if the respective structures are empty or not.

Too many method parameters SC-C1002
Style
Minor

This method takes too many parameters - a potential code smell/styling issue which affects the overall readability of the code. Consider using default parameter values/currying.

Consider filtering first and then sorting SC-P1003
Performance
Major

Algorithms such as sorting and filtering depend upon size of a structure, i.e. the number of elements in a structure. If you wish to arrange your elements in a specified order and select only a subset of these elements, it is suggested that you first filter the elements according to your criteria and then sort them as this potentially reduces the number of elements to be sorted, thus reducing the overall time spent performing this operation.

Consider using the appropriate overloaded method when searching for a single char SC-P1004
Performance
Major

Methods such as String.indexOf and String.lastIndexOf allow you to search for an occurrence of either a single char or a substring within a String. If you'd like to search for an occurrence of a single char, it is recommended that you use the appropriate method that takes a Char as a parameter rather than a String as the former approach is more performant and recommended.

Calling List.size is inefficient SC-P1005
Performance
Major

Scala's List data-structure is an immutable sequence of elements, implemented as a linked list. Therefore, methods such as .size have a complexity of O(n). Repeatedly calling such methods can impact the performance of your application. Therefore, it is suggested that you use a different structure such as an Array or an ArrayBuffer depending whichever that suites your needs.

Benchmarks -

val numsList = (1 to 1000000).toList

// 2713250ns
time {
  numsList.size
}

val numsArray = (1 to 1000000).toBuffer

// 11750ns
time {
  numsArray.size
}
Consider rewriting filter().headOption as find() SC-P1006
Anti-pattern
Major

The scala analyzer has determined that this collection method chain can be simplified into a single call to find().

Appending to List is in-efficient SC-P1007
Performance
Major

Scala's List data-structure is an immutable sequence of elements, implemented as a linked list. Therefore, operations such as append have a complexity of O(n). Repeatedly calling such methods can impact the performance of your application. If you need to append a large number of elements, it is suggested that you use a different structure such as an ArrayBuffer or a Vector depending on whichever that suites your needs.

Consider combining successive .filter() calls SC-P1009
Performance
Major

Certain Scala collections support methods such as .filter, allowing you to select elements from your collection based on specified conditions. Since each filter call iterates through the entire collection, it is recommended that you combine/chain such consecutive calls to avoid re-iterations.