internal static ImmutableArray<byte> EmitToArray( this Compilation compilation, EmitOptions options = null, CompilationTestData testData = null, DiagnosticDescription[] expectedWarnings = null) { var stream = new MemoryStream(); MemoryStream pdbStream = (compilation.Options.OptimizationLevel == OptimizationLevel.Debug) && !CLRHelpers.IsRunningOnMono() ? new MemoryStream() : null; var emitResult = compilation.Emit( peStream: stream, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, manifestResources: null, options: options, testData: testData, getHostDiagnostics: null, cancellationToken: default(CancellationToken)); Assert.True(emitResult.Success, "Diagnostics:\r\n" + string.Join("\r\n", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } return stream.ToImmutable(); }
protected override Task VerifyAsync(string source, string language, DiagnosticAnalyzer[] analyzers, DiagnosticDescription[] diagnostics, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false, string rootNamespace = null) { Assert.True(analyzers != null && analyzers.Length > 0, "Must specify at least one diagnostic analyzer to test suppression"); var compilation = CreateCompilation(source, language, analyzers, rootNamespace); compilation.VerifyAnalyzerDiagnostics(analyzers, onAnalyzerException: onAnalyzerException, logAnalyzerExceptionAsDiagnostics: logAnalyzerExceptionAsDiagnostics, expected: diagnostics); return Task.FromResult(false); }
internal static ImmutableArray<byte> EmitToArray( this Compilation compilation, bool metadataOnly = false, CompilationTestData testData = null, DiagnosticDescription[] expectedWarnings = null) { var stream = new MemoryStream(); var emitResult = compilation.Emit( peStream: stream, outputName: null, pdbFilePath: null, pdbStream: null, xmlDocumentationStream: null, cancellationToken: default(CancellationToken), win32Resources: null, manifestResources: null, metadataOnly: metadataOnly, testData: testData); Assert.True(emitResult.Success, "Diagnostics:\r\n" + string.Join("\r\n, ", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } return stream.ToImmutable(); }
public static MemoryStream EmitToStream(this Compilation compilation, EmitOptions options = null, DiagnosticDescription[] expectedWarnings = null) { var stream = new MemoryStream(); var emitResult = compilation.Emit(stream, options: options); Assert.True(emitResult.Success, "Diagnostics: " + string.Join(", ", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } stream.Position = 0; return stream; }
public static Stream EmitToStream(this Compilation compilation, bool metadataOnly = false, DiagnosticDescription[] expectedWarnings = null) { var stream = new MemoryStream(); var emitResult = metadataOnly ? compilation.EmitMetadataOnly(stream) : compilation.Emit(stream); Assert.True(emitResult.Success, "Diagnostics: " + string.Join(", ", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } stream.Position = 0; return stream; }
protected override void Verify(string source, string language, DiagnosticAnalyzer[] analyzers, DiagnosticDescription[] expectedDiagnostics, Func<Exception, DiagnosticAnalyzer, bool> continueOnAnalyzerException = null, string rootNamespace = null) { using (var workspace = CreateWorkspaceFromFile(source, language, rootNamespace)) { var documentId = workspace.Documents[0].Id; var document = workspace.CurrentSolution.GetDocument(documentId); var span = document.GetSyntaxRootAsync().Result.FullSpan; var actualDiagnostics = new List<Diagnostic>(); foreach (var analyzer in analyzers) { actualDiagnostics.AddRange(DiagnosticProviderTestUtilities.GetAllDiagnostics(analyzer, document, span, donotCatchAnalyzerExceptions: continueOnAnalyzerException == null)); } actualDiagnostics.Verify(expectedDiagnostics); } }
public static MetadataReference EmitToImageReference( this Compilation comp, EmitOptions options = null, bool embedInteropTypes = false, ImmutableArray<string> aliases = default(ImmutableArray<string>), DiagnosticDescription[] expectedWarnings = null) { var image = comp.EmitToArray(options, expectedWarnings: expectedWarnings); if (comp.Options.OutputKind == OutputKind.NetModule) { return ModuleMetadata.CreateFromImage(image).GetReference(display: comp.MakeSourceModuleName()); } else { return AssemblyMetadata.CreateFromImage(image).GetReference(aliases: aliases, embedInteropTypes: embedInteropTypes, display: comp.MakeSourceAssemblySimpleName()); } }
protected override async Task VerifyAsync(string source, string language, DiagnosticAnalyzer[] analyzers, DiagnosticDescription[] expectedDiagnostics, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = true, string rootNamespace = null) { using (var workspace = await CreateWorkspaceFromFileAsync(source, language, rootNamespace)) { var documentId = workspace.Documents[0].Id; var document = workspace.CurrentSolution.GetDocument(documentId); var span = (await document.GetSyntaxRootAsync()).FullSpan; var actualDiagnostics = new List<Diagnostic>(); foreach (var analyzer in analyzers) { actualDiagnostics.AddRange( await DiagnosticProviderTestUtilities.GetAllDiagnosticsAsync(analyzer, document, span, onAnalyzerException, logAnalyzerExceptionAsDiagnostics)); } actualDiagnostics.Verify(expectedDiagnostics); } }
internal static ImmutableArray<byte> EmitToArray( this Compilation compilation, EmitOptions options = null, CompilationTestData testData = null, DiagnosticDescription[] expectedWarnings = null, Stream pdbStream = null, IMethodSymbol debugEntryPoint = null, Stream sourceLinkStream = null, IEnumerable<EmbeddedText> embeddedTexts = null) { var peStream = new MemoryStream(); if (pdbStream == null && compilation.Options.OptimizationLevel == OptimizationLevel.Debug && options?.DebugInformationFormat != DebugInformationFormat.Embedded) { if (MonoHelpers.IsRunningOnMono()) { options = (options ?? EmitOptions.Default).WithDebugInformationFormat(DebugInformationFormat.PortablePdb); } pdbStream = new MemoryStream(); } var emitResult = compilation.Emit( peStream: peStream, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, manifestResources: null, options: options, debugEntryPoint: debugEntryPoint, sourceLinkStream: sourceLinkStream, embeddedTexts: embeddedTexts, testData: testData, cancellationToken: default(CancellationToken)); Assert.True(emitResult.Success, "Diagnostics:\r\n" + string.Join("\r\n", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } return peStream.ToImmutable(); }
internal static ImmutableArray<byte> EmitToArray( this Compilation compilation, bool metadataOnly = false, bool debug = false, CompilationTestData testData = null, Guid mvid = default(Guid), DiagnosticDescription[] expectedWarnings = null) { var stream = new MemoryStream(); if (mvid == default(Guid)) { mvid = Guid.NewGuid(); } var emitResult = compilation.Emit( executableStream: stream, outputName: null, pdbFilePath: debug ? "Compilation.pdb" : null, pdbStream: debug ? new MemoryStream() : null, xmlDocStream: null, cancellationToken: default(CancellationToken), win32Resources: null, manifestResources: null, moduleVersionId: mvid, metadataOnly: metadataOnly, testData: testData); Assert.True(emitResult.Success, "Diagnostics: " + string.Join(", ", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } return stream.ToImmutable(); }
public void CannotEmbedValueTupleImplicitlyReferredFromMetadata() { string piaSource = @" using System; using System.Runtime.InteropServices; [assembly: Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58257"")] [assembly: ImportedFromTypeLib(""Pia1.dll"")] public struct S<T> { } namespace System { public struct ValueTuple<T1, T2> { public ValueTuple(T1 item1, T2 item2) { } } }"; var libSource = @" public class D { public static (int, int) M() { throw new System.Exception(); } public static S<int> M2() { throw new System.Exception(); } }"; var pia = CreateCompilationWithMscorlib(piaSource, options: TestOptions.ReleaseDll, assemblyName: "pia"); pia.VerifyDiagnostics(); var lib = CreateCompilationWithMscorlib(libSource, options: TestOptions.ReleaseDll, references: new[] { pia.ToMetadataReference() }); lib.VerifyEmitDiagnostics(); string source = @" public class C { public void TestTupleFromMetadata() { D.M(); D.M2(); } public void TestTupleAssignmentFromMetadata() { var t = D.M(); t.ToString(); var t2 = D.M2(); t2.ToString(); } }"; var expectedDiagnostics = new DiagnosticDescription[] { // error CS1768: Type 'ValueTuple<T1, T2>' cannot be embedded because it has a generic argument. Consider setting the 'Embed Interop Types' property to false. Diagnostic(ErrorCode.ERR_GenericsUsedInNoPIAType).WithArguments("System.ValueTuple<T1, T2>").WithLocation(1, 1), // error CS1768: Type 'S<T>' cannot be embedded because it has a generic argument. Consider setting the 'Embed Interop Types' property to false. Diagnostic(ErrorCode.ERR_GenericsUsedInNoPIAType).WithArguments("S<T>").WithLocation(1, 1) }; var comp1 = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, references: new MetadataReference[] { pia.ToMetadataReference(embedInteropTypes: true), lib.ToMetadataReference() }); comp1.VerifyEmitDiagnostics(expectedDiagnostics); var comp2 = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, references: new MetadataReference[] { pia.EmitToImageReference(embedInteropTypes: true), lib.EmitToImageReference() }); comp2.VerifyEmitDiagnostics(expectedDiagnostics); }
private static void AppendDiagnosticDescription(StringBuilder sb, DiagnosticDescription d) { Indent(sb, 1); sb.Append(d.ToString()); }
public static string GetAssertText(DiagnosticDescription[] expected, IEnumerable<Diagnostic> actual) { var includeCompilerOutput = false; var includeDiagnosticMessagesAsComments = false; const int CSharp = 1; const int VisualBasic = 2; int language = actual.Any() && actual.First().Id.StartsWith("CS", StringComparison.Ordinal) ? CSharp : VisualBasic; if (language == CSharp) { includeDiagnosticMessagesAsComments = true; } StringBuilder assertText = new StringBuilder(); assertText.AppendLine(); // Write out the 'command line compiler output' including squiggles (easy to read debugging info in the case of a failure). // This will be useful for VB, because we can't do the inline comments. if (includeCompilerOutput) { assertText.AppendLine("Compiler output:"); foreach (Diagnostic d in actual) { Indent(assertText, 1); assertText.AppendLine(d.ToString()); Location location = d.Location; string lineText = location.SourceTree.GetText().Lines.GetLineFromPosition(location.SourceSpan.Start).ToString(); assertText.AppendLine(lineText); FileLinePositionSpan span = location.GetMappedLineSpan(); LinePosition startPosition = span.StartLinePosition; LinePosition endPosition = span.EndLinePosition; assertText.Append(' ', startPosition.Character); int endCharacter = (startPosition.Line == endPosition.Line) ? endPosition.Character : lineText.Length; assertText.Append('~', endCharacter - startPosition.Character); assertText.AppendLine(); } } // write out the error baseline as method calls int i; assertText.AppendLine("Expected:"); var expectedText = new StringBuilder(); for (i = 0; i < expected.Length; i++) { DiagnosticDescription d = expected[i]; AppendDiagnosticDescription(expectedText, d); if (i < expected.Length - 1) { expectedText.Append(","); } expectedText.AppendLine(); } assertText.Append(expectedText); // write out the actual results as method calls (copy/paste this to update baseline) assertText.AppendLine("Actual:"); var actualText = new StringBuilder(); IEnumerator<Diagnostic> e = actual.GetEnumerator(); for (i = 0; e.MoveNext(); i++) { Diagnostic d = e.Current; string message = d.ToString(); if (Regex.Match(message, @"{\d+}").Success) { Assert.True(false, "Diagnostic messages should never contain unsubstituted placeholders.\n " + message); } if (i > 0) { assertText.AppendLine(","); actualText.AppendLine(","); } if (includeDiagnosticMessagesAsComments) { Indent(assertText, 1); assertText.Append("// "); assertText.AppendLine(d.ToString()); Location l = d.Location; if (l.IsInSource) { Indent(assertText, 1); assertText.Append("// "); assertText.AppendLine(l.SourceTree.GetText().Lines.GetLineFromPosition(l.SourceSpan.Start).ToString()); } } var description = new DiagnosticDescription(d, errorCodeOnly: false, showPosition: true); AppendDiagnosticDescription(assertText, description); AppendDiagnosticDescription(actualText, description); } if (i > 0) { assertText.AppendLine(); actualText.AppendLine(); } assertText.AppendLine("Diff:"); assertText.Append(DiffUtil.DiffReport(expectedText.ToString(), actualText.ToString())); return assertText.ToString(); }
public void CannotEmbedValueTupleImplicitlyReferredFromMetadata() { string piaSource = @" using System; using System.Runtime.InteropServices; [assembly: Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58257"")] [assembly: ImportedFromTypeLib(""Pia1.dll"")] public struct S<T> { } namespace System { public struct ValueTuple<T1, T2> { public ValueTuple(T1 item1, T2 item2) { } } }"; var libSource = @" public class D { public static (int, int) M() { throw new System.Exception(); } public static S<int> M2() { throw new System.Exception(); } }"; var pia = CreateCompilationWithMscorlib(piaSource, options: TestOptions.ReleaseDll, assemblyName: "pia"); pia.VerifyDiagnostics(); var lib = CreateCompilationWithMscorlib(libSource, options: TestOptions.ReleaseDll, references: new[] { pia.ToMetadataReference() }); lib.VerifyEmitDiagnostics(); string source = @" public class C { public void TestTupleFromMetadata() { D.M(); D.M2(); } public void TestTupleAssignmentFromMetadata() { var t = D.M(); t.ToString(); var t2 = D.M2(); t2.ToString(); } }"; // We should expect errors, as generic types cannot be embedded // Issue https://github.com/dotnet/roslyn/issues/13200 tracks this var expectedDiagnostics = new DiagnosticDescription[] { }; var comp1 = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, references: new MetadataReference[] { pia.ToMetadataReference(embedInteropTypes: true), lib.ToMetadataReference() }); comp1.VerifyEmitDiagnostics(expectedDiagnostics); var comp2 = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, references: new MetadataReference[] { pia.EmitToImageReference(embedInteropTypes: true), lib.EmitToImageReference() }); comp2.VerifyEmitDiagnostics(expectedDiagnostics); }
protected virtual void Verify(string source, string language, IDiagnosticAnalyzer[] analyzers, DiagnosticDescription[] diagnostics, string rootNamespace = null) { Assert.True(analyzers != null && analyzers.Length > 0, "Must specify at least one diagnostic analyzer to test suppression"); var compilation = CreateCompilation(source, language, analyzers, rootNamespace); compilation.VerifyAnalyzerDiagnostics(analyzers, diagnostics); }
private static void VerifyGeneratedCodeAnalyzerDiagnostics(Compilation compilation, DiagnosticDescription[] expected, GeneratedCodeAnalysisFlags? generatedCodeAnalysisFlagsOpt) { var analyzers = new DiagnosticAnalyzer[] { new GeneratedCodeAnalyzer(generatedCodeAnalysisFlagsOpt) }; compilation.VerifyAnalyzerDiagnostics(analyzers, null, null, logAnalyzerExceptionAsDiagnostics: false, expected: expected); }
public static string GetAssertText(DiagnosticDescription[] expected, IEnumerable <Diagnostic> actual) { var includeCompilerOutput = false; var includeDiagnosticMessagesAsComments = false; const int CSharp = 1; const int VisualBasic = 2; var language = actual.Any() && actual.First().Id.StartsWith("CS") ? CSharp : VisualBasic; if (language == CSharp) { includeDiagnosticMessagesAsComments = true; } StringBuilder assertText = new StringBuilder(); assertText.AppendLine(); // Write out the 'command line compiler output' including squiggles (easy to read debugging info in the case of a failure). // This will be useful for VB, because we can't do the inline comments. if (includeCompilerOutput) { assertText.AppendLine("Compiler output:"); foreach (var d in actual) { Indent(assertText, 1); assertText.AppendLine(d.ToString()); var location = d.Location; var lineText = location.SourceTree.GetText().Lines.GetLineFromPosition(location.SourceSpan.Start).ToString(); assertText.AppendLine(lineText); var span = location.GetMappedLineSpan(); var startPosition = span.StartLinePosition; var endPosition = span.EndLinePosition; assertText.Append(' ', startPosition.Character); var endCharacter = (startPosition.Line == endPosition.Line) ? endPosition.Character : lineText.Length; assertText.Append('~', endCharacter - startPosition.Character); assertText.AppendLine(); } } // write out the error baseline as method calls int i; assertText.AppendLine("Expected:"); var expectedText = new StringBuilder(); for (i = 0; i < expected.Length; i++) { var d = expected[i]; AppendDiagnosticDescription(expectedText, d); if (i < expected.Length - 1) { expectedText.Append(","); } expectedText.AppendLine(); } assertText.Append(expectedText); // write out the actual results as method calls (copy/paste this to update baseline) assertText.AppendLine("Actual:"); var actualText = new StringBuilder(); var e = actual.GetEnumerator(); for (i = 0; e.MoveNext(); i++) { var d = e.Current; string message = d.ToString(); if (Regex.Match(message, @"{\d+}").Success) { Assert.True(false, "Diagnostic messages should never contain unsubstituted placeholders.\n " + message); } if (i > 0) { assertText.AppendLine(","); actualText.AppendLine(","); } if (includeDiagnosticMessagesAsComments) { Indent(assertText, 1); assertText.Append("// "); assertText.AppendLine(d.ToString()); var l = d.Location; if (l.IsInSource) { Indent(assertText, 1); assertText.Append("// "); assertText.AppendLine(l.SourceTree.GetText().Lines.GetLineFromPosition(l.SourceSpan.Start).ToString()); } } var description = new DiagnosticDescription(d, errorCodeOnly: false, showPosition: true); AppendDiagnosticDescription(assertText, description); AppendDiagnosticDescription(actualText, description); } if (i > 0) { assertText.AppendLine(); actualText.AppendLine(); } assertText.AppendLine("Diff:"); assertText.Append(DiffUtil.DiffReport(expectedText.ToString(), actualText.ToString())); return(assertText.ToString()); }
public static string GetAssertText(DiagnosticDescription[] expected, IEnumerable <Diagnostic> actual) { const int CSharp = 1; const int VisualBasic = 2; var language = actual.Any() && actual.First().Id.StartsWith("CS", StringComparison.Ordinal) ? CSharp : VisualBasic; var includeDiagnosticMessagesAsComments = (language == CSharp); int indentDepth = (language == CSharp) ? 4 : 1; StringBuilder assertText = new StringBuilder(); assertText.AppendLine(); // write out the error baseline as method calls int i; assertText.AppendLine("Expected:"); var expectedText = new StringBuilder(); for (i = 0; i < expected.Length; i++) { var d = expected[i]; AppendDiagnosticDescription(expectedText, d, indentDepth); if (i < expected.Length - 1) { expectedText.Append(","); } expectedText.AppendLine(); } assertText.Append(expectedText); // write out the actual results as method calls (copy/paste this to update baseline) assertText.AppendLine("Actual:"); var actualText = new StringBuilder(); var e = actual.GetEnumerator(); for (i = 0; e.MoveNext(); i++) { var d = e.Current; string message = d.ToString(); if (Regex.Match(message, @"{\d+}").Success) { Assert.True(false, "Diagnostic messages should never contain unsubstituted placeholders.\n " + message); } if (i > 0) { assertText.AppendLine(","); actualText.AppendLine(","); } if (includeDiagnosticMessagesAsComments) { Indent(assertText, indentDepth); assertText.Append("// "); assertText.AppendLine(d.ToString()); var l = d.Location; if (l.IsInSource) { Indent(assertText, indentDepth); assertText.Append("// "); assertText.AppendLine(l.SourceTree.GetText().Lines.GetLineFromPosition(l.SourceSpan.Start).ToString()); } } var description = new DiagnosticDescription(d, errorCodeOnly: false); var diffDescription = description; var idx = Array.IndexOf(expected, description); if (idx != -1) { diffDescription = expected[idx]; } AppendDiagnosticDescription(assertText, description, indentDepth); AppendDiagnosticDescription(actualText, diffDescription, indentDepth); } if (i > 0) { assertText.AppendLine(); actualText.AppendLine(); } assertText.AppendLine("Diff:"); assertText.Append(DiffUtil.DiffReport(expectedText.ToString(), actualText.ToString())); return(assertText.ToString()); }
protected abstract Task VerifyAsync(string source, string language, DiagnosticAnalyzer[] analyzers, DiagnosticDescription[] diagnostics, Action<Exception, DiagnosticAnalyzer, Diagnostic> onAnalyzerException = null, bool logAnalyzerExceptionAsDiagnostics = false, string rootNamespace = null);
// In VB use AssertTheseErrors format for expected diagnostics! private static void VerifyEmitDiagnostics( CSharpCompilation compilation, bool metadataOnlyShouldSucceed, DiagnosticDescription[] expectedFullBuildDiagnostics, DiagnosticDescription[] expectedMetadataOnlyDiagnostics = null) { using (var executableStream = new MemoryStream()) { var result = compilation.Emit(executableStream); Assert.False(result.Success); result.Diagnostics.Verify(expectedFullBuildDiagnostics); } using (var executableStream = new MemoryStream()) { var result = compilation.Emit(executableStream, options: new EmitOptions(metadataOnly: true)); if (metadataOnlyShouldSucceed) { Assert.True(result.Success); result.Diagnostics.Verify(); } else { Assert.False(result.Success); result.Diagnostics.Verify(expectedMetadataOnlyDiagnostics ?? expectedFullBuildDiagnostics); } } }
public void TestConcurrentAnalyzer() { if (Environment.ProcessorCount <= 1) { // Don't test for non-concurrent environment. return; } var builder = new StringBuilder(); var typeCount = 100; var typeNames = new string[typeCount]; for (int i = 1; i <= typeCount; i++) { var typeName = $"C{i}"; typeNames[i - 1] = typeName; builder.Append($"\r\nclass {typeName} {{ }}"); } var source = builder.ToString(); var compilation = GetCompilationWithConcurrentBuildEnabled(source); compilation.VerifyDiagnostics(); // Verify analyzer diagnostics for Concurrent analyzer only. var analyzers = new DiagnosticAnalyzer[] { new ConcurrentAnalyzer(typeNames) }; var expected = new DiagnosticDescription[typeCount]; for (int i = 0; i < typeCount; i++) { var typeName = $"C{i + 1}"; expected[i] = Diagnostic(ConcurrentAnalyzer.Descriptor.Id, typeName) .WithArguments(typeName) .WithLocation(i + 2, 7); } compilation.VerifyAnalyzerDiagnostics(analyzers, expected: expected); // Verify analyzer diagnostics for Concurrent and NonConcurrent analyzer together (latter reports diagnostics only for error cases). analyzers = new DiagnosticAnalyzer[] { new ConcurrentAnalyzer(typeNames), new NonConcurrentAnalyzer() }; compilation.VerifyAnalyzerDiagnostics(analyzers, expected: expected); }
public static void ParseAndValidateFirst(string text, DiagnosticDescription expectedFirstError) { var parsedTree = ParseWithRoundTripCheck(text); var actualErrors = parsedTree.GetDiagnostics(); actualErrors.Take(1).Verify(expectedFirstError); }
public void CS0472WRN_NubExprIsConstBool() { // Due to a long-standing bug, the native compiler does not produce warnings for "guid == null", // but does for "int == null". Roslyn corrects this lapse and produces warnings for both built-in // and user-defined lifted equality operators, but the new warnings for user-defined types are // only given in "strict" more. var text = @" using System; class MyClass { public static void W(bool b) { System.Console.Write(b ? 't' : 'f'); } enum E : int { }; public static void Main() { Guid g = default(Guid); Guid? h = g; int i = 0; int? n = i; W(i == null); // CS0472 W(i != null); // CS0472 W(n == null); // no error W(n != null); // no error W(g == null); // CS0472 W(g != null); // CS0472 W(h == null); // no error W(h != null); // no error W(i == default(short?)); // CS0472 W(i != default(short?)); // CS0472 W(n == default(short?)); // no error W(n != default(short?)); // no error W(g == default(Guid?)); // CS0472 W(g != default(Guid?)); // CS0472 W(h == default(Guid?)); // no error W(h != default(Guid?)); // no error W(i == new sbyte?()); // CS0472 W(i != new sbyte?()); // CS0472 W(n == new sbyte?()); // no error W(n != new sbyte?()); // no error W(g == new Guid?()); // CS0472 W(g != new Guid?()); // CS0472 W(h == new Guid?()); // no error W(h != new Guid?()); // no error System.Console.WriteLine(); W(null == i); // CS0472 W(null != i); // CS0472 W(null == n); // no error W(null != n); // no error W(null == g); // CS0472 W(null != g); // CS0472 W(null == h); // no error W(null != h); // no error W(default(long?) == i); // CS0472 W(default(long?) != i); // CS0472 W(default(long?) == n); // no error W(default(long?) != n); // no error W(default(Guid?) == g); // CS0472 W(default(Guid?) != g); // CS0472 W(default(Guid?) == h); // no error W(default(Guid?) != h); // no error W(new double?() == i); // CS0472 W(new double?() != i); // CS0472 W(new double?() == n); // no error W(new double?() != n); // no error W(new Guid?() == g); // CS0472 W(new Guid?() != g); // CS0472 W(new Guid?() == h); // no error W(new Guid?() != h); // no error System.Console.WriteLine(); W(null == null); // No error, because both sides are nullable, but of course W(null != null); // we could give a warning here as well. System.Console.WriteLine(); //check comparisons with converted constants W((E?)1 == null); W(null != (E?)1); W((int?)1 == null); W(null != (int?)1); //check comparisons when null is converted W(0 == (int?)null); W((int?)null != 0); W(0 == (E?)null); W((E?)null != 0); } } "; string expected = @"ftftftftftftftftftftftft ftftftftftftftftftftftft tf ftftftft"; var fullExpected = new DiagnosticDescription[] { // (19,11): warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?' // W(i == null); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "i == null").WithArguments("false", "int", "int?").WithLocation(19, 11), // (20,11): warning CS0472: The result of the expression is always 'true' since a value of type 'int' is never equal to 'null' of type 'int?' // W(i != null); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "i != null").WithArguments("true", "int", "int?").WithLocation(20, 11), // (23,11): warning CS8073: The result of the expression is always 'false' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(g == null); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "g == null").WithArguments("false", "System.Guid", "System.Guid?").WithLocation(23, 11), // (24,11): warning CS8073: The result of the expression is always 'true' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(g != null); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "g != null").WithArguments("true", "System.Guid", "System.Guid?").WithLocation(24, 11), // (28,11): warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'short?' // W(i == default(short?)); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "i == default(short?)").WithArguments("false", "int", "short?").WithLocation(28, 11), // (29,11): warning CS0472: The result of the expression is always 'true' since a value of type 'int' is never equal to 'null' of type 'short?' // W(i != default(short?)); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "i != default(short?)").WithArguments("true", "int", "short?").WithLocation(29, 11), // (32,11): warning CS8073: The result of the expression is always 'false' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(g == default(Guid?)); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "g == default(Guid?)").WithArguments("false", "System.Guid", "System.Guid?").WithLocation(32, 11), // (33,11): warning CS8073: The result of the expression is always 'true' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(g != default(Guid?)); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "g != default(Guid?)").WithArguments("true", "System.Guid", "System.Guid?").WithLocation(33, 11), // (37,11): warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'sbyte?' // W(i == new sbyte?()); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "i == new sbyte?()").WithArguments("false", "int", "sbyte?").WithLocation(37, 11), // (38,11): warning CS0472: The result of the expression is always 'true' since a value of type 'int' is never equal to 'null' of type 'sbyte?' // W(i != new sbyte?()); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "i != new sbyte?()").WithArguments("true", "int", "sbyte?").WithLocation(38, 11), // (41,11): warning CS8073: The result of the expression is always 'false' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(g == new Guid?()); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "g == new Guid?()").WithArguments("false", "System.Guid", "System.Guid?").WithLocation(41, 11), // (42,11): warning CS8073: The result of the expression is always 'true' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(g != new Guid?()); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "g != new Guid?()").WithArguments("true", "System.Guid", "System.Guid?").WithLocation(42, 11), // (49,11): warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?' // W(null == i); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "null == i").WithArguments("false", "int", "int?").WithLocation(49, 11), // (50,11): warning CS0472: The result of the expression is always 'true' since a value of type 'int' is never equal to 'null' of type 'int?' // W(null != i); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "null != i").WithArguments("true", "int", "int?").WithLocation(50, 11), // (53,11): warning CS8073: The result of the expression is always 'false' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(null == g); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "null == g").WithArguments("false", "System.Guid", "System.Guid?").WithLocation(53, 11), // (54,11): warning CS8073: The result of the expression is always 'true' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(null != g); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "null != g").WithArguments("true", "System.Guid", "System.Guid?").WithLocation(54, 11), // (58,11): warning CS0472: The result of the expression is always 'false' since a value of type 'long' is never equal to 'null' of type 'long?' // W(default(long?) == i); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "default(long?) == i").WithArguments("false", "long", "long?").WithLocation(58, 11), // (59,11): warning CS0472: The result of the expression is always 'true' since a value of type 'long' is never equal to 'null' of type 'long?' // W(default(long?) != i); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "default(long?) != i").WithArguments("true", "long", "long?").WithLocation(59, 11), // (62,11): warning CS8073: The result of the expression is always 'false' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(default(Guid?) == g); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "default(Guid?) == g").WithArguments("false", "System.Guid", "System.Guid?").WithLocation(62, 11), // (63,11): warning CS8073: The result of the expression is always 'true' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(default(Guid?) != g); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "default(Guid?) != g").WithArguments("true", "System.Guid", "System.Guid?").WithLocation(63, 11), // (67,11): warning CS0472: The result of the expression is always 'false' since a value of type 'double' is never equal to 'null' of type 'double?' // W(new double?() == i); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "new double?() == i").WithArguments("false", "double", "double?").WithLocation(67, 11), // (68,11): warning CS0472: The result of the expression is always 'true' since a value of type 'double' is never equal to 'null' of type 'double?' // W(new double?() != i); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "new double?() != i").WithArguments("true", "double", "double?").WithLocation(68, 11), // (71,11): warning CS8073: The result of the expression is always 'false' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(new Guid?() == g); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "new Guid?() == g").WithArguments("false", "System.Guid", "System.Guid?").WithLocation(71, 11), // (72,11): warning CS8073: The result of the expression is always 'true' since a value of type 'System.Guid' is never equal to 'null' of type 'System.Guid?' // W(new Guid?() != g); // CS0472 Diagnostic(ErrorCode.WRN_NubExprIsConstBool2, "new Guid?() != g").WithArguments("true", "System.Guid", "System.Guid?").WithLocation(72, 11), // (84,11): warning CS0472: The result of the expression is always 'false' since a value of type 'MyClass.E' is never equal to 'null' of type 'MyClass.E?' // W((E?)1 == null); Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "(E?)1 == null").WithArguments("false", "MyClass.E", "MyClass.E?").WithLocation(84, 11), // (85,11): warning CS0472: The result of the expression is always 'true' since a value of type 'MyClass.E' is never equal to 'null' of type 'MyClass.E?' // W(null != (E?)1); Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "null != (E?)1").WithArguments("true", "MyClass.E", "MyClass.E?").WithLocation(85, 11), // (87,11): warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?' // W((int?)1 == null); Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "(int?)1 == null").WithArguments("false", "int", "int?").WithLocation(87, 11), // (88,11): warning CS0472: The result of the expression is always 'true' since a value of type 'int' is never equal to 'null' of type 'int?' // W(null != (int?)1); Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "null != (int?)1").WithArguments("true", "int", "int?").WithLocation(88, 11), // (92,11): warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?' // W(0 == (int?)null); Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "0 == (int?)null").WithArguments("false", "int", "int?").WithLocation(92, 11), // (93,11): warning CS0472: The result of the expression is always 'true' since a value of type 'int' is never equal to 'null' of type 'int?' // W((int?)null != 0); Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "(int?)null != 0").WithArguments("true", "int", "int?").WithLocation(93, 11), // (95,11): warning CS0472: The result of the expression is always 'false' since a value of type 'MyClass.E' is never equal to 'null' of type 'MyClass.E?' // W(0 == (E?)null); Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "0 == (E?)null").WithArguments("false", "MyClass.E", "MyClass.E?").WithLocation(95, 11), // (96,11): warning CS0472: The result of the expression is always 'true' since a value of type 'MyClass.E' is never equal to 'null' of type 'MyClass.E?' // W((E?)null != 0); Diagnostic(ErrorCode.WRN_NubExprIsConstBool, "(E?)null != 0").WithArguments("true", "MyClass.E", "MyClass.E?").WithLocation(96, 11) }; var compatibleExpected = fullExpected.Where(d => !d.Code.Equals((int)ErrorCode.WRN_NubExprIsConstBool2)).ToArray(); this.CompileAndVerify(source: text, expectedOutput: expected).VerifyDiagnostics(compatibleExpected); this.CompileAndVerify(source: text, expectedOutput: expected, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular.WithStrictFeature()).VerifyDiagnostics(fullExpected); }
public void CannotEmbedValueTupleImplicitlyReferred_ByField() { string piaSource = @" using System; using System.Collections.Generic; using System.Runtime.InteropServices; [assembly: Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58257"")] [assembly: ImportedFromTypeLib(""Pia1.dll"")] public struct S<T> { } namespace System { public struct ValueTuple<T1, T2> { public ValueTuple(T1 item1, T2 item2) { } } } public struct Test1 { public IEnumerable<IEnumerable<(int, int)>> F; public IEnumerable<IEnumerable<S<int>>> F2; }"; var pia = CreateCompilationWithMscorlib(piaSource, options: TestOptions.ReleaseDll, assemblyName: "pia"); pia.VerifyEmitDiagnostics(); string source = @" public interface ITest2 { void M(Test1 x); } "; var expectedDiagnostics = new DiagnosticDescription[] { // error CS1768: Type 'ValueTuple<T1, T2>' cannot be embedded because it has a generic argument. Consider setting the 'Embed Interop Types' property to false. Diagnostic(ErrorCode.ERR_GenericsUsedInNoPIAType).WithArguments("System.ValueTuple<T1, T2>").WithLocation(1, 1), // error CS1768: Type 'S<T>' cannot be embedded because it has a generic argument. Consider setting the 'Embed Interop Types' property to false. Diagnostic(ErrorCode.ERR_GenericsUsedInNoPIAType).WithArguments("S<T>").WithLocation(1, 1) }; var comp1 = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, references: new MetadataReference[] { pia.ToMetadataReference(embedInteropTypes: true) }); comp1.VerifyEmitDiagnostics(expectedDiagnostics); var comp2 = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, references: new MetadataReference[] { pia.EmitToImageReference(embedInteropTypes: true) }); comp2.VerifyEmitDiagnostics(expectedDiagnostics); }
// Generate a diagnostic on every token in the specified spans, and verify that only the specified diagnostics are not suppressed private void VerifyTokenDiagnostics(string markup, string language, DiagnosticDescription[] diagnostics) { string source; IList<TextSpan> spans; MarkupTestFile.GetSpans(markup, out source, out spans); Assert.True(spans.Count > 0, "Must specify a span within which to generate diagnostics on each token"); Verify(source, language, new IDiagnosticAnalyzer[] { new WarningOnTokenAnalyzer(spans) }, diagnostics); }
public static string GetAssertText(DiagnosticDescription[] expected, IEnumerable<Diagnostic> actual) { const int CSharp = 1; const int VisualBasic = 2; var language = actual.Any() && actual.First() is CSDiagnostic ? CSharp : VisualBasic; var includeDiagnosticMessagesAsComments = (language == CSharp); int indentDepth = (language == CSharp) ? 4 : 1; var includeDefaultSeverity = expected.Any() && expected.All(d => d.DefaultSeverity != null); var includeEffectiveSeverity = expected.Any() && expected.All(d => d.EffectiveSeverity != null); if (IsSortedOrEmpty(expected)) { // If this is a new test (empty expectations) or a test that's already sorted, // we sort the actual diagnostics to minimize diff noise as diagnostics change. actual = Sort(actual); } var assertText = new StringBuilder(); assertText.AppendLine(); // write out the error baseline as method calls int i; assertText.AppendLine("Expected:"); var expectedText = ArrayBuilder<string>.GetInstance(); foreach (var d in expected) { expectedText.Add(GetDiagnosticDescription(d, indentDepth)); } GetCommaSeparatedLines(assertText, expectedText); // write out the actual results as method calls (copy/paste this to update baseline) assertText.AppendLine("Actual:"); var actualText = ArrayBuilder<string>.GetInstance(); var e = actual.GetEnumerator(); for (i = 0; e.MoveNext(); i++) { Diagnostic d = e.Current; string message = d.ToString(); if (Regex.Match(message, @"{\d+}").Success) { Assert.True(false, "Diagnostic messages should never contain unsubstituted placeholders.\n " + message); } if (i > 0) { assertText.AppendLine(","); } if (includeDiagnosticMessagesAsComments) { Indent(assertText, indentDepth); assertText.Append("// "); assertText.AppendLine(d.ToString()); var l = d.Location; if (l.IsInSource) { Indent(assertText, indentDepth); assertText.Append("// "); assertText.AppendLine(l.SourceTree.GetText().Lines.GetLineFromPosition(l.SourceSpan.Start).ToString()); } } var description = new DiagnosticDescription(d, errorCodeOnly: false, includeDefaultSeverity, includeEffectiveSeverity); var diffDescription = description; var idx = Array.IndexOf(expected, description); if (idx != -1) { diffDescription = expected[idx]; } assertText.Append(GetDiagnosticDescription(description, indentDepth)); actualText.Add(GetDiagnosticDescription(diffDescription, indentDepth)); } if (i > 0) { assertText.AppendLine(); } assertText.AppendLine("Diff:"); assertText.Append(DiffUtil.DiffReport(expectedText, actualText, separator: Environment.NewLine)); actualText.Free(); expectedText.Free(); return assertText.ToString(); }
private static string GetDiagnosticDescription(DiagnosticDescription d, int indentDepth) { return new string(' ', 4 * indentDepth) + d.ToString(); }
public void CannotEmbedValueTupleImplicitlyReferred() { string piaSource = @" using System; using System.Runtime.InteropServices; [assembly: Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58257"")] [assembly: ImportedFromTypeLib(""Pia1.dll"")] public struct S<T> { } namespace System { public struct ValueTuple<T1, T2> { public ValueTuple(T1 item1, T2 item2) { } } } [ComImport()] [Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58280"")] public interface ITest1 { (int, int) M(); S<int> M2(); }"; var pia = CreateCompilationWithMscorlib(piaSource, options: TestOptions.ReleaseDll, assemblyName: "pia"); pia.VerifyEmitDiagnostics(); string source = @" public interface ITest2 : ITest1 { } "; // We should expect errors as generic types cannot be embedded // Issue https://github.com/dotnet/roslyn/issues/13200 tracks this var expectedDiagnostics = new DiagnosticDescription[] { }; var comp1 = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, references: new MetadataReference[] { pia.ToMetadataReference(embedInteropTypes: true) }); comp1.VerifyEmitDiagnostics(expectedDiagnostics); var comp2 = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, references: new MetadataReference[] { pia.EmitToImageReference(embedInteropTypes: true) }); comp2.VerifyEmitDiagnostics(expectedDiagnostics); }
private static void CompareUnsafeDiagnostics(string template, DiagnosticDescription[] expectedWithoutUnsafe, DiagnosticDescription[] expectedWithUnsafe) { // NOTE: ERR_UnsafeNeeded is not affected by the presence/absence of the /unsafe flag. var withoutUnsafe = string.Format(template, "", ""); CreateCompilationWithMscorlib(withoutUnsafe).VerifyDiagnostics(expectedWithoutUnsafe); CreateCompilationWithMscorlib(withoutUnsafe, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(expectedWithoutUnsafe); var withUnsafeOnType = string.Format(template, "unsafe", ""); CreateCompilationWithMscorlib(withUnsafeOnType, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(expectedWithUnsafe); var withUnsafeOnMembers = string.Format(template, "", "unsafe"); CreateCompilationWithMscorlib(withUnsafeOnMembers, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(expectedWithUnsafe); var withUnsafeOnTypeAndMembers = string.Format(template, "unsafe", "unsafe"); CreateCompilationWithMscorlib(withUnsafeOnTypeAndMembers, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(expectedWithUnsafe); }
public void CannotEmbedGenericDelegateReferred_ByEvent() { string piaSource = @" using System; using System.Runtime.InteropServices; [assembly: Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58257"")] [assembly: ImportedFromTypeLib(""Pia1.dll"")] public delegate void S<T> (T x); [ComImport()] [Guid(""f9c2d51d-4f44-45f0-9eda-c9d599b58280"")] public interface ITest1 { event S<int> E; }"; var pia = CreateCompilationWithMscorlib(piaSource, options: TestOptions.ReleaseDll, assemblyName: "pia"); pia.VerifyEmitDiagnostics(); string source = @" public interface ITest2 : ITest1 { } "; var expectedDiagnostics = new DiagnosticDescription[] { // error CS1768: Type 'S<T>' cannot be embedded because it has a generic argument. Consider setting the 'Embed Interop Types' property to false. Diagnostic(ErrorCode.ERR_GenericsUsedInNoPIAType).WithArguments("S<T>").WithLocation(1, 1) }; var comp1 = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, references: new MetadataReference[] { pia.ToMetadataReference(embedInteropTypes: true) }); comp1.VerifyEmitDiagnostics(expectedDiagnostics); var comp2 = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, references: new MetadataReference[] { pia.EmitToImageReference(embedInteropTypes: true) }); comp2.VerifyEmitDiagnostics(expectedDiagnostics); }