【问题标题】:How can I count number of lines of actual comments?如何计算实际评论的行数?
【发布时间】:2018-11-07 14:07:08
【问题描述】:

我有一堆 MATLAB 脚本/函数文件,我和我的团队的其他成员需要处理这些文件。我们几乎不知道大多数文件的作用,也几乎不知道哪些文件属于一起,哪些文件是分开的。我们确实知道我们总共有 36,000 行。我想知道其中有多少行是 cmets。

很简单,对吧?只需计算其中有多少以评论开始字符 % 开头。

嗯,不。我不想计算被注释为“cmets”的代码块,因为它们实际上并没有告诉我任何东西。而且我不想计算用于将评论行设为“标题”的“空”行

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

像这样。

那么我怎样才能合理估计我有多少行实际信息丰富的 cmets?有没有一种简单的方法可以区分自然语言(可能包含代码 sn-ps)和纯代码


是的,我知道代码应该是不言自明的,但我们继承的代码显然不是。是的,我知道我们可能应该重构这个烂摊子。弄清楚我们有多少 cmets 的目的是突出我们这里的技术债务,以便我们可以将资源分配给这个重构。

【问题讨论】:

  • 我假设您始终可以捕获以 % 和正则表达式开头的所有内容,以捕获由 % 字符以外的其他内容组成的内容。
  • 评论块 (%{ .... %}) 怎么样?
  • 您需要明确定义要排除哪些行或组合,如果我写了% ===% % % % %% ------- %,而不是像%% Heading 这样定义cmets 的有用部分呢?从这个描述中不清楚你对哪种cmet感兴趣
  • 捕捉 cmets 很容易,捕捉像@Wolfie 中的示例这样一些明显的特殊情况也相当容易。我要问的是明智的启发式/正则表达式,用于查看% useful text% for i = length(variable):size(gizmos) 之间的区别。幸运的是,@Dev-iL,代码似乎没有这种类型的块 cmets。
  • 您可以使用我的解决方案来获取哪些行是技术上代码,哪些是技术上 cmets,并可能在某个日志文件中收集所有这些,但确定其中有多少是“真正的” cmets 将是一项艰巨的任务,可能涉及一些机器学习,这可能超出了单个 SO 问题的范围。

标签: matlab comments text-files counting software-quality


【解决方案1】:

我们可以为此使用半文档化的mtree 实用程序。

我们以包含mtree 类本身定义的.m 文件为例。

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 *:分类:1/01 3 *Cexpr:ID:1/10(mtree) 4 *身体:属性:8/05 5 *属性:属性:8/16 6 *Arg:ATTR:8/26 7 *左:ID:8/17(SetAccess) 8 *右:CHARVECTOR:8/27(“受保护”) 9 >下一篇:ATTR: 8/49 10 *左:ID:8/40 (GetAccess) 11 *右:CHARVECTOR:8/50(“受保护”) 12 >下一个:ATTR:8/63 13 *左:ID:8/63(隐藏) 14 *身体:等于:9/09

从上面可以看出,注释和空行(2-7)不会出现在输出中“分数”的左侧。所以如果我们找到一种方法来获取“分子”,我们将获得包含实际代码的行数。

我们很幸运,因为有一种方法可以为我们提供这些分子 - lineno!因此,如果我们调用它并将unique 应用于输出,我们将得到每行的一个副本:

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

这会在 R2018b 中为 nCodeLines 生成 269 的值。如果您愿意假设文件中的最后一行始终是一行代码(而不是注释或空白),您可以从 uLines 的最后一个元素中减去 nCodeLines 以获得数量注释行(在这种情况下为121)。否则,请使用其他技术来计算总行数 (example)。

剩下的就是把它写成一个函数并将.m文件的文件夹提供给它:)

【讨论】:

  • 我认为这解决了错误的问题。我已经可以计算出不是 cmets 的行数了。我想在注释行中计算哪些是信息性文本,哪些是前面带有 % 的代码。如果我去掉第一个字符,也许我可以在以 % 开头的行上使用这种方法......
  • @gibson 有趣的想法。无论如何,您所拥有的与其说是“计数”问题,不如说是“识别”问题(一旦您知道要计数 什么计数 就变得微不足道了)。我建议您删除所有注释行,然后手动检查前几百行,看看其中有多少是“真实的” cmets,有多少是注释掉的代码 - 以建立某种“质量密度”的度量厘米”。然后,乘以注释行的数量。由于您想要的只是一个估计,因此您在密度估计中包含的线越多,最终结果就越准确。
  • 我查看了前几百行 cmets,但这些都是前面带有 % 的代码。但我也看到至少一个文件只有“正确”的 cmets。我可能应该将它们的顺序随机化,这样我就可以从大约 100 行中得到有用的估计。
  • (并且作为我在注释行上使用 mtree 方法的想法的后续行动:mtree 似乎无法区分可执行的行和有错误的行,因此 % the for loop is a = 1:length(gizmos) instead of :length(widgets) because bla bla 会计数作为 % 被剥离后的“代码”)
  • 可能有更聪明的方法来分析mtree,这可以解决这个问题,但我对mtree不够熟悉,无法进一步评论。
【解决方案2】:

通过排除不包含任何文本的所有内容:a-z 或 A-Z,很容易获得不只是分隔​​内容的 cmets。所以,%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));

【讨论】:

    【解决方案3】:

    在这里回答我自己的问题,因为我最终走向了与任何一个答案都不同的方向。


    我需要一个估计,不一定是一个确切的数字。即使它确实对某些行进行了错误分类,我也可以使用自动化系统。但是我找不到一个足够简单的方法来区分代码和文本,所以我选择了更手动的路线。

    我只是greped 所有注释行,然后打乱了输出的行顺序,这样我就可以查看屏幕上的最后 50 行左右,并手动计算有用的 cmets 与注释代码的比率.这给了我一个粗略的估计,将其乘以 cmets 的行数可以估计出有用的 cmets 行数。

    结论是我们有大约 36000 行几乎完全没有文档的代码可供使用。耶。

    为了打乱行序,我使用了一个 shuffle.bat 文件,我在这里找到了 How to randomly rearrange lines in a text file using a batch file

    所以我最终选择了type *.m | grep % | shuffle.bat

    这对我来说已经足够了。


    如果可以使 mtree 输出可解析、可运行的代码行数,Dev-il 使用 mtree 的建议将非常有用。然后我可以让grep 删除注释行,在开始时去掉%,然后使用mtree 来计算什么是可运行代码和最有可能的文本。不幸的是,mtree 会解析任何东西,并且不会真正区分最终作为代码有意义的东西和没有意义的东西。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-17
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 2020-07-06
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      相关资源
      最近更新 更多