Git Product home page Git Product logo

autorefactor's People

Contributors

bananeweizen avatar benzonico avatar cal101 avatar carstenartur avatar dependabot[bot] avatar fabrice-tiercelin avatar gzsombor avatar igorrosenberg avatar jlleitschuh avatar jnrouvignac avatar luiscruz avatar strkkk avatar vogella avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

autorefactor's Issues

Investigate refactorings for Java 1.7

  • #220 try with resources (aka AutoCloseable) - remove useless finally clauses
  • #124 try / multi catch - merge identical catch clauses
  • Rethrowing exceptions better detects the actual type of the exception
  • Use of static methods like with java.util.Objects
  • #118 Diamond operator - remove type arguments when the diamond operator does the job
  • Strings in switch - is there anything to do here?
  • Underscores in number literals
  • Arrays.copyOf() (This is Java 1.6 actually)
  • java.nio.charset.StandardCharsets.UTF_8
  • java.nio.file.Files

Configure the refactorings to use via preferences

As a user, I want to choose which refactorings to apply automatically.

Some of it could be automatically configured based on the Java > Code Style > Cleanup and/or Java > Code Style > Formatting.

Select refactorings from the UI

Do it from Workspace > Preferences, then Java > ???, like the Code Cleanups actions.
Also allow people to select by group/capabilities:

  • Behaviour preserving
  • Compile-safe
  • Possible compile errors

New refactoring - Replace old Vector / Hastable APIs with List-ArrayList / Map-HashMap

Replace Vector and Hastable only methods with List and Map methods

