ProRefactor can be used as a standalone library, entirely independently of Eclipse.
This Java archive (jar) file contains ProRefactor, as well as the third party libraries it requires.
prorefactor.oehive.org/prorefactor.jar
Last updated: June 17, 2008. About a dozen MB.
export LD_LIBRARY_PATH=.
ProRefactor.jar always requires the latest release of Proparse.
This section assumes you will be using Groovy for scripting, but other JVM scripting languages will be similar.
groovy --version
export CLASSPATH=prorefactor.jar
assuming prorefactor.jar is in the working directory. (If you need additional jar files, don't forget on unix, use ':' instead of ';' to separate classpath entries.)
Using the standalone jar file, you can launch a command line console which contains one or two examples of how you can use the ProRefactor libraries. The console (org.prorefactor.Console) is the default class for the standalone jar file, so you can launch it simply with:
java -jar prorefactor.jar
Here's what its menu looks like as of Jan 2007:
h) How-used report l) Load Settings for a project p) Parse a directory q) Quit v) show proparse Version w) Where used report Enter selection:
Showing the Proparse version is useful for checking that the Proparse shared library can be found and loaded OK. The parse a directory option is useful for checking that your ProRefactor project settings are correct, and that ProRefactor can parse your application OK.
In prorefactor/projects/projectname/pubs in your working directory, ProRefactor writes out a parse unit binary (PUB) file for each compile unit in your application. These will be built as needed, when you do a parse or run a report.
These PUB files contain the full syntax tree and some additional information, so that your programs do not need to be re-parsed each time ProRefactor wants to get information about them. The *.pub files can be thought of a bit like your *.r files.
Here's the important bit: These files contain a fair amount of information, and will probably require more disc space than your .r files. In fact, for a very large enterprise application, the PUB files might require as much as a few gigabytes of disc space.
This is not the most efficient way to find where a database field is used, but it is a useful example of using ProRefactor.
See this WebSVN link for the full source.
It prompts for a fully qualified db.table.field name, checks that it exists in ProRefactor's configured schema, and splits it into two string variables: fieldName, and dbTableName.
It then finds all parse units in the directory of your choice, and loads or builds the PUB file for each of those, and then checks to see if your field is used in that compile unit. So, for each parse unit pu:
PUB pub = pu.getPUB(); boolean wasCurrent = pub.loadTo(PUB.SCHEMA); if (wasCurrent==false) pub.build(); if (usesField(pub) == false) return; reportOut.write(pu.getFile().toString());
Next is the relevant code for usesField(). The PUB object has a record of all tables and fields used in that compile unit. We get a copy of the list of fields of the table that were used in the PUB, then check if it contains the name of the field we are interested in.
pub.copySchemaFieldLowercaseNamesInto(fieldNames, dbTableName); return fieldNames.contains(fieldName);
This report shows a snippet from each line of code where a database field is used. For example, a how-used report for sports2000.customer.custnum might show:
s2k\gui\bcust.w define temp-table ... like Customer.CustNum validate s2k\gui\dcust.w define temp-table ... like Customer.CustNum validate s2k\gui\dcust_cl.w define temp-table ... like Customer.CustNum validate s2k\gui\orderreport.p format ... Customer.CustNum column-label "Cust-Num" format ">>>>9" display ... Customer.CustNum s2k\gui\vcust.w define temp-table ... like Customer.CustNum validate s2k\gui\vcust2.w define temp-table ... like Customer.CustNum validate s2k\gui\vordlne2.w find ... customer.custnum eq order.custnum find ... customer.custnum eq order.custnum s2k\gui\worder.w define variable ... like customer.custnum
See this WebSVN link for the full source.
This report takes a ProRefactor Field
object (reportField
) as a parameter, and then walks the syntax tree for each parse unit passed to it, starting at the topmost JPNode
node in the tree. It checks to see if each node is a FieldRefNode
referencing the reportField
we are interested in:
private void walkTree(JPNode node) throws Exception { if (node==null) return; boolean match = false; if (node instanceof FieldRefNode) { Symbol symbol = node.getSymbol(); if ( symbol!=null && symbol instanceof FieldBuffer && ((FieldBuffer)symbol).getField() == reportField ) match = true; } if (match) { printReference(node); } else { walkTree(node.firstChild()); } walkTree(node.nextSibling()); }
In printReference()
, the beginning of the statement is found, and the first one node or two (DISPLAY, ASSIGN, etc.) is displayed, followed by the ellipses "...". The parent of the FieldRefNode
is then found, and everything below it is then printed (including, of course, the FieldRefNode itself).
If you are new to syntax trees, then you might want to have a look at joanju.com/dist/docs/parse_trees to get an idea why print2()
has to take an extra step to make sure that binary operators are printed in line.