Eclipse plugins 插件开发学习 - IScanner 和 IBuffer 封装的高级应用类

由于 IScanner 和 IBuffer 修改源码比较麻烦,功能也不是很强大,需要编写大量的代码。

所以这里谢了一个辅助类,来改善代码。

package  com.humpic.plugins.helper.utils;

import  java.util.ArrayList;
import  java.util.List;
import  org.apache.commons.lang.StringUtils;
import  org.eclipse.jdt.core. * ;
import  org.eclipse.jdt.core.compiler.IScanner;
import  org.eclipse.jdt.core.compiler.InvalidInputException;

public   class  ObjectScanBuffer {
    
private  Offset offset  =   new  Offset();
    
private  IBuffer buffer;
    
private  IScanner scanner;

    
public  ObjectScanBuffer(IType objectClass) {
        
try  {
            ICompilationUnit cu 
=  objectClass.getCompilationUnit();
            
this .buffer  =  cu.getBuffer();
            
this .scanner  =  ToolFactory.createScanner( false false false false );
            
this .scanner.setSource( this .buffer.getCharacters());
            
//  不扫描 package 和 import 部分
            ISourceRange sr  =  objectClass.getSourceRange();
            
this .scanner.resetTo(sr.getOffset(), sr.getOffset()  +  sr.getLength()  -   1 );
        } 
catch  (JavaModelException e) {
            
throw   new  RuntimeException(e);
        }
    }

    
/**
     * 返回下一个 Token
     
*/
    
public   int  getNextToken()  throws  InvalidInputException {
        
return   this .scanner.getNextToken();
    }

    
/**
     * 查找 Token
     * 
     * 
@param  reset
     *            为 true,那么如果没有找到,则会重置 scan 位置
     
*/
    
public   boolean  findToken( int  token,  boolean  reset)  throws  InvalidInputException {
        
int [] savepoint  =   this .savePoint();
        
int  t  =   this .scanner.getNextToken();
        
while  (t  !=  token) {
            
if  (t  <=   0 )
                
break ;
            t 
=   this .scanner.getNextToken();
        }
        
if  (t  !=  token  &&  reset) {
            
this .resetPoint(savepoint);
        }
        
return  t  ==  token;
    }

    
/**
     * 查找 Token, 如果碰到 stopToken,则停止.
     * 
     * 
@param  reset
     *            为 true,那么如果没有找到,则会重置 scan 位置
     
*/
    
public   boolean  findToken( int  token,  int  stopToken,  boolean  reset)  throws  InvalidInputException {
        
int [] savepoint  =   this .savePoint();
        
int  t  =   this .scanner.getNextToken();
        
while  (t  !=  token) {
            
if  (t  <=   0 )
                
break ;
            
if  (t  ==  stopToken)
                
break ;
            t 
=   this .scanner.getNextToken();
        }
        
if  (t  !=  token  &&  reset) {
            
this .resetPoint(savepoint);
        }
        
return  t  ==  token;
    }

    
/**
     * 查找从 startToken 到 endToken 中间的所有 Tokens
     * 
     * 
@param  reset
     *            为 true,那么如果没有找到,则会重置 scan 位置 (如果 startToken 找到,重置到 startToken)
     * 
@return  new Object[] { new Integer(token), tokenText }
     
*/
    
public  List findTokensBetween( int  startToken,  int  endToken,  boolean  reset)  throws  InvalidInputException {
        List tokens 
=   new  ArrayList();
        
if  ( this .findToken(startToken, reset)) {
            
int [] savepoint  =   this .savePoint();

            
int  t  =   this .scanner.getNextToken();
            
while  (t  !=  endToken) {
                
if  (t  <=   0 )
                    
break ;
                tokens.add(
new  Object[] {  new  Integer(t),  this .getTokenText() });
                t 
=   this .scanner.getNextToken();
            }
            
if  (t  !=  endToken) {
                tokens.clear();
                
if  (reset) {
                    
this .resetPoint(savepoint);
                }
            }
        }
        
return  tokens;
    }

    
/**
     * 在 findTokensBetween 返回中查找 是否存在 token
     
*/
    
public   boolean  existToken(List tokens,  int  token) {
        
for  ( int  i  =   0 ; i  <  tokens.size(); i ++ ) {
            Object[] t 
=  (Object[]) tokens.get(i);
            
if  (((Integer) t[ 0 ]).intValue()  ==  token) {
                
return   true ;
            }
        }
        
return   false ;
    }

    
/**
     * 在 findTokensBetween 返回中查找 是否存在 tokenText
     
*/
    
public   boolean  existToken(List tokens, String tokenText) {
        
for  ( int  i  =   0 ; i  <  tokens.size(); i ++ ) {
            Object[] t 
=  (Object[]) tokens.get(i);
            
if  (StringUtils.equals((String) t[ 1 ], tokenText)) {
                
return   true ;
            }
        }
        
return   false ;
    }

    
/**
     * 返回当前的 Token 文本内容
     
*/
    
public  String getTokenText() {
        
return   new  String( this .scanner.getCurrentTokenSource());
    }

    
/**
     * 返回下一个 Token 文本内容
     
*/
    
public  String getNextTokenText()  throws  InvalidInputException {
        
this .scanner.getNextToken();
        
return   this .getTokenText();
    }

    
/**
     * 当前 Token 前面是否存在 空格,或者回车符
     
*/
    
public   boolean  skipSpaces() {
        
int  pos  =   this .offset.getNewPos( this .scanner.getCurrentTokenStartPosition()  -   1 );
        
if  (pos  <   0 )
            
throw   new  RuntimeException( " 该Token所在的位置已经被删除或者修改过了 " );
        String s 
=   this .buffer.getText(pos,  1 );
        
char  c  =  (s.length()  ==   1   ?  s.charAt( 0 ) :  ' /0' );
        
return  c  ==   '   '   ||  c  ==   ' '   ||  c  ==   ' ' ;
    }

    
/**
     * 用 text 替换 当前的 Token
     
*/
    
public   void  replaceText(String text) {
        
int  pos  =   this .offset.getNewPos( this .scanner.getCurrentTokenStartPosition());
        
if  (pos  <   0 )
            
throw   new  RuntimeException( " 该Token所在的位置已经被删除或者修改过了 " );
        
int  size  =   this .scanner.getCurrentTokenEndPosition()  -   this .scanner.getCurrentTokenStartPosition()  +   1 ;
        
this .buffer.replace(pos, size, text);
        
this .offset.addChange(pos,  0   -  size);
        
this .offset.addChange(pos, text.length());
    }

    
/**
     * 在当前 token 位置添加文本
     
*/
    
public   void  appendText(String text) {
        
this .appendText(text,  0 );
    }

    
/**
     * 在距离当前 token 位置Offset距离的地方添加文本(offset可以为负数)
     
*/
    
public   void  appendText(String text,  int  offset) {
        
int  pos  =   this .offset.getNewPos( this .scanner.getCurrentTokenStartPosition()  +  offset);
        
if  (pos  <   0 )
            
throw   new  RuntimeException( " 该Token所在的位置已经被删除或者修改过了 " );
        
int  size  =   0 ;
        
this .buffer.replace(pos, size, text);
        
this .offset.addChange(pos,  0   -  size);
        
this .offset.addChange(pos, text.length());
    }

    
/**
     * 保存当前位置
     
*/
    
public   int [] savePoint() {
        
return   new   int [] {  this .scanner.getCurrentTokenStartPosition(),  this .scanner.getCurrentTokenEndPosition() };
    }

    
/**
     * 恢复到保存的位置
     
*/
    
public   void  resetPoint( int [] savepoint) {
        
this .scanner.resetTo(savepoint[ 0 ], savepoint[ 1 ]);
    }

    
/**
     * 有2个相同的字符串Buffer,对一个Buffer进行Scan,然后在另外一个Buffer进行修改。
     * 这个类就是将用来Scan的原始Buffer的原始位置,映射到新的被修改过的字符串位置
     
*/
    
private   static   class  Offset {
        
private  List changes  =   new  ArrayList();

        
//  在新的位置修改(newsize < 0 代表删除)
         protected   void  addChange( int  newpos,  int  newsize) {
            
if  (newsize  ==   0 )
                
return ;
            
this .changes.add( new   int [] { newpos, newsize });
            System.out.println(
" changes:  "   +  newpos  +   "   "   +  newsize);
        }

        
//  从老位置计算新位置 (返回 -1 代表已经被删除)
         protected   int  getNewPos( int  oldpos) {
            
int  newpos  =  oldpos;
            
for  ( int  i  =   0 ; i  <   this .changes.size(); i ++ ) {
                
int [] pos  =  ( int [])  this .changes.get(i);
                
if  (newpos  >=  pos[ 0 ]) {
                    
if  (pos[ 1 <   0 ) {
                        
if  (newpos  +  pos[ 1 <  pos[ 0 ]) {
                            
return   - 1 ; //  return pos[0]; ???  //  已经被删除
                        }
                    }
                    newpos 
+=  pos[ 1 ];
                }
            }
            System.out.println(
" pos:  "   +  oldpos  +   "  =>  "   +  newpos);
            
return  newpos;
        }
    }

    
public   static   void  main(String[] args) {
        String s1 
=   " 0123456789012345678901234567890123456789012345678901234567890123456789 " ;
        
//  "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String s2  =  s1;

        Offset offset 
=   new  Offset();
        s2 
=  testReplaceText(offset, s2,  4 5 " @@@ " );
        s2 
=  testAppendText(offset, s2,  10 " %%%%%% " );
        s2 
=  testReplaceText(offset, s2,  14 0 " $$ " );
        s2 
=  testAppendText(offset, s2,  32 " ###### " );
        s2 
=  testReplaceText(offset, s2,  44 3 " ******** " );
        s2 
=  testReplaceText(offset, s2,  24 5 " @@@ " );
        System.out.println(s2);
        System.out.println("result = " + (s2.equals("0123@@@9%%%%%%0123$$4567890123@@@901######234567890123********78901234567890123456789")));
    }

    
private   static  String testReplaceText(Offset offset, String s,  int  start,  int  size, String text) {
        
int  pos  =  offset.getNewPos(start);
        offset.addChange(pos, 
0   -  size);
        offset.addChange(pos, text.length());
        
return  StringUtils.left(s, pos)  +  text  +  StringUtils.right(s, s.length()  -  pos  -  size);
    }

    
private   static  String testAppendText(Offset offset, String s,  int  start, String text) {
        
int  pos  =  offset.getNewPos(start);
        offset.addChange(pos, text.length());
        
return  StringUtils.left(s, pos)  +  text  +  StringUtils.right(s, s.length()  -  pos);
    }
}
 

接下来,我们看一下具体的应用:

描述: 判断一个类是否已经实现 Java.io.Serializable, 如果没有实现,那么加入实现代码

