diff --git a/src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpJsonEmbeddedLanguageBraceMatchingService.cs b/src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpJsonBraceMatcher.cs similarity index 71% rename from src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpJsonEmbeddedLanguageBraceMatchingService.cs rename to src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpJsonBraceMatcher.cs index a99b25263b972..9b3dff1af348a 100644 --- a/src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpJsonEmbeddedLanguageBraceMatchingService.cs +++ b/src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpJsonBraceMatcher.cs @@ -12,13 +12,12 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.EmbeddedLanguages { [ExportEmbeddedLanguageBraceMatcher( - PredefinedEmbeddedLanguageBraceMatcherNames.Json, LanguageNames.CSharp, supportsUnannotatedAPIs: true, "Json"), Shared] - internal sealed class CSharpJsonEmbeddedLanguageBraceMatcher : - AbstractJsonEmbeddedLanguageBraceMatcher + PredefinedEmbeddedLanguageNames.Json, LanguageNames.CSharp, supportsUnannotatedAPIs: true, "Json"), Shared] + internal sealed class CSharpJsonBraceMatcher : AbstractJsonBraceMatcher { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpJsonEmbeddedLanguageBraceMatcher() + public CSharpJsonBraceMatcher() : base(CSharpEmbeddedLanguagesProvider.Info) { } diff --git a/src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpRegexEmbeddedLanguageBraceMatcher.cs b/src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpRegexBraceMatcher.cs similarity index 71% rename from src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpRegexEmbeddedLanguageBraceMatcher.cs rename to src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpRegexBraceMatcher.cs index 80051f0b28bb4..565bc556abe99 100644 --- a/src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpRegexEmbeddedLanguageBraceMatcher.cs +++ b/src/EditorFeatures/CSharp/EmbeddedLanguages/CSharpRegexBraceMatcher.cs @@ -12,13 +12,12 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.EmbeddedLanguages { [ExportEmbeddedLanguageBraceMatcher( - PredefinedEmbeddedLanguageBraceMatcherNames.Regex, LanguageNames.CSharp, supportsUnannotatedAPIs: true, "Regex", "Regexp"), Shared] - internal sealed class CSharpRegexEmbeddedLanguageBraceMatcher : - AbstractRegexEmbeddedLanguageBraceMatcher + PredefinedEmbeddedLanguageNames.Regex, LanguageNames.CSharp, supportsUnannotatedAPIs: true, "Regex", "Regexp"), Shared] + internal sealed class CSharpRegexBraceMatcher : AbstractRegexBraceMatcher { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpRegexEmbeddedLanguageBraceMatcher() + public CSharpRegexBraceMatcher() : base(CSharpEmbeddedLanguagesProvider.Info) { } diff --git a/src/EditorFeatures/Core/BraceMatching/PredefinedEmbeddedLanguageBraceMatcherNames.cs b/src/EditorFeatures/Core/BraceMatching/PredefinedEmbeddedLanguageBraceMatcherNames.cs deleted file mode 100644 index 48ab7824ea75f..0000000000000 --- a/src/EditorFeatures/Core/BraceMatching/PredefinedEmbeddedLanguageBraceMatcherNames.cs +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -namespace Microsoft.CodeAnalysis.BraceMatching -{ - internal static class PredefinedEmbeddedLanguageBraceMatcherNames - { - public const string Regex = nameof(Regex); - - public const string Json = nameof(Json); - } -} diff --git a/src/EditorFeatures/Core/EmbeddedLanguages/Json/AbstractJsonEmbeddedLanguageBraceMatcher.cs b/src/EditorFeatures/Core/EmbeddedLanguages/Json/AbstractJsonBraceMatcher.cs similarity index 95% rename from src/EditorFeatures/Core/EmbeddedLanguages/Json/AbstractJsonEmbeddedLanguageBraceMatcher.cs rename to src/EditorFeatures/Core/EmbeddedLanguages/Json/AbstractJsonBraceMatcher.cs index 631b407a2f847..abf09b90b5673 100644 --- a/src/EditorFeatures/Core/EmbeddedLanguages/Json/AbstractJsonEmbeddedLanguageBraceMatcher.cs +++ b/src/EditorFeatures/Core/EmbeddedLanguages/Json/AbstractJsonBraceMatcher.cs @@ -18,11 +18,11 @@ namespace Microsoft.CodeAnalysis.EmbeddedLanguages.Json /// /// Brace matcher impl for embedded json strings. /// - internal abstract class AbstractJsonEmbeddedLanguageBraceMatcher : IEmbeddedLanguageBraceMatcher + internal abstract class AbstractJsonBraceMatcher : IEmbeddedLanguageBraceMatcher { private readonly EmbeddedLanguageInfo _info; - public AbstractJsonEmbeddedLanguageBraceMatcher(EmbeddedLanguageInfo info) + public AbstractJsonBraceMatcher(EmbeddedLanguageInfo info) => _info = info; public BraceMatchingResult? FindBraces( diff --git a/src/EditorFeatures/Core/EmbeddedLanguages/RegularExpressions/AbstractRegexEmbeddedLanguageBraceMatcher.cs b/src/EditorFeatures/Core/EmbeddedLanguages/RegularExpressions/AbstractRegexBraceMatcher.cs similarity index 96% rename from src/EditorFeatures/Core/EmbeddedLanguages/RegularExpressions/AbstractRegexEmbeddedLanguageBraceMatcher.cs rename to src/EditorFeatures/Core/EmbeddedLanguages/RegularExpressions/AbstractRegexBraceMatcher.cs index 0a84d0168c2ab..9d9950a12a127 100644 --- a/src/EditorFeatures/Core/EmbeddedLanguages/RegularExpressions/AbstractRegexEmbeddedLanguageBraceMatcher.cs +++ b/src/EditorFeatures/Core/EmbeddedLanguages/RegularExpressions/AbstractRegexBraceMatcher.cs @@ -19,11 +19,11 @@ namespace Microsoft.CodeAnalysis.EmbeddedLanguages.RegularExpressions /// /// Brace matching impl for embedded regex strings. /// - internal abstract class AbstractRegexEmbeddedLanguageBraceMatcher : IEmbeddedLanguageBraceMatcher + internal abstract class AbstractRegexBraceMatcher : IEmbeddedLanguageBraceMatcher { private readonly EmbeddedLanguageInfo _info; - protected AbstractRegexEmbeddedLanguageBraceMatcher(EmbeddedLanguageInfo info) + protected AbstractRegexBraceMatcher(EmbeddedLanguageInfo info) => _info = info; public BraceMatchingResult? FindBraces( diff --git a/src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicJsonEmbeddedLanguageBraceMatcher.vb b/src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicJsonBraceMatcher.vb similarity index 77% rename from src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicJsonEmbeddedLanguageBraceMatcher.vb rename to src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicJsonBraceMatcher.vb index 85dc5b50cc612..75432ae869ca1 100644 --- a/src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicJsonEmbeddedLanguageBraceMatcher.vb +++ b/src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicJsonBraceMatcher.vb @@ -10,9 +10,9 @@ Imports Microsoft.CodeAnalysis.VisualBasic.EmbeddedLanguages.LanguageServices Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EmbeddedLanguages - Friend Class VisualBasicJsonEmbeddedLanguageBraceMatcher - Inherits AbstractJsonEmbeddedLanguageBraceMatcher + PredefinedEmbeddedLanguageNames.Json, LanguageNames.VisualBasic, True, "Json"), [Shared]> + Friend Class VisualBasicJsonBraceMatcher + Inherits AbstractJsonBraceMatcher diff --git a/src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicRegexEmbeddedLanguageBraceMatcher.vb b/src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicRegexBraceMatcher.vb similarity index 76% rename from src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicRegexEmbeddedLanguageBraceMatcher.vb rename to src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicRegexBraceMatcher.vb index 58205e1a93562..0056a49122cea 100644 --- a/src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicRegexEmbeddedLanguageBraceMatcher.vb +++ b/src/EditorFeatures/VisualBasic/EmbeddedLanguages/VisualBasicRegexBraceMatcher.vb @@ -10,9 +10,9 @@ Imports Microsoft.CodeAnalysis.VisualBasic.EmbeddedLanguages.LanguageServices Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.EmbeddedLanguages - Friend Class VisualBasicRegexEmbeddedLanguageBraceMatcher - Inherits AbstractRegexEmbeddedLanguageBraceMatcher + PredefinedEmbeddedLanguageNames.Regex, LanguageNames.VisualBasic, True, "Regex", "Regexp"), [Shared]> + Friend Class VisualBasicRegexBraceMatcher + Inherits AbstractRegexBraceMatcher diff --git a/src/Features/CSharp/Portable/DocumentHighlighting/CSharpDocumentHighlightsService.cs b/src/Features/CSharp/Portable/DocumentHighlighting/CSharpDocumentHighlightsService.cs index 970e96da01e6a..729486de888cc 100644 --- a/src/Features/CSharp/Portable/DocumentHighlighting/CSharpDocumentHighlightsService.cs +++ b/src/Features/CSharp/Portable/DocumentHighlighting/CSharpDocumentHighlightsService.cs @@ -5,13 +5,17 @@ #nullable disable using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.EmbeddedLanguages.LanguageServices; +using Microsoft.CodeAnalysis.CSharp.LanguageServices; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.DocumentHighlighting; +using Microsoft.CodeAnalysis.EmbeddedLanguages; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.PooledObjects; @@ -22,7 +26,12 @@ internal class CSharpDocumentHighlightsService : AbstractDocumentHighlightsServi { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpDocumentHighlightsService() + public CSharpDocumentHighlightsService( + [ImportMany] IEnumerable> services) + : base(LanguageNames.CSharp, + CSharpEmbeddedLanguagesProvider.Info, + CSharpSyntaxKinds.Instance, + services) { } diff --git a/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpJsonEmbeddedLanguageClassifier.cs b/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpJsonClassifier.cs similarity index 74% rename from src/Features/CSharp/Portable/EmbeddedLanguages/CSharpJsonEmbeddedLanguageClassifier.cs rename to src/Features/CSharp/Portable/EmbeddedLanguages/CSharpJsonClassifier.cs index b41771ce0860d..6d82003cca449 100644 --- a/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpJsonEmbeddedLanguageClassifier.cs +++ b/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpJsonClassifier.cs @@ -12,12 +12,12 @@ namespace Microsoft.CodeAnalysis.CSharp.Features.EmbeddedLanguages { [ExportEmbeddedLanguageClassifier( - PredefinedEmbeddedLanguageClassifierNames.Json, LanguageNames.CSharp, supportsUnannotatedAPIs: true, "Json"), Shared] - internal class CSharpJsonEmbeddedLanguageClassifier : AbstractJsonEmbeddedLanguageClassifier + PredefinedEmbeddedLanguageNames.Json, LanguageNames.CSharp, supportsUnannotatedAPIs: true, "Json"), Shared] + internal class CSharpJsonClassifier : AbstractJsonClassifier { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpJsonEmbeddedLanguageClassifier() + public CSharpJsonClassifier() : base(CSharpEmbeddedLanguagesProvider.Info) { } diff --git a/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpRegexEmbeddedLanguageClassifier.cs b/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpRegexClassifier.cs similarity index 73% rename from src/Features/CSharp/Portable/EmbeddedLanguages/CSharpRegexEmbeddedLanguageClassifier.cs rename to src/Features/CSharp/Portable/EmbeddedLanguages/CSharpRegexClassifier.cs index 5cb209d6d72ac..ac68a92c43226 100644 --- a/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpRegexEmbeddedLanguageClassifier.cs +++ b/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpRegexClassifier.cs @@ -13,14 +13,14 @@ namespace Microsoft.CodeAnalysis.CSharp.Features.EmbeddedLanguages { // Order regex classification before json classification. Json lights up on probable-json strings, but we don't // want that to happen for APIs that are certain to be another language like Regex. - [ExtensionOrder(Before = PredefinedEmbeddedLanguageClassifierNames.Json)] + [ExtensionOrder(Before = PredefinedEmbeddedLanguageNames.Json)] [ExportEmbeddedLanguageClassifier( - PredefinedEmbeddedLanguageClassifierNames.Regex, LanguageNames.CSharp, supportsUnannotatedAPIs: true, "Regex", "Regexp"), Shared] - internal class CSharpRegexEmbeddedLanguageClassifier : AbstractRegexEmbeddedLanguageClassifier + PredefinedEmbeddedLanguageNames.Regex, LanguageNames.CSharp, supportsUnannotatedAPIs: true, "Regex", "Regexp"), Shared] + internal class CSharpRegexClassifier : AbstractRegexClassifier { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public CSharpRegexEmbeddedLanguageClassifier() + public CSharpRegexClassifier() : base(CSharpEmbeddedLanguagesProvider.Info) { } diff --git a/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpRegexDocumentHighlighter.cs b/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpRegexDocumentHighlighter.cs new file mode 100644 index 0000000000000..02f9cb521f892 --- /dev/null +++ b/src/Features/CSharp/Portable/EmbeddedLanguages/CSharpRegexDocumentHighlighter.cs @@ -0,0 +1,26 @@ +// 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; +using System.Composition; +using Microsoft.CodeAnalysis.CSharp.EmbeddedLanguages.LanguageServices; +using Microsoft.CodeAnalysis.DocumentHighlighting; +using Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions.LanguageServices; +using Microsoft.CodeAnalysis.Host.Mef; + +namespace Microsoft.CodeAnalysis.CSharp.Features.EmbeddedLanguages +{ + [ExtensionOrder(Before = PredefinedEmbeddedLanguageNames.Json)] + [ExportEmbeddedLanguageDocumentHighlighter( + PredefinedEmbeddedLanguageNames.Regex, LanguageNames.CSharp, supportsUnannotatedAPIs: true, "Regex", "Regexp"), Shared] + internal class CSharpRegexDocumentHighlighter : AbstractRegexDocumentHighlighter + { + [ImportingConstructor] + [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] + public CSharpRegexDocumentHighlighter() + : base(CSharpEmbeddedLanguagesProvider.Info) + { + } + } +} diff --git a/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs b/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs index 64a1da145f1b8..d3e7679e64fd8 100644 --- a/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs +++ b/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs @@ -11,7 +11,6 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.EmbeddedLanguages; using Microsoft.CodeAnalysis.ErrorReporting; -using Microsoft.CodeAnalysis.Features.EmbeddedLanguages; using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.PooledObjects; @@ -21,8 +20,19 @@ namespace Microsoft.CodeAnalysis.DocumentHighlighting { - internal abstract partial class AbstractDocumentHighlightsService : IDocumentHighlightsService + internal abstract partial class AbstractDocumentHighlightsService : + AbstractEmbeddedLanguageFeatureService, + IDocumentHighlightsService { + protected AbstractDocumentHighlightsService( + string languageName, + EmbeddedLanguageInfo info, + ISyntaxKinds syntaxKinds, + IEnumerable> allServices) + : base(languageName, info, syntaxKinds, allServices) + { + } + public async Task> GetDocumentHighlightsAsync( Document document, int position, IImmutableSet documentsToSearch, HighlightingOptions options, CancellationToken cancellationToken) { @@ -53,14 +63,13 @@ public async Task> GetDocumentHighlightsAsync private async Task> GetDocumentHighlightsInCurrentProcessAsync( Document document, int position, IImmutableSet documentsToSearch, HighlightingOptions options, CancellationToken cancellationToken) { - var result = await TryGetEmbeddedLanguageHighlightsAsync( - document, position, documentsToSearch, options, cancellationToken).ConfigureAwait(false); + var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var result = TryGetEmbeddedLanguageHighlights(document, semanticModel, position, options, cancellationToken); if (!result.IsDefaultOrEmpty) return result; var solution = document.Project.Solution; - var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var symbol = await SymbolFinder.FindSymbolAtPositionAsync( semanticModel, position, solution.Workspace, cancellationToken).ConfigureAwait(false); if (symbol == null) @@ -80,26 +89,18 @@ private async Task> GetDocumentHighlightsInCu return tags; } - private static async Task> TryGetEmbeddedLanguageHighlightsAsync( - Document document, int position, IImmutableSet documentsToSearch, HighlightingOptions options, CancellationToken cancellationToken) + private ImmutableArray TryGetEmbeddedLanguageHighlights( + Document document, SemanticModel semanticModel, int position, HighlightingOptions options, CancellationToken cancellationToken) { - var languagesProvider = document.GetLanguageService(); - if (languagesProvider != null) + var root = semanticModel.SyntaxTree.GetRoot(cancellationToken); + var token = root.FindToken(position); + var embeddedHighlightsServices = this.GetServices(semanticModel, token, cancellationToken); + foreach (var service in embeddedHighlightsServices) { - foreach (var language in languagesProvider.Languages) - { - var highlighter = (language as IEmbeddedLanguageFeatures)?.DocumentHighlightsService; - if (highlighter != null) - { - var highlights = await highlighter.GetDocumentHighlightsAsync( - document, position, documentsToSearch, options, cancellationToken).ConfigureAwait(false); - - if (!highlights.IsDefaultOrEmpty) - { - return highlights; - } - } - } + var result = service.Value.GetDocumentHighlights( + document, semanticModel, token, position, options, cancellationToken); + if (!result.IsDefaultOrEmpty) + return result; } return default; @@ -116,7 +117,7 @@ private async Task> GetTagsForReferencedSymbo { var progress = new StreamingProgressCollector(); - var options = FindSymbols.FindReferencesSearchOptions.GetFeatureOptionsForStartingSymbol(symbol); + var options = FindReferencesSearchOptions.GetFeatureOptionsForStartingSymbol(symbol); await SymbolFinder.FindReferencesAsync( symbol, document.Project.Solution, progress, documentsToSearch, options, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/DocumentHighlighting/ExportEmbeddedLanguageDocumentHighlighterAttribute.cs b/src/Features/Core/Portable/DocumentHighlighting/ExportEmbeddedLanguageDocumentHighlighterAttribute.cs new file mode 100644 index 0000000000000..4592d47cf3a1f --- /dev/null +++ b/src/Features/Core/Portable/DocumentHighlighting/ExportEmbeddedLanguageDocumentHighlighterAttribute.cs @@ -0,0 +1,26 @@ +// 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; + +namespace Microsoft.CodeAnalysis.DocumentHighlighting +{ + /// + /// Use this attribute to export a . + /// + internal class ExportEmbeddedLanguageDocumentHighlighterAttribute : ExportEmbeddedLanguageFeatureServiceAttribute + { + public ExportEmbeddedLanguageDocumentHighlighterAttribute( + string name, string language, params string[] identifiers) + : this(name, language, supportsUnannotatedAPIs: false, identifiers) + { + } + + public ExportEmbeddedLanguageDocumentHighlighterAttribute( + string name, string language, bool supportsUnannotatedAPIs, params string[] identifiers) + : base(typeof(IEmbeddedLanguageDocumentHighlighter), name, language, supportsUnannotatedAPIs, identifiers) + { + } + } +} diff --git a/src/Features/Core/Portable/DocumentHighlighting/IEmbeddedLanguageDocumentHighlighter.cs b/src/Features/Core/Portable/DocumentHighlighting/IEmbeddedLanguageDocumentHighlighter.cs new file mode 100644 index 0000000000000..5d7e6fba9253b --- /dev/null +++ b/src/Features/Core/Portable/DocumentHighlighting/IEmbeddedLanguageDocumentHighlighter.cs @@ -0,0 +1,23 @@ +// 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.Collections.Immutable; +using System.Threading; +using Microsoft.CodeAnalysis.EmbeddedLanguages; + +namespace Microsoft.CodeAnalysis.DocumentHighlighting +{ + /// + internal interface IEmbeddedLanguageDocumentHighlighter : IEmbeddedLanguageFeatureService + { + /// + ImmutableArray GetDocumentHighlights( + Document document, + SemanticModel semanticModel, + SyntaxToken token, + int position, + HighlightingOptions options, + CancellationToken cancellationToken); + } +} diff --git a/src/Features/Core/Portable/EmbeddedLanguages/IEmbeddedLanguageFeatures.cs b/src/Features/Core/Portable/EmbeddedLanguages/IEmbeddedLanguageFeatures.cs index e59d78437770e..5864f01b91d9b 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/IEmbeddedLanguageFeatures.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/IEmbeddedLanguageFeatures.cs @@ -13,11 +13,6 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages /// internal interface IEmbeddedLanguageFeatures : IEmbeddedLanguage { - /// - /// A optional highlighter that can highlight spans for an embedded language string. - /// - IDocumentHighlightsService? DocumentHighlightsService { get; } - /// /// Completion provider that can provide completion items for this /// specific embedded language. diff --git a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonEmbeddedLanguageClassifier.cs b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonClassifier.cs similarity index 97% rename from src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonEmbeddedLanguageClassifier.cs rename to src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonClassifier.cs index 514a909bae8b0..5b4ff21062573 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonEmbeddedLanguageClassifier.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/AbstractJsonClassifier.cs @@ -17,12 +17,12 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.Json.LanguageService /// /// Classifier impl for embedded json strings. /// - internal abstract class AbstractJsonEmbeddedLanguageClassifier : IEmbeddedLanguageClassifier + internal abstract class AbstractJsonClassifier : IEmbeddedLanguageClassifier { private static readonly ObjectPool s_visitorPool = new(() => new Visitor()); private readonly EmbeddedLanguageInfo _info; - public AbstractJsonEmbeddedLanguageClassifier(EmbeddedLanguageInfo info) + public AbstractJsonClassifier(EmbeddedLanguageInfo info) { _info = info; } diff --git a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonEmbeddedLanguage.cs b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonEmbeddedLanguage.cs index 35fe94a28c045..8bfd3b49ceb1e 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonEmbeddedLanguage.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/Json/LanguageServices/JsonEmbeddedLanguage.cs @@ -9,9 +9,6 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.Json.LanguageService { internal class JsonEmbeddedLanguage : IEmbeddedLanguageFeatures { - // No document-highlights for embedded json currently. - public IDocumentHighlightsService? DocumentHighlightsService => null; - // No completion for embedded json currently. public EmbeddedLanguageCompletionProvider? CompletionProvider => null; } diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexEmbeddedLanguageClassifier.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexClassifier.cs similarity index 98% rename from src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexEmbeddedLanguageClassifier.cs rename to src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexClassifier.cs index 1a66b8761ce6b..638c1632d8c6d 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexEmbeddedLanguageClassifier.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexClassifier.cs @@ -18,13 +18,13 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions.L /// /// Classifier impl for embedded regex strings. /// - internal abstract class AbstractRegexEmbeddedLanguageClassifier : IEmbeddedLanguageClassifier + internal abstract class AbstractRegexClassifier : IEmbeddedLanguageClassifier { private static readonly ObjectPool s_visitorPool = SharedPools.Default(); private readonly EmbeddedLanguageInfo _info; - protected AbstractRegexEmbeddedLanguageClassifier(EmbeddedLanguageInfo info) + protected AbstractRegexClassifier(EmbeddedLanguageInfo info) { _info = info; } diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexDocumentHighlightsService.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDocumentHighlighter.cs similarity index 84% rename from src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexDocumentHighlightsService.cs rename to src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDocumentHighlighter.cs index 00753e8bbfa32..3d97b028e2645 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexDocumentHighlightsService.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/AbstractRegexDocumentHighlighter.cs @@ -2,13 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - using System; using System.Collections.Immutable; using System.Threading; -using System.Threading.Tasks; using Microsoft.CodeAnalysis.DocumentHighlighting; +using Microsoft.CodeAnalysis.EmbeddedLanguages; using Microsoft.CodeAnalysis.EmbeddedLanguages.Common; using Microsoft.CodeAnalysis.EmbeddedLanguages.RegularExpressions; using Microsoft.CodeAnalysis.EmbeddedLanguages.VirtualChars; @@ -18,22 +16,22 @@ namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions.L { using RegexToken = EmbeddedSyntaxToken; - internal sealed class RegexDocumentHighlightsService : IDocumentHighlightsService + internal abstract class AbstractRegexDocumentHighlighter : IEmbeddedLanguageDocumentHighlighter { - private readonly RegexEmbeddedLanguage _language; + private readonly EmbeddedLanguageInfo _info; - public RegexDocumentHighlightsService(RegexEmbeddedLanguage language) - => _language = language; + protected AbstractRegexDocumentHighlighter(EmbeddedLanguageInfo info) + => _info = info; - public async Task> GetDocumentHighlightsAsync( - Document document, int position, IImmutableSet documentsToSearch, HighlightingOptions options, CancellationToken cancellationToken) + public ImmutableArray GetDocumentHighlights( + Document document, SemanticModel semanticModel, SyntaxToken token, int position, HighlightingOptions options, CancellationToken cancellationToken) { if (!options.HighlightRelatedRegexComponentsUnderCursor) - { return default; - } - var tree = await _language.TryGetTreeAtPositionAsync(document, position, cancellationToken).ConfigureAwait(false); + var detector = RegexLanguageDetector.GetOrCreate(semanticModel.Compilation, _info); + var tree = detector.TryParseString(token, semanticModel, cancellationToken); + return tree == null ? default : ImmutableArray.Create(new DocumentHighlights(document, GetHighlights(tree, position))); @@ -115,7 +113,7 @@ private static RegexToken GetCaptureToken(RegexEscapeNode node) _ => throw new InvalidOperationException(), }; - private RegexEscapeNode FindReferenceNode(RegexNode node, VirtualChar virtualChar) + private RegexEscapeNode? FindReferenceNode(RegexNode node, VirtualChar virtualChar) { if (node.Kind is RegexKind.BackreferenceEscape or RegexKind.CaptureEscape or diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexEmbeddedLanguage.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexEmbeddedLanguage.cs index d8d7fb443f444..2c96c08d1a21d 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexEmbeddedLanguage.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/LanguageServices/RegexEmbeddedLanguage.cs @@ -5,9 +5,9 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Completion.Providers; -using Microsoft.CodeAnalysis.DocumentHighlighting; using Microsoft.CodeAnalysis.EmbeddedLanguages; using Microsoft.CodeAnalysis.EmbeddedLanguages.RegularExpressions; +using Microsoft.CodeAnalysis.Shared.Extensions; namespace Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions.LanguageServices { @@ -17,7 +17,6 @@ internal class RegexEmbeddedLanguage : IEmbeddedLanguageFeatures private readonly AbstractEmbeddedLanguageFeaturesProvider _provider; - public IDocumentHighlightsService? DocumentHighlightsService { get; } public EmbeddedLanguageCompletionProvider CompletionProvider { get; } public RegexEmbeddedLanguage( @@ -28,18 +27,16 @@ public RegexEmbeddedLanguage( _provider = provider; - DocumentHighlightsService = new RegexDocumentHighlightsService(this); CompletionProvider = new RegexEmbeddedCompletionProvider(this); } -#nullable disable internal async Task<(RegexTree tree, SyntaxToken token)> TryGetTreeAndTokenAtPositionAsync( Document document, int position, CancellationToken cancellationToken) { - var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(position); - var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var detector = RegexLanguageDetector.GetOrCreate(semanticModel.Compilation, this.Info); var tree = detector.TryParseString(token, semanticModel, cancellationToken); return tree == null ? default : (tree, token); diff --git a/src/Features/VisualBasic/Portable/DocumentHighlighting/VisualBasicDocumentHighlightsService.vb b/src/Features/VisualBasic/Portable/DocumentHighlighting/VisualBasicDocumentHighlightsService.vb index 9ba01d722e9b9..280a9004efa96 100644 --- a/src/Features/VisualBasic/Portable/DocumentHighlighting/VisualBasicDocumentHighlightsService.vb +++ b/src/Features/VisualBasic/Portable/DocumentHighlighting/VisualBasicDocumentHighlightsService.vb @@ -4,7 +4,10 @@ Imports System.Composition Imports Microsoft.CodeAnalysis.DocumentHighlighting +Imports Microsoft.CodeAnalysis.EmbeddedLanguages Imports Microsoft.CodeAnalysis.Host.Mef +Imports Microsoft.CodeAnalysis.VisualBasic.EmbeddedLanguages.LanguageServices +Imports Microsoft.CodeAnalysis.VisualBasic.LanguageServices Namespace Microsoft.CodeAnalysis.VisualBasic.DocumentHighlighting @@ -13,7 +16,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.DocumentHighlighting - Public Sub New() + Public Sub New( + services As IEnumerable(Of Lazy(Of IEmbeddedLanguageDocumentHighlighter, EmbeddedLanguageMetadata))) + MyBase.New( + LanguageNames.VisualBasic, + VisualBasicEmbeddedLanguagesProvider.Info, + VisualBasicSyntaxKinds.Instance, + services) End Sub End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicJsonEmbeddedLanguageClassifier.vb b/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicJsonClassifier.vb similarity index 78% rename from src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicJsonEmbeddedLanguageClassifier.vb rename to src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicJsonClassifier.vb index 4ddcd12a53ff2..7019e7e4e0c3a 100644 --- a/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicJsonEmbeddedLanguageClassifier.vb +++ b/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicJsonClassifier.vb @@ -10,9 +10,9 @@ Imports Microsoft.CodeAnalysis.VisualBasic.EmbeddedLanguages.LanguageServices Namespace Microsoft.CodeAnalysis.VisualBasic.Features.EmbeddedLanguages - Friend Class VisualBasicJsonEmbeddedLanguageClassifier - Inherits AbstractJsonEmbeddedLanguageClassifier + PredefinedEmbeddedLanguageNames.Json, LanguageNames.VisualBasic, True, "Json"), [Shared]> + Friend Class VisualBasicJsonClassifier + Inherits AbstractJsonClassifier diff --git a/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicRegexEmbeddedLanguageClassifier.vb b/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicRegexClassifier.vb similarity index 76% rename from src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicRegexEmbeddedLanguageClassifier.vb rename to src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicRegexClassifier.vb index 89816f2a8bfcd..a5ebd4edf9e74 100644 --- a/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicRegexEmbeddedLanguageClassifier.vb +++ b/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicRegexClassifier.vb @@ -11,11 +11,11 @@ Imports Microsoft.CodeAnalysis.VisualBasic.EmbeddedLanguages.LanguageServices Namespace Microsoft.CodeAnalysis.VisualBasic.Features.EmbeddedLanguages ' Order regex classification before json classification. Json lights up on probable-json strings, but we don't ' want that to happen for APIs that are certain to be another language Like Regex. - + - Friend Class VisualBasicRegexEmbeddedLanguageClassifier - Inherits AbstractRegexEmbeddedLanguageClassifier + PredefinedEmbeddedLanguageNames.Regex, LanguageNames.VisualBasic, True, "Regex", "Regexp"), [Shared]> + Friend Class VisualBasicRegexClassifier + Inherits AbstractRegexClassifier diff --git a/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicRegexDocumentHighlighter.vb b/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicRegexDocumentHighlighter.vb new file mode 100644 index 0000000000000..479bb67ee7eaa --- /dev/null +++ b/src/Features/VisualBasic/Portable/EmbeddedLanguages/VisualBasicRegexDocumentHighlighter.vb @@ -0,0 +1,27 @@ +' 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. + +Imports System.Composition +Imports Microsoft.CodeAnalysis.Classification +Imports Microsoft.CodeAnalysis.DocumentHighlighting +Imports Microsoft.CodeAnalysis.Features.EmbeddedLanguages.RegularExpressions.LanguageServices +Imports Microsoft.CodeAnalysis.Host.Mef +Imports Microsoft.CodeAnalysis.VisualBasic.EmbeddedLanguages.LanguageServices + +Namespace Microsoft.CodeAnalysis.VisualBasic.Features.EmbeddedLanguages + ' Order regex classification before json classification. Json lights up on probable-json strings, but we don't + ' want that to happen for APIs that are certain to be another language Like Regex. + + + Friend Class VisualBasicRegexDocumentHighlighter + Inherits AbstractRegexDocumentHighlighter + + + + Public Sub New() + MyBase.New(VisualBasicEmbeddedLanguagesProvider.Info) + End Sub + End Class +End Namespace diff --git a/src/Workspaces/Core/Portable/EmbeddedLanguages/ExportEmbeddedLanguageFeatureServiceAttribute.cs b/src/Workspaces/Core/Portable/EmbeddedLanguages/ExportEmbeddedLanguageFeatureServiceAttribute.cs index d7c8a79825605..eb5a9a9b22e7f 100644 --- a/src/Workspaces/Core/Portable/EmbeddedLanguages/ExportEmbeddedLanguageFeatureServiceAttribute.cs +++ b/src/Workspaces/Core/Portable/EmbeddedLanguages/ExportEmbeddedLanguageFeatureServiceAttribute.cs @@ -59,8 +59,8 @@ internal ExportEmbeddedLanguageFeatureServiceAttribute( if (SupportsUnannotatedAPIs) { - Contract.ThrowIfFalse(name is PredefinedEmbeddedLanguageClassifierNames.Regex or PredefinedEmbeddedLanguageClassifierNames.Json, - $"Only '{PredefinedEmbeddedLanguageClassifierNames.Regex}' or '{PredefinedEmbeddedLanguageClassifierNames.Json}' are allowed to '{nameof(SupportsUnannotatedAPIs)}'"); + Contract.ThrowIfFalse(name is PredefinedEmbeddedLanguageNames.Regex or PredefinedEmbeddedLanguageNames.Json, + $"Only '{PredefinedEmbeddedLanguageNames.Regex}' or '{PredefinedEmbeddedLanguageNames.Json}' are allowed to '{nameof(SupportsUnannotatedAPIs)}'"); } } } diff --git a/src/Workspaces/Core/Portable/Classification/EmbeddedLanguages/PredefinedEmbeddedLanguageClassifierNames.cs b/src/Workspaces/Core/Portable/EmbeddedLanguages/PredefinedEmbeddedLanguageClassifierNames.cs similarity index 73% rename from src/Workspaces/Core/Portable/Classification/EmbeddedLanguages/PredefinedEmbeddedLanguageClassifierNames.cs rename to src/Workspaces/Core/Portable/EmbeddedLanguages/PredefinedEmbeddedLanguageClassifierNames.cs index 94e9a645b8e4c..567234a4e5f9a 100644 --- a/src/Workspaces/Core/Portable/Classification/EmbeddedLanguages/PredefinedEmbeddedLanguageClassifierNames.cs +++ b/src/Workspaces/Core/Portable/EmbeddedLanguages/PredefinedEmbeddedLanguageClassifierNames.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace Microsoft.CodeAnalysis.Classification +namespace Microsoft.CodeAnalysis { - internal static class PredefinedEmbeddedLanguageClassifierNames + internal static class PredefinedEmbeddedLanguageNames { public const string Regex = nameof(Regex);