如何使用 Visual Studio 扩展创建绿色(或蓝色)波浪线装饰

问题描述 投票:0回答:3

我有一个 Visual Studio 扩展,显示红色错误曲线。我还喜欢提供其他颜色的曲线,例如黄色用于警告。

创建红色曲线可以通过扩展 ITagger 类来完成,如下所示:

internal sealed class MySquigglesTagger : ITagger<IErrorTag> {
    public IEnumerable<ITagSpan<IErrorTag>> GetTags(NormalizedSnapshotSpanCollection spans) {
        foreach (IMappingTagSpan<MyTokenTag> myTokenTag in this._aggregator.GetTags(spans))        
            SnapshotSpan tagSpan = myTokenTag.Span.GetSpans(this._sourceBuffer)[0];
            yield return new TagSpan<IErrorTag>(tagSpan, new ErrorTag("Error", "some info about the error"));
        }
    }
}

我尝试过的:

  1. 我的直觉(错误地)说,返回具有不同 errorType 的 ErrorTag 可能会产生不同类型的标签,但无论您传递什么字符串,波浪线都保持红色。例如。 new ErrorTag("Warning") 给出红色波浪线。 MSDN 文档几乎不存在。请参阅错误标签
  2. Tagging 命名空间 中没有提到实现 Itag 的不同 Tag 类。我希望存在警告标签或信息标签。
  3. 在 MSDN 论坛这里问了一个问题。

问题:如何创建绿色(或蓝色或黄色)曲线装饰?可悲的是,即使是神秘或复杂的解决方案也值得赞赏......

我的目标是 VS2015 和 VS2017。

编辑:在输入此问题时,MSDN 论坛上的某人回复说当前的 API 无法完成此操作。在 Visual Studio 中真的不可能做出黄色曲线吗?!

c# .net visual-studio vsix vs-extensibility
3个回答
5
投票

PredefinedErrorTypeNames 包含

ErrorType
ErrorTag
属性支持的值。

您已接近“警告”,但

PredefinedErrorTypeNames.Warning
的值似乎是“编译器警告”。


1
投票

只是为了记录我自己的问题和答案。

创建一个文件

SquigglesTaggerProvider.cs
,其中包含以下内容:

[Export(typeof(IViewTaggerProvider))]
[ContentType("Your Content Type")]
[TagType(typeof(ErrorTag))]
internal sealed class SquigglesTaggerProvider : IViewTaggerProvider {
    [Import]
    private IBufferTagAggregatorFactoryService _aggregatorFactory = null;

    public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag {
        ITagger<T> sc() {
            return new SquigglesTagger(buffer, this._aggregatorFactory) as ITagger<T>;
        }
        return buffer.Properties.GetOrCreateSingletonProperty(sc);
    }
}

创建一个名为

SquigglesTagger.cs
的文件,其中包含以下内容:

internal sealed class SquigglesTagger : ITagger<IErrorTag> {
    private readonly ITextBuffer _sourceBuffer;
    private readonly ITagAggregator<AsmTokenTag> _aggregator;

    internal SquigglesTagger(ITextBuffer buffer, IBufferTagAggregatorFactoryService aggregatorFactory) {
        this._sourceBuffer = buffer;            
        ITagAggregator<AsmTokenTag> sc() {   
            return aggregatorFactory.CreateTagAggregator<AsmTokenTag>(buffer);
        }
        this._aggregator = buffer.Properties.GetOrCreateSingletonProperty(sc);
    }

    public IEnumerable<ITagSpan<IErrorTag>> GetTags(NormalizedSnapshotSpanCollection spans) {
        foreach (IMappingTagSpan<MyTokenTag> myTokenTag in this._aggregator.GetTags(spans))        
            SnapshotSpan tagSpan = myTokenTag.Span.GetSpans(this._sourceBuffer)[0];
            yield return new TagSpan<IErrorTag>(tagSpan, new ErrorTag(PredefinedErrorTypeNames.SyntaxError, "some info about the error"));
        }
    }
}

PredefinedErrorTypeNames
预定义了不同的错误。

public const string SyntaxError = "syntax error";
public const string CompilerError = "compiler error";
public const string OtherError = "other error";
public const string Warning = "compiler warning";
public const string Suggestion = "suggestion";

代码取自我的存储库这里


0
投票

