* Makefile.am:
[monodevelop.git] / extras / MonoDevelop.CodeAnalysis / MonoDevelop.CodeAnalysis.Smokey / SmokeyParser.cs
blob4996d8fff26a33400cb8cb69b264fed0f7d9ea75
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.IO;
5 using System.Xml;
7 using CA = MonoDevelop.CodeAnalysis;
9 namespace MonoDevelop.CodeAnalysis.Smokey {
11 internal static class SmokeyParser {
12 private const string RuleErrorMessage = "A rule has failed to run.";
14 public static IEnumerable<IViolation> ParseOutput (StreamReader sr, IEnumerable<CA.IRule> ruleSet)
16 List<IViolation> found = new List<IViolation> ();
18 // FIXME: instead of checking each defect if its rule is in "set"
19 // we should think on making use of Smokey "ignore" feature
21 // we should only return violations with rules id in this list
22 List<string> ruleIds = new List<string> ();
23 foreach (CA.IRule rule in ruleSet)
24 ruleIds.Add (rule.Id);
26 // if assembly is big, Gendarme outputs progress bar using dots
27 // before actual xml, so we might want to need to move forward
28 while (sr.Peek () != '<')
29 sr.Read ();
31 // go!
32 using (XmlTextReader reader = new XmlTextReader (sr)) {
33 reader.WhitespaceHandling = WhitespaceHandling.None;
34 string file = string.Empty;
35 int line = 0;
37 while (reader.Read ()) {
38 if (reader.NodeType != XmlNodeType.Element)
39 continue;
41 if("Location" == reader.Name) {
42 file = reader.GetAttribute("file");
43 if(null == file){ file = string.Empty; }
44 if(!int.TryParse(reader.GetAttribute("line"), out line)){ line = 0; }
47 if (reader.Name != "Violation")
48 continue;
51 // get rule id
52 string ruleId = reader.GetAttribute ("checkID");
53 // if we don't need to check for this rule, let it go
54 if (!ruleIds.Contains (ruleId))
55 continue;
57 // parse severity (or try to)
58 CA.Severity severity = ParseSeverity (reader.GetAttribute ("severity"));
60 // parse solution and problem
61 string problem = null;
62 string solution = null;
63 while (reader.Read ()) {
64 if (reader.NodeType != XmlNodeType.Element)
65 continue;
67 if (reader.Name == "Cause")
68 problem = reader.ReadString ();
69 else if (reader.Name == "Fix")
70 solution = reader.ReadString ();
71 else if (problem != null && solution != null)
72 break;
75 // sometimes Smokey rules throw an exception
76 // we shouldn't return "dead" violations
77 if (IsErrorMessage (problem))
78 continue;
80 // go!
81 found.Add (new SmokeyViolation (ruleId, problem, solution, severity, file, line));
84 return found;
87 private static CA.Severity ParseSeverity (string value)
89 if (value == "Error")
90 return CA.Severity.High; // FIXME: or Critical?
91 else if (value == "Warning")
92 return CA.Severity.Medium;
93 else if (value == "Nitpick")
94 return CA.Severity.Low;
95 else
96 return CA.Severity.Medium; // by default?
99 private static bool IsErrorMessage (string cause)
101 return cause == RuleErrorMessage;