Refactor example using the new API?

Are there any examples of a refactor using the new pure Java interface? It looks like all the test cases that do refactoring are commented out, and the Javadoc at http://www.oehive.org/node/1514 is too mixed between the old and new APIs for me to be clear on how to do it.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
john's picture

Re: Refactor example using the new API?

Hi Kevin,
I can probably put together a recent example of automated code change for you this weekend if you like. Just let me know.
You are right, the old refactorings I had in ProRefactor have been stripped out of Proparse. They were too complicated, and they used an obscure Proparse feature that I dropped when I ported Proparse from C++ to Java. My more recent tools for automated code changes are simpler. I still have code cleanup to do, like those test cases you found.
In the past two or three years, all the automated code change tools I've built have been scripts written in Groovy (a JVM language). But if you prefer to work with OE 10.2 on Windows, those scripts could reasonably be re-written in ABL using the .Net build of Proparse.
Regards,
John


I'm fine with examples

I'm fine with examples directly in Groovy, it is close enough to Java to be easy for me to translate. If you can get something together this weekend that would be wonderful, as I'm a couple days behind my original estimate which was based on seeing the API docs that are still around from the old version.

I'm actually more comfortable with Java or C# than ABL. Our vendor forces us to write reports using ABL, which is the code I need to refactor to explicitly reference database names, but I'm not comfortable with calling .NET code from ABL and not even sure we have the license to do so.

I might even contribute a patch that gets org.prorefactor.refactor.unittest.NamesT and PUBTest to pass, if I do manage to get that working.


john's picture

OK great, it's on my weekend

OK great, it's on my weekend to-do list!


john's picture

InsertField

Hi Kevin,

I attached a .zip of a project (InsertField) I did for a client. In that project, we were inserting a field into every table and index. (In OE 11 you'd use multi-tenancy instead.)

This is more complicated than your project. This automated code change had to find every record phrase (FIND, FOR) as well as every CREATE, and insert the appropriate line of code for the new field.

I wrote FileBuffer.groovy for loading a source file into memory, making changes to it, and writing it back out again.

InsertField.groovy is kind of a wrapper, which loops through all of the compile units in the project, parses them, then hands the results of the parse off to InsertFieldUnit.groovy which processes the compile unit.

If you look at the top of InsertField.groovy you'll see:

--- USAGE ---
o  You need to dump your project's schema and propath into
   your working directory "prorefactor/projects/...". See:
   http://www.oehive.org/prorefactor/proj_cfg_dump

o  You'll need proparse.jar and 'scripts' in your CLASSPATH.

o  Configure insertfield.properties in your current working directory.

o  Run the script: groovy scripts/InsertField.groovy
-------------

The other groovy files are small supporting classes, for logging etc.

If there was something like FIND {&1} WHERE {&2} NO-LOCK in the code, then we'd just log it rather than try to automate it. This worked well for our project.

I hope that helps!
Regards,
John


AttachmentSize
insertfields.zip11.82 KB

Summary of how InsertField modifies code

Hi John,

Just to make sure I'm understanding this correctly, would it be safe to say the summary of what this Groovy code does for each source file is:

  1. Parse source file using ParseUnit class.
  2. Loop through all nodes in the resulting AST, testing if they are what we need to modify.
  3. Make a TreeMap of files and nodes within them that need modification.
  4. Load the file into a string array list.
  5. Use the JPNode.line and JPNode.column properties to find the piece of of the string that the node represents.
  6. Make appropriate modifications to the string within the array, keeping newly added lines within the one spot in the array
  7. Write out the entire string array to a new file.

Is it also safe to say that this code breaks in the unlikely, but not checked for, circumstance that multiple modifications are needed to the same source line?

(I've intentionally glossed over the handling of shared include files above.)

Thanks,
Kevin


john's picture

Very well written! That

Very well written!
That describes very well what the code does.

Good question about multiple modifications in the same line. In other conversion projects, I've worked backward from the end of the file. The FileTargets and their conversions which were near the end of the file, or near the end of the line, would be done first. That way if two conversions were done on the same line, the change nearest the end of the line would not mess up the column number for any changes earlier in the line. At a glance, it looks like I didn't do that in this project. It would not have been necessary in this project, but it would have been better practice! Good catch.

Regards,
John


john's picture

compareTo

Oh by the way you might want to see the compareTo method in FileTarget.
http://websvn.oehive.org/filedetails.php?repname=proparse&path=%2Ftrunk%...

       public int compareTo(Object o2) {
             FileTarget that = (FileTarget)o2;
             int ret;
             ret = filename.compareTo(that.filename);
             if (ret!=0) return ret;
             ret = line - that.line;
             if (ret!=0) return ret;
             return column - that.column;
       }