diff --git a/.vscode/settings.json b/.vscode/settings.json
index 85140b2d44e86..399accea7023f 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,6 @@
{
"files.associations": {
"**/eng/pipelines/*.yml": "azure-pipelines"
- }
+ },
+ "omnisharp.defaultLaunchSolution": "Compilers.sln",
}
\ No newline at end of file
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 85896ac039e85..61ea8dfc0871d 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -13,18 +13,18 @@
-
+
https://github.com/dotnet/arcade
- 943d03f62955c771825dfa1f1bdeb8f853a2d7dd
+ 4abaab2bf44d06638abeb23fc96c4f6eef58a2f0
https://github.com/dotnet/roslyn
818313426323d979747781a17c78860c833776da
-
+
https://github.com/dotnet/arcade
- 943d03f62955c771825dfa1f1bdeb8f853a2d7dd
+ 4abaab2bf44d06638abeb23fc96c4f6eef58a2f0
diff --git a/eng/common/dotnet-install.sh b/eng/common/dotnet-install.sh
index fdfeea66e7d43..5c94e98632a0a 100755
--- a/eng/common/dotnet-install.sh
+++ b/eng/common/dotnet-install.sh
@@ -55,6 +55,9 @@ case $cpuname in
aarch64)
buildarch=arm64
;;
+ loongarch64)
+ buildarch=loongarch64
+ ;;
amd64|x86_64)
buildarch=x64
;;
diff --git a/eng/common/native/CommonLibrary.psm1 b/eng/common/native/CommonLibrary.psm1
index adf707c8fe700..ca38268c44d83 100644
--- a/eng/common/native/CommonLibrary.psm1
+++ b/eng/common/native/CommonLibrary.psm1
@@ -276,7 +276,8 @@ function Get-MachineArchitecture {
}
if (($ProcessorArchitecture -Eq "AMD64") -Or
($ProcessorArchitecture -Eq "IA64") -Or
- ($ProcessorArchitecture -Eq "ARM64")) {
+ ($ProcessorArchitecture -Eq "ARM64") -Or
+ ($ProcessorArchitecture -Eq "LOONGARCH64")) {
return "x64"
}
return "x86"
diff --git a/global.json b/global.json
index fd86f0793bb3e..59c01b0b4680d 100644
--- a/global.json
+++ b/global.json
@@ -12,7 +12,7 @@
"xcopy-msbuild": "16.10.0-preview2"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21615.1",
- "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.21615.1"
+ "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21623.1",
+ "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.21623.1"
}
}
diff --git a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems
index bfdd9f0689a23..c58db92c96184 100644
--- a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems
+++ b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems
@@ -16,8 +16,6 @@
-
-
@@ -78,4 +76,7 @@
+
+
+
\ No newline at end of file
diff --git a/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceTransform.cs b/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceTransform.cs
deleted file mode 100644
index 3050716634ac4..0000000000000
--- a/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceTransform.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-// 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.Collections;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.CodeStyle;
-using Microsoft.CodeAnalysis.CSharp.CodeStyle;
-using Microsoft.CodeAnalysis.CSharp.Extensions;
-using Microsoft.CodeAnalysis.CSharp.Formatting;
-using Microsoft.CodeAnalysis.CSharp.Syntax;
-using Microsoft.CodeAnalysis.Formatting;
-using Microsoft.CodeAnalysis.Options;
-using Microsoft.CodeAnalysis.Shared.Extensions;
-using Roslyn.Utilities;
-
-#if CODE_STYLE
-using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions;
-#endif
-
-namespace Microsoft.CodeAnalysis.CSharp.ConvertNamespace
-{
- internal static class ConvertNamespaceTransform
- {
- public static async Task ConvertAsync(
- Document document, BaseNamespaceDeclarationSyntax baseNamespace, CancellationToken cancellationToken)
- {
- var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
- return document.WithSyntaxRoot(root.ReplaceNode(baseNamespace, Convert(baseNamespace)));
- }
-
- public static BaseNamespaceDeclarationSyntax Convert(BaseNamespaceDeclarationSyntax baseNamespace)
- {
- return baseNamespace switch
- {
- FileScopedNamespaceDeclarationSyntax fileScopedNamespace => ConvertFileScopedNamespace(fileScopedNamespace),
- NamespaceDeclarationSyntax namespaceDeclaration => ConvertNamespaceDeclaration(namespaceDeclaration),
- _ => throw ExceptionUtilities.UnexpectedValue(baseNamespace.Kind()),
- };
- }
-
- private static bool HasLeadingBlankLine(
- SyntaxToken token, out SyntaxToken withoutBlankLine)
- {
- var leadingTrivia = token.LeadingTrivia;
-
- if (leadingTrivia.Count >= 1 && leadingTrivia[0].Kind() == SyntaxKind.EndOfLineTrivia)
- {
- withoutBlankLine = token.WithLeadingTrivia(leadingTrivia.RemoveAt(0));
- return true;
- }
-
- if (leadingTrivia.Count >= 2 && leadingTrivia[0].IsKind(SyntaxKind.WhitespaceTrivia) && leadingTrivia[1].IsKind(SyntaxKind.EndOfLineTrivia))
- {
- withoutBlankLine = token.WithLeadingTrivia(leadingTrivia.Skip(2));
- return true;
- }
-
- withoutBlankLine = default;
- return false;
- }
-
- private static FileScopedNamespaceDeclarationSyntax ConvertNamespaceDeclaration(NamespaceDeclarationSyntax namespaceDeclaration)
- {
- // We move leading and trailing trivia on the open brace to just be trailing trivia on the semicolon, so we preserve
- // comments etc. logically at the top of the file.
- var semiColon = SyntaxFactory.Token(SyntaxKind.SemicolonToken);
-
- if (namespaceDeclaration.Name.GetTrailingTrivia().Any(t => t.IsSingleOrMultiLineComment()))
- {
- semiColon = semiColon.WithTrailingTrivia(namespaceDeclaration.Name.GetTrailingTrivia())
- .WithAppendedTrailingTrivia(namespaceDeclaration.OpenBraceToken.LeadingTrivia);
- }
- else
- {
- semiColon = semiColon.WithTrailingTrivia(namespaceDeclaration.OpenBraceToken.LeadingTrivia);
- }
-
- semiColon = semiColon.WithAppendedTrailingTrivia(namespaceDeclaration.OpenBraceToken.TrailingTrivia);
-
- var fileScopedNamespace = SyntaxFactory.FileScopedNamespaceDeclaration(
- namespaceDeclaration.AttributeLists,
- namespaceDeclaration.Modifiers,
- namespaceDeclaration.NamespaceKeyword,
- namespaceDeclaration.Name.WithoutTrailingTrivia(),
- semiColon,
- namespaceDeclaration.Externs,
- namespaceDeclaration.Usings,
- namespaceDeclaration.Members).WithAdditionalAnnotations(Formatter.Annotation);
-
- // Ensure there's a blank line between the namespace line and the first body member.
- var firstBodyToken = fileScopedNamespace.SemicolonToken.GetNextToken();
- if (firstBodyToken.Kind() != SyntaxKind.EndOfFileToken &&
- !HasLeadingBlankLine(firstBodyToken, out _))
- {
- fileScopedNamespace = fileScopedNamespace.ReplaceToken(
- firstBodyToken,
- firstBodyToken.WithPrependedLeadingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed));
- }
-
- // Copy leading trivia from the close brace to the end of the file scoped namespace (which means after all of the members)
- if (namespaceDeclaration.CloseBraceToken.HasLeadingTrivia)
- {
- // Ensure there is one blank line before the trivia
- fileScopedNamespace = fileScopedNamespace
- .WithAppendedTrailingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed)
- .WithAppendedTrailingTrivia(namespaceDeclaration.CloseBraceToken.LeadingTrivia.WithoutLeadingBlankLines());
- }
-
- return fileScopedNamespace;
- }
-
- private static NamespaceDeclarationSyntax ConvertFileScopedNamespace(FileScopedNamespaceDeclarationSyntax fileScopedNamespace)
- {
- var namespaceDeclaration = SyntaxFactory.NamespaceDeclaration(
- fileScopedNamespace.AttributeLists,
- fileScopedNamespace.Modifiers,
- fileScopedNamespace.NamespaceKeyword,
- fileScopedNamespace.Name,
- SyntaxFactory.Token(SyntaxKind.OpenBraceToken).WithTrailingTrivia(fileScopedNamespace.SemicolonToken.TrailingTrivia),
- fileScopedNamespace.Externs,
- fileScopedNamespace.Usings,
- fileScopedNamespace.Members,
- SyntaxFactory.Token(SyntaxKind.CloseBraceToken),
- semicolonToken: default).WithAdditionalAnnotations(Formatter.Annotation);
-
- // Ensure there is no errant blank line between the open curly and the first body element.
- var firstBodyToken = namespaceDeclaration.OpenBraceToken.GetNextToken();
- if (firstBodyToken != namespaceDeclaration.CloseBraceToken &&
- firstBodyToken.Kind() != SyntaxKind.EndOfFileToken &&
- HasLeadingBlankLine(firstBodyToken, out var firstBodyTokenWithoutBlankLine))
- {
- namespaceDeclaration = namespaceDeclaration.ReplaceToken(firstBodyToken, firstBodyTokenWithoutBlankLine);
- }
-
- return namespaceDeclaration;
- }
- }
-}
diff --git a/src/Analyzers/CSharp/Tests/MakeFieldReadonly/MakeFieldReadonlyTests.cs b/src/Analyzers/CSharp/Tests/MakeFieldReadonly/MakeFieldReadonlyTests.cs
index 811f51493f746..9a7d768db6754 100644
--- a/src/Analyzers/CSharp/Tests/MakeFieldReadonly/MakeFieldReadonlyTests.cs
+++ b/src/Analyzers/CSharp/Tests/MakeFieldReadonly/MakeFieldReadonlyTests.cs
@@ -1717,13 +1717,13 @@ await TestInRegularAndScript1Async(
}
[WorkItem(46785, "https://github.com/dotnet/roslyn/issues/46785")]
- [Fact(Skip = "https://github.com/dotnet/roslyn/issues/46785"), Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)]
public async Task UsedAsRef_NoDiagnostic()
{
await TestMissingInRegularAndScriptAsync(
@"public class C
{
- private string [|_x|] = string.Empty;
+ private string [|x|] = string.Empty;
public bool M()
{
@@ -1733,6 +1733,26 @@ public bool M()
}");
}
+ [WorkItem(57983, "https://github.com/dotnet/roslyn/issues/57983")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)]
+ public async Task UsedAsRef_NoDiagnostic_02()
+ {
+ await TestMissingInRegularAndScriptAsync(
+@"using System.Runtime.CompilerServices;
+
+public class Test
+{
+ private ulong [|nextD3D12ComputeFenceValue|];
+
+ internal void Repro()
+ {
+ ref ulong d3D12FenceValue = ref Unsafe.NullRef();
+ d3D12FenceValue = ref nextD3D12ComputeFenceValue;
+ d3D12FenceValue++;
+ }
+}");
+ }
+
[WorkItem(42760, "https://github.com/dotnet/roslyn/issues/42760")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)]
public async Task WithThreadStaticAttribute_NoDiagnostic()
diff --git a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryExpressionParenthesesTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryExpressionParenthesesTests.cs
index 834a99db1e4e4..35ab81a00acf0 100644
--- a/src/Analyzers/CSharp/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryExpressionParenthesesTests.cs
+++ b/src/Analyzers/CSharp/Tests/RemoveUnnecessaryParentheses/RemoveUnnecessaryExpressionParenthesesTests.cs
@@ -2120,7 +2120,7 @@ void M()
{
void M()
{
-#ifA || B
+#if A || B
#endif
}
}",
@@ -2151,6 +2151,32 @@ void M()
offeredWhenRequireForClarityIsEnabled: true, index: 1);
}
+ [WorkItem(57768, "https://github.com/dotnet/roslyn/issues/57768")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryParentheses)]
+ public async Task TestParensAroundPPDirective3()
+ {
+ await TestAsync(
+@"class C
+{
+ void M()
+ {
+#if C
+#elif$$(A || B)
+#endif
+ }
+}",
+@"class C
+{
+ void M()
+ {
+#if C
+#elif A || B
+#endif
+ }
+}",
+offeredWhenRequireForClarityIsEnabled: true);
+ }
+
[WorkItem(29454, "https://github.com/dotnet/roslyn/issues/29454")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryParentheses)]
public async Task TestMissingForPreIncrement()
diff --git a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs
index 2ba5d60c76a3e..d65a510d172c2 100644
--- a/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs
+++ b/src/Analyzers/CSharp/Tests/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.cs
@@ -1503,6 +1503,36 @@ public C(int [|i|])
}");
}
+ [WorkItem(56317, "https://github.com/dotnet/roslyn/issues/56317")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedParameters)]
+ public async Task NotImplementedException_NoDiagnostic4()
+ {
+ await TestDiagnosticMissingAsync(
+@"using System;
+
+class C
+{
+ private int Goo(int [|i|])
+ => throw new NotImplementedException();
+}");
+ }
+
+ [WorkItem(56317, "https://github.com/dotnet/roslyn/issues/56317")]
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedParameters)]
+ public async Task NotImplementedException_NoDiagnostic5()
+ {
+ await TestDiagnosticMissingAsync(
+@"using System;
+
+class C
+{
+ private int Goo(int [|i|])
+ {
+ throw new NotImplementedException();
+ }
+}");
+ }
+
[WorkItem(41236, "https://github.com/dotnet/roslyn/issues/41236")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedParameters)]
public async Task NotImplementedException_MultipleStatements1()
diff --git a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs
index f110f9e90fdb9..54e1f0deb591e 100644
--- a/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs
+++ b/src/Analyzers/Core/Analyzers/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs
@@ -152,9 +152,18 @@ static bool IsSingleThrowNotImplementedOperation(IOperation firstBlock)
if (firstOp == null)
return false;
- // unwrap: { throw new NYI(); }
if (firstOp is IExpressionStatementOperation expressionStatement)
+ {
+ // unwrap: { throw new NYI(); }
firstOp = expressionStatement.Operation;
+ }
+ else if (firstOp is IReturnOperation returnOperation)
+ {
+ // unwrap: 'int M(int p) => throw new NYI();'
+ // For this case, the throw operation is wrapped within a conversion operation to 'int',
+ // which in turn is wrapped within a return operation.
+ firstOp = returnOperation.ReturnedValue.WalkDownConversion();
+ }
// => throw new NotImplementedOperation(...)
return IsThrowNotImplementedOperation(notImplementedExceptionType, firstOp);
@@ -177,7 +186,7 @@ static bool IsSingleThrowNotImplementedOperation(IOperation firstBlock)
return firstOp;
}
- static bool IsThrowNotImplementedOperation(INamedTypeSymbol notImplementedExceptionType, IOperation operation)
+ static bool IsThrowNotImplementedOperation(INamedTypeSymbol notImplementedExceptionType, IOperation? operation)
=> operation is IThrowOperation throwOperation &&
UnwrapImplicitConversion(throwOperation.Exception) is IObjectCreationOperation objectCreation &&
notImplementedExceptionType.Equals(objectCreation.Type);
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
index b2d1803e41124..df51a3425bc4f 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs
@@ -453,7 +453,7 @@ internal static void ReportReservedTypeName(string? name, CSharpCompilation comp
{
if (compilation.LanguageVersion >= MessageID.IDS_FeatureRecords.RequiredVersion())
{
- diagnostics.Add(ErrorCode.WRN_RecordNamedDisallowed, location, name);
+ diagnostics.Add(ErrorCode.WRN_RecordNamedDisallowed, location);
}
}
else if (IsReservedTypeName(name))
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
index 45b519df6a5bd..1e78065f9d519 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs
@@ -2854,7 +2854,7 @@ record M(record r) => r;
comp.VerifyDiagnostics(
// (2,7): warning CS8860: Types and aliases should not be named 'record'.
// class record { }
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 7),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 7),
// (6,24): error CS1514: { expected
// record M(record r) => r;
Diagnostic(ErrorCode.ERR_LbraceExpected, "=>").WithLocation(6, 24),
@@ -2886,7 +2886,7 @@ struct record { }
comp.VerifyDiagnostics(
// (2,8): warning CS8860: Types and aliases should not be named 'record'.
// struct record { }
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 8)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 8)
);
}
@@ -2900,7 +2900,7 @@ interface record { }
comp.VerifyDiagnostics(
// (2,11): warning CS8860: Types and aliases should not be named 'record'.
// interface record { }
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 11)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 11)
);
}
@@ -2914,7 +2914,7 @@ enum record { }
comp.VerifyDiagnostics(
// (2,6): warning CS8860: Types and aliases should not be named 'record'.
// enum record { }
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 6)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 6)
);
}
@@ -2928,7 +2928,7 @@ public void TypeNamedRecord_Delegate()
comp.VerifyDiagnostics(
// (2,15): warning CS8860: Types and aliases should not be named 'record'.
// delegate void record();
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 15)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 15)
);
}
@@ -2955,7 +2955,7 @@ public void TypeNamedRecord_Alias()
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using record = System.Console;").WithLocation(2, 1),
// (2,7): warning CS8860: Types and aliases should not be named 'record'.
// using record = System.Console;
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 7)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 7)
);
}
@@ -2999,16 +2999,16 @@ void local() // 4
comp.VerifyDiagnostics(
// (2,9): warning CS8860: Types and aliases should not be named 'record'.
// class C { } // 1
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 9),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 9),
// (5,18): warning CS8860: Types and aliases should not be named 'record'.
// class Nested { } // 2
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(5, 18),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(5, 18),
// (9,17): warning CS8860: Types and aliases should not be named 'record'.
// void Method() { } // 3
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(9, 17),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(9, 17),
// (13,20): warning CS8860: Types and aliases should not be named 'record'.
// void local() // 4
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(13, 20)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(13, 20)
);
}
@@ -3078,31 +3078,31 @@ partial void Method4() { } // 9
comp.VerifyDiagnostics(
// (3,17): warning CS8860: Types and aliases should not be named 'record'.
// partial class C { } // 1
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(3, 17),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(3, 17),
// (5,17): warning CS8860: Types and aliases should not be named 'record'.
// partial class D { } // 2
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(5, 17),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(5, 17),
// (8,17): warning CS8860: Types and aliases should not be named 'record'.
// partial class D { } // 3
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(8, 17),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(8, 17),
// (9,17): warning CS8860: Types and aliases should not be named 'record'.
// partial class D { } // 4
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(9, 17),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(9, 17),
// (16,26): warning CS8860: Types and aliases should not be named 'record'.
// partial class Nested { } // 5
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(16, 26),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(16, 26),
// (22,25): warning CS8860: Types and aliases should not be named 'record'.
// partial void Method() { } // 6
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(22, 25),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(22, 25),
// (25,26): warning CS8860: Types and aliases should not be named 'record'.
// partial void Method2(); // 7
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(25, 26),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(25, 26),
// (27,26): warning CS8860: Types and aliases should not be named 'record'.
// partial void Method3(); // 8
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(27, 26),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(27, 26),
// (30,26): warning CS8860: Types and aliases should not be named 'record'.
// partial void Method4() { } // 9
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(30, 26)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(30, 26)
);
}
@@ -3116,7 +3116,7 @@ record record { }
comp.VerifyDiagnostics(
// (2,8): warning CS8860: Types and aliases should not be named 'record'.
// record record { }
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 8)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 8)
);
}
@@ -3131,10 +3131,10 @@ partial class record { }
comp.VerifyDiagnostics(
// (2,15): warning CS8860: Types and aliases should not be named 'record'.
// partial class record { }
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 15),
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 15),
// (3,15): warning CS8860: Types and aliases should not be named 'record'.
// partial class record { }
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(3, 15)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(3, 15)
);
}
@@ -3159,7 +3159,7 @@ partial class record { }
comp.VerifyDiagnostics(
// (3,15): warning CS8860: Types and aliases should not be named 'record'.
// partial class record { }
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(3, 15)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(3, 15)
);
}
@@ -3174,7 +3174,7 @@ partial class @record { }
comp.VerifyDiagnostics(
// (2,15): warning CS8860: Types and aliases should not be named 'record'.
// partial class record { }
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 15)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 15)
);
}
@@ -3213,7 +3213,7 @@ public static void Main()
comp.VerifyEmitDiagnostics(
// (2,7): warning CS8860: Types and aliases should not be named 'record'.
// class record { }
- Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 7)
+ Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithLocation(2, 7)
);
CompileAndVerify(comp, expectedOutput: "RAN");
}
diff --git a/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs b/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs
index 57217b7bdad0a..f5da455501648 100644
--- a/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs
+++ b/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs
@@ -3,7 +3,8 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.IO;
+using System.Collections.Generic;
+using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis;
@@ -13,18 +14,27 @@ namespace Roslyn.Test.Utilities.TestGenerators
{
internal class SingleFileTestGenerator : ISourceGenerator
{
- private readonly string _content;
- private readonly string _hintName;
+ private readonly List<(string content, string hintName)> _sources = new();
- public SingleFileTestGenerator(string content, string hintName = "generatedFile")
+ public SingleFileTestGenerator()
{
- _content = content;
- _hintName = hintName;
+ }
+
+ public SingleFileTestGenerator(string content, string? hintName = null)
+ {
+ AddSource(content, hintName);
+ }
+
+ public void AddSource(string content, string? hintName = null)
+ {
+ hintName ??= "generatedFile" + (_sources.Any() ? (_sources.Count + 1).ToString() : "");
+ _sources.Add((content, hintName));
}
public void Execute(GeneratorExecutionContext context)
{
- context.AddSource(this._hintName, SourceText.From(_content, Encoding.UTF8));
+ foreach (var (content, hintName) in _sources)
+ context.AddSource(hintName, SourceText.From(content, Encoding.UTF8));
}
public void Initialize(GeneratorInitializationContext context)
diff --git a/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs b/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs
index f18338c3709f3..3b0cba7fa8cf0 100644
--- a/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs
+++ b/src/EditorFeatures/CSharp/ConvertNamespace/ConvertNamespaceCommandHandler.cs
@@ -26,6 +26,7 @@
using Microsoft.VisualStudio.Text.Editor.Commanding.Commands;
using Microsoft.VisualStudio.Text.Operations;
using Microsoft.VisualStudio.Utilities;
+using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.CSharp.CompleteStatement
{
@@ -39,11 +40,6 @@ namespace Microsoft.CodeAnalysis.Editor.CSharp.CompleteStatement
[Order(After = PredefinedCompletionNames.CompletionCommandHandler)]
internal sealed class ConvertNamespaceCommandHandler : IChainedCommandHandler
{
- ///
- /// Annotation used so we can find the semicolon after formatting so that we can properly place the caret.
- ///
- private static readonly SyntaxAnnotation s_annotation = new();
-
///
/// A fake option set where the 'use file scoped' namespace option is on. That way we can call into the helpers
/// and have the results come back positive for converting to file-scoped regardless of the current option
@@ -79,7 +75,7 @@ public CommandState GetCommandState(TypeCharCommandArgs args, Func
public void ExecuteCommand(TypeCharCommandArgs args, Action nextCommandHandler, CommandExecutionContext executionContext)
{
// Attempt to convert the block-namespace to a file-scoped namespace if we're at the right location.
- var convertedRoot = ConvertNamespace(args, executionContext);
+ var (convertedText, semicolonSpan) = ConvertNamespace(args, executionContext);
// No matter if we succeeded or not, insert the semicolon. This way, when we convert, the user can still
// hit ctrl-z to get back to the code with just the semicolon inserted.
@@ -87,7 +83,7 @@ public void ExecuteCommand(TypeCharCommandArgs args, Action nextCommandHandler,
// If we weren't on a block namespace (or couldn't convert it for some reason), then bail out after
// inserting the semicolon.
- if (convertedRoot == null)
+ if (convertedText == null)
return;
// Otherwise, make a transaction for the edit and replace the buffer with the final text.
@@ -95,14 +91,12 @@ public void ExecuteCommand(TypeCharCommandArgs args, Action nextCommandHandler,
this.DisplayName, args.TextView, _textUndoHistoryRegistry, _editorOperationsFactoryService);
var edit = args.SubjectBuffer.CreateEdit(EditOptions.DefaultMinimalChange, reiteratedVersionNumber: null, editTag: null);
- edit.Replace(new Span(0, args.SubjectBuffer.CurrentSnapshot.Length), convertedRoot.ToFullString());
+ edit.Replace(new Span(0, args.SubjectBuffer.CurrentSnapshot.Length), convertedText.ToString());
edit.Apply();
- // Attempt to place the caret right after the semicolon of the file-scoped namespace.
- var annotatedToken = convertedRoot.GetAnnotatedTokens(s_annotation).FirstOrDefault();
- if (annotatedToken != default)
- args.TextView.Caret.MoveTo(new SnapshotPoint(args.SubjectBuffer.CurrentSnapshot, annotatedToken.Span.End));
+ // Place the caret right after the semicolon of the file-scoped namespace.
+ args.TextView.Caret.MoveTo(new SnapshotPoint(args.SubjectBuffer.CurrentSnapshot, semicolonSpan.End));
transaction?.Complete();
}
@@ -111,25 +105,25 @@ public void ExecuteCommand(TypeCharCommandArgs args, Action nextCommandHandler,
/// Returns the updated file contents if semicolon is typed after a block-scoped namespace name that can be
/// converted.
///
- private CompilationUnitSyntax? ConvertNamespace(
+ private (SourceText? convertedText, TextSpan semicolonSpan) ConvertNamespace(
TypeCharCommandArgs args,
CommandExecutionContext executionContext)
{
if (args.TypedChar != ';' || !args.TextView.Selection.IsEmpty)
- return null;
+ return default;
if (!_globalOptions.GetOption(FeatureOnOffOptions.AutomaticallyCompleteStatementOnSemicolon))
- return null;
+ return default;
var subjectBuffer = args.SubjectBuffer;
var caretOpt = args.TextView.GetCaretPoint(subjectBuffer);
if (!caretOpt.HasValue)
- return null;
+ return default;
var caret = caretOpt.Value.Position;
var document = subjectBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();
if (document == null)
- return null;
+ return default;
var cancellationToken = executionContext.OperationContext.UserCancellationToken;
var root = (CompilationUnitSyntax)document.GetRequiredSyntaxRootSynchronously(cancellationToken);
@@ -137,39 +131,29 @@ public void ExecuteCommand(TypeCharCommandArgs args, Action nextCommandHandler,
// User has to be *after* an identifier token.
var token = root.FindToken(caret);
if (token.Kind() != SyntaxKind.IdentifierToken)
- return null;
+ return default;
if (caret < token.Span.End ||
caret >= token.FullSpan.End)
{
- return null;
+ return default;
}
var namespaceDecl = token.GetRequiredParent().GetAncestor();
if (namespaceDecl == null)
- return null;
+ return default;
// That identifier token has to be the last part of a namespace name.
if (namespaceDecl.Name.GetLastToken() != token)
- return null;
+ return default;
// Pass in our special options, and C#10 so that if we can convert this to file-scoped, we will.
if (!ConvertNamespaceAnalysis.CanOfferUseFileScoped(s_optionSet, root, namespaceDecl, forAnalyzer: true, LanguageVersion.CSharp10))
- return null;
-
- var fileScopedNamespace = (FileScopedNamespaceDeclarationSyntax)ConvertNamespaceTransform.Convert(namespaceDecl);
-
- // Place an annotation on the semicolon so that we can find it post-formatting to place the caret.
- fileScopedNamespace = fileScopedNamespace.WithSemicolonToken(
- fileScopedNamespace.SemicolonToken.WithAdditionalAnnotations(s_annotation));
-
- var convertedRoot = root.ReplaceNode(namespaceDecl, fileScopedNamespace);
- var formattedRoot = (CompilationUnitSyntax)Formatter.Format(
- convertedRoot, Formatter.Annotation,
- document.Project.Solution.Workspace,
- options: null, rules: null, cancellationToken);
+ return default;
- return formattedRoot;
+ var (converted, semicolonSpan) = ConvertNamespaceTransform.ConvertNamespaceDeclarationAsync(document, namespaceDecl, cancellationToken).WaitAndGetResult(cancellationToken);
+ var text = converted.GetTextSynchronously(cancellationToken);
+ return (text, semicolonSpan);
}
}
}
diff --git a/src/EditorFeatures/CSharp/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs b/src/EditorFeatures/CSharp/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs
index 76dc07e72e453..a66120dc6f69e 100644
--- a/src/EditorFeatures/CSharp/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs
+++ b/src/EditorFeatures/CSharp/EventHookup/EventHookupCommandHandler_TabKeyCommand.cs
@@ -186,9 +186,10 @@ private static Document AddMethodNameAndAnnotationsToSolution(
var root = document.GetSyntaxRootSynchronously(cancellationToken);
var plusEqualsToken = root.FindTokenOnLeftOfPosition(position);
var eventHookupExpression = plusEqualsToken.GetAncestor();
+ var typeDecl = eventHookupExpression.GetAncestor();
var textToInsert = eventHandlerMethodName + ";";
- if (!eventHookupExpression.IsInStaticContext())
+ if (!eventHookupExpression.IsInStaticContext() && typeDecl is not null)
{
// This will be simplified later if it's not needed.
textToInsert = "this." + textToInsert;
@@ -222,6 +223,8 @@ private static SyntaxNode AddGeneratedHandlerMethodToSolution(
var root = document.Root;
var eventHookupExpression = root.GetAnnotatedNodesAndTokens(plusEqualsTokenAnnotation).Single().AsToken().GetAncestor();
+ var typeDecl = eventHookupExpression.GetAncestor();
+
var generatedMethodSymbol = GetMethodSymbol(document, eventHandlerMethodName, eventHookupExpression, cancellationToken);
if (generatedMethodSymbol == null)
@@ -229,11 +232,11 @@ private static SyntaxNode AddGeneratedHandlerMethodToSolution(
return null;
}
- var typeDecl = eventHookupExpression.GetAncestor();
+ var container = (SyntaxNode)typeDecl ?? eventHookupExpression.GetAncestor();
- var typeDeclWithMethodAdded = CodeGenerator.AddMethodDeclaration(typeDecl, generatedMethodSymbol, document.Project.Solution.Workspace, new CodeGenerationOptions(afterThisLocation: eventHookupExpression.GetLocation()));
+ var newContainer = CodeGenerator.AddMethodDeclaration(container, generatedMethodSymbol, document.Project.Solution.Workspace, new CodeGenerationOptions(afterThisLocation: eventHookupExpression.GetLocation()));
- return root.ReplaceNode(typeDecl, typeDeclWithMethodAdded);
+ return root.ReplaceNode(container, newContainer);
}
private static IMethodSymbol GetMethodSymbol(
diff --git a/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager.cs b/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager.cs
index 570b58457add4..de8b8614f8726 100644
--- a/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager.cs
+++ b/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager.cs
@@ -50,7 +50,7 @@ internal void EventHookupFoundInSession(EventHookupSession analyzedSession)
if (_toolTipPresenter == null &&
CurrentSession == analyzedSession &&
caretPoint.HasValue &&
- analyzedSession.TrackingSpan.GetSpan(CurrentSession.TextView.TextSnapshot).Contains(caretPoint.Value))
+ IsCaretWithinSpanOrAtEnd(analyzedSession.TrackingSpan, analyzedSession.TextView.TextSnapshot, caretPoint.Value))
{
// Create a tooltip presenter that stays alive, even when the user types, without tracking the mouse.
_toolTipPresenter = _toolTipService.CreatePresenter(analyzedSession.TextView,
@@ -80,6 +80,28 @@ internal void EventHookupFoundInSession(EventHookupSession analyzedSession)
}
}
+ private static bool IsCaretWithinSpanOrAtEnd(ITrackingSpan trackingSpan, ITextSnapshot textSnapshot, SnapshotPoint caretPoint)
+ {
+ var snapshotSpan = trackingSpan.GetSpan(textSnapshot);
+
+ // If the caret is within the span, then we want to show the tooltip
+ if (snapshotSpan.Contains(caretPoint))
+ {
+ return true;
+ }
+
+ // Otherwise if the span is empty, and at the end of the file, and the caret
+ // is also at the end of the file, then show the tooltip.
+ if (snapshotSpan.IsEmpty &&
+ snapshotSpan.Start.Position == caretPoint.Position &&
+ caretPoint.Position == textSnapshot.Length)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
internal void BeginSession(
EventHookupCommandHandler eventHookupCommandHandler,
ITextView textView,
diff --git a/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager_EventHookupSession.cs b/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager_EventHookupSession.cs
index e7f4f2bcbcfff..12dbd69c81d9e 100644
--- a/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager_EventHookupSession.cs
+++ b/src/EditorFeatures/CSharp/EventHookup/EventHookupSessionManager_EventHookupSession.cs
@@ -114,7 +114,10 @@ public EventHookupSession(
{
var position = textView.GetCaretPoint(subjectBuffer).Value.Position;
_trackingPoint = textView.TextSnapshot.CreateTrackingPoint(position, PointTrackingMode.Negative);
- _trackingSpan = textView.TextSnapshot.CreateTrackingSpan(new Span(position, 1), SpanTrackingMode.EdgeInclusive);
+
+ // If the caret is at the end of the document we just create an empty span
+ var length = textView.TextSnapshot.Length > position + 1 ? 1 : 0;
+ _trackingSpan = textView.TextSnapshot.CreateTrackingSpan(new Span(position, length), SpanTrackingMode.EdgeInclusive);
var asyncToken = asyncListener.BeginAsyncOperation(GetType().Name + ".Start");
diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs
index b9e38257411fe..7bf6a90253c83 100644
--- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs
@@ -440,7 +440,7 @@ public async Task CrefCompletionSpeculatesOutsideTrivia()
class C
{
}";
- using var workspace = TestWorkspace.Create(LanguageNames.CSharp, new CSharpCompilationOptions(OutputKind.ConsoleApplication), new CSharpParseOptions(), new[] { text }, ExportProvider);
+ using var workspace = TestWorkspace.Create(LanguageNames.CSharp, new CSharpCompilationOptions(OutputKind.ConsoleApplication), new CSharpParseOptions(), new[] { text }, exportProvider: ExportProvider);
var called = false;
var hostDocument = workspace.DocumentWithCursor;
diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs
index 7beee24d167d8..043ff896b0a6a 100644
--- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs
+++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs
@@ -2777,7 +2777,7 @@ static void Main(string[] args)
override $$
}
}";
- using var workspace = TestWorkspace.Create(LanguageNames.CSharp, new CSharpCompilationOptions(OutputKind.ConsoleApplication), new CSharpParseOptions(), new[] { text }, ExportProvider);
+ using var workspace = TestWorkspace.Create(LanguageNames.CSharp, new CSharpCompilationOptions(OutputKind.ConsoleApplication), new CSharpParseOptions(), new[] { text }, exportProvider: ExportProvider);
var provider = new OverrideCompletionProvider();
var testDocument = workspace.Documents.Single();
var document = workspace.CurrentSolution.GetRequiredDocument(testDocument.Id);
diff --git a/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceCommandHandlerTests.cs b/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceCommandHandlerTests.cs
index 738bbb1a11c82..42e05bdf1de6d 100644
--- a/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceCommandHandlerTests.cs
+++ b/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceCommandHandlerTests.cs
@@ -44,7 +44,9 @@ public static XElement GetWorkspaceXml(string markup)
internal void AssertCodeIs(string expectedCode)
{
- Assert.Equal(expectedCode, TextView.TextSnapshot.GetText());
+ MarkupTestFile.GetPosition(expectedCode, out var massaged, out int caretPosition);
+ Assert.Equal(massaged, TextView.TextSnapshot.GetText());
+ Assert.Equal(caretPosition, TextView.Caret.Position.BufferPosition.Position);
}
public void SendTypeChar(char ch)
@@ -64,7 +66,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace N;
+@"namespace N;$$
class C
{
@@ -88,7 +90,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace N;
+@"namespace N;$$
{
class C
{
@@ -109,7 +111,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace A.B;
+@"namespace A.B;$$
class C
{
@@ -130,7 +132,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace A.;B
+@"namespace A.;$$B
{
class C
{
@@ -151,7 +153,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace A;.B
+@"namespace A;$$.B
{
class C
{
@@ -172,7 +174,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace ;A.B
+@"namespace ;$$A.B
{
class C
{
@@ -193,7 +195,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace A.B;
+@"namespace A.B;$$
class C
{
@@ -214,7 +216,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace ;N
+@"namespace ;$$N
{
class C
{
@@ -238,7 +240,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace N;
+@"namespace N;$$
{
namespace N2
{
@@ -266,7 +268,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace N;
+@"namespace N;$$
{
}
@@ -299,7 +301,7 @@ class C
using A;
using B;
-namespace N;
+namespace N;$$
class C
{
@@ -325,7 +327,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
@"
-namespace N;
+namespace N;$$
using A;
using B;
@@ -349,7 +351,7 @@ class C
testState.SendTypeChar(';');
testState.AssertCodeIs(
-@"namespace N; // Goo
+@"namespace N;$$ // Goo
class C
{
diff --git a/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringTests.cs b/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringTests.cs
index feae3626badc2..45f83851ce2c2 100644
--- a/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringTests.cs
+++ b/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertNamespaceRefactoringTests.cs
@@ -417,8 +417,9 @@ class C
}
",
FixedCode = @"
-namespace $$N; // comment
+namespace $$N;
+// comment
class C
{
}
@@ -477,10 +478,9 @@ public async Task TextConvertToFileScopedWithCommentedOutContents()
",
FixedCode = @"
namespace N;
-
- // public class C
- // {
- // }
+// public class C
+// {
+// }
",
LanguageVersion = LanguageVersion.CSharp10,
Options =
@@ -513,7 +513,7 @@ public class C
{
}
- // I'll probably write some more code here later
+// I'll probably write some more code here later
",
LanguageVersion = LanguageVersion.CSharp10,
Options =
diff --git a/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertToFileScopedNamespaceAnalyzerTests.cs b/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertToFileScopedNamespaceAnalyzerTests.cs
index 532c4c132d8b1..2e1d7d2ee8b01 100644
--- a/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertToFileScopedNamespaceAnalyzerTests.cs
+++ b/src/EditorFeatures/CSharpTest/ConvertNamespace/ConvertToFileScopedNamespaceAnalyzerTests.cs
@@ -347,8 +347,9 @@ class C
}
",
FixedCode = @"
-namespace $$N; // comment
+namespace $$N;
+// comment
class C
{
}
@@ -391,6 +392,330 @@ class C
}.RunAsync();
}
+ [Fact]
+ public async Task TestConvertToFileScopedWithDocComment()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = @"
+[|namespace N|]
+{
+ ///
+ class C
+ {
+ }
+}
+",
+ FixedCode = @"
+namespace $$N;
+
+///
+class C
+{
+}
+",
+ LanguageVersion = LanguageVersion.CSharp10,
+ Options =
+ {
+ { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
+ }
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestConvertToFileScopedWithPPDirective1()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = @"
+[|namespace N|]
+{
+#if X
+ class C
+ {
+ }
+#else
+ class C
+ {
+ }
+#endif
+}
+",
+ FixedCode = @"
+namespace $$N;
+
+#if X
+class C
+{
+}
+#else
+class C
+{
+}
+#endif
+",
+ LanguageVersion = LanguageVersion.CSharp10,
+ Options =
+ {
+ { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
+ }
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestConvertToFileScopedWithBlockComment()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = @"
+[|namespace N|]
+{
+ /* x
+ * x
+ */
+ class C
+ {
+ }
+}
+",
+ FixedCode = @"
+namespace $$N;
+
+/* x
+ * x
+ */
+class C
+{
+}
+",
+ LanguageVersion = LanguageVersion.CSharp10,
+ Options =
+ {
+ { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
+ }
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestConvertToFileScopedWithBlockComment2()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = @"
+[|namespace N|]
+{
+ /* x
+ x
+ */
+ class C
+ {
+ }
+}
+",
+ FixedCode = @"
+namespace $$N;
+
+/* x
+ x
+ */
+class C
+{
+}
+",
+ LanguageVersion = LanguageVersion.CSharp10,
+ Options =
+ {
+ { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
+ }
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestConvertToFileScopedWithMultilineString()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = @"
+[|namespace N|]
+{
+ class C
+ {
+ void M()
+ {
+ System.Console.WriteLine(@""
+ a
+ b
+ c
+ d
+ e
+ "");
+ }
+ }
+}
+",
+ FixedCode = @"
+namespace $$N;
+
+class C
+{
+ void M()
+ {
+ System.Console.WriteLine(@""
+ a
+ b
+ c
+ d
+ e
+ "");
+ }
+}
+",
+ LanguageVersion = LanguageVersion.CSharp10,
+ Options =
+ {
+ { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
+ }
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestConvertToFileScopedWithMultilineString2()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = @"
+[|namespace N|]
+{
+ class C
+ {
+ void M()
+ {
+ System.Console.WriteLine($@""
+ a
+ b
+ c{1 + 1}
+ d
+ e
+ "");
+ }
+ }
+}
+",
+ FixedCode = @"
+namespace $$N;
+
+class C
+{
+ void M()
+ {
+ System.Console.WriteLine($@""
+ a
+ b
+ c{1 + 1}
+ d
+ e
+ "");
+ }
+}
+",
+ LanguageVersion = LanguageVersion.CSharp10,
+ Options =
+ {
+ { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
+ }
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestConvertToFileScopedWithMultilineString3()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = @"
+[|namespace N|]
+{
+ class C
+ {
+ void M()
+ {
+ System.Console.WriteLine($@""
+ a
+ b
+ c{
+ 1 + 1
+ }d
+ e
+ "");
+ }
+ }
+}
+",
+ FixedCode = @"
+namespace $$N;
+
+class C
+{
+ void M()
+ {
+ System.Console.WriteLine($@""
+ a
+ b
+ c{
+ 1 + 1
+ }d
+ e
+ "");
+ }
+}
+",
+ LanguageVersion = LanguageVersion.CSharp10,
+ Options =
+ {
+ { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
+ }
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestConvertToFileScopedSingleLineNamespace1()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = @"
+[|namespace N|] { class C { } }
+",
+ FixedCode = @"
+namespace $$N;
+class C { } ",
+ LanguageVersion = LanguageVersion.CSharp10,
+ Options =
+ {
+ { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
+ }
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestConvertToFileScopedSingleLineNamespace2()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = @"
+[|namespace N|]
+{ class C { } }
+",
+ FixedCode = @"
+namespace $$N;
+
+class C { } ",
+ LanguageVersion = LanguageVersion.CSharp10,
+ Options =
+ {
+ { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
+ }
+ }.RunAsync();
+ }
+
#endregion
}
}
diff --git a/src/EditorFeatures/CSharpTest/EventHookup/EventHookupCommandHandlerTests.cs b/src/EditorFeatures/CSharpTest/EventHookup/EventHookupCommandHandlerTests.cs
index 6fbb7e3cbe8fb..0d57db3ad040d 100644
--- a/src/EditorFeatures/CSharpTest/EventHookup/EventHookupCommandHandlerTests.cs
+++ b/src/EditorFeatures/CSharpTest/EventHookup/EventHookupCommandHandlerTests.cs
@@ -1024,6 +1024,62 @@ private void C_MyEvent()
testState.AssertCodeIs(expectedCode);
}
+ [WpfFact, Trait(Traits.Feature, Traits.Features.EventHookup)]
+ [WorkItem(58474, "https://github.com/dotnet/roslyn/issues/58474")]
+ public async Task EventHookupInTopLevelCode()
+ {
+ var markup = @"
+
+System.AppDomain.CurrentDomain.UnhandledException +$$
+
+";
+ using var testState = EventHookupTestState.CreateTestState(markup);
+ testState.SendTypeChar('=');
+ testState.SendTab();
+ await testState.WaitForAsynchronousOperationsAsync();
+
+ var expectedCode = @"
+
+System.AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
+
+void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
+{
+ throw new System.NotImplementedException();
+}";
+ testState.AssertCodeIs(expectedCode);
+ }
+
+ [WpfFact, Trait(Traits.Feature, Traits.Features.EventHookup)]
+ public async Task EventHookupAtEndOfDocument()
+ {
+ var markup = @"
+
+System.AppDomain.CurrentDomain.UnhandledException +$$";
+ using var testState = EventHookupTestState.CreateTestState(markup);
+ testState.SendTypeChar('=');
+
+ await testState.WaitForAsynchronousOperationsAsync();
+ testState.AssertShowing("CurrentDomain_UnhandledException");
+
+ var expectedCode = @"
+
+System.AppDomain.CurrentDomain.UnhandledException +=";
+ testState.AssertCodeIs(expectedCode);
+
+ testState.SendTab();
+ await testState.WaitForAsynchronousOperationsAsync();
+
+ expectedCode = @"
+
+System.AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
+
+void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
+{
+ throw new System.NotImplementedException();
+}";
+ testState.AssertCodeIs(expectedCode);
+ }
+
private static OptionsCollection QualifyMethodAccessWithNotification(NotificationOption2 notification)
=> new OptionsCollection(LanguageNames.CSharp) { { CodeStyleOptions2.QualifyMethodAccess, true, notification } };
}
diff --git a/src/EditorFeatures/CSharpTest/InlineDiagnostics/InlineDiagnosticsTaggerProviderTests.cs b/src/EditorFeatures/CSharpTest/InlineDiagnostics/InlineDiagnosticsTaggerProviderTests.cs
new file mode 100644
index 0000000000000..fcbb5b673911a
--- /dev/null
+++ b/src/EditorFeatures/CSharpTest/InlineDiagnostics/InlineDiagnosticsTaggerProviderTests.cs
@@ -0,0 +1,47 @@
+// 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.Collections.Immutable;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.Editor.InlineDiagnostics;
+using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions;
+using Microsoft.CodeAnalysis.Editor.UnitTests.Squiggles;
+using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.Test.Utilities;
+using Microsoft.VisualStudio.Text.Adornments;
+using Microsoft.VisualStudio.Text.Tagging;
+using Roslyn.Test.Utilities;
+using Roslyn.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.InlineDiagnostics
+{
+ [UseExportProvider]
+ public class InlineDiagnosticsTaggerProviderTests
+ {
+ [WpfFact, Trait(Traits.Feature, Traits.Features.ErrorSquiggles)]
+ public async Task ErrorTagGeneratedForError()
+ {
+ var spans = await GetTagSpansAsync("class C {");
+ Assert.Equal(1, spans.Count());
+
+ var firstSpan = spans.First();
+ Assert.Equal(PredefinedErrorTypeNames.SyntaxError, firstSpan.Tag.ErrorType);
+ }
+
+ private static async Task>> GetTagSpansAsync(string content)
+ {
+ using var workspace = TestWorkspace.CreateCSharp(content, composition: SquiggleUtilities.WpfCompositionWithSolutionCrawler);
+ return await GetTagSpansAsync(workspace);
+ }
+
+ private static async Task>> GetTagSpansAsync(TestWorkspace workspace)
+ {
+ workspace.ApplyOptions(new[] { KeyValuePairUtil.Create(new OptionKey2(InlineDiagnosticsOptions.EnableInlineDiagnostics, LanguageNames.CSharp), (object)true) });
+ return (await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace)).Item2;
+ }
+ }
+}
diff --git a/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs b/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs
index 8156a2a56398e..0aa8e949a25e4 100644
--- a/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs
+++ b/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs
@@ -2,6 +2,7 @@
// 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.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -1473,6 +1474,36 @@ public class C
},
await _aggregator.GetItemsAsync("C"));
}
+
+ [Fact]
+ public async Task DoIncludeSymbolsFromMultipleSourceGeneratedFiles()
+ {
+ using var workspace = TestWorkspace.CreateCSharp(
+ files: Array.Empty(),
+ sourceGeneratedFiles: new[]
+ {
+ @"
+public partial class C
+{
+}",
+ @"
+public partial class C
+{
+}",
+ },
+ composition: EditorTestCompositions.EditorFeatures);
+
+ _provider = new NavigateToItemProvider(workspace, AsynchronousOperationListenerProvider.NullListener, workspace.GetService());
+ _aggregator = new NavigateToTestAggregator(_provider);
+
+ VerifyNavigateToResultItems(
+ new()
+ {
+ new NavigateToItem("C", NavigateToItemKind.Class, "csharp", null, null, s_emptyExactPatternMatch, null),
+ new NavigateToItem("C", NavigateToItemKind.Class, "csharp", null, null, s_emptyExactPatternMatch, null),
+ },
+ await _aggregator.GetItemsAsync("C"));
+ }
}
}
#pragma warning restore CS0618 // MatchKind is obsolete
diff --git a/src/EditorFeatures/CSharpTest/ReassignedVariable/CSharpReassignedVariableTests.cs b/src/EditorFeatures/CSharpTest/ReassignedVariable/CSharpReassignedVariableTests.cs
index 4860b46b1673a..f7fe02f04df99 100644
--- a/src/EditorFeatures/CSharpTest/ReassignedVariable/CSharpReassignedVariableTests.cs
+++ b/src/EditorFeatures/CSharpTest/ReassignedVariable/CSharpReassignedVariableTests.cs
@@ -8,6 +8,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.UnitTests.ReassignedVariable;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
+using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ReassignedVariable
@@ -652,6 +653,23 @@ void M()
}");
}
+ [Fact]
+ public async Task TestReadonlyRefLocalWithNoReassignment1()
+ {
+ await TestAsync(
+@"
+using System;
+class C
+{
+ void M()
+ {
+ int p = 0;
+ ref readonly int refP = ref p!;
+ Console.WriteLine(p);
+ }
+}");
+ }
+
[Fact]
public async Task TestPointerCausingPossibleReassignment()
{
@@ -994,6 +1012,22 @@ void M(int p, int p)
{
p = 1;
}
+}");
+ }
+
+ [Fact, WorkItem(58161, "https://github.com/dotnet/roslyn/issues/58161")]
+ public async Task TestRefToSuppression1()
+ {
+ await TestAsync(
+@"#nullable enable
+
+using System.Diagnostics.CodeAnalysis;
+using System.Threading;
+
+class C
+{
+ public static T EnsureInitialized([NotNull] ref T? [|target|]) where T : class
+ => Volatile.Read(ref [|target|]!);
}");
}
}
diff --git a/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs b/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs
index cbdbef1636087..599213a3cc41b 100644
--- a/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs
+++ b/src/EditorFeatures/CSharpTest/Squiggles/ErrorSquiggleProducerTests.cs
@@ -75,7 +75,7 @@ void Test()
";
using var workspace = TestWorkspace.Create(workspaceXml);
- var spans = (await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace)).Item2;
+ var spans = (await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace)).Item2;
Assert.Equal(1, spans.Count());
Assert.Equal(PredefinedErrorTypeNames.SyntaxError, spans.First().Tag.ErrorType);
@@ -126,7 +126,7 @@ void Test()
}
};
- var diagnosticsAndSpans = await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace, analyzerMap);
+ var diagnosticsAndSpans = await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace, analyzerMap);
var spans =
diagnosticsAndSpans.Item1
@@ -204,7 +204,7 @@ public async Task SemanticErrorReported()
{
using var workspace = TestWorkspace.CreateCSharp("class C : Bar { }", composition: SquiggleUtilities.CompositionWithSolutionCrawler);
- var spans = await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace);
+ var spans = await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace);
Assert.Equal(1, spans.Item2.Count());
@@ -296,10 +296,10 @@ class Test
var updateArgs = DiagnosticsUpdatedArgs.DiagnosticsCreated(
new object(), workspace, workspace.CurrentSolution, document.Project.Id, document.Id,
ImmutableArray.Create(
- TestDiagnosticTagProducer.CreateDiagnosticData(document, new TextSpan(0, 0)),
- TestDiagnosticTagProducer.CreateDiagnosticData(document, new TextSpan(0, 1))));
+ TestDiagnosticTagProducer.CreateDiagnosticData(document, new TextSpan(0, 0)),
+ TestDiagnosticTagProducer.CreateDiagnosticData(document, new TextSpan(0, 1))));
- var spans = await TestDiagnosticTagProducer.GetErrorsFromUpdateSource(workspace, updateArgs);
+ var spans = await TestDiagnosticTagProducer.GetErrorsFromUpdateSource(workspace, updateArgs);
Assert.Equal(1, spans.Count());
var first = spans.First();
@@ -327,10 +327,10 @@ class Test
var updateArgs = DiagnosticsUpdatedArgs.DiagnosticsCreated(
new LiveId(), workspace, workspace.CurrentSolution, document.Project.Id, document.Id,
ImmutableArray.Create(
- TestDiagnosticTagProducer.CreateDiagnosticData(document, new TextSpan(0, 0)),
- TestDiagnosticTagProducer.CreateDiagnosticData(document, new TextSpan(0, 1))));
+ TestDiagnosticTagProducer.CreateDiagnosticData(document, new TextSpan(0, 0)),
+ TestDiagnosticTagProducer.CreateDiagnosticData(document, new TextSpan(0, 1))));
- var spans = await TestDiagnosticTagProducer.GetErrorsFromUpdateSource(workspace, updateArgs);
+ var spans = await TestDiagnosticTagProducer.GetErrorsFromUpdateSource(workspace, updateArgs);
Assert.Equal(2, spans.Count());
var first = spans.First();
@@ -350,7 +350,7 @@ public LiveId()
private static async Task>> GetTagSpansAsync(string content)
{
using var workspace = TestWorkspace.CreateCSharp(content, composition: SquiggleUtilities.CompositionWithSolutionCrawler);
- return (await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace)).Item2;
+ return (await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace)).Item2;
}
private sealed class ReportOnClassWithLink : DiagnosticAnalyzer
diff --git a/src/EditorFeatures/CSharpTest/SuggestionTags/SuggestionTagProducerTests.cs b/src/EditorFeatures/CSharpTest/SuggestionTags/SuggestionTagProducerTests.cs
index 7d236a28c1f68..60a800bee0936 100644
--- a/src/EditorFeatures/CSharpTest/SuggestionTags/SuggestionTagProducerTests.cs
+++ b/src/EditorFeatures/CSharpTest/SuggestionTags/SuggestionTagProducerTests.cs
@@ -47,7 +47,7 @@ void M() {
{ LanguageNames.CSharp, ImmutableArray.Create(new CSharpUseObjectInitializerDiagnosticAnalyzer()) }
};
- var spans = (await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace, analyzerMap)).Item2;
+ var spans = (await TestDiagnosticTagProducer.GetDiagnosticsAndErrorSpans(workspace, analyzerMap)).Item2;
return (spans, workspace.Documents.Single().SelectedSpans.Single());
}
}
diff --git a/src/EditorFeatures/Core.Wpf/InlineDiagnostics/InlineDiagnosticsAdornmentManager.cs b/src/EditorFeatures/Core.Wpf/InlineDiagnostics/InlineDiagnosticsAdornmentManager.cs
index 97ce478c2c1e3..929e599b576bb 100644
--- a/src/EditorFeatures/Core.Wpf/InlineDiagnostics/InlineDiagnosticsAdornmentManager.cs
+++ b/src/EditorFeatures/Core.Wpf/InlineDiagnostics/InlineDiagnosticsAdornmentManager.cs
@@ -189,7 +189,7 @@ protected override void AddAdornmentsToAdornmentLayer_CallOnlyOnUIThread(Normali
}
// Need to get the SnapshotPoint to be able to get the IWpfTextViewLine
- var point = tagMappingSpan.Span.Start.GetPoint(TextView.TextSnapshot, PositionAffinity.Predecessor);
+ var point = tagMappingSpan.Span.End.GetPoint(TextView.TextSnapshot, PositionAffinity.Predecessor);
if (point == null)
{
continue;
diff --git a/src/EditorFeatures/Test/Diagnostics/DiagnosticsClassificationTaggerProviderTests.cs b/src/EditorFeatures/Test/Diagnostics/DiagnosticsClassificationTaggerProviderTests.cs
index 87d71ba66948d..bd36ed6d69eb6 100644
--- a/src/EditorFeatures/Test/Diagnostics/DiagnosticsClassificationTaggerProviderTests.cs
+++ b/src/EditorFeatures/Test/Diagnostics/DiagnosticsClassificationTaggerProviderTests.cs
@@ -37,7 +37,7 @@ public async Task Test_FadingSpans()
{ LanguageNames.CSharp, ImmutableArray.Create(analyzer) }
};
- using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, CSharpParseOptions.Default, composition: SquiggleUtilities.CompositionWithSolutionCrawler);
+ using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, parseOptions: CSharpParseOptions.Default, composition: SquiggleUtilities.CompositionWithSolutionCrawler);
using var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap);
var tagger = wrapper.TaggerProvider.CreateTagger(workspace.Documents.First().GetTextBuffer());
using var disposable = tagger as IDisposable;
diff --git a/src/EditorFeatures/Test/Diagnostics/DiagnosticsSquiggleTaggerProviderTests.cs b/src/EditorFeatures/Test/Diagnostics/DiagnosticsSquiggleTaggerProviderTests.cs
index f84913a7e50a7..6f7aa429bfae8 100644
--- a/src/EditorFeatures/Test/Diagnostics/DiagnosticsSquiggleTaggerProviderTests.cs
+++ b/src/EditorFeatures/Test/Diagnostics/DiagnosticsSquiggleTaggerProviderTests.cs
@@ -41,7 +41,7 @@ public async Task Test_TagSourceDiffer()
{ LanguageNames.CSharp, ImmutableArray.Create(analyzer) }
};
- using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, CSharpParseOptions.Default);
+ using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, parseOptions: CSharpParseOptions.Default);
using var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap);
var tagger = wrapper.TaggerProvider.CreateTagger(workspace.Documents.First().GetTextBuffer());
using var disposable = tagger as IDisposable;
@@ -69,7 +69,7 @@ public async Task Test_TagSourceDiffer()
[WpfFact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
public async Task MultipleTaggersAndDispose()
{
- using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A {" }, CSharpParseOptions.Default);
+ using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A {" }, parseOptions: CSharpParseOptions.Default);
using var wrapper = new DiagnosticTaggerWrapper(workspace);
// Make two taggers.
var tagger1 = wrapper.TaggerProvider.CreateTagger(workspace.Documents.First().GetTextBuffer());
@@ -89,7 +89,7 @@ public async Task MultipleTaggersAndDispose()
[WpfFact, Trait(Traits.Feature, Traits.Features.Diagnostics)]
public async Task TaggerProviderCreatedAfterInitialDiagnosticsReported()
{
- using var workspace = TestWorkspace.CreateCSharp(new string[] { "class C {" }, CSharpParseOptions.Default);
+ using var workspace = TestWorkspace.CreateCSharp(new string[] { "class C {" }, parseOptions: CSharpParseOptions.Default);
using var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap: null, createTaggerProvider: false);
// First, make sure all diagnostics have been reported.
await wrapper.WaitForTags();
@@ -119,7 +119,7 @@ public async Task TestWithMockDiagnosticService_TaggerProviderCreatedBeforeIniti
using var workspace = TestWorkspace.CreateCSharp(
new string[] { "class A { }" },
- CSharpParseOptions.Default,
+ parseOptions: CSharpParseOptions.Default,
composition: s_compositionWithMockDiagnosticService);
var listenerProvider = workspace.ExportProvider.GetExportedValue();
@@ -156,7 +156,7 @@ public async Task TestWithMockDiagnosticService_TaggerProviderCreatedAfterInitia
using var workspace = TestWorkspace.CreateCSharp(
new string[] { "class A { }" },
- CSharpParseOptions.Default,
+ parseOptions: CSharpParseOptions.Default,
composition: s_compositionWithMockDiagnosticService);
var listenerProvider = workspace.ExportProvider.GetExportedValue();
diff --git a/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs b/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs
index a089e84008738..9ad9af6c9bc95 100644
--- a/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs
+++ b/src/EditorFeatures/Test/Preview/PreviewWorkspaceTests.cs
@@ -185,7 +185,7 @@ public async Task TestPreviewDiagnosticTagger()
// enable preview diagnostics
previewWorkspace.EnableDiagnostic();
- var diagnosticsAndErrorsSpans = await SquiggleUtilities.GetDiagnosticsAndErrorSpansAsync(workspace);
+ var diagnosticsAndErrorsSpans = await SquiggleUtilities.GetDiagnosticsAndErrorSpansAsync(workspace);
const string AnalyzerCount = "Analyzer Count: ";
Assert.Equal(AnalyzerCount + 1, AnalyzerCount + diagnosticsAndErrorsSpans.Item1.Length);
diff --git a/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs b/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs
index 2bb8424b5110d..955e649141d88 100644
--- a/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs
+++ b/src/EditorFeatures/Test/SolutionCrawler/WorkCoordinatorTests.cs
@@ -335,6 +335,8 @@ internal async Task Project_AnalyzerOptions_Change(BackgroundAnalysisScope analy
Assert.Equal(expectedDocumentEvents, worker.SyntaxDocumentIds.Count);
Assert.Equal(expectedDocumentEvents, worker.DocumentIds.Count);
+
+ Assert.Equal(1, worker.NonSourceDocumentIds.Count);
}
[InlineData(BackgroundAnalysisScope.ActiveFile, false)]
@@ -701,22 +703,26 @@ internal async Task Document_AdditionalFileChange(BackgroundAnalysisScope analys
var expectedDocumentSyntaxEvents = 5;
var expectedDocumentSemanticEvents = 5;
+ var expectedNonSourceDocumentEvents = 1;
var ncfile = DocumentInfo.Create(DocumentId.CreateNewId(project.Id), "D6");
var worker = await ExecuteOperation(workspace, w => w.OnAdditionalDocumentAdded(ncfile));
Assert.Equal(expectedDocumentSyntaxEvents, worker.SyntaxDocumentIds.Count);
Assert.Equal(expectedDocumentSemanticEvents, worker.DocumentIds.Count);
+ Assert.Equal(expectedNonSourceDocumentEvents, worker.NonSourceDocumentIds.Count);
worker = await ExecuteOperation(workspace, w => w.ChangeAdditionalDocument(ncfile.Id, SourceText.From("//")));
Assert.Equal(expectedDocumentSyntaxEvents, worker.SyntaxDocumentIds.Count);
Assert.Equal(expectedDocumentSemanticEvents, worker.DocumentIds.Count);
+ Assert.Equal(expectedNonSourceDocumentEvents, worker.NonSourceDocumentIds.Count);
worker = await ExecuteOperation(workspace, w => w.OnAdditionalDocumentRemoved(ncfile.Id));
Assert.Equal(expectedDocumentSyntaxEvents, worker.SyntaxDocumentIds.Count);
Assert.Equal(expectedDocumentSemanticEvents, worker.DocumentIds.Count);
+ Assert.Empty(worker.NonSourceDocumentIds);
}
[InlineData(BackgroundAnalysisScope.ActiveFile, false)]
@@ -1619,7 +1625,7 @@ internal static class Metadata
public static readonly IncrementalAnalyzerProviderMetadata Crawler = new IncrementalAnalyzerProviderMetadata(new Dictionary { { "WorkspaceKinds", new[] { SolutionCrawlerWorkspaceKind } }, { "HighPriorityForActiveFile", false }, { "Name", "TestAnalyzer" } });
}
- private class Analyzer : IIncrementalAnalyzer
+ private class Analyzer : IIncrementalAnalyzer2
{
public static readonly Option TestOption = new Option("TestOptions", "TestOption", defaultValue: true);
@@ -1628,6 +1634,7 @@ private class Analyzer : IIncrementalAnalyzer
public readonly HashSet SyntaxDocumentIds = new HashSet();
public readonly HashSet DocumentIds = new HashSet();
+ public readonly HashSet NonSourceDocumentIds = new HashSet();
public readonly HashSet ProjectIds = new HashSet();
public readonly HashSet InvalidateDocumentIds = new HashSet();
@@ -1653,6 +1660,7 @@ public void Reset()
SyntaxDocumentIds.Clear();
DocumentIds.Clear();
+ NonSourceDocumentIds.Clear();
ProjectIds.Clear();
InvalidateDocumentIds.Clear();
@@ -1682,6 +1690,12 @@ public Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, Can
return Task.CompletedTask;
}
+ public Task AnalyzeNonSourceDocumentAsync(TextDocument textDocument, InvocationReasons reasons, CancellationToken cancellationToken)
+ {
+ this.NonSourceDocumentIds.Add(textDocument.Id);
+ return Task.CompletedTask;
+ }
+
public Task RemoveDocumentAsync(DocumentId documentId, CancellationToken cancellationToken)
{
InvalidateDocumentIds.Add(documentId);
@@ -1732,6 +1746,15 @@ public Task DocumentCloseAsync(Document document, CancellationToken cancellation
public Task DocumentResetAsync(Document document, CancellationToken cancellationToken)
=> Task.CompletedTask;
+
+ public Task NonSourceDocumentOpenAsync(TextDocument textDocument, CancellationToken cancellationToken)
+ => Task.CompletedTask;
+
+ public Task NonSourceDocumentCloseAsync(TextDocument textDocument, CancellationToken cancellationToken)
+ => Task.CompletedTask;
+
+ public Task NonSourceDocumentResetAsync(TextDocument textDocument, CancellationToken cancellationToken)
+ => Task.CompletedTask;
#endregion
}
diff --git a/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb b/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb
index 91c3d346c47ec..5a47f2cc52cb4 100644
--- a/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb
+++ b/src/EditorFeatures/Test2/Diagnostics/DiagnosticServiceTests.vb
@@ -149,8 +149,7 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Assert.Equal(workspaceDiagnosticAnalyzer.DiagDescriptor.Id, descriptors(0).Id)
' Add an existing workspace analyzer to the project, ensure no duplicate diagnostics.
- Dim duplicateProjectAnalyzersReference = hostAnalyzers.GetHostAnalyzerReferencesMap().First().Value
- project = project.WithAnalyzerReferences({duplicateProjectAnalyzersReference})
+ project = project.WithAnalyzerReferences(hostAnalyzers.HostAnalyzerReferences)
' Verify duplicate descriptors or diagnostics.
descriptorsMap = hostAnalyzers.GetDiagnosticDescriptorsPerReference(diagnosticService.AnalyzerInfoCache, project)
diff --git a/src/EditorFeatures/TestUtilities/Diagnostics/DiagnosticTaggerWrapper.cs b/src/EditorFeatures/TestUtilities/Diagnostics/DiagnosticTaggerWrapper.cs
index 9b228efd368af..bd97c0ed0d506 100644
--- a/src/EditorFeatures/TestUtilities/Diagnostics/DiagnosticTaggerWrapper.cs
+++ b/src/EditorFeatures/TestUtilities/Diagnostics/DiagnosticTaggerWrapper.cs
@@ -9,6 +9,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics;
+using Microsoft.CodeAnalysis.Editor.InlineDiagnostics;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Shared.TestHooks;
@@ -76,7 +77,8 @@ public ITaggerProvider TaggerProvider
if (typeof(TProvider) == typeof(DiagnosticsSquiggleTaggerProvider)
|| typeof(TProvider) == typeof(DiagnosticsSuggestionTaggerProvider)
- || typeof(TProvider) == typeof(DiagnosticsClassificationTaggerProvider))
+ || typeof(TProvider) == typeof(DiagnosticsClassificationTaggerProvider)
+ || typeof(TProvider) == typeof(InlineDiagnosticsTaggerProvider))
{
_taggerProvider = _workspace.ExportProvider.GetExportedValues()
.OfType()
diff --git a/src/EditorFeatures/TestUtilities/Squiggles/SquiggleUtilities.cs b/src/EditorFeatures/TestUtilities/Squiggles/SquiggleUtilities.cs
index 421c387d4c951..1df8d05f47a29 100644
--- a/src/EditorFeatures/TestUtilities/Squiggles/SquiggleUtilities.cs
+++ b/src/EditorFeatures/TestUtilities/Squiggles/SquiggleUtilities.cs
@@ -26,13 +26,17 @@ public static class SquiggleUtilities
internal static TestComposition CompositionWithSolutionCrawler = EditorTestCompositions.EditorFeatures
.RemoveParts(typeof(MockWorkspaceEventListenerProvider));
- internal static async Task<(ImmutableArray, ImmutableArray>)> GetDiagnosticsAndErrorSpansAsync(
+ internal static TestComposition WpfCompositionWithSolutionCrawler = EditorTestCompositions.EditorFeaturesWpf
+ .RemoveParts(typeof(MockWorkspaceEventListenerProvider));
+
+ internal static async Task<(ImmutableArray, ImmutableArray>)> GetDiagnosticsAndErrorSpansAsync(
TestWorkspace workspace,
IReadOnlyDictionary> analyzerMap = null)
- where TProvider : AbstractDiagnosticsAdornmentTaggerProvider
+ where TProvider : AbstractDiagnosticsAdornmentTaggerProvider
+ where TTag : class, ITag
{
- using var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap);
- var tagger = wrapper.TaggerProvider.CreateTagger(workspace.Documents.First().GetTextBuffer());
+ using var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap);
+ var tagger = wrapper.TaggerProvider.CreateTagger(workspace.Documents.First().GetTextBuffer());
using var disposable = tagger as IDisposable;
await wrapper.WaitForTags();
diff --git a/src/EditorFeatures/TestUtilities/Squiggles/TestDiagnosticTagProducer.cs b/src/EditorFeatures/TestUtilities/Squiggles/TestDiagnosticTagProducer.cs
index 18e8a2a490cdf..bcf78b9d02685 100644
--- a/src/EditorFeatures/TestUtilities/Squiggles/TestDiagnosticTagProducer.cs
+++ b/src/EditorFeatures/TestUtilities/Squiggles/TestDiagnosticTagProducer.cs
@@ -22,24 +22,25 @@
namespace Microsoft.CodeAnalysis.Editor.UnitTests.Squiggles
{
- internal sealed class TestDiagnosticTagProducer
- where TProvider : AbstractDiagnosticsAdornmentTaggerProvider
+ internal sealed class TestDiagnosticTagProducer
+ where TProvider : AbstractDiagnosticsAdornmentTaggerProvider
+ where TTag : class, ITag
{
- internal static Task<(ImmutableArray, ImmutableArray>)> GetDiagnosticsAndErrorSpans(
+ internal static Task<(ImmutableArray, ImmutableArray>)> GetDiagnosticsAndErrorSpans(
TestWorkspace workspace,
IReadOnlyDictionary> analyzerMap = null)
{
- return SquiggleUtilities.GetDiagnosticsAndErrorSpansAsync(workspace, analyzerMap);
+ return SquiggleUtilities.GetDiagnosticsAndErrorSpansAsync(workspace, analyzerMap);
}
- internal static async Task>> GetErrorsFromUpdateSource(TestWorkspace workspace, DiagnosticsUpdatedArgs updateArgs)
+ internal static async Task>> GetErrorsFromUpdateSource(TestWorkspace workspace, DiagnosticsUpdatedArgs updateArgs)
{
var globalOptions = workspace.GetService();
var source = new TestDiagnosticUpdateSource(globalOptions);
- using var wrapper = new DiagnosticTaggerWrapper(workspace, updateSource: source);
+ using var wrapper = new DiagnosticTaggerWrapper(workspace, updateSource: source);
- var tagger = wrapper.TaggerProvider.CreateTagger(workspace.Documents.First().GetTextBuffer());
+ var tagger = wrapper.TaggerProvider.CreateTagger(workspace.Documents.First().GetTextBuffer());
using var disposable = (IDisposable)tagger;
source.RaiseDiagnosticsUpdated(updateArgs);
diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs
index 4fe217f35f5d9..5da952c24d78a 100644
--- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs
+++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs
@@ -4,6 +4,7 @@
#nullable disable
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -128,6 +129,7 @@ internal static TestWorkspace Create(
CompilationOptions compilationOptions,
ParseOptions parseOptions,
string[] files,
+ string[] sourceGeneratedFiles = null,
ExportProvider exportProvider = null,
TestComposition composition = null,
string[] metadataReferences = null,
@@ -137,7 +139,7 @@ internal static TestWorkspace Create(
bool openDocuments = false,
IDocumentServiceProvider documentServiceProvider = null)
{
- var workspaceElement = CreateWorkspaceElement(language, compilationOptions, parseOptions, files, metadataReferences, extension, commonReferences);
+ var workspaceElement = CreateWorkspaceElement(language, compilationOptions, parseOptions, files, sourceGeneratedFiles, metadataReferences, extension, commonReferences);
return Create(workspaceElement, openDocuments, exportProvider, composition, workspaceKind, documentServiceProvider);
}
@@ -193,11 +195,12 @@ public static TestWorkspace CreateCSharp(
string[] metadataReferences = null,
bool openDocuments = false)
{
- return CreateCSharp(new[] { file }, parseOptions, compilationOptions, exportProvider, composition, metadataReferences, openDocuments);
+ return CreateCSharp(new[] { file }, Array.Empty(), parseOptions, compilationOptions, exportProvider, composition, metadataReferences, openDocuments);
}
public static TestWorkspace CreateCSharp(
string[] files,
+ string[] sourceGeneratedFiles = null,
ParseOptions parseOptions = null,
CompilationOptions compilationOptions = null,
ExportProvider exportProvider = null,
@@ -205,7 +208,7 @@ public static TestWorkspace CreateCSharp(
string[] metadataReferences = null,
bool openDocuments = false)
{
- return Create(LanguageNames.CSharp, compilationOptions, parseOptions, files, exportProvider, composition, metadataReferences, openDocuments: openDocuments);
+ return Create(LanguageNames.CSharp, compilationOptions, parseOptions, files, sourceGeneratedFiles, exportProvider, composition, metadataReferences, openDocuments: openDocuments);
}
public static TestWorkspace CreateCSharp2(
@@ -230,11 +233,12 @@ public static TestWorkspace CreateVisualBasic(
string[] metadataReferences = null,
bool openDocuments = false)
{
- return CreateVisualBasic(new[] { file }, parseOptions, compilationOptions, exportProvider, composition, metadataReferences, openDocuments);
+ return CreateVisualBasic(new[] { file }, Array.Empty(), parseOptions, compilationOptions, exportProvider, composition, metadataReferences, openDocuments);
}
public static TestWorkspace CreateVisualBasic(
string[] files,
+ string[] sourceGeneratedFiles = null,
ParseOptions parseOptions = null,
CompilationOptions compilationOptions = null,
ExportProvider exportProvider = null,
@@ -242,7 +246,7 @@ public static TestWorkspace CreateVisualBasic(
string[] metadataReferences = null,
bool openDocuments = false)
{
- return Create(LanguageNames.VisualBasic, compilationOptions, parseOptions, files, exportProvider, composition, metadataReferences, openDocuments: openDocuments);
+ return Create(LanguageNames.VisualBasic, compilationOptions, parseOptions, files, sourceGeneratedFiles, exportProvider, composition, metadataReferences, openDocuments: openDocuments);
}
/// Can pass in multiple file contents with individual source kind: files will be named test1.vb, test2.vbx, etc.
diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs
index 6dc371b3c01a4..bd2b15e80b91e 100644
--- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs
+++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs
@@ -14,7 +14,6 @@
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
-using System.ServiceModel.Description;
using System.Threading;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.CSharp;
@@ -29,7 +28,6 @@
using Microsoft.CodeAnalysis.UnitTests;
using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.VisualStudio.Composition;
-using Microsoft.VisualStudio.Text;
using Roslyn.Test.Utilities;
using Roslyn.Test.Utilities.TestGenerators;
using Roslyn.Utilities;
@@ -103,6 +101,7 @@ internal void InitializeDocuments(
compilationOptions,
parseOptions,
files,
+ sourceGeneratedFiles: Array.Empty(),
metadataReferences,
extension,
commonReferences);
@@ -338,8 +337,15 @@ private static TestHostProject CreateProject(
documents.Add(document);
}
+ SingleFileTestGenerator testGenerator = null;
foreach (var sourceGeneratedDocumentElement in projectElement.Elements(DocumentFromSourceGeneratorElementName))
{
+ if (testGenerator is null)
+ {
+ testGenerator = new SingleFileTestGenerator();
+ analyzers.Add(new TestGeneratorReference(testGenerator));
+ }
+
var name = GetFileName(workspace, sourceGeneratedDocumentElement, ref documentId);
var markupCode = sourceGeneratedDocumentElement.NormalizedValue();
@@ -350,7 +356,7 @@ private static TestHostProject CreateProject(
var document = new TestHostDocument(exportProvider, languageServices, code, name, documentFilePath, cursorPosition, spans, isSourceGenerated: true);
documents.Add(document);
- analyzers.Add(new TestGeneratorReference(new SingleFileTestGenerator(code, name)));
+ testGenerator.AddSource(code, name);
}
var additionalDocuments = new List();
diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs
index 0b7c578644977..6a10834bdce79 100644
--- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs
+++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs
@@ -4,12 +4,10 @@
#nullable disable
-using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.CSharp;
-using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.VisualBasic;
using Roslyn.Utilities;
@@ -22,23 +20,31 @@ internal static XElement CreateWorkspaceElement(
CompilationOptions compilationOptions = null,
ParseOptions parseOptions = null,
string[] files = null,
+ string[] sourceGeneratedFiles = null,
string[] metadataReferences = null,
string extension = null,
bool commonReferences = true)
{
var documentElements = new List();
+ var index = 0;
+ extension ??= (language == LanguageNames.CSharp) ? CSharpExtension : VisualBasicExtension;
if (files != null)
{
- var index = 0;
- extension ??= (language == LanguageNames.CSharp) ? CSharpExtension : VisualBasicExtension;
-
foreach (var file in files)
{
documentElements.Add(CreateDocumentElement(file, GetDefaultTestSourceDocumentName(index++, extension), parseOptions));
}
}
+ if (sourceGeneratedFiles != null)
+ {
+ foreach (var file in sourceGeneratedFiles)
+ {
+ documentElements.Add(CreateDocumentFromSourceGeneratorElement(file, GetDefaultTestSourceDocumentName(index++, extension), parseOptions));
+ }
+ }
+
if (metadataReferences != null)
{
foreach (var reference in metadataReferences)
@@ -171,6 +177,14 @@ protected static XElement CreateDocumentElement(string code, string filePath, Pa
code.Replace("\r\n", "\n"));
}
+ protected static XElement CreateDocumentFromSourceGeneratorElement(string code, string hintName, ParseOptions parseOptions = null)
+ {
+ return new XElement(DocumentFromSourceGeneratorElementName,
+ new XAttribute(FilePathAttributeName, hintName),
+ CreateParseOptionsElement(parseOptions),
+ code.Replace("\r\n", "\n"));
+ }
+
private static XElement CreateParseOptionsElement(ParseOptions parseOptions)
{
return parseOptions == null
diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/CrefCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/CrefCompletionProviderTests.vb
index 3c809d3e366e1..6bc616e38ba64 100644
--- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/CrefCompletionProviderTests.vb
+++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/CrefCompletionProviderTests.vb
@@ -414,7 +414,7 @@ Class C
End Sub
End Class]]>.Value.NormalizeLineEndings()
- Using workspace = TestWorkspace.Create(LanguageNames.VisualBasic, New VisualBasicCompilationOptions(OutputKind.ConsoleApplication), New VisualBasicParseOptions(), {text}, ExportProvider)
+ Using workspace = TestWorkspace.Create(LanguageNames.VisualBasic, New VisualBasicCompilationOptions(OutputKind.ConsoleApplication), New VisualBasicParseOptions(), {text}, exportProvider:=ExportProvider)
Dim called = False
Dim hostDocument = workspace.DocumentWithCursor
diff --git a/src/EditorFeatures/VisualBasicTest/Squiggles/ErrorSquiggleProducerTests.vb b/src/EditorFeatures/VisualBasicTest/Squiggles/ErrorSquiggleProducerTests.vb
index cb2703bb6094b..7987e1167cd42 100644
--- a/src/EditorFeatures/VisualBasicTest/Squiggles/ErrorSquiggleProducerTests.vb
+++ b/src/EditorFeatures/VisualBasicTest/Squiggles/ErrorSquiggleProducerTests.vb
@@ -25,7 +25,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Squiggles
Private Shared Async Function ProduceSquiggles(content As String) As Task(Of ImmutableArray(Of ITagSpan(Of IErrorTag)))
Using workspace = TestWorkspace.CreateVisualBasic(content)
- Return (Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider).GetDiagnosticsAndErrorSpans(workspace)).Item2
+ Return (Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider, IErrorTag).GetDiagnosticsAndErrorSpans(workspace)).Item2
End Using
End Function
@@ -68,7 +68,7 @@ End Class")
End Sub
End Class")
- Dim diagnosticsAndSpans = Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider).GetDiagnosticsAndErrorSpans(workspace)
+ Dim diagnosticsAndSpans = Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider, IErrorTag).GetDiagnosticsAndErrorSpans(workspace)
Dim spans = diagnosticsAndSpans.Item1.Zip(diagnosticsAndSpans.Item2, Function(diagostic, span) (diagostic, span)).OrderBy(Function(s) s.span.Span.Span.Start).ToImmutableArray()
Assert.Equal(1, spans.Count())
@@ -122,7 +122,7 @@ End Class"
options.Add(preferIntrinsicPredefinedTypeOption, preferIntrinsicPredefinedTypeOptionValue)
workspace.ApplyOptions(options)
- Dim diagnosticsAndSpans = Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider).GetDiagnosticsAndErrorSpans(workspace, analyzerMap)
+ Dim diagnosticsAndSpans = Await TestDiagnosticTagProducer(Of DiagnosticsSquiggleTaggerProvider, IErrorTag).GetDiagnosticsAndErrorSpans(workspace, analyzerMap)
Dim spans = diagnosticsAndSpans.Item1.Zip(diagnosticsAndSpans.Item2, Function(diagostic, span) (diagostic, span)).OrderBy(Function(s) s.span.Span.Span.Start).ToImmutableArray()
Assert.Equal(2, spans.Length)
diff --git a/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceCodeFixProvider.cs b/src/Features/CSharp/Portable/ConvertNamespace/ConvertNamespaceCodeFixProvider.cs
similarity index 90%
rename from src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceCodeFixProvider.cs
rename to src/Features/CSharp/Portable/ConvertNamespace/ConvertNamespaceCodeFixProvider.cs
index f0777a097d2c4..23f3c9dd11369 100644
--- a/src/Analyzers/CSharp/CodeFixes/ConvertNamespace/ConvertNamespaceCodeFixProvider.cs
+++ b/src/Features/CSharp/Portable/ConvertNamespace/ConvertNamespaceCodeFixProvider.cs
@@ -55,17 +55,18 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
return Task.CompletedTask;
}
- protected override Task FixAllAsync(
+ protected override async Task FixAllAsync(
Document document, ImmutableArray diagnostics,
SyntaxEditor editor, CancellationToken cancellationToken)
{
var diagnostic = diagnostics.First();
var namespaceDecl = (BaseNamespaceDeclarationSyntax)diagnostic.AdditionalLocations[0].FindNode(cancellationToken);
- var converted = Convert(namespaceDecl);
+ var converted = await ConvertAsync(document, namespaceDecl, cancellationToken).ConfigureAwait(false);
- editor.ReplaceNode(namespaceDecl, converted);
- return Task.CompletedTask;
+ editor.ReplaceNode(
+ editor.OriginalRoot,
+ await converted.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false));
}
private class MyCodeAction : CustomCodeActions.DocumentChangeAction
diff --git a/src/Features/CSharp/Portable/ConvertNamespace/ConvertNamespaceTransform.cs b/src/Features/CSharp/Portable/ConvertNamespace/ConvertNamespaceTransform.cs
new file mode 100644
index 0000000000000..ca9ee3864ee40
--- /dev/null
+++ b/src/Features/CSharp/Portable/ConvertNamespace/ConvertNamespaceTransform.cs
@@ -0,0 +1,240 @@
+// 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;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.IO.Pipes;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CodeStyle;
+using Microsoft.CodeAnalysis.CSharp.CodeStyle;
+using Microsoft.CodeAnalysis.CSharp.Extensions;
+using Microsoft.CodeAnalysis.CSharp.Formatting;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Formatting;
+using Microsoft.CodeAnalysis.Indentation;
+using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.PooledObjects;
+using Microsoft.CodeAnalysis.Shared.Extensions;
+using Microsoft.CodeAnalysis.Text;
+using Roslyn.Utilities;
+
+#if CODE_STYLE
+using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions;
+#endif
+
+namespace Microsoft.CodeAnalysis.CSharp.ConvertNamespace
+{
+ internal static class ConvertNamespaceTransform
+ {
+ public static async Task ConvertAsync(Document document, BaseNamespaceDeclarationSyntax baseNamespace, CancellationToken cancellationToken)
+ {
+ switch (baseNamespace)
+ {
+ case FileScopedNamespaceDeclarationSyntax fileScopedNamespace:
+ return await ConvertFileScopedNamespaceAsync(document, fileScopedNamespace, cancellationToken).ConfigureAwait(false);
+
+ case NamespaceDeclarationSyntax namespaceDeclaration:
+ var (doc, _) = await ConvertNamespaceDeclarationAsync(document, namespaceDeclaration, cancellationToken).ConfigureAwait(false);
+ return doc;
+
+ default:
+ throw ExceptionUtilities.UnexpectedValue(baseNamespace.Kind());
+ }
+ }
+
+ public static async Task<(Document document, TextSpan semicolonSpan)> ConvertNamespaceDeclarationAsync(Document document, NamespaceDeclarationSyntax namespaceDeclaration, CancellationToken cancellationToken)
+ {
+ // First, determine how much indentation we had inside the original block namespace. We'll attempt to remove
+ // that much indentation from each applicable line after we conver the block namespace to a file scoped
+ // namespace.
+ var indentation = await GetIndentationAsync(document, namespaceDeclaration, cancellationToken).ConfigureAwait(false);
+
+ // Next, actually replace the block namespace with the file scoped namespace.
+ var annotation = new SyntaxAnnotation();
+ var (updatedDocument, semicolonSpan) = await ReplaceWithFileScopedNamespaceAsync(document, namespaceDeclaration, annotation, cancellationToken).ConfigureAwait(false);
+
+ // Now, find the file scoped namespace in the updated doc and go and dedent every line if applicable.
+ if (indentation == null)
+ return (updatedDocument, semicolonSpan);
+
+ return await DedentNamespaceAsync(updatedDocument, indentation, annotation, cancellationToken).ConfigureAwait(false);
+ }
+
+ private static async Task<(Document document, TextSpan semicolonSpan)> ReplaceWithFileScopedNamespaceAsync(
+ Document document, NamespaceDeclarationSyntax namespaceDeclaration, SyntaxAnnotation annotation, CancellationToken cancellationToken)
+ {
+ var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
+ var converted = ConvertNamespaceDeclaration(namespaceDeclaration);
+ var updatedRoot = root.ReplaceNode(
+ namespaceDeclaration,
+ converted.WithAdditionalAnnotations(annotation));
+ var fileScopedNamespace = (FileScopedNamespaceDeclarationSyntax)updatedRoot.GetAnnotatedNodes(annotation).Single();
+ return (document.WithSyntaxRoot(updatedRoot), fileScopedNamespace.SemicolonToken.Span);
+ }
+
+ private static async Task GetIndentationAsync(Document document, NamespaceDeclarationSyntax namespaceDeclaration, CancellationToken cancellationToken)
+ {
+ var indentationService = document.GetRequiredLanguageService();
+ var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
+
+ var openBraceLine = sourceText.Lines.GetLineFromPosition(namespaceDeclaration.OpenBraceToken.SpanStart).LineNumber;
+ var closeBraceLine = sourceText.Lines.GetLineFromPosition(namespaceDeclaration.CloseBraceToken.SpanStart).LineNumber;
+ if (openBraceLine == closeBraceLine)
+ return null;
+
+ var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
+ var style = options.GetOption(FormattingOptions.SmartIndent, document.Project.Language);
+
+ var indentation = indentationService.GetIndentation(document, openBraceLine + 1, style, cancellationToken);
+
+ var useTabs = options.GetOption(FormattingOptions.UseTabs);
+ var tabSize = options.GetOption(FormattingOptions.TabSize);
+
+ return indentation.GetIndentationString(sourceText, useTabs, tabSize);
+ }
+
+ private static async Task<(Document document, TextSpan semicolonSpan)> DedentNamespaceAsync(
+ Document document, string indentation, SyntaxAnnotation annotation, CancellationToken cancellationToken)
+ {
+ var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
+ var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
+ var text = await root.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false);
+
+ var fileScopedNamespace = (FileScopedNamespaceDeclarationSyntax)root.GetAnnotatedNodes(annotation).Single();
+ var semicolonLine = text.Lines.GetLineFromPosition(fileScopedNamespace.SemicolonToken.SpanStart).LineNumber;
+
+ using var _ = ArrayBuilder.GetInstance(out var changes);
+ for (var line = semicolonLine + 1; line < text.Lines.Count; line++)
+ changes.AddIfNotNull(TryDedentLine(syntaxTree, text, indentation, text.Lines[line], cancellationToken));
+
+ var dedentedText = text.WithChanges(changes);
+ return (document.WithText(dedentedText), fileScopedNamespace.SemicolonToken.Span);
+ }
+
+ private static TextChange? TryDedentLine(
+ SyntaxTree tree, SourceText text, string indentation, TextLine textLine, CancellationToken cancellationToken)
+ {
+ // if this line is inside a string-literal or interpolated-text-content, then we definitely do not want to
+ // touch what is inside there. Note: this will not apply to raw-string literals, which can potentially be
+ // dedented safely depending on the position of their close terminator.
+ if (tree.IsEntirelyWithinStringLiteral(textLine.Span.Start, cancellationToken))
+ return null;
+
+ // Determine the amount of indentation this text line starts with.
+ var commonIndentation = 0;
+ while (commonIndentation < indentation.Length && commonIndentation < textLine.Span.Length)
+ {
+ if (indentation[commonIndentation] != text[textLine.Start + commonIndentation])
+ break;
+
+ commonIndentation++;
+ }
+
+ return new TextChange(new TextSpan(textLine.Start, commonIndentation), newText: "");
+ }
+
+ private static async Task ConvertFileScopedNamespaceAsync(
+ Document document, FileScopedNamespaceDeclarationSyntax fileScopedNamespace, CancellationToken cancellationToken)
+ {
+ var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
+ return document.WithSyntaxRoot(root.ReplaceNode(fileScopedNamespace, ConvertFileScopedNamespace(fileScopedNamespace)));
+ }
+
+ private static bool HasLeadingBlankLine(
+ SyntaxToken token, out SyntaxToken withoutBlankLine)
+ {
+ var leadingTrivia = token.LeadingTrivia;
+
+ if (leadingTrivia.Count >= 1 && leadingTrivia[0].Kind() == SyntaxKind.EndOfLineTrivia)
+ {
+ withoutBlankLine = token.WithLeadingTrivia(leadingTrivia.RemoveAt(0));
+ return true;
+ }
+
+ if (leadingTrivia.Count >= 2 && leadingTrivia[0].IsKind(SyntaxKind.WhitespaceTrivia) && leadingTrivia[1].IsKind(SyntaxKind.EndOfLineTrivia))
+ {
+ withoutBlankLine = token.WithLeadingTrivia(leadingTrivia.Skip(2));
+ return true;
+ }
+
+ withoutBlankLine = default;
+ return false;
+ }
+
+ private static FileScopedNamespaceDeclarationSyntax ConvertNamespaceDeclaration(NamespaceDeclarationSyntax namespaceDeclaration)
+ {
+ var semiColon = SyntaxFactory.Token(SyntaxKind.SemicolonToken).WithoutTrivia();
+
+ // Move trivia after the original name token to now be after the new semicolon token.
+ var fileScopedNamespace = SyntaxFactory.FileScopedNamespaceDeclaration(
+ namespaceDeclaration.AttributeLists,
+ namespaceDeclaration.Modifiers,
+ namespaceDeclaration.NamespaceKeyword,
+ namespaceDeclaration.Name.WithoutTrailingTrivia(),
+ semiColon.WithTrailingTrivia(namespaceDeclaration.Name.GetTrailingTrivia()),
+ namespaceDeclaration.Externs,
+ namespaceDeclaration.Usings,
+ namespaceDeclaration.Members);
+
+ var firstBodyToken = fileScopedNamespace.SemicolonToken.GetNextToken();
+
+ // If the open-brace token has any special trivia, then move them to before the first member in the namespace.
+ if (namespaceDeclaration.OpenBraceToken.LeadingTrivia.Any(t => t.IsSingleOrMultiLineComment() || t.IsDirective) ||
+ namespaceDeclaration.OpenBraceToken.TrailingTrivia.Any(t => t.IsSingleOrMultiLineComment() || t.IsDirective))
+ {
+ fileScopedNamespace = fileScopedNamespace.ReplaceToken(
+ firstBodyToken,
+ firstBodyToken.WithPrependedLeadingTrivia(namespaceDeclaration.OpenBraceToken.GetAllTrivia()));
+ firstBodyToken = fileScopedNamespace.SemicolonToken.GetNextNonZeroWidthTokenOrEndOfFile();
+ }
+
+ // Otherwise, ensure there's a blank line between the namespace line and the first body member. Don't bother
+ // with this though if we already separated things by moving a pp directive (like a #else) from the open brace
+ // to the first token.
+ if (firstBodyToken.Kind() != SyntaxKind.EndOfFileToken &&
+ !HasLeadingBlankLine(firstBodyToken, out _) &&
+ !namespaceDeclaration.OpenBraceToken.LeadingTrivia.Any(t => t.IsDirective))
+ {
+ fileScopedNamespace = fileScopedNamespace.ReplaceToken(
+ firstBodyToken,
+ firstBodyToken.WithPrependedLeadingTrivia(SyntaxFactory.CarriageReturnLineFeed));
+ }
+
+ // Copy leading trivia from the close brace to the end of the file scoped namespace (which means after all of the members)
+ fileScopedNamespace = fileScopedNamespace.WithAppendedTrailingTrivia(namespaceDeclaration.CloseBraceToken.LeadingTrivia);
+
+ return fileScopedNamespace;
+ }
+
+ private static NamespaceDeclarationSyntax ConvertFileScopedNamespace(FileScopedNamespaceDeclarationSyntax fileScopedNamespace)
+ {
+ var namespaceDeclaration = SyntaxFactory.NamespaceDeclaration(
+ fileScopedNamespace.AttributeLists,
+ fileScopedNamespace.Modifiers,
+ fileScopedNamespace.NamespaceKeyword,
+ fileScopedNamespace.Name,
+ SyntaxFactory.Token(SyntaxKind.OpenBraceToken).WithTrailingTrivia(fileScopedNamespace.SemicolonToken.TrailingTrivia),
+ fileScopedNamespace.Externs,
+ fileScopedNamespace.Usings,
+ fileScopedNamespace.Members,
+ SyntaxFactory.Token(SyntaxKind.CloseBraceToken),
+ semicolonToken: default).WithAdditionalAnnotations(Formatter.Annotation);
+
+ // Ensure there is no errant blank line between the open curly and the first body element.
+ var firstBodyToken = namespaceDeclaration.OpenBraceToken.GetNextToken();
+ if (firstBodyToken != namespaceDeclaration.CloseBraceToken &&
+ firstBodyToken.Kind() != SyntaxKind.EndOfFileToken &&
+ HasLeadingBlankLine(firstBodyToken, out var firstBodyTokenWithoutBlankLine))
+ {
+ namespaceDeclaration = namespaceDeclaration.ReplaceToken(firstBodyToken, firstBodyTokenWithoutBlankLine);
+ }
+
+ return namespaceDeclaration;
+ }
+ }
+}
diff --git a/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs b/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs
index 8350fb94e6d1f..d2d8d33740221 100644
--- a/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs
+++ b/src/Features/CSharp/Portable/Formatting/CSharpNamespaceDeclarationNewDocumentFormattingProvider.cs
@@ -32,8 +32,11 @@ public async Task FormatNewDocumentAsync(Document document, Document?
var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var root = (CompilationUnitSyntax)await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
- var namespaces = GetNamespacesToReplace(document, root, optionSet);
- return await document.ReplaceNodesAsync(namespaces, (oldNode, newNode) => ConvertNamespaceTransform.Convert((BaseNamespaceDeclarationSyntax)newNode), cancellationToken).ConfigureAwait(false);
+ var namespaces = GetNamespacesToReplace(document, root, optionSet).ToList();
+ if (namespaces.Count != 1)
+ return document;
+
+ return await ConvertNamespaceTransform.ConvertAsync(document, namespaces[0], cancellationToken).ConfigureAwait(false);
}
private static IEnumerable GetNamespacesToReplace(Document document, CompilationUnitSyntax root, DocumentOptionSet optionSet)
diff --git a/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs b/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs
index 0c6c0f5ce1817..b27637de58c64 100644
--- a/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs
+++ b/src/Features/Core/Portable/ChangeSignature/AbstractChangeSignatureService.cs
@@ -950,7 +950,6 @@ protected ImmutableArray GetPermutedDocCommentTrivia(Document docu
{
var updatedLeadingTrivia = ImmutableArray.CreateBuilder();
var index = 0;
- SyntaxTrivia lastWhiteSpaceTrivia = default;
var syntaxFacts = document.GetRequiredLanguageService();
@@ -958,11 +957,6 @@ protected ImmutableArray GetPermutedDocCommentTrivia(Document docu
{
if (!trivia.HasStructure)
{
- if (syntaxFacts.IsWhitespaceTrivia(trivia))
- {
- lastWhiteSpaceTrivia = trivia;
- }
-
updatedLeadingTrivia.Add(trivia);
continue;
}
@@ -1015,7 +1009,6 @@ protected ImmutableArray GetPermutedDocCommentTrivia(Document docu
var extraDocComments = Generator.DocumentationCommentTrivia(
extraNodeList,
node.GetTrailingTrivia(),
- lastWhiteSpaceTrivia,
document.Project.Solution.Options.GetOption(FormattingOptions.NewLine, document.Project.Language));
var newTrivia = Generator.Trivia(extraDocComments);
diff --git a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.HostStates.cs b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.HostStates.cs
index af1fe1edd92ab..fe8be59046e32 100644
--- a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.HostStates.cs
+++ b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.HostStates.cs
@@ -16,10 +16,10 @@ private partial class StateManager
{
public IEnumerable GetAllHostStateSets()
{
- var analyzerReferencesMap = _workspace.CurrentSolution.State.Analyzers.GetHostAnalyzerReferencesMap();
+ var analyzerReferences = _workspace.CurrentSolution.State.Analyzers.HostAnalyzerReferences;
foreach (var (key, value) in _hostAnalyzerStateMap)
{
- if (key.AnalyzerReferences == analyzerReferencesMap)
+ if (key.AnalyzerReferences == analyzerReferences)
{
foreach (var stateSet in value.OrderedStateSets)
{
@@ -31,7 +31,7 @@ public IEnumerable GetAllHostStateSets()
private HostAnalyzerStateSets GetOrCreateHostStateSets(Project project, ProjectAnalyzerStateSets projectStateSets)
{
- var key = new HostAnalyzerStateSetKey(project.Language, project.Solution.State.Analyzers.GetHostAnalyzerReferencesMap());
+ var key = new HostAnalyzerStateSetKey(project.Language, project.Solution.State.Analyzers.HostAnalyzerReferences);
var hostStateSets = ImmutableInterlocked.GetOrAdd(ref _hostAnalyzerStateMap, key, CreateLanguageSpecificAnalyzerMap, project.Solution.State.Analyzers);
return hostStateSets.WithExcludedAnalyzers(projectStateSets.SkippedAnalyzersInfo.SkippedAnalyzers);
diff --git a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.cs b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.cs
index 1cd6f957c6a29..8cd11d6a45737 100644
--- a/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.cs
+++ b/src/Features/Core/Portable/Diagnostics/EngineV2/DiagnosticIncrementalAnalyzer.StateManager.cs
@@ -314,14 +314,14 @@ private void VerifyProjectDiagnosticStates(IEnumerable stateSets)
private readonly struct HostAnalyzerStateSetKey : IEquatable
{
- public HostAnalyzerStateSetKey(string language, ImmutableDictionary