7

I'm trying to do a structural replacement for my project. I have a package with 100+ classes, each with 1-20 fields. Our project is migrating to Hungarian notation, which means all private fields have to be prefixed with m.

I know IntelliJ can add prefixes for new fields, but I don't know the recipe for doing a batch Refactor->Rename for all fields.

Regex doesn't work because said fields are used through the application in all kind of contexts, method calls, assignations, arithmetical ops...

What would be the best approach that's not manual?

MLProgrammer-CiM
  • 17,231
  • 5
  • 42
  • 75
  • You could write a program to do it... – brso05 Mar 30 '16 at 12:23
  • 17
    I've seen a lot of time waste in projects, but moving *to* hungarian notation is probably the winner. – Kayaman Mar 30 '16 at 12:29
  • 4
    Waste of time? I'd call it worse than that! http://www.javaranch.com/styleLong.jsp#hungarian, http://stackoverflow.com/questions/111933/why-shouldnt-i-use-hungarian-notation, etcetera. – Stephen C Mar 30 '16 at 12:40
  • 1
    @brso05 - Yea ... a big hairy, complicated program. – Stephen C Mar 30 '16 at 12:41
  • I don't think Intellij can do it out of the box since refactoring is usually localized. Unless you really don't want to write a code to do this, the only way I can think of is ugly: using Structural Search, search for `all fields of the class`. This should return every field you have on your project and from here you either try to use a macro to do the refactoring (which I am not sure will work with dialogs) or use some keyboard macros to insert a combination of keystrokes representing the shortcuts required to do that for you. – dambros Mar 30 '16 at 13:38
  • If you really want to do that. Have a look at [JavaParser](http://javaparser.github.io/javaparser/) which provides a modifiable AST of your source files. – SubOptimal Mar 30 '16 at 13:44
  • Personally, I agree with many of the other comments (that this is probably a bad idea), but sometimes we have to do what we're told. I think it's a valid question, and don't understand the downvotes. – Mike Harris Mar 30 '16 at 14:07
  • 1
    I agree too but it's not my choice. – MLProgrammer-CiM Mar 30 '16 at 14:13
  • 1
    So you don't think regexes will help you, but you added regex tag... – ndnenkov Apr 04 '16 at 20:26
  • Settings | Code Style | Java | Code Generation --> Name Prefix may be a place to start. – Laurel Apr 05 '16 at 21:53
  • Yep, that does it for new fields, but not for the old ones. – MLProgrammer-CiM Apr 05 '16 at 22:40
  • Hungarian notation? in Java?! in 2016?!?! – Matthew Mark Miller Apr 07 '16 at 01:48

3 Answers3

1

Based on answers to similar questions (here, here and here) I guess you can use javaparser and create a small utility to do the refactor for you.

Here is something to get you started:

import japa.parser.JavaParser;
import japa.parser.ParseException;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.body.FieldDeclaration;
import japa.parser.ast.body.VariableDeclaratorId;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class HungarianNotationRefactor {

    public static void main(String[] args) throws IOException, ParseException {
        File file = new File(args[0]);

        CompilationUnit cu;
        cu = JavaParser.parse(file);

        // get all types in file
        cu.getTypes()
                .stream()

                // get all members
                .flatMap(type -> type.getMembers().stream())

                // filter only fields
                .filter(member -> member instanceof FieldDeclaration)
                .map(member -> (FieldDeclaration) member)

                // get all variables and rename
                .flatMap(field -> field.getVariables().stream())
                .forEach(var -> var.setId(new VariableDeclaratorId("m_" + var.getId())));

        try (FileWriter out = new FileWriter(file)) {
            out.append(cu.toString());
        }
        System.out.println(cu.toString());
    }
}

This will rename fields but not this.field occurrences (but it's a start).

Community
  • 1
  • 1
Yoav Aharoni
  • 2,672
  • 13
  • 18
  • That renames the fields, but not the occurrences through the code. Structural search in IntelliJ does that even more trivially. – MLProgrammer-CiM Apr 05 '16 at 22:39
  • @MLProgrammer-CiM `Structural Search and Replace` is an **awesome** tool, but I didn't manage to get it done with it... (perhaps you can give it a go?) – Yoav Aharoni Apr 06 '16 at 02:55
0

Eclipse provides a JDT toolkit which allows java source code manipulation and also provides a LTK toolkit to automate refactoring. Have used JDT extensively and is natural(easy) to use, can assume LTK too is. https://eclipse.org/articles/Article-LTK/ltk.html More information on LTK is available on Eclipse's website.

Can't speak to IntelliJ's automate refactoring capabilities.

tmokha
  • 85
  • 6
-1

It's not a full answer, but an idea:

  1. Write an inspection that finds non-Hungarian field names.
    You can use a regex most likely including (?<! (negative look-behind), or just plain !startsWith. Note that this would also come in handy in the future to notify devs on the project that they're naming it "wrong".
  2. Make that inspection have a quick fix
    It should be fairly simple to implement a name transformation for basic types, as I'm guessing you have a guide on how to name them. e.g. String name -> szName
  3. Analyze > Run Inspection by name...
  4. Run fix for all occurrences from Inspection view.

Sadly I do not know how to write IDEA plugins or inspections, but I wanted to share the idea. After a quick search in the IDEA code, I guess these would be good candidates for starting out from:

TWiStErRob
  • 44,762
  • 26
  • 170
  • 254