gpt4 book ai didi

matlab - 查找 MATLAB mlint 警告 ID 的类别

转载 作者:太空宇宙 更新时间:2023-11-03 19:41:32 25 4
gpt4 key购买 nike

我在 MATLAB 中使用 checkcode 函数为我提供提供的文件名中所有错误消息的结构,以及它们的 McCabe 复杂性和与该错误相关的 ID。即;

info = checkcode(fileName, '-cyc','-id');

在 MATLAB 的首选项中,有一个所有可能错误的列表,并且它们被分解成类别。如“美学和可读性”、“语法错误”、“不鼓励使用函数”等。

有没有一种方法可以使用从上述代码行中获得的错误 ID 来访问这些类别?

最佳答案

对于这个问题,我在脑海中反复思考了不同的想法,最终能够想出一个最优雅的解决方案来解决这个问题。

解决方案

此解决方案的关键组件是 undocumented -allmsg旗帜 of checkcode (or mlint) .如果您提供此参数,则会打印完整的 mlint ID、严重性代码和描述列表。更重要的是,类别打印在此列表中,所有 mlint ID 都列在它们各自的 mlint 类别下。

执行

现在我们不能简单地调用 checkcode(或 mlint), -allmsg 标志,因为那太简单了。相反,它需要一个实际文件来尝试解析和检查错误。您可以传递任何有效的 m 文件,但我选择传递内置的 sum.m,因为实际文件本身只包含帮助信息(因为它是真正的实现很可能是 C++),因此 mlint 能够非常快速解析它而没有任何警告。

checkcode('sum.m', '-allmsg');

打印到命令窗口的输出摘录是:

   INTER    ========== Internal Message Fragments ==========
MSHHH 7 this is used for %#ok and should never be seen!
BAIL 7 done with run due to error
INTRN ========== Serious Internal Errors and Assertions ==========
NOLHS 3 Left side of an assignment is empty.
TMMSG 3 More than 50,000 Code Analyzer messages were generated, leading to some being deleted.
MXASET 4 Expression is too complex for code analysis to complete.
LIN2L 3 A source file line is too long for Code Analyzer.
QUIT 4 Earlier syntax errors confused Code Analyzer (or a possible Code Analyzer bug).
FILER ========== File Errors ==========
NOSPC 4 File <FILE> is too large or complex to analyze.
MBIG 4 File <FILE> is too big for Code Analyzer to handle.
NOFIL 4 File <FILE> cannot be opened for reading.
MDOTM 4 Filename <FILE> must be a valid MATLAB code file.
BDFIL 4 Filename <FILE> is not formed from a valid MATLAB identifier.
RDERR 4 Unable to read file <FILE>.
MCDIR 2 Class name <name> and @directory name do not agree: <FILE>.
MCFIL 2 Class name <name> and file name do not agree: <file>.
CFERR 1 Cannot open or read the Code Analyzer settings from file <FILE>. Using default settings instead.
...
MCLL 1 MCC does not allow C++ files to be read directly using LOADLIBRARY.
MCWBF 1 MCC requires that the first argument of WEBFIGURE not come from FIGURE(n).
MCWFL 1 MCC requires that the first argument of WEBFIGURE not come from FIGURE(n) (line <line #>).
NITS ========== Aesthetics and Readability ==========
DSPS 1 DISP(SPRINTF(...)) can usually be replaced by FPRINTF(...).
SEPEX 0 For better readability, use newline, semicolon, or comma before this statement.
NBRAK 0 Use of brackets [] is unnecessary. Use parentheses to group, if needed.
...

第一列显然是 mlint ID,第二列实际上是严重性编号(0 = 大部分无害,1 = 警告,2 = 错误,4-7 = 更严重的内部问题) , 第三列是显示的消息。

如您所见,所有类别有一个标识符但没有严重性,它们的消息格式是===== Category Name =====

现在我们可以解析这些信息并创建一些数据结构,使我们能够轻松查找给定 mlint ID 的严重性和类别。

不过,这并不总是那么容易。不幸的是,checkcode(或 mlint)只是将此信息打印到命令窗口,并没有将其分配给我们的任何输出变量。因此,有必要使用 evalc (shudder) 捕获输出并将其存储为字符串。然后,我们可以轻松解析此字符串以获取与每个 mlint ID 关联的类别和严重性。

解析器示例

我已将我之前讨论的所有部分放在一个小函数中,该函数将生成一个结构,其中所有字段都是 mlint ID。在每个字段中,您将收到以下信息:

warnings = mlintCatalog();
warnings.DWVRD

id: 'DWVRD'
severity: 2
message: 'WAVREAD has been removed. Use AUDIOREAD instead.'
category: 'Discouraged Function Usage'
category_id: 17

如果您有兴趣,这里是小函数。

function [warnings, categories] = mlintCatalog()
% Get a list of all categories, mlint IDs, and severity rankings
output = evalc('checkcode sum.m -allmsg');

% Break each line into it's components
lines = regexp(output, '\n', 'split').';
pattern = '^\s*(?<id>[^\s]*)\s*(?<severity>\d*)\s*(?<message>.*?\s*$)';
warnings = regexp(lines, pattern, 'names');
warnings = cat(1, warnings{:});

% Determine which ones are category names
isCategory = cellfun(@isempty, {warnings.severity});
categories = warnings(isCategory);

% Fix up the category names
pattern = '(^\s*=*\s*|\s*=*\s*$)';
messages = {categories.message};
categoryNames = cellfun(@(x)regexprep(x, pattern, ''), messages, 'uni', 0);
[categories.message] = categoryNames{:};

% Now pair each mlint ID with it's category
comp = bsxfun(@gt, 1:numel(warnings), find(isCategory).');
[category_id, ~] = find(diff(comp, [], 1) == -1);
category_id(end+1:numel(warnings)) = numel(categories);

% Assign a category field to each mlint ID
[warnings.category] = categoryNames{category_id};

category_id = num2cell(category_id);
[warnings.category_id] = category_id{:};

% Remove the categories from the warnings list
warnings = warnings(~isCategory);

% Convert warning severity to a number
severity = num2cell(str2double({warnings.severity}));
[warnings.severity] = severity{:};

% Save just the categories
categories = rmfield(categories, 'severity');

% Convert array of structs to a struct where the MLINT ID is the field
warnings = orderfields(cell2struct(num2cell(warnings), {warnings.id}));
end

总结

这是一种获取与给定 mlint ID 关联的类别和严重性的完全未记录但相当可靠的方法。此功能存在于 2010 年,甚至可能更早,因此它应该适用于您必须处理的任何版本的 MATLAB。这种方法也比简单地记录给定的 mlint ID 属于哪些类别要灵活得多,因为随着新功能的添加和旧功能的弃用,类别(和严重性)会随着版本的不同而发生变化。

感谢您提出这个具有挑战性的问题,我希望这个答案能提供一点帮助和见解!

关于matlab - 查找 MATLAB mlint 警告 ID 的类别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35898444/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com