jSparrow

WHAT IS jSPARROW?

Jsparrow is a tool that refactors Java code for you, powered by the Eclipse Java compiler.
Based on a set of rules you can decide which improvements should be applied to your code base. These rules range from removing code smells to the introduction of lambda functionals.

One of the latest additions is the usage of the var keyword for local variables to minimize the boilerplate code and increase readability.
You can execute it as part of your development process as an Eclipse IDE Plug-In or integrate it seamlessly into your CI/CD pipeline as a maven Plugin.
3 reasons to work with jSparrow

3 reasons to work with jSparrow

Modernisation

jSparrow helps you upgrade your legacy codebase by automatically transforming old Java language constructs to new ones. i.e. While- and For-Loops will be transformed to Java Streams and java.util.Date will be upgraded to java.time.*

Clean Code

Rules like “Rearrange Class Members” or  “Split Multiple Variable Declarations”” help you keep your code structured and readable. We always develop our rules with best practices in mind.

Bug Prevention

Sometimes bugs can be avoided just by tweaking the Java Syntax a bit. i.e. The “Reorder String Equality Check” rule prevents Null Pointer Exceptions when comparing a String Object and a String Literal. Since a String Literal can’t be null, equals() is called on that literal with the String Object as parameter.

Videos

Measurement

Measurement

  • jSparrow was able to resolve up to one third of the overall issues measured with third party source code analyzers, on various opensource projects. An estimated human effort of several months could be spared by jSparrow in less than five minutes.
jSparrow Rules

jSparrow Rules

JSPARROW'S RULES CREATED TO ASSIST YOU IN YOUR EVERY DAY CODING.

Note: This Table was updated 25.09.2018 which means rules could have already been redone and/or fixed as well as new rules might already be available without shown down below.

