我继承了一些代码,但作者不喜欢使用分号。是否可能一次性修复所有 mlint 消息(至少自动修复的消息),而不必每次单击并按 ALT+ENTER?
注意: 本答案使用的函数MLINT在MATLAB的新版本中不再推荐使用。更好的选择是CHECKCODE函数,只需将对MLINT的调用替换为对这个新函数的调用即可。
我不知道有没有一般性的方法可以根据MLINT的信息自动修复代码。但是,在你的特定情况下,有一种自动化的方法可以让你添加分号到引发MLINT警告的行上。
首先,我们从这个样例脚本junk.m
开始:
a = 1
b = 2;
c = 'a'
d = [1 2 3]
e = 'hello';
%# Find the lines where a given mlint warning occurs:
fileName = 'junk.m';
mlintID = 'NOPTS'; %# The ID of the warning
mlintData = mlint(fileName,'-id'); %# Run mlint on the file
index = strcmp({mlintData.id},mlintID); %# Find occurrences of the warnings...
lineNumbers = [mlintData(index).line]; %# ... and their line numbers
%# Read the lines of code from the file:
fid = fopen(fileName,'rt');
linesOfCode = textscan(fid,'%s','Delimiter',char(10)); %# Read each line
fclose(fid);
%# Modify the lines of code:
linesOfCode = linesOfCode{1}; %# Remove the outer cell array encapsulation
linesOfCode(lineNumbers) = strcat(linesOfCode(lineNumbers),';'); %# Add ';'
%# Write the lines of code back to the file:
fid = fopen(fileName,'wt');
fprintf(fid,'%s\n',linesOfCode{1:end-1}); %# Write all but the last line
fprintf(fid,'%s',linesOfCode{end}); %# Write the last line
fclose(fid);
现在文件junk.m
的每一行末尾都应该有分号。如果需要,您可以将上述代码放入一个函数中,以便可以轻松地在继承的所有文件中运行它。
mlint
(现在是 checkcode
)使用 mlintmex
(内置函数;名称暗示它是 mex 文件),它只是从 linter 返回 text 输出。没有暴露自动修复;即使行号和列号也被作为纯文本输出。它似乎与 Matlab 安装中的 mlint 二进制文件的输出相同($(matlabroot)/bin/$(arch)/mlint
)。%// Get the java component for the active matlab editor
ed = matlab.desktop.editor.getActive().JavaEditor.getTextComponent();
%// Get the java representation of all mlint messages
msgs = com.mathworks.widgets.text.mcode.MLint.getMessages(ed.getText(),ed.getFilename())
%// Loop through all messages and apply the autofix, if it exits
%// Iterate backwards to try to prevent changing the location of subsequent
%// fixes... but two nearby fixes could still mess each other up.
for i = msgs.size-1:-1:0
if msgs.get(i).hasAutoFix()
com.mathworks.widgets.text.mcode.analyzer.CodeAnalyzerUtils.applyAutoFixes(ed,msgs.get(i).getAutoFixChanges);
end
end
编辑: 哎呀! 你可以使用-fix
标志让mlint二进制文件返回修复结果...并且这也适用于内置的checkcode
。虽然这仍未被记录(据我所知),但可能比上面提到的更加健壮:
>> checkcode(matlab.desktop.editor.getActiveFilename(),'-fix')
L 2 (C 3): Terminate statement with semicolon to suppress output (in functions). (CAN FIX)
----FIX MESSAGE <Add a semicolon.>
----CHANGE MESSAGE L 2 (C 13); L 2 (C 12): <;>
L 30 (C 52-53): Input argument 'in' might be unused. If this is OK, consider replacing it by ~. (CAN FIX)
----FIX MESSAGE <Replace name by ~.>
----CHANGE MESSAGE L 30 (C 52); L 30 (C 53): <~>
fix
字段的目的,正如@High Performance Mark在@gnovice的答案中所指出的那样;当有修复可用时,它似乎为1,当消息是上面的FIX MESSAGE
时为2,当消息是CHANGE MESSAGE
时为4。matlab.desktop.editor
公共(!)API获取活动文档(getActive
),并在原地修改文档的getter和setter的Text
属性,而不保存它。function str = applyAutoFixes(filepath)
msgs = checkcode(filepath,'-fix');
fid = fopen(filepath,'rt');
iiLine = 1;
lines = cell(0);
line = fgets(fid);
while ischar(line)
lines{iiLine} = line;
iiLine = iiLine+1;
line = fgets(fid);
end
fclose(fid);
pos = [0 cumsum(cellfun('length',lines))];
str = [lines{:}];
fixes = msgs([msgs.fix] == 4);
%// Iterate backwards to try to prevent changing the indexing of 'str'
%// Note that two changes could still conflict with eachother. You could check
%// for this, or iteratively run mlint and fix one problem at a time.
for fix = fliplr(fixes(:)')
%'// fix.column is a 2x2 - not sure what the second column is used for
change_start = pos(fix.line(1)) + fix.column(1,1);
change_end = pos(fix.line(2)) + fix.column(2,1);
if change_start >= change_end
%// Seems to be an insertion
str = [str(1:change_start) fix.message str(change_start+1:end)];
else
%// Seems to be a replacement
str = [str(1:change_start-1) fix.message str(change_end+1:end)];
end
end
libmwmlint.{dll,so,dylib}
。快速查看符号让我想知道是否可能(MLINT::mlint_file(char const*)
, MLINT::mlint_text(char const*, char const*, unsigned int)
,最有趣/令人望而生畏的是:MLINT::set_output_fun(void (*)(char const*, void*), void*)
)。 - mbauman我知道这是一个旧帖子,但最近我需要它,并改进了原始代码,所以如果其他人需要,这里就有了。它查找函数中缺少的";",不仅限于常规脚本,在代码中保留空格,并仅写入有更改的文件。
function [] = add_semicolon(fileName)
%# Find the lines where a given mlint warning occurs:
mlintIDinScript = 'NOPTS'; %# The ID of the warning
mlintIDinFunction = 'NOPRT';
mlintData = mlint(fileName,'-id'); %# Run mlint on the file
index = strcmp({mlintData.id},mlintIDinScript) | strcmp({mlintData.id},mlintIDinFunction); %# Find occurrences of the warnings...
lineNumbers = [mlintData(index).line]; %# ... and their line numbers
if isempty(lineNumbers)
return;
end;
%# Read the lines of code from the file:
fid = fopen(fileName,'rt');
%linesOfCode = textscan(fid,'%s', 'Whitespace', '\n\r'); %# Read each line
lineNo = 0;
tline = fgetl(fid);
while ischar(tline)
lineNo = lineNo + 1;
linesOfCode{lineNo} = tline;
tline = fgetl(fid);
end
fclose(fid);
%# Modify the lines of code:
%linesOfCode = linesOfCode{1}; %# Remove the outer cell array encapsulation
linesOfCode(lineNumbers) = strcat(linesOfCode(lineNumbers),';'); %# Add ';'
%# Write the lines of code back to the file:
fim = fopen(fileName,'wt');
fprintf(fim,'%s\n',linesOfCode{1:end-1}); %# Write all but the last line
fprintf(fim,'%s',linesOfCode{end}); %# Write the last line
fclose(fim);