Skip to content

Commit

Permalink
Merge pull request dotnet#61529 from CyrusNajmabadi/aspEmbeddedChars
Browse files Browse the repository at this point in the history
Expose VirtualChars to asp.net (through EA) to facilitate route classification
  • Loading branch information
CyrusNajmabadi authored May 26, 2022
2 parents 1db7eeb + 51aa854 commit affb2c7
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ internal readonly struct AspNetCoreEmbeddedLanguageClassificationContext
{
private readonly EmbeddedLanguageClassificationContext _context;

public AspNetCoreEmbeddedLanguageClassificationContext(EmbeddedLanguageClassificationContext context)
internal AspNetCoreEmbeddedLanguageClassificationContext(
EmbeddedLanguageClassificationContext context,
AspNetCoreVirtualCharSequence virtualCharSequence)
{
_context = context;
VirtualCharSequence = virtualCharSequence;
}

/// <inheritdoc cref="EmbeddedLanguageClassificationContext.SyntaxToken"/>
Expand All @@ -23,6 +26,9 @@ public AspNetCoreEmbeddedLanguageClassificationContext(EmbeddedLanguageClassific
/// <inheritdoc cref="EmbeddedLanguageClassificationContext.SemanticModel"/>
public SemanticModel SemanticModel => _context.SemanticModel;

/// <inheritdoc cref="Microsoft.CodeAnalysis.EmbeddedLanguages.VirtualChars.VirtualCharSequence"/>
public AspNetCoreVirtualCharSequence VirtualCharSequence { get; }

/// <inheritdoc cref="EmbeddedLanguageClassificationContext.CancellationToken"/>
public CancellationToken CancellationToken => _context.CancellationToken;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Text;
using Microsoft.CodeAnalysis.EmbeddedLanguages.VirtualChars;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.ExternalAccess.AspNetCore.EmbeddedLanguages
{
internal readonly struct AspNetCoreVirtualChar
{
private readonly VirtualChar _virtualChar;

internal AspNetCoreVirtualChar(VirtualChar virtualChar)
{
_virtualChar = virtualChar;
}

/// <inheritdoc cref="VirtualChar.Rune"/>
public Rune Rune => _virtualChar.Rune;

/// <inheritdoc cref="VirtualChar.SurrogateChar"/>
public char SurrogateChar => _virtualChar.SurrogateChar;

/// <inheritdoc cref="VirtualChar.Span"/>
public TextSpan Span => _virtualChar.Span;

/// <inheritdoc cref="VirtualChar.Value"/>
public int Value => _virtualChar.Value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.EmbeddedLanguages.VirtualChars;

namespace Microsoft.CodeAnalysis.ExternalAccess.AspNetCore.EmbeddedLanguages
{
/// <inheritdoc cref="VirtualCharSequence"/>
internal readonly struct AspNetCoreVirtualCharSequence
{
private readonly VirtualCharSequence _virtualCharSequence;

internal AspNetCoreVirtualCharSequence(VirtualCharSequence virtualCharSequence)
{
_virtualCharSequence = virtualCharSequence;
}

/// <inheritdoc cref="VirtualCharSequence.Length"/>
public int Length => _virtualCharSequence.Length;

/// <inheritdoc cref="VirtualCharSequence.this"/>
public AspNetCoreVirtualChar this[int index] => new(_virtualCharSequence[index]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,15 @@ public void RegisterClassifications(EmbeddedLanguageClassificationContext contex
return;

var classifiers = AspNetCoreClassifierExtensionProvider.GetExtensions(context.Project);
var aspContext = new AspNetCoreEmbeddedLanguageClassificationContext(context);
if (classifiers.Length == 0)
return;

var virtualChars = context.VirtualCharService.TryConvertToVirtualChars(context.SyntaxToken);
if (virtualChars.IsDefaultOrEmpty)
return;

var aspContext = new AspNetCoreEmbeddedLanguageClassificationContext(
context, new AspNetCoreVirtualCharSequence(virtualChars));
foreach (var classifier in classifiers)
classifier.RegisterClassifications(aspContext);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ internal abstract class AbstractEmbeddedLanguageClassificationService : IEmbedde
/// </summary>
private readonly Dictionary<string, ArrayBuilder<Lazy<IEmbeddedLanguageClassifier, EmbeddedLanguageMetadata>>> _identifierToClassifiers = new(StringComparer.OrdinalIgnoreCase);

/// <summary>
/// Information about the embedded language.
/// </summary>
private readonly EmbeddedLanguageInfo _info;

/// <summary>
/// Helper to look at string literals and determine what language they are annotated to take.
/// </summary>
Expand Down Expand Up @@ -71,6 +76,7 @@ protected AbstractEmbeddedLanguageClassificationService(
foreach (var (_, classifiers) in _identifierToClassifiers)
classifiers.RemoveDuplicates();

_info = info;
_detector = new EmbeddedLanguageDetector(info, _identifierToClassifiers.Keys.ToImmutableArray());

_syntaxTokenKinds.Add(syntaxKinds.CharacterLiteralToken);
Expand Down Expand Up @@ -165,7 +171,7 @@ private void ClassifyToken(SyntaxToken token)
_classifierBuffer.Clear();

var context = new EmbeddedLanguageClassificationContext(
_project, _semanticModel, token, _options, _result, _cancellationToken);
_project, _semanticModel, token, _options, _service._info.VirtualCharService, _result, _cancellationToken);

// First, see if this is a string annotated with either a comment or [StringSyntax] attribute. If
// so, delegate to the first classifier we have registered for whatever language ID we find.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

using System.Threading;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.EmbeddedLanguages.VirtualChars;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.Classification
{
internal struct EmbeddedLanguageClassificationContext
{
internal readonly ClassificationOptions Options;
private readonly ArrayBuilder<ClassifiedSpan> _result;

public Project? Project { get; }
Expand All @@ -28,18 +28,23 @@ internal struct EmbeddedLanguageClassificationContext

public CancellationToken CancellationToken { get; }

internal readonly ClassificationOptions Options;
internal readonly IVirtualCharService VirtualCharService;

internal EmbeddedLanguageClassificationContext(
Project? project,
SemanticModel semanticModel,
SyntaxToken syntaxToken,
ClassificationOptions options,
IVirtualCharService virtualCharService,
ArrayBuilder<ClassifiedSpan> result,
CancellationToken cancellationToken)
{
Project = project;
SemanticModel = semanticModel;
SyntaxToken = syntaxToken;
Options = options;
VirtualCharService = virtualCharService;
_result = result;
CancellationToken = cancellationToken;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,14 @@ private VirtualCharSequence(Chunk sequence, TextSpan span)
_span = span;
}

/// <summary>
/// Gets the number of elements contained in the <see cref="VirtualCharSequence"/>.
/// </summary>
public int Length => _span.Length;

/// <summary>
/// Gets the <see cref="VirtualChar"/> at the specified index.
/// </summary>
public VirtualChar this[int index] => _leafCharacters[_span.Start + index];

public bool IsDefault => _leafCharacters == null;
Expand Down

0 comments on commit affb2c7

Please sign in to comment.