]> git.donarmstrong.com Git - lilypond.git/blobdiff - buildscripts/coverage.py
Merge branch 'lilypond/translation' of ssh://jomand@git.sv.gnu.org/srv/git/lilypond
[lilypond.git] / buildscripts / coverage.py
index f4397e10e0eaacf0bc292db788685165b3012fc0..d44f81fdeeb8a7b0ba7328cf6e35c1b059506b7b 100644 (file)
@@ -1,4 +1,5 @@
-#!/bin/sh
+#!/usr/bin/python
+
 import os
 import glob
 import re
@@ -37,13 +38,62 @@ def summary (args):
     for (pain, d) in results:
         print '%(cov)5.2f (%(lines)6d): %(file)s' % d
 
+class Chunk:
+    def __init__ (self, range, coverage_count, all_lines, file):
+        assert coverage_count >= 0
+        assert type (range) == type (())
+        
+        self.coverage_count = coverage_count
+        self.range = range
+        self.all_lines = all_lines
+        self.file = file
+
+    def length (self):
+        return self.range[1] - self.range[0]
+
+    def text (self):
+        return ''.join ([l[2] for l in self.lines()])
+        
+    def lines (self):
+        return self.all_lines[self.range[0]:
+                              self.range[1]]
+    def widen (self):
+        self.range = (min (self.range[0] -1, 0),
+                      self.range[0] +1)
+    def write (self):
+        print 'chunk in', self.file
+        for (c, n, l) in self.lines ():
+            cov = '%d' % c
+            if c == 0:
+                cov = '#######'
+            elif c < 0:
+                cov = ''
+            sys.stdout.write ('%8s:%8d:%s' % (cov, n, l))
+            
+    def uncovered_score (self):
+        return self.length ()
+    
+class SchemeChunk (Chunk):
+    def uncovered_score (self):
+        text = self.text ()
+        if (text.startswith  ('(define ')
+            and not text.startswith ('(define (')):
+            return 0
+
+        if text.startswith  ('(use-modules '):
+            return 0
+
+        if (text.startswith  ('(define-public ')
+            and not text.startswith ('(define-public (')):
+            return 0
 
+        return len ([l for (c,n,l) in self.lines() if (c == 0)]) 
 
 def read_gcov (f):
     ls = []
 
     in_lines = [l for l in open (f).readlines ()]
-    (count_len, line_num_len) = tuple (map (len, in_lines[0].split':')[:2]))
+    (count_len, line_num_len) = tuple (map (len, in_lines[0].split (':')[:2]))
     
     for l in in_lines:
         c = l[:count_len].strip ()
@@ -52,6 +102,13 @@ def read_gcov (f):
 
         if n == 0:
             continue
+
+        if '#' in c:
+            c = 0
+        elif c == '-':
+            c = -1
+        else:
+            c = int (c)
         
         l = l[line_num_len+1:]
 
@@ -59,46 +116,82 @@ def read_gcov (f):
         
     return ls
 
-def get_chunks (ls):
+def get_c_chunks (ls, file):
     chunks = []
     chunk = []
-    for (c,n,l) in ls:
-        if '#' in c:
-            chunk.append ((n,l))
-        elif c.strip () != '-' or l == '}\n':
-            if chunk:
-                chunks.append (chunk)
+
+    last_c = -1
+    for (c, n, l) in ls:
+        if not (c == last_c or c < 0 and l != '}\n'):
+            if chunk and last_c >= 0:
+                nums = [n-1 for (n, l) in chunk]
+                chunks.append (Chunk ((min (nums), max (nums)+1),
+                                      last_c, ls, file))
                 chunk = []
+
+        chunk.append ((n,l))
+        if c >= 0:
+            last_c = c
             
     return chunks
 
-def is_exception_chunk (ch):
-    for (n,l) in ch:
-        for stat in  ('warning', 'error'):
-            if stat in l:
-                return True
-    return False
+def get_scm_chunks (ls, file):
+    chunks = []
+    chunk = []
 
-def print_chunk (ch, lines):
-    nums = [n-1 for (n, l) in ch]
-    for (c, n, l) in lines[min (nums):max (nums)+1]:
-        sys.stdout.write ('%8s:%8d:%s' % (c,n,l))
+    def new_chunk ():
+        if chunk:
+            nums = [n-1 for (n, l) in chunk]
+            chunks.append (SchemeChunk ((min (nums), max (nums)+1),
+                                        max (last_c, 0), ls, file))
+            chunk[:] = []
+        
+    last_c = -1
+    for (cov_count, line_number, line) in ls:
+        if line.startswith ('('):
+            new_chunk ()
+            last_c = -1
+        
+        chunk.append ((line_number, line))
+        if cov_count >= 0:
+            last_c = cov_count
+
+    return chunks
+
+def widen_chunk (ch, ls):
+    a -= 1
+    b += 1
 
+    return [(n, l)  for (c, n, l) in ls[a:b]]
+    
 
-def extract_uncovered (file):
+def extract_chunks (file):
     try:
         ls = read_gcov (file)
     except IOError, s :
         print s
-        return
+        return []
+        
+    cs = []
+    if 'scm' in file:
+        cs = get_scm_chunks (ls, file)
+    else:
+        cs = get_c_chunks (ls, file)
+    return cs
+
+
+def filter_uncovered (chunks):
+    def interesting (c):
+        if c.coverage_count > 0:
+            return False
         
-    cs = get_chunks (ls)
-    cs = [c for c in cs if not is_exception_chunk (c)]
-    print '\n'.join (['%d' % x for (a,x,b) in ls])
-    for c in cs:
-        print 'Uncovered chunk in', file
-        print_chunk (c, ls)
-        print '\n\n: '
+        t = c.text()
+        for stat in  ('warning', 'error', 'print', 'scm_gc_mark'):
+            if stat in t:
+                return False
+        return True
+   
+    return [c for c in chunks if interesting (c)]
     
 
 def main ():
@@ -109,6 +202,11 @@ def main ():
                   default=False,
                   dest="summary")
     
+    p.add_option ("--hotspots",
+                  default=False,
+                  action='store_true',
+                  dest="hotspots")
+    
     p.add_option ("--uncovered",
                   default=False,
                   action='store_true',
@@ -121,10 +219,30 @@ def main ():
     if options.summary:
         summary (['%s.gcov-summary' % s for s in args])
 
-    if options.uncovered:
+    if options.uncovered or options.hotspots:
+        chunks = []
         for a in args:
-            extract_uncovered ('%s.gcov' % a)
-        
+            name = a
+            if name.endswith ('scm'):
+                name += '.cov'
+            else:
+                name += '.gcov'
+            
+            chunks += extract_chunks  (name)
+
+        if options.uncovered:
+            chunks = filter_uncovered (chunks)
+            chunks = [(c.uncovered_score (), c) for c in chunks if c.uncovered_score() > 0]
+        elif options.hotspots:
+            chunks = [((c.coverage_count, -c.length()), c) for c in chunks]
+            
+            
+        chunks.sort ()
+        chunks.reverse ()
+        for (score, c) in chunks:
+            c.write ()
+
+            
         
 if __name__ == '__main__':
     main ()