Подсчет атрибутов исходного кода Java для обнаружения
В настоящее время я работаю над проектом по обнаружению плагиата исходного кода и на самом деле использую различные аспекты атрибутов входных файлов (файлов исходного кода) для обнаружения плагиата среди студенческих заданий. Например, теперь я использую (количество идентификаторов / переменных, количество используемых методов, количество строк кода) и некоторые другие атрибуты для представления каждого файла исходного кода.
Однако, когда я пытаюсь подсчитать количество используемых переменных, одна проблема состоит в том, как узнать, использовалась ли переменная или нет. Потому что студенты могли намеренно ввести некоторые идентификаторы, чтобы покрыть плагиат. Однако, пытаясь решить эту проблему, я обнаружил, что это действительно сложно. Одним из подходов для этого является использование регулярного выражения в Java для обработки поиска идентификаторов, но после их поиска я остановился на том, как проверять использование или нет. (Более того, после этого мне все еще нужно выяснить, вызывается ли java-метод или нет.) Поэтому написание собственной версии регулярного выражения может быть очень сложным.
Я знаю, что в некоторых средах IDE, таких как NetBeans, редактор может мгновенно выяснить, используется ли переменная или нет, и подчеркнуть ее. Поэтому мне интересно, есть ли хороший способ проверки используемых переменных или нет.
Любые предложения о том, как сделать проверку переменных было бы хорошо!
3 ответа
Для такого анализа кода вам обязательно нужно изучить инструменты парсера / компилятора. Вы не можете определить, используется ли переменная путем поиска ее простого имени; Вы также должны искать правильный контекст.
Я предлагаю взглянуть на ANTLR, который является инструментом синтаксического анализа на основе Java. Здесь есть определение синтаксического анализа Java, доступное здесь. Не надейтесь найти простое решение для вашей проблемы, которое может быть реализовано за пару часов.
Еще один инструмент на основе Java- JavaCC. Если вы ищете пример кода, показывающего, как можно использовать эти инструменты, взгляните на PMD, который использует анализатор, созданный с помощью JavaCC, для анализа кода Java.
Другая возможность - написать плагин для IDE, который поддерживает анализ кода - у вас, вероятно, будет гораздо более простой интерфейс для доступа к структуре кода, и, как вы сказали, множество функциональных возможностей уже доступно и может быть просто вызвано вашим плагином.,
Да, вы также можете взломать свой путь с помощью некоторых регулярных выражений. Хотите ли вы сделать это, зависит от того, насколько точным будет ваш инструмент. Без разбора исходного кода решение о том, является ли вхождение имени переменной на самом деле использованием этой переменной, является просто эвристическим предположением.
Первое, что приходит в голову, это сделать что-то вроде этого:
(\w+)\s+<?varname>(\w+)\s*(=[\w\s\(\,)]+)?;
Это должно соответствовать созданию переменной следующим образом:
int x = 1;
double y;
Foo foo = new Foo();
Foo foo = new Foo(a,b,c);
Чтобы сделать вещи менее сложными, было бы неплохо заменить все ;
которые не находятся в кавычках ;\n
, Это должно убедиться, что у вас есть один оператор на строку.
Предоставленное регулярное выражение, помимо попытки сопоставления создания переменной, также помещает имя переменной в группу с именем varname
к которому вы можете получить доступ через matcher
объект вроде так: String varName = matcher.group("varname");
, Чтобы увидеть, используется ли переменная, вы можете проверить, находится ли переменная справа от равенства, например:
[^=]+\s*=\s*.*?x.*;
Это должно соответствовать строки, такие как int y = x;
а также Foo foo = x + y;
Тем не менее, переменная также может быть использована в качестве параметра метода, поэтому вы можете сделать что-то вроде этого:
.*?\(.*?x.*?\).*?;
Это будет соответствовать строкам так:foo(x);
foo(a,b,c,x);
Foo foo = new Foo(a,v,x,y).createNewFoo();
Foo foo = new Foo(a,v,x,y).SOMECONSTANT;
Следует отметить, что в представленных регулярных выражениях x
это просто имя переменной образца, которое должно быть заменено фактическим именем переменной, которое вы сможете извлечь с помощью первого регулярного выражения.
Возможно, вы захотите взглянуть на это руководство по регулярным выражениям Oracle.
Среды IDE классифицируют вхождения переменных на две категории: присваивания определенной переменной и простое ее использование. Назначение должно быть легко распознать с помощью регулярных выражений. Все остальные вхождения должны быть в коде только с использованием этой переменной.