/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Symbol/Compilation/CompilationAPITests.cs
3 684 строки
176 KB
Jan Jones
Validate pooled objects in compiler tests (#82784)
15 май 2026, 09:55
Не верифицирован
15 май 2026, 09:55
e141f0d
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Reflection.PortableExecutable; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; using static Roslyn.Test.Utilities.TestHelpers; using VB = Microsoft.CodeAnalysis.VisualBasic; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class CompilationAPITests : CSharpTestBase { private CSharpCompilationOptions WithDiagnosticOptions( SyntaxTree tree, params (string, ReportDiagnostic)[] options) => TestOptions.DebugDll.WithSyntaxTreeOptionsProvider(new TestSyntaxTreeOptionsProvider(tree, options)); [Fact] public void TreeDiagnosticOptionsDoNotAffectTreeDiagnostics() { #pragma warning disable CS0618 // This test is intentionally calling the obsolete method to assert the diagnosticOptions input is now ignored var tree = SyntaxFactory.ParseSyntaxTree(@" /// <see cref=""x...y""/> class C { }", options: CSharpParseOptions.Default.WithDocumentationMode(DocumentationMode.Diagnose), path: "", encoding: null, diagnosticOptions: CreateImmutableDictionary(("CS1584", ReportDiagnostic.Suppress)), cancellationToken: default); tree.GetDiagnostics().Verify( // (2,16): warning CS1584: XML comment has syntactically incorrect cref attribute 'x...y' // /// <see cref="x...y"/> Diagnostic(ErrorCode.WRN_BadXMLRefSyntax, "x").WithArguments("x...y").WithLocation(2, 16), // (2,17): warning CS1658: Unexpected character '.'. See also error CS1056. // /// <see cref="x...y"/> Diagnostic(ErrorCode.WRN_ErrorOverride, "").WithArguments("Unexpected character '.'", "1056").WithLocation(2, 17)); #pragma warning restore CS0618 } [Fact] public void PerTreeVsGlobalSuppress() { var tree = SyntaxFactory.ParseSyntaxTree("class C { long _f = 0l;}"); var options = TestOptions.DebugDll .WithGeneralDiagnosticOption(ReportDiagnostic.Suppress); var comp = CreateCompilation(tree, options: options); comp.VerifyDiagnostics(); options = options.WithSyntaxTreeOptionsProvider( new TestSyntaxTreeOptionsProvider((tree, new[] { ("CS0078", ReportDiagnostic.Warn) }))); comp = CreateCompilation(tree, options: options); // Syntax tree diagnostic options override global settting comp.VerifyDiagnostics( // (1,22): warning CS0078: The 'l' suffix is easily confused with the digit '1' -- use 'L' for clarity // class C { long _f = 0l;} Diagnostic(ErrorCode.WRN_LowercaseEllSuffix, "l").WithLocation(1, 22)); } [Fact] public void PerTreeDiagnosticOptionsParseWarnings() { var tree = SyntaxFactory.ParseSyntaxTree("class C { long _f = 0l;}"); var comp = CreateCompilation(tree); comp.VerifyDiagnostics( // (1,22): warning CS0078: The 'l' suffix is easily confused with the digit '1' -- use 'L' for clarity // class C { long _f = 0l;} Diagnostic(ErrorCode.WRN_LowercaseEllSuffix, "l").WithLocation(1, 22), // (1,16): warning CS0414: The field 'C._f' is assigned but its value is never used // class C { long _f = 0l;} Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_f").WithArguments("C._f").WithLocation(1, 16)); var options = WithDiagnosticOptions(tree, ("CS0078", ReportDiagnostic.Suppress)); comp = CreateCompilation(tree, options: options); comp.VerifyDiagnostics( // (1,16): warning CS0414: The field 'C._f' is assigned but its value is never used // class C { long _f = 0l;} Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_f").WithArguments("C._f").WithLocation(1, 16)); } [Fact] public void PerTreeDiagnosticOptionsVsPragma() { var tree = SyntaxFactory.ParseSyntaxTree(@" class C { #pragma warning disable CS0078 long _f = 0l; #pragma warning restore CS0078 }"); tree.GetDiagnostics().Verify(); var comp = CreateCompilation(tree); comp.VerifyDiagnostics( // (4,6): warning CS0414: The field 'C._f' is assigned but its value is never used // long _f = 0l; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_f").WithArguments("C._f").WithLocation(4, 6)); var options = WithDiagnosticOptions(tree, ("CS0078", ReportDiagnostic.Error)); comp = CreateCompilation(tree, options: options); // Pragma should have precedence over per-tree options comp.VerifyDiagnostics( // (4,6): warning CS0414: The field 'C._f' is assigned but its value is never used // long _f = 0l; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_f").WithArguments("C._f").WithLocation(4, 6)); } [Fact] public void PerTreeDiagnosticOptionsVsSpecificOptions() { var tree = SyntaxFactory.ParseSyntaxTree("class C { long _f = 0l; }"); var options = WithDiagnosticOptions(tree, ("CS0078", ReportDiagnostic.Suppress)); var comp = CreateCompilation(tree, options: options); comp.VerifyDiagnostics( // (1,16): warning CS0414: The field 'C._f' is assigned but its value is never used // class C { long _f = 0l; } Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_f").WithArguments("C._f").WithLocation(1, 16) ); options = options.WithSpecificDiagnosticOptions( CreateImmutableDictionary(("CS0078", ReportDiagnostic.Error))); var comp2 = CreateCompilation(tree, options: options); // Specific diagnostic options have precedence over per-tree options comp2.VerifyDiagnostics( // (1,16): warning CS0414: The field 'C._f' is assigned but its value is never used // class C { long _f = 0l; } Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_f").WithArguments("C._f").WithLocation(1, 16), // (1,22): error CS0078: The 'l' suffix is easily confused with the digit '1' -- use 'L' for clarity // class C { long _f = 0l; } Diagnostic(ErrorCode.WRN_LowercaseEllSuffix, "l").WithLocation(1, 22).WithWarningAsError(true)); } [Fact] public void DifferentDiagnosticOptionsForTrees() { var tree = SyntaxFactory.ParseSyntaxTree(@" class C { long _f = 0l; }"); var newTree = SyntaxFactory.ParseSyntaxTree(@" class D { long _f = 0l; }"); var options = TestOptions.DebugDll.WithSyntaxTreeOptionsProvider( new TestSyntaxTreeOptionsProvider( (tree, new[] { ("CS0078", ReportDiagnostic.Suppress) }), (newTree, new[] { ("CS0078", ReportDiagnostic.Error) }) ) ); var comp = CreateCompilation(new[] { tree, newTree }, options: options); comp.VerifyDiagnostics( // (1,23): error CS0078: The 'l' suffix is easily confused with the digit '1' -- use 'L' for clarity // class D { long _f = 0l; } Diagnostic(ErrorCode.WRN_LowercaseEllSuffix, "l").WithLocation(1, 23).WithWarningAsError(true), // (1,17): warning CS0414: The field 'D._f' is assigned but its value is never used // class D { long _f = 0l; } Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_f").WithArguments("D._f").WithLocation(1, 17), // (1,17): warning CS0414: The field 'C._f' is assigned but its value is never used // class C { long _f = 0l; } Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_f").WithArguments("C._f").WithLocation(1, 17) ); } [Fact] public void TreeOptionsComparerRespected() { var tree = SyntaxFactory.ParseSyntaxTree(@" class C { long _f = 0l; }"); // Default options have case insensitivity var options = TestOptions.DebugDll.WithSyntaxTreeOptionsProvider( new TestSyntaxTreeOptionsProvider((tree, new[] { ("cs0078", ReportDiagnostic.Suppress) })) ); CreateCompilation(tree, options: options).VerifyDiagnostics( // (1,17): warning CS0414: The field 'C._f' is assigned but its value is never used // class C { long _f = 0l; } Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_f").WithArguments("C._f").WithLocation(1, 17) ); options = TestOptions.DebugDll.WithSyntaxTreeOptionsProvider( new TestSyntaxTreeOptionsProvider( StringComparer.Ordinal, globalOption: default, (tree, new[] { ("cs0078", ReportDiagnostic.Suppress) })) ); CreateCompilation(tree, options: options).VerifyDiagnostics( // (1,23): warning CS0078: The 'l' suffix is easily confused with the digit '1' -- use 'L' for clarity // class C { long _f = 0l; } Diagnostic(ErrorCode.WRN_LowercaseEllSuffix, "l").WithLocation(1, 23), // (1,17): warning CS0414: The field 'C._f' is assigned but its value is never used // class C { long _f = 0l; } Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "_f").WithArguments("C._f").WithLocation(1, 17) ); } [Fact] public void WarningLevelRespectedForLexerWarnings() { var source = @"public class C { public long Field = 0l; }"; CreateCompilation(source).VerifyDiagnostics( // (1,39): warning CS0078: The 'l' suffix is easily confused with the digit '1' -- use 'L' for clarity // public class C { public long Field = 0l; } Diagnostic(ErrorCode.WRN_LowercaseEllSuffix, "l").WithLocation(1, 39) ); CreateCompilation(source, options: TestOptions.ReleaseDll.WithWarningLevel(0)).VerifyDiagnostics( ); } [WorkItem(8360, "https://github.com/dotnet/roslyn/issues/8360")] [WorkItem(9153, "https://github.com/dotnet/roslyn/issues/9153")] [Fact] public void PublicSignWithRelativeKeyPath() { var options = TestOptions.DebugDll .WithPublicSign(true).WithCryptoKeyFile("test.snk"); var comp = CSharpCompilation.Create("test", options: options); comp.VerifyDiagnostics( // error CS7104: Option 'CryptoKeyFile' must be an absolute path. Diagnostic(ErrorCode.ERR_OptionMustBeAbsolutePath).WithArguments("CryptoKeyFile").WithLocation(1, 1), // error CS8102: Public signing was specified and requires a public key, but no public key was specified. Diagnostic(ErrorCode.ERR_PublicSignButNoKey).WithLocation(1, 1) ); } [Fact] [WorkItem(11497, "https://github.com/dotnet/roslyn/issues/11497")] public void PublicSignWithEmptyKeyPath() { CreateCompilation("", options: TestOptions.ReleaseDll.WithPublicSign(true).WithCryptoKeyFile("")).VerifyDiagnostics( // error CS8102: Public signing was specified and requires a public key, but no public key was specified. Diagnostic(ErrorCode.ERR_PublicSignButNoKey).WithLocation(1, 1)); } [Fact] [WorkItem(11497, "https://github.com/dotnet/roslyn/issues/11497")] public void PublicSignWithEmptyKeyPath2() { CreateCompilation("", options: TestOptions.ReleaseDll.WithPublicSign(true).WithCryptoKeyFile("\"\"")).VerifyDiagnostics( // error CS8106: Option 'CryptoKeyFile' must be an absolute path. Diagnostic(ErrorCode.ERR_OptionMustBeAbsolutePath).WithArguments("CryptoKeyFile").WithLocation(1, 1), // error CS8102: Public signing was specified and requires a public key, but no public key was specified. Diagnostic(ErrorCode.ERR_PublicSignButNoKey).WithLocation(1, 1)); } [Fact] [WorkItem(233669, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=233669")] public void CompilationName() { // report an error, rather then silently ignoring the directory // (see cli partition II 22.30) CSharpCompilation.Create(@"C:/goo/Test.exe").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), // error CS8203: Invalid assembly name: Name contains invalid characters. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name contains invalid characters.").WithLocation(1, 1), // error CS5001: Program does not contain a static 'Main' method suitable for an entry point Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1) ); CSharpCompilation.Create(@"C:\goo\Test.exe").GetDeclarationDiagnostics().Verify( // error CS8203: Invalid assembly name: Name contains invalid characters. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name contains invalid characters.").WithLocation(1, 1) ); var compilationOptions = TestOptions.DebugDll.WithWarningLevel(0); CSharpCompilation.Create(@"\goo/Test.exe", options: compilationOptions).VerifyEmitDiagnostics( // error CS8203: Invalid assembly name: Name contains invalid characters. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name contains invalid characters.").WithLocation(1, 1) ); CSharpCompilation.Create(@"C:Test.exe", options: compilationOptions).VerifyEmitDiagnostics( // error CS8203: Invalid assembly name: Name contains invalid characters. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name contains invalid characters.").WithLocation(1, 1) ); CSharpCompilation.Create(@"Te\0st.exe", options: compilationOptions).VerifyEmitDiagnostics( // error CS8203: Invalid assembly name: Name contains invalid characters. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name contains invalid characters.").WithLocation(1, 1) ); CSharpCompilation.Create(@" \t ", options: compilationOptions).VerifyEmitDiagnostics( // error CS8203: Invalid assembly name: Name cannot start with whitespace. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name cannot start with whitespace.").WithLocation(1, 1) ); CSharpCompilation.Create(@"\uD800", options: compilationOptions).VerifyEmitDiagnostics( // error CS8203: Invalid assembly name: Name contains invalid characters. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name contains invalid characters.").WithLocation(1, 1) ); CSharpCompilation.Create(@"", options: compilationOptions).VerifyEmitDiagnostics( // error CS8203: Invalid assembly name: Name cannot be empty. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name cannot be empty.").WithLocation(1, 1) ); CSharpCompilation.Create(@" a", options: compilationOptions).VerifyEmitDiagnostics( // error CS8203: Invalid assembly name: Name cannot start with whitespace. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name cannot start with whitespace.").WithLocation(1, 1) ); CSharpCompilation.Create(@"\u2000a", options: compilationOptions).VerifyEmitDiagnostics( // U+20700 is whitespace // error CS8203: Invalid assembly name: Name contains invalid characters. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name contains invalid characters.").WithLocation(1, 1) ); CSharpCompilation.Create("..\\..\\RelativePath", options: compilationOptions).VerifyEmitDiagnostics( // error CS8203: Invalid assembly name: Name contains invalid characters. Diagnostic(ErrorCode.ERR_BadAssemblyName).WithArguments("Name contains invalid characters.").WithLocation(1, 1) ); // other characters than directory and volume separators are ok: CSharpCompilation.Create(@";,*?<>#!@&", options: compilationOptions).VerifyEmitDiagnostics(); CSharpCompilation.Create("goo", options: compilationOptions).VerifyEmitDiagnostics(); CSharpCompilation.Create(".goo", options: compilationOptions).VerifyEmitDiagnostics(); CSharpCompilation.Create("goo ", options: compilationOptions).VerifyEmitDiagnostics(); // can end with whitespace CSharpCompilation.Create("....", options: compilationOptions).VerifyEmitDiagnostics(); CSharpCompilation.Create(null, options: compilationOptions).VerifyEmitDiagnostics(); } [Fact] public void CreateAPITest() { var listSyntaxTree = new List<SyntaxTree>(); var listRef = new List<MetadataReference>(); var s1 = @"using Goo; namespace A.B { class C { class D { class E { } } } class G<T> { class Q<S1,S2> { } } class G<T1,T2> { } }"; SyntaxTree t1 = SyntaxFactory.ParseSyntaxTree(s1); listSyntaxTree.Add(t1); // System.dll listRef.Add(NetFramework.System.WithEmbedInteropTypes(true)); var ops = TestOptions.ReleaseExe; // Create Compilation with Option is not null var comp = CSharpCompilation.Create("Compilation", listSyntaxTree, listRef, ops); Assert.Equal(ops, comp.Options); Assert.NotEqual(default, comp.SyntaxTrees); Assert.NotNull(comp.References); Assert.Equal(1, comp.SyntaxTrees.Length); Assert.Equal(1, comp.ExternalReferences.Length); var ref1 = comp.ExternalReferences[0]; Assert.True(ref1.Properties.EmbedInteropTypes); Assert.True(ref1.Properties.Aliases.IsEmpty); // Create Compilation with PreProcessorSymbols of Option is empty var ops1 = TestOptions.DebugExe; // Create Compilation with Assembly name contains invalid char var asmname = "ÃÃâ€Â"; comp = CSharpCompilation.Create(asmname, listSyntaxTree, listRef, ops); var comp1 = CSharpCompilation.Create(asmname, listSyntaxTree, listRef, null); } [Fact] public void EmitToNonWritableStreams() { var peStream = new TestStream(canRead: false, canSeek: false, canWrite: false); var pdbStream = new TestStream(canRead: false, canSeek: false, canWrite: false); var c = CSharpCompilation.Create("a", new[] { SyntaxFactory.ParseSyntaxTree("class C { static void Main() {} }") }, new[] { MscorlibRef }); Assert.Throws<ArgumentException>(() => c.Emit(peStream)); Assert.Throws<ArgumentException>(() => c.Emit(new MemoryStream(), pdbStream)); } [Fact] public void EmitOptionsDiagnostics() { var c = CreateCompilation("class C {}"); var stream = new MemoryStream(); var options = new EmitOptions( debugInformationFormat: (DebugInformationFormat)(-1), outputNameOverride: " ", fileAlignment: 513, subsystemVersion: SubsystemVersion.Create(1000000, -1000000), pdbChecksumAlgorithm: new HashAlgorithmName("invalid hash algorithm name")); EmitResult result = c.Emit(stream, options: options); result.Diagnostics.Verify( // error CS2042: Invalid debug information format: -1 Diagnostic(ErrorCode.ERR_InvalidDebugInformationFormat).WithArguments("-1").WithLocation(1, 1), // error CS2041: Invalid output name: Name cannot start with whitespace. Diagnostic(ErrorCode.ERR_InvalidOutputName).WithArguments("Name cannot start with whitespace.").WithLocation(1, 1), // error CS2024: Invalid file section alignment '513' Diagnostic(ErrorCode.ERR_InvalidFileAlignment).WithArguments("513").WithLocation(1, 1), // error CS1773: Invalid version 1000000.-1000000 for /subsystemversion. The version must be 6.02 or greater for ARM or AppContainerExe, and 4.00 or greater otherwise Diagnostic(ErrorCode.ERR_InvalidSubsystemVersion).WithArguments("1000000.-1000000").WithLocation(1, 1), // error CS8113: Invalid hash algorithm name: 'invalid hash algorithm name' Diagnostic(ErrorCode.ERR_InvalidHashAlgorithmName).WithArguments("invalid hash algorithm name").WithLocation(1, 1)); Assert.False(result.Success); } [Fact] public void EmitOptions_PdbChecksumAndDeterminism() { var options = new EmitOptions(pdbChecksumAlgorithm: default(HashAlgorithmName)); var diagnosticBag = new DiagnosticBag(); options.ValidateOptions(diagnosticBag, MessageProvider.Instance, isDeterministic: true); diagnosticBag.Verify( // error CS8113: Invalid hash algorithm name: '' Diagnostic(ErrorCode.ERR_InvalidHashAlgorithmName).WithArguments("")); diagnosticBag.Clear(); options.ValidateOptions(diagnosticBag, MessageProvider.Instance, isDeterministic: false); diagnosticBag.Verify(); } [Fact] public void Emit_BadArgs() { var comp = CSharpCompilation.Create("Compilation", options: TestOptions.ReleaseDll); Assert.Throws<ArgumentNullException>("peStream", () => comp.Emit(peStream: null)); Assert.Throws<ArgumentException>("peStream", () => comp.Emit(peStream: new TestStream(canRead: true, canWrite: false, canSeek: true))); Assert.Throws<ArgumentException>("pdbStream", () => comp.Emit(peStream: new MemoryStream(), pdbStream: new TestStream(canRead: true, canWrite: false, canSeek: true))); Assert.Throws<ArgumentException>("pdbStream", () => comp.Emit(peStream: new MemoryStream(), pdbStream: new MemoryStream(), options: EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.Embedded))); Assert.Throws<ArgumentException>("sourceLinkStream", () => comp.Emit( peStream: new MemoryStream(), pdbStream: new MemoryStream(), options: EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), sourceLinkStream: new TestStream(canRead: false, canWrite: true, canSeek: true))); Assert.Throws<ArgumentException>("embeddedTexts", () => comp.Emit( peStream: new MemoryStream(), pdbStream: null, options: null, embeddedTexts: new[] { EmbeddedText.FromStream("_", new MemoryStream()) })); Assert.Throws<ArgumentException>("embeddedTexts", () => comp.Emit( peStream: new MemoryStream(), pdbStream: null, options: EmitOptions.Default.WithDebugInformationFormat(DebugInformationFormat.PortablePdb), embeddedTexts: new[] { EmbeddedText.FromStream("_", new MemoryStream()) })); Assert.Throws<ArgumentException>("win32Resources", () => comp.Emit( peStream: new MemoryStream(), win32Resources: new TestStream(canRead: true, canWrite: false, canSeek: false))); Assert.Throws<ArgumentException>("win32Resources", () => comp.Emit( peStream: new MemoryStream(), win32Resources: new TestStream(canRead: false, canWrite: false, canSeek: true))); // we don't report an error when we can't write to the XML doc stream: Assert.True(comp.Emit( peStream: new MemoryStream(), pdbStream: new MemoryStream(), xmlDocumentationStream: new TestStream(canRead: true, canWrite: false, canSeek: true)).Success); } [Fact] public void ReferenceAPITest() { var opt = TestOptions.DebugExe; // Create Compilation takes two args var comp = CSharpCompilation.Create("Compilation", options: TestOptions.DebugExe); var ref1 = NetFramework.mscorlib; var ref2 = NetFramework.System; var ref3 = new TestMetadataReference(fullPath: @"c:\xml.bms"); var ref4 = new TestMetadataReference(fullPath: @"c:\aaa.dll"); // Add a new empty item comp = comp.AddReferences(Enumerable.Empty<MetadataReference>()); Assert.Equal(0, comp.ExternalReferences.Length); // Add a new valid item comp = comp.AddReferences(ref1); var assemblySmb = comp.GetReferencedAssemblySymbol(ref1); Assert.NotNull(assemblySmb); Assert.Equal("mscorlib", assemblySmb.Name, StringComparer.OrdinalIgnoreCase); Assert.Equal(1, comp.ExternalReferences.Length); Assert.Equal(MetadataImageKind.Assembly, comp.ExternalReferences[0].Properties.Kind); Assert.Equal(ref1, comp.ExternalReferences[0]); // Replace an existing item with another valid item comp = comp.ReplaceReference(ref1, ref2); Assert.Equal(1, comp.ExternalReferences.Length); Assert.Equal(MetadataImageKind.Assembly, comp.ExternalReferences[0].Properties.Kind); Assert.Equal(ref2, comp.ExternalReferences[0]); // Remove an existing item comp = comp.RemoveReferences(ref2); Assert.Equal(0, comp.ExternalReferences.Length); // Overload with Hashset var hs = new HashSet<MetadataReference> { ref1, ref2, ref3 }; var compCollection = CSharpCompilation.Create("Compilation", references: hs, options: opt); compCollection = compCollection.AddReferences(ref1, ref2, ref3, ref4).RemoveReferences(hs); Assert.Equal(1, compCollection.ExternalReferences.Length); compCollection = compCollection.AddReferences(hs).RemoveReferences(ref1, ref2, ref3, ref4); Assert.Equal(0, compCollection.ExternalReferences.Length); // Overload with Collection var col = new Collection<MetadataReference> { ref1, ref2, ref3 }; compCollection = CSharpCompilation.Create("Compilation", references: col, options: opt); compCollection = compCollection.AddReferences(col).RemoveReferences(ref1, ref2, ref3); Assert.Equal(0, compCollection.ExternalReferences.Length); compCollection = compCollection.AddReferences(ref1, ref2, ref3).RemoveReferences(col); Assert.Equal(0, comp.ExternalReferences.Length); // Overload with ConcurrentStack var stack = new ConcurrentStack<MetadataReference> { }; stack.Push(ref1); stack.Push(ref2); stack.Push(ref3); compCollection = CSharpCompilation.Create("Compilation", references: stack, options: opt); compCollection = compCollection.AddReferences(stack).RemoveReferences(ref1, ref3, ref2); Assert.Equal(0, compCollection.ExternalReferences.Length); compCollection = compCollection.AddReferences(ref2, ref1, ref3).RemoveReferences(stack); Assert.Equal(0, compCollection.ExternalReferences.Length); // Overload with ConcurrentQueue var queue = new ConcurrentQueue<MetadataReference> { }; queue.Enqueue(ref1); queue.Enqueue(ref2); queue.Enqueue(ref3); compCollection = CSharpCompilation.Create("Compilation", references: queue, options: opt); compCollection = compCollection.AddReferences(queue).RemoveReferences(ref3, ref2, ref1); Assert.Equal(0, compCollection.ExternalReferences.Length); compCollection = compCollection.AddReferences(ref2, ref1, ref3).RemoveReferences(queue); Assert.Equal(0, compCollection.ExternalReferences.Length); } [Fact] public void ReferenceDirectiveTests() { var t1 = Parse(@" #r ""a.dll"" #r ""a.dll"" ", filename: "1.csx", options: TestOptions.Script); var rd1 = t1.GetRoot().GetDirectives().Cast<ReferenceDirectiveTriviaSyntax>().ToArray(); Assert.Equal(2, rd1.Length); var t2 = Parse(@" #r ""a.dll"" #r ""b.dll"" ", options: TestOptions.Script); var rd2 = t2.GetRoot().GetDirectives().Cast<ReferenceDirectiveTriviaSyntax>().ToArray(); Assert.Equal(2, rd2.Length); var t3 = Parse(@" #r ""a.dll"" ", filename: "1.csx", options: TestOptions.Script); var rd3 = t3.GetRoot().GetDirectives().Cast<ReferenceDirectiveTriviaSyntax>().ToArray(); Assert.Equal(1, rd3.Length); var t4 = Parse(@" #r ""a.dll"" ", filename: "4.csx", options: TestOptions.Script); var rd4 = t4.GetRoot().GetDirectives().Cast<ReferenceDirectiveTriviaSyntax>().ToArray(); Assert.Equal(1, rd4.Length); var c = CreateCompilationWithMscorlib461(new[] { t1, t2 }, options: TestOptions.ReleaseDll.WithMetadataReferenceResolver( new TestMetadataReferenceResolver(files: new Dictionary<string, PortableExecutableReference>() { { @"a.dll", NetFramework.MicrosoftCSharp }, { @"b.dll", NetFramework.MicrosoftVisualBasic }, }))); c.VerifyDiagnostics(); // same containing script file name and directive string Assert.Same(NetFramework.MicrosoftCSharp, c.GetDirectiveReference(rd1[0])); Assert.Same(NetFramework.MicrosoftCSharp, c.GetDirectiveReference(rd1[1])); Assert.Same(NetFramework.MicrosoftCSharp, c.GetDirectiveReference(rd2[0])); Assert.Same(NetFramework.MicrosoftVisualBasic, c.GetDirectiveReference(rd2[1])); Assert.Same(NetFramework.MicrosoftCSharp, c.GetDirectiveReference(rd3[0])); // different script name or directive string: Assert.Null(c.GetDirectiveReference(rd4[0])); } [Fact, WorkItem(530131, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530131")] public void MetadataReferenceWithInvalidAlias() { var refcomp = CSharpCompilation.Create("DLL", options: TestOptions.ReleaseDll, syntaxTrees: new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree("public class C {}") }, references: new MetadataReference[] { MscorlibRef }); var mtref = refcomp.EmitToImageReference(aliases: ImmutableArray.Create("a", "Alias(*#$@^%*&)")); // not use exported type var comp = CSharpCompilation.Create("APP", options: TestOptions.ReleaseDll, syntaxTrees: new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree( @"class D {}" ) }, references: new MetadataReference[] { MscorlibRef, mtref } ); Assert.Empty(comp.GetDiagnostics()); // use exported type with partial alias comp = CSharpCompilation.Create("APP1", options: TestOptions.ReleaseDll, syntaxTrees: new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree( @"extern alias Alias; class D : Alias::C {}" ) }, references: new MetadataReference[] { MscorlibRef, mtref } ); var errs = comp.GetDiagnostics(); // error CS0430: The extern alias 'Alias' was not specified in a /reference option Assert.Equal(430, errs.FirstOrDefault().Code); // use exported type with invalid alias comp = CSharpCompilation.Create("APP2", options: TestOptions.ReleaseExe, syntaxTrees: new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree( "extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {}", options: TestOptions.Regular9) }, references: new MetadataReference[] { MscorlibRef, mtref } ); comp.VerifyDiagnostics( // (1,21): error CS1040: Preprocessor directives must appear as the first non-whitespace character on a line // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_BadDirectivePlacement, "#").WithLocation(1, 21), // (1,61): error CS1026: ) expected // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 61), // (1,61): error CS1002: ; expected // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 61), // (1,14): error CS8112: Local function 'Alias()' must declare a body because it is not marked 'static extern'. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "Alias").WithArguments("Alias()").WithLocation(1, 14), // (1,8): error CS0246: The type or namespace name 'alias' could not be found (are you missing a using directive or an assembly reference?) // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "alias").WithArguments("alias").WithLocation(1, 8), // (1,14): warning CS0626: Method, operator, or accessor 'Alias()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "Alias").WithArguments("Alias()").WithLocation(1, 14), // (1,14): warning CS8321: The local function 'Alias' is declared but never used // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Alias").WithArguments("Alias").WithLocation(1, 14) ); } [Fact, WorkItem(530131, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530131")] public void MetadataReferenceWithInvalidAliasWithCSharp6() { var refcomp = CSharpCompilation.Create("DLL", options: TestOptions.ReleaseDll, syntaxTrees: new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree("public class C {}", options: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)) }, references: new MetadataReference[] { MscorlibRef }); var mtref = refcomp.EmitToImageReference(aliases: ImmutableArray.Create("a", "Alias(*#$@^%*&)")); // not use exported type var comp = CSharpCompilation.Create("APP", options: TestOptions.ReleaseDll, syntaxTrees: new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree( @"class D {}", options: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)) }, references: new MetadataReference[] { MscorlibRef, mtref } ); Assert.Empty(comp.GetDiagnostics()); // use exported type with partial alias comp = CSharpCompilation.Create("APP1", options: TestOptions.ReleaseDll, syntaxTrees: new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree( @"extern alias Alias; class D : Alias::C {}", options: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)) }, references: new MetadataReference[] { MscorlibRef, mtref } ); var errs = comp.GetDiagnostics(); // error CS0430: The extern alias 'Alias' was not specified in a /reference option Assert.Equal(430, errs.FirstOrDefault().Code); // use exported type with invalid alias comp = CSharpCompilation.Create("APP2", options: TestOptions.ReleaseExe, syntaxTrees: new SyntaxTree[] { SyntaxFactory.ParseSyntaxTree( "extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {}", options: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)) }, references: new MetadataReference[] { MscorlibRef, mtref } ); comp.VerifyDiagnostics( // (1,1): error CS8059: Feature 'top-level statements' is not available in C# 6. Please use language version 9.0 or greater. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {}").WithArguments("top-level statements", "9.0").WithLocation(1, 1), // (1,1): error CS8059: Feature 'extern local functions' is not available in C# 6. Please use language version 9.0 or greater. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "extern").WithArguments("extern local functions", "9.0").WithLocation(1, 1), // (1,14): error CS8059: Feature 'local functions' is not available in C# 6. Please use language version 7.0 or greater. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "Alias").WithArguments("local functions", "7.0").WithLocation(1, 14), // (1,21): error CS1040: Preprocessor directives must appear as the first non-whitespace character on a line // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_BadDirectivePlacement, "#").WithLocation(1, 21), // (1,61): error CS1026: ) expected // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_CloseParenExpected, "").WithLocation(1, 61), // (1,61): error CS1002: ; expected // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 61), // (1,14): error CS8112: Local function 'Alias()' must declare a body because it is not marked 'static extern'. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_LocalFunctionMissingBody, "Alias").WithArguments("Alias()").WithLocation(1, 14), // (1,8): error CS0246: The type or namespace name 'alias' could not be found (are you missing a using directive or an assembly reference?) // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "alias").WithArguments("alias").WithLocation(1, 8), // (1,14): warning CS0626: Method, operator, or accessor 'Alias()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "Alias").WithArguments("Alias()").WithLocation(1, 14), // (1,14): warning CS8321: The local function 'Alias' is declared but never used // extern alias Alias(*#$@^%*&); class D : Alias(*#$@^%*&).C {} Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Alias").WithArguments("Alias").WithLocation(1, 14) ); } [Fact] [ValidatePooledObjects(LeakReason = "Tests pass invalid inputs to public API, causing expected ArgumentExceptions that leak pooled objects.")] public void SyntreeAPITest() { var s1 = "namespace System.Linq {}"; var s2 = @" namespace NA.NB { partial class C<T> { public partial class D { intttt F; } } class C { } } "; var s3 = @"int x;"; var s4 = @"Imports System "; var s5 = @" class D { public static int Goo() { long l = 25l; return 0; } } "; SyntaxTree t1 = SyntaxFactory.ParseSyntaxTree(s1); SyntaxTree withErrorTree = SyntaxFactory.ParseSyntaxTree(s2); SyntaxTree withErrorTree1 = SyntaxFactory.ParseSyntaxTree(s3); SyntaxTree withErrorTreeVB = SyntaxFactory.ParseSyntaxTree(s4); SyntaxTree withExpressionRootTree = SyntaxFactory.ParseExpression(s3).SyntaxTree; var withWarning = SyntaxFactory.ParseSyntaxTree(s5); // Create compilation takes three args var comp = CSharpCompilation.Create("Compilation", syntaxTrees: new[] { SyntaxFactory.ParseSyntaxTree(s1) }, options: TestOptions.ReleaseDll); comp = comp.AddSyntaxTrees(t1, withErrorTree, withErrorTree1, withErrorTreeVB); Assert.Equal(5, comp.SyntaxTrees.Length); comp = comp.RemoveSyntaxTrees(t1, withErrorTree, withErrorTree1, withErrorTreeVB); Assert.Equal(1, comp.SyntaxTrees.Length); // Add a new empty item comp = comp.AddSyntaxTrees(Enumerable.Empty<SyntaxTree>()); Assert.Equal(1, comp.SyntaxTrees.Length); // Add a new valid item comp = comp.AddSyntaxTrees(t1); Assert.Equal(2, comp.SyntaxTrees.Length); Assert.Contains(t1, comp.SyntaxTrees); Assert.False(comp.SyntaxTrees.Contains(SyntaxFactory.ParseSyntaxTree(s1))); comp = comp.AddSyntaxTrees(SyntaxFactory.ParseSyntaxTree(s1)); Assert.Equal(3, comp.SyntaxTrees.Length); // Replace an existing item with another valid item comp = comp.ReplaceSyntaxTree(t1, SyntaxFactory.ParseSyntaxTree(s1)); Assert.Equal(3, comp.SyntaxTrees.Length); // Replace an existing item with same item comp = comp.AddSyntaxTrees(t1).ReplaceSyntaxTree(t1, t1); Assert.Equal(4, comp.SyntaxTrees.Length); // add again and verify that it throws Assert.Throws<ArgumentException>(() => comp.AddSyntaxTrees(t1)); // replace with existing and verify that it throws Assert.Throws<ArgumentException>(() => comp.ReplaceSyntaxTree(t1, comp.SyntaxTrees[0])); // SyntaxTrees have reference equality. This removal should fail. Assert.Throws<ArgumentException>(() => comp = comp.RemoveSyntaxTrees(SyntaxFactory.ParseSyntaxTree(s1))); Assert.Equal(4, comp.SyntaxTrees.Length); // Remove non-existing item Assert.Throws<ArgumentException>(() => comp = comp.RemoveSyntaxTrees(withErrorTree)); Assert.Equal(4, comp.SyntaxTrees.Length); // Add syntaxtree with error comp = comp.AddSyntaxTrees(withErrorTree1); var error = comp.GetDiagnostics(); Assert.InRange(comp.GetDiagnostics().Count(), 0, int.MaxValue); Assert.InRange(comp.GetDeclarationDiagnostics().Count(), 0, int.MaxValue); Assert.True(comp.SyntaxTrees.Contains(t1)); SyntaxTree t4 = SyntaxFactory.ParseSyntaxTree("Using System;"); SyntaxTree t5 = SyntaxFactory.ParseSyntaxTree("Usingsssssssssssss System;"); SyntaxTree t6 = SyntaxFactory.ParseSyntaxTree("Import System;"); // Overload with Hashset var hs = new HashSet<SyntaxTree> { t4, t5, t6 }; var compCollection = CSharpCompilation.Create("Compilation", syntaxTrees: hs); compCollection = compCollection.RemoveSyntaxTrees(hs); Assert.Equal(0, compCollection.SyntaxTrees.Length); compCollection = compCollection.AddSyntaxTrees(hs).RemoveSyntaxTrees(t4, t5, t6); Assert.Equal(0, compCollection.SyntaxTrees.Length); // Overload with Collection var col = new Collection<SyntaxTree> { t4, t5, t6 }; compCollection = CSharpCompilation.Create("Compilation", syntaxTrees: col); compCollection = compCollection.RemoveSyntaxTrees(t4, t5, t6); Assert.Equal(0, compCollection.SyntaxTrees.Length); Assert.Throws<ArgumentException>(() => compCollection = compCollection.AddSyntaxTrees(t4, t5).RemoveSyntaxTrees(col)); Assert.Equal(0, compCollection.SyntaxTrees.Length); // Overload with ConcurrentStack var stack = new ConcurrentStack<SyntaxTree> { }; stack.Push(t4); stack.Push(t5); stack.Push(t6); compCollection = CSharpCompilation.Create("Compilation", syntaxTrees: stack); compCollection = compCollection.RemoveSyntaxTrees(t4, t6, t5); Assert.Equal(0, compCollection.SyntaxTrees.Length); Assert.Throws<ArgumentException>(() => compCollection = compCollection.AddSyntaxTrees(t4, t6).RemoveSyntaxTrees(stack)); Assert.Equal(0, compCollection.SyntaxTrees.Length); // Overload with ConcurrentQueue var queue = new ConcurrentQueue<SyntaxTree> { }; queue.Enqueue(t4); queue.Enqueue(t5); queue.Enqueue(t6); compCollection = CSharpCompilation.Create("Compilation", syntaxTrees: queue); compCollection = compCollection.RemoveSyntaxTrees(t4, t6, t5); Assert.Equal(0, compCollection.SyntaxTrees.Length); Assert.Throws<ArgumentException>(() => compCollection = compCollection.AddSyntaxTrees(t4, t6).RemoveSyntaxTrees(queue)); Assert.Equal(0, compCollection.SyntaxTrees.Length); // Get valid binding var bind = comp.GetSemanticModel(syntaxTree: t1); Assert.Equal(t1, bind.SyntaxTree); Assert.Equal("C#", bind.Language); // Remove syntaxtree without error comp = comp.RemoveSyntaxTrees(t1); Assert.InRange(comp.GetDiagnostics().Count(), 0, int.MaxValue); // Remove syntaxtree with error comp = comp.RemoveSyntaxTrees(withErrorTree1); var e = comp.GetDiagnostics(cancellationToken: default(CancellationToken)); Assert.Equal(0, comp.GetDiagnostics(cancellationToken: default(CancellationToken)).Count()); // Add syntaxtree which is VB language comp = comp.AddSyntaxTrees(withErrorTreeVB); error = comp.GetDiagnostics(cancellationToken: CancellationToken.None); Assert.InRange(comp.GetDiagnostics().Count(), 0, int.MaxValue); comp = comp.RemoveSyntaxTrees(withErrorTreeVB); Assert.Equal(0, comp.GetDiagnostics().Count()); // Add syntaxtree with error comp = comp.AddSyntaxTrees(withWarning); error = comp.GetDeclarationDiagnostics(); Assert.InRange(error.Count(), 1, int.MaxValue); comp = comp.RemoveSyntaxTrees(withWarning); Assert.Equal(0, comp.GetDiagnostics().Count()); // Compilation.Create with syntaxtree with a non-CompilationUnit root node: should throw an ArgumentException. Assert.False(withExpressionRootTree.HasCompilationUnitRoot, "how did we get a CompilationUnit root?"); Assert.Throws<ArgumentException>(() => CSharpCompilation.Create("Compilation", new SyntaxTree[] { withExpressionRootTree })); // AddSyntaxTrees with a non-CompilationUnit root node: should throw an ArgumentException. Assert.Throws<ArgumentException>(() => comp.AddSyntaxTrees(withExpressionRootTree)); // ReplaceSyntaxTrees syntaxtree with a non-CompilationUnit root node: should throw an ArgumentException. Assert.Throws<ArgumentException>(() => comp.ReplaceSyntaxTree(comp.SyntaxTrees[0], withExpressionRootTree)); } [Fact] [ValidatePooledObjects(LeakReason = "Tests pass invalid inputs to public API, causing expected ArgumentExceptions that leak pooled objects.")] public void ChainedOperations() { var s1 = "using System.Linq;"; var s2 = ""; var s3 = "Import System"; SyntaxTree t1 = SyntaxFactory.ParseSyntaxTree(s1); SyntaxTree t2 = SyntaxFactory.ParseSyntaxTree(s2); SyntaxTree t3 = SyntaxFactory.ParseSyntaxTree(s3); var listSyntaxTree = new List<SyntaxTree>(); listSyntaxTree.Add(t1); listSyntaxTree.Add(t2); // Remove second SyntaxTree CSharpCompilation comp = CSharpCompilation.Create(options: TestOptions.ReleaseDll, assemblyName: "Compilation", references: null, syntaxTrees: null); comp = comp.AddSyntaxTrees(listSyntaxTree).RemoveSyntaxTrees(t2); Assert.Equal(1, comp.SyntaxTrees.Length); // Remove mid SyntaxTree listSyntaxTree.Add(t3); comp = comp.RemoveSyntaxTrees(t1).AddSyntaxTrees(listSyntaxTree).RemoveSyntaxTrees(t2); Assert.Equal(2, comp.SyntaxTrees.Length); // remove list listSyntaxTree.Remove(t2); comp = comp.AddSyntaxTrees().RemoveSyntaxTrees(listSyntaxTree); comp = comp.AddSyntaxTrees(listSyntaxTree).RemoveSyntaxTrees(listSyntaxTree); Assert.Equal(0, comp.SyntaxTrees.Length); listSyntaxTree.Clear(); listSyntaxTree.Add(t1); listSyntaxTree.Add(t1); // Chained operation count > 2 Assert.Throws<ArgumentException>(() => comp = comp.AddSyntaxTrees(listSyntaxTree).AddReferences().ReplaceSyntaxTree(t1, t2)); comp = comp.AddSyntaxTrees(t1).AddReferences().ReplaceSyntaxTree(t1, t2); Assert.Equal(1, comp.SyntaxTrees.Length); Assert.Equal(0, comp.ExternalReferences.Length); // Create compilation with args is disordered CSharpCompilation comp1 = CSharpCompilation.Create(assemblyName: "Compilation", syntaxTrees: null, options: TestOptions.ReleaseDll, references: null); var ref1 = NetFramework.mscorlib; var listRef = new List<MetadataReference>(); listRef.Add(ref1); listRef.Add(ref1); // Remove with no args comp1 = comp1.AddReferences(listRef).AddSyntaxTrees(t1).RemoveReferences().RemoveSyntaxTrees(); Assert.Equal(1, comp1.ExternalReferences.Length); Assert.Equal(1, comp1.SyntaxTrees.Length); } [WorkItem(713356, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/713356")] [ClrOnlyFact] public void MissedModuleA() { var netModule1 = CreateCompilation( options: TestOptions.ReleaseModule, assemblyName: "a1", source: new string[] { "public class C1 {}" }); netModule1.VerifyEmitDiagnostics(); var netModule2 = CreateCompilation( options: TestOptions.ReleaseModule, assemblyName: "a2", references: new MetadataReference[] { netModule1.EmitToImageReference() }, source: new string[] { @" public class C2 { public static void M() { var a = new C1(); } }" }); netModule2.VerifyEmitDiagnostics(); var assembly = CreateCompilation( options: TestOptions.ReleaseExe, assemblyName: "a", references: new MetadataReference[] { netModule2.EmitToImageReference() }, source: new string[] { @" public class C3 { public static void Main(string[] args) { var a = new C2(); } }" }); assembly.VerifyEmitDiagnostics( Diagnostic(ErrorCode.ERR_MissingNetModuleReference).WithArguments("a1.netmodule")); assembly = CreateCompilation( options: TestOptions.ReleaseExe, assemblyName: "a", references: new MetadataReference[] { netModule1.EmitToImageReference(), netModule2.EmitToImageReference() }, source: new string[] { @" public class C3 { public static void Main(string[] args) { var a = new C2(); } }" }); assembly.VerifyEmitDiagnostics(); // ILVerify: Assembly or module not found: a2 CompileAndVerify(assembly, verify: Verification.FailsILVerify); } [WorkItem(713356, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/713356")] [Fact] public void MissedModuleB_OneError() { var netModule1 = CreateCompilation( options: TestOptions.ReleaseModule, assemblyName: "a1", source: new string[] { "public class C1 {}" }); netModule1.VerifyEmitDiagnostics(); var netModule2 = CreateCompilation( options: TestOptions.ReleaseModule, assemblyName: "a2", references: new MetadataReference[] { netModule1.EmitToImageReference() }, source: new string[] { @" public class C2 { public static void M() { var a = new C1(); } }" }); netModule2.VerifyEmitDiagnostics(); var netModule3 = CreateCompilation( options: TestOptions.ReleaseModule, assemblyName: "a3", references: new MetadataReference[] { netModule1.EmitToImageReference() }, source: new string[] { @" public class C2a { public static void M() { var a = new C1(); } }" }); netModule3.VerifyEmitDiagnostics(); var assembly = CreateCompilation( options: TestOptions.ReleaseExe, assemblyName: "a", references: new MetadataReference[] { netModule2.EmitToImageReference(), netModule3.EmitToImageReference() }, source: new string[] { @" public class C3 { public static void Main(string[] args) { var a = new C2(); } }" }); assembly.VerifyEmitDiagnostics( Diagnostic(ErrorCode.ERR_MissingNetModuleReference).WithArguments("a1.netmodule")); } [WorkItem(718500, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/718500")] [WorkItem(716762, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/716762")] [Fact] public void MissedModuleB_NoErrorForUnmanagedModules() { var netModule1 = CreateCompilation( options: TestOptions.ReleaseModule, assemblyName: "a1", source: new string[] { @" using System; using System.Runtime.InteropServices; public class C2 { [DllImport(""user32.dll"", CharSet = CharSet.Unicode)] public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type); }" }); netModule1.VerifyEmitDiagnostics(); var assembly = CreateCompilation( options: TestOptions.ReleaseExe, assemblyName: "a", references: new MetadataReference[] { netModule1.EmitToImageReference() }, source: new string[] { @" public class C3 { public static void Main(string[] args) { var a = new C2(); } }" }); assembly.VerifyEmitDiagnostics(); } [WorkItem(715872, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/715872")] [Fact] public void MissedModuleC() { var netModule1 = CreateCompilation( options: TestOptions.ReleaseModule, assemblyName: "a1", source: new string[] { "public class C1 {}" }); netModule1.VerifyEmitDiagnostics(); var netModule2 = CreateCompilation( options: TestOptions.ReleaseModule, assemblyName: "a1", references: new MetadataReference[] { netModule1.EmitToImageReference() }, source: new string[] { @" public class C2 { public static void M() { var a = new C1(); } }" }); netModule2.VerifyEmitDiagnostics(); var assembly = CreateCompilation( options: TestOptions.ReleaseExe, assemblyName: "a", references: new MetadataReference[] { netModule1.EmitToImageReference(), netModule2.EmitToImageReference() }, source: new string[] { @" public class C3 { public static void Main(string[] args) { var a = new C2(); } }" }); assembly.VerifyEmitDiagnostics(Diagnostic(ErrorCode.ERR_NetModuleNameMustBeUnique).WithArguments("a1.netmodule")); } [Fact] public void MixedRefType() { var vbComp = VB.VisualBasicCompilation.Create("CompilationVB"); var comp = CSharpCompilation.Create("Compilation"); vbComp = vbComp.AddReferences(SystemRef); // Add VB reference to C# compilation foreach (var item in vbComp.References) { comp = comp.AddReferences(item); comp = comp.ReplaceReference(item, item); } Assert.Equal(1, comp.ExternalReferences.Length); var text1 = @"class A {}"; var comp1 = CSharpCompilation.Create("Test1", new[] { SyntaxFactory.ParseSyntaxTree(text1) }); var comp2 = CSharpCompilation.Create("Test2", new[] { SyntaxFactory.ParseSyntaxTree(text1) }); var compRef1 = comp1.ToMetadataReference(); var compRef2 = comp2.ToMetadataReference(); var compRef = vbComp.ToMetadataReference(embedInteropTypes: true); var ref1 = NetFramework.mscorlib; var ref2 = NetFramework.System; // Add CompilationReference comp = CSharpCompilation.Create( "Test1", new[] { SyntaxFactory.ParseSyntaxTree(text1) }, new MetadataReference[] { compRef1, compRef2 }); Assert.Equal(2, comp.ExternalReferences.Length); Assert.True(comp.References.Contains(compRef1)); Assert.True(comp.References.Contains(compRef2)); var smb = comp.GetReferencedAssemblySymbol(compRef1); Assert.Equal(SymbolKind.Assembly, smb.Kind); Assert.Equal("Test1", smb.Identity.Name, StringComparer.OrdinalIgnoreCase); // Mixed reference type comp = comp.AddReferences(ref1); Assert.Equal(3, comp.ExternalReferences.Length); Assert.True(comp.References.Contains(ref1)); // Replace Compilation reference with Assembly file reference comp = comp.ReplaceReference(compRef2, ref2); Assert.Equal(3, comp.ExternalReferences.Length); Assert.True(comp.References.Contains(ref2)); // Replace Assembly file reference with Compilation reference comp = comp.ReplaceReference(ref1, compRef2); Assert.Equal(3, comp.ExternalReferences.Length); Assert.True(comp.References.Contains(compRef2)); var modRef1 = TestReferences.MetadataTests.NetModule01.ModuleCS00; // Add Module file reference comp = comp.AddReferences(modRef1); // Not implemented code //var modSmb = comp.GetReferencedModuleSymbol(modRef1); //Assert.Equal("ModuleCS00.mod", modSmb.Name); //Assert.Equal(4, comp.References.Count); //Assert.True(comp.References.Contains(modRef1)); //smb = comp.GetReferencedAssemblySymbol(reference: modRef1); //Assert.Equal(smb.Kind, SymbolKind.Assembly); //Assert.Equal("Test1", smb.Identity.Name, StringComparer.OrdinalIgnoreCase); // GetCompilationNamespace Not implemented(Derived Class AssemblySymbol) //var m = smb.GlobalNamespace.GetMembers(); //var nsSmb = smb.GlobalNamespace.GetMembers("NS").Single() as NamespaceSymbol; //var ns = comp.GetCompilationNamespace(ns: nsSmb); //Assert.Equal(ns.Kind, SymbolKind.Namespace); //Assert.True(String.Equals(ns.Name, "Compilation", StringComparison.OrdinalIgnoreCase)); //var asbSmb = smb as Symbol; //var ns1 = comp.GetCompilationNamespace(ns: asbSmb as NamespaceSymbol); //Assert.Equal(ns1.Kind, SymbolKind.Namespace); //Assert.True(String.Equals(ns1.Name, "Compilation", StringComparison.OrdinalIgnoreCase)); // Get Referenced Module Symbol //var moduleSmb = comp.GetReferencedModuleSymbol(reference: modRef1); //Assert.Equal(SymbolKind.NetModule, moduleSmb.Kind); //Assert.Equal("ModuleCS00.mod", moduleSmb.Name, StringComparer.OrdinalIgnoreCase); // GetCompilationNamespace Not implemented(Derived Class ModuleSymbol) //nsSmb = moduleSmb.GlobalNamespace.GetMembers("Runtime").Single() as NamespaceSymbol; //ns = comp.GetCompilationNamespace(ns: nsSmb); //Assert.Equal(ns.Kind, SymbolKind.Namespace); //Assert.True(String.Equals(ns.Name, "Compilation", StringComparison.OrdinalIgnoreCase)); //var modSmbol = moduleSmb as Symbol; //ns1 = comp.GetCompilationNamespace(ns: modSmbol as NamespaceSymbol); //Assert.Equal(ns1.Kind, SymbolKind.Namespace); //Assert.True(String.Equals(ns1.Name, "Compilation", StringComparison.OrdinalIgnoreCase)); // Get Compilation Namespace //nsSmb = comp.GlobalNamespace; //ns = comp.GetCompilationNamespace(ns: nsSmb); //Assert.Equal(ns.Kind, SymbolKind.Namespace); //Assert.True(String.Equals(ns.Name, "Compilation", StringComparison.OrdinalIgnoreCase)); // GetCompilationNamespace Not implemented(Derived Class MergedNamespaceSymbol) //NamespaceSymbol merged = MergedNamespaceSymbol.Create(new NamespaceExtent(new MockAssemblySymbol("Merged")), null, null); //ns = comp.GetCompilationNamespace(ns: merged); //Assert.Equal(ns.Kind, SymbolKind.Namespace); //Assert.True(String.Equals(ns.Name, "Compilation", StringComparison.OrdinalIgnoreCase)); // GetCompilationNamespace Not implemented(Derived Class RetargetingNamespaceSymbol) //Retargeting.RetargetingNamespaceSymbol retargetSmb = nsSmb as Retargeting.RetargetingNamespaceSymbol; //ns = comp.GetCompilationNamespace(ns: retargetSmb); //Assert.Equal(ns.Kind, SymbolKind.Namespace); //Assert.True(String.Equals(ns.Name, "Compilation", StringComparison.OrdinalIgnoreCase)); // GetCompilationNamespace Not implemented(Derived Class PENamespaceSymbol) //Symbols.Metadata.PE.PENamespaceSymbol pensSmb = nsSmb as Symbols.Metadata.PE.PENamespaceSymbol; //ns = comp.GetCompilationNamespace(ns: pensSmb); //Assert.Equal(ns.Kind, SymbolKind.Namespace); //Assert.True(String.Equals(ns.Name, "Compilation", StringComparison.OrdinalIgnoreCase)); // Replace Module file reference with compilation reference comp = comp.RemoveReferences(compRef1).ReplaceReference(modRef1, compRef1); Assert.Equal(3, comp.ExternalReferences.Length); // Check the reference order after replace Assert.True(comp.ExternalReferences[2] is CSharpCompilationReference, "Expected compilation reference"); Assert.Equal(compRef1, comp.ExternalReferences[2]); // Replace compilation Module file reference with Module file reference comp = comp.ReplaceReference(compRef1, modRef1); // Check the reference order after replace Assert.Equal(3, comp.ExternalReferences.Length); Assert.Equal(MetadataImageKind.Module, comp.ExternalReferences[2].Properties.Kind); Assert.Equal(modRef1, comp.ExternalReferences[2]); // Add VB compilation ref Assert.Throws<ArgumentException>(() => comp.AddReferences(compRef)); foreach (var item in comp.References) { comp = comp.RemoveReferences(item); } Assert.Equal(0, comp.ExternalReferences.Length); // Not Implemented // var asmByteRef = MetadataReference.CreateFromImage(new byte[5], embedInteropTypes: true); //var asmObjectRef = new AssemblyObjectReference(assembly: System.Reflection.Assembly.GetAssembly(typeof(object)),embedInteropTypes :true); //comp =comp.AddReferences(asmByteRef, asmObjectRef); //Assert.Equal(2, comp.References.Count); //Assert.Equal(ReferenceKind.AssemblyBytes, comp.References[0].Kind); //Assert.Equal(ReferenceKind.AssemblyObject , comp.References[1].Kind); //Assert.Equal(asmByteRef, comp.References[0]); //Assert.Equal(asmObjectRef, comp.References[1]); //Assert.True(comp.References[0].EmbedInteropTypes); //Assert.True(comp.References[1].EmbedInteropTypes); } [Fact] public void NegGetCompilationNamespace() { var comp = CSharpCompilation.Create("Compilation"); // Throw exception when the parameter of GetCompilationNamespace is null Assert.Throws<NullReferenceException>( delegate { comp.GetCompilationNamespace(namespaceSymbol: (INamespaceSymbol)null); }); Assert.Throws<NullReferenceException>( delegate { comp.GetCompilationNamespace(namespaceSymbol: (NamespaceSymbol)null); }); } [WorkItem(537623, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537623")] [Fact] [ValidatePooledObjects(LeakReason = "Tests pass invalid inputs to public API, causing expected ArgumentExceptions that leak pooled objects.")] public void NegCreateCompilation() { Assert.Throws<ArgumentNullException>(() => CSharpCompilation.Create("goo", syntaxTrees: new SyntaxTree[] { null })); Assert.Throws<ArgumentNullException>(() => CSharpCompilation.Create("goo", references: new MetadataReference[] { null })); } [WorkItem(537637, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537637")] [Fact] public void NegGetSymbol() { // Create Compilation with miss mid args var comp = CSharpCompilation.Create("Compilation"); Assert.Null(comp.GetReferencedAssemblySymbol(reference: MscorlibRef)); var modRef1 = TestReferences.MetadataTests.NetModule01.ModuleCS00; // Get not exist Referenced Module Symbol Assert.Null(comp.GetReferencedModuleSymbol(modRef1)); // Throw exception when the parameter of GetReferencedAssemblySymbol is null Assert.Throws<ArgumentNullException>( delegate { comp.GetReferencedAssemblySymbol(null); }); // Throw exception when the parameter of GetReferencedModuleSymbol is null Assert.Throws<ArgumentNullException>( delegate { var modSmb1 = comp.GetReferencedModuleSymbol(null); }); } [WorkItem(537778, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537778")] // Throw exception when the parameter of the parameter type of GetReferencedAssemblySymbol is VB.CompilationReference [Fact] public void NegGetSymbol1() { var opt = TestOptions.ReleaseDll; var comp = CSharpCompilation.Create("Compilation"); var vbComp = VB.VisualBasicCompilation.Create("CompilationVB"); vbComp = vbComp.AddReferences(SystemRef); var compRef = vbComp.ToMetadataReference(); Assert.Throws<ArgumentException>(() => comp.AddReferences(compRef)); // Throw exception when the parameter of GetBinding is null Assert.Throws<ArgumentNullException>( delegate { comp.GetSemanticModel(null); }); // Throw exception when the parameter of GetTypeByNameAndArity is NULL //Assert.Throws<Exception>( //delegate //{ // comp.GetTypeByNameAndArity(fullName: null, arity: 1); //}); // Throw exception when the parameter of GetTypeByNameAndArity is less than 0 //Assert.Throws<Exception>( //delegate //{ // comp.GetTypeByNameAndArity(string.Empty, -4); //}); } // Add already existing item [Fact, WorkItem(537574, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537574")] public void NegReference2() { var ref1 = NetFramework.mscorlib; var ref2 = NetFramework.System; var ref3 = NetFramework.SystemData; var ref4 = NetFramework.SystemXml; var comp = CSharpCompilation.Create("Compilation"); comp = comp.AddReferences(ref1, ref1); Assert.Equal(1, comp.ExternalReferences.Length); Assert.Equal(MetadataImageKind.Assembly, comp.ExternalReferences[0].Properties.Kind); Assert.Equal(ref1, comp.ExternalReferences[0]); var listRef = new List<MetadataReference> { ref1, ref2, ref3, ref4 }; // Chained operation count > 3 // ReplaceReference throws if the reference to be replaced is not found. comp = comp.AddReferences(listRef).AddReferences(ref2).RemoveReferences(ref1, ref3, ref4).ReplaceReference(ref2, ref2); Assert.Equal(1, comp.ExternalReferences.Length); Assert.Equal(MetadataImageKind.Assembly, comp.ExternalReferences[0].Properties.Kind); Assert.Equal(ref2, comp.ExternalReferences[0]); Assert.Throws<ArgumentException>(() => comp.AddReferences(listRef).AddReferences(ref2).RemoveReferences(ref1, ref2, ref3, ref4).ReplaceReference(ref2, ref2)); } // Add a new invalid item [Fact, WorkItem(537575, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537575")] public void NegReference3() { var ref1 = InvalidRef; var comp = CSharpCompilation.Create("Compilation"); // Remove non-existing item Assert.Throws<ArgumentException>(() => comp = comp.RemoveReferences(ref1)); // Add a new invalid item comp = comp.AddReferences(ref1); Assert.Equal(1, comp.ExternalReferences.Length); // Replace a non-existing item with another invalid item Assert.Throws<ArgumentException>(() => comp = comp.ReplaceReference(MscorlibRef, ref1)); Assert.Equal(1, comp.ExternalReferences.Length); } // Replace a non-existing item with null [Fact, WorkItem(537567, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537567")] public void NegReference4() { var ref1 = NetFramework.mscorlib; var comp = CSharpCompilation.Create("Compilation"); Assert.Throws<ArgumentException>( delegate { comp = comp.ReplaceReference(ref1, null); }); // Replace null and the arg order of replace is vise Assert.Throws<ArgumentNullException>( delegate { comp = comp.ReplaceReference(newReference: ref1, oldReference: null); }); } // Replace a non-existing item with another valid item [Fact, WorkItem(537566, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537566")] public void NegReference5() { var ref1 = NetFramework.mscorlib; var ref2 = NetFramework.SystemXml; var comp = CSharpCompilation.Create("Compilation"); Assert.Throws<ArgumentException>( delegate { comp = comp.ReplaceReference(ref1, ref2); }); SyntaxTree t1 = SyntaxFactory.ParseSyntaxTree("Using System;"); // Replace a non-existing item with another valid item and disorder the args Assert.Throws<ArgumentException>( delegate { comp.ReplaceReference(newReference: NetFramework.System, oldReference: ref2); }); Assert.Equal(0, comp.SyntaxTrees.Length); Assert.Throws<ArgumentException>(() => comp.ReplaceSyntaxTree(newTree: SyntaxFactory.ParseSyntaxTree("Using System;"), oldTree: t1)); Assert.Equal(0, comp.SyntaxTrees.Length); } [WorkItem(527256, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527256")] // Throw exception when the parameter of SyntaxTrees.Contains is null [Fact] public void NegSyntaxTreesContains() { var comp = CSharpCompilation.Create("Compilation"); Assert.False(comp.SyntaxTrees.Contains(null)); } [WorkItem(537784, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537784")] // Throw exception when the parameter of GetSpecialType() is out of range [Fact] public void NegGetSpecialType() { var comp = CSharpCompilation.Create("Compilation"); // Throw exception when the parameter of GetBinding is out of range Assert.Throws<ArgumentOutOfRangeException>( delegate { comp.GetSpecialType((SpecialType)100); }); Assert.Throws<ArgumentOutOfRangeException>( delegate { comp.GetSpecialType(SpecialType.None); }); Assert.Throws<ArgumentOutOfRangeException>( delegate { comp.GetSpecialType((SpecialType)000); }); Assert.Throws<ArgumentOutOfRangeException>( delegate { comp.GetSpecialType(default(SpecialType)); }); } [WorkItem(538168, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538168")] // Replace a non-existing item with another valid item and disorder the args [Fact] public void NegTree2() { var comp = CSharpCompilation.Create("API"); SyntaxTree t1 = SyntaxFactory.ParseSyntaxTree("Using System;"); Assert.Throws<ArgumentException>( delegate { comp = comp.ReplaceSyntaxTree(newTree: SyntaxFactory.ParseSyntaxTree("Using System;"), oldTree: t1); }); } [WorkItem(537576, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537576")] // Add already existing item [Fact] [ValidatePooledObjects(LeakReason = "Tests intentionally pass invalid arguments to AddSyntaxTrees/RemoveSyntaxTrees, causing ArgumentExceptions that leak PooledHashSet")] public void NegSynTree1() { var comp = CSharpCompilation.Create("Compilation"); SyntaxTree t1 = SyntaxFactory.ParseSyntaxTree("Using System;"); Assert.Throws<ArgumentException>(() => (comp.AddSyntaxTrees(t1, t1))); Assert.Equal(0, comp.SyntaxTrees.Length); } [Fact] [ValidatePooledObjects(LeakReason = "Tests intentionally pass invalid arguments to AddSyntaxTrees/RemoveSyntaxTrees, causing ArgumentExceptions that leak PooledHashSet")] public void NegSynTree() { var comp = CSharpCompilation.Create("Compilation"); SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree("Using Goo;"); // Throw exception when add null SyntaxTree Assert.Throws<ArgumentNullException>( delegate { comp.AddSyntaxTrees(null); }); // Throw exception when Remove null SyntaxTree Assert.Throws<ArgumentNullException>( delegate { comp.RemoveSyntaxTrees(null); }); // No exception when replacing a SyntaxTree with null var compP = comp.AddSyntaxTrees(syntaxTree); comp = compP.ReplaceSyntaxTree(syntaxTree, null); Assert.Equal(0, comp.SyntaxTrees.Length); // Throw exception when remove null SyntaxTree Assert.Throws<ArgumentNullException>( delegate { comp = comp.ReplaceSyntaxTree(null, syntaxTree); }); var s1 = "Imports System.Text"; SyntaxTree t1 = VB.VisualBasicSyntaxTree.ParseText(s1); SyntaxTree t2 = t1; var t3 = t2; var vbComp = VB.VisualBasicCompilation.Create("CompilationVB"); vbComp = vbComp.AddSyntaxTrees(t1, VB.VisualBasicSyntaxTree.ParseText("Using Goo;")); // Throw exception when cast SyntaxTree foreach (var item in vbComp.SyntaxTrees) { t3 = item; Exception invalidCastSynTreeEx = Assert.Throws<InvalidCastException>( delegate { comp = comp.AddSyntaxTrees(t3); }); invalidCastSynTreeEx = Assert.Throws<InvalidCastException>( delegate { comp = comp.RemoveSyntaxTrees(t3); }); invalidCastSynTreeEx = Assert.Throws<InvalidCastException>( delegate { comp = comp.ReplaceSyntaxTree(t3, t3); }); } // Get Binding with tree is not exist SyntaxTree t4 = SyntaxFactory.ParseSyntaxTree(s1); Assert.Throws<ArgumentException>( delegate { comp.RemoveSyntaxTrees(new SyntaxTree[] { t4 }).GetSemanticModel(t4); }); } [Fact] public void GetEntryPoint_Exe() { var source = @" class A { static void Main() { } } "; var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics(); var mainMethod = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("A").GetMember<MethodSymbol>("Main"); Assert.Equal(mainMethod, compilation.GetEntryPoint(default(CancellationToken))); var entryPointAndDiagnostics = compilation.GetEntryPointAndDiagnostics(default(CancellationToken)); Assert.Equal(mainMethod, entryPointAndDiagnostics.MethodSymbol); entryPointAndDiagnostics.Diagnostics.Verify(); } [Fact] public void GetEntryPoint_Dll() { var source = @" class A { static void Main() { } } "; var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll); compilation.VerifyDiagnostics(); Assert.Null(compilation.GetEntryPoint(default(CancellationToken))); Assert.Same(CSharpCompilation.EntryPoint.None, compilation.GetEntryPointAndDiagnostics(default(CancellationToken))); } [Fact] public void GetEntryPoint_Module() { var source = @" class A { static void Main() { } } "; var compilation = CreateCompilation(source, options: TestOptions.ReleaseModule); compilation.VerifyDiagnostics(); Assert.Null(compilation.GetEntryPoint(default(CancellationToken))); Assert.Same(CSharpCompilation.EntryPoint.None, compilation.GetEntryPointAndDiagnostics(default(CancellationToken))); } [Fact] public void CreateCompilationForModule() { var source = @" class A { static void Main() { } } "; // equivalent of csc with no /moduleassemblyname specified: var compilation = CSharpCompilation.Create(assemblyName: null, options: TestOptions.ReleaseModule, syntaxTrees: new[] { Parse(source) }, references: new[] { MscorlibRef }); compilation.VerifyEmitDiagnostics(); Assert.Null(compilation.AssemblyName); Assert.Equal("?", compilation.Assembly.Name); Assert.Equal("?", compilation.Assembly.Identity.Name); // no name is allowed for assembly as well, although it isn't useful: compilation = CSharpCompilation.Create(assemblyName: null, options: TestOptions.ReleaseDll, syntaxTrees: new[] { Parse(source) }, references: new[] { MscorlibRef }); compilation.VerifyEmitDiagnostics(); Assert.Null(compilation.AssemblyName); Assert.Equal("?", compilation.Assembly.Name); Assert.Equal("?", compilation.Assembly.Identity.Name); // equivalent of csc with /moduleassemblyname specified: compilation = CSharpCompilation.Create(assemblyName: "ModuleAssemblyName", options: TestOptions.ReleaseModule, syntaxTrees: new[] { Parse(source) }, references: new[] { MscorlibRef }); compilation.VerifyDiagnostics(); Assert.Equal("ModuleAssemblyName", compilation.AssemblyName); Assert.Equal("ModuleAssemblyName", compilation.Assembly.Name); Assert.Equal("ModuleAssemblyName", compilation.Assembly.Identity.Name); } [WorkItem(8506, "https://github.com/dotnet/roslyn/issues/8506")] [WorkItem(17403, "https://github.com/dotnet/roslyn/issues/17403")] [Fact] public void CrossCorlibSystemObjectReturnType_Script() { // MinAsyncCorlibRef corlib is used since it provides just enough corlib type definitions // and Task APIs necessary for script hosting are provided by MinAsyncRef. This ensures that // `System.Object, mscorlib, Version=4.0.0.0` will not be provided (since it's unversioned). // // In the original bug, Xamarin iOS, Android, and Mac Mobile profile corlibs were // realistic cross-compilation targets. void AssertCompilationCorlib(CSharpCompilation compilation) { Assert.True(compilation.IsSubmission); var taskOfT = compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T); var taskOfObject = taskOfT.Construct(compilation.ObjectType); var entryPoint = compilation.GetEntryPoint(default(CancellationToken)); Assert.Same(compilation.ObjectType.ContainingAssembly, taskOfT.ContainingAssembly); Assert.Same(compilation.ObjectType.ContainingAssembly, taskOfObject.ContainingAssembly); Assert.Equal(taskOfObject, entryPoint.ReturnType); } var firstCompilation = CSharpCompilation.CreateScriptCompilation( "submission-assembly-1", references: new[] { MinAsyncCorlibRef }, syntaxTree: Parse("true", options: TestOptions.Script) ).VerifyDiagnostics(); AssertCompilationCorlib(firstCompilation); var secondCompilation = CSharpCompilation.CreateScriptCompilation( "submission-assembly-2", previousScriptCompilation: firstCompilation, syntaxTree: Parse("false", options: TestOptions.Script)) .WithScriptCompilationInfo(new CSharpScriptCompilationInfo(firstCompilation, null, null)) .VerifyDiagnostics(); AssertCompilationCorlib(secondCompilation); Assert.Same(firstCompilation.ObjectType, secondCompilation.ObjectType); Assert.Null(new CSharpScriptCompilationInfo(null, null, null) .WithPreviousScriptCompilation(firstCompilation) .ReturnTypeOpt); } [WorkItem(3719, "https://github.com/dotnet/roslyn/issues/3719")] [Fact] public void GetEntryPoint_Script() { var source = @"System.Console.WriteLine(1);"; var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Script); compilation.VerifyDiagnostics(); var scriptMethod = compilation.GetMember<MethodSymbol>("Script.<Main>"); Assert.NotNull(scriptMethod); var method = compilation.GetEntryPoint(default(CancellationToken)); Assert.Equal(method, scriptMethod); var entryPoint = compilation.GetEntryPointAndDiagnostics(default(CancellationToken)); Assert.Equal(entryPoint.MethodSymbol, scriptMethod); } [Fact] public void GetEntryPoint_Script_MainIgnored() { var source = @" class A { static void Main() { } } "; var compilation = CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Script); compilation.VerifyDiagnostics( // (4,17): warning CS7022: The entry point of the program is global script code; ignoring 'A.Main()' entry point. // static void Main() { } Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("A.Main()").WithLocation(4, 17)); var scriptMethod = compilation.GetMember<MethodSymbol>("Script.<Main>"); Assert.NotNull(scriptMethod); var entryPoint = compilation.GetEntryPointAndDiagnostics(default(CancellationToken)); Assert.Equal(entryPoint.MethodSymbol, scriptMethod); entryPoint.Diagnostics.Verify( // (4,17): warning CS7022: The entry point of the program is global script code; ignoring 'A.Main()' entry point. // static void Main() { } Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("A.Main()").WithLocation(4, 17)); } [Fact] public void GetEntryPoint_Submission() { var source = @"1 + 1"; var compilation = CSharpCompilation.CreateScriptCompilation("sub", references: new[] { MscorlibRef }, syntaxTree: Parse(source, options: TestOptions.Script)); compilation.VerifyDiagnostics(); var scriptMethod = compilation.GetMember<MethodSymbol>("Script.<Factory>"); Assert.NotNull(scriptMethod); var method = compilation.GetEntryPoint(default(CancellationToken)); Assert.Equal(method, scriptMethod); var entryPoint = compilation.GetEntryPointAndDiagnostics(default(CancellationToken)); Assert.Equal(entryPoint.MethodSymbol, scriptMethod); entryPoint.Diagnostics.Verify(); } [Fact] public void GetEntryPoint_Submission_MainIgnored() { var source = @" class A { static void Main() { } } "; var compilation = CSharpCompilation.CreateScriptCompilation("sub", references: new[] { MscorlibRef }, syntaxTree: Parse(source, options: TestOptions.Script)); compilation.VerifyDiagnostics( // (4,17): warning CS7022: The entry point of the program is global script code; ignoring 'A.Main()' entry point. // static void Main() { } Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("A.Main()").WithLocation(4, 17)); Assert.True(compilation.IsSubmission); var scriptMethod = compilation.GetMember<MethodSymbol>("Script.<Factory>"); Assert.NotNull(scriptMethod); var entryPoint = compilation.GetEntryPointAndDiagnostics(default(CancellationToken)); Assert.Equal(entryPoint.MethodSymbol, scriptMethod); entryPoint.Diagnostics.Verify( // (4,17): warning CS7022: The entry point of the program is global script code; ignoring 'A.Main()' entry point. // static void Main() { } Diagnostic(ErrorCode.WRN_MainIgnored, "Main").WithArguments("A.Main()").WithLocation(4, 17)); } [Fact] public void GetEntryPoint_MainType() { var source = @" class A { static void Main() { } } class B { static void Main() { } } "; var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe.WithMainTypeName("B")); compilation.VerifyDiagnostics(); var mainMethod = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("B").GetMember<MethodSymbol>("Main"); Assert.Equal(mainMethod, compilation.GetEntryPoint(default(CancellationToken))); var entryPointAndDiagnostics = compilation.GetEntryPointAndDiagnostics(default(CancellationToken)); Assert.Equal(mainMethod, entryPointAndDiagnostics.MethodSymbol); entryPointAndDiagnostics.Diagnostics.Verify(); } [Fact] public void CanReadAndWriteDefaultWin32Res() { var comp = CSharpCompilation.Create("Compilation"); var mft = new MemoryStream(new byte[] { 0, 1, 2, 3, }); var res = comp.CreateDefaultWin32Resources(true, false, mft, null); var list = comp.MakeWin32ResourceList(res, new DiagnosticBag()); Assert.Equal(2, list.Count); } [Fact, WorkItem(750437, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/750437")] public void ConflictingAliases() { var alias = NetFramework.System.WithAliases(new[] { "alias" }); var text = @"extern alias alias; using alias=alias; class myClass : alias::Uri { }"; var comp = CreateEmptyCompilation(text, references: new[] { MscorlibRef, alias }); Assert.Equal(2, comp.References.Count()); Assert.Equal("alias", comp.References.Last().Properties.Aliases.Single()); comp.VerifyDiagnostics( // (2,7): warning CS8981: The type name 'alias' only contains lower-cased ascii characters. Such names may become reserved for the language. // using alias=alias; Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "alias").WithArguments("alias").WithLocation(2, 7), // (2,1): error CS1537: The using alias 'alias' appeared previously in this namespace // using alias=alias; Diagnostic(ErrorCode.ERR_DuplicateAlias, "using alias=alias;").WithArguments("alias").WithLocation(2, 1), // (3,17): error CS0104: 'alias' is an ambiguous reference between '<global namespace>' and '<global namespace>' // class myClass : alias::Uri Diagnostic(ErrorCode.ERR_AmbigContext, "alias").WithArguments("alias", "<global namespace>", "<global namespace>").WithLocation(3, 17)); } [WorkItem(546088, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546088")] [Fact] public void CompilationDiagsIncorrectResult() { string source1 = @" using SysAttribute = System.Attribute; using MyAttribute = MyAttribute2Attribute; public class MyAttributeAttribute : SysAttribute {} public class MyAttribute2Attribute : SysAttribute {} [MyAttribute] public class TestClass { } "; string source2 = @""; // Ask for model diagnostics first. { var compilation = CreateCompilation(source: new string[] { source1, source2 }); var tree2 = compilation.SyntaxTrees[1]; //tree for empty file var model2 = compilation.GetSemanticModel(tree2); model2.GetDiagnostics().Verify(); // None, since the file is empty. compilation.GetDiagnostics().Verify( // (8,2): error CS1614: 'MyAttribute' is ambiguous between 'MyAttribute2Attribute' and 'MyAttributeAttribute'; use either '@MyAttribute' or 'MyAttributeAttribute' // [MyAttribute] Diagnostic(ErrorCode.ERR_AmbiguousAttribute, "MyAttribute").WithArguments("MyAttribute", "MyAttribute2Attribute", "MyAttributeAttribute")); } // Ask for compilation diagnostics first. { var compilation = CreateCompilation(source: new string[] { source1, source2 }); var tree2 = compilation.SyntaxTrees[1]; //tree for empty file var model2 = compilation.GetSemanticModel(tree2); compilation.GetDiagnostics().Verify( // (10,2): error CS1614: 'MyAttribute' is ambiguous between 'MyAttribute2Attribute' and 'MyAttributeAttribute'; use either '@MyAttribute' or 'MyAttributeAttribute' // [MyAttribute] Diagnostic(ErrorCode.ERR_AmbiguousAttribute, "MyAttribute").WithArguments("MyAttribute", "MyAttribute2Attribute", "MyAttributeAttribute")); model2.GetDiagnostics().Verify(); // None, since the file is empty. } } [Fact] public void ReferenceManagerReuse_WithOptions() { var c1 = CSharpCompilation.Create("c", options: TestOptions.ReleaseDll); var c2 = c1.WithOptions(TestOptions.ReleaseExe); Assert.True(c1.ReferenceManagerEquals(c2)); c2 = c1.WithOptions(TestOptions.ReleaseDll.WithOutputKind(OutputKind.WindowsApplication)); Assert.True(c1.ReferenceManagerEquals(c2)); c2 = c1.WithOptions(TestOptions.ReleaseDll); Assert.True(c1.ReferenceManagerEquals(c2)); c2 = c1.WithOptions(TestOptions.ReleaseDll.WithOutputKind(OutputKind.NetModule)); Assert.False(c1.ReferenceManagerEquals(c2)); c1 = CSharpCompilation.Create("c", options: TestOptions.ReleaseModule); c2 = c1.WithOptions(TestOptions.ReleaseExe); Assert.False(c1.ReferenceManagerEquals(c2)); c2 = c1.WithOptions(TestOptions.ReleaseDll); Assert.False(c1.ReferenceManagerEquals(c2)); c2 = c1.WithOptions(TestOptions.CreateTestOptions(OutputKind.WindowsApplication, OptimizationLevel.Debug)); Assert.False(c1.ReferenceManagerEquals(c2)); c2 = c1.WithOptions(TestOptions.DebugModule.WithAllowUnsafe(true)); Assert.True(c1.ReferenceManagerEquals(c2)); } [Fact] public void ReferenceManagerReuse_WithMetadataReferenceResolver() { var c1 = CSharpCompilation.Create("c", options: TestOptions.ReleaseDll); var c2 = c1.WithOptions(TestOptions.ReleaseDll.WithMetadataReferenceResolver(new TestMetadataReferenceResolver())); Assert.False(c1.ReferenceManagerEquals(c2)); var c3 = c1.WithOptions(TestOptions.ReleaseDll.WithMetadataReferenceResolver(c1.Options.MetadataReferenceResolver)); Assert.True(c1.ReferenceManagerEquals(c3)); } [Fact] public void ReferenceManagerReuse_WithXmlFileResolver() { var c1 = CSharpCompilation.Create("c", options: TestOptions.ReleaseDll); var c2 = c1.WithOptions(TestOptions.ReleaseDll.WithXmlReferenceResolver(new XmlFileResolver(null))); Assert.False(c1.ReferenceManagerEquals(c2)); var c3 = c1.WithOptions(TestOptions.ReleaseDll.WithXmlReferenceResolver(c1.Options.XmlReferenceResolver)); Assert.True(c1.ReferenceManagerEquals(c3)); } [Fact] public void ReferenceManagerReuse_WithName() { var c1 = CSharpCompilation.Create("c1"); var c2 = c1.WithAssemblyName("c2"); Assert.False(c1.ReferenceManagerEquals(c2)); var c3 = c1.WithAssemblyName("c1"); Assert.True(c1.ReferenceManagerEquals(c3)); var c4 = c1.WithAssemblyName(null); Assert.False(c1.ReferenceManagerEquals(c4)); var c5 = c4.WithAssemblyName(null); Assert.True(c4.ReferenceManagerEquals(c5)); } [Fact] public void ReferenceManagerReuse_WithReferences() { var c1 = CSharpCompilation.Create("c1"); var c2 = c1.WithReferences(new[] { MscorlibRef }); Assert.False(c1.ReferenceManagerEquals(c2)); var c3 = c2.WithReferences(new[] { MscorlibRef, SystemCoreRef }); Assert.False(c3.ReferenceManagerEquals(c2)); c3 = c2.AddReferences(SystemCoreRef); Assert.False(c3.ReferenceManagerEquals(c2)); c3 = c2.RemoveAllReferences(); Assert.False(c3.ReferenceManagerEquals(c2)); c3 = c2.ReplaceReference(MscorlibRef, SystemCoreRef); Assert.False(c3.ReferenceManagerEquals(c2)); c3 = c2.RemoveReferences(MscorlibRef); Assert.False(c3.ReferenceManagerEquals(c2)); } [Fact] public void ReferenceManagerReuse_WithSyntaxTrees() { var ta = Parse("class C { }", options: TestOptions.Regular10); var tb = Parse(@" class C { }", options: TestOptions.Script.WithLanguageVersion(LanguageVersion.CSharp10)); var tc = Parse(@" #r ""bar"" // error: #r in regular code class D { }", options: TestOptions.Regular10); var tr = Parse(@" #r ""goo"" class C { }", options: TestOptions.Script.WithLanguageVersion(LanguageVersion.CSharp10)); var ts = Parse(@" #r ""bar"" class C { }", options: TestOptions.Script.WithLanguageVersion(LanguageVersion.CSharp10)); var a = CSharpCompilation.Create("c", syntaxTrees: new[] { ta }); // add: var ab = a.AddSyntaxTrees(tb); Assert.True(a.ReferenceManagerEquals(ab)); var ac = a.AddSyntaxTrees(tc); Assert.True(a.ReferenceManagerEquals(ac)); var ar = a.AddSyntaxTrees(tr); Assert.False(a.ReferenceManagerEquals(ar)); var arc = ar.AddSyntaxTrees(tc); Assert.True(ar.ReferenceManagerEquals(arc)); // remove: var ar2 = arc.RemoveSyntaxTrees(tc); Assert.True(arc.ReferenceManagerEquals(ar2)); var c = arc.RemoveSyntaxTrees(ta, tr); Assert.False(arc.ReferenceManagerEquals(c)); var none1 = c.RemoveSyntaxTrees(tc); Assert.True(c.ReferenceManagerEquals(none1)); var none2 = arc.RemoveAllSyntaxTrees(); Assert.False(arc.ReferenceManagerEquals(none2)); var none3 = ac.RemoveAllSyntaxTrees(); Assert.True(ac.ReferenceManagerEquals(none3)); // replace: var asc = arc.ReplaceSyntaxTree(tr, ts); Assert.False(arc.ReferenceManagerEquals(asc)); var brc = arc.ReplaceSyntaxTree(ta, tb); Assert.True(arc.ReferenceManagerEquals(brc)); var abc = arc.ReplaceSyntaxTree(tr, tb); Assert.False(arc.ReferenceManagerEquals(abc)); var ars = arc.ReplaceSyntaxTree(tc, ts); Assert.False(arc.ReferenceManagerEquals(ars)); } [Fact] public void ReferenceManagerReuse_WithScriptCompilationInfo() { // Note: The following results would change if we optimized sharing more: https://github.com/dotnet/roslyn/issues/43397 var c1 = CSharpCompilation.CreateScriptCompilation("c1"); Assert.NotNull(c1.ScriptCompilationInfo); Assert.Null(c1.ScriptCompilationInfo.PreviousScriptCompilation); var c2 = c1.WithScriptCompilationInfo(null); Assert.Null(c2.ScriptCompilationInfo); Assert.True(c2.ReferenceManagerEquals(c1)); var c3 = c2.WithScriptCompilationInfo(new CSharpScriptCompilationInfo(previousCompilationOpt: null, returnType: typeof(int), globalsType: null)); Assert.NotNull(c3.ScriptCompilationInfo); Assert.Null(c3.ScriptCompilationInfo.PreviousScriptCompilation); Assert.True(c3.ReferenceManagerEquals(c2)); var c4 = c3.WithScriptCompilationInfo(null); Assert.Null(c4.ScriptCompilationInfo); Assert.True(c4.ReferenceManagerEquals(c3)); var c5 = c4.WithScriptCompilationInfo(new CSharpScriptCompilationInfo(previousCompilationOpt: c1, returnType: typeof(int), globalsType: null)); Assert.False(c5.ReferenceManagerEquals(c4)); var c6 = c5.WithScriptCompilationInfo(new CSharpScriptCompilationInfo(previousCompilationOpt: c1, returnType: typeof(bool), globalsType: null)); Assert.True(c6.ReferenceManagerEquals(c5)); var c7 = c6.WithScriptCompilationInfo(new CSharpScriptCompilationInfo(previousCompilationOpt: c2, returnType: typeof(bool), globalsType: null)); Assert.False(c7.ReferenceManagerEquals(c6)); var c8 = c7.WithScriptCompilationInfo(new CSharpScriptCompilationInfo(previousCompilationOpt: null, returnType: typeof(bool), globalsType: null)); Assert.False(c8.ReferenceManagerEquals(c7)); var c9 = c8.WithScriptCompilationInfo(null); Assert.True(c9.ReferenceManagerEquals(c8)); } private sealed class EvolvingTestReference : PortableExecutableReference { private readonly IEnumerator<Metadata> _metadataSequence; public int QueryCount; public EvolvingTestReference(IEnumerable<Metadata> metadataSequence) : base(MetadataReferenceProperties.Assembly) { _metadataSequence = metadataSequence.GetEnumerator(); } protected override DocumentationProvider CreateDocumentationProvider() { return DocumentationProvider.Default; } protected override Metadata GetMetadataImpl() { QueryCount++; _metadataSequence.MoveNext(); return _metadataSequence.Current; } protected override PortableExecutableReference WithPropertiesImpl(MetadataReferenceProperties properties) { throw new NotImplementedException(); } } [ConditionalFact(typeof(NoUsedAssembliesValidation), typeof(NoIOperationValidation), Reason = "IOperation skip: Compilation changes over time, adds new errors")] public void MetadataConsistencyWhileEvolvingCompilation() { var md1 = AssemblyMetadata.CreateFromImage(CreateCompilation("public class C { }").EmitToArray()); var md2 = AssemblyMetadata.CreateFromImage(CreateCompilation("public class D { }").EmitToArray()); var reference = new EvolvingTestReference(new[] { md1, md2 }); var c1 = CreateEmptyCompilation("public class Main { public static C C; }", new[] { MscorlibRef, reference, reference }); var c2 = c1.WithAssemblyName("c2"); var c3 = c2.AddSyntaxTrees(Parse("public class Main2 { public static int a; }")); var c4 = c3.WithOptions(TestOptions.DebugModule); var c5 = c4.WithReferences(new[] { MscorlibRef, reference }); c3.VerifyDiagnostics(); c1.VerifyDiagnostics(); c4.VerifyDiagnostics(); c2.VerifyDiagnostics(); Assert.Equal(1, reference.QueryCount); c5.VerifyDiagnostics( // (1,36): error CS0246: The type or namespace name 'C' could not be found (are you missing a using directive or an assembly reference?) // public class Main2 { public static C C; } Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "C").WithArguments("C")); Assert.Equal(2, reference.QueryCount); } [Fact] public unsafe void LinkedNetmoduleMetadataMustProvideFullPEImage() { var netModule = TestResources.MetadataTests.NetModule01.ModuleCS00; PEHeaders h = new PEHeaders(new MemoryStream(netModule)); fixed (byte* ptr = &netModule[h.MetadataStartOffset]) { using (var mdModule = ModuleMetadata.CreateFromMetadata((IntPtr)ptr, h.MetadataSize)) { var c = CSharpCompilation.Create("Goo", references: new[] { MscorlibRef, mdModule.GetReference(display: "ModuleCS00") }, options: TestOptions.ReleaseDll); c.VerifyDiagnostics( // error CS7098: Linked netmodule metadata must provide a full PE image: 'ModuleCS00'. Diagnostic(ErrorCode.ERR_LinkedNetmoduleMetadataMustProvideFullPEImage).WithArguments("ModuleCS00").WithLocation(1, 1)); } } } [Fact] public void AppConfig1() { var references = new MetadataReference[] { NetFramework.mscorlib, NetFramework.System, TestReferences.NetFx.silverlight_v5_0_5_0.System }; var compilation = CreateEmptyCompilation( new[] { Parse("") }, references, options: TestOptions.ReleaseDll.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)); compilation.VerifyDiagnostics( // error CS1703: Multiple assemblies with equivalent identity have been imported: 'System (net461)' and 'System.v5.0.5.0_silverlight.dll'. Remove one of the duplicate references. Diagnostic(ErrorCode.ERR_DuplicateImport).WithArguments("System (net461)", "System.v5.0.5.0_silverlight.dll").WithLocation(1, 1)); var appConfig = new MemoryStream(Encoding.UTF8.GetBytes( @"<?xml version=""1.0"" encoding=""utf-8"" ?> <configuration> <runtime> <assemblyBinding xmlns=""urn:schemas-microsoft-com:asm.v1""> <supportPortability PKT=""7cec85d7bea7798e"" enable=""false""/> </assemblyBinding> </runtime> </configuration>")); var comparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfig); compilation = CreateEmptyCompilation( new[] { Parse("") }, references, options: TestOptions.ReleaseDll.WithAssemblyIdentityComparer(comparer)); compilation.VerifyDiagnostics(); } [Fact] public void AppConfig2() { // Create a dll with a reference to .NET system string libSource = @" using System.Runtime.Versioning; public class C { public static FrameworkName Goo() { return null; }}"; var libComp = CreateEmptyCompilation( libSource, references: new[] { MscorlibRef, NetFramework.System }, options: TestOptions.ReleaseDll); libComp.VerifyDiagnostics(); var refData = libComp.EmitToArray(); var mdRef = MetadataReference.CreateFromImage(refData); var references = new[] { NetFramework.mscorlib, NetFramework.System, TestReferences.NetFx.silverlight_v5_0_5_0.System, mdRef }; // Source references the type in the dll string src1 = @"class A { public static void Main(string[] args) { C.Goo(); } }"; var c1 = CreateEmptyCompilation( new[] { Parse(src1) }, references, options: TestOptions.ReleaseDll.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)); c1.VerifyDiagnostics( // error CS1703: Multiple assemblies with equivalent identity have been imported: 'System (net461)' and 'System.v5.0.5.0_silverlight.dll'. Remove one of the duplicate references. Diagnostic(ErrorCode.ERR_DuplicateImport).WithArguments("System (net461)", "System.v5.0.5.0_silverlight.dll").WithLocation(1, 1), // (1,52): error CS7069: Reference to type 'FrameworkName' claims it is defined in 'System', but it could not be found // class A { public static void Main(string[] args) { C.Goo(); } } Diagnostic(ErrorCode.ERR_MissingTypeInAssembly, "C.Goo").WithArguments("System.Runtime.Versioning.FrameworkName", "System").WithLocation(1, 52)); var appConfig = new MemoryStream(Encoding.UTF8.GetBytes( @"<?xml version=""1.0"" encoding=""utf-8"" ?> <configuration> <runtime> <assemblyBinding xmlns=""urn:schemas-microsoft-com:asm.v1""> <supportPortability PKT=""7cec85d7bea7798e"" enable=""false""/> </assemblyBinding> </runtime> </configuration>")); var comparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfig); var src2 = @"class A { public static void Main(string[] args) { C.Goo(); } }"; var c2 = CreateEmptyCompilation( new[] { Parse(src2) }, references, options: TestOptions.ReleaseDll.WithAssemblyIdentityComparer(comparer)); c2.VerifyDiagnostics(); } [Fact] [WorkItem(797640, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/797640")] public void GetMetadataReferenceAPITest() { var comp = CSharpCompilation.Create("Compilation"); var metadata = NetFramework.mscorlib; comp = comp.AddReferences(metadata); var assemblySmb = comp.GetReferencedAssemblySymbol(metadata); var reference = comp.GetMetadataReference(assemblySmb); Assert.NotNull(reference); var comp2 = CSharpCompilation.Create("Compilation"); comp2 = comp2.AddReferences(metadata); var reference2 = comp2.GetMetadataReference(assemblySmb); Assert.NotNull(reference2); } [Fact] [WorkItem(40466, "https://github.com/dotnet/roslyn/issues/40466")] public void GetMetadataReference_VisualBasicSymbols() { var comp = CreateCompilation(""); var vbComp = CreateVisualBasicCompilation("", referencedAssemblies: TargetFrameworkUtil.GetReferences(TargetFramework.Standard)); var assembly = (IAssemblySymbol)vbComp.GetBoundReferenceManager().GetReferencedAssemblies().First().Value; Assert.Null(comp.GetMetadataReference(assembly)); Assert.Null(comp.GetMetadataReference(vbComp.Assembly)); Assert.Null(comp.GetMetadataReference((IAssemblySymbol)null)); } [Fact] public void ConsistentParseOptions() { var tree1 = SyntaxFactory.ParseSyntaxTree("", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp6)); var tree2 = SyntaxFactory.ParseSyntaxTree("", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp6)); var tree3 = SyntaxFactory.ParseSyntaxTree("", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp5)); var assemblyName = GetUniqueName(); var compilationOptions = TestOptions.DebugDll; CSharpCompilation.Create(assemblyName, new[] { tree1, tree2 }, new[] { MscorlibRef }, compilationOptions); Assert.Throws<ArgumentException>(() => { CSharpCompilation.Create(assemblyName, new[] { tree1, tree3 }, new[] { MscorlibRef }, compilationOptions); }); } [Fact] public void SubmissionCompilation_Errors() { var genericParameter = typeof(List<>).GetGenericArguments()[0]; var open = typeof(Dictionary<,>).MakeGenericType(typeof(int), genericParameter); var ptr = typeof(int).MakePointerType(); var byref = typeof(int).MakeByRefType(); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", returnType: genericParameter)); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", returnType: open)); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", returnType: typeof(void))); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", returnType: byref)); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", globalsType: genericParameter)); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", globalsType: open)); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", globalsType: typeof(void))); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", globalsType: typeof(int))); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", globalsType: ptr)); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", globalsType: byref)); var s0 = CSharpCompilation.CreateScriptCompilation("a0", globalsType: typeof(List<int>)); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a1", previousScriptCompilation: s0, globalsType: typeof(List<bool>))); // invalid options: Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", options: TestOptions.ReleaseExe)); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", options: TestOptions.ReleaseDll.WithOutputKind(OutputKind.NetModule))); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", options: TestOptions.ReleaseDll.WithOutputKind(OutputKind.WindowsRuntimeMetadata))); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", options: TestOptions.ReleaseDll.WithOutputKind(OutputKind.WindowsRuntimeApplication))); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", options: TestOptions.ReleaseDll.WithOutputKind(OutputKind.WindowsApplication))); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", options: TestOptions.ReleaseDll.WithCryptoKeyContainer("goo"))); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", options: TestOptions.ReleaseDll.WithCryptoKeyFile("goo.snk"))); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", options: TestOptions.ReleaseDll.WithDelaySign(true))); Assert.Throws<ArgumentException>(() => CSharpCompilation.CreateScriptCompilation("a", options: TestOptions.ReleaseDll.WithDelaySign(false))); } [Fact] public void HasSubmissionResult() { Assert.False(CSharpCompilation.CreateScriptCompilation("sub").HasSubmissionResult()); Assert.True(CreateSubmission("1", parseOptions: TestOptions.Script).HasSubmissionResult()); Assert.False(CreateSubmission("1;", parseOptions: TestOptions.Script).HasSubmissionResult()); Assert.False(CreateSubmission("void goo() { }", parseOptions: TestOptions.Script).HasSubmissionResult()); Assert.False(CreateSubmission("using System;", parseOptions: TestOptions.Script).HasSubmissionResult()); Assert.False(CreateSubmission("int i;", parseOptions: TestOptions.Script).HasSubmissionResult()); Assert.False(CreateSubmission("System.Console.WriteLine();", parseOptions: TestOptions.Script).HasSubmissionResult()); Assert.False(CreateSubmission("System.Console.WriteLine()", parseOptions: TestOptions.Script).HasSubmissionResult()); Assert.True(CreateSubmission("null", parseOptions: TestOptions.Script).HasSubmissionResult()); Assert.True(CreateSubmission("System.Console.WriteLine", parseOptions: TestOptions.Script).HasSubmissionResult()); } /// <summary> /// Previous submission has to have no errors. /// </summary> [Fact] public void PreviousSubmissionWithError() { var s0 = CreateSubmission("int a = \"x\";"); s0.VerifyDiagnostics( // (1,9): error CS0029: Cannot implicitly convert type 'string' to 'int' Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""x""").WithArguments("string", "int")); Assert.Throws<InvalidOperationException>(() => CreateSubmission("a + 1", previous: s0)); } [Fact] [WorkItem(36047, "https://github.com/dotnet/roslyn/issues/36047")] public void CreateArrayType_DefaultArgs() { var comp = (Compilation)CSharpCompilation.Create(""); var elementType = comp.GetSpecialType(SpecialType.System_Object); var arrayType = comp.CreateArrayTypeSymbol(elementType); Assert.Equal(1, arrayType.Rank); Assert.Equal(CodeAnalysis.NullableAnnotation.None, arrayType.ElementNullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.None, arrayType.ElementType.NullableAnnotation); Assert.Throws<ArgumentException>(() => comp.CreateArrayTypeSymbol(elementType, default)); Assert.Throws<ArgumentException>(() => comp.CreateArrayTypeSymbol(elementType, 0)); arrayType = comp.CreateArrayTypeSymbol(elementType, 1, default); Assert.Equal(1, arrayType.Rank); Assert.Equal(CodeAnalysis.NullableAnnotation.None, arrayType.ElementNullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.None, arrayType.ElementType.NullableAnnotation); Assert.Throws<ArgumentException>(() => comp.CreateArrayTypeSymbol(elementType, rank: default)); Assert.Throws<ArgumentException>(() => comp.CreateArrayTypeSymbol(elementType, rank: 0)); arrayType = comp.CreateArrayTypeSymbol(elementType, elementNullableAnnotation: default); Assert.Equal(1, arrayType.Rank); Assert.Equal(CodeAnalysis.NullableAnnotation.None, arrayType.ElementNullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.None, arrayType.ElementType.NullableAnnotation); } [Fact] [WorkItem(36047, "https://github.com/dotnet/roslyn/issues/36047")] public void CreateArrayType_ElementNullableAnnotation() { var comp = (Compilation)CSharpCompilation.Create(""); var elementType = comp.GetSpecialType(SpecialType.System_Object); Assert.Equal(CodeAnalysis.NullableAnnotation.None, comp.CreateArrayTypeSymbol(elementType).ElementNullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.None, comp.CreateArrayTypeSymbol(elementType).ElementType.NullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.None, comp.CreateArrayTypeSymbol(elementType, elementNullableAnnotation: CodeAnalysis.NullableAnnotation.None).ElementNullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.None, comp.CreateArrayTypeSymbol(elementType, elementNullableAnnotation: CodeAnalysis.NullableAnnotation.None).ElementType.NullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.None, comp.CreateArrayTypeSymbol(elementType, elementNullableAnnotation: CodeAnalysis.NullableAnnotation.None).ElementNullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.None, comp.CreateArrayTypeSymbol(elementType, elementNullableAnnotation: CodeAnalysis.NullableAnnotation.None).ElementType.NullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.NotAnnotated, comp.CreateArrayTypeSymbol(elementType, elementNullableAnnotation: CodeAnalysis.NullableAnnotation.NotAnnotated).ElementNullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.NotAnnotated, comp.CreateArrayTypeSymbol(elementType, elementNullableAnnotation: CodeAnalysis.NullableAnnotation.NotAnnotated).ElementType.NullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.Annotated, comp.CreateArrayTypeSymbol(elementType, elementNullableAnnotation: CodeAnalysis.NullableAnnotation.Annotated).ElementNullableAnnotation); Assert.Equal(CodeAnalysis.NullableAnnotation.Annotated, comp.CreateArrayTypeSymbol(elementType, elementNullableAnnotation: CodeAnalysis.NullableAnnotation.Annotated).ElementType.NullableAnnotation); } [Fact] public void CreateAnonymousType_IncorrectLengths() { var compilation = CSharpCompilation.Create("HelloWorld"); Assert.Throws<ArgumentException>(() => compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create((ITypeSymbol)null), ImmutableArray.Create("m1", "m2"))); } [Fact] public void CreateAnonymousType_IncorrectLengths_IsReadOnly() { var compilation = (Compilation)CSharpCompilation.Create("HelloWorld"); Assert.Throws<ArgumentException>(() => compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create((ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32), (ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32)), ImmutableArray.Create("m1", "m2"), ImmutableArray.Create(true))); } [Fact] public void CreateAnonymousType_IncorrectLengths_Locations() { var compilation = (Compilation)CSharpCompilation.Create("HelloWorld"); Assert.Throws<ArgumentException>(() => compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create((ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32), (ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32)), ImmutableArray.Create("m1", "m2"), memberLocations: ImmutableArray.Create(Location.None))); } [Fact] public void CreateAnonymousType_WritableProperty() { var compilation = (Compilation)CSharpCompilation.Create("HelloWorld"); Assert.Throws<ArgumentException>(() => compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create((ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32), (ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32)), ImmutableArray.Create("m1", "m2"), ImmutableArray.Create(false, false))); } [Fact] public void CreateAnonymousType_NullLocations() { var compilation = (Compilation)CSharpCompilation.Create("HelloWorld"); Assert.Throws<ArgumentNullException>(() => compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create((ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32), (ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32)), ImmutableArray.Create("m1", "m2"), memberLocations: ImmutableArray.Create(Location.None, null))); } [Fact] public void CreateAnonymousType_NullArgument1() { var compilation = CSharpCompilation.Create("HelloWorld"); Assert.Throws<ArgumentNullException>(() => compilation.CreateAnonymousTypeSymbol( default(ImmutableArray<ITypeSymbol>), ImmutableArray.Create("m1"))); } [Fact] public void CreateAnonymousType_NullArgument2() { var compilation = CSharpCompilation.Create("HelloWorld"); Assert.Throws<ArgumentNullException>(() => compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create((ITypeSymbol)null), default(ImmutableArray<string>))); } [Fact] public void CreateAnonymousType_NullArgument3() { var compilation = CSharpCompilation.Create("HelloWorld"); Assert.Throws<ArgumentNullException>(() => compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create((ITypeSymbol)null), ImmutableArray.Create("m1"))); } [Fact] public void CreateAnonymousType_NullArgument4() { var compilation = (Compilation)CSharpCompilation.Create("HelloWorld"); Assert.Throws<ArgumentNullException>(() => compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create((ITypeSymbol)compilation.GetSpecialType(SpecialType.System_Int32)), ImmutableArray.Create((string)null))); } [Fact] public void CreateAnonymousType1() { var compilation = (Compilation)CSharpCompilation.Create("HelloWorld"); var type = compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create<ITypeSymbol>(compilation.GetSpecialType(SpecialType.System_Int32)), ImmutableArray.Create("m1")); Assert.True(type.IsAnonymousType); Assert.Equal(1, type.GetMembers().OfType<IPropertySymbol>().Count()); Assert.Equal("<anonymous type: int m1>", type.ToDisplayString()); Assert.All(type.GetMembers().OfType<IPropertySymbol>().Select(p => p.Locations.FirstOrDefault()), loc => Assert.Equal(loc, Location.None)); } [Fact] public void CreateAnonymousType_Locations() { var compilation = (Compilation)CSharpCompilation.Create("HelloWorld"); var tree = CSharpSyntaxTree.ParseText("class C { }"); var loc1 = Location.Create(tree, new TextSpan(0, 1)); var loc2 = Location.Create(tree, new TextSpan(1, 1)); var type = compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create<ITypeSymbol>(compilation.GetSpecialType(SpecialType.System_Int32), compilation.GetSpecialType(SpecialType.System_Int32)), ImmutableArray.Create("m1", "m2"), memberLocations: ImmutableArray.Create(loc1, loc2)); Assert.True(type.IsAnonymousType); Assert.Equal(2, type.GetMembers().OfType<IPropertySymbol>().Count()); Assert.Equal(loc1, type.GetMembers("m1").Single().Locations.Single()); Assert.Equal(loc2, type.GetMembers("m2").Single().Locations.Single()); Assert.Equal("<anonymous type: int m1, int m2>", type.ToDisplayString()); } [Fact] public void CreateAnonymousType2() { var compilation = (Compilation)CSharpCompilation.Create("HelloWorld"); var type = compilation.CreateAnonymousTypeSymbol( ImmutableArray.Create<ITypeSymbol>(compilation.GetSpecialType(SpecialType.System_Int32), compilation.GetSpecialType(SpecialType.System_Boolean)), ImmutableArray.Create("m1", "m2")); Assert.True(type.IsAnonymousType); Assert.Equal(2, type.GetMembers().OfType<IPropertySymbol>().Count()); Assert.Equal("<anonymous type: int m1, bool m2>", type.ToDisplayString()); Assert.All(type.GetMembers().OfType<IPropertySymbol>().Select(p => p.Locations.FirstOrDefault()), loc => Assert.Equal(loc, Location.None)); } [Fact] [WorkItem(36047, "https://github.com/dotnet/roslyn/issues/36047")] public void CreateAnonymousType_DefaultArgs() { var comp = (Compilation)CSharpCompilation.Create(""); var memberTypes = ImmutableArray.Create<ITypeSymbol>(comp.GetSpecialType(SpecialType.System_Object), comp.GetSpecialType(SpecialType.System_String)); var memberNames = ImmutableArray.Create("P", "Q"); var type = comp.CreateAnonymousTypeSymbol(memberTypes, memberNames); Assert.Equal("<anonymous type: System.Object P, System.String Q>", type.ToTestDisplayString(includeNonNullable: true)); type = comp.CreateAnonymousTypeSymbol(memberTypes, memberNames, default); Assert.Equal("<anonymous type: System.Object P, System.String Q>", type.ToTestDisplayString(includeNonNullable: true)); type = comp.CreateAnonymousTypeSymbol(memberTypes, memberNames, default, default); Assert.Equal("<anonymous type: System.Object P, System.String Q>", type.ToTestDisplayString(includeNonNullable: true)); type = comp.CreateAnonymousTypeSymbol(memberTypes, memberNames, default, default, default); Assert.Equal("<anonymous type: System.Object P, System.String Q>", type.ToTestDisplayString(includeNonNullable: true)); type = comp.CreateAnonymousTypeSymbol(memberTypes, memberNames, memberIsReadOnly: default); Assert.Equal("<anonymous type: System.Object P, System.String Q>", type.ToTestDisplayString(includeNonNullable: true)); type = comp.CreateAnonymousTypeSymbol(memberTypes, memberNames, memberLocations: default); Assert.Equal("<anonymous type: System.Object P, System.String Q>", type.ToTestDisplayString(includeNonNullable: true)); type = comp.CreateAnonymousTypeSymbol(memberTypes, memberNames, memberNullableAnnotations: default); Assert.Equal("<anonymous type: System.Object P, System.String Q>", type.ToTestDisplayString(includeNonNullable: true)); } [Fact] [WorkItem(36047, "https://github.com/dotnet/roslyn/issues/36047")] public void CreateAnonymousType_MemberNullableAnnotations_Empty() { var comp = (Compilation)CSharpCompilation.Create(""); var type = comp.CreateAnonymousTypeSymbol(ImmutableArray<ITypeSymbol>.Empty, ImmutableArray<string>.Empty, memberNullableAnnotations: ImmutableArray<CodeAnalysis.NullableAnnotation>.Empty); Assert.Equal("<empty anonymous type>", type.ToTestDisplayString(includeNonNullable: true)); AssertEx.Equal(Array.Empty<CodeAnalysis.NullableAnnotation>(), GetAnonymousTypeNullableAnnotations(type)); } [Fact] [WorkItem(36047, "https://github.com/dotnet/roslyn/issues/36047")] public void CreateAnonymousType_MemberNullableAnnotations() { var comp = (Compilation)CSharpCompilation.Create(""); var memberTypes = ImmutableArray.Create<ITypeSymbol>(comp.GetSpecialType(SpecialType.System_Object), comp.GetSpecialType(SpecialType.System_String)); var memberNames = ImmutableArray.Create("P", "Q"); var type = comp.CreateAnonymousTypeSymbol(memberTypes, memberNames); Assert.Equal("<anonymous type: System.Object P, System.String Q>", type.ToTestDisplayString(includeNonNullable: true)); AssertEx.Equal(new[] { CodeAnalysis.NullableAnnotation.None, CodeAnalysis.NullableAnnotation.None }, GetAnonymousTypeNullableAnnotations(type)); Assert.Throws<ArgumentException>(() => comp.CreateAnonymousTypeSymbol(memberTypes, memberNames, memberNullableAnnotations: ImmutableArray.Create(CodeAnalysis.NullableAnnotation.NotAnnotated))); type = comp.CreateAnonymousTypeSymbol(memberTypes, memberNames, memberNullableAnnotations: ImmutableArray.Create(CodeAnalysis.NullableAnnotation.NotAnnotated, CodeAnalysis.NullableAnnotation.Annotated)); Assert.Equal("<anonymous type: System.Object! P, System.String? Q>", type.ToTestDisplayString(includeNonNullable: true)); AssertEx.Equal(new[] { CodeAnalysis.NullableAnnotation.NotAnnotated, CodeAnalysis.NullableAnnotation.Annotated }, GetAnonymousTypeNullableAnnotations(type)); } private static ImmutableArray<CodeAnalysis.NullableAnnotation> GetAnonymousTypeNullableAnnotations(ITypeSymbol type) { return type.GetMembers().OfType<IPropertySymbol>().SelectAsArray(p => { var result = p.Type.NullableAnnotation; Assert.Equal(result, p.NullableAnnotation); return result; }); } [Theory] [InlineData(WellKnownMemberNames.CheckedAdditionOperatorName, "int.operator checked +(int, int)")] [InlineData(WellKnownMemberNames.AdditionOperatorName, "int.operator +(int, int)")] [InlineData(WellKnownMemberNames.BitwiseAndOperatorName, "int.operator &(int, int)")] [InlineData(WellKnownMemberNames.CheckedDivisionOperatorName, "int.operator checked /(int, int)")] [InlineData(WellKnownMemberNames.DivisionOperatorName, "int.operator /(int, int)")] [InlineData(WellKnownMemberNames.LeftShiftOperatorName, "int.operator <<(int, int)")] [InlineData(WellKnownMemberNames.CheckedMultiplyOperatorName, "int.operator checked *(int, int)")] [InlineData(WellKnownMemberNames.MultiplyOperatorName, "int.operator *(int, int)")] [InlineData(WellKnownMemberNames.BitwiseOrOperatorName, "int.operator |(int, int)")] [InlineData(WellKnownMemberNames.ModulusOperatorName, "int.operator %(int, int)")] [InlineData(WellKnownMemberNames.RightShiftOperatorName, "int.operator >>(int, int)")] [InlineData(WellKnownMemberNames.UnsignedRightShiftOperatorName, "int.operator >>>(int, int)")] [InlineData(WellKnownMemberNames.CheckedSubtractionOperatorName, "int.operator checked -(int, int)")] [InlineData(WellKnownMemberNames.SubtractionOperatorName, "int.operator -(int, int)")] [InlineData(WellKnownMemberNames.ExclusiveOrOperatorName, "int.operator ^(int, int)")] public void CreateBuiltinBinaryOperator_Supported( string name, string display) { var compilation = CreateCompilation(""); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); var op = compilation.CreateBuiltinOperator(name, intType, intType, intType); var result = op.ToDisplayString(); AssertEx.Equal(display, result); } [Theory] [InlineData(WellKnownMemberNames.EqualityOperatorName, "int.operator ==(int, int)")] [InlineData(WellKnownMemberNames.GreaterThanOperatorName, "int.operator >(int, int)")] [InlineData(WellKnownMemberNames.GreaterThanOrEqualOperatorName, "int.operator >=(int, int)")] [InlineData(WellKnownMemberNames.LessThanOperatorName, "int.operator <(int, int)")] [InlineData(WellKnownMemberNames.LessThanOrEqualOperatorName, "int.operator <=(int, int)")] [InlineData(WellKnownMemberNames.InequalityOperatorName, "int.operator !=(int, int)")] public void CreateBuiltinBinaryOperator_Supported_BoolReturnType( string name, string display) { var compilation = CreateCompilation(""); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); var boolType = compilation.GetSpecialType(SpecialType.System_Boolean).GetPublicSymbol(); var op = compilation.CreateBuiltinOperator(name, boolType, intType, intType); var result = op.ToDisplayString(); AssertEx.Equal(display, result); } [Fact] public void CreateBuiltinBinaryOperator_BogusErrorType() { var compilation = CreateCompilation(""); var fakeIntType = compilation.CreateErrorTypeSymbol(compilation.CreateErrorNamespaceSymbol(compilation.GlobalNamespace, "System"), "Int32", arity: 0); Assert.Throws<ArgumentException>(() => compilation.CreateBuiltinOperator(WellKnownMemberNames.AdditionOperatorName, fakeIntType, fakeIntType, fakeIntType)); } [Fact] public void CreateBuiltinBinaryOperator_RealErrorType() { var compilation = CreateCompilation("", references: Array.Empty<MetadataReference>(), targetFramework: TargetFramework.Empty); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); var op = compilation.CreateBuiltinOperator(WellKnownMemberNames.AdditionOperatorName, intType, intType, intType); var result = op.ToDisplayString(); AssertEx.Equal("int.operator +(int, int)", result); } [Fact] public void CreateBuiltinBinaryOperator_NotSupported() { var compilation = CreateCompilation(""); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); var nullableIntType = compilation.GetSpecialType(SpecialType.System_Nullable_T).GetPublicSymbol().Construct(intType); // vb binary operator name Assert.Throws<ArgumentException>("name", () => compilation.CreateBuiltinOperator(WellKnownMemberNames.LikeOperatorName, intType, intType, intType)); // unary operator name Assert.Throws<ArgumentException>("name", () => compilation.CreateBuiltinOperator(WellKnownMemberNames.UnaryPlusOperatorName, intType, intType, intType)); // nullable type 1 Assert.Throws<ArgumentException>(null, () => compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedAdditionOperatorName, nullableIntType, intType, intType)); // nullable type 2 Assert.Throws<ArgumentException>(null, () => compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedAdditionOperatorName, intType, nullableIntType, intType)); // nullable type 3 Assert.Throws<ArgumentException>(null, () => compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedAdditionOperatorName, intType, intType, nullableIntType)); } [Fact] public void CreateBuiltinBinaryOperator_NullChecks() { var compilation = CreateCompilation(""); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); Assert.Throws<ArgumentNullException>("returnType", () => compilation.CreateBuiltinOperator( WellKnownMemberNames.AdditionOperatorName, null, intType, intType)); Assert.Throws<ArgumentNullException>("leftType", () => compilation.CreateBuiltinOperator( WellKnownMemberNames.AdditionOperatorName, intType, null, intType)); Assert.Throws<ArgumentNullException>("rightType", () => compilation.CreateBuiltinOperator( WellKnownMemberNames.AdditionOperatorName, intType, intType, null)); } [Fact] public void CreateBuiltinBinaryOperator_CompareToActualSymbols1() { var compilation = CreateCompilation(@" class C { void M() { var m = /*<bind>*/1 + 1/*</bind>*/; } }"); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); var syntaxTree = compilation.SyntaxTrees.Single(); var semanticModel = compilation.GetSemanticModel(syntaxTree); var expr = GetSyntaxNodeOfTypeForBinding<BinaryExpressionSyntax>(GetSyntaxNodeList(syntaxTree)); var symbol = semanticModel.GetSymbolInfo(expr).Symbol; Assert.NotNull(symbol); var addBuiltIn = compilation.CreateBuiltinOperator(WellKnownMemberNames.AdditionOperatorName, intType, intType, intType); var addBuiltInChecked = compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedAdditionOperatorName, intType, intType, intType); var subtractBuiltIn = compilation.CreateBuiltinOperator(WellKnownMemberNames.SubtractionOperatorName, intType, intType, intType); var subtractBuiltInChecked = compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedSubtractionOperatorName, intType, intType, intType); Assert.Equal(addBuiltIn, symbol); Assert.NotEqual(addBuiltInChecked, symbol); Assert.NotEqual(subtractBuiltIn, symbol); Assert.NotEqual(subtractBuiltInChecked, symbol); } [Fact] public void CreateBuiltinBinaryOperator_CompareToActualSymbols2() { var compilation = CreateCompilation(@" class C { void M() { checked { var m = /*<bind>*/1 + 1/*</bind>*/; } } }"); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); var syntaxTree = compilation.SyntaxTrees.Single(); var semanticModel = compilation.GetSemanticModel(syntaxTree); var expr = GetSyntaxNodeOfTypeForBinding<BinaryExpressionSyntax>(GetSyntaxNodeList(syntaxTree)); var symbol = semanticModel.GetSymbolInfo(expr).Symbol; Assert.NotNull(symbol); var addBuiltIn = compilation.CreateBuiltinOperator(WellKnownMemberNames.AdditionOperatorName, intType, intType, intType); var addBuiltInChecked = compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedAdditionOperatorName, intType, intType, intType); var subtractBuiltIn = compilation.CreateBuiltinOperator(WellKnownMemberNames.SubtractionOperatorName, intType, intType, intType); var subtractBuiltInChecked = compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedSubtractionOperatorName, intType, intType, intType); Assert.NotEqual(addBuiltIn, symbol); Assert.Equal(addBuiltInChecked, symbol); Assert.NotEqual(subtractBuiltIn, symbol); Assert.NotEqual(subtractBuiltInChecked, symbol); } [Fact] public void CreateBuiltinBinaryOperator_CompareToActualSymbols3() { var compilation = CreateCompilation(@" class C { void M() { var m = /*<bind>*/1 + 1/*</bind>*/; } }", options: TestOptions.ReleaseDll.WithOverflowChecks(true)); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); var syntaxTree = compilation.SyntaxTrees.Single(); var semanticModel = compilation.GetSemanticModel(syntaxTree); var expr = GetSyntaxNodeOfTypeForBinding<BinaryExpressionSyntax>(GetSyntaxNodeList(syntaxTree)); var symbol = semanticModel.GetSymbolInfo(expr).Symbol; Assert.NotNull(symbol); var addBuiltIn = compilation.CreateBuiltinOperator(WellKnownMemberNames.AdditionOperatorName, intType, intType, intType); var addBuiltInChecked = compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedAdditionOperatorName, intType, intType, intType); var subtractBuiltIn = compilation.CreateBuiltinOperator(WellKnownMemberNames.SubtractionOperatorName, intType, intType, intType); var subtractBuiltInChecked = compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedSubtractionOperatorName, intType, intType, intType); Assert.NotEqual(addBuiltIn, symbol); Assert.Equal(addBuiltInChecked, symbol); Assert.NotEqual(subtractBuiltIn, symbol); Assert.NotEqual(subtractBuiltInChecked, symbol); } [Theory] [InlineData(WellKnownMemberNames.UnaryPlusOperatorName, "int.operator +(int)")] [InlineData(WellKnownMemberNames.CheckedUnaryNegationOperatorName, "int.operator checked -(int)")] [InlineData(WellKnownMemberNames.UnaryNegationOperatorName, "int.operator -(int)")] [InlineData(WellKnownMemberNames.OnesComplementOperatorName, "int.operator ~(int)")] [InlineData(WellKnownMemberNames.CheckedIncrementOperatorName, "int.operator checked ++(int)")] [InlineData(WellKnownMemberNames.IncrementOperatorName, "int.operator ++(int)")] [InlineData(WellKnownMemberNames.CheckedDecrementOperatorName, "int.operator checked --(int)")] [InlineData(WellKnownMemberNames.DecrementOperatorName, "int.operator --(int)")] public void CreateBuiltinUnaryOperator_Supported( string name, string display) { var compilation = CreateCompilation(""); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); var op = compilation.CreateBuiltinOperator(name, intType, intType); var result = op.ToDisplayString(); AssertEx.Equal(display, result); } [Theory] [InlineData(WellKnownMemberNames.LogicalNotOperatorName, "bool.operator !(bool)")] public void CreateBuiltinUnaryOperator_Supported_Bool( string name, string display) { var compilation = CreateCompilation(""); var boolType = compilation.GetSpecialType(SpecialType.System_Boolean).GetPublicSymbol(); var op = compilation.CreateBuiltinOperator(name, boolType, boolType); var result = op.ToDisplayString(); AssertEx.Equal(display, result); } [Fact] public void CreateBuiltinUnaryOperator_BogusErrorType() { var compilation = CreateCompilation(""); var fakeIntType = compilation.CreateErrorTypeSymbol(compilation.CreateErrorNamespaceSymbol(compilation.GlobalNamespace, "System"), "Int32", arity: 0); Assert.Throws<ArgumentException>(null, () => compilation.CreateBuiltinOperator( WellKnownMemberNames.UnaryPlusOperatorName, fakeIntType, fakeIntType)); } [Fact] public void CreateBuiltinUnaryOperator_RealErrorType() { var compilation = CreateCompilation("", references: Array.Empty<MetadataReference>(), targetFramework: TargetFramework.Empty); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); var op = compilation.CreateBuiltinOperator(WellKnownMemberNames.UnaryPlusOperatorName, intType, intType); var result = op.ToDisplayString(); AssertEx.Equal("int.operator +(int)", result); } [Fact] public void CreateBuiltinUnaryOperator_NotSupported() { var compilation = CreateCompilation(""); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); var nullableIntType = compilation.GetSpecialType(SpecialType.System_Nullable_T).GetPublicSymbol().Construct(intType); // Binary operator name Assert.Throws<ArgumentException>("name", () => compilation.CreateBuiltinOperator(WellKnownMemberNames.AdditionOperatorName, intType, intType)); // Nullable type 1 Assert.Throws<ArgumentException>(null, () => compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedUnaryNegationOperatorName, nullableIntType, intType)); // Nullable type 2 Assert.Throws<ArgumentException>(null, () => compilation.CreateBuiltinOperator(WellKnownMemberNames.CheckedUnaryNegationOperatorName, intType, nullableIntType)); // op_Implicit Assert.Throws<ArgumentException>("name", () => compilation.CreateBuiltinOperator(WellKnownMemberNames.ImplicitConversionName, intType, intType)); // op_Explicit Assert.Throws<ArgumentException>("name", () => compilation.CreateBuiltinOperator(WellKnownMemberNames.ExplicitConversionName, intType, intType)); // op_True Assert.Throws<ArgumentException>("name", () => compilation.CreateBuiltinOperator(WellKnownMemberNames.TrueOperatorName, intType, intType)); // op_False Assert.Throws<ArgumentException>("name", () => compilation.CreateBuiltinOperator(WellKnownMemberNames.FalseOperatorName, intType, intType)); } [Fact] public void CreateBuiltinUnaryOperator_NullChecks() { var compilation = CreateCompilation(""); var intType = compilation.GetSpecialType(SpecialType.System_Int32).GetPublicSymbol(); Assert.Throws<ArgumentNullException>("returnType", () => compilation.CreateBuiltinOperator( WellKnownMemberNames.UnaryPlusOperatorName, null, intType)); Assert.Throws<ArgumentNullException>("operandType", () => compilation.CreateBuiltinOperator( WellKnownMemberNames.UnaryPlusOperatorName, intType, null)); } [Fact] [WorkItem(36046, "https://github.com/dotnet/roslyn/issues/36046")] [ValidatePooledObjects(LeakReason = "EnsureCSharpSymbolOrNull throws on VB type arguments after ArrayBuilder allocation")] public void ConstructTypeWithNullability() { var source = @"class Pair<T, U> { }"; var comp = (Compilation)CreateCompilation(source); var genericType = (INamedTypeSymbol)comp.GetMember("Pair"); var typeArguments = ImmutableArray.Create<ITypeSymbol>(comp.GetSpecialType(SpecialType.System_Object), comp.GetSpecialType(SpecialType.System_String)); Assert.Throws<ArgumentException>(() => genericType.Construct(default(ImmutableArray<ITypeSymbol>), default(ImmutableArray<CodeAnalysis.NullableAnnotation>))); Assert.Throws<ArgumentException>(() => genericType.Construct(typeArguments: default, typeArgumentNullableAnnotations: default)); var type = genericType.Construct(typeArguments, default); Assert.Equal("Pair<System.Object, System.String>", type.ToTestDisplayString(includeNonNullable: true)); AssertEx.Equal(new[] { CodeAnalysis.NullableAnnotation.None, CodeAnalysis.NullableAnnotation.None }, type.TypeArgumentNullableAnnotations); AssertEx.Equal(new[] { CodeAnalysis.NullableAnnotation.None, CodeAnalysis.NullableAnnotation.None }, type.TypeArgumentNullableAnnotations()); Assert.Throws<ArgumentException>(() => genericType.Construct(typeArguments, ImmutableArray<CodeAnalysis.NullableAnnotation>.Empty)); Assert.Throws<ArgumentException>(() => genericType.Construct(ImmutableArray.Create<ITypeSymbol>(null, null), default)); type = genericType.Construct(typeArguments, ImmutableArray.Create(CodeAnalysis.NullableAnnotation.Annotated, CodeAnalysis.NullableAnnotation.NotAnnotated)); Assert.Equal("Pair<System.Object?, System.String!>", type.ToTestDisplayString(includeNonNullable: true)); AssertEx.Equal(new[] { CodeAnalysis.NullableAnnotation.Annotated, CodeAnalysis.NullableAnnotation.NotAnnotated }, type.TypeArgumentNullableAnnotations); AssertEx.Equal(new[] { CodeAnalysis.NullableAnnotation.Annotated, CodeAnalysis.NullableAnnotation.NotAnnotated }, type.TypeArgumentNullableAnnotations()); // Type arguments from VB. comp = CreateVisualBasicCompilation(""); typeArguments = ImmutableArray.Create<ITypeSymbol>(comp.GetSpecialType(SpecialType.System_Object), comp.GetSpecialType(SpecialType.System_String)); Assert.Throws<ArgumentException>(() => genericType.Construct(typeArguments, default)); } [Fact] [WorkItem(37310, "https://github.com/dotnet/roslyn/issues/37310")] [ValidatePooledObjects(LeakReason = "EnsureCSharpSymbolOrNull throws on VB type arguments after ArrayBuilder allocation")] public void ConstructMethodWithNullability() { var source = @"class Program { static void M<T, U>() { } }"; var comp = (Compilation)CreateCompilation(source); var genericMethod = (IMethodSymbol)comp.GetMember("Program.M"); var typeArguments = ImmutableArray.Create<ITypeSymbol>(comp.GetSpecialType(SpecialType.System_Object), comp.GetSpecialType(SpecialType.System_String)); Assert.Throws<ArgumentException>(() => genericMethod.Construct(default(ImmutableArray<ITypeSymbol>), default(ImmutableArray<CodeAnalysis.NullableAnnotation>))); Assert.Throws<ArgumentException>(() => genericMethod.Construct(typeArguments: default, typeArgumentNullableAnnotations: default)); var type = genericMethod.Construct(typeArguments, default); Assert.Equal("void Program.M<System.Object, System.String>()", type.ToTestDisplayString(includeNonNullable: true)); AssertEx.Equal(new[] { CodeAnalysis.NullableAnnotation.None, CodeAnalysis.NullableAnnotation.None }, type.TypeArgumentNullableAnnotations); AssertEx.Equal(new[] { CodeAnalysis.NullableAnnotation.None, CodeAnalysis.NullableAnnotation.None }, type.TypeArgumentNullableAnnotations()); Assert.Throws<ArgumentException>(() => genericMethod.Construct(typeArguments, ImmutableArray<CodeAnalysis.NullableAnnotation>.Empty)); Assert.Throws<ArgumentException>(() => genericMethod.Construct(ImmutableArray.Create<ITypeSymbol>(null, null), default)); type = genericMethod.Construct(typeArguments, ImmutableArray.Create(CodeAnalysis.NullableAnnotation.Annotated, CodeAnalysis.NullableAnnotation.NotAnnotated)); Assert.Equal("void Program.M<System.Object?, System.String!>()", type.ToTestDisplayString(includeNonNullable: true)); AssertEx.Equal(new[] { CodeAnalysis.NullableAnnotation.Annotated, CodeAnalysis.NullableAnnotation.NotAnnotated }, type.TypeArgumentNullableAnnotations); AssertEx.Equal(new[] { CodeAnalysis.NullableAnnotation.Annotated, CodeAnalysis.NullableAnnotation.NotAnnotated }, type.TypeArgumentNullableAnnotations()); // Type arguments from VB. comp = CreateVisualBasicCompilation(""); typeArguments = ImmutableArray.Create<ITypeSymbol>(comp.GetSpecialType(SpecialType.System_Object), comp.GetSpecialType(SpecialType.System_String)); Assert.Throws<ArgumentException>(() => genericMethod.Construct(typeArguments, default)); } [Fact, WorkItem(65499, "https://github.com/dotnet/roslyn/issues/65499")] public void NetModuleReference() { var module = CreateCompilation(string.Empty, options: TestOptions.ReleaseDll.WithOutputKind(OutputKind.NetModule)); module.VerifyDiagnostics(); var moduleStream = new MemoryStream(); var result = module.Emit(moduleStream); Assert.True(result.Success); moduleStream.Position = 0; var moduleReference = MetadataReference.CreateFromStream(moduleStream, MetadataReferenceProperties.Module); var comp = CreateCompilation(string.Empty, references: new[] { moduleReference }); comp.VerifyEmitDiagnostics(); Assert.Equal(2, comp.Assembly.Modules.Length); } [ConditionalFact(typeof(IsEnglishLocal))] [WorkItem(65499, "https://github.com/dotnet/roslyn/issues/65499")] [WorkItem(71236, "https://github.com/dotnet/roslyn/issues/71236")] public void NetModuleReference_AssemblySpecifiedAsModule() { var module = CreateCompilation(string.Empty); module.VerifyDiagnostics(); var moduleStream = new MemoryStream(); var result = module.Emit(moduleStream); Assert.True(result.Success); moduleStream.Position = 0; var moduleReference = MetadataReference.CreateFromStream(moduleStream, MetadataReferenceProperties.Module); var comp = CreateCompilation(string.Empty, references: new[] { moduleReference }); comp.VerifyEmitDiagnostics( // error CS1542: '<in-memory module>' cannot be added to this assembly because it already is an assembly Diagnostic(ErrorCode.ERR_AddModuleAssembly).WithArguments("<in-memory module>").WithLocation(1, 1)); Assert.Equal(1, comp.Assembly.Modules.Length); } [ConditionalFact(typeof(IsEnglishLocal))] [WorkItem(65499, "https://github.com/dotnet/roslyn/issues/65499")] [WorkItem(71236, "https://github.com/dotnet/roslyn/issues/71236")] public void NetModuleReference_ModuleSpecifiedAsAssembly() { var module = CreateCompilation(string.Empty, options: TestOptions.ReleaseDll.WithOutputKind(OutputKind.NetModule)); module.VerifyDiagnostics(); var moduleStream = new MemoryStream(); var result = module.Emit(moduleStream); Assert.True(result.Success); moduleStream.Position = 0; var moduleReference = MetadataReference.CreateFromStream(moduleStream, MetadataReferenceProperties.Assembly); var comp = CreateCompilation(string.Empty, references: new[] { moduleReference }); comp.VerifyEmitDiagnostics( // error CS1509: The referenced file '<in-memory assembly>' is not an assembly Diagnostic(ErrorCode.ERR_ImportNonAssembly).WithArguments("<in-memory assembly>").WithLocation(1, 1)); Assert.Equal(1, comp.Assembly.Modules.Length); } #region Script return values [ConditionalFact(typeof(DesktopOnly))] public void ReturnNullAsObject() { var script = CreateSubmission("return null;", returnType: typeof(object)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnStringAsObject() { var script = CreateSubmission("return \"¡Hola!\";", returnType: typeof(object)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnIntAsObject() { var script = CreateSubmission("return 42;", returnType: typeof(object)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void TrailingReturnVoidAsObject() { var script = CreateSubmission("return", returnType: typeof(object)); script.VerifyDiagnostics( // (1,7): error CS1733: Expected expression // return Diagnostic(ErrorCode.ERR_ExpressionExpected, "").WithLocation(1, 7), // (1,7): error CS1002: ; expected // return Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 7)); Assert.False(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnIntAsInt() { var script = CreateSubmission("return 42;", returnType: typeof(int)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnNullResultType() { // test that passing null is the same as passing typeof(object) var script = CreateSubmission("return 42;", returnType: null); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnNoSemicolon() { var script = CreateSubmission("return 42", returnType: typeof(uint)); script.VerifyDiagnostics( // (1,10): error CS1002: ; expected // return 42 Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 10)); Assert.False(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnAwait() { var script = CreateSubmission("return await System.Threading.Tasks.Task.FromResult(42);", returnType: typeof(int)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); script = CreateSubmission("return await System.Threading.Tasks.Task.FromResult(42);", returnType: typeof(Task<int>)); script.VerifyDiagnostics( // (1,8): error CS0029: Cannot implicitly convert type 'int' to 'System.Threading.Tasks.Task<int>' // return await System.Threading.Tasks.Task.FromResult(42); Diagnostic(ErrorCode.ERR_NoImplicitConv, "await System.Threading.Tasks.Task.FromResult(42)").WithArguments("int", "System.Threading.Tasks.Task<int>").WithLocation(1, 8)); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnTaskNoAwait() { var script = CreateSubmission("return System.Threading.Tasks.Task.FromResult(42);", returnType: typeof(int)); script.VerifyDiagnostics( // (1,8): error CS4016: Since this is an async method, the return expression must be of type 'int' rather than 'Task<int>' // return System.Threading.Tasks.Task.FromResult(42); Diagnostic(ErrorCode.ERR_BadAsyncReturnExpression, "System.Threading.Tasks.Task.FromResult(42)").WithArguments("int", "System.Threading.Tasks.Task<int>").WithLocation(1, 8)); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnInNestedScopes() { var script = CreateSubmission(@" bool condition = false; if (condition) { return 1; } else { return -1; }", returnType: typeof(int)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnInNestedScopeWithTrailingExpression() { var script = CreateSubmission(@" if (true) { return 1; } System.Console.WriteLine();", returnType: typeof(object)); script.VerifyDiagnostics( // (6,1): warning CS0162: Unreachable code detected // System.Console.WriteLine(); Diagnostic(ErrorCode.WRN_UnreachableCode, "System").WithLocation(6, 1)); Assert.True(script.HasSubmissionResult()); script = CreateSubmission(@" if (true) { return 1; } System.Console.WriteLine()", returnType: typeof(object)); script.VerifyDiagnostics( // (6,1): warning CS0162: Unreachable code detected // System.Console.WriteLine(); Diagnostic(ErrorCode.WRN_UnreachableCode, "System").WithLocation(6, 1)); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnInNestedScopeNoTrailingExpression() { var script = CreateSubmission(@" bool condition = false; if (condition) { return 1; } System.Console.WriteLine();", returnType: typeof(int)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnInNestedMethod() { var script = CreateSubmission(@" int TopMethod() { return 42; }", returnType: typeof(string)); script.VerifyDiagnostics(); Assert.False(script.HasSubmissionResult()); script = CreateSubmission(@" object TopMethod() { return new System.Exception(); } TopMethod().ToString()", returnType: typeof(string)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnInNestedLambda() { var script = CreateSubmission(@" System.Func<object> f = () => { return new System.Exception(); }; 42", returnType: typeof(int)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); script = CreateSubmission(@" System.Func<object> f = () => new System.Exception(); 42", returnType: typeof(int)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnInNestedAnonymousMethod() { var script = CreateSubmission(@" System.Func<object> f = delegate () { return new System.Exception(); }; 42", returnType: typeof(int)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void LoadedFileWithWrongReturnType() { var resolver = TestSourceReferenceResolver.Create( KeyValuePair.Create("a.csx", "return \"Who returns a string?\";")); var script = CreateSubmission(@" #load ""a.csx"" 42", returnType: typeof(int), options: TestOptions.DebugDll.WithSourceReferenceResolver(resolver)); script.VerifyDiagnostics( // a.csx(1,8): error CS0029: Cannot implicitly convert type 'string' to 'int' // return "Who returns a string?" Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""Who returns a string?""").WithArguments("string", "int").WithLocation(1, 8), // (3,1): warning CS0162: Unreachable code detected // 42 Diagnostic(ErrorCode.WRN_UnreachableCode, "42").WithLocation(3, 1)); Assert.True(script.HasSubmissionResult()); } [ConditionalFact(typeof(DesktopOnly))] public void ReturnVoidInNestedMethodOrLambda() { var script = CreateSubmission(@" void M1() { return; } System.Action a = () => { return; }; 42", returnType: typeof(int)); script.VerifyDiagnostics(); Assert.True(script.HasSubmissionResult()); var compilation = CreateCompilationWithMscorlib461(@" void M1() { return; } System.Action a = () => { return; }; 42", parseOptions: TestOptions.Script); compilation.VerifyDiagnostics(); } #endregion #region GetTypesByMetadataName Tests [Fact] public void GetTypesByMetadataName_NotInSourceNotInReferences() { var comp = CreateCompilation(""); comp.VerifyDiagnostics(); var types = comp.GetTypesByMetadataName("N.C`1"); Assert.Empty(types); } [Theory] [CombinatorialData] public void GetTypesByMetadataName_SingleInSourceNotInReferences( bool useMetadataReference, [CombinatorialValues("public", "internal")] string accessibility) { var referenceComp = CreateCompilation(""); var comp = CreateCompilation( $@"namespace N; {accessibility} class C<T> {{}}", new[] { useMetadataReference ? referenceComp.ToMetadataReference() : referenceComp.EmitToImageReference() }); comp.VerifyDiagnostics(); var types = comp.GetTypesByMetadataName("N.C`1"); Assert.Single(types); AssertEx.Equal("N.C<T>", types[0].ToTestDisplayString()); } [Theory] [CombinatorialData] public void GetTypesByMetadataName_MultipleInSourceNotInReferences( bool useMetadataReference, [CombinatorialValues("public", "internal")] string accessibility) { var referenceComp = CreateCompilation(""); var comp = CreateCompilation( $@"namespace N; {accessibility} class C<T> {{}} {accessibility} class C<T> {{}}", new[] { useMetadataReference ? referenceComp.ToMetadataReference() : referenceComp.EmitToImageReference() }); comp.VerifyDiagnostics( // (3,16): error CS0101: The namespace 'N' already contains a definition for 'C' // internal class C<T> {} Diagnostic(ErrorCode.ERR_DuplicateNameInNS, "C").WithArguments("C", "N").WithLocation(3, 8 + accessibility.Length) ); var types = comp.GetTypesByMetadataName("N.C`1"); Assert.Single(types); AssertEx.Equal("N.C<T>", types[0].ToTestDisplayString()); Assert.Equal(2, types[0].Locations.Length); } [Theory] [CombinatorialData] public void GetTypesByMetadataName_SingleInSourceSingleInReferences( bool useMetadataReference, [CombinatorialValues("public", "internal")] string accessibility) { string source = $@"namespace N; {accessibility} class C<T> {{}}"; var referenceComp = CreateCompilation(source); referenceComp.VerifyDiagnostics(); MetadataReference reference = useMetadataReference ? referenceComp.ToMetadataReference() : referenceComp.EmitToImageReference(); var comp = CreateCompilation(source, new[] { reference }); comp.VerifyDiagnostics(); var types = comp.GetTypesByMetadataName("N.C`1"); Assert.Equal(2, types.Length); AssertEx.Equal("N.C<T>", types[0].ToTestDisplayString()); Assert.Same(comp.Assembly.GetPublicSymbol(), types[0].ContainingAssembly); AssertEx.Equal("N.C<T>", types[1].ToTestDisplayString()); var assembly1 = comp.GetAssemblyOrModuleSymbol(reference).GetPublicSymbol(); Assert.Same(types[1].ContainingAssembly, assembly1); } [Theory] [CombinatorialData] public void GetTypesByMetadataName_NotInSourceSingleInReferences( bool useMetadataReference, [CombinatorialValues("public", "internal")] string accessibility) { string source = @$"namespace N; {accessibility} class C<T> {{}}"; var referenceComp = CreateCompilation(source); referenceComp.VerifyDiagnostics(); MetadataReference reference = useMetadataReference ? referenceComp.ToMetadataReference() : referenceComp.EmitToImageReference(); var comp = CreateCompilation("", new[] { reference }); comp.VerifyDiagnostics(); var types = comp.GetTypesByMetadataName("N.C`1"); Assert.Single(types); AssertEx.Equal("N.C<T>", types[0].ToTestDisplayString()); var assembly1 = comp.GetAssemblyOrModuleSymbol(reference).GetPublicSymbol(); Assert.Same(types[0].ContainingAssembly, assembly1); } [Theory] [CombinatorialData] public void GetTypesByMetadataName_NotInSourceMultipleInReferences( bool useMetadataReference, [CombinatorialValues("public", "internal")] string accessibility) { string source = @$"namespace N; {accessibility} class C<T> {{}}"; var referenceComp1 = CreateCompilation(source); referenceComp1.VerifyDiagnostics(); var referenceComp2 = CreateCompilation(source); referenceComp2.VerifyDiagnostics(); MetadataReference reference1 = getReference(referenceComp1); MetadataReference reference2 = getReference(referenceComp2); var comp = CreateCompilation("", new[] { reference1, reference2 }); comp.VerifyDiagnostics(); var types = comp.GetTypesByMetadataName("N.C`1"); Assert.Equal(2, types.Length); AssertEx.Equal("N.C<T>", types[0].ToTestDisplayString()); AssertEx.Equal("N.C<T>", types[1].ToTestDisplayString()); var assembly1 = comp.GetAssemblyOrModuleSymbol(reference1).GetPublicSymbol(); Assert.Same(types[0].ContainingAssembly, assembly1); var assembly2 = comp.GetAssemblyOrModuleSymbol(reference2).GetPublicSymbol(); Assert.Same(types[1].ContainingAssembly, assembly2); MetadataReference getReference(CSharpCompilation referenceComp1) { return useMetadataReference ? referenceComp1.ToMetadataReference() : referenceComp1.EmitToImageReference(); } } [Theory] [CombinatorialData] public void GetTypesByMetadataName_SingleInSourceMultipleInReferences( bool useMetadataReference, [CombinatorialValues("public", "internal")] string accessibility) { string source = @$"namespace N; {accessibility} class C<T> {{}}"; var referenceComp1 = CreateCompilation(source); referenceComp1.VerifyDiagnostics(); var referenceComp2 = CreateCompilation(source); referenceComp2.VerifyDiagnostics(); MetadataReference reference1 = getReference(referenceComp1); MetadataReference reference2 = getReference(referenceComp2); var comp = CreateCompilation(source, new[] { reference1, reference2 }); comp.VerifyDiagnostics(); var types = comp.GetTypesByMetadataName("N.C`1"); Assert.Equal(3, types.Length); AssertEx.Equal("N.C<T>", types[0].ToTestDisplayString()); Assert.Same(comp.Assembly.GetPublicSymbol(), types[0].ContainingAssembly); AssertEx.Equal("N.C<T>", types[1].ToTestDisplayString()); AssertEx.Equal("N.C<T>", types[2].ToTestDisplayString()); var assembly1 = comp.GetAssemblyOrModuleSymbol(reference1).GetPublicSymbol(); Assert.Same(types[1].ContainingAssembly, assembly1); var assembly2 = comp.GetAssemblyOrModuleSymbol(reference2).GetPublicSymbol(); Assert.Same(types[2].ContainingAssembly, assembly2); MetadataReference getReference(CSharpCompilation referenceComp1) { return useMetadataReference ? referenceComp1.ToMetadataReference() : referenceComp1.EmitToImageReference(); } } [Fact] public void GetTypesByMetadataName_Ordering() { var corlibSource = @" namespace System { public class Object {} public class Void {} } public class C {} "; var parseOptions = TestOptions.Regular.WithNoRefSafetyRulesAttribute(); var corlib = CreateEmptyCompilation(corlibSource, parseOptions: parseOptions); var corlibReference = corlib.EmitToImageReference(); var other = CreateEmptyCompilation(@"public class C {}", new[] { corlibReference }, parseOptions: parseOptions); var otherReference = other.EmitToImageReference(); var current = CreateEmptyCompilation(@"public class C {}", new[] { otherReference, corlibReference }); current.VerifyDiagnostics(); var types = current.GetTypesByMetadataName("C"); AssertEx.Equal(types.Select(t => t.ToTestDisplayString()), new[] { "C", "C", "C" }); Assert.Same(types[0].ContainingAssembly, current.Assembly.GetPublicSymbol()); var corlibAssembly = current.GetAssemblyOrModuleSymbol(corlibReference).GetPublicSymbol(); Assert.Same(types[1].ContainingAssembly, corlibAssembly); var otherAssembly = current.GetAssemblyOrModuleSymbol(otherReference).GetPublicSymbol(); Assert.Same(types[2].ContainingAssembly, otherAssembly); } [Fact] public void GetTypeByMetadataName_CorLibViaExtern() { var corlibSource = @" namespace System { public class Object {} public class Void {} } public class C {} "; var parseOptions = TestOptions.Regular.WithNoRefSafetyRulesAttribute(); var corlib = CreateEmptyCompilation(corlibSource, parseOptions: parseOptions); var corlibReference = corlib.EmitToImageReference(aliases: ImmutableArray.Create("corlib")); var current = CreateEmptyCompilation(@"", new[] { corlibReference }, parseOptions: parseOptions); current.VerifyDiagnostics(); var type = ((Compilation)current).GetTypeByMetadataName("C"); Assert.NotNull(type); var corlibAssembly = current.GetAssemblyOrModuleSymbol(corlibReference).GetPublicSymbol(); Assert.Same(type.ContainingAssembly, corlibAssembly); } [Fact] public void GetTypeByMetadataName_OtherViaExtern() { var corlibSource = @" namespace System { public class Object {} public class Void {} } "; var parseOptions = TestOptions.Regular.WithNoRefSafetyRulesAttribute(); var corlib = CreateEmptyCompilation(corlibSource, parseOptions: parseOptions); var corlibReference = corlib.EmitToImageReference(); var other = CreateEmptyCompilation(@"public class C {}", new[] { corlibReference }, parseOptions: parseOptions); var otherReference = other.EmitToImageReference(aliases: ImmutableArray.Create("other")); var current = CreateEmptyCompilation(@"", new[] { otherReference, corlibReference }); current.VerifyDiagnostics(); var type = ((Compilation)current).GetTypeByMetadataName("C"); Assert.Null(type); } #endregion } }