Here are the replacements to do for Vector:

  • Vector() => ArrayList()
  • Vector(Collection c) => ArrayList(Collection c)
  • Vector(int initialCapacity) => ArrayList(int initialCapacity)
  • Vector(int initialCapacity, int capacityIncrement) => ArrayList(int initialCapacity)
  • Vector.addElement() => List.add()
  • Vector.capacity() => ?
  • Vector.elementAt() => List.get()
  • Vector.elements() => List.iterator() - somewhat equivalent
  • Vector.firstElement() => List.get(0) -- Hmmm is it equivalent? Need to use if statement to ensure size?
  • Vector.indexOf(Object, int) => ?
  • Vector.lastElement() => List.get(Vector.size()) -- Hmmm is it equivalent? Need to use if statement to ensure size?
  • Vector.lastIndexOf(Object, int) => ?
  • Vector.copyInto() => List.toArray()
  • Vector.insertElementAt() => List.add()
  • Vector.removeAllElements() => List.removeAll()
  • Vector.removeElement() => List.remove()
  • Vector.removeElementAt() => List.remove()
  • Vector.setElementAt() => List.set()
  • Vector.setSize() => while (col.size() < X) { col.add(null);
  • Vector.trimToSize() => ArrayList.trimToSize()
  • other??

And for Hashtable:

  • Hashtable.elements() => Hashtable.entrySet().iterator() - somewhat
  • Hashtable.keys() => Hashtable.keySet().iterator() - somewhat
  • Hashtable.rehash() => ?

Replace Vector and Hastable by ArrayList and HashMap when the variable is local to a method

Issue #14 should cover this one.

Meta - JUnit and TestNG support

Refactor asserts

assertTrue(a.equals(b));
assertTrue(i == 0);
assertTrue(obj != null);
assertTrue(obj1 == obj2);
// etc.

into

assertEquals(a, b);
assertEquals(i, 0);
assertNotNull(obj);
assertSame(obj1, obj2);
// etc.

Do this for:

  • org.junit.Assert
  • junit.framework.Assert
  • org.testng.Assert

Remove try / catch / fail test anti pattern

Let the exception put the current test method in error.

@Test
public testMethod() {
    try {
        // ...
    } catch (Exception e) {
       fail("Unexpected Exception");
    }
}

Becomes:

@Test
public testMethod() throws Exception {
    // ...
}

Expected exceptions

JUnit

import org.testng.annotations.Test;
@Test(expectedExceptions = ArithmeticException.class)

TestNG

import org.junit.Test;
@Test(expected = ArithmeticException.class)

Expected vs. Actual

JUnit's and TestNG's Assert classes assume a very specific order for expected vs. actual value (Note: JUnit and TestNG use reversed order, but this is of no particular matter for the rest of this discussion).
If the developer does not respect this order, then a test failure will provide the wrong error message. The following assert with JUnit:

assertEquals(i, 6598);

Would output the following failure message::

junit.framework.AssertionFailedError: expected:<2883> but was:<6598>

Where logically, the message should have been:

junit.framework.AssertionFailedError: expected:<6598> but was:<2883>

This refactoring would consist in properly ordering the expected and actual values (with respect to the underlying framework), where constants are passed in the concrete parameters of the assert*() methods.
For implementation, here is the expected vs. actual order for each framework:

  • JUnit:
    ** junit.framework.Assert.assertEquals(expected, actual)
    ** org.junit.Assert.assertEquals(expected, actual)
  • TestNG:
    ** org.testng.Assert.assertEquals(actual, expected)

New refactoring - Remove uselessly specifying generics

Example 1

Code to refactor:

  public <A, B> Map<A,B> getBla(A a, B b)
  {
    if (a == null) {
      return Collections.<A,B>emptyMap();
    }
    return Collections.<A,B>singletonMap(val, val);
  }

Refactored code:

  public <A, B> Map<A,B> getBla(A a, B b)
  {
    if (a == null) {
      return Collections.emptyMap();
    }
    return Collections.singletonMap(val, val);
  }

Quick assist - Convert string concatenations to StringBuilder appends

As a developer I start writing a string concatenation until I figure out I need to convert it to StringBuilder appends.

Given

String s = "foo" + "bar" + "baz";

When

triggering the "convert to StringBuilder appends" quick fix

Then

Code is rewritten to:

String s = new StringBuilder("foo").append("bar").apend("baz").toString;

Because Exception is a super type of IOException and NullPointerException.

New refactoring - Simplify more complex boolean expressions

Example 1

This code:

if (b) {
    return someMethod();
} else {
    return false;
}

Can be rewritten to:

return b && someMethod();

Example 2

This code:

if (b) {
    return someMethod();
} else {
    return true;
}

Can be rewritten to:

return !b || someMethod();

Variations

  • with local variable declaration
  • with local variable assignment
  • with instance variable assignment
  • no else clause
  • use of boolean primitives
  • use of boolean objects
  • ...

Improve performance for large java file (and large code bases)

Improve performance for large code bases by changing how the refactorings are executed.

Instead of making each refactoring go visit the entire AST for a Java file, register each refactoring.

Only one visitor will visit the entire AST and will delegate each ASTNode to the refactorings one by one. When one refactoring decides to change the AST, other refactoring will be skipped (and subtree will not be visited) and will the visitor will move to the next sibling.

Investigate refactorings for Java 1.8

#See http://www.techempower.com/blog/2013/03/26/everything-about-java-8/ :

Also see https://blog.jetbrains.com/upsource/2016/08/03/what-to-look-for-in-java-8-code/

New refactoring - Reduce variable scope

This will certainly require building a Control Flow Graph to do some variable analysis. It would be nice to build the CFG without looking at the IBinding's to avoid the need to dump then reload the whole tree each time a change is made.

Loop on refactorings after successfully applying a refactoring

Given

A user has one file (or a group of file) to refactor,

When

the user hit Shift+Alt+Y to apply automatic refactorings

Then

Actual: User might have to hit again Shift+Alt+Y several times to ensure all the possible automatic refactorings have been applied
Expected: All the possible refactorings should have been applied to the file (or the group of files), even the refactorings that are enabled by other automatic refactorings

Add a CFG (Control Flow Graph) builder

Being able to use a CFG allow to build new or safer refactorings.
It analyses better how and where variables are used, allowing to make more informed decisions. Moreover other analysis can be built on top of it.

See:

Automatically correct spelling mistakes

Automatically correct spelling mistakes using the installed Eclipse dictionary (including user dictionary).

When there is only one correction suggestion, then it is safe to assume it can be replaced.

Problem comes when some words are used across the whole codebase, but it is not in the dictionary or the user dictionary. Can we somehow offer a first pass that finds all badly written words and offer to add them to the dictionary in batch, based on number of occurrences.

This can be done for:

  • comments
  • identifiers
  • text in strings

New refactoring - Inefficient String buffering

Example 1

Replace

String s = "";
for (Var v...) {
    s += v.some + v.thing;
return s;

with

StringBuilder s = new StringBuilder();
for (Var v...) {
    s.append(v.some).append(v.thing);
return s.toString();

Example 2

Replace

String s = "init";
for (Var v...) {
    s = s + v.some + v.thing;
return s;

with

StringBuilder s = new StringBuilder("init");
for (Var v...) {
    s.append(v.some).append(v.thing);
return s.toString();

StringBuffer("")

Also replace new StringBuffer("") with new StringBuffer(). Ditto for StringBuilder

New refactoring - Remove reverse expressions

Example 1

Code to refactor:

if (b) {
} else if (!b) {
}

Refactored code:

if (b) {
} else {
}

Example 2

Code to refactor:

if (b) {
} else if (!b && c) {
}

Refactored code:

if (b) {
} else if (c) {
}

Example 3

Code to refactor:

if (b || (!b && c)) {
}

Refactored code:

if (b || c) {
}

Example 4

Code to refactor:

boolean bool = b || (!b && c);

Refactored code:

boolean bool = b || c;

Etc.

New refactoring - turn single exit point into multiple return statement

When methods are short, it is very beneficial to turn single exit point style into return statement. Here is a reference:
http://www.leepoint.net/JavaBasics/methods/method-commentary/methcom-30-multiple-return.html

Refactor this code:

public static double max(double a, double b) {
    double result;    // Stores the maximum value until the return.
    if (a > b) {
        result = a;
    } else {
        result = b;
    }
    return result;
}

To this:

public static double max(double a, double b) {
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

and then to this:

public static double max(double a, double b) {
    if (a > b) {
        return a;
    }
    return b;   // Only executed if comparison was false.
}

New refactoring - remove redundant throw declarations

Given

public void f() throws IOException, NullPointerException, Exception {
    ...
}

When

triggering automatic refactoring

Then

Code is rewritten to:

public void f() throws Exception {
    ...
}

Because Exception is a super type of IOException and NullPointerException.

New refactoring - refactor into a static inner class

Reference:

Given

public class WithInnerClass {
    private class InnerClass {
        int i;
    }

    public void m() {
        InnerClass ic = new InnerClass();
        ic.i = 0;
    }
}

When

calling autorefactor...

Then

Rewrite code to:

public class WithInnerClass {
    private static class InnerClass {
        int i;
    }

    public void m() {
        InnerClass ic = new InnerClass();
        ic.i = 0;
    }
}

New refactoring - Autobox primitives

Example 1

Convert from:

public void compare(int i, int j) {
    Integer ii = new Integer(i);
    Integer jj = Integer.valueOf(j);
    return ii.compareTo(jj);
}

to:

public void compare(int i, int j) {
    Integer ii = i;
    Integer jj = j;
    return ii.compareTo(jj);
}

and then (raise another bug for this one):

public void compare(int i, int j) {
    Integer ii = i;
    return ii.compareTo(j);
}

Variations

The same applies to all primitives and their wrappers.

New refactoring - remove redundant inherited javadocs

Given

A method named M with a javadoc in an interface or class named A
And a method named MM overriding M with the same javadoc, in a sub-interface/class of A named B

When

User triggers auto refactor on B

Then

The javadoc for MM is transformed to a javadoc with

/** {@inheritDoc} */

New refactoring - Meta - Suggest methods that can be extracted

If possible, improve or build on the JDT extract method.

Extract method across type of variables, types, and casts

It would be nice to provide Extract method refactoring across:

  • any kind of expression, just look at the expression type (all can be extracted as parameters),
  • types and supertypes (choose supertype over subtype when more code can be extracted)
  • type casts (you have code that uses ints in one place and longs in other? Then use longs to extract more code)
  • the presence of local variables or inlined code (very useful because of line length limits)
  • etc.

Move statements together

Probably too hard to do, would be to move statements together, but this might require deep inter procedural analysis. Maybe simple arithmetics or boolean expressions that all live in the current method body can be moved like this.

Consecutive lines threshold

Also, if we hit specific thresholds: If more than X (10? 20? 30?) consecutive lines of code are only here to output one variable: then we suggest to extract a method.

Eclipse's JDT Extract Method

See info about Eclipse's JDT Extract Method here:

  • http://wiki.eclipse.org/Extract_method_revival
  • org.eclipse.jdt.ui.extract.method
  • org.eclipse.jdt.ui.actions.ExtractMethodAction
  • org.eclipse.jdt.internal.corext.refactoring.code.ExtractMethodRefactoring
  • org.eclipse.jdt.internal.corext.refactoring.code.ExtractMethodAnalyzer

For development, see:

Example tests with in and out folders:

Code comments are lost

Given

Code to be refactored with embedded comments

When

Automatic refactoring is performed

Then

Actual: Comments are removed
Expected: Comments should be kept the same.

Java AST Search

Using the File Search for refactoring suffer from the limits of regular expressions It would be nice to have a Java AST Search that ignores whitespace, expressions, or group of statements.

For this we need to define a DSL to express expression types, or statements we want to ignore, etc.

Here are a few examples of possible syntax:

  • if (EXPR<boolean>) { STMT+ } any boolean expression in the if condition will match, and one or more statements in the body of the loop will match.
  • if (EXPR) { STMT+ } same, but no type specified for the expression (even though nothing else than boolean can exist here).
  • if (IDENT != null) { try { IDENT.close(); } catch (TYPE IDENT) { STMT* } } this must reuse be the same identifier, how to convey it? The type of the identifier must be java.io.Closeable. How to convey it?
    ** if (IDENT1 != null) { try { IDENT1.close(); } catch (TYPE IDENT2) { STMT* } }
    ** if (EXPR1<java.io.Closeable> != null) { try { EXPR1.close(); } catch (TYPE IDENT) { STMT* } }to convey it?

Difficulties:

  • See some of the difficulties pointed above
  • How to reconcile regular expressions like operators (*, +) with Java language operators?
  • It must be usable from a limited TextField

See:

New refactoring - Convert uses of compareTo() to equals()

When "the natural ordering for a class is consistent with equals" as defined in java.lang.Comparable, then we can replace such code:

boolean b1 = obj1.compareTo(obj2) == 0;
boolean b2 = obj1.compareTo(obj2) != 0;

with:

boolean b1 = obj1.equals(obj2);
boolean b2 = !obj1.equals(obj2);

Such natural ordering is valid with all the java primitive wrappers, java.lang.String, java.math.BigInteger, java.util.Date, etc. (Test all the classes listed in java.lang.Comparable's javadoc).

New refactoring - convert line and block comments to javadocs

Convert line and block comments to javadocs if they are situated before a field, method, constructor or type declaration.
Code would need to ensure the comment ends with a period, that all parameters, return and throw are covered, and that it respects the configured style (line length, indentation).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.