Updating samples for VS 17.4 Preview 2
This commit is contained in:
Родитель
5a45ba62e1
Коммит
b3cf6e0baf
|
@ -5,14 +5,15 @@
|
|||
<LangVersion>10</LangVersion>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<NoWarn>$(NoWarn);CS1591;IDE0008;CA1812</NoWarn>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
|
||||
<!-- The VisualStudio.Extensibility preview packages are available from the azure-public/vside/vssdk feed -->
|
||||
<RestoreAdditionalProjectSources>https://pkgs.dev.azure.com/azure-public/vside/_packaging/vssdk/nuget/v3/index.json;$(RestoreAdditionalProjectSources)</RestoreAdditionalProjectSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.1043-preview-2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.1043-preview-2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -30,9 +30,9 @@ internal class DocumentSelectorSample : ExtensionPart, ITextViewLifetimeListener
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task TextViewCreatedAsync(ITextView textView, CancellationToken cancellationToken)
|
||||
public Task TextViewCreatedAsync(ITextViewSnapshot textViewSnapshot, CancellationToken cancellationToken)
|
||||
{
|
||||
return this.RunUnitTestsAfterDelayAsync(textView, cancellationToken);
|
||||
return this.RunUnitTestsAfterDelayAsync(textViewSnapshot, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -42,21 +42,21 @@ internal class DocumentSelectorSample : ExtensionPart, ITextViewLifetimeListener
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task TextViewClosedAsync(ITextView textView, CancellationToken cancellationToken)
|
||||
public async Task TextViewClosedAsync(ITextViewSnapshot textViewSnapshot, CancellationToken cancellationToken)
|
||||
{
|
||||
await this.StopUnitTestsAsync(textView, cancellationToken);
|
||||
await this.StopUnitTestsAsync(textViewSnapshot, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task RunUnitTestsAfterDelayAsync(ITextView textView, CancellationToken cancellationToken)
|
||||
private async Task RunUnitTestsAfterDelayAsync(ITextViewSnapshot textViewSnapshot, CancellationToken cancellationToken)
|
||||
{
|
||||
await Task.Delay(500);
|
||||
var document = await textView.GetTextDocumentAsync(cancellationToken);
|
||||
var document = await textViewSnapshot.GetTextDocumentAsync(cancellationToken);
|
||||
await this.WriteToOutputWindowAsync($"Running unit tests in {document.Uri.LocalPath}", cancellationToken);
|
||||
}
|
||||
|
||||
private async Task StopUnitTestsAsync(ITextView textView, CancellationToken cancellationToken)
|
||||
private async Task StopUnitTestsAsync(ITextViewSnapshot textViewSnapshot, CancellationToken cancellationToken)
|
||||
{
|
||||
var document = await textView.GetTextDocumentAsync(cancellationToken);
|
||||
var document = await textViewSnapshot.GetTextDocumentAsync(cancellationToken);
|
||||
await this.WriteToOutputWindowAsync($"Stop running unit tests in {document.Uri.LocalPath}", cancellationToken);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.1043-preview-2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.1043-preview-2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -55,11 +55,10 @@ internal class InsertGuidCommand : Command
|
|||
}
|
||||
|
||||
var document = await textView.GetTextDocumentAsync(cancellationToken);
|
||||
await this.Extensibility.Editor().MutateAsync(
|
||||
m =>
|
||||
await this.Extensibility.Editor().EditAsync(
|
||||
batch =>
|
||||
{
|
||||
var mutator = m.GetMutator(document);
|
||||
mutator.Replace(textView.Selection.Extent, newGuidString);
|
||||
document.AsEditable(batch).Replace(textView.Selection.Extent, newGuidString);
|
||||
},
|
||||
cancellationToken);
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.1043-preview-2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.1043-preview-2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
using Microsoft.VisualStudio.Extensibility.Editor;
|
||||
|
||||
[assembly: ContentTypeDefinition("markdown")]
|
||||
[assembly: ContentTypeBaseDefinition("markdown", baseContentTypeName: "code++")]
|
||||
[assembly: DocumentTypeDefinition("markdown")]
|
||||
[assembly: DocumentTypeBaseDefinition("markdown", baseDocumentTypeName: "code++")]
|
||||
[assembly: FileExtensionMapping("markdown", fileExtension: ".md")]
|
||||
[assembly: FileExtensionMapping("markdown", fileExtension: ".mdk")]
|
||||
[assembly: FileExtensionMapping("markdown", fileExtension: ".markdown")]
|
||||
|
|
|
@ -1,170 +1,220 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.VisualStudio.Extensions.MarkdownLinter;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.RpcContracts.DiagnosticManagement;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// Helper class for running linter on a string or file.
|
||||
/// </summary>
|
||||
internal static class LinterUtilities
|
||||
namespace Microsoft.VisualStudio.Extensions.MarkdownLinter
|
||||
{
|
||||
private static Regex linterOutputRegex = new Regex(@"(?<File>[^:]+):(?<Line>\d*)(:(?<Column>\d*))? (?<Error>.*)/(?<Description>.*)", RegexOptions.Compiled);
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.VisualStudio.Extensibility.Editor.Data;
|
||||
using Microsoft.VisualStudio.Extensibility.Languages;
|
||||
using Microsoft.VisualStudio.RpcContracts.DiagnosticManagement;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// Runs markdown linter on a file path and returns diagnostic entries.
|
||||
/// Helper class for running linter on a string or file.
|
||||
/// </summary>
|
||||
/// <param name="filePath">File path to run markdown linter on.</param>
|
||||
/// <returns>an enumeration of <see cref="Diagnostic"/> entries for warnings in the markdown file.</returns>
|
||||
public static async Task<IEnumerable<Diagnostic>> RunLinterOnFileAsync(string filePath)
|
||||
internal static class LinterUtilities
|
||||
{
|
||||
using var linter = new Process();
|
||||
var lineQueue = new AsyncQueue<string>();
|
||||
private static Regex linterOutputRegex = new Regex(@"(?<File>[^:]+):(?<Line>\d*)(:(?<Column>\d*))? (?<Error>.*)/(?<Description>.*)", RegexOptions.Compiled);
|
||||
|
||||
linter.StartInfo = new ProcessStartInfo()
|
||||
/// <summary>
|
||||
/// Runs markdown linter on a file uri and returns diagnostic entries.
|
||||
/// </summary>
|
||||
/// <param name="fileUri">File uri to run markdown linter on.</param>
|
||||
/// <returns>an enumeration of <see cref="DocumentDiagnostic"/> entries for warnings in the markdown file.</returns>
|
||||
public static async Task<IEnumerable<DocumentDiagnostic>> RunLinterOnFileAsync(Uri fileUri)
|
||||
{
|
||||
FileName = "node.exe",
|
||||
Arguments = $"\"{Environment.ExpandEnvironmentVariables("%APPDATA%\\npm\\node_modules\\markdownlint-cli\\markdownlint.js")}\" \"{filePath}\"",
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
using var linter = new Process();
|
||||
var lineQueue = new AsyncQueue<string>();
|
||||
|
||||
linter.EnableRaisingEvents = true;
|
||||
linter.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
|
||||
{
|
||||
if (e.Data is object)
|
||||
linter.StartInfo = new ProcessStartInfo()
|
||||
{
|
||||
lineQueue.Enqueue(e.Data);
|
||||
}
|
||||
else
|
||||
FileName = "node.exe",
|
||||
Arguments = $"\"{Environment.ExpandEnvironmentVariables("%APPDATA%\\npm\\node_modules\\markdownlint-cli\\markdownlint.js")}\" \"{fileUri.LocalPath}\"",
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
|
||||
linter.EnableRaisingEvents = true;
|
||||
linter.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
|
||||
{
|
||||
lineQueue.Complete();
|
||||
}
|
||||
});
|
||||
if (e.Data is object)
|
||||
{
|
||||
lineQueue.Enqueue(e.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
lineQueue.Complete();
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
linter.Start();
|
||||
linter.BeginErrorReadLine();
|
||||
}
|
||||
catch (Win32Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException(message: ex.Message, innerException: ex);
|
||||
}
|
||||
|
||||
return await ProcessLinterQueueAsync(lineQueue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs markdown linter on a given text and returns diagnostic entries.
|
||||
/// </summary>
|
||||
/// <param name="content">Content to run markdown linter on.</param>
|
||||
/// <returns>an enumeration of <see cref="Diagnostic"/> entries for warnings in the markdown file.</returns>
|
||||
public static async Task<IEnumerable<Diagnostic>> RunLinterOnTextAsync(string content)
|
||||
{
|
||||
using var linter = new Process();
|
||||
var lineQueue = new AsyncQueue<string>();
|
||||
|
||||
linter.StartInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = "cmd.exe",
|
||||
Arguments = $"/k \"{Environment.ExpandEnvironmentVariables("%APPDATA%\\npm\\markdownlint.cmd")}\" -s",
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardInput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
|
||||
linter.EnableRaisingEvents = true;
|
||||
linter.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
|
||||
{
|
||||
if (e.Data is object)
|
||||
{
|
||||
lineQueue.Enqueue(e.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
lineQueue.Complete();
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
linter.Start();
|
||||
linter.BeginErrorReadLine();
|
||||
linter.StandardInput.AutoFlush = true;
|
||||
await linter.StandardInput.WriteAsync(content);
|
||||
linter.StandardInput.Close();
|
||||
}
|
||||
catch (Win32Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException(message: ex.Message, innerException: ex);
|
||||
}
|
||||
|
||||
return await ProcessLinterQueueAsync(lineQueue);
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<Diagnostic>> ProcessLinterQueueAsync(AsyncQueue<string> lineQueue)
|
||||
{
|
||||
Requires.NotNull(lineQueue, nameof(lineQueue));
|
||||
|
||||
List<Diagnostic> diagnostics = new List<Diagnostic>();
|
||||
|
||||
while (!(lineQueue.IsCompleted && lineQueue.IsEmpty))
|
||||
{
|
||||
string? line = null;
|
||||
try
|
||||
{
|
||||
line = await lineQueue.DequeueAsync();
|
||||
linter.Start();
|
||||
linter.BeginErrorReadLine();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
catch (Win32Exception ex)
|
||||
{
|
||||
break;
|
||||
throw new InvalidOperationException(message: ex.Message, innerException: ex);
|
||||
}
|
||||
|
||||
var diagnostic = line is object ? GetDiagnosticFromLinterOutput(line) : null;
|
||||
if (diagnostic is object)
|
||||
{
|
||||
diagnostics.Add(diagnostic);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something went wrong so break and return the current set.
|
||||
break;
|
||||
}
|
||||
var markdownDiagnostics = await ProcessLinterQueueAsync(lineQueue);
|
||||
return CreateDocumentDiagnosticsForClosedDocument(fileUri, markdownDiagnostics);
|
||||
}
|
||||
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
private static Diagnostic? GetDiagnosticFromLinterOutput(string outputLine)
|
||||
{
|
||||
Requires.NotNull(outputLine, nameof(outputLine));
|
||||
var match = linterOutputRegex.Match(outputLine);
|
||||
if (!match.Success)
|
||||
/// <summary>
|
||||
/// Runs markdown linter on a given text document and returns diagnostic entries.
|
||||
/// </summary>
|
||||
/// <param name="textDocument">Document to run markdown linter on.</param>
|
||||
/// <returns>an enumeration of <see cref="DocumentDiagnostic"/> entries for warnings in the markdown file.</returns>
|
||||
public static async Task<IEnumerable<DocumentDiagnostic>> RunLinterOnDocumentAsync(ITextDocumentSnapshot textDocument)
|
||||
{
|
||||
return null;
|
||||
using var linter = new Process();
|
||||
var lineQueue = new AsyncQueue<string>();
|
||||
|
||||
var content = textDocument.CopyToString();
|
||||
|
||||
linter.StartInfo = new ProcessStartInfo()
|
||||
{
|
||||
FileName = "cmd.exe",
|
||||
Arguments = $"/k \"{Environment.ExpandEnvironmentVariables("%APPDATA%\\npm\\markdownlint.cmd")}\" -s",
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardInput = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
|
||||
linter.EnableRaisingEvents = true;
|
||||
linter.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
|
||||
{
|
||||
if (e.Data is object)
|
||||
{
|
||||
lineQueue.Enqueue(e.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
lineQueue.Complete();
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
linter.Start();
|
||||
linter.BeginErrorReadLine();
|
||||
linter.StandardInput.AutoFlush = true;
|
||||
foreach (var line in textDocument.Lines)
|
||||
{
|
||||
await linter.StandardInput.WriteAsync(line.CopyToString());
|
||||
}
|
||||
|
||||
linter.StandardInput.Close();
|
||||
}
|
||||
catch (Win32Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException(message: ex.Message, innerException: ex);
|
||||
}
|
||||
|
||||
var markdownDiagnostics = await ProcessLinterQueueAsync(lineQueue);
|
||||
return CreateDocumentDiagnosticsForOpenDocument(textDocument, markdownDiagnostics);
|
||||
}
|
||||
|
||||
int line = int.Parse(match.Groups["Line"].Value, CultureInfo.InvariantCulture) - 1;
|
||||
int column = match.Groups.ContainsKey("Column") && !string.IsNullOrEmpty(match.Groups["Column"].Value) ? (int.Parse(match.Groups["Column"].Value, CultureInfo.InvariantCulture) - 1) : -1;
|
||||
/// <summary>
|
||||
/// Checks if the given path is a valid markdown file.
|
||||
/// </summary>
|
||||
/// <param name="localPath">Local file path to verify.</param>
|
||||
/// <returns>true if file is a markdown file, false otherwise.</returns>
|
||||
public static bool IsValidMarkdownFile(string localPath)
|
||||
{
|
||||
return localPath is object && Path.GetExtension(localPath).Equals(".md", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
string error = match.Groups["Error"].Value;
|
||||
private static IEnumerable<DocumentDiagnostic> CreateDocumentDiagnosticsForOpenDocument(ITextDocumentSnapshot document, IEnumerable<MarkdownDiagnosticInfo> diagnostics)
|
||||
{
|
||||
foreach (var diagnostic in diagnostics)
|
||||
{
|
||||
var startindex = document.Lines[diagnostic.Range.StartLine].Start.Offset + diagnostic.Range.StartColumn;
|
||||
var endIndex = document.Lines[diagnostic.Range.EndLine].Start.Offset + diagnostic.Range.EndColumn;
|
||||
|
||||
return new Diagnostic(
|
||||
message: match.Groups["Description"].Value,
|
||||
code: match.Groups["Error"].Value,
|
||||
DiagnosticSeverity.Warning,
|
||||
range: new RpcContracts.Utilities.Range(startLine: line, startColumn: column));
|
||||
yield return DocumentDiagnostic.CreateDocumentDiagnostic(
|
||||
new TextRange(document, startindex, endIndex),
|
||||
diagnostic.Message,
|
||||
diagnostic.ErrorCode,
|
||||
DiagnosticSeverity.Warning,
|
||||
providerName: "Markdown Linter");
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<DocumentDiagnostic> CreateDocumentDiagnosticsForClosedDocument(Uri fileUri, IEnumerable<MarkdownDiagnosticInfo> diagnostics)
|
||||
{
|
||||
foreach (var diagnostic in diagnostics)
|
||||
{
|
||||
yield return DocumentDiagnostic.CreateDocumentDiagnosticForClosedDocument(
|
||||
uri: fileUri,
|
||||
range: diagnostic.Range,
|
||||
diagnostic.Message,
|
||||
diagnostic.ErrorCode,
|
||||
DiagnosticSeverity.Warning,
|
||||
providerName: "Markdown Linter");
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<MarkdownDiagnosticInfo>> ProcessLinterQueueAsync(AsyncQueue<string> lineQueue)
|
||||
{
|
||||
Requires.NotNull(lineQueue, nameof(lineQueue));
|
||||
|
||||
List<MarkdownDiagnosticInfo> diagnostics = new List<MarkdownDiagnosticInfo>();
|
||||
|
||||
while (!(lineQueue.IsCompleted && lineQueue.IsEmpty))
|
||||
{
|
||||
string? line = null;
|
||||
try
|
||||
{
|
||||
line = await lineQueue.DequeueAsync();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var diagnostic = line is object ? GetDiagnosticFromLinterOutput(line) : null;
|
||||
if (diagnostic is object)
|
||||
{
|
||||
diagnostics.Add(diagnostic);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something went wrong so break and return the current set.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
private static MarkdownDiagnosticInfo? GetDiagnosticFromLinterOutput(string outputLine)
|
||||
{
|
||||
Requires.NotNull(outputLine, nameof(outputLine));
|
||||
var match = linterOutputRegex.Match(outputLine);
|
||||
if (!match.Success)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int line = int.Parse(match.Groups["Line"].Value, CultureInfo.InvariantCulture) - 1;
|
||||
int column = match.Groups.ContainsKey("Column") && !string.IsNullOrEmpty(match.Groups["Column"].Value) ? (int.Parse(match.Groups["Column"].Value, CultureInfo.InvariantCulture) - 1) : -1;
|
||||
|
||||
return new MarkdownDiagnosticInfo(
|
||||
range: new RpcContracts.Utilities.Range(startLine: line, startColumn: column),
|
||||
message: match.Groups["Description"].Value,
|
||||
errorCode: match.Groups["Error"].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.VisualStudio.Extensions.MarkdownLinter
|
||||
{
|
||||
using Microsoft.VisualStudio.Extensibility.Languages;
|
||||
|
||||
using Range = Microsoft.VisualStudio.RpcContracts.Utilities.Range;
|
||||
|
||||
/// <summary>
|
||||
/// Class that contains diagnostic information found by the Markdown linter.
|
||||
/// Holds information to be converted to a <see cref="DocumentDiagnostic"/>.
|
||||
/// </summary>
|
||||
public class MarkdownDiagnosticInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MarkdownDiagnosticInfo"/> class.
|
||||
/// </summary>
|
||||
/// <param name="range">Range where the diagnostic exists.</param>
|
||||
/// <param name="message">Message to be presented with the diagnostic.</param>
|
||||
/// <param name="errorCode">Unique error code of this type of diagnostic.</param>
|
||||
public MarkdownDiagnosticInfo(Range range, string message, string errorCode)
|
||||
{
|
||||
this.Range = range;
|
||||
this.Message = message;
|
||||
this.ErrorCode = errorCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the range of the diagnostic.
|
||||
/// </summary>
|
||||
public Range Range { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the error message of the diagnostic.
|
||||
/// </summary>
|
||||
public string Message { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the error code of the diagnostic.
|
||||
/// </summary>
|
||||
public string ErrorCode { get; }
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ internal class MarkdownDiagnosticsService : DisposableObject
|
|||
#pragma warning restore CA2213 // Disposable fields should be disposed
|
||||
|
||||
private OutputWindow? outputWindow;
|
||||
private DiagnosticsProvider? diagnosticsProvider;
|
||||
private DiagnosticsReporter? diagnosticsReporter;
|
||||
private Dictionary<Uri, CancellationTokenSource> documentCancellationTokens;
|
||||
private Task initializationTask;
|
||||
|
||||
|
@ -71,10 +71,10 @@ internal class MarkdownDiagnosticsService : DisposableObject
|
|||
|
||||
try
|
||||
{
|
||||
var diagnostics = await LinterUtilities.RunLinterOnFileAsync(documentUri.LocalPath);
|
||||
var diagnostics = await LinterUtilities.RunLinterOnFileAsync(documentUri);
|
||||
|
||||
await this.diagnosticsProvider!.ClearDiagnosticsAsync(documentUri, cancellationToken);
|
||||
await this.diagnosticsProvider!.AppendDiagnosticsAsync(documentUri, diagnostics, cancellationToken);
|
||||
await this.diagnosticsReporter!.ClearDiagnosticsAsync(documentUri, cancellationToken);
|
||||
await this.diagnosticsReporter!.ReportDiagnosticsAsync(diagnostics, cancellationToken);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
|
@ -88,12 +88,12 @@ internal class MarkdownDiagnosticsService : DisposableObject
|
|||
/// <summary>
|
||||
/// Processes the current version <see cref="ITextView"/> instance for markdown errors and reports to the error list.
|
||||
/// </summary>
|
||||
/// <param name="textView">Text View instance to read the contents from.</param>
|
||||
/// <param name="textViewSnapshot">Text View instance to read the contents from.</param>
|
||||
/// <param name="cancellationToken">Cancellation token to monitor.</param>
|
||||
/// <returns>Task indicating completion of reporting markdown errors to error list.</returns>
|
||||
public async Task ProcessTextViewAsync(ITextView textView, CancellationToken cancellationToken)
|
||||
public async Task ProcessTextViewAsync(ITextViewSnapshot textViewSnapshot, CancellationToken cancellationToken)
|
||||
{
|
||||
var document = await textView.GetTextDocumentAsync(cancellationToken);
|
||||
var document = await textViewSnapshot.GetTextDocumentAsync(cancellationToken);
|
||||
if (document is null)
|
||||
{
|
||||
return;
|
||||
|
@ -130,7 +130,7 @@ internal class MarkdownDiagnosticsService : DisposableObject
|
|||
}
|
||||
}
|
||||
|
||||
await this.diagnosticsProvider!.ClearDiagnosticsAsync(documentUri, cancellationToken);
|
||||
await this.diagnosticsReporter!.ClearDiagnosticsAsync(documentUri, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -141,11 +141,11 @@ internal class MarkdownDiagnosticsService : DisposableObject
|
|||
if (isDisposing)
|
||||
{
|
||||
this.outputWindow?.Dispose();
|
||||
this.diagnosticsProvider?.Dispose();
|
||||
this.diagnosticsReporter?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessDocumentAsync(ITextDocument document, CancellationToken cancellationToken)
|
||||
private async Task ProcessDocumentAsync(ITextDocumentSnapshot documentSnapshot, CancellationToken cancellationToken)
|
||||
{
|
||||
// Wait for 1 second to see if any other changes are being sent.
|
||||
await Task.Delay(1000, cancellationToken);
|
||||
|
@ -155,15 +155,12 @@ internal class MarkdownDiagnosticsService : DisposableObject
|
|||
return;
|
||||
}
|
||||
|
||||
// For simplicity in the sample, we are using GetText here but in very large files this will cause performance issues.
|
||||
// Instead consider using ITextDocument.CopyTo or ITextDocument.GetLine methods.
|
||||
var content = document.GetText();
|
||||
try
|
||||
{
|
||||
var diagnostics = await LinterUtilities.RunLinterOnTextAsync(content);
|
||||
var diagnostics = await LinterUtilities.RunLinterOnDocumentAsync(documentSnapshot);
|
||||
|
||||
await this.diagnosticsProvider!.ClearDiagnosticsAsync(document, cancellationToken);
|
||||
await this.diagnosticsProvider!.AppendDiagnosticsAsync(document, diagnostics, cancellationToken);
|
||||
await this.diagnosticsReporter!.ClearDiagnosticsAsync(documentSnapshot, cancellationToken);
|
||||
await this.diagnosticsReporter!.ReportDiagnosticsAsync(diagnostics, cancellationToken);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
|
@ -179,7 +176,7 @@ internal class MarkdownDiagnosticsService : DisposableObject
|
|||
this.outputWindow = await this.extensibility.Views().Output.GetChannelAsync(nameof(MarkdownLinterExtension) + Guid.NewGuid(), nameof(Strings.MarkdownLinterWindowName), default);
|
||||
Assumes.NotNull(this.outputWindow);
|
||||
|
||||
this.diagnosticsProvider = this.extensibility.Languages().GetDiagnosticsProvider(nameof(MarkdownLinterExtension));
|
||||
Assumes.NotNull(this.diagnosticsProvider);
|
||||
this.diagnosticsReporter = this.extensibility.Languages().GetDiagnosticsReporter(nameof(MarkdownLinterExtension));
|
||||
Assumes.NotNull(this.diagnosticsReporter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.1043-preview-2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.1043-preview-2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -14,7 +14,7 @@ using Microsoft.VisualStudio.Extensibility.Editor.UI;
|
|||
/// </summary>
|
||||
[ExtensionPart(typeof(ITextViewLifetimeListener))]
|
||||
[ExtensionPart(typeof(ITextViewChangedListener))]
|
||||
[AppliesTo(ContentType = "markdown")]
|
||||
[AppliesTo(DocumentType = "markdown")]
|
||||
internal class TextViewEventListener : ExtensionPart, ITextViewLifetimeListener, ITextViewChangedListener
|
||||
{
|
||||
private readonly MarkdownDiagnosticsService diagnosticsProvider;
|
||||
|
@ -38,9 +38,9 @@ internal class TextViewEventListener : ExtensionPart, ITextViewLifetimeListener,
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task TextViewClosedAsync(ITextView textView, CancellationToken cancellationToken)
|
||||
public async Task TextViewClosedAsync(ITextViewSnapshot textViewSnapshot, CancellationToken cancellationToken)
|
||||
{
|
||||
var document = await textView.GetTextDocumentAsync(cancellationToken);
|
||||
var document = await textViewSnapshot.GetTextDocumentAsync(cancellationToken);
|
||||
if (document is null)
|
||||
{
|
||||
return;
|
||||
|
@ -50,8 +50,8 @@ internal class TextViewEventListener : ExtensionPart, ITextViewLifetimeListener,
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task TextViewCreatedAsync(ITextView textView, CancellationToken cancellationToken)
|
||||
public Task TextViewCreatedAsync(ITextViewSnapshot textViewSnapshot, CancellationToken cancellationToken)
|
||||
{
|
||||
return this.diagnosticsProvider.ProcessTextViewAsync(textView, cancellationToken);
|
||||
return this.diagnosticsProvider.ProcessTextViewAsync(textViewSnapshot, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.1043-preview-2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.1043-preview-2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.1043-preview-2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.1043-preview-2" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.1043-preview-2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.1043-preview-2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
<LangVersion>10</LangVersion>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<NoWarn>$(NoWarn);CS1591;IDE0008;CA1812</NoWarn>
|
||||
<NoWarn>$(NoWarn);CS1591;IDE0008;CA1812;CA1303</NoWarn>
|
||||
|
||||
<!-- The VisualStudio.Extensibility preview packages are available from the azure-public/vside/vssdk feed -->
|
||||
<RestoreAdditionalProjectSources>https://pkgs.dev.azure.com/azure-public/vside/_packaging/vssdk/nuget/v3/index.json;$(RestoreAdditionalProjectSources)</RestoreAdditionalProjectSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.19-preview-1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Sdk" Version="17.4.1043-preview-2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Extensibility.Build" Version="17.4.1043-preview-2" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
Загрузка…
Ссылка в новой задаче