1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
//
// 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;
/// <summary>
/// Provides a service to help with the Text Structure Navigation.
/// </summary>
[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<Lazy<ITextStructureNavigatorProvider, IContentTypeMetadata>> _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;
}
/// <summary>
/// Invalidate our cached navigator.
/// </summary>
void OnContentTypeChanged(object sender, ContentTypeChangedEventArgs e)
{
ITextBuffer buffer = e.Before.TextBuffer;
buffer.Properties.RemoveProperty(typeof(ITextStructureNavigator));
buffer.ContentTypeChanged -= OnContentTypeChanged;
}
#endregion // Private Helpers
}
}
|