     public   void  generate(Shell parentShell, IType objectClass) {

        System.out.println(
" AddSerializableGenerator " );

        IField existingFields 
=  objectClass.getField( " serialVersionUID " );

        
try  {
            
//  import
            ICompilationUnit cu  =  objectClass.getCompilationUnit();
            cu.createImport(
" java.io.Serializable " null null );

            
//  field
             if  ( ! existingFields.exists()) {
                IJavaElement insertPosition 
=   null ;
                
if  (objectClass.getMethods().length  >   0 )
                    insertPosition 
=  objectClass.getMethods()[ 0 ];
                
if  (objectClass.getFields().length  >   0 )
                    insertPosition 
=  objectClass.getFields()[ 0 ];

                String formattedContent 
=   " private static final long serialVersionUID =  "   +  RandomStringUtils.randomNumeric( 19 +   " L; " ;
                objectClass.createField(formattedContent, insertPosition, 
true null );
            }

            
//  implements
             if  (cu.isWorkingCopy()) {
                ObjectScanBuffer sb 
new  ObjectScanBuffer(objectClass);
                List tokens = sb.findTokensBetween(ITerminalSymbols.TokenNameclass, ITerminalSymbols.TokenNameLBRACE, 
false );
                
if  (sb.existToken(tokens, "Serializable")) {
                    System.out.println("Serializable interface has been implements");
                    
return ;
                }
                
if  (sb.existToken(tokens, ITerminalSymbols.TokenNameimplements)) {
                    sb.appendText(", Serializable ");
                } 
else  {
                    
if  (!sb.skipSpaces())
                        sb.appendText(" ");
                    sb.appendText("implements Serializable "
);
                }
            }
        } 
catch  (Exception e) {
            MessageDialog.openError(parentShell,
"Generation Failed " , e.getMessage());
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值