提交 fb261546 编写于 作者: J Julien Couvreur

Fix for #9463: iterator rewriter to report missing types gracefully

上级 bb9817d4
......@@ -990,7 +990,12 @@ private bool ShouldCheckConstraints
internal NamedTypeSymbol GetSpecialType(SpecialType typeId, DiagnosticBag diagnostics, CSharpSyntaxNode node)
{
NamedTypeSymbol typeSymbol = this.Compilation.GetSpecialType(typeId);
return GetSpecialType(this.Compilation, typeId, node, diagnostics);
}
internal static NamedTypeSymbol GetSpecialType(CSharpCompilation compilation, SpecialType typeId, CSharpSyntaxNode node, DiagnosticBag diagnostics)
{
NamedTypeSymbol typeSymbol = compilation.GetSpecialType(typeId);
Debug.Assert((object)typeSymbol != null, "Expect an error type if special type isn't found");
ReportUseSiteDiagnostics(typeSymbol, diagnostics, node);
return typeSymbol;
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CodeGen;
......@@ -74,7 +75,88 @@ internal partial class IteratorRewriter : StateMachineRewriter
stateMachineType = new IteratorStateMachine(slotAllocatorOpt, compilationState, method, methodOrdinal, isEnumerable, elementType);
compilationState.ModuleBuilderOpt.CompilationState.SetStateMachineType(method, stateMachineType);
return new IteratorRewriter(body, method, isEnumerable, stateMachineType, slotAllocatorOpt, compilationState, diagnostics).Rewrite();
var rewriter = new IteratorRewriter(body, method, isEnumerable, stateMachineType, slotAllocatorOpt, compilationState, diagnostics);
if (!rewriter.VerifyPresenceOfRequiredAPIs())
{
return body;
}
return rewriter.Rewrite();
}
/// <returns>
/// Returns true if all types and members we need are present and good
/// </returns>
protected bool VerifyPresenceOfRequiredAPIs()
{
DiagnosticBag bag = DiagnosticBag.GetInstance();
EnsureSpecialType(SpecialType.System_Int32, bag);
EnsureSpecialType(SpecialType.System_IDisposable, bag);
EnsureSpecialMember(SpecialMember.System_IDisposable__Dispose, bag);
// IEnumerator
EnsureSpecialType(SpecialType.System_Collections_IEnumerator, bag);
EnsureSpecialPropertyGetter(SpecialMember.System_Collections_IEnumerator__Current, bag);
EnsureSpecialMember(SpecialMember.System_Collections_IEnumerator__MoveNext, bag);
EnsureSpecialMember(SpecialMember.System_Collections_IEnumerator__Reset, bag);
// IEnumerator<T>
EnsureSpecialType(SpecialType.System_Collections_Generic_IEnumerator_T, bag);
EnsureSpecialPropertyGetter(SpecialMember.System_Collections_Generic_IEnumerator_T__Current, bag);
if (_isEnumerable)
{
// IEnumerable and IEnumerable<T>
EnsureSpecialType(SpecialType.System_Collections_IEnumerable, bag);
EnsureSpecialMember(SpecialMember.System_Collections_IEnumerable__GetEnumerator, bag);
EnsureSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T, bag);
EnsureSpecialMember(SpecialMember.System_Collections_Generic_IEnumerable_T__GetEnumerator, bag);
}
bool hasErrors = bag.HasAnyErrors();
if (hasErrors)
{
diagnostics.AddRange(bag);
}
bag.Free();
return !hasErrors;
}
private Symbol EnsureSpecialMember(SpecialMember member, DiagnosticBag bag)
{
Symbol symbol;
Binder.TryGetSpecialTypeMember(F.Compilation, member, body.Syntax, bag, out symbol);
return symbol;
}
private void EnsureSpecialType(SpecialType type, DiagnosticBag bag)
{
Binder.GetSpecialType(F.Compilation, type, body.Syntax, bag);
}
/// <summary>
/// Check that the property and its getter exist and collect any use-site errors.
/// </summary>
private void EnsureSpecialPropertyGetter(SpecialMember member, DiagnosticBag bag)
{
PropertySymbol symbol = (PropertySymbol)EnsureSpecialMember(member, bag);
if ((object)symbol != null)
{
var getter = symbol.GetMethod;
if ((object)getter == null)
{
Binder.Error(bag, ErrorCode.ERR_PropertyLacksGet, body.Syntax, symbol);
return;
}
var info = getter.GetUseSiteDiagnostic();
if ((object)info != null)
{
bag.Add(new CSDiagnostic(info, body.Syntax.Location));
}
}
}
protected override bool PreserveInitialParameterValues
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using System;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
......@@ -2343,7 +2344,6 @@ public class NotSupportedException : Exception { }
public class ValueType { }
public class Enum { }
public struct Void { }
public interface IDisposable
{
void Dispose();
......@@ -2394,5 +2394,132 @@ public System.Collections.IEnumerable SomeNumbers()
// warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1));
}
[Fact, WorkItem(9463, "https://github.com/dotnet/roslyn/issues/9463")]
public void IEnumerableIteratorReportsDiagnosticsWhenCoreTypesAreMissing()
{
// Note that IDisposable.Dispose, IEnumerator.Current and other types are missing
// Also, IEnumerator<T> doesn't have a get accessor
var source = @"
namespace System
{
public class Object { }
public struct Int32 { }
public struct Boolean { }
public class String { }
public class Exception { }
public class ValueType { }
public class Enum { }
public struct Void { }
public interface IDisposable { }
}
namespace System.Collections
{
public interface IEnumerable { }
public interface IEnumerator { }
}
namespace System.Collections.Generic
{
public interface IEnumerator<T>
{
T Current { set; }
}
}
public class C
{
public System.Collections.IEnumerable SomeNumbers() { yield return 42; }
}";
var compilation = CreateCompilation(new[] { Parse(source) });
compilation.VerifyEmitDiagnostics(
// warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1),
// (31,57): error CS0656: Missing compiler required member 'System.IDisposable.Dispose'
// public System.Collections.IEnumerable SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ yield return 42; }").WithArguments("System.IDisposable", "Dispose").WithLocation(31, 57),
// (31,57): error CS0154: The property or indexer 'IEnumerator<T>.Current' cannot be used in this context because it lacks the get accessor
// public System.Collections.IEnumerable SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_PropertyLacksGet, "{ yield return 42; }").WithArguments("System.Collections.Generic.IEnumerator<T>.Current").WithLocation(31, 57),
// (31,57): error CS0656: Missing compiler required member 'System.Collections.IEnumerator.Current'
// public System.Collections.IEnumerable SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ yield return 42; }").WithArguments("System.Collections.IEnumerator", "Current").WithLocation(31, 57),
// (31,57): error CS0656: Missing compiler required member 'System.Collections.IEnumerator.MoveNext'
// public System.Collections.IEnumerable SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ yield return 42; }").WithArguments("System.Collections.IEnumerator", "MoveNext").WithLocation(31, 57),
// (31,57): error CS0656: Missing compiler required member 'System.Collections.IEnumerator.Reset'
// public System.Collections.IEnumerable SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ yield return 42; }").WithArguments("System.Collections.IEnumerator", "Reset").WithLocation(31, 57),
// (31,57): error CS0656: Missing compiler required member 'System.Collections.IEnumerable.GetEnumerator'
// public System.Collections.IEnumerable SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ yield return 42; }").WithArguments("System.Collections.IEnumerable", "GetEnumerator").WithLocation(31, 57),
// (31,57): error CS0518: Predefined type 'System.Collections.Generic.IEnumerable`1' is not defined or imported
// public System.Collections.IEnumerable SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "{ yield return 42; }").WithArguments("System.Collections.Generic.IEnumerable`1").WithLocation(31, 57),
// (31,57): error CS0656: Missing compiler required member 'System.Collections.Generic.IEnumerable`1.GetEnumerator'
// public System.Collections.IEnumerable SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ yield return 42; }").WithArguments("System.Collections.Generic.IEnumerable`1", "GetEnumerator").WithLocation(31, 57));
}
[Fact, WorkItem(9463, "https://github.com/dotnet/roslyn/issues/9463")]
public void IEnumeratorIteratorReportsDiagnosticsWhenCoreTypesAreMissing()
{
// Note that IDisposable.Dispose and other types are missing
// Also IEnumerator.Current lacks a get accessor
var source = @"
namespace System
{
public class Object { }
public struct Int32 { }
public struct Boolean { }
public class String { }
public class Exception { }
public class ValueType { }
public class Enum { }
public struct Void { }
public interface IDisposable { }
}
namespace System.Collections
{
public interface IEnumerable { }
public interface IEnumerator
{
Object Current { set; }
}
}
public class C
{
public System.Collections.IEnumerator SomeNumbers() { yield return 42; }
}";
var compilation = CreateCompilation(new[] { Parse(source) });
// No error about IEnumerable
compilation.VerifyEmitDiagnostics(
// (27,57): error CS0656: Missing compiler required member 'System.IDisposable.Dispose'
// public System.Collections.IEnumerator SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ yield return 42; }").WithArguments("System.IDisposable", "Dispose").WithLocation(27, 57),
// (27,57): error CS0518: Predefined type 'System.Collections.Generic.IEnumerator`1' is not defined or imported
// public System.Collections.IEnumerator SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "{ yield return 42; }").WithArguments("System.Collections.Generic.IEnumerator`1").WithLocation(27, 57),
// (27,57): error CS0656: Missing compiler required member 'System.Collections.Generic.IEnumerator`1.Current'
// public System.Collections.IEnumerator SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ yield return 42; }").WithArguments("System.Collections.Generic.IEnumerator`1", "Current").WithLocation(27, 57),
// (27,57): error CS0154: The property or indexer 'IEnumerator.Current' cannot be used in this context because it lacks the get accessor
// public System.Collections.IEnumerator SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_PropertyLacksGet, "{ yield return 42; }").WithArguments("System.Collections.IEnumerator.Current").WithLocation(27, 57),
// (27,57): error CS0656: Missing compiler required member 'System.Collections.IEnumerator.MoveNext'
// public System.Collections.IEnumerator SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ yield return 42; }").WithArguments("System.Collections.IEnumerator", "MoveNext").WithLocation(27, 57),
// (27,57): error CS0656: Missing compiler required member 'System.Collections.IEnumerator.Reset'
// public System.Collections.IEnumerator SomeNumbers() { yield return 42; }
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "{ yield return 42; }").WithArguments("System.Collections.IEnumerator", "Reset").WithLocation(27, 57),
// warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1));
}
}
}
......@@ -414,11 +414,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' <param name="node">Where to report the error, if any.</param>
Public Function GetSpecialType(typeId As SpecialType, node As SyntaxNodeOrToken, diagBag As DiagnosticBag) As NamedTypeSymbol
Dim reportedAnError As Boolean = False
Return GetSpecialType(typeId, node, diagBag, reportedAnError, suppressUseSiteError:=False)
Return GetSpecialType(SourceModule.ContainingAssembly, typeId, node, diagBag, reportedAnError, suppressUseSiteError:=False)
End Function
Public Shared Function GetSpecialType(assembly As AssemblySymbol, typeId As SpecialType, node As SyntaxNodeOrToken, diagBag As DiagnosticBag) As NamedTypeSymbol
Dim reportedAnError As Boolean = False
Return GetSpecialType(assembly, typeId, node, diagBag, reportedAnError, suppressUseSiteError:=False)
End Function
Public Function GetSpecialType(typeId As SpecialType, node As SyntaxNodeOrToken, diagBag As DiagnosticBag, ByRef reportedAnError As Boolean, suppressUseSiteError As Boolean) As NamedTypeSymbol
Dim symbol As NamedTypeSymbol = SourceModule.ContainingAssembly.GetSpecialType(typeId)
Return GetSpecialType(SourceModule.ContainingAssembly, typeId, node, diagBag, reportedAnError, suppressUseSiteError)
End Function
Public Shared Function GetSpecialType(assembly As AssemblySymbol, typeId As SpecialType, node As SyntaxNodeOrToken, diagBag As DiagnosticBag, ByRef reportedAnError As Boolean, suppressUseSiteError As Boolean) As NamedTypeSymbol
Dim symbol As NamedTypeSymbol = assembly.GetSpecialType(typeId)
If diagBag IsNot Nothing Then
Dim info = GetUseSiteErrorForSpecialType(symbol, suppressUseSiteError)
......@@ -526,8 +535,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' member isn't found.
''' </summary>
Friend Function GetSpecialTypeMember(member As SpecialMember, syntax As VisualBasicSyntaxNode, diagnostics As DiagnosticBag) As Symbol
Return GetSpecialTypeMember(Me.ContainingMember.ContainingAssembly, member, syntax, diagnostics)
End Function
Friend Shared Function GetSpecialTypeMember(assembly As AssemblySymbol, member As SpecialMember, syntax As VisualBasicSyntaxNode, diagnostics As DiagnosticBag) As Symbol
Dim useSiteError As DiagnosticInfo = Nothing
Dim specialMemberSymbol As Symbol = GetSpecialTypeMember(Me.ContainingMember.ContainingAssembly, member, useSiteError)
Dim specialMemberSymbol As Symbol = GetSpecialTypeMember(assembly, member, useSiteError)
If useSiteError IsNot Nothing Then
ReportDiagnostic(diagnostics, syntax, useSiteError)
......
......@@ -79,38 +79,51 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return rewriter.Rewrite()
End Function
''' <returns>
''' Returns true if any members that we need are missing or have use-site errors.
''' </returns>
Friend Overrides Function EnsureAllSymbolsAndSignature() As Boolean
Dim hasErrors As Boolean = MyBase.EnsureAllSymbolsAndSignature
If Me.Method.IsSub OrElse Me._elementType.IsErrorType Then
hasErrors = True
If MyBase.EnsureAllSymbolsAndSignature OrElse Me.Method.IsSub OrElse Me._elementType.IsErrorType Then
Return True
End If
Dim bag = DiagnosticBag.GetInstance()
' NOTE: We don't ensure DebuggerStepThroughAttribute, it is just not emitted if not found
' EnsureWellKnownMember(Of MethodSymbol)(WellKnownMember.System_Diagnostics_DebuggerStepThroughAttribute__ctor, hasErrors)
' TODO: do we need these here? They are used on the actual iterator method.
' EnsureWellKnownMember(Of MethodSymbol)(WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachine__ctor, hasErrors)
EnsureSpecialType(SpecialType.System_Object, hasErrors)
EnsureSpecialType(SpecialType.System_Boolean, hasErrors)
EnsureSpecialType(SpecialType.System_Int32, hasErrors)
If Me.Method.ReturnType.IsDefinition Then
If Me._isEnumerable Then
EnsureSpecialType(SpecialType.System_Collections_IEnumerator, hasErrors)
End If
Else
If Me._isEnumerable Then
EnsureSpecialType(SpecialType.System_Collections_Generic_IEnumerator_T, hasErrors)
EnsureSpecialType(SpecialType.System_Collections_IEnumerable, hasErrors)
End If
EnsureSpecialType(SpecialType.System_Collections_IEnumerator, hasErrors)
EnsureSpecialType(SpecialType.System_Object, bag)
EnsureSpecialType(SpecialType.System_Boolean, bag)
EnsureSpecialType(SpecialType.System_Int32, bag)
EnsureSpecialType(SpecialType.System_IDisposable, bag)
EnsureSpecialMember(SpecialMember.System_IDisposable__Dispose, bag)
' IEnumerator
EnsureSpecialType(SpecialType.System_Collections_IEnumerator, bag)
EnsureSpecialPropertyGetter(SpecialMember.System_Collections_IEnumerator__Current, bag)
EnsureSpecialMember(SpecialMember.System_Collections_IEnumerator__MoveNext, bag)
EnsureSpecialMember(SpecialMember.System_Collections_IEnumerator__Reset, bag)
' IEnumerator(Of T)
EnsureSpecialType(SpecialType.System_Collections_Generic_IEnumerator_T, bag)
EnsureSpecialPropertyGetter(SpecialMember.System_Collections_Generic_IEnumerator_T__Current, bag)
If Me._isEnumerable Then
EnsureSpecialType(SpecialType.System_Collections_IEnumerable, bag)
EnsureSpecialMember(SpecialMember.System_Collections_IEnumerable__GetEnumerator, bag)
EnsureSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T, bag)
EnsureSpecialMember(SpecialMember.System_Collections_Generic_IEnumerable_T__GetEnumerator, bag)
End If
EnsureSpecialType(SpecialType.System_IDisposable, hasErrors)
Dim hasErrors As Boolean = bag.HasAnyErrors
If hasErrors Then
Me.Diagnostics.AddRange(bag)
End If
bag.Free()
Return hasErrors
End Function
......
......@@ -368,6 +368,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return False
End Function
Friend Function EnsureSpecialType(type As SpecialType, bag As DiagnosticBag) As Symbol
Return Binder.GetSpecialType(F.Compilation.Assembly, type, Me.Body.Syntax, bag)
End Function
Friend Sub EnsureSpecialType(type As SpecialType, <[In], Out> ByRef hasErrors As Boolean)
Dim sType = Me.F.SpecialType(type)
If sType.GetUseSiteErrorInfo IsNot Nothing Then
......@@ -375,6 +379,31 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End If
End Sub
Friend Function EnsureSpecialMember(member As SpecialMember, bag As DiagnosticBag) As Symbol
Return Binder.GetSpecialTypeMember(F.Compilation.Assembly, member, Me.Body.Syntax, bag)
End Function
''' <summary>
''' Check that the property and its getter exist and collect any use-site errors.
''' </summary>
Friend Sub EnsureSpecialPropertyGetter(member As SpecialMember, bag As DiagnosticBag)
Dim symbol = DirectCast(EnsureSpecialMember(member, bag), PropertySymbol)
If symbol IsNot Nothing Then
Dim getter = symbol.GetMethod
If getter Is Nothing Then
Binder.ReportDiagnostic(bag, Body.Syntax, ERRID.ERR_NoGetProperty1, CustomSymbolDisplayFormatter.QualifiedName(symbol))
Return
End If
Dim useSiteError = getter.GetUseSiteErrorInfo()
If useSiteError IsNot Nothing Then
Binder.ReportDiagnostic(bag, Body.Syntax, useSiteError)
End If
End If
End Sub
Friend Sub EnsureWellKnownType(type As WellKnownType, <[In], Out> ByRef hasErrors As Boolean)
Dim wkType = Me.F.WellKnownType(type)
If wkType.GetUseSiteErrorInfo IsNot Nothing Then
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Roslyn.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests
......@@ -1688,5 +1689,146 @@ End Class
Dim verifier = CompileAndVerify(compilation, verify:=False)
verifier.VerifyDiagnostics()
End Sub
<Fact, WorkItem(9463, "https://github.com/dotnet/roslyn/issues/9463")>
Public Sub IEnumerableIteratorReportsDiagnosticsWhenCoreTypesAreMissing()
' Note that IDisposable.Dispose, IEnumerator.Current and other types are missing
' Also, IEnumerator(Of T) doesn't have a get accessor
Dim source = "
Namespace System
Public Class [Object]
End Class
Public Class [Int32]
End Class
Public Class [Boolean]
End Class
Public Class [String]
End Class
Public Class Exception
End Class
Public Class ValueType
End Class
Public Class [Enum]
End Class
Public Class Void
End Class
Public Interface IDisposable
End Interface
End Namespace
Namespace System.Collections
Public Interface IEnumerable
End Interface
Public Interface IEnumerator
End Interface
End Namespace
Namespace System.Collections.Generic
Public Interface IEnumerator(Of T)
WriteOnly Property Current As T
End Interface
End Namespace
Class C
Public Iterator Function SomeNumbers() As System.Collections.IEnumerable
Yield Nothing
End Function
End Class
"
Dim compilation = CreateCompilation({Parse(source)})
compilation.AssertTheseEmitDiagnostics(<expected>
BC30002: Type 'System.Collections.Generic.IEnumerable' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC30524: Property 'System.Collections.Generic.IEnumerator(Of T).Current' is 'WriteOnly'.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Collections.Generic.IEnumerable`1.GetEnumerator' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Collections.IEnumerable.GetEnumerator' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Collections.IEnumerator.Current' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Collections.IEnumerator.MoveNext' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Collections.IEnumerator.Reset' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.IDisposable.Dispose' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
</expected>)
End Sub
<Fact, WorkItem(9463, "https://github.com/dotnet/roslyn/issues/9463")>
Public Sub IEnumeratorIteratorReportsDiagnosticsWhenCoreTypesAreMissing()
' Note that IDisposable.Dispose and other types are missing
' Also IEnumerator.Current lacks a get accessor
Dim source = "
Namespace System
Public Class [Object]
End Class
Public Class [Int32]
End Class
Public Class [Boolean]
End Class
Public Class [String]
End Class
Public Class Exception
End Class
Public Class ValueType
End Class
Public Class [Enum]
End Class
Public Class Void
End Class
Public Interface IDisposable
End Interface
End Namespace
Namespace System.Collections
Public Interface IEnumerable
End Interface
Public Interface IEnumerator
WriteOnly Property Current As Object
End Interface
End Namespace
Class C
Public Iterator Function SomeNumbers() As System.Collections.IEnumerator
Yield Nothing
End Function
End Class
"
Dim compilation = CreateCompilation({Parse(source)})
' No error about IEnumerable
compilation.AssertTheseEmitDiagnostics(<expected>
BC30002: Type 'System.Collections.Generic.IEnumerator' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC30524: Property 'System.Collections.IEnumerator.Current' is 'WriteOnly'.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Collections.Generic.IEnumerator`1.Current' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Collections.IEnumerator.MoveNext' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.Collections.IEnumerator.Reset' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BC35000: Requested operation is not available because the runtime library function 'System.IDisposable.Dispose' is not defined.
Public Iterator Function SomeNumbers() As System.Collections.IEnumerator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
</expected>)
End Sub
End Class
End Namespace
......@@ -441,10 +441,13 @@ public static string GetAssertMessage<T>(IEnumerable<T> expected, IEnumerable<T>
}
}
var expectedString = string.Join(itemSeparator, expected.Select(itemInspector));
var actualString = string.Join(itemSeparator, actual.Select(itemInspector));
var message = new StringBuilder();
message.AppendLine();
message.AppendLine("Expected:");
message.AppendLine(expectedString);
message.AppendLine("Actual:");
message.AppendLine(actualString);
message.AppendLine("Differences:");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册