8 people like it.

Count noise-lines in C# code

This is the code I used to generate this pie chart: http://pic.twitter.com/PgPEFByg56 Enough said?

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
open System
open System.IO
open System.Text.RegularExpressions
open MSDN.FSharp.Charting
open System.Windows.Forms

(SafeEnumerateFiles hidden for clarity)

/// Return all the lines in files matching the given wildcard starting at the given path.
let FileLines path wildcard =
    SafeEnumerateFiles path wildcard
    |> Seq.map (fun fileName -> File.ReadAllLines(fileName))
    |> Seq.concat
    
/// Break down the sequence giving counts of lines matching each regex pattern.
let CountByPattern patterns lines =
    seq { for pattern in patterns do
              yield lines
                    |> Seq.filter (fun line -> Regex.IsMatch(line, pattern))
                    |> Seq.length
    }

/// Break down the given lines into counts by pattern, associating each count with a label.
let Analyze patternsLabels lines =
    let patterns, labels =
        patternsLabels |> Array.map fst,
        patternsLabels |> Array.map snd

    lines
    |> CountByPattern patterns
    |> Seq.zip labels

// Example:
// > AnalyzeCSharp @"D:\MyCode";;
// val it : (string * int) [] =
//   [|("{ or }", 25128); ("Blank", 18261); ("Null checks", 877);
//     ("Comments", 27103); ("Useful lines", 61343)|]
// > 

/// Analyze C# files starting at the given path, showing various forms of noise.
let AnalyzeCSharp path = 
    let lines = FileLines path "*.cs" |> Seq.cache
    let patternCounts = 
        lines
        |> Analyze [|
                       "(^([ \t]*)([{}])([ \t]*)$)",  "{ or }"
                       "(^[ \t]*$)",                  "Blank"
                       "(\=[ \t]*null)",              "Null checks"
                       "(^[ \t]*//)",                 "Comments"
                   |]
    let otherCount =  ["Useful lines", (lines |> Seq.length) - (patternCounts |> Seq.sumBy snd)]

    Seq.append patternCounts otherCount
    |> Array.ofSeq

/// Show an FSharp chart in a Windows form.
let Show chart =
    let form = new Form(Visible=true, TopMost=true, Width=700, Height=700)
    let ctl = new ChartControl(chart, Dock=DockStyle.Fill)
    form.Controls.Add(ctl)

/// Show an array of strings and ints as a labelled pie chart.
let ToPie name (results : array<string*int>) =
    FSharpChart.Pie(results, Name = name)
    |> Show
namespace System
namespace System.IO
namespace System.Text
namespace System.Text.RegularExpressions
namespace Microsoft.FSharp
namespace System.Windows
namespace System.Windows.Forms
/// Enumerate files starting at a given path, having a given wildcard.
/// (Inaccessible directories are ignored.)
let SafeEnumerateFiles (path : string) (wildcard: string) =
    let safeEnumerate f path =
        try
            f(path)
        with
            | :? System.UnauthorizedAccessException -> Seq.empty

    let enumerateDirs =
        safeEnumerate Directory.EnumerateDirectories

    let enumerateFiles =
        safeEnumerate (fun path -> Directory.EnumerateFiles(path, wildcard))

    let rec enumerate baseDir =
        seq {
            yield! enumerateFiles baseDir
        
            for dir in enumerateDirs baseDir do
                yield! enumerate dir
        }

    enumerate path
val FileLines : path:string -> wildcard:string -> seq<string>

Full name: Script.FileLines


 Return all the lines in files matching the given wildcard starting at the given path.
val path : string
val wildcard : string
val SafeEnumerateFiles : path:string -> wildcard:string -> seq<string>

Full name: Script.SafeEnumerateFiles


 Enumerate files starting at a given path, having a given wildcard.
 (Inaccessible directories are ignored.)
module Seq

from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val fileName : string
type File =
  static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
  static member AppendAllText : path:string * contents:string -> unit + 1 overload
  static member AppendText : path:string -> StreamWriter
  static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
  static member Create : path:string -> FileStream + 3 overloads
  static member CreateText : path:string -> StreamWriter
  static member Decrypt : path:string -> unit
  static member Delete : path:string -> unit
  static member Encrypt : path:string -> unit
  static member Exists : path:string -> bool
  ...

