import java.util.Stack; import java.util.Vector; import com.ibm.jdt.compiler.api.*; import com.ibm.jdt.formatter.api.*; /** *
This formatter calls the default IBM formatter and then * takes its output and reprocesses it to make each open brace * line up column-wise with its matching end brace. This is to * undo the new "feature" in the VAJ 3.5.3 code formatter that * moved the open brace in by an extra indentation factor. * *
DISCLAIMER
* *This Java code is provided to you on an 'as-is' basis * without warranty or condition of any kind, either express or * implied, including, but not limited to, warranty or condition of * merchantable quality or fitness for a particular purpose.
* *Copyright (c) 2001, IBM and Kenton Lynne * All Rights Reserved
* * @author Kenton Lynne * @version 1.0.2 - fixes for parsing code correctly */ public class MyFixForIBMCodeFormatter { static public Vector matchedBraces = new Vector(); /** * Adds a Braces object to the matchedBraces Vector passed such that * the Vector is ordered by open brace position * Creation date: (06/06/01 3:48:01 PM) */ static public void addBraces(int openPos, int closePos) { // create a two-element array to hold the values int[] braces = new int[2]; braces[0] = openPos; braces[1] = closePos; // insert this into the matchedBraces Vector ordered by openPos int i; for (i = 0; i < matchedBraces.size(); i++) { try { if (((int[]) matchedBraces.elementAt(i))[0] > openPos) { break; // done! insert at position i } } catch (ArrayIndexOutOfBoundsException e) // in case Vector is empty { break; //done! insert at position i (should be 0) } } // i should now contain the position to insert this Braces element in the Vector matchedBraces.insertElementAt(braces, i); } /** * Count the number of whitespace characters before the character pointed at by * index within the input string * Creation date: (06/07/01 9:03:31 AM) * @return int */ static public int countSpaces(String stg, int index) { int count = 0; while (index >= 0 && (stg.charAt(index - 1) == ' ' || stg.charAt(index - 1) == '\t')) { count++; index--; } return count; } /** * Searches the input string for open and closed braces * and builds in matchedBraces Vector a sorted list of * Braces objects that contain pointers to the matched * braces within that code segment. * Braces that appear within comments or quoted strings are ignored * Creation date: (06/06/01 3:30:11 PM) * @return void * @param param java.lang.String */ static public void findBraces(String s) { Stack openBraces = new Stack(); int state = 0; // state machine: // 0: not in a comment // 1: possible start of comment ('/' found) // 2: within a line comment ('//' found) // 3: within a block comment ('/*' found) // 4: possible end of block comment ('*' found) // 5: within a single-quoted string // 7: within a double-quoted string // 6: within a single-quoted string ('\' found) // 8: within a double-quoted string ('\' found) // run a state machine to find all the braces that aren't within in comments for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); switch (state) { //////////////////////////////// case 0 : // not within a comment if (ch == '/') // start of comment? { state = 1; } else if (ch == '\'') // single quoted string { state = 5; } else if (ch == '\"') // double-quoted string { state = 7; } else if (ch == '{') // stack the open brace position { openBraces.push(new Integer(i)); } else if (ch == '}') // match with open brace on top of stack { addBraces(((Integer) openBraces.pop()).intValue(), i); } break; ///////////////////////////////// case 1 : // possible start of comment if (ch == '/') // line comment { state = 2; } else if (ch == '*') // block comment { state = 3; } else // not a comment { state = 0; } break; ///////////////////////////////// case 2 : // within a line comment if (ch == '\n') // end of comment { state = 0; } break; //////////////////////////////// case 3 : // within a block comment if (ch == '*') // possible end of comment { state = 4; } else // not end of comment { state = 2; } break; //////////////////////////////// case 4 : // possible end of block comment if (ch == '/') // end of block comment { state = 0; } else if (ch == '*') // still possible end of comment { // stay in same state } else // back inside of block comment { state = 3; } break; /////////////////////////////// case 5 : // within a single-quoted string - previous char was NOT an escape char if (ch == '\'') // end of string { state = 0; } else if (ch == '\\') // escape char within quoted string { state = 6; } break; /////////////////////////////// case 6 : // within a single-quoted string - previous char was an escape char // doesn't matter what character follows the escape character - still within quoted string state = 5; break; /////////////////////////////// case 7 : // within a double-quoted string - previous char was NOT an escape char if (ch == '\"') // end of string { state = 0; } else if (ch == '\\') // escape char within quoted string { state = 8; } break; /////////////////////////////// case 8 : // within a double-quoted string - previous char was an escape char // doesn't matter what character follows the escape character - still within quoted string state = 7; break; /////////////////////////////// } // end of switch } // end of for loop } /**This method performs the formatting. It's called for * all formatting inside VisualAge when control-w (or * whatever key you assign) is pressed in the editor. This applies * for class definitions or method definitions. There is no way * to tell the difference between a call to format a class definition * or a method definition.
* *Depending on the VA Assist/J settings, this may also be called * when importing, exporting, or viewing the entire class source.
* *This sample version of the format method calls the default * VisualAge formatter and adds a comment at the top of the code. * The comment contains a list of all options passed to the * formatter from VisualAge. If you want to use the IBM * formatting options, this is an example of how to get them.
* * @param code (java.lang.String)int)com.ibm.jdt.compiler.api.ConfigurableOption[])java.lang.String)System.getProperty("line.separator")