⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nantoutputparser.cs

📁 c#源代码
💻 CS
字号:
//
// SharpDevelop NAnt add-in.
//
// Copyright (C) 2004 Matthew Ward
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// Matthew Ward (mrward@users.sourceforge.net)


using ICSharpCode.SharpDevelop.Services;
using System;
using System.IO;
using System.Text.RegularExpressions;

namespace ICSharpCode.NAntAddIn
{
	/// <summary>
	/// Utility class that parses the console output from NAnt.
	/// </summary>
	public class NAntOutputParser
	{
		NAntOutputParser()
		{
		}
		
		/// <summary>
		/// Parses the NAnt console output and extracts a set of 
		/// Tasks.
		/// </summary>
		/// <param name="output">The NAnt console output to parse.</param>
		/// <returns>A <see cref="TaskCollection"/>.</returns>
		public static TaskCollection Parse(string output)
		{
			TaskCollection tasks = new TaskCollection();
			
			output = output.Replace("\r\n", "\n");
			
			// Look for errors on a per line basis.
			Task task = null;
			StringReader reader = new StringReader(output);
			while (reader.Peek() != -1) {
				
				string currentLine = reader.ReadLine();
				if (currentLine.StartsWith("BUILD FAILED")) {
				    break;
				}
				
				task = ParseLine(currentLine);
				if (task != null) {
					tasks.Add(task);
				}
			}
			reader.Close();
						
			// Look for multiline build errors.
			task = ParseMultilineBuildError(output);
			if (task != null) {
				tasks.Add(task);
			}
			
			// Look for NAnt build failed.
			task = ParseNAntBuildFailedError(output);
			if (task != null) {
				tasks.Add(task);
			}
				
			return tasks;
		}
		
		/// <summary>
		/// Parses a single line of text looking for errors.
		/// </summary>
		/// <param name="textLine">A NAnt output line.</param>
		/// <returns>A <see cref="Task"/> if the line contains an error or 
		/// a warning; otherwise <see langword="null"/>.</returns>
		static Task ParseLine(string textLine)
		{
			Task task = null;
			
			task = ParseCSharpError(textLine);
			
			if (task == null) {
				task = ParseVBError(textLine);
			}
			
			if (task == null) {
				task = ParseFatalError(textLine);
			}
			
			if (task == null) {
				task = ParseVBFatalError(textLine);
			}
			
			if (task == null) {
				task = ParseNAntWarning(textLine);
			}
			if (task == null) {
				task = ParseNAntError(textLine);
			}
			
			return task;
		}
		
		/// <summary>
		/// Looks for errors of the form 
		/// "C:/MyProject/MyProject.build(40,3): error CS1000: An error occurred."
		/// </summary>
		/// <param name="textLine">The line of text to parse.</param>
		/// <returns>A <see cref="Task"/> if an error was found; otherwise
		/// <see langword="null"/>.</returns>
		static Task ParseCSharpError(string textLine)
		{
			Task task = null;
			Match match = Regex.Match(textLine, @"^.*?(\w+:[/\\].*?)\(([\d]*),([\d]*)\): (.*?) (.*?): (.*?)$");
			if (match.Success) {
				try	{
					// Take off 1 for line/col since SharpDevelop is zero index based.
					int line = Convert.ToInt32(match.Groups[2].Value) - 1;
					int col = Convert.ToInt32(match.Groups[3].Value) - 1;                     
					string description = String.Concat(match.Groups[6].Value, " (", match.Groups[5], ")");
					
					TaskType taskType = TaskType.Error;
					if (String.Compare(match.Groups[4].Value, "warning", true) == 0) {
						taskType = TaskType.Warning;
					}
					task = new Task(match.Groups[1].Value, description, col, line, taskType);
				} catch (Exception) {
					// Ignore.
				}
			}
			
			return task;
		}
		
		/// <summary>
		/// Looks for errors of the form 
		/// "C:/MyProject/MyProject.build(40,3): ifnot is deprecated."
		/// </summary>
		/// <param name="textLine">The line of text to parse.</param>
		/// <returns>A <see cref="Task"/> if an error was found; otherwise
		/// <see langword="null"/>.</returns>
		static Task ParseNAntError(string textLine)
		{
			Task task = null;
			
			Match match = Regex.Match(textLine, @"^.*?(\w+:[/\\].*?)\(([\d]*),([\d]*)\): (.*?)$");
			if (match.Success) {
				try	{
					// Take off 1 for line/col since SharpDevelop is zero index based.
					int line = Convert.ToInt32(match.Groups[2].Value) - 1;
					int col = Convert.ToInt32(match.Groups[3].Value) - 1;                     
					
					task = new Task(match.Groups[1].Value, match.Groups[4].Value, col, line, TaskType.Warning);
				} catch (Exception) {
					// Ignore.
				}
			}

			return task;
		}
		
		/// <summary>
		/// Looks for errors of the form 
		/// "C:/MyProject/MyProject.build(40): error CS1000: An error occurred."
		/// </summary>
		/// <remarks>
		/// This should handle C++ errors too.</remarks>
		/// <param name="textLine">The line of text to parse.</param>
		/// <returns>A <see cref="Task"/> if an error was found; otherwise
		/// <see langword="null"/>.</returns>
		static Task ParseVBError(string textLine)
		{
			Task task = null;
			Match match = Regex.Match(textLine, @"^.*?(\w+:[/\\].*?)\(([\d]*)\) : (.*?) (.*?): (.*?)$");
			if (match.Success) {
				try	{
					// Take off 1 for line/col since SharpDevelop is zero index based.
					int line = Convert.ToInt32(match.Groups[2].Value) - 1;
					string description = String.Concat(match.Groups[5].Value, " (", match.Groups[4], ")");
					
					TaskType taskType = TaskType.Error;
					if (String.Compare(match.Groups[3].Value, "warning", true) == 0) {
						taskType = TaskType.Warning;
					}
					task = new Task(match.Groups[1].Value, description, 0, line, taskType);
				} catch (Exception) {
					// Ignore.
				}
			}
			
			return task;
		}
		
