Как я могу посчитать количество строк реальных комментариев? - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть куча файлов сценариев / функций MATLAB, над которыми мне и остальной моей команде нужно работать. Мы почти не имеем представления о том, что делает большинство файлов, и почти не знаем, какие из них принадлежат друг другу, а какие - отдельными. Мы знаем, что у нас всего 36 000 строк. Я хотел бы знать, сколько из этих строк являются комментариями.

Легко, правда? Просто посчитайте, сколько из них начинается с символа начала комментария%.

Ну нет. Я не хочу считать блоки кода, которые были закомментированы как «комментарии», так как на самом деле они ничего мне не говорят. И я бы предпочел не считать «пустые» строки, используемые для того, чтобы сделать одну строку комментария «заголовком»

% %%%%%%%%
% headline
% %%%%%%%%

вот так.

Так, как я могу получить разумную оценку того, сколько строк фактических информативных комментариев у меня есть? Есть ли простой способ отличить естественный язык (возможно, содержащий фрагменты кода) от чистого кода ?


Да, я знаю, что код должен быть понятен, насколько это практически возможно, но код, который мы унаследовали, явно не является таковым. Да, я знаю, что мы, вероятно, должны изменить этот беспорядок. Цель выяснения, сколько у нас комментариев, состоит в том, чтобы выделить технический долг, который у нас есть, чтобы мы могли выделить ресурсы для этого рефакторинга.

Ответы [ 3 ]

0 голосов
/ 07 ноября 2018

Легко получить комментарии, которые не просто разделяют вещи, исключая все, что не содержит текста: a-z или A-Z. Таким образом,% a является «информативным комментарием», а% ----- - нет.

Теперь, чтобы отфильтровать код, я считаю, что лучшим способом было бы рассмотреть %text text как комментарий, а остальное как код: комментарий - это место, где между двумя частями текста есть пробел. Куском текста может быть что угодно, содержащее букву, или оно может быть ограничено только буквами и пунктуацией (в одном случае a=5 - это отдельный фрагмент текста, в другом - это не фрагмент текста) , и вы также должны исключить зарезервированные кодовые слова.

Это, очевидно, не будет работать постоянно, так как текст, содержащий только одно слово комментария, является также информативным комментарием, скажем, у вас может быть комментарий, говорящий %randomize. Тем не менее, учтите следующее: randomize может быть комментарием, говорящим о том, что нижеприведенное вещество выполняет рандомизацию (скорее всего), или это может быть функция, которая делает рандомизацию без каких-либо параметров и выдает какие-либо выходные данные (скажем, злоупотребляя отражением, чтобы действительно что-то сделать) , Невозможно выполнить синтаксический анализ между этими двумя параметрами - парсер должен будет построчно запускать код и пытаться выяснить, работает ли строка, или выдает ошибку для работы в таких сценариях.

Обратите внимание, что код не будет работать напрямую и не является оптимальным, но исправить его должно быть достаточно просто.

isC = parseComment(commentText)
splitText = split(commentText, ' '); % split by whitespace.
isValidText = false(length(splitText),1);
if (length(isValidText) == 1)
   isC = false;
   return
end
for i=1:length(splitText)
   % find if this "word" is valid non-code text.
   if (contains(splitText(i), [a-z])) % Fix this condition, should suitably check if the thingy is a word in a way you want it.
      if ~isReservedCodeWord(splitText(i)) % here you should exclude if, for, while and so on.
         isValidText(i) = true;
      end
   end
end
%checking of parts is complete, check if the string has 2 adjacent "valid text" parts.
isC = any(isValidText(1:end-1) & isValidText(2:end));
0 голосов
/ 08 ноября 2018

Отвечая на мой собственный вопрос здесь, так как я в конечном итоге пошел в другом направлении, чем любой из ответов.


Мне нужна была оценка, не обязательно точное число. Я был бы в порядке с автоматизированной системой, даже если бы она неправильно классифицировала некоторые строки. Но я не смог найти достаточно простой способ отличить код от текста, поэтому я выбрал более ручной маршрут.

Я просто grep отредактировал все строки комментариев, а затем скремблировал порядок строк вывода, чтобы я мог посмотреть последние примерно 50 строк на моем экране и вручную посчитать соотношение полезных комментариев к закомментированному коду. , Это дает мне приблизительную оценку, а умножение на количество строк комментариев дает оценку количества полезных строк комментариев.

Вывод: у нас есть около 36000 строк почти полностью недокументированного кода для игры. Yay.

Чтобы изменить порядок строк, я использовал файл shuffle.bat, который нашел здесь Как случайным образом переставить строки в текстовом файле с помощью пакетного файла

Итак, я закончил с type *.m | grep % | shuffle.bat

И этого мне было достаточно.


Предложение Dev-il использовать mtree было бы очень полезно, если бы можно было сделать mtree для вывода количества строк разбираемого, запускаемого кода. Тогда я мог бы grep вычеркнуть строки комментариев, убрать % в начале, а затем использовать mtree, чтобы подсчитать, что такое исполняемый код и что, скорее всего, текст. К сожалению, mtree будет анализировать что угодно, и в действительности не различает то, что в конечном итоге имеет смысл как код, и то, что не имеет.

0 голосов
/ 07 ноября 2018

Мы можем использовать для этого полудокументированную утилиту mtree.

Давайте возьмем, к примеру, файл .m, который содержит определение самого класса mtree.

dbtype mtree урожайность (это только начало):

1     classdef mtree
2     %MTREE  Create and manipulate M parse trees
3     %   This is an experimental program whose behavior and interface is likely
4     %   to change in the future.
5     
6     % Copyright 2006-2016 The MathWorks, Inc.
7     
8         properties (SetAccess='protected', GetAccess='protected', Hidden)
9             T    % parse tree array

Теперь, если мы вызовем утилиту mtree для себя и покажем результат в виде текста,

tree = mtree('mtree.m','-file');
tree.dumptree()

вот что мы получаем (опять же, только начало):

  1  *:  CLASSDEF:   1/01 
  3     *Cexpr:  ID:   1/10  (mtree)
  4     *Body:  PROPERTIES:   8/05 
  5        *Attr:  ATTRIBUTES:   8/16 
  6           *Arg:  ATTR:   8/26 
  7              *Left:  ID:   8/17  (SetAccess)
  8              *Right:  CHARVECTOR:   8/27  ('protected')
  9           >Next:  ATTR:   8/49 
 10              *Left:  ID:   8/40  (GetAccess)
 11              *Right:  CHARVECTOR:   8/50  ('protected')
 12           >Next:  ATTR:   8/63 
 13              *Left:  ID:   8/63  (Hidden)
 14        *Body:  EQUALS:   9/09 

Как видно из вышесказанного, комментарий и пустые строки (2-7) не появляются в левой части «дробей» в выводе. Так что, если мы найдем способ получить «числители», мы получим номера строк, которые содержат реальный код.

Нам повезло, так как существует метод, который дает нам эти числители - lineno! Поэтому, если мы вызовем его и применим unique к выводу, мы получим ровно одну копию каждой строки:

uLines = unique(tree.lineno);
nCodeLines = numel(uLines);

Это дает значение 269 для nCodeLines в R2018b. Если вы хотите предположить, что последняя строка в файле всегда является строкой кода (а не комментарием или пробелом), вы можете просто вычесть nCodeLines из последнего элемента uLines, чтобы получить сумму строки комментариев (121 в данном случае). В противном случае используйте другой метод для подсчета общего количества строк ( пример ).

Осталось только написать это как функцию и передать в нее папку .m файлов:)

...