我和其他团队需要处理一堆MATLAB脚本/函数文件。我们几乎不知道大多数文件的作用,也几乎不知道哪些文件属于同一文件,哪些文件是分开的。我们确实知道我们总共有36,000条线。我想知道其中有多少行是注释。
容易,对吧?只需计算其中有多少以注释开始字符%开头即可。
嗯,不。我不想统计被注释为“注释”的代码块,因为它们实际上并没有告诉我任何事情。而且我不希望将用于将一条评论行设为“标题”的“空”行计算在内
% %%%%%%%%
% headline
% %%%%%%%%
像这样
那么我如何才能合理估算出我有多少行实际的信息性评论?有没有一种简便的方法可以将自然语言(可能包含代码段)与纯代码区分开?
是的,我知道代码在实际中应该是不言自明的,但是我们清楚地继承的代码不是。是的,我知道我们应该重构这个烂摊子。弄清楚我们要发表多少评论的目的是为了突出我们在此处拥有的技术债务,以便我们可以为重构分配资源。
答案 0 :(得分:3)
为此,我们可以使用半文档的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);
在R2018b中,269
的值为nCodeLines
。如果您愿意假设文件的最后一行始终是代码行(而不是注释或空格),则可以从nCodeLines
的最后一个元素中减去uLines
到获取注释行的数量(在这种情况下为121
)。否则,请使用其他技术来计算总行数(example)。
剩下的就是将其作为函数编写,并将.m
文件的文件夹提供给它:)
答案 1 :(得分:0)
通过排除不包含任何文本的所有内容(a-z或A-Z),很容易获得不仅用于分隔内容的注释。因此,%a是“信息性评论”,而%-----不是。
现在,要过滤掉代码,我认为最好的方法是将%text text
视为注释,将其余部分视为代码:comment是两段文本之间有空格的地方。一段文字可以是任何包含字母的内容,也可以只包含字母和标点符号(在一种情况下,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));
答案 2 :(得分:0)
在这里回答我自己的问题,因为我最终选择的方向与任何一个答案不同。
我需要一个估计值,不一定是确切数字。即使自动化系统确实对某些行进行了错误分类,我也应该会满意。但是我找不到足够简单的方法来将代码与文本区分开,因此我采用了更为手动的方法。
我只grep
注释了所有注释行,然后加扰了输出的行顺序,以便可以查看屏幕上的最后50条左右的行,并手动计算有用注释与注释的代码。这给了我一个粗略的估计,然后多加注释行数就可以估计出有用的注释行数。
结论是,我们可以使用大约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
会解析任何内容,并且不会真正区分最终成为代码有意义的内容和没有意义的内容。