Skip to content

Commit

Permalink
Merge pull request #180 from tonyhallett/colour-improvements
Browse files Browse the repository at this point in the history
fix #179
  • Loading branch information
tonyhallett authored Aug 19, 2021
2 parents e08ef4e + 6483558 commit 98daf26
Show file tree
Hide file tree
Showing 14 changed files with 299 additions and 96 deletions.
2 changes: 1 addition & 1 deletion FineCodeCoverage/Core/FCCEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ internal class FCCEngine : IFCCEngine
private readonly ILogger logger;
private readonly IAppDataFolder appDataFolder;
private readonly IServiceProvider serviceProvider;

private IInitializeStatusProvider initializeStatusProvider;
private readonly ICoverageToolOutputManager coverageOutputManager;
internal System.Threading.Tasks.Task reloadCoverageTask;
Expand Down Expand Up @@ -71,7 +72,6 @@ IServiceProvider serviceProvider
this.appDataFolder = appDataFolder;
this.serviceProvider = serviceProvider;
colorThemeService = serviceProvider.GetService(typeof(SVsColorThemeService));

}

internal string GetLogReloadCoverageStatusMessage(ReloadCoverageStatus reloadCoverageStatus)
Expand Down
13 changes: 8 additions & 5 deletions FineCodeCoverage/FineCodeCoverage.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
<Compile Include="Core\Cobertura\Package.cs" />
<Compile Include="Core\Cobertura\Packages.cs" />
<Compile Include="Core\Cobertura\Sources.cs" />
<Compile Include="Impl\CoverageColorProvider.cs" />
<Compile Include="Core\CoverageToolOutput\AppOptionsCoverageToolOutputFolderSolutionProvider.cs" />
<Compile Include="Core\CoverageToolOutput\CoverageToolOutputFolderFromSolutionProvider.cs" />
<Compile Include="Core\CoverageToolOutput\FccOutputExistenceCoverageToolOutputFolderSolutionProvider.cs" />
Expand All @@ -81,6 +82,8 @@
<Compile Include="Core\Coverlet\Console\CoverletConsoleCustomPathExecutor.cs" />
<Compile Include="Core\Coverlet\Console\CoverletConsoleDotnetToolsLocalExecutor.cs" />
<Compile Include="Core\CoverageToolOutput\ICoverageToolOutputManager.cs" />
<Compile Include="Impl\ICoverageColours.cs" />
<Compile Include="Impl\ICoverageColoursProvider.cs" />
<Compile Include="Core\ICoverageUtilManager.cs" />
<Compile Include="Core\MsTestPlatform\IMsTestPlatformUtil.cs" />
<Compile Include="Core\Utilities\LinqExtensions.cs" />
Expand Down Expand Up @@ -153,9 +156,9 @@
<Compile Include="Core\CoverageToolOutput\CoverageToolOutputManager.cs" />
<Compile Include="Impl\ILogger.cs" />
<Compile Include="Impl\RunSettingsRetriever.cs" />
<Compile Include="Impl\GlyphFactory.cs" />
<Compile Include="Impl\GlyphFactoryProvider.cs" />
<Compile Include="Impl\GlyphTag.cs" />
<Compile Include="Impl\CoverageLineGlyphFactory.cs" />
<Compile Include="Impl\CoverageLineGlyphFactoryProvider.cs" />
<Compile Include="Impl\CoverageLineGlyphTag.cs" />
<Compile Include="Impl\Logger.cs" />
<Compile Include="Impl\TestContainerDiscovery\Container.cs" />
<Compile Include="Impl\TestContainerDiscovery\ContainerData.cs" />
Expand All @@ -173,8 +176,8 @@
<Compile Include="Impl\TestContainerDiscovery\TestOperationFactory.cs" />
<Compile Include="Impl\TestContainerDiscovery\TestRunResponse.cs" />
<Compile Include="Impl\Vsix.cs" />
<Compile Include="Impl\Tagger.cs" />
<Compile Include="Impl\TaggerProvider.cs" />
<Compile Include="Impl\CoverageLineGlyphTagger.cs" />
<Compile Include="Impl\CoverageLineGlyphTaggerProvider.cs" />
<Compile Include="Impl\TestContainerDiscovery\TestContainerDiscoverer.cs" />
<Compile Include="Core\OpenCover\OpenCoverUtil.cs" />
<Compile Include="Options\AppOptions.cs">
Expand Down
139 changes: 139 additions & 0 deletions FineCodeCoverage/Impl/CoverageColorProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
using System;
using System.ComponentModel.Composition;
using FineCodeCoverage.Options;
using Microsoft;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

