我在MATLAB中使用校驗碼函數給我一個提供的文件名中的所有錯誤消息的結構,以及它們的McCabe複雜度和與該錯誤相關的ID。即;查找MATLAB mlint警告ID的類別
info = checkcode(fileName, '-cyc','-id');
在MATLAB的首選項中,列出了所有可能的錯誤,並將它們分解爲多個類別。如「美觀性和可讀性」,「語法錯誤」,「勸阻功能使用」等。
有沒有辦法使用從上面的代碼獲得的錯誤ID訪問這些類別?
我在MATLAB中使用校驗碼函數給我一個提供的文件名中的所有錯誤消息的結構,以及它們的McCabe複雜度和與該錯誤相關的ID。即;查找MATLAB mlint警告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所處的類別還要靈活得多,因爲添加新功能並且不推薦使用舊功能,類別(和嚴重性)將從發佈變爲發佈。
感謝您提出這個具有挑戰性的問題,我希望這個答案提供一些幫助和見解!
這似乎比使用我創建的Excel文件存儲它們更好的解決方案。我一定會用這個更新我的方法。謝謝。 –
+1我對[Atom](https://atom.io/)文本編輯器的linter插件有類似的建議:https://github.com/ajdm/linter-matlab/issues/2#issuecomment- 182097020 – Amro
就關閉這個問題了。我設法從幾個不同的地方提取數據並將它們拼湊在一起。我現在有一個excel電子表格,包含所有matlab的警告和錯誤,以及相應的ID代碼,類別和嚴重程度(即,如果是警告或錯誤)列的錯誤。我現在可以讀取這個文件,查看使用'checkcode'函數得到的ID代碼並提取所需的任何信息。這現在可以用於創建分析工具來看看編寫的腳本/班等
的質量。如果有人想這個文件的一個副本,然後請給我留言,我會很樂意提供它。
達倫。
你可以鏈接一些文檔,哪些類別被解釋?我無法找到它.... –
一個主頁選項卡,單擊環境部分的首選項,然後選擇左側的「代碼分析器」。所有類別都在那裏。 –
爲了澄清,我的意圖是輸入一個錯誤ID,如'DWVRD'(它對應於錯誤「wavread將在未來版本中刪除,使用audioread代替」)到某個函數中,這將返回哪個類別此錯誤代碼被列在其下並與其相關的任何其他屬性。 –