我有一个Visual Studio for Java加载项,如配置文件。可以找到示例文件here。
在特定行上插入 \ 字符时会出现问题。当使用向后斜杠时,下一行被解释为值(或作为键,或作为键和值)。一个简单的例子是:
1. part1_key\
2. part2_key\
3. part3_key = value
4. key = part1_value\
5. part2_value
语法高亮显示器在加载文件时有效,但是当修改一行时,只评估那条行并突出显示。因此,例如,当第4行插入 \ 时,第4行会突出显示,但第5行不更新。第5行仅在修改后更新(添加或删除字符或空格)。
我创建了一个 ITaggerProvider ,用于创建 ITagger ,其类型为 Key , Value 或注释。 ITagger 类如下:
internal sealed class PropertiesTokenTagger : ITagger<PropertiesTokenTag> {
private readonly Regex keyValuePattern = new Regex(@"(?<!^\s*|\\)([ \t]*[=:][ \t]*|[ \t]+)");
private readonly Regex separatorPattern = new Regex(@"^([=:]|[ \t]+)");
private readonly Regex commentPattern = new Regex(@"^\s*[#!]");
private readonly Regex escapedLineEndPattern = new Regex(@"\\$");
public event EventHandler<SnapshotSpanEventArgs> TagsChanged {
add { }
remove { }
}
public IEnumerable<ITagSpan<PropertiesTokenTag>> GetTags(NormalizedSnapshotSpanCollection spans) {
// sadly `spans` gets one line at a time, so previouslyEscapedValue will not get the chance to be used
foreach (var curSpan in spans) {
var containingLine = curSpan.Start.GetContainingLine();
var lineStartLoc = containingLine.Start.Position;
var lineText = containingLine.GetText();
var previousIsNotComment = false;
var previousLine = curSpan.Snapshot.Lines.LastOrDefault(l => l.End <= curSpan.Start);
if (previousLine != null && escapedLineEndPattern.IsMatch(previousLine.GetText())) {
var previousToken = GetTags(new NormalizedSnapshotSpanCollection(previousLine.Extent)).ToList();
if (previousToken.Count > 0) {
var propertiesTokenTypes = previousToken.Last().Tag.Type;
if (propertiesTokenTypes == PropertiesValue) {
var valueSpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartLoc, lineText.Length));
yield return new TagSpan<PropertiesTokenTag>(valueSpan, new PropertiesTokenTag(PropertiesValue));
continue;
}
if (propertiesTokenTypes == PropertiesKey && separatorPattern.IsMatch(lineText)) {
var valueSpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartLoc, lineText.Length));
yield return new TagSpan<PropertiesTokenTag>(valueSpan, new PropertiesTokenTag(PropertiesValue));
continue;
}
previousIsNotComment = propertiesTokenTypes != PropertiesComment;
}
}
if (commentPattern.IsMatch(lineText) && !previousIsNotComment) {
var commentSpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartLoc, lineText.Length));
yield return new TagSpan<PropertiesTokenTag>(commentSpan, new PropertiesTokenTag(PropertiesComment));
continue;
}
if (keyValuePattern.IsMatch(lineText)) {
var splitPosition = keyValuePattern.Split(lineText)[0].Length;
var keySpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartLoc, splitPosition));
yield return new TagSpan<PropertiesTokenTag>(keySpan, new PropertiesTokenTag(PropertiesKey));
var valueSpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartLoc + splitPosition + 1, lineText.Length - splitPosition - 1));
yield return new TagSpan<PropertiesTokenTag>(valueSpan, new PropertiesTokenTag(PropertiesValue));
} else {
var keySpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartLoc, lineText.Length));
yield return new TagSpan<PropertiesTokenTag>(keySpan, new PropertiesTokenTag(PropertiesKey));
}
}
}
从我看到的问题是,从外部源调用 GetTags 方法的事实,我无法手动调用此方法以更新其他行。此方法返回 TagSpans 的 List ,其中与 NormalizedSnapshotSpanCollection 参数相交,因此,如果我尝试返回标记除当前行之外的另一行,该标记不会被处理。
LE:我已经完成了,解决方案是从GetTags方法外部引发TagsChanged事件,也从 ITagger 中的聚合器引发。