Skip to content

Update rustc output parsing #112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions VisualRust.Build/Rustc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public class Rustc : Microsoft.Build.Utilities.Task
{
private static readonly Regex defectRegex = new Regex(@"^([^\n:]+):(\d+):(\d+):\s+(\d+):(\d+)\s+(.*)$", RegexOptions.Multiline | RegexOptions.CultureInvariant);

// FIXME: This currently does not handle errors with descriptions, e.g. "unreachable pattern [E0001] (pass `--explain E0001` to see a detailed explanation)"
private static readonly Regex errorCodeRegex = new Regex(@"\[([A-Z]\d\d\d\d)\]$", RegexOptions.CultureInvariant);

private string[] configFlags = new string[0];
Expand Down Expand Up @@ -234,7 +233,7 @@ private bool ExecuteInner()
if(String.Equals(target, Shared.Environment.DefaultTarget, StringComparison.OrdinalIgnoreCase))
Log.LogError("Could not find a Rust installation.");
else
Log.LogError("Could not find a Rust instalation that can compile target {0}.", target);
Log.LogError("Could not find a Rust installation that can compile target {0}.", target);
return false;
}
var psi = new ProcessStartInfo()
Expand Down Expand Up @@ -305,29 +304,38 @@ private IEnumerable<RustcParsedMessage> ParseOutput(string output)
RustcParsedMessage previous = null;
foreach (Match match in errorMatches)
{
Match errorMatch = errorCodeRegex.Match(match.Groups[6].Value);
string remainingMsg = match.Groups[6].Value.Trim();
Match errorMatch = errorCodeRegex.Match(remainingMsg);
string errorCode = errorMatch.Success ? errorMatch.Groups[1].Value : null;
int line = Int32.Parse(match.Groups[2].Value, System.Globalization.NumberStyles.None);
int col = Int32.Parse(match.Groups[3].Value, System.Globalization.NumberStyles.None);
int endLine = Int32.Parse(match.Groups[4].Value, System.Globalization.NumberStyles.None);
int endCol = Int32.Parse(match.Groups[5].Value, System.Globalization.NumberStyles.None);

if (match.Groups[6].Value.StartsWith("warning: "))
if (remainingMsg.StartsWith("warning: "))
{
string msg = match.Groups[6].Value.Substring(9, match.Groups[6].Value.Length - 9 - (errorCode != null ? 8 : 0));
if (previous != null) yield return previous;
previous = new RustcParsedMessage(RustcParsedMessageType.Warning, msg, errorCode, match.Groups[1].Value,
line, col, endLine, endCol);
}
else if (match.Groups[6].Value.StartsWith("note: "))
else if (remainingMsg.StartsWith("note: ") || remainingMsg.StartsWith("help: "))
{
string msg = match.Groups[6].Value.Substring(6, match.Groups[6].Value.Length - 6 - (errorCode != null ? 8 : 0));
RustcParsedMessage note = new RustcParsedMessage(RustcParsedMessageType.Note, msg, errorCode, match.Groups[1].Value,
if (remainingMsg.StartsWith("help: pass `--explain ") && previous != null)
{
previous.CanExplain = true;
continue;
}

// NOTE: "note: " and "help: " are both 6 characters long (though hardcoding this is probably still not a very good idea)
string msg = remainingMsg.Substring(6, remainingMsg.Length - 6 - (errorCode != null ? 8 : 0));
var type = remainingMsg.StartsWith("note: ") ? RustcParsedMessageType.Note : RustcParsedMessageType.Help;
RustcParsedMessage note = new RustcParsedMessage(type, msg, errorCode, match.Groups[1].Value,
line, col, endLine, endCol);

if (previous != null)
{
// try to merge notes with a previous message (warning or error where it belongs to), if the span is the same
// try to merge notes and help messages with a previous message (warning or error where it belongs to), if the span is the same
if (previous.TryMergeWithFollowing(note))
{
continue; // skip setting new previous, because we successfully merged the new note into the previous message
Expand All @@ -341,8 +349,8 @@ private IEnumerable<RustcParsedMessage> ParseOutput(string output)
}
else
{
bool startsWithError = match.Groups[6].Value.StartsWith("error: ");
string msg = match.Groups[6].Value.Substring((startsWithError ? 7 : 0), match.Groups[6].Value.Length - (startsWithError ? 7 : 0) - (errorCode != null ? 8 : 0));
bool startsWithError = remainingMsg.StartsWith("error: ");
string msg = remainingMsg.Substring((startsWithError ? 7 : 0), remainingMsg.Length - (startsWithError ? 7 : 0) - (errorCode != null ? 8 : 0));
if (previous != null) yield return previous;
previous = new RustcParsedMessage(RustcParsedMessageType.Error, msg, errorCode, match.Groups[1].Value,
line, col, endLine, endCol);
Expand Down
12 changes: 8 additions & 4 deletions VisualRust.Build/RustcParsedMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ enum RustcParsedMessageType
{
Error,
Warning,
Note
Note,
Help
}

class RustcParsedMessage
Expand All @@ -19,6 +20,7 @@ class RustcParsedMessage
public int ColumnNumber;
public int EndLineNumber;
public int EndColumnNumber;
public bool CanExplain; // TODO: currently we don't do anything with this

public RustcParsedMessage(RustcParsedMessageType type, string message, string errorCode, string file,
int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber)
Expand All @@ -31,15 +33,17 @@ public RustcParsedMessage(RustcParsedMessageType type, string message, string er
ColumnNumber = columnNumber;
EndLineNumber = endLineNumber;
EndColumnNumber = endColumnNumber;
CanExplain = false;
}

public bool TryMergeWithFollowing(RustcParsedMessage other)
{
if (other.Type == RustcParsedMessageType.Note && other.File == this.File &&
other.LineNumber == this.LineNumber && other.ColumnNumber == this.ColumnNumber &&
if ((other.Type == RustcParsedMessageType.Note || other.Type == RustcParsedMessageType.Help)
&& other.File == this.File && other.LineNumber == this.LineNumber && other.ColumnNumber == this.ColumnNumber &&
other.EndLineNumber == this.EndLineNumber && other.EndColumnNumber == this.EndColumnNumber)
{
this.Message += "\nnote: " + other.Message;
var prefix = other.Type == RustcParsedMessageType.Note ? "\nnote: " : "\nhelp: ";
this.Message += prefix + other.Message;
return true;
}
else
Expand Down