我有一个 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"));
}
}
}
我尝试过的:
问题:如何创建绿色(或蓝色或黄色)曲线装饰?可悲的是,即使是神秘或复杂的解决方案也值得赞赏......
我的目标是 VS2015 和 VS2017。
编辑:在输入此问题时,MSDN 论坛上的某人回复说当前的 API 无法完成此操作。在 Visual Studio 中真的不可能做出黄色曲线吗?!
ErrorType
的 ErrorTag
属性支持的值。
您已接近“警告”,但
PredefinedErrorTypeNames.Warning
的值似乎是“编译器警告”。
只是为了记录我自己的问题和答案。
创建一个文件
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";
代码取自我的存储库这里。
准确地说,波形装饰有一个画笔,它可以是 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 有一个不同的装饰,所有其他都是花体。