diff --git a/.github/workflows/main-merge.yml b/.github/workflows/main-merge.yml
index 15711d10c9e5a..f25597ce1c37c 100644
--- a/.github/workflows/main-merge.yml
+++ b/.github/workflows/main-merge.yml
@@ -2,9 +2,9 @@
name: Inter-branch merge
on:
- # schedule:
- # # Create a merge every 3 hours (works only for merges from `main`, others would need a `push` trigger).
- # - cron: '0 */3 * * *'
+ schedule:
+ # Create a merge every 3 hours (works only for merges from `main`, others would need a `push` trigger).
+ - cron: '0 */3 * * *'
workflow_dispatch:
inputs:
configuration_file_branch:
@@ -21,5 +21,6 @@ jobs:
if: github.repository == 'dotnet/roslyn'
uses: dotnet/arcade/.github/workflows/inter-branch-merge-base.yml@main
with:
- configuration_file_path: 'eng/config/branch-merge.jsonc'
+ configuration_file_path: 'eng/config/main-to-main-vs-deps-branch-merge.jsonc'
configuration_file_branch: ${{ inputs.configuration_file_branch || 'main' }}
+
diff --git a/Roslyn.sln b/Roslyn.sln
index 6fca77405900e..980009f1a1d57 100644
--- a/Roslyn.sln
+++ b/Roslyn.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.0.31319.15
+# Visual Studio Version 18
+VisualStudioVersion = 18.0.10623.112 main
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoslynDeployment", "src\Deployment\RoslynDeployment.csproj", "{600AF682-E097-407B-AD85-EE3CED37E680}"
EndProject
@@ -2207,8 +2207,11 @@ Global
src\Workspaces\SharedUtilitiesAndExtensions\Workspace\VisualBasic\VisualBasicWorkspaceExtensions.projitems*{57ca988d-f010-4bf2-9a2e-07d6dcd2ff2c}*SharedItemsImports = 5
src\Analyzers\CSharp\Tests\CSharpAnalyzers.UnitTests.projitems*{58969243-7f59-4236-93d0-c93b81f569b3}*SharedItemsImports = 13
src\Dependencies\Collections\Microsoft.CodeAnalysis.Collections.projitems*{5f8d2414-064a-4b3a-9b42-8e2a04246be5}*SharedItemsImports = 5
+ src\Dependencies\Contracts\Microsoft.CodeAnalysis.Contracts.projitems*{5f8d2414-064a-4b3a-9b42-8e2a04246be5}*SharedItemsImports = 5
src\Dependencies\PooledObjects\Microsoft.CodeAnalysis.PooledObjects.projitems*{5f8d2414-064a-4b3a-9b42-8e2a04246be5}*SharedItemsImports = 5
+ src\Dependencies\Threading\Microsoft.CodeAnalysis.Threading.projitems*{5f8d2414-064a-4b3a-9b42-8e2a04246be5}*SharedItemsImports = 5
src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Core\CompilerExtensions.projitems*{5f8d2414-064a-4b3a-9b42-8e2a04246be5}*SharedItemsImports = 5
+ src\Workspaces\SharedUtilitiesAndExtensions\Compiler\Extensions\Microsoft.CodeAnalysis.Extensions.projitems*{5f8d2414-064a-4b3a-9b42-8e2a04246be5}*SharedItemsImports = 5
src\Workspaces\SharedUtilitiesAndExtensions\Workspace\Core\WorkspaceExtensions.projitems*{5f8d2414-064a-4b3a-9b42-8e2a04246be5}*SharedItemsImports = 5
src\Analyzers\Core\CodeFixes\CodeFixes.projitems*{5ff1e493-69cc-4d0b-83f2-039f469a04e1}*SharedItemsImports = 5
src\Workspaces\SharedUtilitiesAndExtensions\Workspace\Core\WorkspaceExtensions.projitems*{5ff1e493-69cc-4d0b-83f2-039f469a04e1}*SharedItemsImports = 5
diff --git a/eng/Directory.Packages.props b/eng/Directory.Packages.props
index ce4aac1b06c33..75ead14245059 100644
--- a/eng/Directory.Packages.props
+++ b/eng/Directory.Packages.props
@@ -66,9 +66,6 @@
-
-
-
@@ -99,14 +96,12 @@
-
-
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 14028e430ed09..b6f602b74c189 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/eng/build.ps1 b/eng/build.ps1
index b8d9f22be29fa..ea4c6ffd7c578 100644
--- a/eng/build.ps1
+++ b/eng/build.ps1
@@ -440,7 +440,7 @@ function TestUsingRunTests() {
}
} elseif ($testVsi) {
- $args += " --timeout 110"
+ $args += " --timeout 220"
$args += " --runtime both"
$args += " --sequential"
$args += " --include '\.IntegrationTests'"
diff --git a/eng/config/PublishData.json b/eng/config/PublishData.json
index 1d494eeb3f501..e2ad4fac15ab1 100644
--- a/eng/config/PublishData.json
+++ b/eng/config/PublishData.json
@@ -176,6 +176,15 @@
"insertionCreateDraftPR": false
},
"main": {
+ "nugetKind": [
+ "Shipping",
+ "NonShipping"
+ ],
+ "vsBranch": "main",
+ "insertionCreateDraftPR": true,
+ "insertionTitlePrefix": "[Validation]"
+ },
+ "main-vs-deps": {
"nugetKind": [
"Shipping",
"NonShipping"
diff --git a/eng/config/branch-merge.jsonc b/eng/config/branch-merge.jsonc
deleted file mode 100644
index 2c2a486a106ea..0000000000000
--- a/eng/config/branch-merge.jsonc
+++ /dev/null
@@ -1,9 +0,0 @@
-// Used by .github/workflows/main-merge.yml
-{
- "merge-flow-configurations": {
- // "main": {
- // "MergeToBranch": "release/dev17.15",
- // "ExtraSwitches": "-QuietComments"
- // }
- }
-}
diff --git a/eng/config/globalconfigs/Common.globalconfig b/eng/config/globalconfigs/Common.globalconfig
index f073601eac363..acb1c8e4880ff 100644
--- a/eng/config/globalconfigs/Common.globalconfig
+++ b/eng/config/globalconfigs/Common.globalconfig
@@ -127,9 +127,6 @@ dotnet_diagnostic.VSTHRD010.severity = none
# VSTHRD110: Observe result of async calls
dotnet_diagnostic.VSTHRD110.severity = none
-# Workaround for old Microsoft.VisualStudio.Progression.* packages: https://github.com/dotnet/roslyn/issues/71404
-dotnet_diagnostic.VSIXCompatibility1001.severity = none
-
dotnet_diagnostic.HAA0101.severity = none
dotnet_diagnostic.HAA0102.severity = none
dotnet_diagnostic.HAA0201.severity = none
diff --git a/eng/config/main-to-main-vs-deps-branch-merge.jsonc b/eng/config/main-to-main-vs-deps-branch-merge.jsonc
new file mode 100644
index 0000000000000..cd979074b54a4
--- /dev/null
+++ b/eng/config/main-to-main-vs-deps-branch-merge.jsonc
@@ -0,0 +1,10 @@
+// Used by .github/workflows/main-merge.yml
+{
+ "merge-flow-configurations": {
+ // Merge any main changes to main-vs-deps.
+ "main": {
+ "MergeToBranch": "main-vs-deps",
+ "ExtraSwitches": "-QuietComments"
+ }
+ }
+}
diff --git a/eng/targets/Settings.props b/eng/targets/Settings.props
index d2f750758827c..d6ed357dadc0c 100644
--- a/eng/targets/Settings.props
+++ b/eng/targets/Settings.props
@@ -11,9 +11,6 @@
RoslynDev
-
- $(NoWarn);VSIXCompatibility1001
-
$(NoWarn);NU1507
@@ -120,6 +117,7 @@
002400000480000094000000060200000024000052534131000400000100010009f3c8fcb7cb2592cc6e6d3646d4d9a2bda9e7a243d357bc17a5a06f50ed0dae74a343cd9538fe45bbc90a3f7cbecb23558205e3b246b69f7f7730e520460d560da1c68cda9e2256e3b801629e2dc1fd588b1681aaf4f2c98abcfc50086ecbcd55f76f7dbaf018e708527d8ae3a2714b3ec9b62bd9aaf56cf55b3ffc9eee31aa
00240000048000009400000006020000002400005253413100040000010001005984d9e99e5722bb74ddbb59972bff1a2fd9e0ccb2d50e09ef85e39ec4a4e4bf2de896997de1af164be0558cdd5a50a283b9353fc4e5ccc1c87363e6e7d87af7bec8ca40281596fc8f5b5aad9904230f6f3892f8dde382cee7ba9854004d86ce93834a86b42ebdd0faf86d9fa6d935e05aed68cb4d828cea77df028739aaa9dc
002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293
+ $(MicrosoftSharedPublicKey)
+
""", mSkeleton.GetDocumentationCommentXml());
var mImplementation = e.GetMember("M");
AssertEx.Equal("""
-
+
""", mImplementation.GetDocumentationCommentXml());
var p = extension.GetMember("P");
AssertEx.Equal("""
-
+
""", p.GetDocumentationCommentXml());
var pGetImplementation = e.GetMember("get_P");
AssertEx.Equal("""
-
+
""", pGetImplementation.GetDocumentationCommentXml());
@@ -40150,8 +41370,6 @@ static class E
}
}
""";
- // Tracked by https://github.com/dotnet/roslyn/issues/76130 : consider warning (WRN_MissingParamTag) about missing documentation for extension parameter
- // since one of the instance members has a tag
var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
comp.VerifyEmitDiagnostics(
// (8,26): warning CS1572: XML comment has a param tag for 'o', but there is no parameter by that name
@@ -40178,8 +41396,6 @@ static class E
}
}
""";
- // Tracked by https://github.com/dotnet/roslyn/issues/76130 : consider warning (WRN_MissingParamTag) about missing documentation for member parameter
- // since the extension parameter is documented
var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
comp.VerifyEmitDiagnostics();
}
@@ -40306,8 +41522,6 @@ static class E
}
}
""";
- // Tracked by https://github.com/dotnet/roslyn/issues/76130 : consider warning (WRN_MissingTypeParamTag) about missing documentation for extension type parameter
- // since one of the members has a tag
var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
comp.VerifyEmitDiagnostics(
// (8,30): warning CS1711: XML comment has a typeparam tag for 'T', but there is no type parameter by that name
@@ -40334,8 +41548,6 @@ static class E
}
}
""";
- // Tracked by https://github.com/dotnet/roslyn/issues/76130 : consider warning (WRN_MissingTypeParamTag) about missing documentation for member type parameter
- // since the extension type parameter is documented
var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
comp.VerifyEmitDiagnostics();
}
diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs
index 712b431e107a8..3026f4bc56e36 100644
--- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs
+++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs
@@ -4,9 +4,12 @@
#nullable disable
using System;
+using System.Globalization;
using System.Linq;
+using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
+using Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
@@ -219,6 +222,78 @@ static class E
comp.VerifyEmitDiagnostics();
}
+ [Fact]
+ public void PositionalPattern_03()
+ {
+ // implicit span conversion
+ var src = """
+int[] i = new int[] { 1, 2 };
+if (i is var (x, y))
+ System.Console.Write((x, y));
+
+static class E
+{
+ extension(System.Span s)
+ {
+ public void Deconstruct(out int i, out int j) { i = 42; j = 43; }
+ }
+}
+""";
+ var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
+ CompileAndVerify(comp, expectedOutput: ExpectedOutput("(42, 43)"), verify: Verification.Skipped).VerifyDiagnostics();
+ }
+
+ [Fact]
+ public void PositionalPattern_04()
+ {
+ // implicit tuple conversion
+ var src = """
+var t = (42, "ran");
+if (t is var (x, y))
+ System.Console.Write((x, y));
+
+static class E
+{
+ extension((object, object) t)
+ {
+ public void Deconstruct(out int i, out int j) { i = 42; j = 43; }
+ }
+}
+""";
+ var comp = CreateCompilation(src);
+ CompileAndVerify(comp, expectedOutput: ExpectedOutput("(42, ran)")).VerifyDiagnostics();
+ }
+
+ [Fact]
+ public void PositionalPattern_05()
+ {
+ // We check conversion during initial binding
+ var src = """
+int[] i = [];
+_ = i is var (x, y);
+
+static class E
+{
+ extension(System.ReadOnlySpan r)
+ {
+ public void Deconstruct(out int i, out int j) => throw null;
+ }
+}
+
+namespace System
+{
+ public ref struct ReadOnlySpan
+ {
+ }
+}
+""";
+ var comp = CreateCompilation(src);
+ comp.VerifyEmitDiagnostics(
+ // (2,14): error CS0656: Missing compiler required member 'ReadOnlySpan.op_Implicit'
+ // _ = i is var (x, y);
+ Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "(x, y)").WithArguments("System.ReadOnlySpan", "op_Implicit").WithLocation(2, 14));
+ }
+
[Fact]
public void InvocationOnNull()
{
@@ -314,7 +389,7 @@ public static class E
try
{
var comp = CreateCompilation([src, OverloadResolutionPriorityAttributeDefinition]);
- // Tracked by https://github.com/dotnet/roslyn/issues/76130 : assertion in NullableWalker
+ // Tracked by https://github.com/dotnet/roslyn/issues/78828 : assertion in NullableWalker
CompileAndVerify(comp, expectedOutput: "42").VerifyDiagnostics();
}
catch (InvalidOperationException)
@@ -2176,7 +2251,7 @@ class C
public object? P3 => throw null!;
}
""";
- // Tracked by https://github.com/dotnet/roslyn/issues/76130 : incorrect nullability analysis for property pattern with extension property (unexpected warning)
+ // Tracked by https://github.com/dotnet/roslyn/issues/78828 : incorrect nullability analysis for property pattern with extension property (unexpected warning)
var comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
comp.VerifyEmitDiagnostics(
// (4,5): warning CS8602: Dereference of a possibly null reference.
@@ -2285,5 +2360,3190 @@ public static class E
// [System.Diagnostics.CodeAnalysis.UnscopedRef]
Diagnostic(ErrorCode.ERR_UnscopedRefAttributeUnsupportedMemberTarget, "System.Diagnostics.CodeAnalysis.UnscopedRef").WithLocation(8, 10));
}
+
+ [Fact]
+ public void Ambiguity_01()
+ {
+ var src = """
+var x = object.M; // 1
+x();
+
+System.Action y = object.M; // 2
+
+static class E1
+{
+ extension(object)
+ {
+ public static void M() { }
+ }
+}
+
+static class E2
+{
+ extension(object)
+ {
+ public static int M => 0;
+ }
+}
+""";
+
+ var comp = CreateCompilation(src);
+ // Tracked by https://github.com/dotnet/roslyn/issues/76130 : the diagnostic should describe what went wrong
+ comp.VerifyEmitDiagnostics(
+ // (1,9): error CS9286: 'object' does not contain a definition for 'M' and no accessible extension member 'M' for receiver of type 'object' could be found (are you missing a using directive or an assembly reference?)
+ // var x = object.M; // 1
+ Diagnostic(ErrorCode.ERR_ExtensionResolutionFailed, "object.M").WithArguments("object", "M").WithLocation(1, 9),
+ // (4,19): error CS9286: 'object' does not contain a definition for 'M' and no accessible extension member 'M' for receiver of type 'object' could be found (are you missing a using directive or an assembly reference?)
+ // System.Action y = object.M; // 2
+ Diagnostic(ErrorCode.ERR_ExtensionResolutionFailed, "object.M").WithArguments("object", "M").WithLocation(4, 19));
+
+ src = """
+var x = I.M; // binds to I1.M (method)
+x();
+
+System.Action y = I.M; // binds to I1.M (method)
+y();
+
+interface I1 { static void M() { System.Console.Write("I1.M() "); } }
+interface I2 { static int M => 0; }
+interface I3 { static int M = 0; }
+interface I : I1, I2, I3 { }
+""";
+
+ comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
+ CompileAndVerify(comp, expectedOutput: ExpectedOutput("I1.M() I1.M()"), verify: Verification.Skipped).VerifyDiagnostics();
+
+ src = """
+I i = new C();
+var x = i.M; // binds to I1.M (method)
+x();
+
+System.Action y = i.M; // binds to I1.M (method)
+y();
+
+interface I1 { void M() { System.Console.Write("I1.M() "); } }
+interface I2 { int M => 0; }
+interface I : I1, I2 { }
+
+class C : I { }
+""";
+
+ comp = CreateCompilation(src, targetFramework: TargetFramework.Net90);
+ CompileAndVerify(comp, expectedOutput: ExpectedOutput("I1.M() I1.M()"), verify: Verification.Skipped).VerifyDiagnostics();
+ }
+
+ [Fact]
+ public void CS1943ERR_QueryTypeInferenceFailedSelectMany()
+ {
+ // ReportQueryInferenceFailedSelectMany
+ var comp = CreateCompilation("""
+using System;
+using System.Collections.Generic;
+
+class Test
+{
+ class TestClass
+ { }
+
+ static void Main()
+ {
+ int[] nums = { 0, 1, 2, 3, 4, 5 };
+ TestClass tc = new TestClass();
+
+ var x = from n in nums
+ from s in tc // CS1943
+ select n + s;
+ }
+}
+
+static class E
+{
+ extension(IEnumerable source)
+ {
+ public IEnumerable SelectMany(
+ Func> collectionSelector,
+ Func resultSelector)
+ => throw null;
+ }
+}
+""");
+
+ comp.VerifyEmitDiagnostics(
+ // (13,27): error CS1943: An expression of type 'Test.TestClass' is not allowed in a subsequent from clause in a query expression with source type 'int[]'. Type inference failed in the call to 'SelectMany'.
+ // tc
+ Diagnostic(ErrorCode.ERR_QueryTypeInferenceFailedSelectMany, "tc").WithArguments("Test.TestClass", "int[]", "SelectMany"));
+ }
+
+ [Fact]
+ public void Foreach_Extension_01()
+ {
+ var src = """
+class Program
+{
+ public static void M(Buffer4 x)
+ {
+ foreach(var s in x)
+ {
+ }
+ }
+}
+
+namespace System
+{
+ public readonly ref struct Span
+ {
+ }
+}
+
+static class Ext
+{
+ extension(System.Span f)
+ {
+ public Enumerator GetEnumerator() => default;
+ }
+
+ public ref struct Enumerator
+ {
+ public ref T Current => throw null;
+
+ public bool MoveNext() => false;
+ }
+}
+
+[System.Runtime.CompilerServices.InlineArray(4)]
+public struct Buffer4
+{
+ private T _element0;
+}
+""";
+ var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseDll);
+ comp.VerifyEmitDiagnostics(
+ // (5,26): error CS9189: foreach statement on an inline array of type 'Buffer4' is not supported
+ // foreach(var s in x)
+ Diagnostic(ErrorCode.ERR_InlineArrayForEachNotSupported, "x").WithArguments("Buffer4").WithLocation(5, 26),
+ // (20,25): warning CS0436: The type 'Span' in '' conflicts with the imported type 'Span' in 'System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Using the type defined in ''.
+ // extension(System.Span f)
+ Diagnostic(ErrorCode.WRN_SameFullNameThisAggAgg, "Span").WithArguments("", "System.Span", "System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Span").WithLocation(20, 25)
+ );
+ }
+
+ [Fact]
+ public void DelegateCreation_01()
+ {
+ var src = """
+string s;
+_ = new System.Action(s.M);
+
+string s2;
+_ = new System.Action(s2.M2);
+
+_ = new System.Action(string.M2);
+
+static class E
+{
+ extension(string s)
+ {
+ public void M() { }
+ public static void M2() { }
+ }
+}
+""";
+ var comp = CreateCompilation(src);
+ comp.VerifyEmitDiagnostics(
+ // (2,23): error CS0165: Use of unassigned local variable 's'
+ // _ = new System.Action(s.M);
+ Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(2, 23),
+ // (4,8): warning CS0168: The variable 's2' is declared but never used
+ // string s2;
+ Diagnostic(ErrorCode.WRN_UnreferencedVar, "s2").WithArguments("s2").WithLocation(4, 8),
+ // (5,23): error CS0176: Member 'E.extension(string).M2()' cannot be accessed with an instance reference; qualify it with a type name instead
+ // _ = new System.Action(s2.M2);
+ Diagnostic(ErrorCode.ERR_ObjectProhibited, "s2.M2").WithArguments("E.extension(string).M2()").WithLocation(5, 23));
+ }
+
+ [Fact]
+ public void AsyncMethodBuilder_01()
+ {
+ var src = """
+using System;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+Console.Write(await object.M());
+
+static class C
+{
+ extension(object)
+ {
+ [AsyncMethodBuilder(typeof(MyTaskMethodBuilder<>))]
+ public static async MyTask M() { await Task.Yield(); Console.Write("M "); return 3; }
+ }
+}
+
+public class MyTask
+{
+ private Action _continuation;
+ private bool _isCompleted;
+ internal T _result;
+
+ public Awaiter GetAwaiter() => new Awaiter(this);
+ public T Result => _result;
+
+ internal void Complete(T result)
+ {
+ _result = result;
+ _isCompleted = true;
+ _continuation?.Invoke();
+ }
+
+ public readonly struct Awaiter : ICriticalNotifyCompletion
+ {
+ private readonly MyTask _task;
+ internal Awaiter(MyTask task) => _task = task;
+
+ public bool IsCompleted => _task._isCompleted;
+ public T GetResult() => _task._result;
+
+ public void OnCompleted(Action cont) => HandleCompletion(cont);
+ public void UnsafeOnCompleted(Action cont) => HandleCompletion(cont);
+
+ private void HandleCompletion(Action cont)
+ {
+ if (_task._isCompleted) { cont(); return; }
+
+ _task._continuation = cont;
+ }
+ }
+}
+
+public struct MyTaskMethodBuilder
+{
+ private readonly MyTask _task;
+ private MyTaskMethodBuilder(MyTask task) => _task = task;
+
+ public static MyTaskMethodBuilder Create() => new MyTaskMethodBuilder(new MyTask());
+ public MyTask Task => _task;
+ public void Start(ref TSM sm) where TSM : IAsyncStateMachine => sm.MoveNext();
+
+ public void SetStateMachine(IAsyncStateMachine _) { }
+ public void SetResult(T result) => _task.Complete(result);
+ public void SetException(Exception e) => throw null;
+
+ public void AwaitOnCompleted(ref TA a, ref TSM sm) where TA : INotifyCompletion where TSM: IAsyncStateMachine => a.OnCompleted(sm.MoveNext);
+ public void AwaitUnsafeOnCompleted(ref TA a, ref TSM sm) where TA : ICriticalNotifyCompletion where TSM: IAsyncStateMachine => a.UnsafeOnCompleted(sm.MoveNext);
+}
+
+namespace System.Runtime.CompilerServices { class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type t) { } } }
+""";
+ var comp = CreateCompilation(src);
+ CompileAndVerify(comp, expectedOutput: "M 3").VerifyDiagnostics();
+ }
+
+ [Fact]
+ public void PEMethodSymbol_GetUseSiteInfo()
+ {
+ // missing implementation method for M
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0570: 'E.extension(int).M()' is not supported by the language
+ // int.M();
+ Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("E.extension(int).M()").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void Retargeting_01()
+ {
+ var libSrc = """
+public static class E
+{
+ extension(object)
+ {
+ public static void M() { }
+ }
+}
+
+namespace System.Runtime.CompilerServices
+{
+ public class ExtensionAttribute : System.Attribute {}
+}
+""";
+ var libComp = CreateCompilation(libSrc, targetFramework: TargetFramework.Mscorlib40);
+
+ var src = """
+object.M();
+""";
+ var comp = CreateCompilation(src, targetFramework: TargetFramework.Mscorlib46, references: [libComp.ToMetadataReference()]);
+ comp.VerifyEmitDiagnostics();
+
+ var extension = comp.GlobalNamespace.GetTypeMember("E").GetTypeMembers().Single();
+ Assert.IsType(extension);
+ AssertExtensionDeclaration(extension.GetPublicSymbol());
+ }
+
+ [Theory]
+ [InlineData("public")]
+ [InlineData("assembly")]
+ [InlineData("family")]
+ public void PENamedTypeSymbol_01(string accessibility)
+ {
+ // Accessibility of extension marker is not private
+ var ilSrc = $$"""
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method {{accessibility}} hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+
+ var tree = comp.SyntaxTrees[0];
+ var model = comp.GetSemanticModel(tree);
+ var invocation = GetSyntax(tree, "int.M()");
+ Assert.Null(model.GetSymbolInfo(invocation).Symbol);
+ Assert.Equal([], model.GetSymbolInfo(invocation).CandidateSymbols.ToTestDisplayStrings());
+ Assert.Equal([], model.GetMemberGroup(invocation).ToTestDisplayStrings());
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_02()
+ {
+ // Accessibility of extension marker is not private, instance extension method
+ var ilSrc = $$"""
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method public hidebysig specialname static void '$' ( int32 i ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig instance void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M ( int32 i ) cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+42.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,4): error CS1061: 'int' does not contain a definition for 'M' and no accessible extension method 'M' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
+ // 42.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M").WithArguments("int", "M").WithLocation(1, 4));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_03()
+ {
+ // Extension marker method is generic
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_04()
+ {
+ // Extension marker method is not static
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_05()
+ {
+ // Extension marker doesn't return void
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static int32 '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_06()
+ {
+ // Extension marker lacks its parameter
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' () cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_07()
+ {
+ // Extension marker has an extra parameter
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '', string s ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_08()
+ {
+ // No containing type
+ var ilSrc = """
+.class public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+{
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+
+ var extension = comp.GlobalNamespace.GetTypeMember("<>E__0");
+ Assert.True(extension.IsExtension);
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_09()
+ {
+ // Two extension markers
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method private hidebysig specialname static void '$' ( string '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_10()
+ {
+ // Arity mismatch between skeleton and implementation
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0570: 'E.extension(int).M()' is not supported by the language
+ // int.M();
+ Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("E.extension(int).M()").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_11()
+ {
+ // Accessibility mismatch between skeleton and implementation
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method assembly hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0570: 'E.extension(int).M()' is not supported by the language
+ // int.M();
+ Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("E.extension(int).M()").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_12()
+ {
+ // parameter count mismatch between skeleton and implementation
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M (string s) cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0570: 'E.extension(int).M()' is not supported by the language
+ // int.M();
+ Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("E.extension(int).M()").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_13()
+ {
+ // return type mismatch between skeleton and implementation
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static int32 M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0570: 'E.extension(int).M()' is not supported by the language
+ // int.M();
+ Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("E.extension(int).M()").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_14()
+ {
+ // parameter type mismatch, instance method
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 i ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig instance void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M ( object i ) cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+42.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,4): error CS0570: 'E.extension(int).M()' is not supported by the language
+ // 42.M();
+ Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("E.extension(int).M()").WithLocation(1, 4));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_15()
+ {
+ // parameter type mismatch, instance method
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 i ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig instance void M ( string s ) cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M ( int32 i, object s ) cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+42.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,4): error CS0570: 'E.extension(int).M(string)' is not supported by the language
+ // 42.M();
+ Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("E.extension(int).M(string)").WithLocation(1, 4));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_16()
+ {
+ // constraint mismatch between skeleton and implementation
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0570: 'E.extension(int).M()' is not supported by the language
+ // int.M();
+ Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("E.extension(int).M()").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_17()
+ {
+ // implementation is not static
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig instance void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0570: 'E.extension(int).M()' is not supported by the language
+ // int.M();
+ Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("E.extension(int).M()").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_18()
+ {
+ // skeleton type is not sealed
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+
+ Assert.False(comp.GetTypeByMetadataName("E").GetTypeMembers().Single().IsExtension);
+ }
+
+ [Theory]
+ [InlineData("assembly")]
+ [InlineData("family")]
+ public void PENamedTypeSymbol_19(string accessibility)
+ {
+ // skeleton type is not public
+ var ilSrc = $$"""
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested {{accessibility}} auto ansi specialname beforefieldinit sealed '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+
+ Assert.False(comp.GetTypeByMetadataName("E").GetTypeMembers().Single().IsExtension);
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_20()
+ {
+ // skeleton type not sealed
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+
+ Assert.False(comp.GetTypeByMetadataName("E").GetTypeMembers().Single().IsExtension);
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_21()
+ {
+ // skeleton type has a base that's not object
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi specialname beforefieldinit sealed '<>E__0'
+ extends [mscorlib]System.String
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+
+ Assert.False(comp.GetTypeByMetadataName("E").GetTypeMembers().Single().IsExtension);
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_22()
+ {
+ // skeleton type implements an interface
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi specialname beforefieldinit sealed '<>E__0'
+ extends [mscorlib]System.Object
+ implements I
+ {
+ .method private hidebysig specialname static void '$' ( int32 '' ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M () cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+
+.class interface private auto ansi abstract beforefieldinit I
+{
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0117: 'int' does not contain a definition for 'M'
+ // int.M();
+ Diagnostic(ErrorCode.ERR_NoSuchMember, "M").WithArguments("int", "M").WithLocation(1, 5));
+
+ Assert.False(comp.GetTypeByMetadataName("E").GetTypeMembers().Single().IsExtension);
+ }
+
+ [Fact]
+ public void PENamedTypeSymbol_23()
+ {
+ // parameter type mismatch, static method
+ var ilSrc = """
+.class public auto ansi abstract sealed beforefieldinit E
+ extends [mscorlib]System.Object
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 )
+ .class nested public auto ansi sealed specialname beforefieldinit '<>E__0'
+ extends [mscorlib]System.Object
+ {
+ .method private hidebysig specialname static void '$' ( int32 i ) cil managed
+ {
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
+ IL_0000: ret
+ }
+
+ .method public hidebysig static void M ( string s ) cil managed
+ {
+ IL_0000: ldnull
+ IL_0001: throw
+ }
+ }
+
+ .method public hidebysig static void M ( object s ) cil managed
+ {
+ IL_0000: nop
+ IL_0001: ret
+ }
+}
+""";
+ var src = """
+int.M();
+""";
+ var comp = CreateCompilationWithIL(src, ilSrc);
+ comp.VerifyEmitDiagnostics(
+ // (1,5): error CS0570: 'E.extension(int).M(string)' is not supported by the language
+ // int.M();
+ Diagnostic(ErrorCode.ERR_BindToBogus, "M").WithArguments("E.extension(int).M(string)").WithLocation(1, 5));
+ }
+
+ [Fact]
+ public void RefReadonlyExtensionParameterWithOneExplicitRefArgument()
+ {
+ var src = """
+int i = 0;
+42.Copy(ref i);
+System.Console.Write(i);
+
+static class E
+{
+ extension(ref readonly int i)
+ {
+ public void Copy(ref int j) { j = i; }
+ }
+}
+""";
+ var comp = CreateCompilation(src);
+ CompileAndVerify(comp, expectedOutput: "42");
+ }
+
+ [Fact]
+ public void Cref_01()
+ {
+ var src = """
+///
+///
+///
+///
+static class E
+{
+ extension(int i)
+ {
+ ///
+ ///
+ ///
+ public void M(string s) => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (10,24): warning CS1574: XML comment has cref attribute 'M(string)' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "M(string)").WithArguments("M(string)").WithLocation(10, 24));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ AssertEx.Equal("T:E.<>E__0", e.GetTypeMembers().Single().GetDocumentationCommentId());
+
+ var mSkeleton = comp.GetMember("E").GetTypeMembers().Single().GetMember("M");
+ AssertEx.Equal("""
+
+
+
+
+
+
+""", mSkeleton.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal([
+ "(E.extension(int).M(string), void E.<>E__0.M(System.String s))",
+ "(E.M(int, string), void E.M(this System.Int32 i, System.String s))",
+ "(E.extension(int).M, void E.<>E__0.M(System.String s))",
+ "(E.M, void E.M(this System.Int32 i, System.String s))",
+ "(M(int, string), void E.M(this System.Int32 i, System.String s))",
+ "(M(string), null)",
+ "(M, void E.M(this System.Int32 i, System.String s))"],
+ PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_02()
+ {
+ var src = """
+///
+static class E
+{
+ extension(T t)
+ {
+ public void M(U u) => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ AssertEx.Equal("T:E.<>E__0`1", e.GetTypeMembers().Single().GetDocumentationCommentId());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension{T}(T).M{U}(U), void E.<>E__0.M(U u))"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_03()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(ref int).M()' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(ref int).M()").WithArguments("extension(ref int).M()").WithLocation(1, 16));
+ }
+
+ [Fact]
+ public void Cref_04()
+ {
+ var src = """
+///
+///
+static class E
+{
+ extension(ref int i)
+ {
+ public void M() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (2,16): warning CS1574: XML comment has cref attribute 'extension(int).M()' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).M()").WithArguments("extension(int).M()").WithLocation(2, 16));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal([
+ "(E.extension(ref int).M(), void E.<>E__0.M())",
+ "(E.extension(int).M(), null)"],
+ PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_05()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null!;
+ }
+ extension(string s)
+ {
+ public void M() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).M(), void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_06()
+ {
+ var src = """
+///
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null!;
+ }
+ extension(int)
+ {
+ public static void M() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M()'. Assuming 'E.extension(int).M()', but could have also matched other overloads including 'E.extension(int).M()'.
+ // ///
+ Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M()").WithArguments("E.extension(int).M()", "E.extension(int).M()", "E.extension(int).M()").WithLocation(1, 16),
+ // (2,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M'. Assuming 'E.extension(int).M()', but could have also matched other overloads including 'E.extension(int).M()'.
+ // ///
+ Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M").WithArguments("E.extension(int).M", "E.extension(int).M()", "E.extension(int).M()").WithLocation(2, 16),
+ // (11,28): error CS0111: Type 'E' already defines a member called 'M' with the same parameter types
+ // public static void M() => throw null!;
+ Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M").WithArguments("M", "E").WithLocation(11, 28));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal([
+ "(E.extension(int).M(), null)",
+ "(E.extension(int).M, null)"],
+ PrintXmlCrefSymbols(tree, model));
+
+ var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType();
+ var crefs = docComments.SelectMany(doc => doc.DescendantNodes().OfType()).ToArray();
+ Assert.Equal(CandidateReason.OverloadResolutionFailure, model.GetSymbolInfo(crefs[0].Cref).CandidateReason);
+ Assert.Equal(CandidateReason.Ambiguous, model.GetSymbolInfo(crefs[1].Cref).CandidateReason);
+ }
+
+ [Fact]
+ public void Cref_08()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i, int j)
+ {
+ public void M() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (4,22): error CS9285: An extension container can have only one receiver parameter
+ // extension(int i, int j)
+ Diagnostic(ErrorCode.ERR_ReceiverParameterOnlyOne, "int j").WithLocation(4, 22));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).M(), void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_09()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i, int j)
+ {
+ public void M() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(int, int).M()' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int, int).M()").WithArguments("extension(int, int).M()").WithLocation(1, 16),
+ // (4,22): error CS9285: An extension container can have only one receiver parameter
+ // extension(int i, int j)
+ Diagnostic(ErrorCode.ERR_ReceiverParameterOnlyOne, "int j").WithLocation(4, 22));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int, int).M(), null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_10()
+ {
+ // Missing closing parens
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension(.M()'
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension(.M()").WithArguments("E.extension(.M()").WithLocation(1, 16),
+ // (1,28): warning CS1658: ) expected. See also error CS1026.
+ // ///
+ Diagnostic(ErrorCode.WRN_ErrorOverride, ".").WithArguments(") expected", "1026").WithLocation(1, 28));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(.M(), null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_11()
+ {
+ // Missing extension parameter
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension().M()' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension().M()").WithArguments("extension().M()").WithLocation(1, 16));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension().M(), null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_12()
+ {
+ // Two extension parameters
+ var src = """
+///
+static class E
+{
+ extension(int i, int j)
+ {
+ public void M() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(int, int).M()' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int, int).M()").WithArguments("extension(int, int).M()").WithLocation(1, 16),
+ // (4,22): error CS9285: An extension container can have only one receiver parameter
+ // extension(int i, int j)
+ Diagnostic(ErrorCode.ERR_ReceiverParameterOnlyOne, "int j").WithLocation(4, 22));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int, int).M(), null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_13()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public int P => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).P, System.Int32 E.<>E__0.P { get; })"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_14()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public int P => throw null!;
+ }
+ extension(string s)
+ {
+ public string P => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).P, System.Int32 E.<>E__0.P { get; })"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_15()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public int P => throw null!;
+ }
+ extension(string s)
+ {
+ public string P => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(string).P, System.String E.<>E__1.P { get; })"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_16()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_17()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(string).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(string).M").WithArguments("extension(string).M").WithLocation(1, 16));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(string).M, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_18()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_19()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null;
+ public void M() => throw null;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_20()
+ {
+ var src = """
+///
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null;
+ public void M() => throw null;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal([
+ "(E.extension(int).M{U}, void E.<>E__0.M())",
+ "(E.M{U}, void E.M(this System.Int32 i))"],
+ PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_21()
+ {
+ // Arity for extension in cref differs from that in declaration
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(int).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).M").WithArguments("extension(int).M").WithLocation(1, 16));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).M, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_22()
+ {
+ // Arity for extension in cref differs from that in declaration
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension{T}(int).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension{T}(int).M").WithArguments("extension{T}(int).M").WithLocation(1, 16));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension{T}(int).M, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_23()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension{T}(int).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_24()
+ {
+ var src = """
+///
+static class E
+{
+ public static void M() => throw null;
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.M").WithArguments("M").WithLocation(1, 16));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.M, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_25()
+ {
+ // Type argument name differs from type parameter name
+ var src = """
+///
+static class E
+{
+ extension(T t)
+ {
+ public void M() => throw null;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension{U}(U).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_26()
+ {
+ // __arglist
+ var src = """
+///
+static class E
+{
+ extension(__arglist)
+ {
+ public int P => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(string).P' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(string).P").WithArguments("extension(string).P").WithLocation(1, 16),
+ // (4,15): error CS1669: __arglist is not valid in this context
+ // extension(__arglist)
+ Diagnostic(ErrorCode.ERR_IllegalVarArgs, "__arglist").WithLocation(4, 15));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(string).P, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_27()
+ {
+ // member named "extension"
+ var src = """
+///
+static class E
+{
+ public static void extension(string s) => throw null!;
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(string), void E.extension(System.String s))"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_28()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public int P => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension(int).'
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension(int).").WithArguments("E.extension(int).").WithLocation(1, 16),
+ // (1,33): warning CS1658: Identifier expected. See also error CS1001.
+ // ///
+ Diagnostic(ErrorCode.WRN_ErrorOverride, @"""").WithArguments("Identifier expected", "1001").WithLocation(1, 33));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int)., null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_29()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public class Nested { }
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(int).Nested' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).Nested").WithArguments("extension(int).Nested").WithLocation(1, 16),
+ // (6,22): error CS9282: This member is not allowed in an extension block
+ // public class Nested { }
+ Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Nested").WithLocation(6, 22));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).Nested, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_30()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ void I.M() { }
+ }
+}
+
+interface I
+{
+ void M();
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(int).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).M").WithArguments("extension(int).M").WithLocation(1, 16),
+ // (6,16): error CS0541: 'E.extension(int).M()': explicit interface declaration can only be declared in a class, record, struct or interface
+ // void I.M() { }
+ Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M").WithArguments("E.extension(int).M()").WithLocation(6, 16),
+ // (6,16): error CS9282: This member is not allowed in an extension block
+ // void I.M() { }
+ Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "M").WithLocation(6, 16));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).M, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_31()
+ {
+ var src = """
+///
+static class E
+{
+ extension(object)
+ {
+ public static void M() { }
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(missing).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(missing).M").WithArguments("extension(missing).M").WithLocation(1, 16),
+ // (1,28): warning CS1580: Invalid type for parameter missing in XML comment cref attribute: 'E.extension(missing).M'
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRefParamType, "missing").WithArguments("missing", "E.extension(missing).M").WithLocation(1, 28));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(missing).M, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_32()
+ {
+ // nested type named "extension"
+ var src = """
+///
+///
+///
+static class E
+{
+ class @extension
+ {
+ public static void M() { }
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal([
+ "(E.extension, E.extension)",
+ "(E.extension.M, void E.extension.M())",
+ "(E.extension.M(), void E.extension.M())"],
+ PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_33()
+ {
+ // nested type named "extension", error cases
+ var src = """
+///
+///
+///
+static class E
+{
+ class @extension
+ {
+ public static void M() { }
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (2,16): warning CS1574: XML comment has cref attribute 'extension().M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension().M").WithArguments("extension().M").WithLocation(2, 16),
+ // (3,16): warning CS1574: XML comment has cref attribute 'extension(int).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).M").WithArguments("extension(int).M").WithLocation(3, 16));
+ }
+
+ [Fact]
+ public void Cref_34()
+ {
+ // generic nested type named "extension"
+ var src = """
+///
+///
+static class E
+{
+ class @extension
+ {
+ public static void M() { }
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal([
+ "(E.extension{T}, E.extension)",
+ "(E.extension{T}.M, void E.extension.M())"],
+ PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_35()
+ {
+ // generic nested type named "extension", error cases
+ var src = """
+///
+static class E
+{
+ class @extension
+ {
+ public static void M() { }
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension{T}(int).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension{T}(int).M").WithArguments("extension{T}(int).M").WithLocation(1, 16));
+ }
+
+ [Fact]
+ public void Cref_36()
+ {
+ // can refer to method named "extension", but cannot refer to extension block
+ var src = """
+///
+///
+static class E
+{
+ public static void extension() { }
+ public static void extension(int i) { }
+}
+
+///
+///
+static class E2
+{
+ extension(int)
+ {
+ }
+
+ ///
+ ///
+ static void M() { }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (9,16): warning CS1574: XML comment has cref attribute 'extension()' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E2.extension()").WithArguments("extension()").WithLocation(9, 16),
+ // (10,16): warning CS1574: XML comment has cref attribute 'extension(int)' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E2.extension(int)").WithArguments("extension(int)").WithLocation(10, 16),
+ // (17,20): warning CS1574: XML comment has cref attribute 'extension()' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension()").WithArguments("extension()").WithLocation(17, 20),
+ // (18,20): warning CS1574: XML comment has cref attribute 'extension(int)' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int)").WithArguments("extension(int)").WithLocation(18, 20));
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal([
+ "(E.extension(), void E.extension())",
+ "(E.extension(int), void E.extension(System.Int32 i))",
+ "(E2.extension(), null)",
+ "(E2.extension(int), null)",
+ "(extension(), null)",
+ "(extension(int), null)"],
+ PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_37()
+ {
+ // method named "extension"
+ var src = """
+///
+///
+static class E
+{
+ public static void extension() { }
+ public static void extension(int i) { }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal([
+ "(E.extension(), void E.extension())",
+ "(E.extension(int), void E.extension(System.Int32 i))"],
+ PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_38()
+ {
+ // method named "extension", error case
+ var src = """
+///
+///
+static class E
+{
+ public static void extension() { }
+ public static void extension(int i) { }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension().M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension().M").WithArguments("extension().M").WithLocation(1, 16),
+ // (2,16): warning CS1574: XML comment has cref attribute 'extension(int).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(int).M").WithArguments("extension(int).M").WithLocation(2, 16));
+ }
+
+ [Fact]
+ public void Cref_39()
+ {
+ // nested type named "extension"
+ var src = """
+///
+static class E
+{
+ class @extension
+ {
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension, E.extension)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_40()
+ {
+ // inaccessible due to file accessibility on type
+ var src1 = """
+///
+class C { }
+""";
+ var src2 = """
+file static class E
+{
+ extension(object)
+ {
+ public static void M() { }
+ }
+}
+""";
+ var comp = CreateCompilation([(src1, "file1"), (src2, "file2")], parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // file1(1,16): warning CS1574: XML comment has cref attribute 'extension(object).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(object).M").WithArguments("extension(object).M").WithLocation(1, 16));
+
+ var c = comp.GetMember("C");
+ AssertEx.Equal("""
+
+
+
+
+""", c.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.First();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(object).M, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_41()
+ {
+ // inaccessible due to internal
+ var src = """
+///
+class C { }
+""";
+ var libSrc = """
+public static class E
+{
+ extension(object)
+ {
+ internal static void M() { }
+ }
+}
+""";
+ var libComp = CreateCompilation(libSrc);
+ var comp = CreateCompilation(src, references: [libComp.EmitToImageReference()],
+ parseOptions: TestOptions.RegularPreviewWithDocumentationComments,
+ options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All));
+
+ comp.VerifyEmitDiagnostics();
+
+ var c = comp.GetMember("C");
+ AssertEx.Equal("""
+
+
+
+
+""", c.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(object).M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_42()
+ {
+ // inaccessible due to private
+ var src = """
+///
+class C { }
+""";
+ var libSrc = """
+public static class E
+{
+ extension(object)
+ {
+ private static void M() { }
+ }
+}
+""";
+ var libComp = CreateCompilation(libSrc);
+ var comp = CreateCompilation(src, references: [libComp.EmitToImageReference()], parseOptions: TestOptions.RegularPreviewWithDocumentationComments, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All));
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(object).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(object).M").WithArguments("extension(object).M").WithLocation(1, 16));
+
+ var c = comp.GetMember("C");
+ AssertEx.Equal("""
+
+
+
+
+""", c.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(object).M, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_43()
+ {
+ var src = """
+///
+static class E
+{
+ extension(T t)
+ {
+ public static void M() { }
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension{int}(int).M'
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension{int}(int).M").WithArguments("E.extension{int}(int).M").WithLocation(1, 16),
+ // (1,28): warning CS1658: Type parameter declaration must be an identifier not a type. See also error CS0081.
+ // ///
+ Diagnostic(ErrorCode.WRN_ErrorOverride, "int").WithArguments("Type parameter declaration must be an identifier not a type", "0081").WithLocation(1, 28));
+ }
+
+ [Fact]
+ public void Cref_44()
+ {
+ var src = """
+///
+extension(int)
+{
+ public static void M() { }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(int).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).M").WithArguments("extension(int).M").WithLocation(1, 16),
+ // (2,1): error CS9283: Extensions must be declared in a top-level, non-generic, static class
+ // extension(int)
+ Diagnostic(ErrorCode.ERR_BadExtensionContainingType, "extension").WithLocation(2, 1),
+ // (4,24): warning CS1591: Missing XML comment for publicly visible type or member 'extension(int).M()'
+ // public static void M() { }
+ Diagnostic(ErrorCode.WRN_MissingXMLComment, "M").WithArguments("extension(int).M()").WithLocation(4, 24));
+ }
+
+ [Fact]
+ public void Cref_45()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int)
+ {
+ extension(string)
+ {
+ public static void M() { }
+ }
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension(int).extension(string).M'
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension(int).extension(string).M").WithArguments("E.extension(int).extension(string).M").WithLocation(1, 16),
+ // (1,33): warning CS1658: An extension member syntax is disallowed in nested position within an extension member syntax. See also error CS9309.
+ // ///
+ Diagnostic(ErrorCode.WRN_ErrorOverride, "extension(string).M").WithArguments("An extension member syntax is disallowed in nested position within an extension member syntax", "9309").WithLocation(1, 33),
+ // (6,9): error CS9282: This member is not allowed in an extension block
+ // extension(string)
+ Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "extension").WithLocation(6, 9));
+ }
+
+ [Fact]
+ public void Cref_46()
+ {
+ var src = """
+///
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null!;
+ public void M(int j) => throw null!;
+ public void M2(int j) => throw null!;
+ public void M2() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M'. Assuming 'E.extension(int).M()', but could have also matched other overloads including 'E.extension(int).M(int)'.
+ // ///
+ Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M").WithArguments("E.extension(int).M", "E.extension(int).M()", "E.extension(int).M(int)").WithLocation(1, 16),
+ // (2,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M2'. Assuming 'E.extension(int).M2(int)', but could have also matched other overloads including 'E.extension(int).M2()'.
+ // ///
+ Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M2").WithArguments("E.extension(int).M2", "E.extension(int).M2(int)", "E.extension(int).M2()").WithLocation(2, 16));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).M, null)", "(E.extension(int).M2, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_47()
+ {
+ // Xml doc APIs on PE symbols
+ var src = """
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var comp2 = CreateCompilation("", references: [comp.EmitToImageReference(documentation: new TestDocumentationProvider())]);
+
+ var mSkeleton = comp2.GetMember("E").GetTypeMembers().Single().GetMember("M");
+ Assert.Equal("M:E.<>E__0.M", mSkeleton.GetDocumentationCommentId());
+ Assert.Equal("M:E.<>E__0.M", mSkeleton.GetDocumentationCommentXml());
+ }
+
+ private class TestDocumentationProvider : DocumentationProvider
+ {
+ protected internal override string GetDocumentationForSymbol(string documentationMemberID, CultureInfo preferredCulture, CancellationToken cancellationToken = default)
+ {
+ return documentationMemberID;
+ }
+
+ public override bool Equals(object obj) => (object)this == obj;
+
+ public override int GetHashCode() => throw new NotImplementedException();
+ }
+
+ [Fact]
+ public void Cref_48()
+ {
+ var libSrc = """
+public static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null!;
+ }
+}
+""";
+ var libComp = CreateCompilation(libSrc);
+
+ var src = """
+///
+class C
+{
+}
+""";
+ var comp = CreateCompilation(src, references: [libComp.EmitToImageReference()], parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var c = comp.GetMember("C");
+ AssertEx.Equal("""
+
+
+
+
+""", c.GetDocumentationCommentXml());
+ }
+
+ [Fact]
+ public void Cref_49()
+ {
+ var src = """
+///
+static class E
+{
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(missing).M' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.extension(missing).M").WithArguments("extension(missing).M").WithLocation(1, 16),
+ // (1,28): warning CS1580: Invalid type for parameter missing in XML comment cref attribute: 'E.extension(missing).M'
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRefParamType, "missing").WithArguments("missing", "E.extension(missing).M").WithLocation(1, 28));
+ }
+
+ [Fact]
+ public void Cref_50()
+ {
+ var src = """
+///
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M() => throw null!;
+ public void M2(int j) => throw null!;
+ }
+ extension(int i)
+ {
+ public void M(int j) => throw null!;
+ public void M2() => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M'. Assuming 'E.extension(int).M()', but could have also matched other overloads including 'E.extension(int).M(int)'.
+ // ///
+ Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M").WithArguments("E.extension(int).M", "E.extension(int).M()", "E.extension(int).M(int)").WithLocation(1, 16),
+ // (2,16): warning CS0419: Ambiguous reference in cref attribute: 'E.extension(int).M2'. Assuming 'E.extension(int).M2(int)', but could have also matched other overloads including 'E.extension(int).M2()'.
+ // ///
+ Diagnostic(ErrorCode.WRN_AmbiguousXMLReference, "E.extension(int).M2").WithArguments("E.extension(int).M2", "E.extension(int).M2(int)", "E.extension(int).M2()").WithLocation(2, 16));
+
+ var e = comp.GetMember("E");
+ AssertEx.Equal("""
+
+
+
+
+
+""", e.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).M, null)", "(E.extension(int).M2, null)"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_51()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int)
+ {
+ public static void M() { }
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal(["(E.extension(int).@M, void E.<>E__0.M())"], PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_52()
+ {
+ // unqualified reference
+ var src = """
+///
+///
+static class E
+{
+ extension(int)
+ {
+ ///
+ ///
+ public static void M1() { }
+
+ public static void Method() { }
+ public static int Property => 42;
+ }
+
+ ///
+ ///
+ extension(object)
+ {
+ }
+
+ ///
+ ///
+ public static void M2() { }
+}
+""";
+ // Tracked by https://github.com/dotnet/roslyn/issues/76130 : cref, such unqualified references in CREF should work within context of enclosing static type
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'extension(int).Method' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Method").WithArguments("extension(int).Method").WithLocation(1, 16),
+ // (2,16): warning CS1574: XML comment has cref attribute 'extension(int).Property' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Property").WithArguments("extension(int).Property").WithLocation(2, 16),
+ // (7,24): warning CS1574: XML comment has cref attribute 'extension(int).Method' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Method").WithArguments("extension(int).Method").WithLocation(7, 24),
+ // (8,24): warning CS1574: XML comment has cref attribute 'extension(int).Property' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Property").WithArguments("extension(int).Property").WithLocation(8, 24),
+ // (15,20): warning CS1574: XML comment has cref attribute 'extension(int).Method' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Method").WithArguments("extension(int).Method").WithLocation(15, 20),
+ // (16,20): warning CS1574: XML comment has cref attribute 'extension(int).Property' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Property").WithArguments("extension(int).Property").WithLocation(16, 20),
+ // (21,20): warning CS1574: XML comment has cref attribute 'extension(int).M2' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).M2").WithArguments("extension(int).M2").WithLocation(21, 20),
+ // (22,20): warning CS1574: XML comment has cref attribute 'extension(int).Property' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "extension(int).Property").WithArguments("extension(int).Property").WithLocation(22, 20));
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal([
+ "(extension(int).Method, null)",
+ "(extension(int).Property, null)",
+ "(extension(int).Method, null)",
+ "(extension(int).Property, null)",
+ "(extension(int).Method, null)",
+ "(extension(int).Property, null)",
+ "(extension(int).M2, null)",
+ "(extension(int).Property, null)"],
+ PrintXmlCrefSymbols(tree, model));
+
+ src = """
+///
+static class E
+{
+ ///
+ static class Nested
+ {
+ ///
+ public static void M() { }
+
+ public static void Method() { }
+ }
+}
+""";
+ comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+ }
+
+ [Fact]
+ public void Cref_53()
+ {
+ var src = """
+static class E
+{
+ extension(int i)
+ {
+ ///
+ ///
+ public void M(string s) => throw null!;
+ }
+ extension(int i)
+ {
+ public void M2(string s) => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (5,24): warning CS1574: XML comment has cref attribute 'M2(string)' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "M2(string)").WithArguments("M2(string)").WithLocation(5, 24));
+
+ var mSkeleton = comp.GetMember("E").GetTypeMembers().First().GetMember("M");
+ AssertEx.Equal("""
+
+
+
+
+
+""", mSkeleton.GetDocumentationCommentXml());
+
+ var tree = comp.SyntaxTrees.Single();
+ var model = comp.GetSemanticModel(tree);
+ AssertEx.Equal([
+ "(M2(string), null)",
+ "(M2, void E.M2(this System.Int32 i, System.String s))"],
+ PrintXmlCrefSymbols(tree, model));
+ }
+
+ [Fact]
+ public void Cref_54()
+ {
+ var libSrc = """
+public static class E
+{
+ extension(int)
+ {
+ public static void M() { }
+ }
+}
+""";
+ var libComp = CreateCompilation(libSrc);
+ var libRef = libComp.EmitToImageReference();
+
+ var src = """
+///
+class C
+{
+}
+""";
+ var comp = CreateCompilation(src, references: [libRef], parseOptions: TestOptions.Regular13.WithDocumentationMode(DocumentationMode.Diagnose));
+ comp.VerifyEmitDiagnostics(
+ // (1,18): error CS8652: The feature 'extensions' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
+ // ///
+ Diagnostic(ErrorCode.ERR_FeatureInPreview, "extension(int).M").WithArguments("extensions").WithLocation(1, 18));
+
+ comp = CreateCompilation(src, references: [libRef], parseOptions: TestOptions.RegularNext.WithDocumentationMode(DocumentationMode.Diagnose));
+ comp.VerifyEmitDiagnostics();
+
+ comp = CreateCompilation(src, references: [libRef], parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics();
+ }
+
+ [Fact]
+ public void Cref_55()
+ {
+ var src = """
+///
+static class E
+{
+ extension(int i)
+ {
+ public void M(string s) => throw null!;
+ }
+}
+""";
+ var comp = CreateCompilation(src, parseOptions: TestOptions.RegularPreviewWithDocumentationComments);
+ comp.VerifyEmitDiagnostics(
+ // (1,16): warning CS1574: XML comment has cref attribute 'M(string)' that could not be resolved
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRef, "E.M(string)").WithArguments("M(string)").WithLocation(1, 16));
+ }
}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/IteratorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/IteratorTests.cs
index 69f12e7e3d7e2..0692049f45402 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/IteratorTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/IteratorTests.cs
@@ -13,6 +13,7 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.Test.Utilities;
using System.Linq;
+using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
@@ -35,12 +36,16 @@ IEnumerable I()
var comp = CreateCompilation(text);
var i = comp.GetMember("Test.I");
+ IMethodSymbol publicI = i.GetPublicSymbol();
+
Assert.True(i.IsIterator);
+ Assert.True(publicI.IsIterator);
Assert.Equal("System.Int32", i.IteratorElementTypeWithAnnotations.ToTestDisplayString());
comp.VerifyDiagnostics();
Assert.True(i.IsIterator);
+ Assert.True(publicI.IsIterator);
Assert.Equal("System.Int32", i.IteratorElementTypeWithAnnotations.ToTestDisplayString());
}
@@ -61,6 +66,102 @@ IEnumerable I()
comp.VerifyDiagnostics();
}
+ [Fact]
+ public void BasicIterators_Async()
+ {
+ var source = """
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+
+ class Test
+ {
+ async IAsyncEnumerable I()
+ {
+ await Task.Yield();
+ yield return 1;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source, targetFramework: TargetFramework.Net60);
+ comp.VerifyDiagnostics();
+
+ var i = comp.GetMember("Test.I");
+ Assert.True(i.IsIterator);
+ Assert.True(i.GetPublicSymbol().IsIterator);
+ Assert.Equal("System.Int32", i.IteratorElementTypeWithAnnotations.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void BasicIterators_Metadata()
+ {
+ var source = """
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+
+ public class Test
+ {
+ public IEnumerable I1()
+ {
+ yield return 1;
+ }
+
+ public async IAsyncEnumerable I2()
+ {
+ await Task.Yield();
+ yield return 1;
+ }
+ }
+ """;
+
+ var sourceComp = CreateCompilation(source, targetFramework: TargetFramework.Net60);
+ sourceComp.VerifyDiagnostics();
+
+ var userComp = CreateCompilation("", references: [sourceComp.EmitToImageReference()]);
+ userComp.VerifyEmitDiagnostics();
+ var testType = Assert.IsAssignableFrom(userComp.GetTypeByMetadataName("Test"));
+
+ var i1 = testType.GetMethod("I1");
+ Assert.False(i1.IsIterator);
+ Assert.False(i1.GetPublicSymbol().IsIterator);
+
+ var i2 = testType.GetMethod("I2");
+ Assert.False(i2.IsIterator);
+ Assert.False(i2.GetPublicSymbol().IsIterator);
+ }
+
+ [Fact]
+ public void MethodJustReturnsEnumerable_NotIterator()
+ {
+ var source = """
+ using System.Collections.Generic;
+
+ class Test
+ {
+ IEnumerable I1()
+ {
+ return [];
+ }
+
+ IAsyncEnumerable I2()
+ {
+ return default;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source, targetFramework: TargetFramework.Net60);
+ comp.VerifyDiagnostics();
+
+ var i1 = comp.GetMember("Test.I1");
+ Assert.False(i1.IsIterator);
+ Assert.False(i1.GetPublicSymbol().IsIterator);
+
+ var i2 = comp.GetMember("Test.I2");
+ Assert.False(i2.IsIterator);
+ Assert.False(i2.GetPublicSymbol().IsIterator);
+ }
+
[Fact]
public void WrongYieldType()
{
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs
index a5b2d45978332..3f571adf122cc 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs
@@ -2374,11 +2374,13 @@ public unsafe IEnumerable M4(int* a)
var local = model.GetDeclaredSymbol(declaration).GetSymbol();
Assert.True(local.IsIterator);
+ Assert.True(local.GetPublicSymbol().IsIterator);
Assert.Equal("System.Int32", local.IteratorElementTypeWithAnnotations.ToTestDisplayString());
model.GetOperation(declaration.Body);
Assert.True(local.IsIterator);
+ Assert.True(local.GetPublicSymbol().IsIterator);
Assert.Equal("System.Int32", local.IteratorElementTypeWithAnnotations.ToTestDisplayString());
comp.VerifyDiagnostics(
@@ -10709,5 +10711,89 @@ public class C(string p)
Diagnostic(ErrorCode.ERR_StaticLocalFunctionCannotCaptureVariable, "p").WithArguments("p").WithLocation(16, 42)
] : []);
}
+
+ [Fact]
+ public void SimpleIteratorLocalFunction()
+ {
+ var source = """
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+
+ class C
+ {
+ void M()
+ {
+ #pragma warning disable 8321 // The local function 'X' is declared but never used
+
+ IEnumerable I1()
+ {
+ yield return 1;
+ }
+
+ async IAsyncEnumerable I2()
+ {
+ await Task.Yield();
+ yield return 1;
+ }
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source, targetFramework: TargetFramework.Net60);
+ comp.VerifyDiagnostics();
+
+ var syntaxTree = comp.SyntaxTrees.Single();
+ var semanticModel = comp.GetSemanticModel(syntaxTree);
+ var localFunctionSyntaxes = syntaxTree.GetRoot().DescendantNodes().OfType().ToArray();
+
+ var i1Syntax = localFunctionSyntaxes[0];
+ IMethodSymbol i1Symbol = semanticModel.GetDeclaredSymbol(i1Syntax);
+ Assert.True(i1Symbol.IsIterator);
+
+ var i2Syntax = localFunctionSyntaxes[1];
+ IMethodSymbol i2Symbol = semanticModel.GetDeclaredSymbol(i2Syntax);
+ Assert.True(i2Symbol.IsIterator);
+ }
+
+ [Fact]
+ public void LocalFunctionJustReturnsEnumerable_NotIterator()
+ {
+ var source = """
+ using System.Collections.Generic;
+
+ class C
+ {
+ void M()
+ {
+ #pragma warning disable 8321 // The local function 'X' is declared but never used
+
+ IEnumerable I1()
+ {
+ return [];
+ }
+
+ IAsyncEnumerable I2()
+ {
+ return default;
+ }
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source, targetFramework: TargetFramework.Net60);
+ comp.VerifyDiagnostics();
+
+ var syntaxTree = comp.SyntaxTrees.Single();
+ var semanticModel = comp.GetSemanticModel(syntaxTree);
+ var localFunctionSyntaxes = syntaxTree.GetRoot().DescendantNodes().OfType().ToArray();
+
+ var i1Syntax = localFunctionSyntaxes[0];
+ IMethodSymbol i1Symbol = semanticModel.GetDeclaredSymbol(i1Syntax);
+ Assert.False(i1Symbol.IsIterator);
+
+ var i2Syntax = localFunctionSyntaxes[1];
+ IMethodSymbol i2Symbol = semanticModel.GetDeclaredSymbol(i2Syntax);
+ Assert.False(i2Symbol.IsIterator);
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs
index bf231df859a11..977c987f503b7 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs
@@ -11300,5 +11300,162 @@ public static void M({{scoped2}} {{modifier}} R r) { }
""";
CreateCompilation(source).VerifyDiagnostics();
}
+
+ [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/78711")]
+ [InlineData("public void UseSpan(Span span)", 17)]
+ [InlineData("void I.UseSpan(Span span)", 12)]
+ public void RefStructInterface_ScopedDifference(string implSignature, int column)
+ {
+ // This is a case where interface methods need to be treated specially in scoped variance checks.
+ // Because a ref struct can implement the interface, we need to compare the signatures as if the interface has a receiver parameter which is ref-to-ref-struct.
+ var source = $$"""
+ using System;
+
+ interface I
+ {
+ void UseSpan(scoped Span span);
+ }
+
+ ref struct RS : I
+ {
+ public Span Span { get; set; }
+ public RS(Span span) => Span = span;
+
+ {{implSignature}} // 1
+ {
+ this.Span = span;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source, targetFramework: TargetFramework.Net90);
+ comp.VerifyEmitDiagnostics(
+ // (13,17): error CS8987: The 'scoped' modifier of parameter 'span' doesn't match overridden or implemented member.
+ // public void UseSpan(Span span)
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "UseSpan").WithArguments("span").WithLocation(13, column));
+ }
+
+ [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/78711")]
+ [InlineData("public readonly void UseSpan(Span span)")]
+ [InlineData("readonly void I.UseSpan(Span span)")]
+ public void RefStructInterface_ScopedDifference_ReadonlyImplementation(string implSignature)
+ {
+ var source = $$"""
+ using System;
+
+ interface I
+ {
+ void UseSpan(scoped Span span);
+ }
+
+ ref struct RS : I
+ {
+ public Span Span { get; set; }
+ public RS(Span span) => Span = span;
+
+ {{implSignature}}
+ {
+ Span = span; // 1
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source, targetFramework: TargetFramework.Net90);
+ comp.VerifyEmitDiagnostics(
+ // (15,9): error CS1604: Cannot assign to 'Span' because it is read-only
+ // Span = span; // 1
+ Diagnostic(ErrorCode.ERR_AssgReadonlyLocal, "Span").WithArguments("Span").WithLocation(15, 9));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78711")]
+ public void SimilarScenarioAs78711InvolvingNonReceiverParameter()
+ {
+ // Demonstrate a scenario similar to https://github.com/dotnet/roslyn/issues/78711 involving a non-receiver parameter has consistent behavior
+ // In this case, the interface and implementation parameters cannot differ by type. But it as close as we can get to the receiver parameter case.
+ var source = """
+ using System;
+
+ interface I
+ {
+ void UseSpan1(ref RS rs, scoped Span span);
+ void UseSpan2(ref readonly RS rs, scoped Span span);
+ }
+
+ class C : I
+ {
+ public void UseSpan1(ref RS rs, Span span) // 1
+ {
+ rs.Span = span;
+ }
+
+ public void UseSpan2(ref readonly RS rs, Span span)
+ {
+ rs.Span = span; // 2
+ }
+ }
+
+ ref struct RS
+ {
+ public Span Span { get; set; }
+ public RS(Span span) => Span = span;
+ }
+ """;
+
+ var comp = CreateCompilation(source, targetFramework: TargetFramework.Net90);
+ comp.VerifyEmitDiagnostics(
+ // (11,17): error CS8987: The 'scoped' modifier of parameter 'span' doesn't match overridden or implemented member.
+ // public void UseSpan1(ref RS rs, Span span) // 1
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "UseSpan1").WithArguments("span").WithLocation(11, 17),
+ // (18,9): error CS8332: Cannot assign to a member of variable 'rs' or use it as the right hand side of a ref assignment because it is a readonly variable
+ // rs.Span = span; // 2
+ Diagnostic(ErrorCode.ERR_AssignReadonlyNotField2, "rs.Span").WithArguments("variable", "rs").WithLocation(18, 9));
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78711")]
+ public void Repro_78711()
+ {
+ var source = """
+ using System;
+
+ public static class Demo
+ {
+ public static void Show()
+ {
+ var stru = new Stru();
+
+ Unsafe(ref stru);
+
+ Console.Out.WriteLine(stru.Span);
+ }
+
+ private static void Unsafe(ref T stru) where T : IStru, allows ref struct
+ {
+ Span span = stackalloc char[10];
+
+ "bug".CopyTo(span);
+
+ stru.UseSpan(span);
+ }
+ }
+
+ internal interface IStru
+ {
+ public void UseSpan(scoped Span span);
+ }
+
+ internal ref struct Stru : IStru
+ {
+ public Span Span;
+
+ public void UseSpan(Span span) => Span = span; // 1
+ }
+ """;
+
+ var comp = CreateCompilation(source, targetFramework: TargetFramework.Net90);
+ comp.VerifyEmitDiagnostics(
+ // (33,17): error CS8987: The 'scoped' modifier of parameter 'span' doesn't match overridden or implemented member.
+ // public void UseSpan(Span span) => Span = span;
+ Diagnostic(ErrorCode.ERR_ScopedMismatchInParameterOfOverrideOrImplementation, "UseSpan").WithArguments("span").WithLocation(33, 17));
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
index 0edf1f6e5fe4a..4de4f0482aad2 100644
--- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs
@@ -628,6 +628,9 @@ private static Syntax.InternalSyntax.QualifiedCrefSyntax GenerateQualifiedCref()
private static Syntax.InternalSyntax.NameMemberCrefSyntax GenerateNameMemberCref()
=> InternalSyntaxFactory.NameMemberCref(GenerateIdentifierName(), null);
+ private static Syntax.InternalSyntax.ExtensionMemberCrefSyntax GenerateExtensionMemberCref()
+ => InternalSyntaxFactory.ExtensionMemberCref(InternalSyntaxFactory.Token(SyntaxKind.ExtensionKeyword), null, GenerateCrefParameterList(), InternalSyntaxFactory.Token(SyntaxKind.DotToken), GenerateNameMemberCref());
+
private static Syntax.InternalSyntax.IndexerMemberCrefSyntax GenerateIndexerMemberCref()
=> InternalSyntaxFactory.IndexerMemberCref(InternalSyntaxFactory.Token(SyntaxKind.ThisKeyword), null);
@@ -3377,6 +3380,20 @@ public void TestNameMemberCrefFactoryAndProperties()
AttachAndCheckDiagnostics(node);
}
+ [Fact]
+ public void TestExtensionMemberCrefFactoryAndProperties()
+ {
+ var node = GenerateExtensionMemberCref();
+
+ Assert.Equal(SyntaxKind.ExtensionKeyword, node.ExtensionKeyword.Kind);
+ Assert.Null(node.TypeArgumentList);
+ Assert.NotNull(node.Parameters);
+ Assert.Equal(SyntaxKind.DotToken, node.DotToken.Kind);
+ Assert.NotNull(node.Member);
+
+ AttachAndCheckDiagnostics(node);
+ }
+
[Fact]
public void TestIndexerMemberCrefFactoryAndProperties()
{
@@ -9272,6 +9289,32 @@ public void TestNameMemberCrefIdentityRewriter()
Assert.Same(oldNode, newNode);
}
+ [Fact]
+ public void TestExtensionMemberCrefTokenDeleteRewriter()
+ {
+ var oldNode = GenerateExtensionMemberCref();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestExtensionMemberCrefIdentityRewriter()
+ {
+ var oldNode = GenerateExtensionMemberCref();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
[Fact]
public void TestIndexerMemberCrefTokenDeleteRewriter()
{
@@ -10935,6 +10978,9 @@ private static QualifiedCrefSyntax GenerateQualifiedCref()
private static NameMemberCrefSyntax GenerateNameMemberCref()
=> SyntaxFactory.NameMemberCref(GenerateIdentifierName(), default(CrefParameterListSyntax));
+ private static ExtensionMemberCrefSyntax GenerateExtensionMemberCref()
+ => SyntaxFactory.ExtensionMemberCref(SyntaxFactory.Token(SyntaxKind.ExtensionKeyword), default(TypeArgumentListSyntax), GenerateCrefParameterList(), SyntaxFactory.Token(SyntaxKind.DotToken), GenerateNameMemberCref());
+
private static IndexerMemberCrefSyntax GenerateIndexerMemberCref()
=> SyntaxFactory.IndexerMemberCref(SyntaxFactory.Token(SyntaxKind.ThisKeyword), default(CrefBracketedParameterListSyntax));
@@ -13684,6 +13730,20 @@ public void TestNameMemberCrefFactoryAndProperties()
Assert.Equal(node, newNode);
}
+ [Fact]
+ public void TestExtensionMemberCrefFactoryAndProperties()
+ {
+ var node = GenerateExtensionMemberCref();
+
+ Assert.Equal(SyntaxKind.ExtensionKeyword, node.ExtensionKeyword.Kind());
+ Assert.Null(node.TypeArgumentList);
+ Assert.NotNull(node.Parameters);
+ Assert.Equal(SyntaxKind.DotToken, node.DotToken.Kind());
+ Assert.NotNull(node.Member);
+ var newNode = node.WithExtensionKeyword(node.ExtensionKeyword).WithTypeArgumentList(node.TypeArgumentList).WithParameters(node.Parameters).WithDotToken(node.DotToken).WithMember(node.Member);
+ Assert.Equal(node, newNode);
+ }
+
[Fact]
public void TestIndexerMemberCrefFactoryAndProperties()
{
@@ -19579,6 +19639,32 @@ public void TestNameMemberCrefIdentityRewriter()
Assert.Same(oldNode, newNode);
}
+ [Fact]
+ public void TestExtensionMemberCrefTokenDeleteRewriter()
+ {
+ var oldNode = GenerateExtensionMemberCref();
+ var rewriter = new TokenDeleteRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ if(!oldNode.IsMissing)
+ {
+ Assert.NotEqual(oldNode, newNode);
+ }
+
+ Assert.NotNull(newNode);
+ Assert.True(newNode.IsMissing, "No tokens => missing");
+ }
+
+ [Fact]
+ public void TestExtensionMemberCrefIdentityRewriter()
+ {
+ var oldNode = GenerateExtensionMemberCref();
+ var rewriter = new IdentityRewriter();
+ var newNode = rewriter.Visit(oldNode);
+
+ Assert.Same(oldNode, newNode);
+ }
+
[Fact]
public void TestIndexerMemberCrefTokenDeleteRewriter()
{
diff --git a/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/LexicalTests.cs b/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/LexicalTests.cs
index b17f2475f3594..a2360d1bf4c0d 100644
--- a/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/LexicalTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/LexicalTests.cs
@@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
+using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
@@ -4572,5 +4573,90 @@ disabled text 2
Assert.True(trivia.ContainsDiagnostics);
Assert.Equal((int)ErrorCode.ERR_Merge_conflict_marker_encountered, trivia.Errors().Single().Code);
}
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78593")]
+ public void TestDotPrefixedNumberStartingAtStartOfSlidingTextWindow()
+ {
+ // This test depends on the line endings for the file being \r\n to ensure the right contents lines up at
+ // the right locations.
+ //
+ // It specifically validates what happens when we see `.0` at the start of the
+ // sliding text window, where the lexer tries to peek back one char to see if this
+ // is actually `..0` (a range expr) or `.0` (a floating point number).
+ var code = Resources.DotPrefixedNumberStartingAtStartOfSlidingTextWindow;
+ if (!code.Contains("\r\n"))
+ code = code.Replace("\n", "\r\n");
+
+ var sourceText = SourceText.From(code);
+
+ {
+ // Run a full parse, and validate the tree returned).
+
+ using var lexer = new Lexer(sourceText, CSharpParseOptions.Default);
+
+ // Ensure we have a normal window size, not some larger array that another test created and cached in
+ // the window pool
+ lexer.TextWindow.GetTestAccessor().SetDefaultCharacterWindow();
+
+ using var parser = new LanguageParser(lexer, oldTree: null, changes: null);
+
+ Microsoft.CodeAnalysis.SyntaxTreeExtensions.VerifySource(
+ sourceText, parser.ParseCompilationUnit().CreateRed());
+ }
+
+ {
+ // Now, replicate the same conditions that hte parser runs through by driving the a new lexer here
+ // directly. That ensures that we are actually validating exactly the conditions that led to the bug
+ // (a dot token starting a number, right at the start of the character window).
+ var lexer = new Lexer(sourceText, CSharpParseOptions.Default);
+
+ // Ensure we have a normal window size, not some larger array that another test created and cached in
+ // the window pool
+ lexer.TextWindow.GetTestAccessor().SetDefaultCharacterWindow();
+
+ var mode = LexerMode.Syntax;
+ for (var i = 0; i < 1326; i++)
+ lexer.Lex(ref mode);
+
+ // Lexer will read from index 0 in the arrray.
+ Assert.Equal(0, lexer.TextWindow.Offset);
+
+ // We have 205 real chars in the window
+ Assert.Equal(205, lexer.TextWindow.CharacterWindowCount);
+
+ // The lexer is at position 10199 in the file.
+ Assert.Equal(10199, lexer.TextWindow.Position);
+
+ /// The 205 characters represent the final part of the doc
+ Assert.Equal(lexer.TextWindow.Text.Length, lexer.TextWindow.Position + lexer.TextWindow.CharacterWindowCount);
+
+ // We're at the start of a token.
+ Assert.Equal(lexer.TextWindow.LexemeStartPosition, lexer.TextWindow.Position);
+
+ // Ensure that the lexer's window is starting with the next FP number (".03") right at
+ // the start of the window.
+ Assert.True(lexer.TextWindow.CharacterWindow is ['.', '0', '3', ',', ..], $"Start of window was '{new string(lexer.TextWindow.CharacterWindow, 0, 4)}'");
+
+ var token = lexer.Lex(ref mode);
+ Assert.Equal(SyntaxKind.NumericLiteralToken, token.Kind);
+ Assert.Equal(3, token.FullWidth);
+ Assert.Equal(".03", token.ToString());
+
+ // But we moved 3 characters forward.
+ Assert.Equal(3, lexer.TextWindow.Offset);
+
+ // We still have 205 real chars in the window
+ Assert.Equal(205, lexer.TextWindow.CharacterWindowCount);
+
+ // The lexer position has moved 3 characters forward as well.
+ Assert.Equal(10202, lexer.TextWindow.Position);
+
+ // We're at the start of a token.
+ Assert.Equal(lexer.TextWindow.LexemeStartPosition, lexer.TextWindow.Position);
+
+ // Character window didn't changee.
+ Assert.True(lexer.TextWindow.CharacterWindow is ['.', '0', '3', ',', ..], $"Start of window was '{new string(lexer.TextWindow.CharacterWindow, 0, 4)}'");
+ }
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/CrefParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/CrefParsingTests.cs
index b478bdf25b928..da1e331238d5e 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/CrefParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/CrefParsingTests.cs
@@ -6,6 +6,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
+using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using System;
using System.Linq;
@@ -3573,5 +3574,475 @@ public void AliasQualifiedGenericTypeConstructor()
}
#endregion Non-simple-type constructors
+
+ #region Extension members
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_01()
+ {
+ UsingNode("extension", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken);
+ }
+ }
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_02()
+ {
+ UsingNode("E.extension", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "extension");
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_03()
+ {
+ UsingNode("E.extension()", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "extension");
+ }
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_04()
+ {
+ UsingNode("E.extension(int)", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "extension");
+ }
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CrefParameter);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_05()
+ {
+ UsingNode("E.extension{T}", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.GenericName);
+ {
+ N(SyntaxKind.IdentifierToken, "extension");
+ N(SyntaxKind.TypeArgumentList);
+ {
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "T");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_06()
+ {
+ UsingNode("E.extension{T}()", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.GenericName);
+ {
+ N(SyntaxKind.IdentifierToken, "extension");
+ N(SyntaxKind.TypeArgumentList);
+ {
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "T");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ }
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_07()
+ {
+ UsingNode("E.extension{T}(int)", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.GenericName);
+ {
+ N(SyntaxKind.IdentifierToken, "extension");
+ N(SyntaxKind.TypeArgumentList);
+ {
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "T");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ }
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CrefParameter);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_08()
+ {
+ UsingNode("E.extension{T}(int).", options: TestOptions.RegularPreviewWithDocumentationComments,
+ // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension{T}(int).'
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension{T}(int).").WithArguments("E.extension{T}(int).").WithLocation(1, 16),
+ // (1,36): warning CS1658: Identifier expected. See also error CS1001.
+ // ///
+ Diagnostic(ErrorCode.WRN_ErrorOverride, @"""").WithArguments("Identifier expected", "1001").WithLocation(1, 36));
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.ExtensionMemberCref);
+ {
+ N(SyntaxKind.ExtensionKeyword);
+ N(SyntaxKind.TypeArgumentList);
+ {
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "T");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CrefParameter);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.DotToken);
+ M(SyntaxKind.NameMemberCref);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_09()
+ {
+ UsingNode("E.extension{T}(int).M", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.ExtensionMemberCref);
+ {
+ N(SyntaxKind.ExtensionKeyword);
+ N(SyntaxKind.TypeArgumentList);
+ {
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "T");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CrefParameter);
+ {
+ N(SyntaxKind.PredefinedType);
+ {
+ N(SyntaxKind.IntKeyword);
+ }
+ }
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "M");
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_10()
+ {
+ UsingNode("E.extension{T}().M", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.ExtensionMemberCref);
+ {
+ N(SyntaxKind.ExtensionKeyword);
+ N(SyntaxKind.TypeArgumentList);
+ {
+ N(SyntaxKind.LessThanToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "T");
+ }
+ N(SyntaxKind.GreaterThanToken);
+ }
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "M");
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_11()
+ {
+ UsingNode("E.extension().M", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.ExtensionMemberCref);
+ {
+ N(SyntaxKind.ExtensionKeyword);
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "M");
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_12()
+ {
+ UsingNode("E.extension().extension().M", options: TestOptions.RegularPreviewWithDocumentationComments,
+ // (1,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'E.extension().extension().M'
+ // ///
+ Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "E.extension().extension().M").WithArguments("E.extension().extension().M").WithLocation(1, 16),
+ // (1,30): warning CS1658: An extension member syntax is disallowed in nested position within an extension member syntax. See also error CS9309.
+ // ///
+ Diagnostic(ErrorCode.WRN_ErrorOverride, "extension().M").WithArguments("An extension member syntax is disallowed in nested position within an extension member syntax", "9309").WithLocation(1, 30));
+
+ N(SyntaxKind.QualifiedCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "E");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.ExtensionMemberCref);
+ {
+ N(SyntaxKind.ExtensionKeyword);
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.ExtensionMemberCref);
+ {
+ N(SyntaxKind.ExtensionKeyword);
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "M");
+ }
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact, CompilerTrait(CompilerFeature.Extensions)]
+ public void ExtensionCref_13()
+ {
+ UsingNode("extension().M", options: TestOptions.RegularPreviewWithDocumentationComments);
+
+ N(SyntaxKind.ExtensionMemberCref);
+ {
+ N(SyntaxKind.ExtensionKeyword);
+ N(SyntaxKind.CrefParameterList);
+ {
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.CloseParenToken);
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.NameMemberCref);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "M");
+ }
+ }
+ }
+ EOF();
+ }
+
+ #endregion
}
}
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs
index 8e383919cef6a..8d7bf2990fe4a 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ExtensionsParsingTests.cs
@@ -1568,7 +1568,7 @@ static class C
""";
var comp = CreateCompilation(src);
comp.VerifyEmitDiagnostics(
- // (5,9): error CS9282: Extension declarations can include only methods or properties
+ // (5,9): error CS9282: This member is not allowed in an extension block
// extension(Type2) { }
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "extension").WithLocation(5, 9));
@@ -2143,7 +2143,7 @@ static class C
""";
var comp = CreateCompilation(src);
comp.VerifyEmitDiagnostics(
- // (5,19): error CS9282: Extension declarations can include only methods or properties
+ // (5,19): error CS9282: This member is not allowed in an extension block
// const int i = 0;
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "i").WithLocation(5, 19));
@@ -2226,7 +2226,7 @@ static class C
// (5,19): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context
// fixed int field[10];
Diagnostic(ErrorCode.ERR_UnsafeNeeded, "field[10]").WithLocation(5, 19),
- // (5,19): error CS9282: Extension declarations can include only methods or properties
+ // (5,19): error CS9282: This member is not allowed in an extension block
// fixed int field[10];
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "field").WithLocation(5, 19));
@@ -2308,13 +2308,13 @@ static class C
""";
var comp = CreateCompilation(src);
comp.VerifyEmitDiagnostics(
- // (5,35): error CS9282: Extension declarations can include only methods or properties
+ // (5,35): error CS9282: This member is not allowed in an extension block
// event System.EventHandler eventField;
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "eventField").WithLocation(5, 35),
- // (5,35): error CS9282: Extension declarations can include only methods or properties
+ // (5,35): error CS9282: This member is not allowed in an extension block
// event System.EventHandler eventField;
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "eventField").WithLocation(5, 35),
- // (5,35): error CS9282: Extension declarations can include only methods or properties
+ // (5,35): error CS9282: This member is not allowed in an extension block
// event System.EventHandler eventField;
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "eventField").WithLocation(5, 35),
// (5,35): warning CS0067: The event 'C.extension(object).eventField' is never used
@@ -2395,13 +2395,13 @@ event System.EventHandler Event { add { } remove { } }
""";
var comp = CreateCompilation(src);
comp.VerifyEmitDiagnostics(
- // (5,35): error CS9282: Extension declarations can include only methods or properties
+ // (5,35): error CS9282: This member is not allowed in an extension block
// event System.EventHandler Event { add { } remove { } }
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Event").WithLocation(5, 35),
- // (5,43): error CS9282: Extension declarations can include only methods or properties
+ // (5,43): error CS9282: This member is not allowed in an extension block
// event System.EventHandler Event { add { } remove { } }
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "add").WithLocation(5, 43),
- // (5,51): error CS9282: Extension declarations can include only methods or properties
+ // (5,51): error CS9282: This member is not allowed in an extension block
// event System.EventHandler Event { add { } remove { } }
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "remove").WithLocation(5, 51));
@@ -2583,7 +2583,7 @@ class Nested { }
""";
var comp = CreateCompilation(src);
comp.VerifyEmitDiagnostics(
- // (5,15): error CS9282: Extension declarations can include only methods or properties
+ // (5,15): error CS9282: This member is not allowed in an extension block
// class Nested { }
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Nested").WithLocation(5, 15));
@@ -2646,7 +2646,7 @@ static class C
// (5,9): error CS1520: Method must have a return type
// Constructor() { }
Diagnostic(ErrorCode.ERR_MemberNeedsType, "Constructor").WithLocation(5, 9),
- // (5,9): error CS9282: Extension declarations can include only methods or properties
+ // (5,9): error CS9282: This member is not allowed in an extension block
// Constructor() { }
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Constructor").WithLocation(5, 9));
@@ -2717,7 +2717,7 @@ static Constructor() { }
// (5,16): error CS1520: Method must have a return type
// static Constructor() { }
Diagnostic(ErrorCode.ERR_MemberNeedsType, "Constructor").WithLocation(5, 16),
- // (5,16): error CS9282: Extension declarations can include only methods or properties
+ // (5,16): error CS9282: This member is not allowed in an extension block
// static Constructor() { }
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Constructor").WithLocation(5, 16));
@@ -2785,7 +2785,7 @@ static class C
""";
var comp = CreateCompilation(src);
comp.VerifyEmitDiagnostics(
- // (5,10): error CS9282: Extension declarations can include only methods or properties
+ // (5,10): error CS9282: This member is not allowed in an extension block
// ~Finalizer() { }
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "Finalizer").WithLocation(5, 10));
@@ -2854,7 +2854,7 @@ static class C
""";
var comp = CreateCompilation(src);
comp.VerifyEmitDiagnostics(
- // (5,13): error CS9282: Extension declarations can include only methods or properties
+ // (5,13): error CS9282: This member is not allowed in an extension block
// int field;
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "field").WithLocation(5, 13),
// (5,13): warning CS0169: The field 'C.extension(object).field' is never used
@@ -3024,7 +3024,7 @@ static class C
// (5,39): error CS0563: One of the parameters of a binary operator must be the containing type
// public static object operator +(object a, object b) => a;
Diagnostic(ErrorCode.ERR_BadBinaryOperatorSignature, "+").WithLocation(5, 39),
- // (5,39): error CS9282: Extension declarations can include only methods or properties
+ // (5,39): error CS9282: This member is not allowed in an extension block
// public static object operator +(object a, object b) => a;
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "+").WithLocation(5, 39));
@@ -3121,7 +3121,7 @@ static class C
// (5,41): error CS0556: User-defined conversion must convert to or from the enclosing type
// public static implicit operator int(object t) => 0;
Diagnostic(ErrorCode.ERR_ConversionNotInvolvingContainedType, "int").WithLocation(5, 41),
- // (5,41): error CS9282: Extension declarations can include only methods or properties
+ // (5,41): error CS9282: This member is not allowed in an extension block
// public static implicit operator int(object t) => 0;
Diagnostic(ErrorCode.ERR_ExtensionDisallowsMember, "int").WithLocation(5, 41));
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/IgnoredDirectiveParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/IgnoredDirectiveParsingTests.cs
index fbf167277ec88..c741759106b0a 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/IgnoredDirectiveParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/IgnoredDirectiveParsingTests.cs
@@ -287,7 +287,7 @@ public void AfterToken()
EOF();
}
- [Fact]
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78157")]
public void AfterIf()
{
var source = """
@@ -299,7 +299,7 @@ public void AfterIf()
""";
VerifyTrivia();
- UsingTree(source, TestOptions.Regular.WithFeature(FeatureName),
+ UsingTree(source, TestOptions.Regular.WithFeature(FeatureName).WithPreprocessorSymbols("X"),
// (3,2): error CS9283: '#:' directives cannot be after '#if' directive
// #:y
Diagnostic(ErrorCode.ERR_PPIgnoredFollowsIf, ":").WithLocation(3, 2),
@@ -366,6 +366,71 @@ public void AfterIf()
}
}
EOF();
+
+ UsingTree(source, TestOptions.Regular.WithFeature(FeatureName),
+ // (5,2): error CS9299: '#:' directives cannot be after '#if' directive
+ // #:z
+ Diagnostic(ErrorCode.ERR_PPIgnoredFollowsIf, ":").WithLocation(5, 2));
+
+ N(SyntaxKind.CompilationUnit);
+ {
+ N(SyntaxKind.EndOfFileToken);
+ {
+ L(SyntaxKind.IgnoredDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.StringLiteralToken, "x");
+ N(SyntaxKind.EndOfDirectiveToken);
+ {
+ T(SyntaxKind.EndOfLineTrivia, "\n");
+ }
+ }
+ L(SyntaxKind.IfDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.IfKeyword);
+ {
+ T(SyntaxKind.WhitespaceTrivia, " ");
+ }
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "X");
+ }
+ N(SyntaxKind.EndOfDirectiveToken);
+ {
+ T(SyntaxKind.EndOfLineTrivia, "\n");
+ }
+ }
+ L(SyntaxKind.IgnoredDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.StringLiteralToken, "y");
+ N(SyntaxKind.EndOfDirectiveToken);
+ {
+ T(SyntaxKind.EndOfLineTrivia, "\n");
+ }
+ }
+ L(SyntaxKind.EndIfDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.EndIfKeyword);
+ N(SyntaxKind.EndOfDirectiveToken);
+ {
+ T(SyntaxKind.EndOfLineTrivia, "\n");
+ }
+ }
+ L(SyntaxKind.IgnoredDirectiveTrivia);
+ {
+ N(SyntaxKind.HashToken);
+ N(SyntaxKind.ColonToken);
+ N(SyntaxKind.StringLiteralToken, "z");
+ N(SyntaxKind.EndOfDirectiveToken);
+ }
+ }
+ }
+ EOF();
}
[Fact]
diff --git a/src/Compilers/CSharp/Test/Syntax/Resources.resx b/src/Compilers/CSharp/Test/Syntax/Resources.resx
index 2004f7e760271..37ec16cc49bde 100644
--- a/src/Compilers/CSharp/Test/Syntax/Resources.resx
+++ b/src/Compilers/CSharp/Test/Syntax/Resources.resx
@@ -119,6 +119,253 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ // ------------------------------
+// THIS FILE IS AUTO GENERATED
+// PLEASE DO NOT MODIFY
+// ------------------------------
+// Hash: D5-B1-B5-D5-B6-27-C1-44-E0-20-77-14-52-A7-7A-E3-26-1C-6C-74-82-E1-2D-00-C3-73-22-7D-F5-CF-1B-76-95-45-88-4A-9A-0D-E3-D1-8F-69-F3-C3-76-41-92-67-F1-9D-64-EF-86-77-39-48-8C-0E-20-44-51-CA-5D-65
+
+using Goobar.Combat;
+using Goobar.Commons.Rules;
+using Goobar.Localization;
+using Goobar.Shared.Entities.Units;
+using static System.Collections.Immutable.ImmutableArray;
+using System;
+using System.Collections.Immutable;
+using Goobar.Shared.Utils;
+using System.Collections.Generic;
+using Goobar.GeneratedCode;
+
+namespace Goobar;
+
+
+[GenerateAllValues(typeof(Goobar.Commons.Rules.UnitEquipmentAttributeDefinition))]
+public static partial class EquipmentAttributes
+{
+
+ public static class Minor_Power_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_Power_Flat",
+ Attribute: CombatAttribute.Power,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(30.0, 60.0, 110.0, 180.0, 280.0),
+ SecondaryStatByRarityTo: Create(40.0, 80.0, 140.0, 220.0, 320.0),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Minor_Power_Perc
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_Power_Perc",
+ Attribute: CombatAttribute.Power,
+ ModifierType: AttributeModifierType.Percentage,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(.02, .04, .06, .09, .13),
+ SecondaryStatByRarityTo: Create(.03, .05, .08, .12, .16),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Minor_CritChance_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_CritChance_Flat",
+ Attribute: CombatAttribute.CritChance,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(.02, .04, .06, .09, .13),
+ SecondaryStatByRarityTo: Create(.03, .05, .08, .12, .16),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Minor_CritBoost_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_CritBoost_Flat",
+ Attribute: CombatAttribute.CritBoost,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(.02, .04, .06, .09, .13),
+ SecondaryStatByRarityTo: Create(.03, .05, .08, .12, .16),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Minor_Defense_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_Defense_Flat",
+ Attribute: CombatAttribute.Defense,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(40.0, 100.0, 170.0, 280.0, 380.0),
+ SecondaryStatByRarityTo: Create(60.0, 120.0, 210.0, 330.0, 480.0),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Minor_Defense_Perc
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_Defense_Perc",
+ Attribute: CombatAttribute.Defense,
+ ModifierType: AttributeModifierType.Percentage,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(.02, .04, .06, .09, .13),
+ SecondaryStatByRarityTo: Create(.03, .05, .08, .12, .16),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Minor_HullPoints_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_HullPoints_Flat",
+ Attribute: CombatAttribute.HullPoints,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(170.0, 390.0, 700.0, 1000.0, 1400.0),
+ SecondaryStatByRarityTo: Create(230.0, 450.0, 780.0, 1200.0, 1800.0),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Minor_HullPoints_Perc
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_HullPoints_Perc",
+ Attribute: CombatAttribute.HullPoints,
+ ModifierType: AttributeModifierType.Percentage,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(.02, .04, .06, .09, .13),
+ SecondaryStatByRarityTo: Create(.03, .05, .08, .12, .16),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Minor_Manipulation_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_Manipulation_Flat",
+ Attribute: CombatAttribute.Manipulation,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(2.0, 4.0, 6.0, 8.0, 10.0),
+ SecondaryStatByRarityTo: Create(3.0, 5.0, 7.0, 9.0, 12.0),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Minor_Security_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_Security_Flat",
+ Attribute: CombatAttribute.Security,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(2.0, 4.0, 6.0, 8.0, 10.0),
+ SecondaryStatByRarityTo: Create(3.0, 5.0, 7.0, 9.0, 12.0),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Minor_Initiative_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Minor_Initiative_Flat",
+ Attribute: CombatAttribute.Initiative,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(2.0, 4.0, 6.0, 8.0, 10.0),
+ SecondaryStatByRarityTo: Create(3.0, 5.0, 7.0, 9.0, 12.0),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Major_Power_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Major_Power_Flat",
+ Attribute: CombatAttribute.Power,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(40.0, 70.0, 130.0, 220.0, 340.0),
+ SecondaryStatByRarityTo: Create(50.0, 100.0, 170.0, 270.0, 400.0),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Major_Power_Perc
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Major_Power_Perc",
+ Attribute: CombatAttribute.Power,
+ ModifierType: AttributeModifierType.Percentage,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(.03, .05, .07, .1, .16),
+ SecondaryStatByRarityTo: Create(.04, .06, .09, .15, .2),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Major_CritChance_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Major_CritChance_Flat",
+ Attribute: CombatAttribute.CritChance,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(.03, .05, .07, .1, .16),
+ SecondaryStatByRarityTo: Create(.04, .06, .09, .15, .2),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Major_CritBoost_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Major_CritBoost_Flat",
+ Attribute: CombatAttribute.CritBoost,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(.03, .05, .07, .1, .16),
+ SecondaryStatByRarityTo: Create(.04, .06, .09, .15, .2),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Major_Defense_Flat
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Major_Defense_Flat",
+ Attribute: CombatAttribute.Defense,
+ ModifierType: AttributeModifierType.Flat,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom: Create(50.0, 120.0, 200.0, 340.0, 460.0),
+ SecondaryStatByRarityTo: Create(70.0, 140.0, 250.0, 400.0, 580.0),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+
+ public static class Major_Defense_Perc
+ {
+ public static readonly UnitEquipmentAttributeDefinition Instance = new(
+ Id: "Major_Defense_Perc",
+ Attribute: CombatAttribute.Defense,
+ ModifierType: AttributeModifierType.Percentage,
+ PrimaryStatsByLevel: null,
+ SecondaryStatByRarityFrom1: Create(.03, .05, .07, .1, .16),
+ SecondaryStatByRarityTo: Create(.04, .06, .09, .15, .2),
+ CalibrationStatsByLevel: null,
+ UnitEquipmentSubType: UnitEquipmentSubType.Implant);
+ }
+}
+
extern alias libAlias=other_library.dll;
class myClass
@@ -18522,4 +18769,4 @@ static int Main()
int x = 0;
#if A == A\
-
+
\ No newline at end of file
diff --git a/src/Compilers/Core/CodeAnalysisTest/InternalUtilities/EnumerableExtensionsTests.cs b/src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/EnumerableExtensionsTests.cs
similarity index 100%
rename from src/Compilers/Core/CodeAnalysisTest/InternalUtilities/EnumerableExtensionsTests.cs
rename to src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/EnumerableExtensionsTests.cs
diff --git a/src/Compilers/Core/CodeAnalysisTest/Collections/ImmutableArrayExtensionsTests.cs b/src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/ImmutableArrayExtensionsTests.cs
similarity index 91%
rename from src/Compilers/Core/CodeAnalysisTest/Collections/ImmutableArrayExtensionsTests.cs
rename to src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/ImmutableArrayExtensionsTests.cs
index 537dd761567aa..12df4b9146bd1 100644
--- a/src/Compilers/Core/CodeAnalysisTest/Collections/ImmutableArrayExtensionsTests.cs
+++ b/src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/ImmutableArrayExtensionsTests.cs
@@ -7,13 +7,12 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
-using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Test.Utilities;
using Xunit;
-namespace Microsoft.CodeAnalysis.UnitTests.Collections
+namespace Microsoft.CodeAnalysis.UnitTests
{
public class ImmutableArrayExtensionsTests
{
@@ -544,5 +543,47 @@ public void IsSubsetOf_Equal(int[] array, int[] other)
Assert.True(array.ToImmutableArray().IsSubsetOf(other.ToImmutableArray()));
Assert.True(other.ToImmutableArray().IsSubsetOf(array.ToImmutableArray()));
}
+
+ public sealed class Comparer(Func equals, Func hashCode) : IEqualityComparer
+ {
+ private readonly Func _equals = equals;
+ private readonly Func _hashCode = hashCode;
+
+ public bool Equals(T x, T y) => _equals(x, y);
+ public int GetHashCode(T obj) => _hashCode(obj);
+ }
+
+ [Fact]
+ public void HasDuplicates()
+ {
+ var comparer = new Comparer((x, y) => x % 10 == y % 10, x => (x % 10).GetHashCode());
+
+ Assert.False(ImmutableArray.Empty.HasDuplicates());
+ Assert.False(ImmutableArray.Empty.HasDuplicates(comparer));
+ Assert.False(ImmutableArray.Empty.HasDuplicates(i => i + 1));
+
+ Assert.False(ImmutableArray.Create(1).HasDuplicates());
+ Assert.False(ImmutableArray.Create(1).HasDuplicates(comparer));
+ Assert.False(ImmutableArray.Create(1).HasDuplicates(i => i + 1));
+
+ Assert.False(ImmutableArray.Create(1, 2).HasDuplicates());
+ Assert.False(ImmutableArray.Create(1, 2).HasDuplicates(comparer));
+ Assert.False(ImmutableArray.Create(1, 2).HasDuplicates(i => i + 1));
+
+ Assert.True(ImmutableArray.Create(1, 1).HasDuplicates());
+ Assert.True(ImmutableArray.Create(11, 1).HasDuplicates(comparer));
+ Assert.True(ImmutableArray.Create(1, 3).HasDuplicates(i => i % 2));
+ Assert.True(ImmutableArray.Create(11.0, 1.2).HasDuplicates(i => (int)i, comparer));
+
+ Assert.False(ImmutableArray.Create(2, 0, 1, 3).HasDuplicates());
+ Assert.False(ImmutableArray.Create(2, 0, 1, 13).HasDuplicates(comparer));
+ Assert.False(ImmutableArray.Create(2, 0, 1, 53).HasDuplicates(i => i % 10));
+ Assert.False(ImmutableArray.Create(2.3, 0.1, 1.3, 53.4).HasDuplicates(i => (int)i, comparer));
+
+ Assert.True(ImmutableArray.Create(2, 0, 1, 2).HasDuplicates());
+ Assert.True(ImmutableArray.Create(2, 0, 1, 12).HasDuplicates(comparer));
+ Assert.True(ImmutableArray.Create(2, 0, 1, 52).HasDuplicates(i => i % 10));
+ Assert.True(ImmutableArray.Create(2.3, 0.1, 1.3, 52.4).HasDuplicates(i => (int)i, comparer));
+ }
}
}
diff --git a/src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/ListExtensionsTests.cs b/src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/ListExtensionsTests.cs
new file mode 100644
index 0000000000000..6e324819dfcdf
--- /dev/null
+++ b/src/Compilers/Core/CodeAnalysisTest/Collections/Extensions/ListExtensionsTests.cs
@@ -0,0 +1,58 @@
+// 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.
+
+#nullable disable
+
+using System;
+using System.Collections.Generic;
+using Roslyn.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.UnitTests;
+
+public class ListExtensionsTests
+{
+ public sealed class Comparer(Func equals, Func hashCode) : IEqualityComparer
+ {
+ private readonly Func _equals = equals;
+ private readonly Func _hashCode = hashCode;
+
+ public bool Equals(T x, T y) => _equals(x, y);
+ public int GetHashCode(T obj) => _hashCode(obj);
+ }
+
+ [Fact]
+ public void HasDuplicates()
+ {
+ var comparer = new Comparer((x, y) => x % 10 == y % 10, x => (x % 10).GetHashCode());
+
+ Assert.False(new int[0].HasDuplicates());
+ Assert.False(new int[0].HasDuplicates(comparer));
+ Assert.False(new int[0].HasDuplicates(i => i + 1));
+
+ Assert.False(new[] { 1 }.HasDuplicates());
+ Assert.False(new[] { 1 }.HasDuplicates(comparer));
+ Assert.False(new[] { 1 }.HasDuplicates(i => i + 1));
+
+ Assert.False(new[] { 1, 2 }.HasDuplicates());
+ Assert.False(new[] { 1, 2 }.HasDuplicates(comparer));
+ Assert.False(new[] { 1, 2 }.HasDuplicates(i => i + 1));
+
+ Assert.True(new[] { 1, 1 }.HasDuplicates());
+ Assert.True(new[] { 11, 1 }.HasDuplicates(comparer));
+ Assert.True(new[] { 1, 3 }.HasDuplicates(i => i % 2));
+ Assert.True(new[] { 11.0, 1.2 }.HasDuplicates(i => (int)i, comparer));
+
+ Assert.False(new[] { 2, 0, 1, 3 }.HasDuplicates());
+ Assert.False(new[] { 2, 0, 1, 13 }.HasDuplicates(comparer));
+ Assert.False(new[] { 2, 0, 1, 53 }.HasDuplicates(i => i % 10));
+ Assert.False(new[] { 2.3, 0.1, 1.3, 53.4 }.HasDuplicates(i => (int)i, comparer));
+
+ Assert.True(new[] { 2, 0, 1, 2 }.HasDuplicates());
+ Assert.True(new[] { 2, 0, 1, 12 }.HasDuplicates(comparer));
+ Assert.True(new[] { 2, 0, 1, 52 }.HasDuplicates(i => i % 10));
+ Assert.True(new[] { 2.3, 0.1, 1.3, 52.4 }.HasDuplicates(i => (int)i, comparer));
+ }
+}
+
diff --git a/src/Compilers/Core/CodeAnalysisTest/Collections/List/IEnumerable.Generic.Tests.cs b/src/Compilers/Core/CodeAnalysisTest/Collections/List/IEnumerable.Generic.Tests.cs
index 63b1cc00bafbe..13d7735555a29 100644
--- a/src/Compilers/Core/CodeAnalysisTest/Collections/List/IEnumerable.Generic.Tests.cs
+++ b/src/Compilers/Core/CodeAnalysisTest/Collections/List/IEnumerable.Generic.Tests.cs
@@ -155,37 +155,6 @@ private void RepeatTest(
RepeatTest((e, i, it) => testCode(e, i), iters);
}
- private void VerifyModifiedEnumerator(
- IEnumerator enumerator,
- object expectedCurrent,
- bool expectCurrentThrow,
- bool atEnd)
- {
- if (expectCurrentThrow)
- {
- Assert.Throws(
- () => enumerator.Current);
- }
- else
- {
- object? current = enumerator.Current;
- for (int i = 0; i < 3; i++)
- {
- Assert.Equal(expectedCurrent, current);
- current = enumerator.Current;
- }
- }
-
- Assert.Throws(
- () => enumerator.MoveNext());
-
- if (!!ResetImplemented)
- {
- Assert.Throws(
- () => enumerator.Reset());
- }
- }
-
private void VerifyEnumerator(
IEnumerator enumerator,
T[] expectedItems)
diff --git a/src/Compilers/Core/Portable/CodeAnalysisEventSource.Common.cs b/src/Compilers/Core/Portable/CodeAnalysisEventSource.Common.cs
index b8e9e1df6ab39..4e3dba61cd567 100644
--- a/src/Compilers/Core/Portable/CodeAnalysisEventSource.Common.cs
+++ b/src/Compilers/Core/Portable/CodeAnalysisEventSource.Common.cs
@@ -11,8 +11,9 @@ internal sealed partial class CodeAnalysisEventSource : EventSource
{
public static class Keywords
{
- public const EventKeywords Performance = (EventKeywords)1;
- public const EventKeywords Correctness = (EventKeywords)2;
+ public const EventKeywords Performance = (EventKeywords)0b001;
+ public const EventKeywords Correctness = (EventKeywords)0b010;
+ public const EventKeywords AnalyzerLoading = (EventKeywords)0b100;
}
public static class Tasks
@@ -100,18 +101,87 @@ internal unsafe void NodeTransform(int nodeHashCode, string name, string tableTy
[Event(8, Message = "Server compilation {0} completed", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.Compilation)]
internal void StopServerCompilation(string name) => WriteEvent(8, name);
- [Event(9, Message = "ALC for directory '{0}' created", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Start, Task = Tasks.AnalyzerAssemblyLoader)]
- internal void CreateAssemblyLoadContext(string directory) => WriteEvent(9, directory);
+ [Event(9, Message = "ALC for directory '{0}' created", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational, Opcode = EventOpcode.Start, Task = Tasks.AnalyzerAssemblyLoader)]
+ internal void CreateAssemblyLoadContext(string directory, string? alc) => WriteEvent(9, directory, alc);
- [Event(10, Message = "ALC for directory '{0}' disposed", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)]
- internal void DisposeAssemblyLoadContext(string directory) => WriteEvent(10, directory);
+ [Event(10, Message = "ALC for directory '{0}' disposed", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)]
+ internal void DisposeAssemblyLoadContext(string directory, string? alc) => WriteEvent(10, directory, alc);
- [Event(11, Message = "ALC for directory '{0}' disposal failed with exception '{1}'", Keywords = Keywords.Performance, Level = EventLevel.Error, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)]
- internal void DisposeAssemblyLoadContextException(string directory, string errorMessage) => WriteEvent(11, directory, errorMessage);
+ [Event(11, Message = "ALC for directory '{0}' disposal failed with exception '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Error, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)]
+ internal void DisposeAssemblyLoadContextException(string directory, string errorMessage, string? alc) => WriteEvent(11, directory, errorMessage, alc);
- [Event(12, Message = "CreateNonLockingLoader", Keywords = Keywords.Performance, Level = EventLevel.Informational, Task = Tasks.AnalyzerAssemblyLoader)]
+ [Event(12, Message = "CreateNonLockingLoader", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational, Task = Tasks.AnalyzerAssemblyLoader)]
internal void CreateNonLockingLoader(string directory) => WriteEvent(12, directory);
+ [Event(13, Message = "Request add Analyzer reference '{0}' to project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
+ internal void AnalyzerReferenceRequestAddToProject(string path, string projectName) => WriteEvent(13, path, projectName);
+
+ [Event(14, Message = "Analyzer reference '{0}' was added to project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
+ internal void AnalyzerReferenceAddedToProject(string path, string projectName) => WriteEvent(14, path, projectName);
+
+ [Event(15, Message = "Request remove Analyzer reference '{0}' from project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
+ internal void AnalyzerReferenceRequestRemoveFromProject(string path, string projectName) => WriteEvent(15, path, projectName);
+
+ [Event(16, Message = "Analyzer reference '{0}' was removed from project '{1}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
+ internal void AnalyzerReferenceRemovedFromProject(string path, string projectName) => WriteEvent(16, path, projectName);
+
+ [Event(17, Message = "Analyzer reference was redirected by '{0}' from '{1}' to '{2}' for project '{3}'", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Verbose, Task = Tasks.BuildStateTable)]
+ internal unsafe void AnanlyzerReferenceRedirected(string redirectorType, string originalPath, string newPath, string project)
+ {
+ if (IsEnabled())
+ {
+ fixed (char* redirectorTypeBytes = redirectorType)
+ fixed (char* originalPathBytes = originalPath)
+ fixed (char* newPathBytes = newPath)
+ fixed (char* projectBytes = project)
+ {
+ Span data =
+ [
+ GetEventDataForString(redirectorType, redirectorTypeBytes),
+ GetEventDataForString(originalPath, originalPathBytes),
+ GetEventDataForString(newPath, newPathBytes),
+ GetEventDataForString(project, projectBytes),
+ ];
+
+ fixed (EventData* dataPtr = data)
+ {
+ WriteEventCore(eventId: 17, data.Length, dataPtr);
+ }
+ }
+ }
+ }
+
+ [Event(18, Message = "ALC for directory '{0}': Assembly '{1}' was resolved by '{2}' ", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
+ internal unsafe void ResolvedAssembly(string directory, string assemblyName, string resolver, string filePath, string alc)
+ {
+ if (IsEnabled())
+ {
+ fixed (char* directoryBytes = directory)
+ fixed (char* assemblyNameBytes = assemblyName)
+ fixed (char* resolverBytes = resolver)
+ fixed (char* filePathBytes = filePath)
+ fixed (char* alcBytes = alc)
+ {
+ Span data =
+ [
+ GetEventDataForString(directory, directoryBytes),
+ GetEventDataForString(assemblyName, assemblyNameBytes),
+ GetEventDataForString(resolver, resolverBytes),
+ GetEventDataForString(filePath, filePathBytes),
+ GetEventDataForString(alc, alcBytes),
+ ];
+
+ fixed (EventData* dataPtr = data)
+ {
+ WriteEventCore(eventId: 18, data.Length, dataPtr);
+ }
+ }
+ }
+ }
+
+ [Event(19, Message = "ALC for directory '{0}': Failed to resolve assembly '{1}' ", Keywords = Keywords.AnalyzerLoading, Level = EventLevel.Informational)]
+ internal unsafe void ResolveAssemblyFailed(string directory, string assemblyName) => WriteEvent(19, directory, assemblyName);
+
private static unsafe EventData GetEventDataForString(string value, char* ptr)
{
fixed (char* ptr2 = value)
diff --git a/src/Compilers/Core/Portable/CodeGen/ILBuilder.cs b/src/Compilers/Core/Portable/CodeGen/ILBuilder.cs
index 3d7af82151476..b79e41b9ac324 100644
--- a/src/Compilers/Core/Portable/CodeGen/ILBuilder.cs
+++ b/src/Compilers/Core/Portable/CodeGen/ILBuilder.cs
@@ -1277,11 +1277,11 @@ public int GetILOffsetFromMarker(int ilMarker)
private string GetDebuggerDisplay()
{
#if DEBUG
- var visType = Type.GetType("Roslyn.Test.Utilities.ILBuilderVisualizer, Roslyn.Test.Utilities", false);
+ var visType = Type.GetType("Roslyn.Test.Utilities.ILBuilderVisualizer, Microsoft.CodeAnalysis.Test.Utilities", false);
if (visType != null)
{
var method = visType.GetTypeInfo().GetDeclaredMethod("ILBuilderToString");
- return (string)method!.Invoke(null, [this, null, null])!;
+ return (string)method!.Invoke(null, [this, null, null, null])!;
}
#endif
diff --git a/src/Compilers/Core/Portable/CommandLine/CommandLineArguments.cs b/src/Compilers/Core/Portable/CommandLine/CommandLineArguments.cs
index cc79c598cd69f..75ae0055ff582 100644
--- a/src/Compilers/Core/Portable/CommandLine/CommandLineArguments.cs
+++ b/src/Compilers/Core/Portable/CommandLine/CommandLineArguments.cs
@@ -239,9 +239,9 @@ public abstract class CommandLineArguments
public bool NoWin32Manifest { get; internal set; }
///
- /// Resources specified as arguments to the compilation.
+ /// Manifest resource information parsed from /resource arguments.
///
- public ImmutableArray ManifestResources { get; internal set; }
+ public ImmutableArray ManifestResourceArguments { get; internal set; }
///
/// Encoding to be used for source files or 'null' for autodetect/default.
@@ -308,13 +308,24 @@ public CompilationOptions CompilationOptions
///
public CultureInfo? PreferredUILang { get; internal set; }
+ // Cache the values so that underlying file streams are not created multiple times for the same files.
+ private readonly Lazy> _lazyManifestResources;
+
internal StrongNameProvider GetStrongNameProvider(StrongNameFileSystem fileSystem)
=> new DesktopStrongNameProvider(KeyFileSearchPaths, fileSystem);
internal CommandLineArguments()
{
+ _lazyManifestResources = new Lazy>(
+ () => ManifestResourceArguments.SelectAsArray(static r => r.ToDescription()));
}
+ ///
+ /// Resources specified as arguments to the compilation.
+ ///
+ public ImmutableArray ManifestResources
+ => _lazyManifestResources.Value;
+
///
/// Returns a full path of the file that the compiler will generate the assembly to if compilation succeeds.
///
diff --git a/src/Compilers/Core/Portable/CommandLine/CommandLineParser.cs b/src/Compilers/Core/Portable/CommandLine/CommandLineParser.cs
index f591e49836df7..ac05da9bf7f0d 100644
--- a/src/Compilers/Core/Portable/CommandLine/CommandLineParser.cs
+++ b/src/Compilers/Core/Portable/CommandLine/CommandLineParser.cs
@@ -822,21 +822,24 @@ static bool isClientArgsOption(string arg, string optionName, out bool hasValue,
private static readonly char[] s_resourceSeparators = { ',' };
- internal static void ParseResourceDescription(
+ internal static bool TryParseResourceDescription(
ReadOnlyMemory resourceDescriptor,
string? baseDirectory,
- bool skipLeadingSeparators, //VB does this
- out string? filePath,
- out string? fullPath,
- out string? fileName,
- out string resourceName,
- out string? accessibility)
+ bool skipLeadingSeparators, // VB does this
+ bool allowEmptyAccessibility, // VB does this
+ [NotNullWhen(true)] out string? filePath,
+ [NotNullWhen(true)] out string? fullPath,
+ [NotNullWhen(true)] out string? fileName,
+ [NotNullWhen(true)] out string? resourceName,
+ [NotNullWhen(true)] out bool? isPublic,
+ out string? rawAccessibility)
{
filePath = null;
fullPath = null;
fileName = null;
- resourceName = "";
- accessibility = null;
+ resourceName = null;
+ isPublic = null;
+ rawAccessibility = null;
// resource descriptor is: "[,[,public|private]]"
var parts = ArrayBuilder>.GetInstance();
@@ -867,17 +870,41 @@ internal static void ParseResourceDescription(
if (length >= 3)
{
- accessibility = RemoveQuotesAndSlashes(parts[offset + 2]);
+ rawAccessibility = RemoveQuotesAndSlashes(parts[offset + 2]);
+ }
+
+ if (rawAccessibility == null || rawAccessibility == "" && allowEmptyAccessibility)
+ {
+ // If no accessibility is given, we default to "public".
+ // NOTE: Dev10 distinguishes between null and empty.
+ isPublic = true;
+ }
+ else if (string.Equals(rawAccessibility, "public", StringComparison.OrdinalIgnoreCase))
+ {
+ isPublic = true;
+ }
+ else if (string.Equals(rawAccessibility, "private", StringComparison.OrdinalIgnoreCase))
+ {
+ isPublic = false;
+ }
+ else
+ {
+ isPublic = null;
}
parts.Free();
- if (RoslynString.IsNullOrWhiteSpace(filePath))
+
+ if (isPublic == null || RoslynString.IsNullOrWhiteSpace(filePath))
{
- return;
+ return false;
}
fileName = PathUtilities.GetFileName(filePath);
fullPath = FileUtilities.ResolveRelativePath(filePath, baseDirectory);
+ if (!PathUtilities.IsValidFilePath(fullPath))
+ {
+ return false;
+ }
// The default resource name is the file name.
// Also use the file name for the name when user specifies string like "filePath,,private"
@@ -885,6 +912,8 @@ internal static void ParseResourceDescription(
{
resourceName = fileName;
}
+
+ return true;
}
///
diff --git a/src/Compilers/Core/Portable/CommandLine/CommandLineResource.cs b/src/Compilers/Core/Portable/CommandLine/CommandLineResource.cs
new file mode 100644
index 0000000000000..d3e6900bb3953
--- /dev/null
+++ b/src/Compilers/Core/Portable/CommandLine/CommandLineResource.cs
@@ -0,0 +1,79 @@
+// 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.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using Roslyn.Utilities;
+
+namespace Microsoft.CodeAnalysis;
+
+///
+/// Describes a manifest resource specification stored in command line arguments.
+///
+public readonly struct CommandLineResource
+{
+ ///
+ /// Name of the manifest resource as it appears in metadata.
+ ///
+ public string ResourceName { get; }
+
+ ///
+ /// Full path to the resource content file.
+ ///
+ public string FullPath { get; }
+
+ ///
+ /// Accessibility of the resource.
+ ///
+ public bool IsPublic { get; }
+
+ ///
+ /// File name of a linked resource, or null if the resource is embedded.
+ ///
+ public string? LinkedResourceFileName { get; }
+
+ internal CommandLineResource(string resourceName, string fullPath, string? linkedResourceFileName, bool isPublic)
+ {
+ Debug.Assert(!resourceName.IsEmpty());
+ Debug.Assert(PathUtilities.IsAbsolute(fullPath));
+
+ ResourceName = resourceName;
+ FullPath = fullPath;
+ LinkedResourceFileName = linkedResourceFileName;
+ IsPublic = isPublic;
+ }
+
+ ///
+ /// True if the resource is embedded.
+ ///
+ public bool IsEmbedded
+ => LinkedResourceFileName == null;
+
+ ///
+ /// True if the resource is linked.
+ ///
+ [MemberNotNullWhen(true, nameof(LinkedResourceFileName))]
+ public bool IsLinked
+ => LinkedResourceFileName != null;
+
+ ///
+ /// Creates for this resource.
+ ///
+ internal ResourceDescription ToDescription()
+ {
+ // fail fast if the method is called on default(CommandLineResource)
+ var fullPath = FullPath ?? throw new NullReferenceException();
+
+ Func dataProvider = () =>
+ {
+ // Use FileShare.ReadWrite because the file could be opened by the current process.
+ // For example, it is an XML doc file produced by the build.
+ return new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ };
+
+ return new ResourceDescription(ResourceName, LinkedResourceFileName, dataProvider, IsPublic, isEmbedded: IsEmbedded, checkArgs: false);
+ }
+}
diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs
index a4b6fb9a55513..1fe98873aa0da 100644
--- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs
+++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs
@@ -87,8 +87,8 @@ private partial Assembly Load(AssemblyName assemblyName, string resolvedPath)
{
if (!_loadContextByDirectory.TryGetValue(fullDirectoryPath, out loadContext))
{
- CodeAnalysisEventSource.Log.CreateAssemblyLoadContext(fullDirectoryPath);
loadContext = new DirectoryLoadContext(fullDirectoryPath, this);
+ CodeAnalysisEventSource.Log.CreateAssemblyLoadContext(fullDirectoryPath, loadContext.ToString());
_loadContextByDirectory[fullDirectoryPath] = loadContext;
}
}
@@ -179,11 +179,11 @@ private partial void DisposeWorker()
try
{
context.Unload();
- CodeAnalysisEventSource.Log.DisposeAssemblyLoadContext(context.Directory);
+ CodeAnalysisEventSource.Log.DisposeAssemblyLoadContext(context.Directory, context.ToString());
}
catch (Exception ex) when (FatalError.ReportAndCatch(ex, ErrorSeverity.Critical))
{
- CodeAnalysisEventSource.Log.DisposeAssemblyLoadContextException(context.Directory, ex.ToString());
+ CodeAnalysisEventSource.Log.DisposeAssemblyLoadContextException(context.Directory, ex.ToString(), context.ToString());
}
}
@@ -209,10 +209,12 @@ public DirectoryLoadContext(string directory, AnalyzerAssemblyLoader loader)
var assembly = resolver.Resolve(_loader, assemblyName, this, Directory);
if (assembly is not null)
{
+ CodeAnalysisEventSource.Log.ResolvedAssembly(Directory, assemblyName.ToString(), resolver.GetType().Name, assembly.Location, GetLoadContext(assembly)!.ToString());
return assembly;
}
}
+ CodeAnalysisEventSource.Log.ResolveAssemblyFailed(Directory, assemblyName.ToString());
return null;
}
diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/IAnalyzerPathResolver.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/IAnalyzerPathResolver.cs
index 513b7fd7d20eb..de498db0836d2 100644
--- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/IAnalyzerPathResolver.cs
+++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/IAnalyzerPathResolver.cs
@@ -16,7 +16,7 @@
namespace Microsoft.CodeAnalysis
{
///
- /// This interface gives the host the ability to control the actaul path used to load an analyzer into the
+ /// This interface gives the host the ability to control the actual path used to load an analyzer into the
/// compiler.
///
/// Instances of these types are considered in the order they are added to the .
diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
index 20d769cfd2bd7..3dd2e0369982c 100644
--- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
+++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
@@ -1,8 +1,18 @@
+Microsoft.CodeAnalysis.CommandLineArguments.ManifestResourceArguments.get -> System.Collections.Immutable.ImmutableArray
+Microsoft.CodeAnalysis.CommandLineResource
+Microsoft.CodeAnalysis.CommandLineResource.CommandLineResource() -> void
+Microsoft.CodeAnalysis.CommandLineResource.FullPath.get -> string!
+Microsoft.CodeAnalysis.CommandLineResource.IsEmbedded.get -> bool
+Microsoft.CodeAnalysis.CommandLineResource.IsLinked.get -> bool
+Microsoft.CodeAnalysis.CommandLineResource.IsPublic.get -> bool
+Microsoft.CodeAnalysis.CommandLineResource.LinkedResourceFileName.get -> string?
+Microsoft.CodeAnalysis.CommandLineResource.ResourceName.get -> string!
Microsoft.CodeAnalysis.Compilation.EmitDifference(Microsoft.CodeAnalysis.Emit.EmitBaseline! baseline, System.Collections.Generic.IEnumerable! edits, System.Func! isAddedSymbol, System.IO.Stream! metadataStream, System.IO.Stream! ilStream, System.IO.Stream! pdbStream, Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.Emit.EmitDifferenceResult!
Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions
Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions.EmitDifferenceOptions() -> void
Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions.EmitFieldRva.get -> bool
Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions.EmitFieldRva.init -> void
+Microsoft.CodeAnalysis.IMethodSymbol.IsIterator.get -> bool
static readonly Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions.Default -> Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions
Microsoft.CodeAnalysis.IEventSymbol.IsPartialDefinition.get -> bool
Microsoft.CodeAnalysis.IEventSymbol.PartialDefinitionPart.get -> Microsoft.CodeAnalysis.IEventSymbol?
diff --git a/src/Compilers/Core/Portable/Symbols/IMethodSymbol.cs b/src/Compilers/Core/Portable/Symbols/IMethodSymbol.cs
index 74b62ca605838..471315eee86e4 100644
--- a/src/Compilers/Core/Portable/Symbols/IMethodSymbol.cs
+++ b/src/Compilers/Core/Portable/Symbols/IMethodSymbol.cs
@@ -293,5 +293,10 @@ public interface IMethodSymbol : ISymbol
/// Returns a flag indicating whether this symbol has at least one applied/inherited conditional attribute.
///
bool IsConditional { get; }
+
+ ///
+ /// Returns if this method is a source method implemented as an iterator (either sync or async)
+ ///
+ bool IsIterator { get; }
}
}
diff --git a/src/Compilers/Core/Portable/Syntax/SyntaxTreeExtensions.cs b/src/Compilers/Core/Portable/Syntax/SyntaxTreeExtensions.cs
index 39dc59103b1ab..7422b9c1882ca 100644
--- a/src/Compilers/Core/Portable/Syntax/SyntaxTreeExtensions.cs
+++ b/src/Compilers/Core/Portable/Syntax/SyntaxTreeExtensions.cs
@@ -19,8 +19,13 @@ internal static class SyntaxTreeExtensions
[Conditional("DEBUG")]
internal static void VerifySource(this SyntaxTree tree, IEnumerable? changes = null)
{
- var root = tree.GetRoot();
- var text = tree.GetText();
+ VerifySource(tree.GetText(), tree.GetRoot(), changes);
+ }
+
+ ///
+ [Conditional("DEBUG")]
+ internal static void VerifySource(SourceText text, SyntaxNode root, IEnumerable? changes = null)
+ {
var fullSpan = new TextSpan(0, text.Length);
SyntaxNode? node = null;
diff --git a/src/Compilers/Core/RebuildTest/RebuildCommandLineTests.cs b/src/Compilers/Core/RebuildTest/RebuildCommandLineTests.cs
index fa0dee9b65980..95769465a02a9 100644
--- a/src/Compilers/Core/RebuildTest/RebuildCommandLineTests.cs
+++ b/src/Compilers/Core/RebuildTest/RebuildCommandLineTests.cs
@@ -38,11 +38,6 @@ private void AddSourceFile(string filePath, string content)
FilePathToStreamMap.Add(Path.Combine(BuildPaths.WorkingDirectory, filePath), new TestableFile(content));
}
- private void AddReference(string filePath, byte[] imageBytes)
- {
- FilePathToStreamMap.Add(Path.Combine(BuildPaths.SdkDirectory!, filePath), new TestableFile(imageBytes));
- }
-
private void AddOutputFile(ref string? filePath)
{
if (filePath is object)
diff --git a/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs b/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs
index 32f881abf5f02..d5874d984e045 100644
--- a/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs
+++ b/src/Compilers/Test/Core/Compilation/CompilationExtensions.cs
@@ -117,23 +117,25 @@ public static MetadataReference EmitToImageReference(
EmitOptions options = null,
bool embedInteropTypes = false,
ImmutableArray aliases = default,
- DiagnosticDescription[] expectedWarnings = null) => EmitToPortableExecutableReference(comp, options, embedInteropTypes, aliases, expectedWarnings);
+ DiagnosticDescription[] expectedWarnings = null,
+ DocumentationProvider documentation = null) => EmitToPortableExecutableReference(comp, options, embedInteropTypes, aliases, expectedWarnings, documentation);
public static PortableExecutableReference EmitToPortableExecutableReference(
this Compilation comp,
EmitOptions options = null,
bool embedInteropTypes = false,
ImmutableArray aliases = default,
- DiagnosticDescription[] expectedWarnings = null)
+ DiagnosticDescription[] expectedWarnings = null,
+ DocumentationProvider documentation = null)
{
var image = comp.EmitToArray(options, expectedWarnings: expectedWarnings);
if (comp.Options.OutputKind == OutputKind.NetModule)
{
- return ModuleMetadata.CreateFromImage(image).GetReference(display: comp.MakeSourceModuleName());
+ return ModuleMetadata.CreateFromImage(image).GetReference(documentation, display: comp.MakeSourceModuleName());
}
else
{
- return AssemblyMetadata.CreateFromImage(image).GetReference(aliases: aliases, embedInteropTypes: embedInteropTypes, display: comp.MakeSourceAssemblySimpleName());
+ return AssemblyMetadata.CreateFromImage(image).GetReference(documentation, aliases: aliases, embedInteropTypes: embedInteropTypes, display: comp.MakeSourceAssemblySimpleName());
}
}
diff --git a/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs b/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs
index 5a17d6ac9d980..8c97ecf3362ba 100644
--- a/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs
+++ b/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs
@@ -175,19 +175,6 @@ private static string GetSnippetFromSyntax(SyntaxNode syntax)
return $"'{prefix} ... {suffix}'";
}
- private static bool ShouldLogType(IOperation operation)
- {
- var operationKind = (int)operation.Kind;
-
- // Expressions
- if (operationKind >= 0x100 && operationKind < 0x400)
- {
- return true;
- }
-
- return false;
- }
-
protected void LogString(string str)
{
if (_pendingIndent)
@@ -409,11 +396,6 @@ private void VisitArray(ImmutableArray list, string header, bool logElemen
VisitArrayCommon(list, header, logElementCount, logNullForDefault, o => Visit(o));
}
- private void VisitArray(ImmutableArray list, string header, bool logElementCount, bool logNullForDefault = false)
- {
- VisitArrayCommon(list, header, logElementCount, logNullForDefault, VisitSymbolArrayElement);
- }
-
private void VisitArray(ImmutableArray list, string header, bool logElementCount, bool logNullForDefault = false)
{
VisitArrayCommon(list, header, logElementCount, logNullForDefault, VisitStringArrayElement);
diff --git a/src/Compilers/Test/Core/TestResource.resx b/src/Compilers/Test/Core/TestResource.resx
index 22f413935ce41..385fb3b385d16 100644
--- a/src/Compilers/Test/Core/TestResource.resx
+++ b/src/Compilers/Test/Core/TestResource.resx
@@ -877,6 +877,15 @@ class RawStringLiterals
""";
}
+static class Extensions
+{
+ extension(int)
+ {
+ public static void M() { }
+ public static int P => 0;
+ }
+}
+
#line 6
#line 2 "test.cs"
#line default
diff --git a/src/Compilers/Test/Core/Traits/Traits.cs b/src/Compilers/Test/Core/Traits/Traits.cs
index b5003cb91f2ed..8fa34d3fd1978 100644
--- a/src/Compilers/Test/Core/Traits/Traits.cs
+++ b/src/Compilers/Test/Core/Traits/Traits.cs
@@ -298,7 +298,6 @@ public static class Features
public const string Packaging = nameof(Packaging);
public const string PasteTracking = nameof(PasteTracking);
public const string Peek = nameof(Peek);
- public const string Progression = nameof(Progression);
public const string ProjectSystemShims = nameof(ProjectSystemShims);
public const string SarifErrorLogging = nameof(SarifErrorLogging);
public const string QuickInfo = nameof(QuickInfo);
@@ -315,6 +314,7 @@ public static class Features
public const string SmartIndent = nameof(SmartIndent);
public const string SmartTokenFormatting = nameof(SmartTokenFormatting);
public const string Snippets = nameof(Snippets);
+ public const string SolutionExplorer = nameof(SolutionExplorer);
public const string SourceGenerators = nameof(SourceGenerators);
public const string SplitComment = nameof(SplitComment);
public const string SplitStringLiteral = nameof(SplitStringLiteral);
diff --git a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb
index 70dfaf80e5cc6..707f5b985cd23 100644
--- a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb
+++ b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb
@@ -116,7 +116,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim win32ResourceFile As String = Nothing
Dim win32IconFile As String = Nothing
Dim noWin32Manifest As Boolean = False
- Dim managedResources = New List(Of ResourceDescription)()
+ Dim managedResources = New List(Of CommandLineResource)()
Dim sourceFiles = New List(Of CommandLineSourceFile)()
Dim hasSourceFiles = False
Dim additionalFiles = New List(Of CommandLineSourceFile)()
@@ -704,15 +704,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Continue For
Case "res", "resource"
- Dim embeddedResource = ParseResourceDescription(name, value, baseDirectory, diagnostics, embedded:=True)
- If embeddedResource IsNot Nothing Then
+ Dim embeddedResource As CommandLineResource
+ If TryParseResourceDescription(name, value, baseDirectory, diagnostics, isEmbedded:=True, embeddedResource) Then
managedResources.Add(embeddedResource)
End If
Continue For
Case "linkres", "linkresource"
- Dim linkedResource = ParseResourceDescription(name, value, baseDirectory, diagnostics, embedded:=False)
- If linkedResource IsNot Nothing Then
+ Dim linkedResource As CommandLineResource
+ If TryParseResourceDescription(name, value, baseDirectory, diagnostics, isEmbedded:=False, linkedResource) Then
managedResources.Add(linkedResource)
End If
Continue For
@@ -1509,7 +1509,7 @@ lVbRuntimePlus:
.DisplayHelp = displayHelp,
.DisplayVersion = displayVersion,
.DisplayLangVersions = displayLangVersions,
- .ManifestResources = managedResources.AsImmutable(),
+ .ManifestResourceArguments = managedResources.AsImmutable(),
.CompilationOptions = options,
.ParseOptions = parseOptions,
.EmitOptions = emitOptions,
@@ -1525,7 +1525,7 @@ lVbRuntimePlus:
.SkipAnalyzers = skipAnalyzers,
.EmbeddedFiles = embeddedFiles.AsImmutable(),
.GeneratedFilesOutputDirectory = generatedFilesOutputDirectory,
- .ReportInternalsVisibleToAttributes = reportIVTs
+ .ReportInternalsVisibleToAttributes = reportIvts
}
End Function
@@ -1705,10 +1705,18 @@ lVbRuntimePlus:
End Function
' See ParseCommandLine in vbc.cpp.
- Friend Overloads Shared Function ParseResourceDescription(name As String, resourceDescriptor As String, baseDirectory As String, diagnostics As IList(Of Diagnostic), embedded As Boolean) As ResourceDescription
+ Friend Overloads Shared Function TryParseResourceDescription(
+ argName As String,
+ resourceDescriptor As String,
+ baseDirectory As String,
+ diagnostics As IList(Of Diagnostic),
+ isEmbedded As Boolean,
+ ByRef resource As CommandLineResource) As Boolean
+
If String.IsNullOrEmpty(resourceDescriptor) Then
- AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, name, ":")
- Return Nothing
+ AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, argName, ":")
+ resource = Nothing
+ Return False
End If
' NOTE: these are actually passed to out parameters of .ParseResourceDescription.
@@ -1716,52 +1724,41 @@ lVbRuntimePlus:
Dim fullPath As String = Nothing
Dim fileName As String = Nothing
Dim resourceName As String = Nothing
- Dim accessibility As String = Nothing
+ Dim isPublic As Boolean? = Nothing
+ Dim rawAccessibility As String = Nothing
- ParseResourceDescription(
+ If Not TryParseResourceDescription(
resourceDescriptor.AsMemory(),
baseDirectory,
- True,
+ skipLeadingSeparators:=True,
+ allowEmptyAccessibility:=True,
filePath,
fullPath,
fileName,
resourceName,
- accessibility)
+ isPublic,
+ rawAccessibility) Then
- If String.IsNullOrWhiteSpace(filePath) Then
- AddInvalidSwitchValueDiagnostic(diagnostics, name, filePath)
- Return Nothing
- End If
+ If isPublic Is Nothing Then
+ AddInvalidSwitchValueDiagnostic(diagnostics, argName, rawAccessibility)
+ ElseIf RoslynString.IsNullOrWhiteSpace(filePath) Then
+ AddInvalidSwitchValueDiagnostic(diagnostics, argName, filePath)
+ Else
+ Debug.Assert(Not PathUtilities.IsValidFilePath(fullPath))
+ AddDiagnostic(diagnostics, ERRID.FTL_InvalidInputFileName, filePath)
+ End If
- If Not PathUtilities.IsValidFilePath(fullPath) Then
- AddDiagnostic(diagnostics, ERRID.FTL_InvalidInputFileName, filePath)
- Return Nothing
+ resource = Nothing
+ Return False
End If
- Dim isPublic As Boolean
- If String.IsNullOrEmpty(accessibility) Then
- ' If no accessibility is given, we default to "public".
- ' NOTE: Dev10 treats empty the same as null (the difference being that empty indicates a comma after the resource name).
- ' NOTE: Dev10 distinguishes between empty and whitespace-only.
- isPublic = True
- ElseIf String.Equals(accessibility, "public", StringComparison.OrdinalIgnoreCase) Then
- isPublic = True
- ElseIf String.Equals(accessibility, "private", StringComparison.OrdinalIgnoreCase) Then
- isPublic = False
- Else
- AddInvalidSwitchValueDiagnostic(diagnostics, name, accessibility)
- Return Nothing
- End If
+ resource = New CommandLineResource(
+ resourceName:=resourceName,
+ fullPath:=fullPath,
+ linkedResourceFileName:=If(isEmbedded, Nothing, fileName),
+ isPublic.Value)
- Dim dataProvider As Func(Of Stream) = Function()
- ' Use FileShare.ReadWrite because the file could be opened by the current process.
- ' For example, it Is an XML doc file produced by the build.
- Return New FileStream(fullPath,
- FileMode.Open,
- FileAccess.Read,
- FileShare.ReadWrite)
- End Function
- Return New ResourceDescription(resourceName, fileName, dataProvider, isPublic, embedded, checkArgs:=False)
+ Return True
End Function
Private Shared Sub AddInvalidSwitchValueDiagnostic(diagnostics As IList(Of Diagnostic), ByVal name As String, ByVal nullStringText As String)
diff --git a/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb b/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb
index c2905bea3bc0d..7438416a2b6a3 100644
--- a/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb
+++ b/src/Compilers/VisualBasic/Portable/Generated/BoundNodes.xml.Generated.vb
@@ -194,22 +194,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Interpolation
End Enum
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Partial Friend MustInherit Class BoundExpression
Inherits BoundNode
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb
index 215b7105d69f8..7acc4a1a228fc 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/MethodSymbol.vb
@@ -133,7 +133,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' Source: Returns whether this method is an iterator; i.e., does it have the Iterator modifier?
''' Metadata: Returns False; methods from metadata cannot be an iterator.
'''
- Public MustOverride ReadOnly Property IsIterator As Boolean
+ Public MustOverride ReadOnly Property IsIterator As Boolean Implements IMethodSymbol.IsIterator
'''
''' Indicates whether the accessor is marked with the 'init' modifier.
diff --git a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb
index b325f2d3eb235..78a0e9cea769d 100644
--- a/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb
+++ b/src/Compilers/VisualBasic/Portable/Symbols/Source/SourceAssemblySymbol.vb
@@ -519,12 +519,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Return _lazyNetModuleAttributesBag
End Function
- Private Function GetNetModuleAttributes() As ImmutableArray(Of VisualBasicAttributeData)
- Dim attributesBag = Me.GetNetModuleAttributesBag()
- Debug.Assert(attributesBag.IsSealed)
- Return attributesBag.Attributes
- End Function
-
Friend Function GetNetModuleDecodedWellKnownAttributeData() As CommonAssemblyWellKnownAttributeData
Dim attributesBag = Me.GetNetModuleAttributesBag()
Debug.Assert(attributesBag.IsSealed)
diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb
index 8841ef4e3fa67..b2cc251b377d1 100644
--- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb
+++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb
@@ -1158,180 +1158,165 @@ End Module").Path
End Sub
- Public Sub ParseResourceDescription()
+ Public Sub TryParseResourceDescription()
Dim diags = New List(Of Diagnostic)()
- Dim desc As ResourceDescription
+ Dim resource As CommandLineResource
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "\somepath\someFile.goo.bar", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "\somepath\someFile.goo.bar", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("someFile.goo.bar", desc.FileName)
- Assert.Equal("someFile.goo.bar", desc.ResourceName)
- Assert.True(desc.IsPublic)
+ Assert.Equal("someFile.goo.bar", resource.LinkedResourceFileName)
+ Assert.Equal("someFile.goo.bar", resource.ResourceName)
+ Assert.True(resource.IsPublic)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "\somepath\someFile.goo.bar,someName", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "\somepath\someFile.goo.bar,someName", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("someFile.goo.bar", desc.FileName)
- Assert.Equal("someName", desc.ResourceName)
- Assert.True(desc.IsPublic)
+ Assert.Equal("someFile.goo.bar", resource.LinkedResourceFileName)
+ Assert.Equal("someName", resource.ResourceName)
+ Assert.True(resource.IsPublic)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "\somepath\someFile.goo.bar,someName,public", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "\somepath\someFile.goo.bar,someName,public", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("someFile.goo.bar", desc.FileName)
- Assert.Equal("someName", desc.ResourceName)
- Assert.True(desc.IsPublic)
+ Assert.Equal("someFile.goo.bar", resource.LinkedResourceFileName)
+ Assert.Equal("someName", resource.ResourceName)
+ Assert.True(resource.IsPublic)
' use file name in place of missing resource name
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "\somepath\someFile.goo.bar,,private", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "\somepath\someFile.goo.bar,,private", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("someFile.goo.bar", desc.FileName)
- Assert.Equal("someFile.goo.bar", desc.ResourceName)
- Assert.False(desc.IsPublic)
+ Assert.Equal("someFile.goo.bar", resource.LinkedResourceFileName)
+ Assert.Equal("someFile.goo.bar", resource.ResourceName)
+ Assert.False(resource.IsPublic)
' quoted accessibility is fine
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "\somepath\someFile.goo.bar,,""private""", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "\somepath\someFile.goo.bar,,""private""", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("someFile.goo.bar", desc.FileName)
- Assert.Equal("someFile.goo.bar", desc.ResourceName)
- Assert.False(desc.IsPublic)
+ Assert.Equal("someFile.goo.bar", resource.LinkedResourceFileName)
+ Assert.Equal("someFile.goo.bar", resource.ResourceName)
+ Assert.False(resource.IsPublic)
' leading commas are ignored...
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", ",,\somepath\someFile.goo.bar,,private", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", ",,\somepath\someFile.goo.bar,,private", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("someFile.goo.bar", desc.FileName)
- Assert.Equal("someFile.goo.bar", desc.ResourceName)
- Assert.False(desc.IsPublic)
+ Assert.Equal("someFile.goo.bar", resource.LinkedResourceFileName)
+ Assert.Equal("someFile.goo.bar", resource.ResourceName)
+ Assert.False(resource.IsPublic)
' ...as long as there's no whitespace between them
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", ", ,\somepath\someFile.goo.bar,,private", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", ", ,\somepath\someFile.goo.bar,,private", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", " "))
diags.Clear()
- Assert.Null(desc)
' trailing commas are ignored...
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "\somepath\someFile.goo.bar,,private", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "\somepath\someFile.goo.bar,,private", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("someFile.goo.bar", desc.FileName)
- Assert.Equal("someFile.goo.bar", desc.ResourceName)
- Assert.False(desc.IsPublic)
+ Assert.Equal("someFile.goo.bar", resource.LinkedResourceFileName)
+ Assert.Equal("someFile.goo.bar", resource.ResourceName)
+ Assert.False(resource.IsPublic)
' ...even if there's whitespace between them
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "\somepath\someFile.goo.bar,,private, ,", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "\somepath\someFile.goo.bar,,private, ,", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("someFile.goo.bar", desc.FileName)
- Assert.Equal("someFile.goo.bar", desc.ResourceName)
- Assert.False(desc.IsPublic)
+ Assert.Equal("someFile.goo.bar", resource.LinkedResourceFileName)
+ Assert.Equal("someFile.goo.bar", resource.ResourceName)
+ Assert.False(resource.IsPublic)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "\somepath\someFile.goo.bar,someName,publi", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "\somepath\someFile.goo.bar,someName,publi", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", "publi"))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "D:rive\relative\path,someName,public", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "D:rive\relative\path,someName,public", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.FTL_InvalidInputFileName).WithArguments("D:rive\relative\path"))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "inva\l*d?path,someName,public", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "inva\l*d?path,someName,public", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.FTL_InvalidInputFileName).WithArguments("inva\l*d?path"))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", Nothing, _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", Nothing, _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("resource", ":"))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_ArgumentRequired).WithArguments("resource", ":"))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", " ", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", " ", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", " "))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", " , ", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", " , ", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", " "))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "path, ", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "path, ", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("path", desc.FileName)
- Assert.Equal("path", desc.ResourceName)
- Assert.True(desc.IsPublic)
+ Assert.Equal("path", resource.LinkedResourceFileName)
+ Assert.Equal("path", resource.ResourceName)
+ Assert.True(resource.IsPublic)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", " ,name", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", " ,name", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", " "))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", " , , ", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", " , , ", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", " "))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "path, , ", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "path, , ", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", " "))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", " ,name, ", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", " ,name, ", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", " "))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", " , ,private", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", " , ,private", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", " "))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "path,name,", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "path,name,", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("path", desc.FileName)
- Assert.Equal("name", desc.ResourceName)
- Assert.True(desc.IsPublic)
+ Assert.Equal("path", resource.LinkedResourceFileName)
+ Assert.Equal("name", resource.ResourceName)
+ Assert.True(resource.IsPublic)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "path,name,,", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "path,name,,", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("path", desc.FileName)
- Assert.Equal("name", desc.ResourceName)
- Assert.True(desc.IsPublic)
+ Assert.Equal("path", resource.LinkedResourceFileName)
+ Assert.Equal("name", resource.ResourceName)
+ Assert.True(resource.IsPublic)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "path,name, ", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "path,name, ", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", " "))
diags.Clear()
- Assert.Null(desc)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", "path, ,private", _baseDirectory, diags, embedded:=False)
+ Assert.True(VisualBasicCommandLineParser.TryParseResourceDescription("resource", "path, ,private", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify()
diags.Clear()
- Assert.Equal("path", desc.FileName)
- Assert.Equal("path", desc.ResourceName)
- Assert.False(desc.IsPublic)
+ Assert.Equal("path", resource.LinkedResourceFileName)
+ Assert.Equal("path", resource.ResourceName)
+ Assert.False(resource.IsPublic)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("resource", " ,name,private", _baseDirectory, diags, embedded:=False)
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("resource", " ,name,private", _baseDirectory, diags, isEmbedded:=False, resource))
diags.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("resource", " "))
diags.Clear()
- Assert.Null(desc)
Dim longI = New String("i"c, 260)
- desc = VisualBasicCommandLineParser.ParseResourceDescription("", String.Format("{0},e,private", longI), _baseDirectory, diags, embedded:=False)
- ' // error BC2032: File name 'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii' is empty, contains invalid characters, has a drive specification without an absolute path, or is too long
- diags.Verify(Diagnostic(ERRID.FTL_InvalidInputFileName).WithArguments("iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii").WithLocation(1, 1))
+ Assert.False(VisualBasicCommandLineParser.TryParseResourceDescription("", String.Format("{0},e,private", longI), _baseDirectory, diags, isEmbedded:=False, resource))
+ ' // error BC2032: File name '...' is empty, contains invalid characters, has a drive specification without an absolute path, or is too long
+ diags.Verify(Diagnostic(ERRID.FTL_InvalidInputFileName).WithArguments(longI).WithLocation(1, 1))
End Sub
diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/IteratorTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/IteratorTests.vb
index 9eb87de985e30..6e5e0876ee2d4 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/IteratorTests.vb
+++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/IteratorTests.vb
@@ -2,7 +2,9 @@
' The .NET Foundation licenses this file to you under the MIT license.
' See the LICENSE file in the project root for more information.
+Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
+Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Test.Utilities
@@ -12,6 +14,75 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Public Class IteratorTests
Inherits FlowTestBase
+
+ Public Sub BasicIterator()
+ Dim compilation = CreateCompilation(
+
+
+
+
+ ).VerifyDiagnostics()
+
+ Dim i = compilation.GetMember(Of MethodSymbol)("C.I")
+ Assert.True(i.IsIterator)
+ Assert.True(DirectCast(i, IMethodSymbol).IsIterator)
+ End Sub
+
+
+ Public Sub BasicIterator_Metadata()
+ Dim sourceComp = CreateCompilation(
+
+
+
+
+ ).VerifyDiagnostics()
+
+ Dim userComp = CreateCompilation("", references:={sourceComp.EmitToImageReference()}).VerifyDiagnostics()
+ Dim cMetadataType = Assert.IsAssignableFrom(Of PENamedTypeSymbol)(userComp.GetTypeByMetadataName("C"))
+
+ Dim i = cMetadataType.GetMethod("I")
+ Assert.False(i.IsIterator)
+ Assert.False(DirectCast(i, IMethodSymbol).IsIterator)
+ End Sub
+
+
+ Public Sub Method_NotIterator()
+ Dim compilation = CreateCompilation(
+
+
+
+
+ ).VerifyDiagnostics()
+
+ Dim i = compilation.GetMember(Of MethodSymbol)("C.I")
+ Assert.False(i.IsIterator)
+ Assert.False(DirectCast(i, IMethodSymbol).IsIterator)
+ End Sub
+
Public Sub IteratorNoYields()
Dim compilation = CreateCompilationWithMscorlib40AndVBRuntime(
@@ -978,6 +1049,28 @@ End Class
CompileAndVerify(compilation.WithOptions(TestOptions.ReleaseExe), expected)
End Sub
+
+ Public Sub SimpleIteratorProperty()
+ Dim compilation = CreateCompilation(
+
+
+).VerifyDiagnostics()
+
+ Dim [property] = compilation.GetMember(Of PropertySymbol)("C.P")
+ Assert.True([property].GetMethod.IsIterator)
+ Assert.True(DirectCast([property].GetMethod, IMethodSymbol).IsIterator)
+ End Sub
+
@@ -1016,13 +1109,64 @@ End Class
compilation.AssertTheseEmitDiagnostics()
Dim [property] = compilation.GetMember(Of PropertySymbol)("A.P")
Assert.True([property].GetMethod.IsIterator)
+ Assert.True(DirectCast([property].GetMethod, IMethodSymbol).IsIterator)
Assert.False([property].SetMethod.IsIterator)
+ Assert.False(DirectCast([property].SetMethod, IMethodSymbol).IsIterator)
[property] = compilation.GetMember(Of PropertySymbol)("B.P")
Assert.True([property].GetMethod.IsIterator)
+ Assert.True(DirectCast([property].GetMethod, IMethodSymbol).IsIterator)
Assert.False([property].SetMethod.IsIterator)
+ Assert.False(DirectCast([property].SetMethod, IMethodSymbol).IsIterator)
CompileAndVerify(compilation, expectedOutput:="123")
End Sub
+
+ Public Sub IteratorProperty_Metadata()
+ Dim sourceComp = CreateCompilation(
+
+
+).VerifyDiagnostics()
+
+ Dim userComp = CreateCompilation("", references:={sourceComp.EmitToImageReference()}).VerifyDiagnostics()
+ Dim cMetadataType = Assert.IsAssignableFrom(Of PENamedTypeSymbol)(userComp.GetTypeByMetadataName("C"))
+
+ Dim [property] = cMetadataType.GetProperty("P")
+ Assert.False([property].GetMethod.IsIterator)
+ Assert.False(DirectCast([property].GetMethod, IMethodSymbol).IsIterator)
+ End Sub
+
+
+ Public Sub Property_NotIterator()
+ Dim compilation = CreateCompilation(
+
+
+).VerifyDiagnostics()
+
+ Dim [property] = compilation.GetMember(Of PropertySymbol)("C.P")
+ Assert.False([property].GetMethod.IsIterator)
+ Assert.False(DirectCast([property].GetMethod, IMethodSymbol).IsIterator)
+ End Sub
+
Public Sub CompilerLoweringPreserveAttribute_01()
Dim source1 = "
diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/LambdaTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/LambdaTests.vb
index be410c2a6445f..e2cfdfb80a5ee 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/LambdaTests.vb
+++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/LambdaTests.vb
@@ -5,6 +5,7 @@
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
+Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Roslyn.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
@@ -2491,5 +2492,54 @@ End Class
CompileAndVerify(comp1, symbolValidator:=validate).VerifyDiagnostics()
End Sub
+
+ Public Sub IteratorLambda()
+ Dim compilation = CreateCompilation(
+
+
+Imports System.Collections.Generic
+
+Class C
+ Sub M()
+ Dim lambda = Iterator Function() As IEnumerable(Of Integer)
+ Yield 1
+ End Function
+ End Sub
+End Class
+
+).VerifyDiagnostics()
+
+ Dim syntaxTree = compilation.SyntaxTrees.Single()
+ Dim semanticModel = compilation.GetSemanticModel(syntaxTree)
+ Dim lambdaSyntax = syntaxTree.GetRoot().DescendantNodes().OfType(Of LambdaExpressionSyntax)().Single()
+ Dim lambdaSymbolInfo = semanticModel.GetSymbolInfo(lambdaSyntax)
+ Dim lambdaMethod As IMethodSymbol = Assert.IsAssignableFrom(Of IMethodSymbol)(lambdaSymbolInfo.Symbol)
+ Assert.True(lambdaMethod.IsIterator)
+ End Sub
+
+
+ Public Sub NotIteratorLambda()
+ Dim compilation = CreateCompilation(
+
+
+Imports System.Collections.Generic
+
+Class C
+ Sub M()
+ Dim lambda = Function() As IEnumerable(Of Integer)
+ Return Nothing
+ End Function
+ End Sub
+End Class
+
+).VerifyDiagnostics()
+
+ Dim syntaxTree = compilation.SyntaxTrees.Single()
+ Dim semanticModel = compilation.GetSemanticModel(syntaxTree)
+ Dim lambdaSyntax = syntaxTree.GetRoot().DescendantNodes().OfType(Of LambdaExpressionSyntax)().Single()
+ Dim lambdaSymbolInfo = semanticModel.GetSymbolInfo(lambdaSyntax)
+ Dim lambdaMethod As IMethodSymbol = Assert.IsAssignableFrom(Of IMethodSymbol)(lambdaSymbolInfo.Symbol)
+ Assert.False(lambdaMethod.IsIterator)
+ End Sub
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolDisplay/SymbolDisplayTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolDisplay/SymbolDisplayTests.vb
index 5c6423f123c86..2dd567fc52e14 100644
--- a/src/Compilers/VisualBasic/Test/Symbol/SymbolDisplay/SymbolDisplayTests.vb
+++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolDisplay/SymbolDisplayTests.vb
@@ -6062,7 +6062,7 @@ static class E
Dim comp As Compilation
If useMetadata Then
Dim libComp = CreateCSharpCompilation("c", text, parseOptions:=parseOptions)
- comp = CreateCSharpCompilation("d", code:="", parseOptions:=parseOptions, referencedAssemblies:={libComp.EmitToImageReference()})
+ comp = CreateCSharpCompilation("d", code:="", parseOptions:=parseOptions, referencedAssemblies:=libComp.References.Concat(libComp.EmitToImageReference()))
Else
comp = CreateCSharpCompilation("c", text, parseOptions:=parseOptions)
End If
@@ -6070,6 +6070,7 @@ static class E
Dim e = DirectCast(comp.GlobalNamespace.GetMembers("E").Single(), ITypeSymbol)
Dim extension = e.GetMembers().OfType(Of ITypeSymbol).Single()
+ Assert.True(extension.IsExtension)
Assert.Equal("E.<>E__0", SymbolDisplay.ToDisplayString(extension, format))
Dim parts = SymbolDisplay.ToDisplayParts(extension, format)
@@ -6116,7 +6117,7 @@ static class E
Dim comp As Compilation
If useMetadata Then
Dim libComp = CreateCSharpCompilation("c", text, parseOptions:=parseOptions)
- comp = CreateCSharpCompilation("d", code:="", parseOptions:=parseOptions, referencedAssemblies:={libComp.EmitToImageReference()})
+ comp = CreateCSharpCompilation("d", code:="", parseOptions:=parseOptions, referencedAssemblies:=libComp.References.Concat(libComp.EmitToImageReference()))
Else
comp = CreateCSharpCompilation("c", text, parseOptions:=parseOptions)
End If
@@ -6125,6 +6126,7 @@ static class E
Dim extension = e.GetMembers().OfType(Of ITypeSymbol).Single()
' Tracked by https://github.com/dotnet/roslyn/issues/76130 : the arity should not be included in the extension type name
+ Assert.True(extension.IsExtension)
Assert.Equal("E.<>E__0`1(Of T)", SymbolDisplay.ToDisplayString(extension, format))
Dim parts = SymbolDisplay.ToDisplayParts(extension, format)
diff --git a/src/Dependencies/Collections/Extensions/IEnumerableExtensions.cs b/src/Dependencies/Collections/Extensions/IEnumerableExtensions.cs
index 0e86991e66dea..144d037776595 100644
--- a/src/Dependencies/Collections/Extensions/IEnumerableExtensions.cs
+++ b/src/Dependencies/Collections/Extensions/IEnumerableExtensions.cs
@@ -337,6 +337,72 @@ public static bool IsEmpty(this List source)
return source.Count == 0;
}
+ public static bool HasDuplicates(this IEnumerable source)
+ => source.HasDuplicates(EqualityComparer.Default);
+
+ public static bool HasDuplicates(this IEnumerable source, IEqualityComparer comparer)
+ => source.HasDuplicates(static x => x, comparer);
+
+ public static bool HasDuplicates(this IEnumerable source, Func selector)
+ => source.HasDuplicates(selector, EqualityComparer.Default);
+
+ ///
+ /// Determines whether duplicates exist using given equality comparer.
+ ///
+ /// Array to search for duplicates
+ /// Whether duplicates were found
+ ///
+ /// API proposal: https://github.com/dotnet/runtime/issues/30582.
+ ///
+ ///
+ public static bool HasDuplicates(this IEnumerable source, Func