Я бросил вокруг меня разные идеи в этом вопросе и, наконец, смог придумать в основном элегантное решение, как справиться с этим.
Решение
Критический компонент этого решения является undocumented -allmsg
флаг of checkcode
(or mlint
). Если вы укажете этот аргумент, будет напечатан полный список идентификаторов mlint
, кодов серьезности и описаний. Что еще более важно, категории также, напечатанные в этом списке, и все mlint
Идентификаторы перечислены под их соответствующей категорией mlint
.
Исполнение
Теперь мы не можем просто вызвать checkcode
(или mlint
) с только-allmsg
флаг, потому что это было бы слишком легко. Вместо этого для этого требуется фактический файл, чтобы попытаться проанализировать и проверить наличие ошибок. Вы можете получить , но я решил передать встроенный 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.
Пример Parser
Я поставил все части, которые я обсуждал ранее вместе в маленькую функцию, которая будет генерировать-структуру, где все поля являются идентификаторы mlint
. В каждом поле вы получите следующую информацию:
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
, поскольку категория (и серьезность) будет изменяться с момента выпуска на выпуск при добавлении новых функций и устаревших старых функциях.
Благодарим за задание этого сложного вопроса, и я надеюсь, что этот ответ даст небольшую помощь и понимание!
Можете ли вы связать некоторую документацию, где объясняются категории thoe? Я не могу найти его .... –
На вкладке «Главная» нажмите «Настройки» в разделе «Окружающая среда», затем выберите «Анализатор кода» слева. Все категории находятся там. –
Чтобы уточнить, я намерен ввести идентификатор ошибки, такой как «DWVRD» (который соответствует ошибке «wavread будет удалён в будущей версии, используйте вместо него аудиозапись») в какую-то функцию, которая вернет категорию, в которой указан этот код ошибки перечисленные ниже и любые другие связанные с ним свойства. –