提交 966081a8 编写于 作者: C Cyrus Najmabadi

Make json highlighting into an actual brace highlighting.

上级 8f40f116
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Implementation.BraceMatching;
namespace Microsoft.CodeAnalysis.Editor.CSharp.BraceMatching
{
[ExportBraceMatcher(LanguageNames.CSharp)]
internal class CSharpJsonBraceMatcher : IBraceMatcher
{
public Task<BraceMatchingResult?> FindBracesAsync(Document document, int position, CancellationToken cancellationToken)
=> CommonJsonBraceMatcher.FindBracesAsync(document, position, cancellationToken);
}
}
......@@ -10,17 +10,7 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.BraceMatching
[ExportBraceMatcher(LanguageNames.CSharp)]
internal class CSharpRegexBraceMatcher : IBraceMatcher
{
public async Task<BraceMatchingResult?> FindBracesAsync(Document document, int position, CancellationToken cancellationToken = default)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var token = root.FindToken(position);
if (token.Kind() != SyntaxKind.StringLiteralToken)
{
return null;
}
return await CommonRegexBraceMatcher.FindBracesAsync(
document, token, position, cancellationToken).ConfigureAwait(false);
}
public Task<BraceMatchingResult?> FindBracesAsync(Document document, int position, CancellationToken cancellationToken)
=> CommonRegexBraceMatcher.FindBracesAsync(document, position, cancellationToken);
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Json;
......@@ -10,11 +8,11 @@
using Microsoft.CodeAnalysis.VirtualChars;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.DocumentHighlighting
namespace Microsoft.CodeAnalysis.Editor.Implementation.BraceMatching
{
internal abstract partial class AbstractDocumentHighlightsService : IDocumentHighlightsService
internal static class CommonJsonBraceMatcher
{
private async Task<ImmutableArray<DocumentHighlights>> TryGetJsonHighlightsAsync(
internal static async Task<BraceMatchingResult?> FindBracesAsync(
Document document, int position, CancellationToken cancellationToken)
{
var option = document.Project.Solution.Workspace.Options.GetOption(JsonOptions.HighlightRelatedJsonComponentsUnderCursor, document.Project.Language);
......@@ -46,79 +44,53 @@ internal abstract partial class AbstractDocumentHighlightsService : IDocumentHig
return default;
}
return GetHighlights(document, tree, position);
return GetMatchingBraces(tree, position);
}
private ImmutableArray<DocumentHighlights> GetHighlights(
Document document, JsonTree tree, int position)
{
var bracesOnTheRight = GetHighlights(document, tree, position, caretOnLeft: true);
var bracesOnTheLeft = GetHighlights(document, tree, position - 1, caretOnLeft: false);
if (!bracesOnTheRight.IsEmpty)
{
// We were on the left of an open open. Return these highlights, and any
// highlights if we were on the right of a close paren.
return bracesOnTheRight.Concat(bracesOnTheLeft);
}
// Nothing was on the right of the caret. Return anything we were able to find on
// the left of the caret
return bracesOnTheLeft;
}
private ImmutableArray<DocumentHighlights> GetHighlights(
Document document, JsonTree tree, int position, bool caretOnLeft)
private static BraceMatchingResult? GetMatchingBraces(JsonTree tree, int position)
{
var virtualChar = tree.Text.FirstOrNullable(vc => vc.Span.Contains(position));
if (virtualChar == null)
{
return ImmutableArray<DocumentHighlights>.Empty;
return null;
}
var ch = virtualChar.Value;
if (caretOnLeft)
{
return ch == '{' || ch == '[' || ch == '('
? FindBraceHighlights(document, tree, ch)
: ImmutableArray<DocumentHighlights>.Empty;
}
else
if (ch == '{' || ch == '[' || ch == '(' ||
ch == '}' || ch == ']' || ch == ')')
{
return ch == '}' || ch == ']' || ch == ')'
? FindBraceHighlights(document, tree, ch)
: ImmutableArray<DocumentHighlights>.Empty;
return FindBraceHighlights(tree, ch);
}
return null;
}
private ImmutableArray<DocumentHighlights> FindBraceHighlights(
Document document, JsonTree tree, VirtualChar ch)
private static BraceMatchingResult? FindBraceHighlights(JsonTree tree, VirtualChar ch)
{
var node = FindObjectOrArrayNode(tree.Root, ch);
switch (node)
{
case JsonObjectNode obj: return Create(document, obj.OpenBraceToken, obj.CloseBraceToken);
case JsonArrayNode array: return Create(document, array.OpenBracketToken, array.CloseBracketToken);
case JsonConstructorNode cons: return Create(document, cons.OpenParenToken, cons.CloseParenToken);
case JsonObjectNode obj: return Create(obj.OpenBraceToken, obj.CloseBraceToken);
case JsonArrayNode array: return Create(array.OpenBracketToken, array.CloseBracketToken);
case JsonConstructorNode cons: return Create(cons.OpenParenToken, cons.CloseParenToken);
}
return default;
}
private ImmutableArray<DocumentHighlights> Create(Document document, JsonToken open, JsonToken close)
private static BraceMatchingResult? Create(JsonToken open, JsonToken close)
{
if (open.IsMissing || close.IsMissing)
{
return default;
}
return ImmutableArray.Create(new DocumentHighlights(
document, ImmutableArray.Create(
new HighlightSpan(JsonHelpers.GetSpan(open), HighlightSpanKind.None),
new HighlightSpan(JsonHelpers.GetSpan(close), HighlightSpanKind.None))));
return new BraceMatchingResult(
JsonHelpers.GetSpan(open),
JsonHelpers.GetSpan(close));
}
private JsonValueNode FindObjectOrArrayNode(JsonNode node, VirtualChar ch)
private static JsonValueNode FindObjectOrArrayNode(JsonNode node, VirtualChar ch)
{
switch (node)
{
......@@ -147,7 +119,7 @@ private JsonValueNode FindObjectOrArrayNode(JsonNode node, VirtualChar ch)
return null;
}
private bool Matches(JsonToken openToken, JsonToken closeToken, VirtualChar ch)
private static bool Matches(JsonToken openToken, JsonToken closeToken, VirtualChar ch)
=> openToken.VirtualChars.Contains(ch) || closeToken.VirtualChars.Contains(ch);
}
}
......@@ -13,8 +13,18 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.BraceMatching
internal static class CommonRegexBraceMatcher
{
internal static async Task<BraceMatchingResult?> FindBracesAsync(
Document document, SyntaxToken token, int position, CancellationToken cancellationToken)
Document document, int position, CancellationToken cancellationToken)
{
var option = document.Project.Solution.Workspace.Options.GetOption(
RegularExpressionsOptions.HighlightRelatedRegexComponentsUnderCursor, document.Project.Language);
if (!option)
{
return default;
}
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var token = root.FindToken(position);
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
if (RegexPatternDetector.IsDefinitelyNotPattern(token, syntaxFacts))
{
......
......@@ -9,15 +9,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.BraceMatching
Friend Class VisualBasicRegexBraceMatcher
Implements IBraceMatcher
Public Async Function FindBracesAsync(document As Document, position As Integer, Optional cancellationToken As CancellationToken = Nothing) As Task(Of BraceMatchingResult?) Implements IBraceMatcher.FindBracesAsync
Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False)
Dim token = root.FindToken(position)
If token.Kind() <> SyntaxKind.StringLiteralToken Then
Return Nothing
End If
Return Await CommonRegexBraceMatcher.FindBracesAsync(
document, token, position, cancellationToken).ConfigureAwait(False)
Public Function FindBracesAsync(document As Document, position As Integer, Optional cancellationToken As CancellationToken = Nothing) As Task(Of BraceMatchingResult?) Implements IBraceMatcher.FindBracesAsync
Return CommonRegexBraceMatcher.FindBracesAsync(document, position, cancellationToken)
End Function
End Class
End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Threading
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis.Editor.Implementation.BraceMatching
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.BraceMatching
<ExportBraceMatcher(LanguageNames.VisualBasic)>
Friend Class VisualBasicJsonBraceMatcher
Implements IBraceMatcher
Public Function FindBracesAsync(document As Document, position As Integer, Optional cancellationToken As CancellationToken = Nothing) As Task(Of BraceMatchingResult?) Implements IBraceMatcher.FindBracesAsync
Return CommonJsonBraceMatcher.FindBracesAsync(document, position, cancellationToken)
End Function
End Class
End Namespace
......@@ -60,13 +60,7 @@ internal abstract partial class AbstractDocumentHighlightsService : IDocumentHig
private async Task<ImmutableArray<DocumentHighlights>> GetDocumentHighlightsInCurrentProcessAsync(
Document document, int position, IImmutableSet<Document> documentsToSearch, CancellationToken cancellationToken)
{
var result = await TryGetJsonHighlightsAsync(document, position, cancellationToken).ConfigureAwait(false);
if (!result.IsDefaultOrEmpty)
{
return result;
}
result = await TryGetRegexPatternHighlightsAsync(document, position, cancellationToken).ConfigureAwait(false);
var result = await TryGetRegexPatternHighlightsAsync(document, position, cancellationToken).ConfigureAwait(false);
if (!result.IsDefaultOrEmpty)
{
return result;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册