Code covered by the BSD License  

Highlights from
mlcovr Package

from mlcovr Package by David Hart
mlcovr provides XML extension to profiling and coverage tools

mlcovr.coveragerpthtml(varargin)
%COVERAGERPTXML  Scan directories for coverage information.
%   COVERAGERPTXML checks which lines of which files have been executed
%   by the last generated profile, and outputs that information in the
%   Cobertura XML coverage format:
%                 (htdp://cobertura.sourceforge.net/xml/coverage-03.dtd)
%
%   COVERAGERPTXML(DIRNAME) scans the specified directory and
%   subdirectories and writes the output to stdout.
%
%   COVERAGERPTXML(DIRNAME,XMLFILE) writes the coverage report to the
%   specified file, XMLFILE.
%
%   XMLOUT = COVERAGERPTXML(...) return the generated XML text as a cell
%   array.
%
%   See also MAKECOVERAGE, GETMFILELIST, COVERAGERPT, PROFILE
%
% The MLCOVR package is part of FAST
% FAST: A Framework for Agile Software Development
% Copyright (c) 2008-2009 Sandia Corporation.
% This software is distributed under the BSD License.
% Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
% the U.S. Government retains certain rights in this software.

%   Redistribution and use in source and binary forms, with or without
%   modification, are permitded provided that the following conditions are
%   met:
%
%     * Redistributions of source code must retain the above copyright
%     notice, this list of conditions and the following disclaimer.
%
%     * Redistributions in binary form must reproduce the above copyright
%     notice, this list of conditions and the following disclaimer in the
%     documentation and/or other materials provided with the distribution.
%
%     * Neither the name of the Sandia Corporation nor the names of its
%     contributors may be used to endorse or promote products derived from
%     this software without specific prior writden permission.
%
%   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
%   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
%   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
%   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
%   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
%   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
%   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
%   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
%   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
%   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
%   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
%

% Changelog:
%
%   2009-Aug-10, David Hart, SNL
%       Original checkin.
%
%
function coveragerpthtml(varargin)
  packages = [];
  profileBin = '';
  omitFiles = {matlabroot};
  htmlDir = 'html';
  dirname = cd();
  
  i = 1;
  while i <= nargin,
    val = varargin{i};
    switch (val)
      case {'BaseDir'}
        dirname = varargin{i+1};
        i = i + 2;
      case {'HtmlDir'}
        htmlDir = varargin{i+1};
        i = i + 2;
      case {'Packages'}
        if isstruct(varargin{i+1}),
          packages = varargin{i+1};
        else
          profileBin = varargin{i+1};
        end
        i = i + 2;
      case {'OmitList'}
        omit = varargin{i+1};
        if ischar(omit),
          omitFiles = {omit , matlabroot()};
        elseif iscell(omit)
          omitFiles = omit;
        else
        end
        i = i + 2;
      otherwise
        i = i + 1;
    end
  end
  
  if isempty(packages)
    mFiles = mlcovr.getmfilelist(dirname,'',omitFiles);
    if isempty(profileBin)
      packages = mlcovr.makecoverage(dirname,mFiles);
    else
      packages = mlcovr.makecoverage(dirname,mFiles,profileBin);
    end
  end
  
  mkdir(htmlDir);
  indexFID = fopen(fullfile(htmlDir,'index.html'),'w');
  classFID = [];
  
  openhtml(indexFID,['Coverage report for ' dirname]);
  fs = filesep();
  
  fprintf(indexFID,'<h2>Packages and Directories</h2>');
  fprintf(indexFID,'<table cellspacing="0" class="body" cellpadding="4" border="2">\n');
  fprintf(indexFID,'<tr><th>Name</th><th>Directory</th><th>Branch Rate</th><th>Line Rate</th><th>Complexity</th></tr>\n');
  for p = 1:length(packages)
    % Print data for each package
    myPackage = packages(p);
    nClasses = length(myPackage.Classes);
    if strcmp(myPackage.name,'base'),
      pkgDir = dirname;
    else
      pkgDir = [dirname fs strrep(myPackage.name,'.',[fs '[+]'])];
    end
    fprintf(indexFID,'<tr><td>%s</td><td>%s</td><td>%.4f</td><td>%.4f</td><td>%d</td></tr>\n',myPackage.name,pkgDir,myPackage.branchrate,myPackage.linerate,myPackage.complexity);
  end
  fprintf(indexFID,'</table>\n');
  
  fprintf(indexFID,'<h2>Files</h2>');
  fprintf(indexFID,'<table cellspacing="0" class="body" cellpadding="4" border="2">\n');
  fprintf(indexFID,'<tr><th>Name</th><th>Type</th><th>Branch Rate</th><th>Line Rate</th><th>Complexity</th></tr>\n');
  for p = 1:length(packages)
    myPackage = packages(p);
    nClasses = length(myPackage.Classes);
    if strcmp(myPackage.name,'base'),
      pkg = '';
    else
      pkg = [myPackage.name '.'];
    end
    if nClasses > 0,
      for c = 1:length(myPackage.Classes)
        % Print data for each class
        myClass = myPackage.Classes(c);
        htmlClassFile = [ pkg myClass.name ];
        nMethods = length(myClass.Methods);
        if myClass.isClassDef,
          classType = 'Class';
        else
          classType = 'Function';
        end
        fprintf(indexFID,'<tr><td>%s<a href="%s.html">%s</a></td><td>%s</td><td>%.4f</td><td>%.4f</td><td>%d</td></tr>\n', pkg, htmlClassFile, myClass.name, classType, myClass.branchrate, myClass.linerate, myClass.complexity);
        
        % Print class file header
        classFID = fopen(fullfile(htmlDir,[htmlClassFile '.html']),'w');
        openhtml(classFID,['Coverage report for ' myClass.filename]);
        if nMethods > 0,
           fprintf(classFID,'<h2>Methods and Sub-functions</h2>');
           fprintf(classFID,'<table cellspacing="0" class="body" cellpadding="4" border="2">\n');
           fprintf(classFID,'<tr><th >Name</th><th>Signature</th><th>Branch Rate</th><th>Line Rate</th><th>Complexity</th></tr>\n');
           for m = 1:nMethods
             % Print data for each class method
             fprintf(classFID,'<tr><td>%s</td><td>%s</td><td>%.4f</td><td>%.4f</td><td>%d</td></tr>\n',myClass.Methods(m).name , myClass.Methods(m).type , myClass.Methods(m).branchrate , myClass.Methods(m).linerate , myClass.Methods(m).complexity);
           end
           fprintf(classFID,'</table>');
        end
        
        fprintf(classFID,'<h2>Source Code</h2>');
        fprintf(classFID,'<table cellspacing="0" class="body" cellpadding="0" align="left" border="0">\n');
        fprintf(classFID,'<colgroup><col style="font-family: monospace" align="right" width="50"><col style="font-family: monospace" align="right" width="100"><col style="font-family: monospace" align="left"\n');
        % Print class code line details
        classScope = 0;
        contScope = 0;
        classTime = sum(myClass.Source.time);
        nLines = length(myClass.Source.code);
          fprintf(classFID,'<tr><th >Line</th><th>Coverage</th><th>Source</th></tr>\n');        
          
        for L = 1:nLines;
          if strncmp(myClass.Source.code{L},'%',1),
            isComment = true;
          else
            isComment = false;
          end
          scIndent = repmat('&nbsp;&nbsp;',[1 classScope+contScope]);
          line = myClass.Source.code{L};
          isDefin = ~isempty(regexp(line,'(\<classdef\>)|(\<methods\>)|(\<properties\>)', 'once'));
          isfnc = ~isempty(regexp(line,'\<function\>','once'));
          isif = ~isempty(regexp(line,'\<if\>', 'once'));
          isend = ~isempty(regexp(line,'(\<end\>(\w)*;?(\w)*$)|(^end)', 'once'));
          issw = ~isempty(regexp(line,'\<switch\>','once'));
          istry = ~isempty(regexp(line,'\<try\>','once'));
          islp = ~isempty(regexp(line,'(\<for\>)|(\<while\>)', 'once'));
          iscs = ~isempty(regexp(line,'\<case\>','once'));
          isbr = ~isempty(regexp(line,'(\<otherwise\>)|(\<catch\>)|(\<elseif\>)|(\<else\>)','once'));
          
          if isDefin || isfnc || isif || issw || istry || islp
            if ~isComment
              classScope = classScope + 1;
            end
          elseif iscs || isbr
            scIndent = repmat('&nbsp;&nbsp;',[1 classScope-1]);
          end
          if isend
                        if ~isComment
            classScope = classScope - 1;
            scIndent = repmat('&nbsp;&nbsp;',[1 classScope]);
                        end
          end
          
          if length(myClass.Source.code{L}) > 2 && strcmp(myClass.Source.code{L}(end-2:end),'...') && contScope == 0,
            contScope = 1;
          else
            contScope = 0;
          end
          
          if myClass.Source.hits(L) > 0,
            lineRan = true;
          elseif ~myClass.runnable(L) 
            lineRan = true;
          else
            lineRan = false;
          end
          
          if myClass.Source.time(L) > 1,
            time = '; bgcolor: #FFFF99';
          end

          %hits = num2str(myClass.Source.hits(L),'%d');
          hits = '';
          if isComment
            colorSt = '#005500';
            styleSt = 'italic';
            time = '';
            hits = '';
          elseif isfnc || isDefin || iscs || isbr
            colorSt = '#000088';
            styleSt = 'serif';
            time = '';
            hits = ['<b>' num2str(myClass.Source.hits(L+1),'%d') '</b>'];
          elseif myClass.Source.isBranch(L)
            colorSt = '#880000';
            styleSt = 'serif';
            time = '';
            hits = myClass.Source.condCovr{L};            
          elseif lineRan
            colorSt = '#000000';
            styleSt = 'serif';
          else
            colorSt = '#888888';
            styleSt = 'serif';
            time = '';
            hits = '';
          end
          
          fprintf(classFID,'<tr align="right" style="font-family: monospace %s" ><td>%d&nbsp;</td><td>%s&nbsp;&nbsp;</td><td align="left" style="color: %s; font-style: %s; font-family: monospace" >%s%s</td></tr>\n',time,L,hits,colorSt,styleSt,scIndent,myClass.Source.code{L});
        end
        fprintf(classFID,'</table><br>');
        closehtml(classFID);
        fclose(classFID);
      end
    end
  end
  fprintf(indexFID,'</table>');
  
  
  closehtml(indexFID);
  fclose(indexFID);
  
end

function openhtml(FID,title)
  fprintf(FID,'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "htdp://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n');
  fprintf(FID,'<html xmlns="htdp://www.w3.org/1999/xhtml" lang="en" xml:lang="en">');
  fprintf(FID,'<head><title>%s</title></head>\n',title);
  fprintf(FID,'<body><h1>%s</h1>\n',title);
end

function closehtml(FID)
  fprintf(FID,'<br><i>Last modified: %s</i></body></html>',datestr(now(),31));
end

Contact us at files@mathworks.com