У меня возникла проблема с написанием алгоритма, который поможет мне сканировать файловую систему и найти все подклассы определенного класса.
Подробности:
У меня есть приложение, которое сканирует внешнее приложение, используя nio
Files.walk()
то время как я проверяю "extends SuperClass" при чтении файла, если слово завершается, я добавляю имя класса в свой список следующим образом:
List<String> subclasses = new ArrayList<>();
Files.walk(appPath)
.filter(p->Files.isRegularFile(p) && p.toString()
.endsWith(".java")).forEach(path -> {
try {
List<String> lines = Files.readAllLines(path);
Pattern pattern = Pattern.compile("\\bextends SuperClass\\b");
Matcher matcher = pattern
.matcher(lines.stream()
.collect(Collectors.joining(" ")));
boolean isChild = matcher.find();
if(isChild) subclasses.add(path.getFileName().toString());
}catch (IOException e){
//handle IOE
}
Проблема с вышеизложенным заключается в том, что он получает только прямые подклассы SuperClass
но мне нужно получить все прямые и косвенные подклассы. Я думал о рекурсии, так как у меня нет идеи, сколько подклассов SuperClass
существует, но я не мог реализовать разумную реализацию.
ЗАМЕТКИ:
- Сканирование более 600 тысяч файлов
- У меня нет идеи, сколько прямых/косвенных подклассов
SuperClass
существует - Приложение, которое я просматриваю, является внешним, и я не могу изменить его код, поэтому мне разрешен доступ к нему, читая файлы и видя, где
extends
расширение - Если есть нерекурсивное решение проблемы, которое было бы здорово, но если нет другого пути, я буду более чем счастлив принять рекурсивный, поскольку я забочусь о том, чтобы решение было больше, чем производительность.
Редактировать:
Я использую следующее регулярное выражение для сравнения имени и импорта, чтобы убедиться, что даже в случае одинакового имени разные пакеты вывод правильный:
Pattern pattern = Pattern.compile("("+superClasss.getPackage()+")[\\s\\S]*(\\bextends "+superClass.getName()+"\\b)[\\s\\S]");
Я также пробовал:
Pattern pattern = Pattern.compile("\\bextends "+superClass.getName()+"\\b");
Но есть и недостающие подклассы, я считаю, что код ниже пропускает некоторые проверки и не работает в полной мере:
public static List<SuperClass> getAllSubClasses(Path path, SuperClass parentClass) throws IOException{
classesToDo.add(baseClass);
while(classesToDo.size() > 0) {
SuperClass superClass = classesToDo.remove(0);
List<SuperClass> subclasses = getDirectSubClasses(parentPath,parentClass);
if(subclasses.size() > 0)
classes.addAll(subclasses);
classesToDo.addAll(subclasses);
}
return classes;
}
Любая помощь действительно оценена!
Edit 2 Я также заметил еще одну проблему: когда я обнаруживаю subclass
я получаю имя файла currentPath.getFileName()
которое может быть или не быть подклассовым именем, поскольку подкласс может быть nested
или непубличным class
в том же файле,