Name of rule 25/09/2018What it doesMinimun Java version 
Add Parenthesis to Control StatementsTransforms single statements after control statements to block constructs by adding curly braces. This improves readability.1.1format, organize, readability
Make SerialVersionUID Static FinalApplying this rule adds the modifiers static and final long variables with the name SerialVersionUID, as this confirms to Java code conventions. For example, 'private long serialVersionUID = 1L' becomes 'private static final long serialVersionUID = 1L'.1.1conventions
Organize ImportsAccording to Oracle code conventions members of classes and interfaces should appear in the following order:1) Class variables 2) Instance variables3) Constructors4) Methods. Additionally, those members should be sorted based on their access modifier. Applying this rule will sort class members to promote readability.1.1format, organize, readability
Rearrange Class MembersReformats code according to the coding conventions defined in Eclipse. For example, line breaks will be added if lines are too long. Properly formatted code improves readability and makes collaboration easier.1.1readability
Reformat CodeReformats code according to the coding conventions defined in Eclipse. For example, line breaks will be added if lines are too long. Properly formatted code improves readability and makes collaboration easier.1.1format, organize, readability
Remove Boxing for String ConversionsWhen calling toString() on a primitive no new instance of that primitive has to be created. This rule replaces occurrences of such code with a static method. For example, 'new Integer(1).toString()' becomes 'Integer.toString(1)'. Applying this rule improves performance. 1.1string-manipulation, performance
Remove Deprecated Date ConstructsRemoves deprecated Date constructs which are obsolete since JDK version 1.11.1format, organize, readability
Remove Explicit Type ArgumentSince Java 1.7 the Diamond Operator (<>) can be used to simplify instance creation where generics are involved.For example, 'Map> myMap = new HashMap>()' can be replaced by 'Map> myMap = new HashMap<>()'. In order to apply this rule your project must use Java 1.7 or later.7outdated constructs
Remove Inherited Interfaces from Class DeclarationRemove interfaces from class declaration, which are already implemented by a super class. These interfaces are inherited from the super class.1.1lambda
Remove Lambda Expression ParenthesisIf the body of a Lambda statement contains only a single expression braces are optional. It can be reduced to a lambda expression by removing the parenthesis.For example 'stream.map(x -> { return x*2 })' is replaced by 'stream.map(x -> return x*2)'.This makes the code more readable and more concise.8lambda
Remove toString() on StringAll method invocations of toString() on a String element are not needed. Applying this rule will remove such method calls.For example, '"string".toString()' becomes '"string"'.This transformation improves performance.1.1string-manipulation, performance
Reorder String Equality CheckTo avoid NullPointerExceptions, String literals should be placed on the left side when checking for equality. This means that 'val.equals("val")' is transformed into '"val".equals(val)'.1.1string-manipulation
Replace Assignment with Compound OperatorAssignments involving an arithmetic assignment can be simplified by using a compound operator such as '+=', '-=', '/=' or '*='.For example, this rule will transform 'a=a+1' into 'a+=1'.The rule only applies if both operands are primitive types.1.4readability, conventionsconstructs
Replace Concatenation with Infix-OperationThis rule replaces the concat() method on Strings with the '+' operator.For example, 's = s.concat("bar")' becomes 's = s + "bar"'. This improves readability and performance for chained concatenations.1.1string-manipulation
Replace Equality Check with isEmpty()Java 6 introduced isEmpty() on collections and Strings. This rule replaces equality checks involving length() or size() with calls to isEmpty(). For example, 's.length() == 0' becomes 's.isEmpty()'.Applying this rule improves readability.6readability, conventions, outdated constructs
Replace equals() on Enum ConstantsReplace occurrences of equals() on Enum constants with an identity comparison (==). In the case the equals relation is wrapped with an boolean negation the result will be an not equals (!=).5conventions
Replace Expression Lambda with Method ReferenceThis rule simplifies expression lambdas by using method reference.For example, 'personList.forEach(person -> doSomething(person))' becomes 'personList.forEach(this::doSomething)'.This rule can only be applied if the parameters of the lambda expression and the method match.8lambda
Replace For-Loop with Enhanced-For-LoopSince Java 1.5 enhanced for-loops can be used to iterate over collections. This rule replaces old for-loops utilizing iterators with enhanced for-loops in order to improve readability.5outdated constructs, loop
Replace For-Loop with Stream::anyMatchReplaces an occurrences of enhanced for-loops which are only used to initialize or return a boolean variable with Stream::anyMatch. The stream syntax is more concise and improves readability.8lambda, loop
Replace For-Loop with Stream::collect(Collectors.joining())Transforms loops which are only used for concatenating a string to an invocation of Stream::collect(Collectors.joining()).If the Java compliance level is below 1.8 and at least 1.5, then a StringBuilder is introduced for concatenating the values on each iteration of the loop.5lambda, loop
Replace For-Loop with Stream::findFirstEnhanced for-loops which are used to find an element within a collection can be replaced by Stream::findFirst. Using the stream syntax a multi-line control statement can be reduced to a single line. 8lambda, loop
Replace For-Loop with Stream::forEachEnhanced For-Loops can be replaced by forEach().For example 'for(Item item: items) { }' becomes 'items.forEach()'.This makes code more readable and can be combined with other stream functions such as filter and map.8lambda, loop
Replace For-Loop with Stream::sumReplace For-Loop with Stream::sum8lambda, loop
Replace indexOf() with contains()This rule replaces calls to indexOf() on instances of String or Collection with calls to the contains() method.For example 'l.indexOf(s) >= 0' is transformed to 'l.contains(s)'.contains()' was introduced in Java 1.4 and helps to make the code more readable.5readability, outdated constructs
Replace Inefficient Constructors with valueOf()All calls to a constructor of a primitive type will be replaced by the corresponding static valueOf() method.For example 'new Integer("1")' becomes 'Integer.valueOf("1")'.5conventions, performance
Replace Nested Loops with flatMapReplace Nested Loops with flatMap8lambda, loop
Replace put(..) with putIfAbsent(..)Java 8 adds an API that allows for conditionally adding entries to a map. Before, one would have to resort to if-statements.For example, 'if(!map.containsKey(aKey)) { map.put(aKey, aValue); }' becomes 'map.putIfAbsent(aKey,aValue)'.Using this rule reduces clutter and improves readability8outdated constructs
Replace removeAll() with clear()Simplifies the code by replacing all occurrences of removeAll() which have the current collection as parameter with clear(). For example, list.removeAll(list) becomes list.clear().1.2outdated constructs
Replace static final Collections with Collections.unmodifiable...()An unmodifiable Collection can be created with the matching Collections.unmodifiable...() method. Some examples are Collections.unmodifiableList(), Collections.unmodifiableSortedSet(), etc.A declaration of a Collection with the static and final modifiers is not sufficient because it might still be modifiable.The Collections which are created with Collections.unmodifiable...() throw an UnsupportedOperationException as soon as a modification is attempted.1.2conventions
Replace While-Loop with Enhanced For-LoopApplying this rule replaces While-loops over iterators with an equivalent for-loop. Loops where the body modifies the iterator in some way will not be transformed.5outdated constructs, loop
Split Multiple Variable DeclarationsCode conventions for Java recommend that each variable or field is declared on a separate line. This rule will split declarations occurring on the same lines over multiple lines to improve readability.1.1readability, conventions
StringBuffer() to StringBuilder()This rule changes the type of local variables from StringBuffer() to StringBuilder().5string-manipulation, performance
Use @Override AnnotationThis rule adds the @Override annotation to methods overriding or implementing parent class methods. Even though using @Override it is not mandatory, using this annotation is considered a best practice for two main reasons:1) It ensures that the method signature is a subsignature of the overridden method (otherwise, a compile error is indicated).2) It improves the readability.6readability, conventions
Use equals() on Primitive ObjectsIt is recommended that you use equals() on primitive objects. Applying this rule will replace occurrences of != and == with equals().For example, '"hello" == "world"' will become '"hello".equals("world")'Using this rule helps to avoid bugs, as == checks for object reference equality instead of value equality.1.1conventions, string-manipulation
Use Functional InterfacesAnonymous instances of a functional interface type are replaces by a simple lambda expression. Only instances of functional interfaces can be replaced.8outdated constructs, lambda
Use Multi-CatchJava 7 introduced the possibility to merge multiple catch clauses into a single multi-catch clause. Merging is only possible if the catch statements are identical. Using this rule reduces clutter and improves readability.7readability, outdated constructs
Use Portable NewlineThis rule replaces any occurrences of '\n' with '%n'. For example 'String.format("\n\n")' is replaced by 'String.format("%n%n")'.The benefit of this approach is that '%n' is portable across platforms.5string-manipulation
Use Stream::collectReplaces 'Stream.forEach' with 'Stream.collect' if the argument of the forEach statement is only used for adding elements to a list.For example, 'stream.forEach(x -> list.add)' is transformed into 'stream.collect(Collectors.toList())'.This simplifies adding elements to a list.5lambda, loop
Use Stream::filterIf-Statements making up the entire execution block of a Stream::forEach method can be transformed into a call to Stream::filter. This only applies if there are no other statements passed as arguments to forEach(). filter() can be used with other stream functions and improves readability. 8lambda, loop
Use Stream::mapExtracts a block from the body of the consumer of the Stream::forEach method and introduces Stream::map instead. This makes complicated code blocks easier to read and reuse.8lambda, loop
Use String LiteralsRemoves all class instantiations of String if the constructor parameter is empty or a String itself.For example 'new String("StringLiteral")' becomes '"StringLiteral"'. This improves performance and readability.1.1string-manipulation, performance
Use StringUtils MethodsThis rule replaces various String methods with their null-safe counterparts from StringUtils.For example, '"String".trim()' becomes 'StringUtils.trim("String")'.Using this rule makes null pointer exceptions less likely to occur.1.1string-manipulation
Use Try-With-ResourceThis rule adds the try-with-resources statement introduced in Java 7. Closing statements are removed as the construct takes care of that. Applying this rule makes the code safer and more readable. 7outdated constructs
Use Local Variable Type InferenceReplaces local variable declarations with var, wherever it is legal.10format, organize, readability
Use Optional::IfPresentReplaces if-clauses for Optionals with isPresent() by using the ifPresent(Consumer) method, which wraps the executing statements of the if clause into a Consumer.8outdated constructs, lambda

