1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
4+ using System . IO ;
5+ using System . Diagnostics ;
6+ using System . Threading . Tasks ;
7+ using System . Text . RegularExpressions ;
8+
9+ namespace NimrodSharp
10+ {
11+ public enum errTypes
12+ {
13+ unknown ,
14+ XDeclaredButNotUsed
15+ }
16+ public enum CheckReplyType
17+ {
18+ Hint ,
19+ Warning ,
20+ Error ,
21+ Fatal ,
22+ Unknown
23+ }
24+ public class CheckReply
25+ {
26+ public CheckReplyType type ;
27+ public errTypes message ;
28+ public string messageString ;
29+ public string filePath ;
30+ public int row ;
31+ public int col ;
32+ public int rowend ;
33+ public int colend ;
34+
35+ }
36+ public static class checkfuncs
37+ {
38+ private static string findIdentifier ( string message )
39+ {
40+ var firstidx = message . IndexOf ( '\' ' ) ;
41+ var lastidx = message . IndexOf ( '\' ' , firstidx + 1 ) ;
42+ var ident = message . Substring ( firstidx + 1 , lastidx - firstidx - 1 ) ;
43+ var dotidx = ident . IndexOf ( '.' ) ;
44+ if ( dotidx != - 1 )
45+ {
46+ ident = ident . Substring ( dotidx ) ;
47+ }
48+ return ident ;
49+ }
50+ private static ProcessStartInfo CreateStartInfo ( string filename , string rootDir )
51+ {
52+ ProcessStartInfo rv = new ProcessStartInfo ( "nimrod" ) ;
53+ rv . WorkingDirectory = rootDir ;
54+ rv . Arguments = "--path:" + rootDir + " --verbosity:0 check " + filename ;
55+ rv . WorkingDirectory = Path . GetDirectoryName ( filename ) ;
56+ rv . CreateNoWindow = true ;
57+ rv . UseShellExecute = false ;
58+ rv . RedirectStandardError = true ;
59+ rv . RedirectStandardInput = true ;
60+ rv . RedirectStandardOutput = true ;
61+ return rv ;
62+ }
63+ private static void addEndInformation ( CheckReply reply )
64+ {
65+ switch ( reply . message )
66+ {
67+ case errTypes . unknown :
68+ break ;
69+ case errTypes . XDeclaredButNotUsed :
70+ var ident = findIdentifier ( reply . messageString ) ;
71+ reply . colend = reply . colend + ident . Length ;
72+ break ;
73+ default :
74+ break ;
75+ }
76+ }
77+ private static CheckReply ParseLine ( Match match , string rootDir )
78+ {
79+ CheckReply rv = new CheckReply ( ) ;
80+ rv . filePath = match . Groups [ 1 ] . Value ;
81+ if ( ! Path . IsPathRooted ( rv . filePath ) )
82+ {
83+ rv . filePath = Path . Combine ( rootDir , rv . filePath ) ;
84+ }
85+ rv . row = int . Parse ( match . Groups [ 2 ] . Value ) - 1 ;
86+ rv . col = int . Parse ( match . Groups [ 3 ] . Value ) ;
87+ rv . rowend = rv . row ;
88+ rv . colend = rv . col + 1 ;
89+ if ( match . Groups [ 4 ] . Value == "Hint" )
90+ {
91+ rv . type = CheckReplyType . Warning ;
92+ }
93+ else if ( match . Groups [ 4 ] . Value == "Error" )
94+ {
95+ rv . type = CheckReplyType . Error ;
96+ }
97+ else
98+ {
99+ rv . type = CheckReplyType . Unknown ;
100+ }
101+ var result = Enum . TryParse < errTypes > ( match . Groups [ 6 ] . Value , out rv . message ) ;
102+ if ( ! result )
103+ {
104+ rv . message = errTypes . unknown ;
105+ }
106+ rv . messageString = match . Groups [ 5 ] . Value ;
107+ addEndInformation ( rv ) ;
108+ return rv ;
109+ }
110+
111+ private static IEnumerable < CheckReply > ParseReply ( string reply , string rootDir )
112+ {
113+ var rv = new List < CheckReply > ( ) ;
114+ var regex = new Regex ( @"(.+\.nim)\((\d+), (\d+)\) (.+?): (.+) \[(.+)\]" ) ;
115+
116+ var matches = regex . Matches ( reply ) ;
117+ foreach ( Match match in matches )
118+ {
119+ rv . Add ( ParseLine ( match , rootDir ) ) ;
120+ }
121+ return rv ;
122+ }
123+
124+
125+ public static IEnumerable < CheckReply > CheckFile ( string filename , string projectRoot )
126+ {
127+ var startInfo = CreateStartInfo ( filename , projectRoot ) ;
128+ startInfo . WorkingDirectory = projectRoot ;
129+ var proc = Process . Start ( startInfo ) ;
130+ string result = proc . StandardOutput . ReadToEnd ( ) ;
131+ proc . WaitForExit ( ) ;
132+ return ParseReply ( result , Path . GetDirectoryName ( filename ) ) ;
133+ }
134+ }
135+ }
0 commit comments