You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
340 lines
11 KiB
340 lines
11 KiB
// SharpDevelop samples |
|
// Copyright (c) 2007, AlphaSierraPapa |
|
// All rights reserved. |
|
// |
|
// Redistribution and use in source and binary forms, with or without modification, are |
|
// permitted provided that the following conditions are met: |
|
// |
|
// - Redistributions of source code must retain the above copyright notice, this list |
|
// of conditions and the following disclaimer. |
|
// |
|
// - Redistributions in binary form must reproduce the above copyright notice, this list |
|
// of conditions and the following disclaimer in the documentation and/or other materials |
|
// provided with the distribution. |
|
// |
|
// - Neither the name of the SharpDevelop team nor the names of its contributors may be used to |
|
// endorse or promote products derived from this software without specific prior written |
|
// permission. |
|
// |
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &AS IS& AND ANY EXPRESS |
|
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
|
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
|
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
|
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
|
|
using System; |
|
using System.IO; |
|
using System.Text.RegularExpressions; |
|
|
|
using ICSharpCode.Core; |
|
using ICSharpCode.SharpDevelop; |
|
|
|
namespace ICSharpCode.NAnt |
|
{ |
|
/// <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 { |
|
int line = Convert.ToInt32(match.Groups[2].Value); |
|
int col = Convert.ToInt32(match.Groups[3].Value); |
|
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(FileName.Create(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 { |
|
int line = Convert.ToInt32(match.Groups[2].Value); |
|
int col = Convert.ToInt32(match.Groups[3].Value); |
|
|
|
task = new Task(FileName.Create(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 { |
|
int line = Convert.ToInt32(match.Groups[2].Value); |
|
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(FileName.Create(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(null, 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(null, 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(null, 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 { |
|
int line = Convert.ToInt32(match.Groups[2].Value); |
|
int col = Convert.ToInt32(match.Groups[3].Value); |
|
string description = String.Concat(match.Groups[4], Environment.NewLine, match.Groups[5]); |
|
task = new Task(FileName.Create(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(null, 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 { |
|
int line = Convert.ToInt32(match.Groups[2].Value); |
|
int col = Convert.ToInt32(match.Groups[3].Value); |
|
string description = String.Concat(match.Groups[4]); |
|
task = new Task(FileName.Create(match.Groups[1].Value), description, col, line, TaskType.Error); |
|
} catch(Exception) { }; |
|
} |
|
|
|
return task; |
|
} |
|
} |
|
}
|
|
|