Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analyzer/fix that checks NoWarn appends #161

Merged
merged 4 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions MonoDevelop.MSBuild.Editor/Analysis/MSBuildCodeFixService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

using MonoDevelop.MSBuild.Analysis;
using MonoDevelop.MSBuild.Editor.Completion;
using MonoDevelop.MSBuild.Language;

namespace MonoDevelop.MSBuild.Editor.Analysis
{
Expand Down Expand Up @@ -121,11 +122,11 @@ void ReportFix (MSBuildCodeAction a, ImmutableArray<MSBuildDiagnostic> diags) {
/// there is a better concept of a durable context/scope to which information can be bound.
/// </remarks>
public async Task<List<MSBuildCodeFix>> GetFixes (
ITextBuffer buffer, MSBuildParseResult result, SnapshotSpan range,
ITextBuffer buffer, MSBuildRootDocument parsedDocument, IList<MSBuildDiagnostic> diagnostics, SnapshotSpan range,
MSBuildDiagnosticSeverity requestedSeverities, CancellationToken cancellationToken)
{
var filteredDiags = ImmutableArray.CreateRange (
result.Diagnostics.Where (d => range.IntersectsWith (new SnapshotSpan (range.Snapshot, d.Span.Start, d.Span.Length))));
diagnostics.Where (d => range.IntersectsWith (new SnapshotSpan (range.Snapshot, d.Span.Start, d.Span.Length))));

var fixes = new List<MSBuildCodeFix> ();
void ReportFix (MSBuildCodeAction a, ImmutableArray<MSBuildDiagnostic> d)
Expand All @@ -147,8 +148,8 @@ void ReportFix (MSBuildCodeAction a, ImmutableArray<MSBuildDiagnostic> d)
if (diagnosticIdToFixProviderMap.TryGetValue (diagnostic.Descriptor.Id, out var fixProvider)) {
var ctx = new MSBuildFixContext (
buffer,
result.MSBuildDocument,
result.MSBuildDocument.XDocument,
parsedDocument,
parsedDocument.XDocument,
new Xml.Dom.TextSpan (range.Start, range.Length),
ImmutableArray.Create (diagnostic),
ReportFix, cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ async Task<List<MSBuildCodeFix>> GetSuggestedActionsAsync (ISuggestedActionCateg

var severities = CategoriesToSeverity (requestedActionCategories);
if (severities != 0) {
actions = await provider.CodeFixService.GetFixes (textBuffer, result, range, severities, cancellationToken);
actions = await provider.CodeFixService.GetFixes (textBuffer, result.MSBuildDocument, result.Diagnostics, range, severities, cancellationToken);
for (int i = 0; i < actions.Count; i++) {
if (!requestedActionCategories.Contains (actions[i].Category)) {
actions.RemoveAt (i);
Expand Down
43 changes: 43 additions & 0 deletions MonoDevelop.MSBuild.Editor/CodeFixes/AppendNoWarnFixProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.Threading.Tasks;

using MonoDevelop.MSBuild.Analyzers;
using MonoDevelop.MSBuild.Editor.Analysis;
using MonoDevelop.Xml.Dom;

namespace MonoDevelop.MSBuild.Editor.CodeFixes
{
[Export (typeof (MSBuildFixProvider))]
class AppendNoWarnFixProvider : MSBuildFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create (
AppendNoWarnAnalyzer.DiagnosticId
);

public override Task RegisterCodeFixesAsync (MSBuildFixContext context)
{
foreach (var diag in context.Diagnostics) {
if (context.XDocument.FindAtOffset (diag.Span.Start) is XElement prop && prop.InnerSpan is TextSpan valueSpan) {
context.RegisterCodeFix (new PrependListValueAction (valueSpan, "$(NoWarn)"), diag);
}
}
return Task.CompletedTask;
}

class PrependListValueAction (TextSpan valueSpan, string valueToPrepend) : SimpleMSBuildCodeAction
{
public override string Title => $"Prepend '{valueToPrepend}' to list";

protected override MSBuildCodeActionOperation CreateOperation ()
{
var op = new EditTextActionOperation ();
op.Insert (valueSpan.Start, valueToPrepend + ";");
return op;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#nullable enable

using System.Threading.Tasks;

using MonoDevelop.MSBuild.Analyzers;
using MonoDevelop.MSBuild.Editor.CodeFixes;

using NUnit.Framework;
using NUnit.Framework.Internal;

namespace MonoDevelop.MSBuild.Tests.Editor.CodeFixes;

[TestFixture]
class AppendNoWarnCodeFixTests : MSBuildEditorTest
{
[Test]
public Task TestFixAppendNoWarn ()
{
return this.TestCodeFix<AppendNoWarnAnalyzer, AppendNoWarnFixProvider> (
@"<Project>
<PropertyGroup>
<NoW|arn>CS1234;CS456</NoWarn>
</PropertyGroup>
</Project>
",
"Prepend '$(NoWarn)' to list",
1,
@"<Project>
<PropertyGroup>
<NoWarn>$(NoWarn);CS1234;CS456</NoWarn>
</PropertyGroup>
</Project>
");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#nullable enable

using System.Threading.Tasks;

using MonoDevelop.MSBuild.Analyzers;
using MonoDevelop.MSBuild.Editor.CodeFixes;

using NUnit.Framework;
using NUnit.Framework.Internal;

namespace MonoDevelop.MSBuild.Tests.Editor.CodeFixes;

[TestFixture]
class FixMultitargetingPluralizationCodeFixTests : MSBuildEditorTest
{
[Test]
public Task DepluralizeTargetFrameworks ()
{
return this.TestCodeFix<TargetFrameworksOrTargetFrameworkAnalyzer, FixMultitargetingPluralizationFixProvider> (
@"<Project>
<PropertyGroup>
<TargetFra|meworks>net8.0</TargetFrameworks>
</PropertyGroup>
</Project>
",
"Change 'TargetFrameworks' to 'TargetFramework'",
1,
@"<Project>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>
");
}

[Test]
public Task PluralizeTargetFramework ()
{
return this.TestCodeFix<TargetFrameworksOrTargetFrameworkAnalyzer, FixMultitargetingPluralizationFixProvider> (
@"<Project>
<PropertyGroup>
<Tar|getFramework>net48;net8.0</TargetFramework>
</PropertyGroup>
</Project>
",
"Change 'TargetFramework' to 'TargetFrameworks'",
1,
@"<Project>
<PropertyGroup>
<TargetFrameworks>net48;net8.0</TargetFrameworks>
</PropertyGroup>
</Project>
");
}

[Test]
public Task DepluralizeRuntimeIdentifiers ()
{
return this.TestCodeFix<RuntimeIdentifierOrRuntimeIdentifiersAnalyzer, FixMultitargetingPluralizationFixProvider> (
@"<Project>
<PropertyGroup>
<Runtim|eIdentifiers>windows-x64</RuntimeIdentifiers>
</PropertyGroup>
</Project>
",
"Change 'RuntimeIdentifiers' to 'RuntimeIdentifier'",
1,
@"<Project>
<PropertyGroup>
<RuntimeIdentifier>windows-x64</RuntimeIdentifier>
</PropertyGroup>
</Project>
");
}
[Test]
public Task PluralizeRuntimeIdentifier ()
{
return this.TestCodeFix<RuntimeIdentifierOrRuntimeIdentifiersAnalyzer, FixMultitargetingPluralizationFixProvider> (
@"<Project>
<PropertyGroup>
<Runt|imeIdentifier>windows-x64;linux-x64</RuntimeIdentifier>
</PropertyGroup>
</Project>
",
"Change 'RuntimeIdentifier' to 'RuntimeIdentifiers'",
1,
@"<Project>
<PropertyGroup>
<RuntimeIdentifiers>windows-x64;linux-x64</RuntimeIdentifiers>
</PropertyGroup>
</Project>
");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

using MonoDevelop.MSBuild.Editor.Roslyn;
using MonoDevelop.MSBuild.Language;
using MonoDevelop.MSBuild.Tests.Editor.Mocks;
using MonoDevelop.Xml.Tests;
using MonoDevelop.Xml.Parser;

Expand All @@ -17,7 +16,7 @@
namespace MonoDevelop.MSBuild.Tests
{
[TestFixture]
public class MSBuildFindReferencesTests
class MSBuildFindReferencesTests : MSBuildDocumentTest
{
List<(int Offset, int Length, ReferenceUsage Usage)> FindReferences (string docString, MSBuildReferenceKind kind, object reference, [CallerMemberName] string testMethodName = null)
{
Expand All @@ -27,7 +26,7 @@ public class MSBuildFindReferencesTests
var (xdoc, _) = xmlParser.Parse (new StringReader (docString));

var logger = TestLoggerFactory.CreateLogger (testMethodName);
var doc = MSBuildTestHelpers.CreateEmptyDocument ();
var doc = CreateEmptyDocument ();
var parseContext = new MSBuildParserContext (
new NullMSBuildEnvironment (), null, null, null, "test.csproj", new PropertyValueCollector (false), null, logger, null, default);
doc.Build (xdoc, parseContext);
Expand Down
6 changes: 2 additions & 4 deletions MonoDevelop.MSBuild.Tests.Editor/MSBuildResolverTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,19 @@
using MonoDevelop.MSBuild.Language;
using MonoDevelop.MSBuild.Language.Syntax;
using MonoDevelop.MSBuild.Language.Typesystem;

using MonoDevelop.Xml.Tests;

using NUnit.Framework;

namespace MonoDevelop.MSBuild.Tests
{
[TestFixture]
public class MSBuildResolverTests
class MSBuildResolverTests : MSBuildDocumentTest
{
List<(int offset, MSBuildResolveResult result)> Resolve (string doc, ILogger logger)
{
var functionTypeProvider = new RoslynFunctionTypeProvider (null, logger);
return MSBuildTestHelpers
.SelectAtMarkers (doc, (state) => MSBuildResolver.Resolve (state.parser.Clone (), state.textSource, state.doc, functionTypeProvider, logger))
return SelectAtMarkers (doc, (state) => MSBuildResolver.Resolve (state.parser.Clone (), state.textSource, state.doc, functionTypeProvider, logger))
.ToList ();
}

Expand Down
1 change: 1 addition & 0 deletions MonoDevelop.MSBuild.Tests.Editor/MSBuildTestEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading.Tasks;

using MonoDevelop.MSBuild.Editor.Completion;
using MonoDevelop.MSBuild.Tests.Helpers;
using MonoDevelop.Xml.Editor.Tests;

namespace MonoDevelop.MSBuild.Tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

using Microsoft.VisualStudio.Text.Editor;

using MonoDevelop.MSBuild.Editor.Refactorings.ExtractExpression;
using MonoDevelop.MSBuild.Language.Expressions;
using MonoDevelop.MSBuild.Language.Syntax;
using MonoDevelop.MSBuild.Util;
using MonoDevelop.Xml.Dom;
using MonoDevelop.Xml.Editor.Tests.Extensions;
using MonoDevelop.Xml.Parser;
using MonoDevelop.Xml.Tests.Parser;

Expand Down Expand Up @@ -87,36 +83,8 @@ public Task ExtractFromTaskToExistingGroupInProject () => TestExtractExpression

async Task TestExtractExpression (string textWithMarkers, int expectedFixCount, string invokeFixWithTitle, string expectedTextAfterInvoke, string typeText, string expectedTextAfterTyping)
{
var ctx = await this.GetRefactorings<ExtractExpressionRefactoringProvider> (textWithMarkers);

Assert.That (ctx.CodeFixes, Has.Count.EqualTo (expectedFixCount));
Assert.That (ctx.CodeFixes.Select (c => c.Action.Title), Has.One.EqualTo (invokeFixWithTitle));

var fix = ctx.CodeFixes.Single (c => c.Action.Title == invokeFixWithTitle);

var operations = await fix.Action.ComputeOperationsAsync (CancellationToken.None);

var options = ctx.TextView.Options;
options.SetOptionValue (DefaultOptions.ConvertTabsToSpacesOptionId, true);
options.SetOptionValue (DefaultOptions.IndentSizeOptionId, 2);
options.SetOptionValue (DefaultOptions.TabSizeOptionId, 2);

foreach (var op in operations) {
op.Apply (options, ctx.TextBuffer, CancellationToken.None, ctx.TextView);
}

Assert.That (
ctx.TextBuffer.CurrentSnapshot.GetText (),
Is.EqualTo (expectedTextAfterInvoke));

// type a new name for the extracted property
await Catalog.JoinableTaskContext.Factory.SwitchToMainThreadAsync (default);
var commandService = Catalog.CommandServiceFactory.GetService (ctx.TextView);
commandService.Type (typeText);

Assert.That (
ctx.TextBuffer.CurrentSnapshot.GetText (),
Is.EqualTo (expectedTextAfterTyping));
var context = await this.GetRefactorings<ExtractExpressionRefactoringProvider> (textWithMarkers);
await this.TestCodeFixContext (context, invokeFixWithTitle, expectedFixCount, expectedTextAfterInvoke, typeText, expectedTextAfterTyping);
}

[Test]
Expand Down Expand Up @@ -174,7 +142,7 @@ public void ExtractionPointsFromTarget ()
("Target", true), ("Project", true));
}

void CheckExtractionPoints (string textWithMarkers, MSBuildSyntaxKind originKind, params (string scopeName, bool createGroup)[] expectedSpanProps)
static void CheckExtractionPoints (string textWithMarkers, MSBuildSyntaxKind originKind, params (string scopeName, bool createGroup)[] expectedSpanProps)
{
var doc = TextWithMarkers.Parse (textWithMarkers, '^', '$');

Expand Down

This file was deleted.

Loading
Loading