К сожалению, Ваш вопрос полон недостатков:
- Можно, Корсика, разобрать источник входного сигнала (через JavaCC или ANTLR синтаксический анализатор), пока не достигнете желаемой линии. Но кажется, что тратить усилия на разбор одного и того же источника, поскольку у вас уже есть файлы
.class
.
- Итак, лучше проанализировать файл
.class
. Но, к сожалению, у вас нет гарантий, что это класс, в котором ваша линия появляется, потому что может быть более одного класса, определенного в том же исходном файле.
Augh!Это подводит меня к виду сложного решения:
я объявить класс, который будет содержать всю логин:
public class SourceMethodsIndexer
{
private final SortedMap<Integer, List<Method>> indexOfMethodsByFirstLineNumber;
}
Конструктор будет выглядеть следующим образом:
public SourceMethodsIndexer(File sourceFile)
.. и должен выполнять следующие задачи:
1. Просмотрите каталог классов, относящийся к целевому пакету.
File targetPackageDir=getTargetPackageDir(sourceFile);
File[] classFiles=targetPackageDir.listFiles(new FileFilter(){
public boolean accept(File dir, String name){
return name.endsWith(".class");
}
});
2.Use Apache BCEL для сбора всех непубличных классов, принадлежащих вашему исходному исходному файлу (вы можете вызывать JavaClass.getSourceFileName()
для фильтрации классов), а также открытый класс, соответствующий имени вашего исходного файла источника.
Collection<JavaClass> targetClasses=getNonPublicClasses(classFiles, sourceFile.getName());
targetClasses.add(publicClass);
3.Заберите все методы в каждом классе.
Set<Method> targetMethods=new HashSet<Method>(1024);
for (JavaClass javaClass:targetClasses)
{
targetMethods.addAll(Arrays.asList(javaClass.getMethods()));
}
4.Now вы можете искать непосредственно свой номер строки, или индекс первых методов по номеру строки, чтобы получить доступ к ним позже быстрее: JavaClass.getMethods()[n].getLineNumberTable().getSourceLine(0)
(заботиться, что может быть повторено значение).
this.indexOfMethodsByFirstLineNumber=new TreeMap<Integer, List<Method>>((int)(1.7d*methods.size()));
for (Method method: methods)
{
// Note: The -1 in this line stands to make the SortedMap work properly when searching for ranges.
int firstLine=getLineNumberTable().getSourceLine(0)-1;
List<Method> methodsInTheSameLine=indexOfMethodsByFirstLineNumber.get(firstLine);
if (methodsInTheSameLine==null)
{
methodsInTheSameLine=new ArrayList<Method>();
indexOfMethodsByFirstLineNumber.put(firstLine,methodsInTheSameLine);
}
methodsInTheSameLine.add(method);
}
5.Public способ сделать поиск:
public Method getMethodByLine(int lineNumber)
{
Set<Method> methodsInTheSameLine=this.indexOfMethodsByFirstLineNumber.headMap(lineNumber).lastKey();
if (methodsInTheSameLine.size()==0)
{
// There are no methods method in that line: Absurd.
}
else if (methodsInTheSameLine.size()>1)
{
// There are more than one method in that line. Hardly probable, but possible.
}
else
{
// There is one method in that line:
return methods.get(0);
}
}
Поскольку исходный код не гарантируется компилируется, это может быть невозможно, к тому же номер строки не может быть в методе вообще. – Andreas
Хммм, хорошо да, позвольте мне сделать его компилируемым точно. – Bruce