		/// <summary>
		/// Looks for errors of the form 
		/// "fatal error CS00042: An error occurred."
		/// </summary>
		/// <param name="textLine">The line of text to parse.</param>
		/// <returns>A <see cref="Task"/> if an error was found; otherwise
		/// <see langword="null"/>.</returns>
		static Task ParseFatalError(string textLine)
		{
			Task task = null;
			Match match = Regex.Match(textLine, @"^.*?(fatal error .*?: .*?)$");
			if (match.Success) {
				try	{
					task = new Task(String.Empty, match.Groups[1].Value, 0, 0, TaskType.Error);
				} catch (Exception) {
					// Ignore.
				}
			}
			
			return task;			
		}
		
		/// <summary>
		/// Looks for errors of the form 
		/// "vbc : error BC31019: Unable to write to output file."
		/// </summary>
		/// <param name="textLine">The line of text to parse.</param>
		/// <returns>A <see cref="Task"/> if an error was found; otherwise
		/// <see langword="null"/>.</returns>
		static Task ParseVBFatalError(string textLine)
		{
			Task task = null;
			Match match = Regex.Match(textLine, @"^.*?vbc : error (.*?): (.*?)$");
			if (match.Success) {
				try	{
					string description = String.Concat(match.Groups[2].Value, " (", match.Groups[1].Value, ")");
					task = new Task(String.Empty, description, 0, 0, TaskType.Error);
				} catch (Exception) {
					// Ignore.
				}
			}
			
			return task;			
		}	
		
		/// <summary>
		/// Looks for errors of the form 
		/// "fatal error CS00042: An error occurred."
		/// </summary>
		/// <param name="textLine">The line of text to parse.</param>
		/// <returns>A <see cref="Task"/> if a warning was found; otherwise
		/// <see langword="null"/>.</returns>
		static Task ParseNAntWarning(string textLine)
		{
			Task task = null;
			Match match = Regex.Match(textLine, @"^.*?(Read-only property .*? cannot be overwritten.)$");
			if (match.Success) {
				try	{
					task = new Task(String.Empty, match.Groups[1].Value, 0, 0, TaskType.Warning);
				} catch (Exception) {
					// Ignore.
				}
			}
			
			return task;			
		}
		
		/// <summary>
		/// Looks for errors of the form 
		/// "BUILD FAILED"
		/// "[csc] C:/foo/foo.cs(5,5):"
		/// "Something bad happened."
		/// </summary>
		/// <param name="textLine">The line of text to parse.</param>
		/// <returns>A <see cref="Task"/> if an error was found; otherwise
		/// <see langword="null"/>.</returns>
		static Task ParseNAntBuildFailedError(string output)
		{
			Task task = null;
			
			Match match = Regex.Match(output, @"^BUILD FAILED.*?$\n^$\n^(\w+:[/\\].*?)\(([\d]*),([\d]*)\):$\n^(.*?)$\n^(.*?)$", RegexOptions.Multiline);
			
			if (match.Success) {
				
				try	{
					// Take off 1 for line/col since SharpDevelop is zero index based.
					int line = Convert.ToInt32(match.Groups[2].Value) - 1;
					int col = Convert.ToInt32(match.Groups[3].Value) - 1;
					string description = String.Concat(match.Groups[4], Environment.NewLine, match.Groups[5]);
					task = new Task(match.Groups[1].Value, description, col, line, TaskType.Error);
				} catch(Exception) { };
			} else {
				
				match = Regex.Match(output, @"^BUILD FAILED$\n^$\n^(.*?)$", RegexOptions.Multiline);
				
				if (match.Success) {
					task = new Task(String.Empty, match.Groups[1].Value, 0, 0, TaskType.Error);
				}
			}	
			
			return task;
		}
		
		/// <summary>
		/// Parses errors of the form.
		/// "[delete] C:\foo\foo.build(94,5):"
        /// "[delete] Cannot delete directory 'C:\foo\bin'. The directory does not exist."
 		/// </summary>
		/// <param name="textLine">The line of text to parse.</param>
		/// <returns>A <see cref="Task"/> if an error was found; otherwise
		/// <see langword="null"/>.</returns> 
		static Task ParseMultilineBuildError(string output)
		{
			Task task = null;
			
			Match match = Regex.Match(output, @"^.*?\[delete\] (\w+:[/\\].*?)\(([\d]*),([\d]*)\):$\n^.*?\[delete\] (.*?)$", RegexOptions.Multiline);
			
			if (match.Success) {
				
				try	{
					// Take off 1 for line/col since SharpDevelop is zero index based.
					int line = Convert.ToInt32(match.Groups[2].Value) - 1;
					int col = Convert.ToInt32(match.Groups[3].Value) - 1;
					string description = String.Concat(match.Groups[4]);
					task = new Task(match.Groups[1].Value, description, col, line, TaskType.Error);
				} catch(Exception) { };
			}
			
			return task;
		}		
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -