using System; using System.IO; using System.Text; using System.Text.RegularExpressions; using System.Xml; using NAnt.Core; using NAnt.Core.Attributes; using NAnt.Core.Types; namespace ASPCommenter { /// /// NAnt task to extract XML comments from ASP files /// [TaskName("getcomment")] public class ExtractCommentTask : Task { private FileSet m_fileset = new FileSet(); private FileInfo m_output; private string m_basedir = @"\"; private Encoding m_enc = Encoding.GetEncoding(1252); /// /// Get or set the file to extract comment from /// [BuildElement("fileset", Required=true)] public FileSet Fileset { get { return m_fileset; } } /// /// Get or set the output XML file to write comments to /// [TaskAttribute("output", Required=true)] public FileInfo Output { get { return m_output; } set { m_output = value; } } /// /// The base directory where the code is localted. Relative to the project base /// directory. /// [TaskAttribute("basedir")] public FileInfo BaseDirectory { get { return m_output; } set { m_output = value; } } protected override void ExecuteTask() { ExtractComment(); } public void ExtractComment() { XmlTextWriter writer = new XmlTextWriter(m_output.FullName, m_enc); Log(Level.Info, "Extracting comments"); writer.WriteStartDocument(); writer.WriteStartElement("doc"); foreach(string file in m_fileset.FileNames) { ExtractComment(file, ref writer); } writer.WriteEndDocument(); writer.Close(); } public void ExtractComment(string file, ref XmlTextWriter writer) { Regex rxComment = new Regex("(''').*\n"); Regex rxLine = new Regex(".*\n"); Regex rxDeclaration = new Regex("(sub|function).*[a-z].*\n"); MatchCollection matches; StreamReader reader = new StreamReader(file, m_enc); string content; string comment = ""; string declaration; string nextLine; string relativeFile = file.Replace(Project.BaseDirectory + m_basedir, ""); Log(Level.Info, "\tFrom {0}", relativeFile, m_output.FullName); content = reader.ReadToEnd(); reader.Close(); matches = rxComment.Matches(content); writer.WriteStartElement("file"); writer.WriteAttributeString("path", relativeFile); foreach(Match m in matches) { comment += m.Value.Substring(4, m.Length - 4); nextLine = rxLine.Match(content, m.Index + m.Length).Value; if (rxDeclaration.IsMatch(nextLine)) { declaration = rxDeclaration.Match(nextLine).Value; declaration = declaration.Remove(declaration.Length - 2, 2); try { CheckXml(comment); writer.WriteStartElement("member"); writer.WriteAttributeString("signature", declaration); writer.WriteRaw(comment); writer.WriteEndElement(); } catch (XmlException ex) { Log(Level.Error, "\t\tInvalid XML in {0} comments : {1}", declaration, ex.Message); } comment = ""; declaration = ""; } } writer.WriteEndElement(); } private void CheckXml(string xml) { XmlValidatingReader vr = new XmlValidatingReader(xml, XmlNodeType.Element, null); while(vr.Read()) {} vr.Close(); } } }