9 people like it.
Like the snippet!
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