Two of our rules are configurable.

This increases readability, allows effective search and provides seamless integration.

 

Name of Configurable Rule 05/10/2018ConfigurationsMinimum Java Version: 
Logging Rule+ CLICK HERE FOR SCREENSHOT
This rule replaces the standard output statements with logger statements when possible. The following standard output methods are supported:

System.out.print(String),
System.out.println(String)
System.err.print(String)
System.err.println(String)
Throwable.printStackTrace()

As a replacement option, the user can choose either of the logger
methods provided by api-s of both of the supported loggers. In particular:

Logger.trace(String)
Logger.debug(String)
Logger.info(String)
Logger.warn(String)
Logger.error(String)
logging, outdated constructs, conventions
Rename Fields+ CLICK HERE FOR SCREENSHOT
This rule finds the fields that do not comply with the naming conventions and renames them.

private fields
protected fields
package-private fields
public fields

As a replacement option, the user can choose:

Search scope for references:
Project (References will be searched for in the enclosing project)
Workspace(Search for references in the whole workspace. This is slower)

Configure replacements:
Upper case(example "variable_name" to "variableName")
Leave case as is(example "variable_name" to "variablename")
or/and
Upper case(example "variable$name" to "variableName")
Leave case as is(example "variable$name" to "variablename")
5readability