diff --git a/global.json b/global.json
deleted file mode 100644
index b887553..0000000
--- a/global.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "sdk": {
- "version": "7.0.100",
- "rollForward": "feature"
- }
-}
diff --git a/src/ColumnGuide/ColumnGuideAdornment.cs b/src/ColumnGuide/ColumnGuideAdornment.cs
index 2fec024..e770974 100644
--- a/src/ColumnGuide/ColumnGuideAdornment.cs
+++ b/src/ColumnGuide/ColumnGuideAdornment.cs
@@ -1,7 +1,6 @@
// Copyright (c) Paul Harrington. All Rights Reserved. Licensed under the MIT License. See LICENSE in the project root for license information.
using Microsoft.ApplicationInsights.DataContracts;
-using Microsoft.VisualStudio.CodingConventions;
using Microsoft.VisualStudio.Text.Editor;
using System;
using System.Collections.Generic;
@@ -65,19 +64,18 @@ internal class ColumnGuideAdornment : IDisposable
/// The upon which the adornment will be drawn
/// The guideline settings.
/// The guideline brush.
- /// The coding conventions manager for handling .editorconfig settings.
- /// Telemetry interface.
- public ColumnGuideAdornment(IWpfTextView view, ITextEditorGuidesSettings settings, GuidelineBrush guidelineBrush, ICodingConventionsManager codingConventionsManager)
+ /// The coding conventions manager for handling .editorconfig settings.
+ public ColumnGuideAdornment(IWpfTextView view, ITextEditorGuidesSettings settings, GuidelineBrush guidelineBrush, CodingConventions codingConventions)
{
_view = view;
_guidelineBrush = guidelineBrush;
_guidelineBrush.BrushChanged += GuidelineBrushChanged;
_strokeParameters = StrokeParameters.FromBrush(_guidelineBrush.Brush);
- if (codingConventionsManager != null && view.TryGetTextDocument(out var textDocument))
+ if (codingConventions != null)
{
_codingConventionsCancellationTokenSource = new CancellationTokenSource();
- var fireAndForgetTask = LoadGuidelinesFromEditorConfigAsync(codingConventionsManager, textDocument.FilePath);
+ var fireAndForgetTask = LoadGuidelinesFromEditorConfigAsync(codingConventions, view);
}
InitializeGuidelines(settings.GuideLinePositionsInChars);
@@ -274,32 +272,34 @@ private void AddGuidelinesToAdornmentLayer()
///
/// Try to load guideline positions from .editorconfig
///
- /// The coding conventions (.editorconfig) manager.
- /// Path to the document being edited.
+ /// The coding conventions (.editorconfig) manager.
+ /// Editor's WPF view.
/// A task which completes when the convention has been loaded and applied.
- private async Task LoadGuidelinesFromEditorConfigAsync(ICodingConventionsManager codingConventionsManager, string filePath)
+ private async Task LoadGuidelinesFromEditorConfigAsync(CodingConventions codingConventions, IWpfTextView view)
{
- var cancellationToken = _codingConventionsCancellationTokenSource.Token;
- var codingConventionContext = await codingConventionsManager.GetConventionContextAsync(filePath, cancellationToken).ConfigureAwait(false);
+ CancellationToken cancellationToken = _codingConventionsCancellationTokenSource.Token;
+ CodingConventions.Context context = await codingConventions.CreateContextAsync(view, cancellationToken).ConfigureAwait(false);
+ if (context is null)
+ {
+ return;
+ }
- codingConventionContext.CodingConventionsChangedAsync += OnCodingConventionsChangedAsync;
- cancellationToken.Register(() => codingConventionContext.CodingConventionsChangedAsync -= OnCodingConventionsChangedAsync);
+ context.ConventionsChanged += UpdateGuidelinesFromCodingConvention;
+ cancellationToken.Register(() => context.ConventionsChanged -= UpdateGuidelinesFromCodingConvention);
- await UpdateGuidelinesFromCodingConventionAsync(codingConventionContext, cancellationToken).ConfigureAwait(false);
+ UpdateGuidelinesFromCodingConvention(context);
}
- private Task OnCodingConventionsChangedAsync(object sender, CodingConventionsChangedEventArgs arg) => UpdateGuidelinesFromCodingConventionAsync((ICodingConventionContext)sender, _codingConventionsCancellationTokenSource.Token);
-
- private Task UpdateGuidelinesFromCodingConventionAsync(ICodingConventionContext codingConventionContext, CancellationToken cancellationToken)
+ private void UpdateGuidelinesFromCodingConvention(CodingConventions.Context context)
{
- if (cancellationToken.IsCancellationRequested)
+ if (_codingConventionsCancellationTokenSource.Token.IsCancellationRequested)
{
- return Task.FromCanceled(cancellationToken);
+ return;
}
StrokeParameters strokeParameters = null;
- if (codingConventionContext.CurrentConventions.TryGetConventionValue("guidelines_style", out string guidelines_style))
+ if (context.TryGetCurrentSetting("guidelines_style", out string guidelines_style))
{
if (TryParseStrokeParametersFromCodingConvention(guidelines_style, out strokeParameters))
{
@@ -310,13 +310,13 @@ private Task UpdateGuidelinesFromCodingConventionAsync(ICodingConventionContext
ICollection guidelines = null;
- if (codingConventionContext.CurrentConventions.TryGetConventionValue("guidelines", out string guidelinesConventionValue))
+ if (context.TryGetCurrentSetting("guidelines", out string guidelinesConventionValue))
{
guidelines = ParseGuidelinesFromCodingConvention(guidelinesConventionValue, strokeParameters);
}
// Also support max_line_length: https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties#max_line_length
- if (codingConventionContext.CurrentConventions.TryGetConventionValue("max_line_length", out string max_line_length) && TryParsePosition(max_line_length, out int maxLineLengthValue))
+ if (context.TryGetCurrentSetting("max_line_length", out string max_line_length) && TryParsePosition(max_line_length, out int maxLineLengthValue))
{
(guidelines ?? (guidelines = new List())).Add(new Guideline(maxLineLengthValue, strokeParameters));
}
@@ -354,8 +354,6 @@ private Task UpdateGuidelinesFromCodingConventionAsync(ICodingConventionContext
Telemetry.Client.TrackEvent(eventTelemetry);
s_sentEditorConfigTelemetry = true;
}
-
- return Task.CompletedTask;
}
private bool HaveGuidelinesChanged(IEnumerable newGuidelines)
diff --git a/src/ColumnGuide/ColumnGuideFactory.cs b/src/ColumnGuide/ColumnGuideFactory.cs
index 38fa358..4058ca8 100644
--- a/src/ColumnGuide/ColumnGuideFactory.cs
+++ b/src/ColumnGuide/ColumnGuideFactory.cs
@@ -1,7 +1,6 @@
// Copyright (c) Paul Harrington. All Rights Reserved. Licensed under the MIT License. See LICENSE in the project root for license information.
using Microsoft.ApplicationInsights.DataContracts;
-using Microsoft.VisualStudio.CodingConventions;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Utilities;
using System.Collections.Generic;
@@ -42,7 +41,7 @@ public void TextViewCreated(IWpfTextView textView)
{
// Always create the adornment, even if there are no guidelines, since we
// respond to dynamic changes.
- var _ = new ColumnGuideAdornment(textView, TextEditorGuidesSettings, GuidelineBrush, CodingConventionsManager);
+ var _ = new ColumnGuideAdornment(textView, TextEditorGuidesSettings, GuidelineBrush, CodingConventions);
}
public void OnImportsSatisfied()
@@ -120,11 +119,11 @@ internal static void AddGuidelinesToTelemetry(EventTelemetry eventTelemetry, IEn
[Import]
private GuidelineBrush GuidelineBrush { get; set; }
- [Import(AllowDefault = true)]
- private ICodingConventionsManager CodingConventionsManager { get; set; }
+ [Import]
+ private CodingConventions CodingConventions { get; set; }
[Import]
private HostServices HostServices { get; set; }
}
- #endregion //Adornment Factory
+#endregion //Adornment Factory
}
diff --git a/src/VSIX/CodingConventions.cs b/src/VSIX/CodingConventions.cs
new file mode 100644
index 0000000..faaf5b0
--- /dev/null
+++ b/src/VSIX/CodingConventions.cs
@@ -0,0 +1,71 @@
+// Copyright (c) Paul Harrington. All Rights Reserved. Licensed under the MIT License. See LICENSE in the project root for license information.
+
+using System.ComponentModel.Composition;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.CodingConventions;
+using Microsoft.VisualStudio.Text.Editor;
+
+namespace EditorGuidelines
+{
+ ///
+ /// Coding conventions support via Microsoft.VisualStudio.CodingConventions assembly.
+ ///
+ [Export]
+ internal sealed class CodingConventions
+ {
+ ///
+ /// Try to import from Microsoft.VisualStudio.CodingConventions.
+ ///
+ [Import(AllowDefault = true)]
+ private ICodingConventionsManager CodingConventionsManager { get; set; }
+
+ public async Task CreateContextAsync(IWpfTextView view, CancellationToken cancellationToken)
+ {
+ if (CodingConventionsManager is null)
+ {
+ // Coding Conventions not available in this SKU.
+ return null;
+ }
+
+ if (!view.TryGetTextDocument(out var textDocument))
+ {
+ return null;
+ }
+
+ string filePath = textDocument.FilePath;
+ ICodingConventionContext codingConventionContext = await CodingConventionsManager.GetConventionContextAsync(filePath, cancellationToken).ConfigureAwait(false);
+ return new Context(codingConventionContext, cancellationToken);
+ }
+
+ ///
+ /// Coding conventions narrowed to a single file.
+ ///
+ public class Context
+ {
+ private readonly ICodingConventionContext _innerContext;
+
+ public Context(ICodingConventionContext innerContext, CancellationToken cancellationToken)
+ {
+ _innerContext = innerContext;
+ _innerContext.CodingConventionsChangedAsync += OnCodingConventionsChangedAsync;
+ cancellationToken.Register(() => _innerContext.CodingConventionsChangedAsync -= OnCodingConventionsChangedAsync);
+ }
+
+ private Task OnCodingConventionsChangedAsync(object sender, CodingConventionsChangedEventArgs arg)
+ {
+ ConventionsChanged?.Invoke(this);
+ return Task.CompletedTask;
+ }
+
+ public delegate void ConventionsChangedEventHandler(Context sender);
+
+ public event ConventionsChangedEventHandler ConventionsChanged;
+
+ public bool TryGetCurrentSetting(string key, out string value)
+ {
+ return _innerContext.CurrentConventions.TryGetConventionValue(key, out value);
+ }
+ }
+ }
+}
diff --git a/src/VSIX_Dev17/CodingConventions.cs b/src/VSIX_Dev17/CodingConventions.cs
new file mode 100644
index 0000000..5af8f15
--- /dev/null
+++ b/src/VSIX_Dev17/CodingConventions.cs
@@ -0,0 +1,72 @@
+// Copyright (c) Paul Harrington. All Rights Reserved. Licensed under the MIT License. See LICENSE in the project root for license information.
+
+using System.ComponentModel.Composition;
+using System.Threading.Tasks;
+using System.Threading;
+using Microsoft.VisualStudio.Text.Editor;
+using System.Collections.Generic;
+
+namespace EditorGuidelines
+{
+ ///
+ /// Dev 17 support for Coding Conventions. Uses the dictionary supplied via .
+ ///
+ [Export]
+ internal sealed class CodingConventions
+ {
+ public Task CreateContextAsync(IWpfTextView view, CancellationToken cancellationToken)
+ {
+ return Task.FromResult(new Context(view.Options, cancellationToken));
+ }
+
+ ///
+ /// Coding conventions narrowed to a single file.
+ ///
+ public class Context
+ {
+ private readonly IEditorOptions _editorOptions;
+ private readonly CancellationToken _cancellationToken;
+ private IReadOnlyDictionary _currentConventions;
+
+ // This is the same as DefaultOptions.RawCodingConventionsSnapshotOptionName from the 17.6
+ // editor SDK. However, by not referencing that constant, we can avoid taking a dependency
+ // on the 17.6 SDK and can continue to load on earlier versions (albeit without
+ // CodingConventions support).
+ private const string c_codingConventionsSnapshotOptionName = "CodingConventionsSnapshot";
+
+ public Context(IEditorOptions editorOptions, CancellationToken cancellationToken)
+ {
+ _editorOptions = editorOptions;
+ _cancellationToken = cancellationToken;
+
+ _editorOptions.OptionChanged += OnEditorOptionChanged;
+ _cancellationToken.Register(() => _editorOptions.OptionChanged -= OnEditorOptionChanged);
+ }
+
+ private void OnEditorOptionChanged(object sender, EditorOptionChangedEventArgs e)
+ {
+ if (e.OptionId == c_codingConventionsSnapshotOptionName)
+ {
+ _currentConventions = _editorOptions.GetOptionValue>(c_codingConventionsSnapshotOptionName);
+ ConventionsChanged?.Invoke(this);
+ }
+ }
+
+ public delegate void ConventionsChangedEventHandler(Context sender);
+
+ public event ConventionsChangedEventHandler ConventionsChanged;
+
+ public bool TryGetCurrentSetting(string key, out string value)
+ {
+ if (_currentConventions is null || !_currentConventions.TryGetValue(key, out object obj) || obj is null)
+ {
+ value = null;
+ return false;
+ }
+
+ value = obj.ToString();
+ return !string.IsNullOrEmpty(value);
+ }
+ }
+ }
+}
diff --git a/src/VSIX_Dev17/VSIX_Dev17.csproj b/src/VSIX_Dev17/VSIX_Dev17.csproj
index 429b11c..28f99b2 100644
--- a/src/VSIX_Dev17/VSIX_Dev17.csproj
+++ b/src/VSIX_Dev17/VSIX_Dev17.csproj
@@ -39,13 +39,10 @@
-
-
compile; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive