Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

using System.Collections.Immutable;
using System.Diagnostics;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
Expand Down Expand Up @@ -59,7 +58,7 @@ internal override TypeWithAnnotations IteratorElementTypeWithAnnotations
}
}

internal override bool IsIterator
public override bool IsIterator
{
get { return _originalMethod.IsIterator; }
}
Expand Down
3 changes: 1 addition & 2 deletions src/Compilers/CSharp/Portable/Symbols/MethodSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Symbols;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
Expand Down Expand Up @@ -1085,7 +1084,7 @@ public sealed override bool HasUnsupportedMetadata

#endregion

internal virtual bool IsIterator
public virtual bool IsIterator
{
get
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ INamedTypeSymbol IMethodSymbol.AssociatedAnonymousDelegate

bool IMethodSymbol.IsConditional => _underlying.IsConditional;

bool IMethodSymbol.IsIterator => _underlying.IsIterator;

DllImportData IMethodSymbol.GetDllImportData() => _underlying.GetDllImportData();

#region ISymbol Members
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ internal sealed override TypeWithAnnotations IteratorElementTypeWithAnnotations
}
}

internal sealed override bool IsIterator => _lazyIteratorElementType is object;
public sealed override bool IsIterator => _lazyIteratorElementType is object;
}
}
62 changes: 62 additions & 0 deletions src/Compilers/CSharp/Test/Semantic/Semantics/IteratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -61,6 +62,67 @@ IEnumerable<int> I()
comp.VerifyDiagnostics();
}

[Fact]
public void BasicIterators_Async()
{
var source = """
using System.Collections.Generic;
using System.Threading.Tasks;

class Test
{
async IAsyncEnumerable<int> I()
{
await Task.Yield();
yield return 1;
}
}
""";

var comp = CreateCompilation(source, targetFramework: TargetFramework.Net60);
comp.VerifyDiagnostics();

var i = comp.GetMember<MethodSymbol>("Test.I");
Assert.True(i.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<int> I1()
{
yield return 1;
}

public async IAsyncEnumerable<int> 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<PENamedTypeSymbol>(userComp.GetTypeByMetadataName("Test"));

var i1 = testType.GetMethod("I1");
Assert.False(i1.IsIterator);

var i2 = testType.GetMethod("I2");
Assert.False(i2.IsIterator);
}

[Fact]
public void WrongYieldType()
{
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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?
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/Core/Portable/Symbols/IMethodSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,10 @@ public interface IMethodSymbol : ISymbol
/// Returns a flag indicating whether this symbol has at least one applied/inherited conditional attribute.
/// </summary>
bool IsConditional { get; }

/// <summary>
/// Returns <see langword="true"/> if this method is a source method implemented as an iterator (either sync or async)
/// </summary>
bool IsIterator { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
''' </summary>
Public MustOverride ReadOnly Property IsIterator As Boolean
Public MustOverride ReadOnly Property IsIterator As Boolean Implements IMethodSymbol.IsIterator

''' <summary>
''' Indicates whether the accessor is marked with the 'init' modifier.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,61 @@
' 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.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Imports Roslyn.Test.Utilities

Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics

Public Class IteratorTests
Inherits FlowTestBase

<Fact>
Public Sub BasicIterator()
Dim compilation = CreateCompilation(
<compilation>
<file name="a.vb">
<![CDATA[
Imports System.Collections.Generic

Class C
Public Iterator Function I As IEnumerable(Of Integer)
Yield 1
End Function
End Class
]]>
</file>
</compilation>).VerifyDiagnostics()

Dim i = compilation.GetMember(Of MethodSymbol)("C.I")
Assert.True(i.IsIterator)
End Sub

<Fact>
Public Sub BasicIterator_Metadata()
Dim sourceComp = CreateCompilation(
<compilation>
<file name="a.vb">
<![CDATA[
Imports System.Collections.Generic

Public Class C
Public Iterator Function I As IEnumerable(Of Integer)
Yield 1
End Function
End Class
]]>
</file>
</compilation>).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)
End Sub

<Fact()>
Public Sub IteratorNoYields()
Dim compilation = CreateCompilationWithMscorlib40AndVBRuntime(
Expand Down Expand Up @@ -1021,6 +1068,30 @@ End Class
CompileAndVerify(compilation, expectedOutput:="123")
End Sub

<Fact>
Public Sub IteratorProperty_Metadata()
Dim sourceComp = CreateCompilation(
<compilation>
<file name="a.vb"><![CDATA[
Imports System.Collections.Generic

Class C
Iterator ReadOnly Property P As IEnumerable(Of Integer)
Get
Yield 1
End Get
End Property
End Class
]]></file>
</compilation>).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)
End Sub

<Fact()>
Public Sub CompilerLoweringPreserveAttribute_01()
Dim source1 = "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ public IMethodSymbol ReduceExtensionMethod(ITypeSymbol receiverType)

public bool IsConditional => _symbol.IsConditional;

public bool IsIterator => _symbol.IsIterator;

public SignatureCallingConvention CallingConvention => _symbol.CallingConvention;

public ImmutableArray<INamedTypeSymbol> UnmanagedCallingConventionTypes => _symbol.UnmanagedCallingConventionTypes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,7 @@ Microsoft.CodeAnalysis.IMethodSymbol.get_IsConditional
Microsoft.CodeAnalysis.IMethodSymbol.get_IsExtensionMethod
Microsoft.CodeAnalysis.IMethodSymbol.get_IsGenericMethod
Microsoft.CodeAnalysis.IMethodSymbol.get_IsInitOnly
Microsoft.CodeAnalysis.IMethodSymbol.get_IsIterator
Microsoft.CodeAnalysis.IMethodSymbol.get_IsPartialDefinition
Microsoft.CodeAnalysis.IMethodSymbol.get_IsReadOnly
Microsoft.CodeAnalysis.IMethodSymbol.get_IsVararg
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ public virtual ImmutableArray<CustomModifier> ReturnTypeCustomModifiers

public bool IsConditional => false;

public bool IsIterator => false;

public SignatureCallingConvention CallingConvention => SignatureCallingConvention.Default;

public ImmutableArray<INamedTypeSymbol> UnmanagedCallingConventionTypes => [];
Expand Down
Loading