由于 IScanner 和 IBuffer 修改源码比较麻烦,功能也不是很强大,需要编写大量的代码。
所以这里谢了一个辅助类,来改善代码。
接下来,我们看一下具体的应用:
描述: 判断一个类是否已经实现 Java.io.Serializable, 如果没有实现,那么加入实现代码
所以这里谢了一个辅助类,来改善代码。
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);
}
}
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());
}
}
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());
}
}
Java Serializable辅助生成工具
本文介绍了一款用于Java项目的辅助工具,旨在简化Serializable接口的添加过程。通过此工具,开发者可以轻松地为类添加实现Serializable所需的 serialVersionUID 字段,并确保类声明实现Serializable接口。

被折叠的 条评论
为什么被折叠?