namespace FineCodeCoverage.Impl
{
[Export(typeof(ICoverageColoursProvider))]
[Export(typeof(ICoverageColours))]
internal class CoverageColorProvider : ICoverageColoursProvider, ICoverageColours
{
private readonly IVsFontAndColorStorage fontAndColorStorage;
private Guid categoryWithCoverage = Guid.Parse("ff349800-ea43-46c1-8c98-878e78f46501");
private uint storeFlags = (uint)(__FCSTORAGEFLAGS.FCSF_READONLY | __FCSTORAGEFLAGS.FCSF_LOADDEFAULTS | __FCSTORAGEFLAGS.FCSF_NOAUTOCOLORS | __FCSTORAGEFLAGS.FCSF_PROPAGATECHANGES);
private System.Windows.Media.Color defaultCoverageTouchedArea = System.Windows.Media.Colors.Green;
private System.Windows.Media.Color defaultCoverageNotTouchedArea = System.Windows.Media.Colors.Red;
private System.Windows.Media.Color defaultCoveragePartiallyTouchedArea = System.Windows.Media.Color.FromRgb(255, 165, 0);
private System.Windows.Media.Color coverageTouchedArea;
private System.Windows.Media.Color coverageNotTouchedArea;
private System.Windows.Media.Color coveragePartiallyTouchedArea;
public System.Windows.Media.Color CoverageTouchedArea {
get {
UpdateFromFontsAndColorsIfNecessary();
return coverageTouchedArea;
}
private set
{
coverageTouchedArea = value;
}
}

public System.Windows.Media.Color CoverageNotTouchedArea {
get
{
UpdateFromFontsAndColorsIfNecessary();
return coverageNotTouchedArea;
}
private set
{
coverageNotTouchedArea = value;
}
}

public System.Windows.Media.Color CoveragePartiallyTouchedArea {
get
{
UpdateFromFontsAndColorsIfNecessary();
return coveragePartiallyTouchedArea;
}
private set
{
coveragePartiallyTouchedArea = value;
}

}

private bool coverageColoursFromFontsAndColours;
private bool requiresFromFontsAndColours;

[ImportingConstructor]
public CoverageColorProvider([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider, IAppOptionsProvider appOptionsProvider)
{
ThreadHelper.ThrowIfNotOnUIThread();
fontAndColorStorage = (IVsFontAndColorStorage)serviceProvider.GetService(typeof(IVsFontAndColorStorage));
Assumes.Present(fontAndColorStorage);
coverageColoursFromFontsAndColours = appOptionsProvider.Get().CoverageColoursFromFontsAndColours;
UseDefaultColoursIfNotFontsAndColours();
appOptionsProvider.OptionsChanged += AppOptionsProvider_OptionsChanged;
}

private void AppOptionsProvider_OptionsChanged(IAppOptions appOptions)
{
coverageColoursFromFontsAndColours = appOptions.CoverageColoursFromFontsAndColours;
UseDefaultColoursIfNotFontsAndColours();
}

private void UseDefaultColoursIfNotFontsAndColours()
{
if (!coverageColoursFromFontsAndColours)
{
CoverageTouchedArea = defaultCoverageTouchedArea;
CoverageNotTouchedArea = defaultCoverageNotTouchedArea;
CoveragePartiallyTouchedArea = defaultCoveragePartiallyTouchedArea;
}
}

public void UpdateRequired()
{
requiresFromFontsAndColours = true;
}

private void UpdateFromFontsAndColorsIfNecessary()
{
if(coverageColoursFromFontsAndColours && requiresFromFontsAndColours)
{
UpdateColoursFromFontsAndColors();
}
}

private void UpdateColoursFromFontsAndColors()
{
ThreadHelper.ThrowIfNotOnUIThread();
var success = fontAndColorStorage.OpenCategory(ref categoryWithCoverage, storeFlags);
if (success == VSConstants.S_OK)
{
CoverageTouchedArea = GetColor("Coverage Touched Area");
CoverageNotTouchedArea = GetColor("Coverage Not Touched Area");
CoveragePartiallyTouchedArea = GetColor("Coverage Partially Touched Area");
}
fontAndColorStorage.CloseCategory();
//throw ?
requiresFromFontsAndColours = false;
}

private System.Windows.Media.Color GetColor(string displayName)
{
ThreadHelper.ThrowIfNotOnUIThread();
var touchAreaInfo = new ColorableItemInfo[1];
var getItemSuccess = fontAndColorStorage.GetItem(displayName, touchAreaInfo);
if (getItemSuccess == VSConstants.S_OK)
{
return ParseColor(touchAreaInfo[0].crBackground);
}
throw new Exception("Failed to get color");
}

private System.Windows.Media.Color ParseColor(uint color)
{
var dcolor = System.Drawing.ColorTranslator.FromOle(Convert.ToInt32(color));
return System.Windows.Media.Color.FromArgb(dcolor.A, dcolor.R, dcolor.G, dcolor.B);
}


}

}
73 changes: 73 additions & 0 deletions FineCodeCoverage/Impl/CoverageLineGlyphFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Formatting;

namespace FineCodeCoverage.Impl
{
internal class CoverageLineGlyphFactory : IGlyphFactory
{
private enum CoverageType { Covered, Partial, NotCovered}
private ICoverageColours coverageColours;

public CoverageLineGlyphFactory(ICoverageColours coverageColours)
{
this.coverageColours = coverageColours;
}

public UIElement GenerateGlyph(IWpfTextViewLine textViewLine, IGlyphTag glyphTag)
{
if (!(glyphTag is CoverageLineGlyphTag tag))
{
return null;
}

// vars

var line = tag?.CoverageLine?.Line;
var lineHitCount = line?.Hits ?? 0;
var lineConditionCoverage = line?.ConditionCoverage?.Trim();

var coverageType = CoverageType.NotCovered;

if (lineHitCount > 0)
{
coverageType = CoverageType.Covered;

if (!string.IsNullOrWhiteSpace(lineConditionCoverage) && !lineConditionCoverage.StartsWith("100"))
{
coverageType = CoverageType.Partial;
}
}

// result

var result = new Rectangle();
result.Width = 3;
result.Height = 16;
result.Fill = GetBrush(coverageType);
// return

return result;
}

private Brush GetBrush(CoverageType coverageType)
{
Color color = default;
switch (coverageType)
{
case CoverageType.Partial:
color = coverageColours.CoveragePartiallyTouchedArea;
break;
case CoverageType.NotCovered:
color = coverageColours.CoverageNotTouchedArea;
break;
case CoverageType.Covered:
color = coverageColours.CoverageTouchedArea;
break;
}
return new SolidColorBrush(color);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,22 @@
namespace FineCodeCoverage.Impl
{
[ContentType("code")]
[TagType(typeof(GlyphTag))]
[TagType(typeof(CoverageLineGlyphTag))]
[Order(Before = "VsTextMarker")]
[Name(Vsix.GlyphFactoryProviderName)]
[Export(typeof(IGlyphFactoryProvider))]
internal class GlyphFactoryProvider: IGlyphFactoryProvider
internal class CoverageLineGlyphFactoryProvider: IGlyphFactoryProvider
{
private readonly ICoverageColours coverageColours;

[ImportingConstructor]
public CoverageLineGlyphFactoryProvider(ICoverageColours coverageColours)
{
this.coverageColours = coverageColours;
}
public IGlyphFactory GetGlyphFactory(IWpfTextView textView, IWpfTextViewMargin textViewMargin)
{
return new GlyphFactory();
return new CoverageLineGlyphFactory(coverageColours);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

namespace FineCodeCoverage.Impl
{
internal class GlyphTag : IGlyphTag
internal class CoverageLineGlyphTag : IGlyphTag
{
public CoverageLine CoverageLine { get; }

public GlyphTag(CoverageLine coverageLine)
public CoverageLineGlyphTag(CoverageLine coverageLine)
{
CoverageLine = coverageLine;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,33 @@

namespace FineCodeCoverage.Impl
{
internal class Tagger<T> : ITagger<T> where T : ITag
internal class CoverageLineGlyphTagger : ITagger<CoverageLineGlyphTag>
{
private readonly ITextBuffer _textBuffer;
private readonly IFCCEngine fccEngine;
private readonly ICoverageColoursProvider coverageColoursProvider;

public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
public event EventHandler<SnapshotSpanEventArgs> TagsChanged;

public Tagger(ITextBuffer textBuffer,IFCCEngine fccEngine)
public CoverageLineGlyphTagger(ITextBuffer textBuffer, IFCCEngine fccEngine, ICoverageColoursProvider coverageColoursProvider)
{
_textBuffer = textBuffer;
this.fccEngine = fccEngine;
this.coverageColoursProvider = coverageColoursProvider;
fccEngine.UpdateMarginTags += FCCEngine_UpdateMarginTags;
}

private void FCCEngine_UpdateMarginTags(UpdateMarginTagsEventArgs e)
{
coverageColoursProvider.UpdateRequired();
var span = new SnapshotSpan(_textBuffer.CurrentSnapshot, 0, _textBuffer.CurrentSnapshot.Length);
var spanEventArgs = new SnapshotSpanEventArgs(span);
TagsChanged?.Invoke(this, spanEventArgs);
}

IEnumerable<ITagSpan<T>> ITagger<T>.GetTags(NormalizedSnapshotSpanCollection spans)
IEnumerable<ITagSpan<CoverageLineGlyphTag>> ITagger<CoverageLineGlyphTag>.GetTags(NormalizedSnapshotSpanCollection spans)
{
var result = new List<ITagSpan<T>>();
var result = new List<ITagSpan<CoverageLineGlyphTag>>();

if (spans == null || fccEngine.CoverageLines == null)
{
Expand All @@ -51,10 +54,9 @@ IEnumerable<ITagSpan<T>> ITagger<T>.GetTags(NormalizedSnapshotSpanCollection spa

foreach (var coverageLine in coverageLines)
{
var tag = new GlyphTag(coverageLine);
var tagSpan = new TagSpan<GlyphTag>(span, tag);
var iTagSpan = tagSpan as ITagSpan<T>;
result.Add(iTagSpan);
var tag = new CoverageLineGlyphTag(coverageLine);
var tagSpan = new TagSpan<CoverageLineGlyphTag>(span, tag);
result.Add(tagSpan);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@
namespace FineCodeCoverage.Impl
{
[ContentType("code")]
[TagType(typeof(GlyphTag))]
[TagType(typeof(CoverageLineGlyphTag))]
[Name(Vsix.TaggerProviderName)]
[Export(typeof(ITaggerProvider))]
internal class TaggerProvider : ITaggerProvider
internal class CoverageLineGlyphTaggerProvider : ITaggerProvider
{
private readonly IFCCEngine fccEngine;
private readonly ICoverageColoursProvider coverageColoursProvider;

[ImportingConstructor]
public TaggerProvider(IFCCEngine fccEngine)
public CoverageLineGlyphTaggerProvider(IFCCEngine fccEngine, ICoverageColoursProvider coverageColoursProvider)
{
this.fccEngine = fccEngine;
this.coverageColoursProvider = coverageColoursProvider;
}
public ITagger<T> CreateTagger<T>(ITextBuffer textBuffer) where T : ITag
{
return new Tagger<T>(textBuffer,fccEngine);
return new CoverageLineGlyphTagger(textBuffer, fccEngine, coverageColoursProvider) as ITagger<T>;
}
}
}
Loading

0 comments on commit 98daf26

Please sign in to comment.