<s> package org . eclipse . jdt . internal . core . dom . rewrite ; import java . util . ArrayList ; import java . util . Collection ; import java . util . HashMap ; import java . util . Map ; import org . eclipse . core . runtime . Assert ; import org . eclipse . jdt . core . JavaCore ; import org . eclipse . jdt . core . ToolFactory ; import org . eclipse . jdt . core . dom . ASTNode ; import org . eclipse . jdt . core . dom . Annotation ; import org . eclipse . jdt . core . dom . Block ; import org . eclipse . jdt . core . dom . BodyDeclaration ; import org . eclipse . jdt . core . dom . Expression ; import org . eclipse . jdt . core . dom . Statement ; import org . eclipse . jdt . core . formatter . CodeFormatter ; import org . eclipse . jdt . core . formatter . DefaultCodeFormatterConstants ; import org . eclipse . jdt . core . formatter . IndentManipulation ; import org . eclipse . jface . text . BadLocationException ; import org . eclipse . jface . text . BadPositionCategoryException ; import org . eclipse . jface . text . DefaultPositionUpdater ; import org . eclipse . jface . text . Document ; import org . eclipse . jface . text . Position ; import org . eclipse . text . edits . DeleteEdit ; import org . eclipse . text . edits . InsertEdit ; import org . eclipse . text . edits . MultiTextEdit ; import org . eclipse . text . edits . ReplaceEdit ; import org . eclipse . text . edits . TextEdit ; final class ASTRewriteFormatter { public static class NodeMarker extends Position { public Object data ; } private class ExtendedFlattener extends ASTRewriteFlattener { private ArrayList positions ; public ExtendedFlattener ( RewriteEventStore store ) { super ( store ) ; this . positions = new ArrayList ( ) ; } public void preVisit ( ASTNode node ) { Object trackData = getEventStore ( ) . getTrackedNodeData ( node ) ; if ( trackData != null ) { addMarker ( trackData , this . result . length ( ) , 0 ) ; } Object placeholderData = getPlaceholders ( ) . getPlaceholderData ( node ) ; if ( placeholderData != null ) { addMarker ( placeholderData , this . result . length ( ) , 0 ) ; } } public void postVisit ( ASTNode node ) { Object placeholderData = getPlaceholders ( ) . getPlaceholderData ( node ) ; if ( placeholderData != null ) { fixupLength ( placeholderData , this . result . length ( ) ) ; } Object trackData = getEventStore ( ) . getTrackedNodeData ( node ) ; if ( trackData != null ) { fixupLength ( trackData , this . result . length ( ) ) ; } } public boolean visit ( Block node ) { if ( getPlaceholders ( ) . isCollapsed ( node ) ) { visitList ( node , Block . STATEMENTS_PROPERTY , null ) ; return false ; } return super . visit ( node ) ; } private NodeMarker addMarker ( Object annotation , int startOffset , int length ) { NodeMarker marker = new NodeMarker ( ) ; marker . offset = startOffset ; marker . length = length ; marker . data = annotation ; this . positions . add ( marker ) ; return marker ; } private void fixupLength ( Object data , int endOffset ) { for ( int i = this . positions . size ( ) - 1 ; i >= 0 ; i -- ) { NodeMarker marker = ( NodeMarker ) this . positions . get ( i ) ; if ( marker . data == data ) { marker . length = endOffset - marker . offset ; return ; } } } public NodeMarker [ ] getMarkers ( ) { return ( NodeMarker [ ] ) this . positions . toArray ( new NodeMarker [ this . positions . size ( ) ] ) ; } } private final String lineDelimiter ; private final int tabWidth ; private final int indentWidth ; private final NodeInfoStore placeholders ; private final RewriteEventStore eventStore ; private final Map options ; public ASTRewriteFormatter ( NodeInfoStore placeholders , RewriteEventStore eventStore , Map options , String lineDelimiter ) { this . placeholders = placeholders ; this . eventStore = eventStore ; this . options = options == null ? JavaCore . getOptions ( ) : ( Map ) new HashMap ( options ) ; this . options . put ( DefaultCodeFormatterConstants . FORMATTER_ALIGNMENT_FOR_RESOURCES_IN_TRY , DefaultCodeFormatterConstants . createAlignmentValue ( true , DefaultCodeFormatterConstants . WRAP_NEXT_PER_LINE , DefaultCodeFormatterConstants . INDENT_DEFAULT ) ) ; this . lineDelimiter = lineDelimiter ; this . tabWidth = IndentManipulation . getTabWidth ( options ) ; this . indentWidth = IndentManipulation . getIndentWidth ( options ) ; } public NodeInfoStore getPlaceholders ( ) { return this . placeholders ; } public RewriteEventStore getEventStore ( ) { return this . eventStore ; } public int getTabWidth ( ) { return this . tabWidth ; } public int getIndentWidth ( ) { return this . indentWidth ; } public String getLineDelimiter ( ) { return this . lineDelimiter ; } public String getFormattedResult ( ASTNode node , int initialIndentationLevel , Collection resultingMarkers ) { ExtendedFlattener flattener = new ExtendedFlattener ( this . eventStore ) ; node . accept ( flattener ) ; NodeMarker [ ] markers = flattener . getMarkers ( ) ; for ( int i = 0 ; i < markers . length ; i ++ ) { resultingMarkers . add ( markers [ i ] ) ; } String unformatted = flattener . getResult ( ) ; TextEdit edit = formatNode ( node , unformatted , initialIndentationLevel ) ; if ( edit == null ) { if ( initialIndentationLevel > 0 ) { String indentString = createIndentString ( initialIndentationLevel ) ; ReplaceEdit [ ] edits = IndentManipulation . getChangeIndentEdits ( unformatted , 0 , this . tabWidth , this . indentWidth , indentString ) ; edit = new MultiTextEdit ( ) ; edit . addChild ( new InsertEdit ( 0 , indentString ) ) ; edit . addChildren ( edits ) ; } else { return unformatted ; } } return evaluateFormatterEdit ( unformatted , edit , markers ) ; } public String createIndentString ( int indentationUnits ) { return ToolFactory . createCodeFormatter ( this . options ) . createIndentationString ( indentationUnits ) ; } public String getIndentString ( String currentLine ) { return IndentManipulation . extractIndentString ( currentLine , this . tabWidth , this . indentWidth ) ; } public String changeIndent ( String code , int codeIndentLevel , String newIndent ) { return IndentManipulation . changeIndent ( code , codeIndentLevel , this . tabWidth , this . indentWidth , newIndent , this . lineDelimiter ) ; } public int computeIndentUnits ( String line ) { return IndentManipulation . measureIndentUnits ( line , this . tabWidth , this . indentWidth ) ; } public static String evaluateFormatterEdit ( String string , TextEdit edit , Position [ ] positions ) { try { Document doc = createDocument ( string , positions ) ; edit . apply ( doc , 0 ) ; if ( positions != null ) { for ( int i = 0 ; i < positions . length ; i ++ ) { Assert . isTrue ( ! positions [ i ] . isDeleted , "" ) ; } } return doc . get ( ) ; } catch ( BadLocationException e ) { Assert . isTrue ( false , "" + e . getMessage ( ) ) ; } return null ; } public TextEdit formatString ( int kind , String string , int offset , int length , int indentationLevel ) { return ToolFactory . createCodeFormatter ( this . options ) . format ( kind , string , offset , length , indentationLevel , this . lineDelimiter ) ; } private TextEdit formatNode ( ASTNode node , String str , int indentationLevel ) { int code ; String prefix = "" ; String suffix = "" ; if ( node instanceof Statement ) { code = CodeFormatter . K_STATEMENTS ; if ( node . getNodeType ( ) == ASTNode . SWITCH_CASE ) { prefix = "switch(1) {" ; suffix = "}" ; code = CodeFormatter . K_STATEMENTS ; } } else if ( node instanceof Expression && node . getNodeType ( ) != ASTNode . VARIABLE_DECLARATION_EXPRESSION ) { if ( node instanceof Annotation ) { suffix = "nclass A {}" ; code = CodeFormatter . K_COMPILATION_UNIT ; } else { code = CodeFormatter . K_EXPRESSION ; } } else if ( node instanceof BodyDeclaration ) { code = CodeFormatter . K_CLASS_BODY_DECLARATIONS ; } else { switch ( node . getNodeType ( ) ) { case ASTNode . ARRAY_TYPE : case ASTNode . PARAMETERIZED_TYPE : case ASTNode . PRIMITIVE_TYPE : case ASTNode . QUALIFIED_TYPE : case ASTNode . SIMPLE_TYPE : suffix = " x;" ; code = CodeFormatter . K_CLASS_BODY_DECLARATIONS ; break ; case ASTNode . WILDCARD_TYPE : prefix = "A<" ; suffix = "> x;" ; code = CodeFormatter . K_CLASS_BODY_DECLARATIONS ; break ; case ASTNode . COMPILATION_UNIT : code = CodeFormatter . K_COMPILATION_UNIT ; break ; case ASTNode . VARIABLE_DECLARATION_EXPRESSION : case ASTNode . SINGLE_VARIABLE_DECLARATION : suffix = ";" ; code = CodeFormatter . K_STATEMENTS ; break ; case ASTNode . VARIABLE_DECLARATION_FRAGMENT : prefix = "A " ; suffix = ";" ; code = CodeFormatter . K_STATEMENTS ; break ; case ASTNode . PACKAGE_DECLARATION : case ASTNode . IMPORT_DECLARATION : suffix = "nclass A {}" ; code = CodeFormatter . K_COMPILATION_UNIT ; break ; case ASTNode . JAVADOC : suffix = "nclass A {}" ; code = CodeFormatter . K_COMPILATION_UNIT ; break ; case ASTNode . CATCH_CLAUSE : prefix = "try {}" ; code = CodeFormatter . K_STATEMENTS ; break ; case ASTNode . ANONYMOUS_CLASS_DECLARATION : prefix = "new A()" ; suffix = ";" ; code = CodeFormatter . K_STATEMENTS ; break ; case ASTNode . MEMBER_VALUE_PAIR : prefix = "@Author(" ; suffix = ") class x {}" ; code = CodeFormatter . K_COMPILATION_UNIT ; break ; case ASTNode . MODIFIER : suffix = " class x {}" ; code = CodeFormatter . K_COMPILATION_UNIT ; break ; case ASTNode . TYPE_PARAMETER : prefix = "class X<" ; suffix = "> {}" ; code = CodeFormatter . K_COMPILATION_UNIT ; break ; case ASTNode . MEMBER_REF : case ASTNode . METHOD_REF : case ASTNode . METHOD_REF_PARAMETER : case ASTNode . TAG_ELEMENT : case ASTNode . TEXT_ELEMENT : return null ; default : return null ; } } String concatStr = prefix + str + suffix ; TextEdit edit = formatString ( code , concatStr , prefix . length ( ) , str . length ( ) , indentationLevel ) ; if ( prefix . length ( ) > 0 ) { edit = shifEdit ( edit , prefix . length ( ) ) ; } return edit ; } private static TextEdit shifEdit ( TextEdit oldEdit , int diff ) { TextEdit newEdit ; if ( oldEdit instanceof ReplaceEdit ) { ReplaceEdit edit = ( ReplaceEdit ) oldEdit ; newEdit = new ReplaceEdit ( edit . getOffset ( ) - diff , edit . getLength ( ) , edit . getText ( ) ) ; } else if ( oldEdit instanceof InsertEdit ) { InsertEdit edit = ( InsertEdit ) oldEdit ; newEdit = new InsertEdit ( edit . getOffset ( ) - diff , edit . getText ( ) ) ; } else if ( oldEdit instanceof DeleteEdit ) { DeleteEdit edit = ( DeleteEdit ) oldEdit ; newEdit = new DeleteEdit ( edit . getOffset ( ) - diff , edit . getLength ( ) ) ; } else if ( oldEdit instanceof MultiTextEdit ) { newEdit = new MultiTextEdit ( ) ; } else { return null ; } TextEdit [ ] children = oldEdit . getChildren ( ) ; for ( int i = 0 ; i < children . length ; i ++ ) { TextEdit shifted = shifEdit ( children [ i ] , diff ) ; if ( shifted != null ) { newEdit . addChild ( shifted ) ; } } return newEdit ; } private static Document createDocument ( String string , Position [ ] positions ) throws IllegalArgumentException { Document doc = new Document ( string ) ; try { if ( positions != null ) { final String POS_CATEGORY = "myCategory" ; doc . addPositionCategory ( POS_CATEGORY ) ; doc . addPositionUpdater ( new DefaultPositionUpdater ( POS_CATEGORY ) { protected boolean notDeleted ( ) { int start = this . fOffset ; int end = start + this . fLength ; if ( start < this . fPosition . offset && ( this . fPosition . offset + this . fPosition . length < end ) ) { this . fPosition . offset = end ; return false ; } return true ; } } ) ; for ( int i = 0 ; i < positions . length ; i ++ ) { try { doc . addPosition ( POS_CATEGORY , positions [ i ] ) ; } catch ( BadLocationException e ) { throw new IllegalArgumentException ( "" + positions [ i ] . offset + ", length: " + positions [ i ] . length + "" + string . length ( ) ) ; } } } } catch ( BadPositionCategoryException cannotHappen ) { } return doc ; } public static interface Prefix { String getPrefix ( int indent ) ; } public static interface BlockContext { String [ ] getPrefixAndSuffix ( int indent , ASTNode node , RewriteEventStore events ) ; } public static class ConstPrefix implements Prefix { private String prefix ; public ConstPrefix ( String prefix ) { this . prefix = prefix ; } public String getPrefix ( int indent ) { return this . prefix ; } } private class FormattingPrefix implements Prefix { private int kind ; private String string ; private int start ; private int length ; public FormattingPrefix ( String string , String sub , int kind ) { this . start = string . indexOf ( sub ) ; this . length = sub . length ( ) ; this . string = string ; this . kind = kind ; } public String getPrefix ( int indent ) { Position pos = new Position ( this . start , this . length ) ; String str = this . string ; TextEdit res = formatString ( this . kind , str , 0 , str . length ( ) , indent ) ; if ( res != null ) { str = evaluateFormatterEdit ( str , res , new Position [ ] { pos } ) ; } return str . substring ( pos . offset + 1 , pos . offset + pos . length - 1 ) ; } } private class BlockFormattingPrefix implements BlockContext { private String prefix ; private int start ; public BlockFormattingPrefix ( String prefix , int start ) { this . start = start ; this . prefix = prefix ; } public String [ ] getPrefixAndSuffix ( int indent , ASTNode node , RewriteEventStore events ) { String nodeString = ASTRewriteFlattener . asString ( node , events ) ; String str = this . prefix + nodeString ; Position pos = new Position ( this . start , this . prefix . length ( ) + 1 - this . start ) ; TextEdit res = formatString ( CodeFormatter . K_STATEMENTS , str , 0 , str . length ( ) , indent ) ; if ( res != null ) { str = evaluateFormatterEdit ( str , res , new Position [ ] { pos } ) ; } return new String [ ] { str . substring ( pos . offset + 1 , pos . offset + pos . length - 1 ) , "" } ; } } private class BlockFormattingPrefixSuffix implements BlockContext { private String prefix ; private String suffix ; private int start ; public BlockFormattingPrefixSuffix ( String prefix , String suffix , int start ) { this . start = start ; this . suffix = suffix ; this . prefix = prefix ; } public String [ ] getPrefixAndSuffix ( int indent , ASTNode node , RewriteEventStore events ) { String nodeString = ASTRewriteFlattener . asString ( node , events ) ; int nodeStart = this . prefix . length ( ) ; int nodeEnd = nodeStart + nodeString . length ( ) - 1 ; String str = this . prefix + nodeString + this . suffix ; Position pos1 = new Position ( this . start , nodeStart + 1 - this . start ) ; Position pos2 = new Position ( nodeEnd , 2 ) ; TextEdit res = formatString ( CodeFormatter . K_STATEMENTS , str , 0 , str . length ( ) , indent ) ; if ( res != null ) { str = evaluateFormatterEdit ( str , res , new Position [ ] { pos1 , pos2 } ) ; } return new String [ ] { str . substring ( pos1 . offset + 1 , pos1 . offset + pos1 . length - 1 ) , str . substring ( pos2 . offset + 1 , pos2 . offset + pos2 . length - 1 ) } ; } } public final static Prefix NONE = new ConstPrefix ( "" ) ; public final static Prefix SPACE = new ConstPrefix ( " " ) ; public final static Prefix ASSERT_COMMENT = new ConstPrefix ( " : " ) ; public final Prefix VAR_INITIALIZER = new FormattingPrefix ( "A a={};" , "a={" , CodeFormatter . K_STATEMENTS ) ; public final Prefix METHOD_BODY = new FormattingPrefix ( "void a() {}" , ") {" , CodeFormatter . K_CLASS_BODY_DECLARATIONS ) ; public final Prefix FINALLY_BLOCK = new FormattingPrefix ( "" , "} finally {" , CodeFormatter . K_STATEMENTS ) ; public final Prefix CATCH_BLOCK = new FormattingPrefix ( "" , "} c" , CodeFormatter . K_STATEMENTS ) ; public final Prefix ANNOT_MEMBER_DEFAULT = new FormattingPrefix ( "" , ") default 1" , CodeFormatter . K_CLASS_BODY_DECLARATIONS ) ; public final Prefix ENUM_BODY_START = new FormattingPrefix ( "" , "){v" , CodeFormatter . K_COMPILATION_UNIT ) ; public final Prefix ENUM_BODY_END = new FormattingPrefix ( "" , "}}," , CodeFormatter . K_COMPILATION_UNIT ) ; public final Prefix WILDCARD_EXTENDS = new FormattingPrefix ( "" , "? extends B" , CodeFormatter . K_CLASS_BODY_DECLARATIONS ) ; public final Prefix WILDCARD_SUPER = new FormattingPrefix ( "" , "? super B" , CodeFormatter . K_CLASS_BODY_DECLARATIONS ) ; public final Prefix FIRST_ENUM_CONST = new FormattingPrefix ( "enum E { X;}" , "{ X" , CodeFormatter . K_COMPILATION_UNIT ) ; public final Prefix ANNOTATION_SEPARATION = new FormattingPrefix ( "" , "A @" , CodeFormatter . K_COMPILATION_UNIT ) ; public final Prefix PARAM_ANNOTATION_SEPARATION = new FormattingPrefix ( "" , "A @" , CodeFormatter . K_CLASS_BODY_DECLARATIONS ) ; public final Prefix TRY_RESOURCES = new FormattingPrefix ( "" , "; B" , CodeFormatter . K_STATEMENTS ) ; public final Prefix TRY_RESOURCES_PAREN = new FormattingPrefix ( "" , "y (" , CodeFormatter . K_STATEMENTS ) ; public final BlockContext IF_BLOCK_WITH_ELSE = new BlockFormattingPrefixSuffix ( "if (true)" , "else{}" , 8 ) ; public final BlockContext IF_BLOCK_NO_ELSE = new BlockFormattingPrefix ( "if (true)" , 8 ) ; public final BlockContext ELSE_AFTER_STATEMENT = new BlockFormattingPrefix ( "" , 15 ) ; public final BlockContext ELSE_AFTER_BLOCK = new BlockFormattingPrefix ( "" , 11 ) ; public final BlockContext FOR_BLOCK = new BlockFormattingPrefix ( "for (;;) " , 7 ) ; public final BlockContext WHILE_BLOCK = new BlockFormattingPrefix ( "while (true)" , 11 ) ; public final BlockContext DO_BLOCK = new BlockFormattingPrefixSuffix ( "do " , "" , 1 ) ; } </s>