Skip to content

Commit

Permalink
Merge pull request #59872 from dotnet/merges/main-to-release/dev17.3
Browse files Browse the repository at this point in the history
Merge main to release/dev17.3
  • Loading branch information
dotnet-bot authored Mar 2, 2022
2 parents f00b4c5 + f8a7ec2 commit bd36982
Show file tree
Hide file tree
Showing 25 changed files with 418 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
2. Each IDE diagnostic ID has a dedicated documentation page. For example:
1. Diagnostic with code style option: <https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0011>
2. Diagnostic without code style option: <https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0004>
3. Multiple diagnostic IDs sharing the same option(s): <https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0003-ide0009>
3. Multiple diagnostic IDs sharing the same option(s): <https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0003-ide0009>. In this case, a [redirection](https://github.com/dotnet/docs/blob/7ae7272d643aa1c6db96cad8d09d4c2332855960/.openpublishing.redirection.fundamentals.json#L11-L14) for all diagnostic IDs must be added.

3. We have tabular indices for IDE diagnostic IDs and code style options for easier reference and navigation:
1. Primary index (rule ID + code style options): <https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/>
Expand All @@ -20,14 +20,14 @@

Roslyn IDE team (@dotnet/roslyn-ide) is responsible for ensuring that the documentation for IDE analyzers is up-to-date. Whenever we add a new IDE analyzer, add new code style option(s) OR update semantics of existing IDE analyzers the following needs to be done:

1. **Action required in [dotnet\docs](https://github.com/dotnet/docs) repo**:
1. **Action required in [dotnet/docs](https://github.com/dotnet/docs) repo**:
1. If you _creating a Roslyn PR for an IDE analyzer_:
1. Please follow the steps at [Contribute docs for 'IDExxxx' rules](https://docs.microsoft.com/contribute/dotnet/dotnet-contribute-code-analysis#contribute-docs-for-idexxxx-rules) to add documentation for IDE analyzers to [dotnet\docs](https://github.com/dotnet/docs) repo.
1. Please follow the steps at [Contribute docs for 'IDExxxx' rules](https://docs.microsoft.com/contribute/dotnet/dotnet-contribute-code-analysis#contribute-docs-for-idexxxx-rules) to add documentation for IDE analyzers to [dotnet/docs](https://github.com/dotnet/docs) repo.
2. Ideally, the documentation PR should be created in parallel to the Roslyn PR or immediately following the approval/merge of Roslyn PR.
2. If you are _reviewing a Roslyn PR for an IDE analyzer_:
1. Please ensure that the analyzer author is made aware of the above doc contribution requirements, especially if it is a community PR.
2. If the documentation PR in is not being created in parallel to the Roslyn PR, please ensure that a [new doc issue](https://github.com/dotnet/docs/issues) is filed in `dotnet/docs` repo to track this work.

2. **No action required in Roslyn repo**: Help links have been hooked up to IDE code style analyzers in Roslyn repo in the base analyzer types, so every new IDE analyzer diagnostic ID will automatically have `https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ideXXXX` as its help link. There is no action required on the Roslyn PR to ensure this linking.

If you feel any of the existing IDE rule docs have insufficient or incorrect information, please submit a PR to [dotnet\docs](https://github.com/dotnet/docs) repo to update the documentation.
If you feel any of the existing IDE rule docs have insufficient or incorrect information, please submit a PR to [dotnet/docs](https://github.com/dotnet/docs) repo to update the documentation.
13 changes: 13 additions & 0 deletions eng/config/PublishData.json
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,19 @@
"insertionCreateDraftPR": true,
"insertionTitlePrefix": "[d17.2p3]"
},
"release/dev17.3": {
"nugetKind": [
"Shipping",
"NonShipping"
],
"version": "4.3.*",
"packageFeeds": "default",
"channels": [],
"vsBranch": "main",
"vsMajorVersion": 17,
"insertionCreateDraftPR": true,
"insertionTitlePrefix": "[d17.3p1]"
},
"features/NullableReferenceTypes": {
"nugetKind": "PerBuildPreRelease",
"version": "2.6.*",
Expand Down
4 changes: 2 additions & 2 deletions eng/pipelines/test-integration-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ steps:
condition: not(succeeded())

- task: PublishBuildArtifacts@1
displayName: Publish Screenshots
displayName: Publish Screenshots and Test Attachments
inputs:
PathtoPublish: '$(Build.SourcesDirectory)\artifacts\bin\Microsoft.VisualStudio.LanguageServices.IntegrationTests\${{ parameters.configuration }}\net472\xUnitResults'
PathtoPublish: '$(Build.SourcesDirectory)\artifacts\bin\Microsoft.VisualStudio.LanguageServices.IntegrationTests\${{ parameters.configuration }}\net472\TestResults'
ArtifactName: '$(System.JobAttempt)-Screenshots ${{ parameters.configuration }} OOP64_${{ parameters.oop64bit }} OOPCoreClr_${{ parameters.oopCoreClr }} LspEditor_${{ parameters.lspEditor }} $(Build.BuildNumber)'
publishLocation: Container
continueOnError: true
Expand Down
4 changes: 1 addition & 3 deletions src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<Compile Include="$(MSBuildThisFileDirectory)SimplifyInterpolation\CSharpSimplifyInterpolationCodeFixProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SimplifyLinqExpression\CSharpSimplifyLinqExpressionCodeFixProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SimplifyPropertyPattern\CSharpSimplifyPropertyPatternCodeFixProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TransposeRecordKeyword\CSharpTransposeRecordKeywordCodeFixProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UseCollectionInitializer\CSharpUseCollectionInitializerCodeFixProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UseCompoundAssignment\CSharpUseCompoundAssignmentCodeFixProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UseCompoundAssignment\CSharpUseCompoundCoalesceAssignmentCodeFixProvider.cs" />
Expand Down Expand Up @@ -79,7 +80,4 @@
<ItemGroup Condition="'$(DefaultLanguageSourceExtension)' != '' AND '$(BuildingInsideVisualStudio)' != 'true'">
<ExpectedCompile Include="$(MSBuildThisFileDirectory)**\*$(DefaultLanguageSourceExtension)" />
</ItemGroup>
<ItemGroup>
<Folder Include="$(MSBuildThisFileDirectory)ConvertNamespace\" />
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions src/Analyzers/CSharp/CodeFixes/CSharpCodeFixesResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,7 @@
<data name="Place_colon_on_following_line" xml:space="preserve">
<value>Place colon on following line</value>
</data>
<data name="Fix_record_declaration" xml:space="preserve">
<value>Fix_record_declaration</value>
</data>
</root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Immutable;
using System.Composition;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Shared.Extensions;

namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.TransposeRecordKeyword
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.TransposeRecordKeyword), Shared]
internal class CSharpTransposeRecordKeywordCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
private const string CS9012 = nameof(CS9012); // Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'?

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public CSharpTransposeRecordKeywordCodeFixProvider()
{
}

public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(CS9012);

internal override CodeFixCategory CodeFixCategory
=> CodeFixCategory.Compile;

private static bool TryGetRecordDeclaration(
Diagnostic diagnostic, CancellationToken cancellationToken, [NotNullWhen(true)] out RecordDeclarationSyntax? recordDeclaration)
{
recordDeclaration = diagnostic.Location.FindNode(cancellationToken) as RecordDeclarationSyntax;
return recordDeclaration != null;
}

private static bool TryGetTokens(
RecordDeclarationSyntax recordDeclaration,
out SyntaxToken classOrStructKeyword,
out SyntaxToken recordKeyword)
{
recordKeyword = recordDeclaration.Keyword;
if (!recordKeyword.IsMissing)
{
var leadingTrivia = recordKeyword.LeadingTrivia;
var skippedTriviaIndex = leadingTrivia.IndexOf(SyntaxKind.SkippedTokensTrivia);
if (skippedTriviaIndex >= 0)
{
var skippedTrivia = leadingTrivia[skippedTriviaIndex];
var structure = (SkippedTokensTriviaSyntax)skippedTrivia.GetStructure()!;
var tokens = structure.Tokens;
if (tokens.Count == 1)
{
classOrStructKeyword = tokens.Single();
if (classOrStructKeyword.Kind() is SyntaxKind.ClassKeyword or SyntaxKind.StructKeyword)
{
// Because the class/struct keyword is skipped trivia on the record keyword, it will
// not have trivia of it's own. So we need to move the other trivia appropriate trivia
// on the record keyword to it.
var remainingLeadingTrivia = SyntaxFactory.TriviaList(leadingTrivia.Skip(skippedTriviaIndex + 1));
var trailingTriviaTakeUntil = remainingLeadingTrivia.IndexOf(SyntaxKind.EndOfLineTrivia) is >= 0 and var eolIndex
? eolIndex + 1
: remainingLeadingTrivia.Count;

classOrStructKeyword = classOrStructKeyword
.WithLeadingTrivia(SyntaxFactory.TriviaList(remainingLeadingTrivia.Skip(trailingTriviaTakeUntil)))
.WithTrailingTrivia(recordKeyword.TrailingTrivia);
recordKeyword = recordKeyword
.WithLeadingTrivia(leadingTrivia.Take(skippedTriviaIndex))
.WithTrailingTrivia(SyntaxFactory.TriviaList(remainingLeadingTrivia.Take(trailingTriviaTakeUntil)));

return true;
}
}
}
}

classOrStructKeyword = default;
return false;
}

public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var cancellationToken = context.CancellationToken;

var diagnostic = context.Diagnostics.First();
if (TryGetRecordDeclaration(diagnostic, cancellationToken, out var recordDeclaration) &&
TryGetTokens(recordDeclaration, out _, out _))
{
context.RegisterCodeFix(
new MyCodeAction(c => this.FixAsync(document, diagnostic, c)),
diagnostic);
}

return Task.CompletedTask;
}

protected override Task FixAllAsync(
Document document, ImmutableArray<Diagnostic> diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
foreach (var diagnostic in diagnostics)
{
if (TryGetRecordDeclaration(diagnostic, cancellationToken, out var recordDeclaration))
{
editor.ReplaceNode(
recordDeclaration,
(current, _) =>
{
var currentRecordDeclaration = (RecordDeclarationSyntax)current;
if (!TryGetTokens(currentRecordDeclaration, out var classOrStructKeyword, out var recordKeyword))
return currentRecordDeclaration;
return currentRecordDeclaration
.WithClassOrStructKeyword(classOrStructKeyword)
.WithKeyword(recordKeyword);
});
}
}

return Task.CompletedTask;
}

private class MyCodeAction : CustomCodeActions.DocumentChangeAction
{
public MyCodeAction(
Func<CancellationToken, Task<Document>> createChangedDocument)
: base(CSharpCodeFixesResources.Fix_record_declaration, createChangedDocument, nameof(CSharpTransposeRecordKeywordCodeFixProvider))
{
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit bd36982

Please sign in to comment.