MatrixBerryCore
MLintScanner.m
Go to the documentation of this file.
1 classdef MLintScanner
2  methods (Static)
3  [fileList,reportList]=scan(dirNameList,...
4  pathPatternToExclude)
5  [htmlOut,fullFileNameList,reportList]=...
6  scanWithHtmlReport(dirList,patternToExclude)
7  end
8 end
9 function [fileList,reportList]=scan(dirNameList,pathPatternToExclude)
10 pathList=mxberry.io.PathUtils.genPathByRootList(dirNameList,...
11  pathPatternToExclude);
12 %
13 [reportListOfList,fileListOfList]=cellfun(@(x)scanDir(x),pathList,...
14  'UniformOutput',false);
15 isnEmptyVec=~cellfun('isempty',reportListOfList);
16 fileListOfList=fileListOfList(isnEmptyVec);
17 reportListOfList=reportListOfList(isnEmptyVec);
18 fileList=vertcat(fileListOfList{:});
19 reportList=vertcat(reportListOfList{:});
20 if isempty(fileList)
21  fileList={};
22  reportList={};
23 end
24 end
25 %
26 function [reportList,localFilenames]=scanDir(dirName)
27 dirFileList = what(dirName);
28 fileList = sort([dirFileList.m]);
29 localFilenames = strcat(dirName,filesep,fileList);
30 reportList=mlint(localFilenames,'-struct');
31 %
32 isnEmptyVec=~cellfun('isempty',reportList);
33 reportList=reportList(isnEmptyVec);
34 localFilenames=localFilenames(isnEmptyVec);
35 end
36 function [htmlOut,fullFileNameList,reportList]=scanWithHtmlReport(dirList,patternToExclude)
37 [fullFileNameList,reportList]=...
38  mxberry.dev.MLintScanner.scan(dirList,...
39  patternToExclude);
40 [~,fileList]=cellfun(@fileparts,fullFileNameList,'UniformOutput',false);
41 %
42 SHtmlProxyReportVec = [];
43 reportName = 'MLint-MXBerry Code Analyzer Report';
44 %
45 nFiles=numel(fullFileNameList);
46 for iFile = 1:nFiles
47  %
48  SHtmlProxyReportVec(iFile).fileName = fileList{iFile}; %#ok<*AGROW>
49  SHtmlProxyReportVec(iFile).fullFileName = fullFileNameList{iFile};
50  %
51  SHtmlProxyReportVec(iFile).lineNumber = [];
52  SHtmlProxyReportVec(iFile).lineMessage = {};
53  %
54  SMlintProblemVec = reportList{iFile};
55  for iProblem = 1:numel(SMlintProblemVec)
56  ln = SMlintProblemVec(iProblem).message;
57  ln = code2html(ln);
58  for iLine = 1:numel(SMlintProblemVec(iProblem).line)
59  SHtmlProxyReportVec(iFile).lineNumber(end+1) = ...
60  SMlintProblemVec(iProblem).line(iLine);
61  SHtmlProxyReportVec(iFile).lineMessage{end+1} = ln;
62  end
63  end
64  %
65  % Now sort the list by line number
66  if ~isempty(SHtmlProxyReportVec(iFile).lineNumber)
67  lineNum = [SHtmlProxyReportVec(iFile).lineNumber];
68  lineMsg = SHtmlProxyReportVec(iFile).lineMessage;
69  [~, ndx] = sort(lineNum);
70  lineNum = lineNum(ndx);
71  lineMsg = lineMsg(ndx);
72  SHtmlProxyReportVec(iFile).lineNumber = lineNum;
73  SHtmlProxyReportVec(iFile).lineMessage = lineMsg;
74  end
75 
76 end
77 %
78 % Limit the number of messages displayed to keep from being overwhelmed by
79 % large pathological files.
80 DISPLAY_LIMIT = 500;
81 %
82 % Now generate the HTML
83 dirListExpr=mxberry.core.cell.cellstr2expression(dirList);
84 rerunAction = sprintf(...
85  'mxberry.dev.MLintScanner.scanWithHtmlReport(%s,''%s'')',...
86  dirListExpr,patternToExclude);
87 s = makeReportHeader(reportName, rerunAction);
88 %
89 s{end+1} = '<table cellspacing="0" cellpadding="2" border="0">';
90 for n = 1:length(SHtmlProxyReportVec)
91  encodedFileName = urlencode(SHtmlProxyReportVec(n).fullFileName);
92  decodedFileName = urldecode(encodedFileName);
93  %
94  s{end+1} = '<tr><td valign="top" class="td-linetop">';
95  openInEditor = sprintf('edit(''%s'')',decodedFileName);
96  regExpRep = sprintf('%s', SHtmlProxyReportVec(n).fileName);
97  %
98  s{end+1} = ['<a href="matlab:' openInEditor '">'];
99  s{end+1} = sprintf('<span class="mono">');
100  s{end+1} = regExpRep;
101  s{end+1} = sprintf('</span> </a> </br>');
102  %
103  if isempty(SHtmlProxyReportVec(n).lineNumber)
104  msgStr = '<span class="soft"> No Messages </span>';
105  elseif length(SHtmlProxyReportVec(n).lineNumber)==1
106  msgStr = '<span class="warning"> 1 message </span>';
107  elseif length(SHtmlProxyReportVec(n).lineNumber) < DISPLAY_LIMIT
108  msgStr = ['<span class="warning">',...
109  sprintf('%d messages',length(SHtmlProxyReportVec(n).lineNumber)),...
110  '</span>'];
111  else
112  % Truncate the list of messages if there are too many.
113  msgStr = ['<span class="warning">',...
114  sprintf('%d messages',length(SHtmlProxyReportVec(n).lineNumber)), ...
115  '\n<br/>' ...
116  sprintf('Showing only first %d',DISPLAY_LIMIT),'</span>'];
117  end
118  s{end+1} = sprintf('%s</td><td valign="top" class="td-linetopleft">',msgStr);
119  %
120  if ~isempty(SHtmlProxyReportVec(n).lineNumber)
121  for m = 1:min(length(SHtmlProxyReportVec(n).lineNumber),DISPLAY_LIMIT)
122 
123  openMessageLine = sprintf('opentoline(''%s'',%d)',...
124  decodedFileName, SHtmlProxyReportVec(n).lineNumber(m));
125  %
126  lineNum = sprintf('%d', SHtmlProxyReportVec(n).lineNumber(m));
127  lineMsg = sprintf('%s',SHtmlProxyReportVec(n).lineMessage{m});
128  %
129  s{end+1} = sprintf('<span class="mono">');
130  s{end+1} = ['<a href="matlab:' openMessageLine '">'];
131  s{end+1} = lineNum;
132  s{end+1} = sprintf('</a> ');
133  s{end+1} = lineMsg;
134  s{end+1} = sprintf('</span> <br/>');
135  end
136  end
137  s{end+1} = '</td></tr>';
138 end
139 %
140 s{end+1} = '</table>';
141 s{end+1} = '</body></html>';
142 %
143 if nargout==0
144  sOut = [s{:}];
145  web(['text://' sOut],'-noaddressbox');
146 else
147  htmlOut = s;
148 end
149 end
150 function htmlOut = makeReportHeader( reportName,rerunAction)
151 htmlOut = {};
152 
153 %% XML information
154 h1 = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
155 h2 = '<html xmlns="http://www.w3.org/1999/xhtml">';
156 encoding = 'UTF-8';
157 h3 = sprintf('<head><meta http-equiv="Content-Type" content="text/html; charset=%s" />',encoding);
158 %% Add cascading style sheet link
159 reportdir = fullfile(matlabroot,'toolbox','matlab','codetools','+internal','+matlab','+codetools','+reports');
160 cssfile = fullfile(reportdir,'matlab-report-styles.css');
161 h4 = sprintf('<link rel="stylesheet" href="file:///%s" type="text/css" />', cssfile);
162 
163 jsfile = fullfile(reportdir,'matlabreports.js');
164 h5 = sprintf('<script type="text/javascript" language="JavaScript" src="file:///%s"></script>',jsfile);
165 
166 %% HTML header
167 htmlOut{1} = [h1 h2 h3 h4 h5];
168 
169 htmlOut{2} = sprintf('<title>%s</title>', reportName);
170 htmlOut{3} = '</head>';
171 htmlOut{4} = '<body>';
172 htmlOut{5} = sprintf('<div class="report-head">%s</div><p>', reportName);
173 
174 
175 %% Descriptive text
176 htmlOut{end+1} = '<table border="0"><tr>';
177 htmlOut{end+1} = '<td>';
178 htmlOut{end+1} = sprintf('<input type="button" value="%s" id="rerunThisReport" onclick="runreport(''%s'');" />',...
179 'Rerun This Report', escape(rerunAction));
180  htmlOut{end+1} = '</td>';
181 end
182 function escapedAction = escape(action)
183  escapedAction = regexprep(action,'[\\'']','\\$0');
184  char(com.mathworks.mlwidgets.html.HTMLUtils.encodeUrl(escapedAction));
185 end
function filesep()
function scan(in dirNameList, in pathPatternToExclude)