准确地说,波形装饰有一个画笔,它可以是 Red SolidColorBrush,也可以是由导出的 EditorFormatDefinition 确定的画笔,其中 NameAttribute 名称与 IErrorTag.ErrorType 的名称匹配,并且对应的导出的 ErrorTypeDefinition 也具有与IErrorTag.ErrorType.

EditorFormatDefinition.CreateResourceDictionaryFromDefinition 中的 ResourceDictionary 决定了画笔。如果您不重写此方法,则导出的 EditorFormatDefinition 可以为 SolidColorBrush 设置 ForegroundColor 或将 ForegroundBrush 设置为任何 Brush 实现。

这些导出可以在

ITagger<T>
上实现。 比如说

class ErrorEditorFormatDefinition : EditorFormatDefinition
{

    public ErrorEditorFormatDefinition(Color errorColor, string displayName = null) : this(displayName)
    {
        this.ForegroundColor = errorColor;

    }
    public ErrorEditorFormatDefinition(Brush brush, string displayName = null) : this(displayName)
    {
        this.ForegroundBrush = brush;
    }
    private ErrorEditorFormatDefinition(string displayName)
    {
        if (displayName != null)
        {
            this.DisplayName = displayName;
        }
        this.BackgroundCustomizable = false;
    }
}

internal class ErrorTagger : ITagger<IErrorTag>
{
    public const string MethodNotCoveredErrorType = "MethodNotCovered";
    public const string MethodPartiallyCoveredErrorType = "MethodPartiallyCovered";
    public const string LineNotCoveredErrorType = "LineNotCovered";
    public const string LinePartiallyCoveredErrorType = "LinePartiallyCovered";

    public event EventHandler<SnapshotSpanEventArgs> TagsChanged;

    [Export(typeof(ErrorTypeDefinition))]
    [Name(MethodNotCoveredErrorType)]
    public ErrorTypeDefinition MethodNotCoveredErrorTypeDefinition { get; }

    [Export(typeof(ErrorTypeDefinition))]
    [Name(MethodPartiallyCoveredErrorType)]
    public ErrorTypeDefinition MethodPartiallyErrorTypeDefinition { get; }
    
    [Export(typeof(ErrorTypeDefinition))]
    [Name(LineNotCoveredErrorType)]
    public ErrorTypeDefinition LineNotCoveredErrorTypeDefinition { get; }
    
    [Export(typeof(ErrorTypeDefinition))]
    [Name(LinePartiallyCoveredErrorType)]
    public ErrorTypeDefinition LinePartiallyErrorTypeDefinition { get; }


    [Export(typeof(EditorFormatDefinition))]
    [Name(MethodNotCoveredErrorType)]
    [UserVisible(true)]
    public EditorFormatDefinition MethodNotCoveredErrorFormatDefinition { get; } = new ErrorEditorFormatDefinition(new SolidColorBrush(Colors.Pink));

    [Export(typeof(EditorFormatDefinition))]
    [Name(MethodPartiallyCoveredErrorType)]
    public EditorFormatDefinition MethodPartiallyCoveredErrorFormatDefinition { get; } = new ErrorEditorFormatDefinition(new LinearGradientBrush()
    {
        StartPoint = new System.Windows.Point(0, 0),
        EndPoint = new System.Windows.Point(1, 0),
        GradientStops = new GradientStopCollection
        {
            new GradientStop(Colors.Yellow, 0.0),
            new GradientStop(Colors.Red, 0.25),
            new GradientStop(Colors.Blue, 0.75),
            new GradientStop(Colors.LimeGreen, 1.0)
        }
    },"Call me what you want");
    
    [Name(LineNotCoveredErrorType)]
    [Export(typeof(EditorFormatDefinition))]
    public EditorFormatDefinition LineNotCoveredErrorFormatDefinition { get; } = new ErrorEditorFormatDefinition(Colors.Brown);
    [Name(LinePartiallyCoveredErrorType)]
    public EditorFormatDefinition LinePartiallyCoveredErrorFormatDefinition { get; } = new ErrorEditorFormatDefinition(Colors.Cyan);

    public IEnumerable<ITagSpan<IErrorTag>> GetTags(NormalizedSnapshotSpanCollection spans)
    {
        return new List<ITagSpan<IErrorTag>>
        {
            // determine as appropriate
            new TagSpan<IErrorTag>(new SnapshotSpan(spans[0].Snapshot, new Span(0, spans[0].Snapshot.Length)), new ErrorTag(MethodPartiallyCoveredErrorType, "Method partially covered")),
        };
    }
}