Full name: System.IO.File
File.ReadAllLines(path: string) : string []
File.ReadAllLines(path: string, encoding: Text.Encoding) : string []
val concat : sources:seq<#seq<'T>> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.concat
val CountByPattern : patterns:seq<string> -> lines:seq<string> -> seq<int>

Full name: Script.CountByPattern


 Break down the sequence giving counts of lines matching each regex pattern.
val patterns : seq<string>
val lines : seq<string>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val pattern : string
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.filter
val line : string
Multiple items
type Regex =
  new : pattern:string -> Regex + 1 overload
  member GetGroupNames : unit -> string[]
  member GetGroupNumbers : unit -> int[]
  member GroupNameFromNumber : i:int -> string
  member GroupNumberFromName : name:string -> int
  member IsMatch : input:string -> bool + 1 overload
  member Match : input:string -> Match + 2 overloads
  member Matches : input:string -> MatchCollection + 1 overload
  member Options : RegexOptions
  member Replace : input:string * replacement:string -> string + 5 overloads
  ...

Full name: System.Text.RegularExpressions.Regex

--------------------
Regex(pattern: string) : unit
Regex(pattern: string, options: RegexOptions) : unit
Regex.IsMatch(input: string, pattern: string) : bool
Regex.IsMatch(input: string, pattern: string, options: RegexOptions) : bool
val length : source:seq<'T> -> int

Full name: Microsoft.FSharp.Collections.Seq.length
val Analyze : patternsLabels:(string * 'a) [] -> lines:seq<string> -> seq<'a * int>

Full name: Script.Analyze


 Break down the given lines into counts by pattern, associating each count with a label.
val patternsLabels : (string * 'a) []
val patterns : string []
val labels : 'a []
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val zip : source1:seq<'T1> -> source2:seq<'T2> -> seq<'T1 * 'T2>

Full name: Microsoft.FSharp.Collections.Seq.zip
val AnalyzeCSharp : path:string -> (string * int) []

Full name: Script.AnalyzeCSharp


 Analyze C# files starting at the given path, showing various forms of noise.
val cache : source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.cache
val patternCounts : seq<string * int>
val otherCount : (string * int) list
val sumBy : projection:('T -> 'U) -> source:seq<'T> -> 'U (requires member ( + ) and member get_Zero)

Full name: Microsoft.FSharp.Collections.Seq.sumBy
val append : source1:seq<'T> -> source2:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.append
val ofSeq : source:seq<'T> -> 'T []

Full name: Microsoft.FSharp.Collections.Array.ofSeq
val Show : chart:'a -> unit

Full name: Script.Show


 Show an FSharp chart in a Windows form.
val chart : 'a
val form : Form
Multiple items
type Form =
  inherit ContainerControl
  new : unit -> Form
  member AcceptButton : IButtonControl with get, set
  member Activate : unit -> unit
  member ActiveMdiChild : Form
  member AddOwnedForm : ownedForm:Form -> unit
  member AllowTransparency : bool with get, set
  member AutoScale : bool with get, set
  member AutoScaleBaseSize : Size with get, set
  member AutoScroll : bool with get, set
  member AutoSize : bool with get, set
  ...
  nested type ControlCollection

Full name: System.Windows.Forms.Form

--------------------
Form() : unit
val ctl : Control
type DockStyle =
  | None = 0
  | Top = 1
  | Bottom = 2
  | Left = 3
  | Right = 4
  | Fill = 5

Full name: System.Windows.Forms.DockStyle
field DockStyle.Fill = 5
property Control.Controls: Control.ControlCollection
Control.ControlCollection.Add(value: Control) : unit
val ToPie : name:'a -> results:(string * int) array -> unit

Full name: Script.ToPie


 Show an array of strings and ints as a labelled pie chart.
val name : 'a
val results : (string * int) array
type 'T array = 'T []

Full name: Microsoft.FSharp.Core.array<_>
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>

More information

Link:http://fssnip.net/h4
Posted:4 years ago
Author:Kit Eason
Tags: c# , regex