// // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. // // This file contain implementations details that are subject to change without notice. // Use at your own risk. // namespace Microsoft.VisualStudio.Text.Operations.Implementation { using System; using System.Collections.Generic; using System.ComponentModel.Composition; using Microsoft.VisualStudio.Text.Utilities; using Microsoft.VisualStudio.Utilities; /// /// Provides a service to help with the Text Structure Navigation. /// [Export(typeof(ITextStructureNavigatorSelectorService))] internal sealed class TextStructureNavigatorSelectorService : ITextStructureNavigatorSelectorService { [Import] internal IContentTypeRegistryService _contentTypeRegistryService { get; set; } [Import] internal GuardedOperations _guardedOperations { get; set; } [ImportMany(typeof(ITextStructureNavigatorProvider))] internal List> _textStructureNavigatorProviders { get; set; } public ITextStructureNavigator GetTextStructureNavigator(ITextBuffer textBuffer) { if (textBuffer == null) { throw new ArgumentNullException(nameof(textBuffer)); } ITextStructureNavigator navigator = null; if (textBuffer.Properties.TryGetProperty(typeof(ITextStructureNavigator), out navigator)) { return navigator; } navigator = CreateNavigator(textBuffer, textBuffer.ContentType); // Cache navigator until buffer's content type changes. textBuffer.Properties[typeof(ITextStructureNavigator)] = navigator; textBuffer.ContentTypeChanged += OnContentTypeChanged; return navigator; } public ITextStructureNavigator CreateTextStructureNavigator(ITextBuffer textBuffer, IContentType contentType) { if (textBuffer == null) { throw new ArgumentNullException(nameof(textBuffer)); } if (contentType == null) { throw new ArgumentNullException(nameof(contentType)); } return CreateNavigator(textBuffer, contentType); } #region Private Helpers private ITextStructureNavigator CreateNavigator(ITextBuffer textBuffer, IContentType contentType) { ITextStructureNavigator navigator = _guardedOperations.InvokeBestMatchingFactory (_textStructureNavigatorProviders, contentType, (provider) => (provider.CreateTextStructureNavigator(textBuffer)), _contentTypeRegistryService, this); // If we're here, and there's no navigator found, we'll create a default one if (navigator == null) { navigator = new DefaultTextNavigator(textBuffer, _contentTypeRegistryService); } return navigator; } /// /// Invalidate our cached navigator. /// void OnContentTypeChanged(object sender, ContentTypeChangedEventArgs e) { ITextBuffer buffer = e.Before.TextBuffer; buffer.Properties.RemoveProperty(typeof(ITextStructureNavigator)); buffer.ContentTypeChanged -= OnContentTypeChanged; } #endregion // Private Helpers } }