From 6d23499cd5cb7a32246a1ea1934a96176a03351d Mon Sep 17 00:00:00 2001 From: Philippe Miossec Date: Fri, 4 Jan 2019 13:36:56 +0100 Subject: [PATCH] Highlight project header lines in build output --- Tests/UnitTests/ClassificationFormatTests.cs | 4 ++ .../BuildOutputClassifierTestsBase.cs | 14 ++++++ .../Parsers/BuildProjectHeaderParserTests.cs | 48 +++++++++++++++++++ .../ParsersConfigurationServiceTests.cs | 2 + Tests/UnitTests/StyleManagerTests.cs | 5 ++ Tests/UnitTests/UnitTests.csproj | 1 + VSOutputEnhancer/ClassificationType.cs | 3 ++ .../Exports/ClassificationTypeExports.cs | 4 ++ .../BuildProjectHeaderFormatDefinition.cs | 19 ++++++++ .../BuildProjectHeaderData.cs | 27 +++++++++++ .../BuildProjectHeaderParser.cs | 33 +++++++++++++ .../BuildProjectHeaderProcessor.cs | 19 ++++++++ .../Properties/Resources.Designer.cs | 9 ++++ VSOutputEnhancer/Properties/Resources.resx | 3 ++ VSOutputEnhancer/Resources/DarkTheme.json | 3 ++ VSOutputEnhancer/Resources/LightTheme.json | 3 ++ VSOutputEnhancer/VSOutputEnhancer.csproj | 4 ++ 17 files changed, 201 insertions(+) create mode 100644 Tests/UnitTests/Parsers/BuildProjectHeaderParserTests.cs create mode 100644 VSOutputEnhancer/Exports/Formats/BuildProjectHeaderFormatDefinition.cs create mode 100644 VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderData.cs create mode 100644 VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderParser.cs create mode 100644 VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderProcessor.cs diff --git a/Tests/UnitTests/ClassificationFormatTests.cs b/Tests/UnitTests/ClassificationFormatTests.cs index 61ad5be..5349f81 100644 --- a/Tests/UnitTests/ClassificationFormatTests.cs +++ b/Tests/UnitTests/ClassificationFormatTests.cs @@ -67,6 +67,10 @@ private static IEnumerable GetAllExportedFormats() private String GetCorrectName(Type formatType) { + if (formatType == typeof(BuildProjectHeaderFormatDefinition)) + { + return "Output enhancer: Build project header"; + } if (formatType == typeof(BuildMessageErrorFormatDefinition)) { return "Output enhancer: Build error message"; diff --git a/Tests/UnitTests/Classifiers/BuildOutputClassifierTestsBase.cs b/Tests/UnitTests/Classifiers/BuildOutputClassifierTestsBase.cs index be174b4..ed78208 100644 --- a/Tests/UnitTests/Classifiers/BuildOutputClassifierTestsBase.cs +++ b/Tests/UnitTests/Classifiers/BuildOutputClassifierTestsBase.cs @@ -11,6 +11,20 @@ namespace Balakin.VSOutputEnhancer.Tests.UnitTests.Classifiers [ExcludeFromCodeCoverage] public abstract class BuildOutputClassifierTestsBase : ClassifierTestsBase { + [Fact] + public void BuildProjectHeader() + { + const String buildCompleteMessage = "1>------ Build started: Project: UnitTests, Configuration: Debug Any CPU ------\r\n"; + var span = Utils.CreateSpan(buildCompleteMessage); + + var expectedResult = new[] + { + new ClassificationSpan(span, new ClassificationTypeStub(ClassificationType.BuildProjectHeader)) + }; + + Test(span, expectedResult); + } + [Fact] public void BuildFailed() { diff --git a/Tests/UnitTests/Parsers/BuildProjectHeaderParserTests.cs b/Tests/UnitTests/Parsers/BuildProjectHeaderParserTests.cs new file mode 100644 index 0000000..aa6736b --- /dev/null +++ b/Tests/UnitTests/Parsers/BuildProjectHeaderParserTests.cs @@ -0,0 +1,48 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using Balakin.VSOutputEnhancer.Parsers; +using Balakin.VSOutputEnhancer.Parsers.BuildProjectHeader; +using FluentAssertions; +using Microsoft.VisualStudio.Text; +using Xunit; + +namespace Balakin.VSOutputEnhancer.Tests.UnitTests.Parsers +{ + [ExcludeFromCodeCoverage] + public class BuildProjectHeaderParserTests + { + [Theory] + [InlineData("Message\r\n")] + [InlineData("1>------ Publish: 10 succeeded, 3 failed, 122 skipped\r\n")] + [InlineData("------ Anything ------\r\n")] + [InlineData("Anything ------\r\n")] + public void NotParsed(String message) + { + var span = Utils.CreateSpan(message); + var parser = new BuildProjectHeaderParser(); + BuildProjectHeaderData parsedData; + var parsed = parser.TryParse(span, out parsedData); + + parsed.Should().BeFalse(); + parsedData.Should().BeNull(); + } + + [Fact] + public void Build() + { + const String publishCompleteMessage = "1>------ Rebuild All started: Project: VSOutputEnhancer, Configuration: Debug Any CPU ------\r\n"; + var expectedResult = new BuildProjectHeaderData( + new ParsedValue(1, new Span(0, 1)), + new ParsedValue("Rebuild All started: Project: VSOutputEnhancer, Configuration: Debug Any CPU", new Span(9, 76)) + ); + + var span = Utils.CreateSpan(publishCompleteMessage); + BuildProjectHeaderData parsedData; + var parser = new BuildProjectHeaderParser(); + var parsed = parser.TryParse(span, out parsedData); + + parsed.Should().BeTrue(); + parsedData.ShouldBeEquivalentTo(expectedResult); + } + } +} \ No newline at end of file diff --git a/Tests/UnitTests/ParsersConfigurationServiceTests.cs b/Tests/UnitTests/ParsersConfigurationServiceTests.cs index 36bde0f..60825a8 100644 --- a/Tests/UnitTests/ParsersConfigurationServiceTests.cs +++ b/Tests/UnitTests/ParsersConfigurationServiceTests.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using Balakin.VSOutputEnhancer.Parsers.BowerMessage; using Balakin.VSOutputEnhancer.Parsers.BuildFileRelatedMessage; +using Balakin.VSOutputEnhancer.Parsers.BuildProjectHeader; using Balakin.VSOutputEnhancer.Parsers.BuildResult; using Balakin.VSOutputEnhancer.Parsers.DebugException; using Balakin.VSOutputEnhancer.Parsers.DebugTraceMessage; @@ -33,6 +34,7 @@ private void TestBuildOutput(String contentType) { var expectedResult = new[] { + new ParserConfiguration(typeof(BuildProjectHeaderParser), typeof(BuildProjectHeaderData), typeof(BuildProjectHeaderProcessor)), new ParserConfiguration(typeof(BuildResultParser), typeof(BuildResultData), typeof(BuildResultDataProcessor)), new ParserConfiguration(typeof(BuildFileRelatedMessageParser), typeof(BuildFileRelatedMessageData), typeof(BuildFileRelatedMessageDataProcessor)), new ParserConfiguration(typeof(PublishResultParser), typeof(PublishResultData), typeof(PublishResultDataProcessor)), diff --git a/Tests/UnitTests/StyleManagerTests.cs b/Tests/UnitTests/StyleManagerTests.cs index ff4e98e..e9e7551 100644 --- a/Tests/UnitTests/StyleManagerTests.cs +++ b/Tests/UnitTests/StyleManagerTests.cs @@ -57,6 +57,10 @@ public void SimilarClassificationTypesHasSimilarColors(Theme theme) { ClassificationType.DebugTraceInformation }; + var info = new[] + { + ClassificationType.BuildProjectHeader + }; TestSimilarColors(error.Select(styleManager.GetStyleForClassificationType).ToList(), "error"); TestSimilarColors(warning.Select(styleManager.GetStyleForClassificationType).ToList(), "warning"); @@ -67,6 +71,7 @@ public void SimilarClassificationTypesHasSimilarColors(Theme theme) .Except(warning) .Except(success) .Except(skip) + .Except(info) .ToList(); notChecked.Should().BeEmpty("Classification types did not checked: " + String.Join(", ", notChecked)); } diff --git a/Tests/UnitTests/UnitTests.csproj b/Tests/UnitTests/UnitTests.csproj index c6b603b..6053367 100644 --- a/Tests/UnitTests/UnitTests.csproj +++ b/Tests/UnitTests/UnitTests.csproj @@ -87,6 +87,7 @@ + diff --git a/VSOutputEnhancer/ClassificationType.cs b/VSOutputEnhancer/ClassificationType.cs index 6d89994..30669b0 100644 --- a/VSOutputEnhancer/ClassificationType.cs +++ b/VSOutputEnhancer/ClassificationType.cs @@ -10,6 +10,7 @@ internal static class ClassificationType { BuildMessageError, BuildMessageWarning, + BuildProjectHeader, BuildResultFailed, BuildResultSucceeded, PublishResultFailed, @@ -25,6 +26,8 @@ internal static class ClassificationType BowerMessageError }; + public const String BuildProjectHeader = "BuildProjectHeader"; + public const String BuildMessageError = "BuildMessageError"; public const String BuildMessageWarning = "BuildMessageWarning"; diff --git a/VSOutputEnhancer/Exports/ClassificationTypeExports.cs b/VSOutputEnhancer/Exports/ClassificationTypeExports.cs index c63d41a..580e4ce 100644 --- a/VSOutputEnhancer/Exports/ClassificationTypeExports.cs +++ b/VSOutputEnhancer/Exports/ClassificationTypeExports.cs @@ -9,6 +9,10 @@ namespace Balakin.VSOutputEnhancer.Exports { internal static class ClassificationTypeExports { + [Export(typeof(ClassificationTypeDefinition))] + [Name(ClassificationType.BuildProjectHeader)] + public static ClassificationTypeDefinition BuildProjectHeader; + [Export(typeof(ClassificationTypeDefinition))] [Name(ClassificationType.BuildResultSucceeded)] public static ClassificationTypeDefinition BuildResultSucceeded; diff --git a/VSOutputEnhancer/Exports/Formats/BuildProjectHeaderFormatDefinition.cs b/VSOutputEnhancer/Exports/Formats/BuildProjectHeaderFormatDefinition.cs new file mode 100644 index 0000000..3d392a1 --- /dev/null +++ b/VSOutputEnhancer/Exports/Formats/BuildProjectHeaderFormatDefinition.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.Composition; +using Microsoft.VisualStudio.Text.Classification; +using Microsoft.VisualStudio.Utilities; + +namespace Balakin.VSOutputEnhancer.Exports.Formats +{ + [Export(typeof(EditorFormatDefinition))] + [ClassificationType(ClassificationTypeNames = ClassificationType.BuildProjectHeader)] + [Name(ClassificationType.BuildProjectHeader)] + [UserVisible(false)] + [Order(Before = Priority.Default)] + internal sealed class BuildProjectHeaderFormatDefinition : StyledClassificationFormatDefinition + { + [ImportingConstructor] + public BuildProjectHeaderFormatDefinition(IStyleManager styleManager) : base(styleManager) + { + } + } +} \ No newline at end of file diff --git a/VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderData.cs b/VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderData.cs new file mode 100644 index 0000000..96e9c4d --- /dev/null +++ b/VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderData.cs @@ -0,0 +1,27 @@ +using System; + +namespace Balakin.VSOutputEnhancer.Parsers.BuildProjectHeader +{ + // TODO: Review accessibility level + public class BuildProjectHeaderData : ParsedData + { + // TODO: Refactor ParsedData builder to get rid of this constructor + public BuildProjectHeaderData() + { + } + + public BuildProjectHeaderData( + ParsedValue buildTaskId, + ParsedValue fullMessage) + { + BuildTaskId = buildTaskId; + FullMessage = fullMessage; + } + + // This properties filled using reflection + // ReSharper disable UnusedAutoPropertyAccessor.Local + public ParsedValue BuildTaskId { get; private set; } + public ParsedValue FullMessage { get; private set; } + // ReSharper restore UnusedAutoPropertyAccessor.Local + } +} \ No newline at end of file diff --git a/VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderParser.cs b/VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderParser.cs new file mode 100644 index 0000000..e196c41 --- /dev/null +++ b/VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderParser.cs @@ -0,0 +1,33 @@ +using System; +using System.Text.RegularExpressions; +using Microsoft.VisualStudio.Text; + +namespace Balakin.VSOutputEnhancer.Parsers.BuildProjectHeader +{ + [UseForClassification(ContentType.BuildOutput)] + [UseForClassification(ContentType.BuildOrderOutput)] + internal class BuildProjectHeaderParser : IParser + { + public Boolean TryParse(SnapshotSpan span, out BuildProjectHeaderData result) + { + var text = span.GetText(); + + result = null; + if (!text.EndsWith(" ------\r\n", StringComparison.Ordinal)) + { + return false; + } + + var regex = $"^(?:(?\\d+)>)------ (?.*) ------\r\n$"; + + var match = Regex.Match(text, regex, RegexOptions.Compiled); + if (!match.Success) + { + return false; + } + + result = ParsedData.Create(match, span.Span); + return true; + } + } +} \ No newline at end of file diff --git a/VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderProcessor.cs b/VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderProcessor.cs new file mode 100644 index 0000000..09ed086 --- /dev/null +++ b/VSOutputEnhancer/Parsers/BuildProjectHeader/BuildProjectHeaderProcessor.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using Microsoft.VisualStudio.Text; + +namespace Balakin.VSOutputEnhancer.Parsers.BuildProjectHeader +{ + internal class BuildProjectHeaderProcessor : IParsedDataProcessor + { + public IEnumerable ProcessData(SnapshotSpan span, BuildProjectHeaderData parsedData) + { + if (parsedData == null) + { + yield break; + } + + yield return new ProcessedParsedData(span, ClassificationType.BuildProjectHeader); + } + } +} \ No newline at end of file diff --git a/VSOutputEnhancer/Properties/Resources.Designer.cs b/VSOutputEnhancer/Properties/Resources.Designer.cs index fced73d..0fa000c 100644 --- a/VSOutputEnhancer/Properties/Resources.Designer.cs +++ b/VSOutputEnhancer/Properties/Resources.Designer.cs @@ -87,6 +87,15 @@ internal static string FormatDisplayName_BuildMessageWarning { } } + /// + /// Looks up a localized string similar to Output enhancer: Build project header. + /// + internal static string FormatDisplayName_BuildProjectHeader { + get { + return ResourceManager.GetString("FormatDisplayName_BuildProjectHeader", resourceCulture); + } + } + /// /// Looks up a localized string similar to Output enhancer: Build failed. /// diff --git a/VSOutputEnhancer/Properties/Resources.resx b/VSOutputEnhancer/Properties/Resources.resx index afcbbde..83829ed 100644 --- a/VSOutputEnhancer/Properties/Resources.resx +++ b/VSOutputEnhancer/Properties/Resources.resx @@ -129,6 +129,9 @@ Output enhancer: Build failed + + Output enhancer: Build project header + Output enhancer: Build succeeded diff --git a/VSOutputEnhancer/Resources/DarkTheme.json b/VSOutputEnhancer/Resources/DarkTheme.json index b2f81fb..d4d16fe 100644 --- a/VSOutputEnhancer/Resources/DarkTheme.json +++ b/VSOutputEnhancer/Resources/DarkTheme.json @@ -1,4 +1,7 @@ { + "BuildProjectHeader": { + "ForegroundColor": "#00FFFF" + }, "BuildMessageError": { "ForegroundColor": "#D85050" }, diff --git a/VSOutputEnhancer/Resources/LightTheme.json b/VSOutputEnhancer/Resources/LightTheme.json index 45cef9b..0b53aa7 100644 --- a/VSOutputEnhancer/Resources/LightTheme.json +++ b/VSOutputEnhancer/Resources/LightTheme.json @@ -1,4 +1,7 @@ { + "BuildProjectHeader": { + "ForegroundColor": "#00FFFF" + }, "BuildMessageError": { "ForegroundColor": "#BF0606" }, diff --git a/VSOutputEnhancer/VSOutputEnhancer.csproj b/VSOutputEnhancer/VSOutputEnhancer.csproj index bdd5950..2c10028 100644 --- a/VSOutputEnhancer/VSOutputEnhancer.csproj +++ b/VSOutputEnhancer/VSOutputEnhancer.csproj @@ -85,6 +85,7 @@ + @@ -105,6 +106,9 @@ + + +