预定义的错误类型名称只是那些保证具有匹配的错误类型定义/编辑器格式定义的名称。

public static class PredefinedErrorTypeNames { 
  /// <summary>Represents syntax errors.</summary> 
  public const string SyntaxError = "syntax error"; 
  /// <summary>Represents compiler errors.</summary> 
  public const string CompilerError = "compiler error"; 
  /// <summary>Represents other errors.</summary> 
  public const string OtherError = "other error"; 
  /// <summary>Represents compiler warnings.</summary> 
  public const string Warning = "compiler warning"; 
  /// <summary>Represents a suggestion with no visual treatment.</summary> 
  public const string Suggestion = "suggestion";
  ///<summary>Represents a suggestion with subtle visual treatment.</summary> 
  public const string HintedSuggestion = "hinted suggestion"; 
}

请注意,“建议”在“字体和颜色”中不可见 - 另请检查下面的“显示名称”更改,了解如何在“字体和颜色”中找到这些更改。

[Export(typeof(EditorFormatDefinition))]
[Name("suggestion")]
[UserVisible(false)]
internal class SuggestionClassificationFormatDefinition : EditorFormatDefinition
{
    public SuggestionClassificationFormatDefinition()
    {
        this.ForegroundBrush = (Brush)Brushes.Transparent;
        this.BackgroundCustomizable = new bool?(false);
        this.DisplayName = "Suggestion";
    }
}

[Export(typeof(EditorFormatDefinition))]
[Name("compiler warning")]
[UserVisible(true)]
internal class WarningClassificationFormatDefinition : EditorFormatDefinition
{
    public WarningClassificationFormatDefinition()
    {
        this.ForegroundBrush = (Brush)new SolidColorBrush(Color.FromRgb((byte)0, (byte)128, (byte)0));
        this.BackgroundCustomizable = new bool?(false);
        this.DisplayName = "Warning";
    }
}

[Export(typeof(EditorFormatDefinition))]
[Name("compiler error")]
[UserVisible(true)]
internal class CompilerErrorClassificationFormatDefinition : EditorFormatDefinition
{
    public CompilerErrorClassificationFormatDefinition()
    {
        this.ForegroundBrush = (Brush)Brushes.Blue;
        this.BackgroundCustomizable = new bool?(false);
        this.DisplayName = "Compiler Error";
    }
}

[Export(typeof(EditorFormatDefinition))]
[Name("other error")]
[UserVisible(true)]
internal class OtherErrorClassificationFormatDefinition : EditorFormatDefinition
{
    public OtherErrorClassificationFormatDefinition()
    {
        this.ForegroundBrush = (Brush)new SolidColorBrush(Color.FromRgb((byte)149, (byte)23, (byte)149));
        this.BackgroundCustomizable = new bool?(false);
        this.DisplayName = "Other Error";
    }
}

[Export(typeof(EditorFormatDefinition))]
[Name("syntax error")]
[UserVisible(true)]
internal class SyntaxErrorFormatDefinition : EditorFormatDefinition
{
    public SyntaxErrorFormatDefinition()
    {
        this.ForegroundBrush = (Brush)Brushes.Red;
        this.BackgroundCustomizable = new bool?(false);
        this.DisplayName = "Syntax Error";
    }
}

[Export(typeof(EditorFormatDefinition))]
[Name("hinted suggestion")]
[UserVisible(true)]
internal class HintedSuggestionClassificationFormatDefinition : EditorFormatDefinition
{
    public HintedSuggestionClassificationFormatDefinition()
    {
        this.ForegroundBrush = (Brush)new SolidColorBrush(Color.FromRgb((byte)165, (byte)165, (byte)165));
        this.BackgroundCustomizable = new bool?(false);
        this.DisplayName = "Suggestion ellipses (...)";
    }
}

Vs 2022 中有一个未包含在此列表中。 ErrorType“编辑并继续”默认提供紫色画笔,它是字体和颜色中的“粗鲁编辑”。

如果您希望在 Visual Studio 中编辑波形图颜色,请在 EditorFormatDefinition 上设置

[UserVisible(true)]
,如果您这样做,则设置
this.BackgroundCustomizable = false;
,就像我对 ErrorEditorFormatDefinition 类所做的那样,前提是不使用背景。如果您提供非 SolidColorBrush,请勿执行此操作。

最后,ErrorType = PredefinedErrorTypeNames.HintedSuggestion 有一个不同的装饰,所有其他都是花体。

© www.soinside.com 2019 - 2024. All rights reserved.