提交 c3b188ac 编写于 作者: M Manish Vasani

Merge remote-tracking branch 'upstream/master' into ClosedFileDiagnostics

......@@ -3,9 +3,9 @@
<ProductDependencies>
</ProductDependencies>
<ToolsetDependencies>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.19574.1">
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.19577.4">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>87b59e17420bf0c3341edacbd8a6721e619afbac</Sha>
<Sha>e103549927549c5b5b8cf02479f8e3b021037001</Sha>
</Dependency>
</ToolsetDependencies>
</Dependencies>
......@@ -187,6 +187,10 @@ function Process-Arguments() {
exit 1
}
if ($bootstrap) {
$script:restore = $true
}
$script:test32 = -not $test64
foreach ($property in $properties) {
......
......@@ -112,17 +112,18 @@ function Build {
@properties
}
if ($clean) {
if(Test-Path $ArtifactsDir) {
Remove-Item -Recurse -Force $ArtifactsDir
Write-Host 'Artifacts directory deleted.'
}
exit 0
}
try {
. $PSScriptRoot\tools.ps1
If ((Test-Path variable:LastExitCode) -And ($LastExitCode -ne 0)) {
if ($clean) {
if (Test-Path $ArtifactsDir) {
Remove-Item -Recurse -Force $ArtifactsDir
Write-Host 'Artifacts directory deleted.'
}
exit 0
}
if ((Test-Path variable:LastExitCode) -And ($LastExitCode -ne 0)) {
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message 'Eng/common/tools.ps1 returned a non-zero exit code.'
ExitWithExitCode $LastExitCode
}
......
......@@ -49,6 +49,10 @@ variables:
- name: NetCore_31_Blazor_Features_Channel_Id
value: 531
# .NET Core Experimental
- name: NetCore_Experimental_Channel_Id
value: 562
# Whether the build is internal or not
- name: IsInternalBuild
value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }}
......
......@@ -207,4 +207,17 @@ stages:
channelId: 551
transportFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json'
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json'
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal-symbols/nuget/v3/index.json'
\ No newline at end of file
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal-symbols/nuget/v3/index.json'
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
parameters:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
dependsOn: ${{ parameters.publishDependsOn }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
stageName: 'NETCore_Experimental_Publishing'
channelName: '.NET Core Experimental'
channelId: 562
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json'
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json'
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental-symbols/nuget/v3/index.json'
......@@ -247,7 +247,7 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements =
if ($msbuildCmd -ne $null) {
# Workaround for https://github.com/dotnet/roslyn/issues/35793
# Due to this issue $msbuildCmd.Version returns 0.0.0.0 for msbuild.exe 16.2+
$msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split(@('-', '+'))[0])
$msbuildVersion = [Version]::new((Get-Item $msbuildCmd.Path).VersionInfo.ProductVersion.Split([char[]]@('-', '+'))[0])
if ($msbuildVersion -ge $vsMinVersion) {
return $global:_MSBuildExe = $msbuildCmd.Path
......
......@@ -7,6 +7,6 @@
"xcopy-msbuild": "16.3.0-alpha"
},
"msbuild-sdks": {
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.19574.1"
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.19577.4"
}
}
......@@ -317,13 +317,10 @@ internal virtual GeneratedLabelSymbol ContinueLabel
/// <summary>
/// Get the element type of this iterator.
/// </summary>
/// <param name="node">Node to report diagnostics, if any, such as "yield statement cannot be used
/// inside a lambda expression"</param>
/// <param name="diagnostics">Where to place any diagnostics</param>
/// <returns>Element type of the current iterator, or an error type.</returns>
internal virtual TypeWithAnnotations GetIteratorElementType(YieldStatementSyntax node, DiagnosticBag diagnostics)
internal virtual TypeWithAnnotations GetIteratorElementType()
{
return Next.GetIteratorElementType(node, diagnostics);
return Next.GetIteratorElementType();
}
/// <summary>
......
......@@ -207,19 +207,23 @@ private void CheckRequiredLangVersionForAsyncIteratorMethods(DiagnosticBag diagn
}
}
private BoundStatement BindYieldReturnStatement(YieldStatementSyntax node, DiagnosticBag diagnostics)
protected virtual void ValidateYield(YieldStatementSyntax node, DiagnosticBag diagnostics)
{
var binder = this;
Next?.ValidateYield(node, diagnostics);
}
TypeSymbol elementType = binder.GetIteratorElementType(node, diagnostics).Type;
private BoundStatement BindYieldReturnStatement(YieldStatementSyntax node, DiagnosticBag diagnostics)
{
ValidateYield(node, diagnostics);
TypeSymbol elementType = GetIteratorElementType().Type;
BoundExpression argument = (node.Expression == null)
? BadExpression(node).MakeCompilerGenerated()
: binder.BindValue(node.Expression, diagnostics, BindValueKind.RValue);
: BindValue(node.Expression, diagnostics, BindValueKind.RValue);
argument = ValidateEscape(argument, ExternalScope, isByRef: false, diagnostics: diagnostics);
if (!argument.HasAnyErrors)
{
argument = binder.GenerateConversionForAssignment(elementType, argument, diagnostics);
argument = GenerateConversionForAssignment(elementType, argument, diagnostics);
}
else
{
......@@ -261,7 +265,7 @@ private BoundStatement BindYieldBreakStatement(YieldStatementSyntax node, Diagno
Error(diagnostics, ErrorCode.ERR_YieldNotAllowedInScript, node.YieldKeyword);
}
GetIteratorElementType(node, diagnostics);
ValidateYield(node, diagnostics);
CheckRequiredLangVersionForAsyncIteratorMethods(diagnostics);
return new BoundYieldBreakStatement(node);
}
......@@ -1700,7 +1704,7 @@ private BoundBlock BindBlockParts(BlockSyntax node, DiagnosticBag diagnostics)
var method = ContainingMemberOrLambda as MethodSymbol;
if ((object)method != null)
{
method.IteratorElementTypeWithAnnotations = GetIteratorElementType(null, diagnostics);
method.IteratorElementTypeWithAnnotations = GetIteratorElementType();
}
else
{
......
......@@ -143,7 +143,7 @@ internal override BoundExpression ConditionalReceiverExpression
// This should only be called in the context of syntactically incorrect programs. In other
// contexts statements are surrounded by some enclosing method or lambda.
internal override TypeWithAnnotations GetIteratorElementType(YieldStatementSyntax node, DiagnosticBag diagnostics)
internal override TypeWithAnnotations GetIteratorElementType()
{
// There's supposed to be an enclosing method or lambda.
throw ExceptionUtilities.Unreachable;
......
......@@ -155,16 +155,39 @@ public void ValidateIteratorMethods(DiagnosticBag diagnostics)
}
}
Location errorLocation = iterator.Locations[0];
if (iterator.IsVararg)
{
// error CS1636: __arglist is not allowed in the parameter list of iterators
diagnostics.Add(ErrorCode.ERR_VarargsIterator, iterator.Locations[0]);
diagnostics.Add(ErrorCode.ERR_VarargsIterator, errorLocation);
}
if (((iterator as SourceMemberMethodSymbol)?.IsUnsafe == true || (iterator as LocalFunctionSymbol)?.IsUnsafe == true)
&& Compilation.Options.AllowUnsafe) // Don't cascade
{
diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, iterator.Locations[0]);
diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, errorLocation);
}
var returnType = iterator.ReturnType;
RefKind refKind = iterator.RefKind;
TypeWithAnnotations elementType = InMethodBinder.GetIteratorElementTypeFromReturnType(Compilation, refKind, returnType, errorLocation, diagnostics);
if (elementType.IsDefault)
{
if (refKind != RefKind.None)
{
Error(diagnostics, ErrorCode.ERR_BadIteratorReturnRef, errorLocation, iterator);
}
else if (!returnType.IsErrorType())
{
Error(diagnostics, ErrorCode.ERR_BadIteratorReturn, errorLocation, iterator, returnType);
}
}
bool asyncInterface = InMethodBinder.IsAsyncStreamInterface(Compilation, refKind, returnType);
if (asyncInterface && !iterator.IsAsync)
{
diagnostics.Add(ErrorCode.ERR_IteratorMustBeAsync, errorLocation, iterator, returnType);
}
}
}
......
......@@ -234,7 +234,7 @@ internal override bool SupportsExtensionMethods
}
}
internal override TypeWithAnnotations GetIteratorElementType(YieldStatementSyntax node, DiagnosticBag diagnostics)
internal override TypeWithAnnotations GetIteratorElementType()
{
if (IsScriptClass)
{
......@@ -245,7 +245,7 @@ internal override TypeWithAnnotations GetIteratorElementType(YieldStatementSynta
else
{
// This path would eventually throw, if we didn't have the case above.
return Next.GetIteratorElementType(node, diagnostics);
return Next.GetIteratorElementType();
}
}
......
......@@ -13,27 +13,15 @@ namespace Microsoft.CodeAnalysis.CSharp
/// <summary>
/// A binder for a method body, which places the method's parameters in scope
/// and notes if the method is an iterator method.
/// Note: instances of this type can be re-used across different attempts at compiling the same method (caching by binder factory).
/// </summary>
internal sealed class InMethodBinder : LocalScopeBinder
{
private MultiDictionary<string, ParameterSymbol> _lazyParameterMap;
private readonly MethodSymbol _methodSymbol;
private SmallDictionary<string, Symbol> _lazyDefinitionMap;
private IteratorInfo _iteratorInfo;
private class IteratorInfo
{
public static readonly IteratorInfo Empty = new IteratorInfo(default, default(ImmutableArray<Diagnostic>));
public readonly TypeWithAnnotations ElementType;
public readonly ImmutableArray<Diagnostic> ElementTypeDiagnostics;
public IteratorInfo(TypeWithAnnotations elementType, ImmutableArray<Diagnostic> elementTypeDiagnostics)
{
this.ElementType = elementType;
this.ElementTypeDiagnostics = elementTypeDiagnostics;
}
}
private TypeWithAnnotations.Boxed _iteratorElementType;
private readonly static TypeWithAnnotations.Boxed SentinelElementType = new TypeWithAnnotations.Boxed(default);
public InMethodBinder(MethodSymbol owner, Binder enclosing)
: base(enclosing, enclosing.Flags & ~BinderFlags.AllClearedAtExecutableCodeBoundary)
......@@ -88,9 +76,9 @@ internal override bool IsInMethodBody
internal void MakeIterator()
{
if (_iteratorInfo == null)
if (_iteratorElementType == null)
{
_iteratorInfo = IteratorInfo.Empty;
_iteratorElementType = SentinelElementType;
}
}
......@@ -98,7 +86,7 @@ internal override bool IsDirectlyInIterator
{
get
{
return _iteratorInfo != null;
return _iteratorElementType != null;
}
}
......@@ -126,7 +114,11 @@ internal override GeneratedLabelSymbol ContinueLabel
}
}
internal override TypeWithAnnotations GetIteratorElementType(YieldStatementSyntax node, DiagnosticBag diagnostics)
protected override void ValidateYield(YieldStatementSyntax node, DiagnosticBag diagnostics)
{
}
internal override TypeWithAnnotations GetIteratorElementType()
{
RefKind refKind = _methodSymbol.RefKind;
TypeSymbol returnType = _methodSymbol.ReturnType;
......@@ -139,49 +131,26 @@ internal override TypeWithAnnotations GetIteratorElementType(YieldStatementSynta
// and deduce an iterator element type from the return type. If we didn't do this, the
// TypeInfo.ConvertedType of the yield statement would always be an error type. However, we will
// not mutate any state (i.e. we won't store the result).
var elementType = GetIteratorElementTypeFromReturnType(Compilation, refKind, returnType, node, diagnostics).elementType;
var elementType = GetIteratorElementTypeFromReturnType(Compilation, refKind, returnType, errorLocation: null, diagnostics: null);
return !elementType.IsDefault ? elementType : TypeWithAnnotations.Create(CreateErrorType());
}
if (_iteratorInfo == IteratorInfo.Empty)
if (_iteratorElementType == SentinelElementType)
{
DiagnosticBag elementTypeDiagnostics = DiagnosticBag.GetInstance();
(TypeWithAnnotations elementType, bool asyncInterface) = GetIteratorElementTypeFromReturnType(Compilation, refKind, returnType, node, elementTypeDiagnostics);
Location errorLocation = _methodSymbol.Locations[0];
TypeWithAnnotations elementType = GetIteratorElementTypeFromReturnType(Compilation, refKind, returnType, errorLocation: null, diagnostics: null);
if (elementType.IsDefault)
{
if (refKind != RefKind.None)
{
Error(elementTypeDiagnostics, ErrorCode.ERR_BadIteratorReturnRef, errorLocation, _methodSymbol);
}
else if (!returnType.IsErrorType())
{
Error(elementTypeDiagnostics, ErrorCode.ERR_BadIteratorReturn, errorLocation, _methodSymbol, returnType);
}
elementType = TypeWithAnnotations.Create(CreateErrorType());
}
else if (asyncInterface && !_methodSymbol.IsAsync)
{
Error(elementTypeDiagnostics, ErrorCode.ERR_IteratorMustBeAsync, errorLocation, _methodSymbol, returnType);
}
var info = new IteratorInfo(elementType, elementTypeDiagnostics.ToReadOnlyAndFree());
var oldInfo = Interlocked.CompareExchange(ref _iteratorInfo, info, IteratorInfo.Empty);
if (oldInfo == IteratorInfo.Empty)
{
diagnostics.AddRange(_iteratorInfo.ElementTypeDiagnostics);
}
Interlocked.CompareExchange(ref _iteratorElementType, new TypeWithAnnotations.Boxed(elementType), SentinelElementType);
}
return _iteratorInfo.ElementType;
return _iteratorElementType.Value;
}
// If an element type is found, we also return whether the interface is meant to be used with async.
internal static (TypeWithAnnotations elementType, bool asyncInterface) GetIteratorElementTypeFromReturnType(CSharpCompilation compilation,
RefKind refKind, TypeSymbol returnType, CSharpSyntaxNode errorLocationNode, DiagnosticBag diagnostics)
internal static TypeWithAnnotations GetIteratorElementTypeFromReturnType(CSharpCompilation compilation,
RefKind refKind, TypeSymbol returnType, Location errorLocation, DiagnosticBag diagnostics)
{
if (refKind == RefKind.None && returnType.Kind == SymbolKind.NamedType)
{
......@@ -193,25 +162,41 @@ internal override TypeWithAnnotations GetIteratorElementType(YieldStatementSynta
var objectType = compilation.GetSpecialType(SpecialType.System_Object);
if (diagnostics != null)
{
ReportUseSiteDiagnostics(objectType, diagnostics, errorLocationNode);
ReportUseSiteDiagnostics(objectType, diagnostics, errorLocation);
}
return (TypeWithAnnotations.Create(objectType), false);
return TypeWithAnnotations.Create(objectType);
case SpecialType.System_Collections_Generic_IEnumerable_T:
case SpecialType.System_Collections_Generic_IEnumerator_T:
return (((NamedTypeSymbol)returnType).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0], false);
return ((NamedTypeSymbol)returnType).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0];
}
if (TypeSymbol.Equals(originalDefinition, compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_IAsyncEnumerable_T), TypeCompareKind.ConsiderEverything2) ||
TypeSymbol.Equals(originalDefinition, compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_IAsyncEnumerator_T), TypeCompareKind.ConsiderEverything2))
if (TypeSymbol.Equals(originalDefinition, compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_IAsyncEnumerable_T), TypeCompareKind.ConsiderEverything) ||
TypeSymbol.Equals(originalDefinition, compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_IAsyncEnumerator_T), TypeCompareKind.ConsiderEverything))
{
return (((NamedTypeSymbol)returnType).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0], true);
return ((NamedTypeSymbol)returnType).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0];
}
}
return default;
}
internal static bool IsAsyncStreamInterface(CSharpCompilation compilation, RefKind refKind, TypeSymbol returnType)
{
if (refKind == RefKind.None && returnType.Kind == SymbolKind.NamedType)
{
TypeSymbol originalDefinition = returnType.OriginalDefinition;
if (TypeSymbol.Equals(originalDefinition, compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_IAsyncEnumerable_T), TypeCompareKind.ConsiderEverything) ||
TypeSymbol.Equals(originalDefinition, compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_IAsyncEnumerator_T), TypeCompareKind.ConsiderEverything))
{
return true;
}
}
return false;
}
internal override void LookupSymbolsInSingleBinder(
LookupResult result, string name, int arity, ConsList<TypeSymbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
......
......@@ -74,13 +74,17 @@ internal override bool IsDirectlyInIterator
// NOTE: Specifically not overriding IsIndirectlyInIterator.
internal override TypeWithAnnotations GetIteratorElementType(YieldStatementSyntax node, DiagnosticBag diagnostics)
internal override TypeWithAnnotations GetIteratorElementType()
{
return TypeWithAnnotations.Create(CreateErrorType());
}
protected override void ValidateYield(YieldStatementSyntax node, DiagnosticBag diagnostics)
{
if (node != null)
{
diagnostics.Add(ErrorCode.ERR_YieldInAnonMeth, node.YieldKeyword.GetLocation());
}
return TypeWithAnnotations.Create(CreateErrorType());
}
internal override void LookupSymbolsInSingleBinder(
......
......@@ -7779,7 +7779,7 @@ public override BoundNode VisitYieldReturnStatement(BoundYieldReturnStatement no
}
var method = _delegateInvokeMethod ?? (MethodSymbol)_symbol;
TypeWithAnnotations elementType = InMethodBinder.GetIteratorElementTypeFromReturnType(compilation, RefKind.None,
method.ReturnType, errorLocationNode: null, diagnostics: null).elementType;
method.ReturnType, errorLocation: null, diagnostics: null);
_ = VisitOptionalImplicitConversion(expr, elementType, useLegacyWarnings: false, trackMembers: false, AssignmentKind.Return);
return null;
......
......@@ -1881,6 +1881,7 @@ public static async System.Collections.Generic.IAsyncEnumerable<int> M()
[Fact]
[WorkItem(31608, "https://github.com/dotnet/roslyn/issues/31608")]
[WorkItem(39970, "https://github.com/dotnet/roslyn/issues/39970")]
public void AsyncIterator_WithoutAwait_WithoutAsync()
{
string source = @"
......@@ -1892,11 +1893,13 @@ static System.Collections.Generic.IAsyncEnumerable<int> M()
}
}";
var comp = CreateCompilationWithAsyncIterator(source);
comp.VerifyDiagnostics(
var expected = new DiagnosticDescription[] {
// (4,61): error CS8403: Method 'C.M()' with an iterator block must be 'async' to return 'IAsyncEnumerable<int>'
// static System.Collections.Generic.IAsyncEnumerable<int> M()
Diagnostic(ErrorCode.ERR_IteratorMustBeAsync, "M").WithArguments("C.M()", "System.Collections.Generic.IAsyncEnumerable<int>").WithLocation(4, 61)
);
};
comp.VerifyDiagnostics(expected);
comp.VerifyEmitDiagnostics(expected);
}
[Fact]
......
......@@ -14586,14 +14586,16 @@ public static void Main()
}
";
var comp = CreateCompilation(text);
comp.VerifyDiagnostics(
var expected = new DiagnosticDescription[] {
// (12,13): error CS1621: The yield statement cannot be used inside an anonymous method or lambda expression
// yield return this; // CS1621
Diagnostic(ErrorCode.ERR_YieldInAnonMeth, "yield"),
// (8,24): error CS0161: 'C.GetEnumerator()': not all code paths return a value
// public IEnumerator GetEnumerator()
Diagnostic(ErrorCode.ERR_ReturnExpected, "GetEnumerator").WithArguments("C.GetEnumerator()")
);
};
comp.VerifyDiagnostics(expected);
comp.VerifyEmitDiagnostics(expected);
}
[Fact]
......
......@@ -2244,6 +2244,35 @@ public static int Main()
Assert.Equal(1, compilation.GetDiagnostics().Length);
}
[WorkItem(39992, "https://github.com/dotnet/roslyn/issues/39992")]
[Fact]
public void GetDiagnosticsCalledTwice_GetEmitDiagnostics()
{
var text = @"
interface IMyEnumerator { }
public class Test
{
static IMyEnumerator Goo()
{
yield break;
}
public static int Main()
{
return 1;
}
}";
var compilation = CreateCompilation(text);
var expected = new DiagnosticDescription[] {
// (6,26): error CS1624: The body of 'Test.Goo()' cannot be an iterator block because 'IMyEnumerator' is not an iterator interface type
// static IMyEnumerator Goo()
Diagnostic(ErrorCode.ERR_BadIteratorReturn, "Goo").WithArguments("Test.Goo()", "IMyEnumerator").WithLocation(6, 26)
};
compilation.VerifyDiagnostics(expected);
compilation.VerifyEmitDiagnostics(expected);
}
[Fact]
public void TestArgumentEquality()
{
......
......@@ -1478,7 +1478,7 @@ private static string NewMethod(int i)
[WorkItem(15532, "https://github.com/dotnet/roslyn/issues/15532")]
public async Task ExtractLocalFunctionCall()
{
await TestInRegularAndScriptAsync(@"
var code = @"
class C
{
public static void Main()
......@@ -1486,18 +1486,33 @@ public static void Main()
void Local() { }
[|Local();|]
}
}";
await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_local_function });
}
[Fact]
public async Task ExtractLocalFunctionCall_2()
{
await TestInRegularAndScriptAsync(@"
class C
{
public static void Main()
{
[|void Local() { }
Local();|]
}
}", @"
class C
{
public static void Main()
{
void Local() { }
{|Rename:NewMethod|}();
}
private static void NewMethod()
{
{|Warning:Local();|}
void Local() { }
Local();
}
}");
}
......@@ -1506,7 +1521,7 @@ private static void NewMethod()
[WorkItem(15532, "https://github.com/dotnet/roslyn/issues/15532")]
public async Task ExtractLocalFunctionCallWithCapture()
{
await TestInRegularAndScriptAsync(@"
var code = @"
class C
{
public static void Main(string[] args)
......@@ -1514,20 +1529,8 @@ public static void Main(string[] args)
bool Local() => args == null;
[|Local();|]
}
}", @"
class C
{
public static void Main(string[] args)
{
bool Local() => args == null;
{|Rename:NewMethod|}(args);
}
private static void NewMethod(string[] args)
{
{|Warning:Local();|}
}
}");
}";
await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_local_function });
}
[Fact]
......@@ -1567,9 +1570,9 @@ class C
public static void Main()
{
void Local()
{|Warning:{
{
{|Rename:NewMethod|}();
}|}
}
Local();
}
......@@ -1616,7 +1619,7 @@ static void Main(string[] args)
private static int NewMethod(int v, int i)
{
{|Warning:v = v + i;|}
v = v + i;
return v;
}
}");
......@@ -1650,7 +1653,7 @@ static void Main(string[] args)
int v = 0;
for(int i=0 ; i<5; i++)
{
{|Warning:v = {|Rename:NewMethod|}(v, i)|};
v = {|Rename:NewMethod|}(v, i);
}
}
}
......@@ -1690,7 +1693,7 @@ static void Main(string[] args)
int v = 0;
for(int i=0 ; i<5; i++)
{
{|Warning:i = {|Rename:NewMethod|}(ref v, i)|};
i = {|Rename:NewMethod|}(ref v, i);
}
}
}
......@@ -3125,6 +3128,116 @@ void M()
}");
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task EnsureStaticLocalFunctionOptionHasNoEffect()
{
await TestInRegularAndScriptAsync(
@"class Program
{
static void Main(string[] args)
{
bool b = true;
System.Console.WriteLine([|b != true|] ? b = true : b = false);
}
}",
@"class Program
{
static void Main(string[] args)
{
bool b = true;
System.Console.WriteLine({|Rename:NewMethod|}(b) ? b = true : b = false);
}
private static bool NewMethod(bool b)
{
return b != true;
}
}", options: Option(CSharpCodeStyleOptions.PreferStaticLocalFunction, CodeStyleOptions.FalseWithSuggestionEnforcement));
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/39946"), Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task ExtractLocalFunctionCallAndDeclaration()
{
await TestInRegularAndScriptAsync(@"
class C
{
public static void Main()
{
static void LocalParent()
{
[|void Local() { }
Local();|]
}
}
}", @"
class C
{
public static void Main()
{
static void LocalParent()
{
{|Rename:NewMethod|}();
}
}
private static void NewMethod()
{
void Local() { }
Local();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task TestMissingWhenOnlyLocalFunctionCallSelected()
{
var code = @"
class Program
{
static void Main(string[] args)
{
[|Local();|]
static void Local()
{
}
}
}";
await TestExactActionSetOfferedAsync(code, new[] { FeaturesResources.Extract_local_function });
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task TestOfferedWhenBothLocalFunctionCallAndDeclarationSelected()
{
await TestInRegularAndScriptAsync(@"
class Program
{
static void Main(string[] args)
{
[|Local();
var test = 5;
static void Local()
{
}|]
}
}", @"
class Program
{
static void Main(string[] args)
{
{|Rename:NewMethod|}();
}
private static void NewMethod()
{
Local();
var test = 5;
static void Local()
{
}
}
}");
}
[Fact, WorkItem(38529, "https://github.com/dotnet/roslyn/issues/38529"), Trait(Traits.Feature, Traits.Features.CodeActionsExtractMethod)]
public async Task TestExtractNonAsyncMethodWithAsyncLocalFunction()
{
await TestInRegularAndScriptAsync(
......@@ -3139,9 +3252,9 @@ void M()
@"class C
{
void M()
{|Warning:{
{
{|Rename:NewMethod|}();
}|}
}
private static void NewMethod()
{
......@@ -3347,9 +3460,9 @@ async Task MyDelay(TimeSpan duration)
class C
{
async Task MyDelay(TimeSpan duration)
{|Warning:{
{
await {|Rename:NewMethod|}(duration);
}|}
}
private static async Task NewMethod(TimeSpan duration)
{
......
......@@ -137,7 +137,7 @@ protected async Task NotSupported_ExtractMethodAsync(string codeWithMarker)
Assert.True(selectedCode.ContainsValidContext);
// extract method
var extractor = new CSharpMethodExtractor((CSharpSelectionResult)selectedCode);
var extractor = new CSharpMethodExtractor((CSharpSelectionResult)selectedCode, localFunction: false);
var result = await extractor.ExtractMethodAsync(CancellationToken.None);
Assert.NotNull(result);
Assert.Equal(succeed,
......
......@@ -10329,7 +10329,7 @@ public async Task ExtractMethod_Argument1()
var service = new CSharpExtractMethodService();
Assert.NotNull(await Record.ExceptionAsync(async () =>
{
var tree = await service.ExtractMethodAsync(null, default, null, CancellationToken.None);
var tree = await service.ExtractMethodAsync(document: null, textSpan: default, localFunction: false, options: null, CancellationToken.None);
}));
}
......@@ -10345,7 +10345,7 @@ public async Task ExtractMethod_Argument2()
var service = new CSharpExtractMethodService() as IExtractMethodService;
await service.ExtractMethodAsync(document, default);
await service.ExtractMethodAsync(document, textSpan: default, localFunction: false);
}
[WpfFact]
......
......@@ -278,8 +278,8 @@ protected static async Task AssertCodeCleanupResult(string expected, string code
Assert.Equal(expected, actual.ToString());
}
[Export(typeof(IWorkspaceDiagnosticAnalyzerProviderService))]
private class CodeCleanupAnalyzerProviderService : IWorkspaceDiagnosticAnalyzerProviderService
[Export(typeof(IHostDiagnosticAnalyzerPackageProvider))]
private class CodeCleanupAnalyzerProviderService : IHostDiagnosticAnalyzerPackageProvider
{
private readonly HostDiagnosticAnalyzerPackage _info;
......@@ -300,9 +300,9 @@ public IAnalyzerAssemblyLoader GetAnalyzerAssemblyLoader()
return FromFileLoader.Instance;
}
public IEnumerable<HostDiagnosticAnalyzerPackage> GetHostDiagnosticAnalyzerPackages()
public ImmutableArray<HostDiagnosticAnalyzerPackage> GetHostDiagnosticAnalyzerPackages()
{
yield return _info;
return ImmutableArray.Create(_info);
}
public class FromFileLoader : IAnalyzerAssemblyLoader
......
......@@ -99,7 +99,7 @@ public bool ExecuteCommand(ExtractMethodCommandArgs args, CommandExecutionContex
}
var result = ExtractMethodService.ExtractMethodAsync(
document, spans.Single().Span.ToTextSpan(), cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
document, spans.Single().Span.ToTextSpan(), localFunction: false, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
Contract.ThrowIfNull(result);
if (!result.Succeeded && !result.SucceededWithSuggestion)
......@@ -220,7 +220,7 @@ private bool TryNotifyFailureToUser(Document document, ExtractMethodResult resul
{
options = options.WithChangedOption(ExtractMethodOptions.DontPutOutOrRefOnStruct, document.Project.Language, true);
var newResult = ExtractMethodService.ExtractMethodAsync(
document, spans.Single().Span.ToTextSpan(), options, cancellationToken).WaitAndGetResult(cancellationToken);
document, spans.Single().Span.ToTextSpan(), localFunction: false, options, cancellationToken).WaitAndGetResult(cancellationToken);
// retry succeeded, return new result
if (newResult.Succeeded || newResult.SucceededWithSuggestion)
......
......@@ -390,7 +390,7 @@ internal MyDiagnosticAnalyzerService(DiagnosticAnalyzer analyzer, IAsynchronousO
}
internal MyDiagnosticAnalyzerService(IEnumerable<DiagnosticAnalyzer> analyzers, IAsynchronousOperationListener listener, string language = LanguageNames.CSharp)
: base(new HostAnalyzerManager(
: base(new DiagnosticAnalyzerInfoCache(
ImmutableArray.Create<AnalyzerReference>(
new TestAnalyzerReferenceByLanguage(
ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>>.Empty.Add(language, ImmutableArray.CreateRange(analyzers)))),
......@@ -446,10 +446,9 @@ private class NoNameAnalyzer : DocumentDiagnosticAnalyzer
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(s_syntaxRule);
public override async Task<ImmutableArray<Diagnostic>> AnalyzeSyntaxAsync(Document document, CancellationToken cancellationToken)
public override Task<ImmutableArray<Diagnostic>> AnalyzeSyntaxAsync(Document document, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
return ImmutableArray.Create(Diagnostic.Create(s_syntaxRule, Location.Create(document.FilePath, TextSpan.FromBounds(0, 0), new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 0)))));
return Task.FromResult(ImmutableArray.Create(Diagnostic.Create(s_syntaxRule, Location.Create(document.FilePath, TextSpan.FromBounds(0, 0), new LinePositionSpan(new LinePosition(0, 0), new LinePosition(0, 0))))));
}
public override Task<ImmutableArray<Diagnostic>> AnalyzeSemanticsAsync(Document document, CancellationToken cancellationToken)
......
......@@ -255,7 +255,7 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable()
dotnet_diagnostic.IDE0036.severity = %value%
# IDE0037
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_diagnostic.IDE0037.severity = %value%
# IDE0039
csharp_style_pattern_local_over_anonymous_function = true:suggestion
......@@ -419,7 +419,7 @@ public void VisualBasic_VerifyIDEDiagnosticSeveritiesAreConfigurable()
dotnet_diagnostic.IDE0036.severity = %value%
# IDE0037
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_diagnostic.IDE0037.severity = %value%
# IDE0040
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
......@@ -721,6 +721,9 @@ public void CSharp_VerifyIDECodeStyleOptionsAreConfigurable()
# IDE0037, PreferInferredTupleNames
dotnet_style_prefer_inferred_tuple_names = true:suggestion
# IDE0037, PreferInferredAnonymousTypeMemberNames
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
# IDE0039, PreferLocalOverAnonymousFunction
csharp_style_pattern_local_over_anonymous_function = true:suggestion
......@@ -915,6 +918,9 @@ public void VisualBasic_VerifyIDECodeStyleOptionsAreConfigurable()
# IDE0037, PreferInferredTupleNames
dotnet_style_prefer_inferred_tuple_names = true:suggestion
# IDE0037, PreferInferredAnonymousTypeMemberNames
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
# IDE0040, RequireAccessibilityModifiers
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
......
......@@ -10,8 +10,8 @@
namespace Microsoft.CodeAnalysis.Editor.UnitTests.Preview
{
[Export(typeof(IWorkspaceDiagnosticAnalyzerProviderService))]
internal class TestOnly_CompilerDiagnosticAnalyzerProviderService : IWorkspaceDiagnosticAnalyzerProviderService
[Export(typeof(IHostDiagnosticAnalyzerPackageProvider))]
internal class TestOnly_CompilerDiagnosticAnalyzerProviderService : IHostDiagnosticAnalyzerPackageProvider
{
private readonly HostDiagnosticAnalyzerPackage _info;
......@@ -38,9 +38,9 @@ public IAnalyzerAssemblyLoader GetAnalyzerAssemblyLoader()
return FromFileLoader.Instance;
}
public IEnumerable<HostDiagnosticAnalyzerPackage> GetHostDiagnosticAnalyzerPackages()
public ImmutableArray<HostDiagnosticAnalyzerPackage> GetHostDiagnosticAnalyzerPackages()
{
yield return _info;
return ImmutableArray.Create(_info);
}
public class FromFileLoader : IAnalyzerAssemblyLoader
......
......@@ -145,7 +145,7 @@ private class MyDiagnosticAnalyzerService : DiagnosticAnalyzerService
internal MyDiagnosticAnalyzerService(
ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>> analyzersMap,
IAsynchronousOperationListener listener)
: base(new HostAnalyzerManager(ImmutableArray.Create<AnalyzerReference>(new TestAnalyzerReferenceByLanguage(analyzersMap)), hostDiagnosticUpdateSource: null),
: base(new DiagnosticAnalyzerInfoCache(ImmutableArray.Create<AnalyzerReference>(new TestAnalyzerReferenceByLanguage(analyzersMap)), hostDiagnosticUpdateSource: null),
hostDiagnosticUpdateSource: null,
registrationService: new MockDiagnosticUpdateSourceRegistrationService(),
listener: listener)
......
......@@ -52,14 +52,14 @@ internal sealed class TestDiagnosticAnalyzerService : DiagnosticAnalyzerService
}
private TestDiagnosticAnalyzerService(
HostAnalyzerManager hostAnalyzerManager,
DiagnosticAnalyzerInfoCache analyzerInfoCache,
AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource,
Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException,
IDiagnosticUpdateSourceRegistrationService registrationService = null,
IAsynchronousOperationListener listener = null)
: base(hostAnalyzerManager, hostDiagnosticUpdateSource, registrationService ?? new MockDiagnosticUpdateSourceRegistrationService(), listener)
: base(analyzerInfoCache, hostDiagnosticUpdateSource, registrationService ?? new MockDiagnosticUpdateSourceRegistrationService(), listener)
{
_hostAnalyzerReferenceMap = hostAnalyzerManager.CreateAnalyzerReferencesMap(projectOpt: null);
_hostAnalyzerReferenceMap = analyzerInfoCache.CreateAnalyzerReferencesMap(project: null);
_onAnalyzerException = onAnalyzerException;
}
......@@ -73,27 +73,27 @@ internal sealed class TestDiagnosticAnalyzerService : DiagnosticAnalyzerService
_onAnalyzerException = onAnalyzerException;
}
private static HostAnalyzerManager CreateHostAnalyzerManager(string language, DiagnosticAnalyzer analyzer, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
private static DiagnosticAnalyzerInfoCache CreateHostAnalyzerManager(string language, DiagnosticAnalyzer analyzer, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
{
return CreateHostAnalyzerManager(language, ImmutableArray.Create(analyzer), hostDiagnosticUpdateSource);
}
private static HostAnalyzerManager CreateHostAnalyzerManager(string language, ImmutableArray<DiagnosticAnalyzer> analyzers, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
private static DiagnosticAnalyzerInfoCache CreateHostAnalyzerManager(string language, ImmutableArray<DiagnosticAnalyzer> analyzers, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
{
var map = ImmutableDictionary.CreateRange(
SpecializedCollections.SingletonEnumerable(KeyValuePairUtil.Create(language, analyzers)));
return CreateHostAnalyzerManager(map, hostDiagnosticUpdateSource);
}
private static HostAnalyzerManager CreateHostAnalyzerManager(ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>> analyzersMap, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
private static DiagnosticAnalyzerInfoCache CreateHostAnalyzerManager(ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>> analyzersMap, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
{
var analyzerReferences = ImmutableArray.Create<AnalyzerReference>(new TestAnalyzerReferenceByLanguage(analyzersMap));
return CreateHostAnalyzerManager(analyzerReferences, hostDiagnosticUpdateSource);
}
private static HostAnalyzerManager CreateHostAnalyzerManager(ImmutableArray<AnalyzerReference> hostAnalyzerReferences, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
private static DiagnosticAnalyzerInfoCache CreateHostAnalyzerManager(ImmutableArray<AnalyzerReference> hostAnalyzerReferences, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource)
{
return new HostAnalyzerManager(hostAnalyzerReferences, hostDiagnosticUpdateSource);
return new DiagnosticAnalyzerInfoCache(hostAnalyzerReferences, hostDiagnosticUpdateSource);
}
internal override Action<Exception, DiagnosticAnalyzer, Diagnostic> GetOnAnalyzerException(ProjectId projectId, DiagnosticLogAggregator diagnosticLogAggregator)
......
......@@ -1567,15 +1567,6 @@ internal class CSharpFeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Warning: Extracting a local function reference may produce invalid code.
/// </summary>
internal static string Warning_Extracting_a_local_function_reference_may_produce_invalid_code {
get {
return ResourceManager.GetString("Warning_Extracting_a_local_function_reference_may_produce_invalid_code", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Warning: Inlining temporary into conditional method call..
/// </summary>
......
......@@ -523,9 +523,6 @@
<data name="Convert_to_switch_expression" xml:space="preserve">
<value>Convert to 'switch' expression</value>
</data>
<data name="Warning_Extracting_a_local_function_reference_may_produce_invalid_code" xml:space="preserve">
<value>Warning: Extracting a local function reference may produce invalid code</value>
</data>
<data name="Name" xml:space="preserve">
<value>&lt;Name&gt;</value>
</data>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册