/// <summary> /// Entrypoint for the <see cref="T:Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.CSharpExpressionCompiler"/>. /// </summary> internal static EmitBaseline CreateInitialBaselineWithoutChecks(ModuleMetadata module, LocalVariableNameProvider localNames) { var reader = module.MetadataReader; var moduleVersionId = module.GetModuleVersionId(); return new EmitBaseline( module, compilation: null, moduleBuilder: null, moduleVersionId: moduleVersionId, ordinal: 0, encId: default(Guid), typesAdded: new Dictionary<ITypeDefinition, uint>(), eventsAdded: new Dictionary<IEventDefinition, uint>(), fieldsAdded: new Dictionary<IFieldDefinition, uint>(), methodsAdded: new Dictionary<IMethodDefinition, uint>(), propertiesAdded: new Dictionary<IPropertyDefinition, uint>(), eventMapAdded: new Dictionary<uint, uint>(), propertyMapAdded: new Dictionary<uint, uint>(), tableEntriesAdded: EmptyTableSizes, blobStreamLengthAdded: 0, stringStreamLengthAdded: 0, userStringStreamLengthAdded: 0, guidStreamLengthAdded: 0, anonymousTypeMap: null, // Unset for initial metadata localsForMethodsAddedOrChanged: new Dictionary<uint, ImmutableArray<EncLocalInfo>>(), localNames: localNames, typeToEventMap: reader.CalculateTypeEventMap(), typeToPropertyMap: reader.CalculateTypePropertyMap()); }
public WinMDModule( ModuleMetadata owner, AbstractMemoryBlock memoryBlock, PEFileReader peFileReader, ReadOnlyArray<AssemblyIdentity> referencedAssemblies, WinMDScenario scenario) : base(owner, memoryBlock, peFileReader, referencedAssemblies) { this.scenario = scenario; this.winMdStartIndex = (uint)referencedAssemblies.Count - WinMdExtraRefs; }
public EmitBaseline( Compilation compilation, ModuleMetadata module, int ordinal, Guid encId, Microsoft.CodeAnalysis.Emit.GenerationDelta delta) : base(module, ordinal) { this.compilation = compilation; this.encId = encId; this.delta = delta; }
private ImmutableArray<ModuleMetadata> GetAllModules(ModuleMetadata manifestModule, string assemblyDir) { ArrayBuilder<ModuleMetadata> moduleBuilder = null; foreach (string moduleName in manifestModule.GetModuleNames()) { if (moduleBuilder == null) { moduleBuilder = ArrayBuilder<ModuleMetadata>.GetInstance(); moduleBuilder.Add(manifestModule); } var module = CreateModuleMetadata(PathUtilities.CombineAbsoluteAndRelativePaths(assemblyDir, moduleName), prefetchEntireImage: false); moduleBuilder.Add(module); } return (moduleBuilder != null) ? moduleBuilder.ToImmutableAndFree() : ImmutableArray.Create(manifestModule); }
/// <summary> /// Creates an <see cref="EmitBaseline"/> from the metadata of the module before editing /// and from a function that maps from a method to an array of local names. Only the /// initial baseline is created using this method; subsequent baselines are created /// automatically when emitting the differences in subsequent compilations. /// </summary> /// <param name="module">The metadata of the module before editing.</param> /// <param name="localNames">A function that returns the array of local names given a method index from the module metadata.</param> /// <returns>An EmitBaseline for the module.</returns> public static EmitBaseline CreateInitialBaseline(ModuleMetadata module, LocalVariableNameProvider localNames) { if (module == null) { throw new ArgumentNullException("module"); } if (!module.Module.HasIL) { throw new ArgumentException(CodeAnalysisResources.PEImageNotAvailable, "module"); } if (localNames == null) { throw new ArgumentNullException("localNames"); } return CreateInitialBaselineWithoutChecks(module, localNames); }
internal ModuleInstance( MetadataReference metadataReference, ModuleMetadata moduleMetadata, Guid moduleVersionId, byte[] fullImage, byte[] metadataOnly, object symReader, bool includeLocalSignatures) { Debug.Assert((fullImage == null) || (fullImage.Length > metadataOnly.Length)); this.MetadataReference = metadataReference; this.ModuleMetadata = moduleMetadata; this.ModuleVersionId = moduleVersionId; this.FullImage = fullImage; this.MetadataOnly = metadataOnly; this.MetadataHandle = GCHandle.Alloc(metadataOnly, GCHandleType.Pinned); this.SymReader = symReader; // should be non-null if and only if there are symbols _includeLocalSignatures = includeLocalSignatures; }
public void AddReferences_Errors() { var moduleRef = ModuleMetadata.CreateFromImage(TestResources.MetadataTests.NetModule01.ModuleCS00).GetReference(); var options = ScriptOptions.Default.WithReferences(ImmutableArray <MetadataReference> .Empty); Assert.Throws <ArgumentNullException>("references", () => options.AddReferences((MetadataReference[])null)); Assert.Throws <ArgumentNullException>("references[0]", () => options.AddReferences(new MetadataReference[] { null })); Assert.Throws <ArgumentNullException>("references", () => options.AddReferences((IEnumerable <MetadataReference>)null)); Assert.Throws <ArgumentNullException>("references[0]", () => options.AddReferences((IEnumerable <MetadataReference>) new MetadataReference[] { null })); Assert.Throws <ArgumentNullException>("references", () => options.AddReferences((Assembly[])null)); Assert.Throws <ArgumentNullException>("references[0]", () => options.AddReferences(new Assembly[] { null })); Assert.Throws <ArgumentNullException>("references", () => options.AddReferences((IEnumerable <Assembly>)null)); Assert.Throws <ArgumentNullException>("references[0]", () => options.AddReferences((IEnumerable <Assembly>) new Assembly[] { null })); Assert.Throws <ArgumentNullException>("references", () => options.AddReferences((string[])null)); Assert.Throws <ArgumentNullException>("references[0]", () => options.AddReferences(new string[] { null })); Assert.Throws <ArgumentNullException>("references", () => options.AddReferences((IEnumerable <string>)null)); Assert.Throws <ArgumentNullException>("references[0]", () => options.AddReferences((IEnumerable <string>) new string[] { null })); }
/// <summary> /// Validate the contents of the DeclSecurity metadata table. /// </summary> internal static void ValidateDeclSecurity(CSharpCompilation compilation, params DeclSecurityEntry[] expectedEntries) { using (var metadata = ModuleMetadata.CreateFromImage(compilation.EmitToArray())) { var metadataReader = metadata.Module.GetMetadataReader(); Assert.Equal(expectedEntries.Length, metadataReader.DeclarativeSecurityAttributes.Count); var actualEntries = new List <DeclSecurityEntry>(expectedEntries.Length); int i = 0; foreach (var actualHandle in metadataReader.DeclarativeSecurityAttributes) { var actual = metadataReader.GetDeclarativeSecurityAttribute(actualHandle); var expected = expectedEntries[i]; var actualPermissionSetBytes = metadataReader.GetBytes(actual.PermissionSet); var actualPermissionSet = new string(actualPermissionSetBytes.Select(b => (char)b).ToArray()); string actualParentName; SymbolKind actualParentKind; GetAttributeParentNameAndKind(metadataReader, actual.Parent, out actualParentName, out actualParentKind); actualEntries.Add(new DeclSecurityEntry() { ActionFlags = actual.Action, ParentNameOpt = actualParentName, PermissionSet = actualPermissionSet, ParentKind = actualParentKind }); i++; } AssertEx.SetEqual(actualEntries, expectedEntries); } }
public void Ctor_Errors() { Assert.Throws <ArgumentException>(() => AssemblyMetadata.CreateFromImage(default(ImmutableArray <byte>))); Assert.Throws <ArgumentException>(() => AssemblyMetadata.CreateFromImage(default(IEnumerable <byte>))); Assert.Throws <ArgumentException>(() => AssemblyMetadata.CreateFromImage(default(byte[]))); Assert.Throws <ArgumentNullException>(() => AssemblyMetadata.Create((ModuleMetadata)null)); Assert.Throws <ArgumentException>(() => AssemblyMetadata.Create(default(ImmutableArray <ModuleMetadata>))); Assert.Throws <ArgumentException>(() => AssemblyMetadata.Create(ImmutableArray.Create <ModuleMetadata>())); var m1 = ModuleMetadata.CreateFromImage(TestResources.SymbolsTests.MultiModule.MultiModule); var m2 = ModuleMetadata.CreateFromImage(TestResources.SymbolsTests.MultiModule.mod2); var m3 = ModuleMetadata.CreateFromImage(TestResources.SymbolsTests.MultiModule.mod3); Assert.Throws <ArgumentException>(() => AssemblyMetadata.Create(m1, m2.Copy(), m3)); Assert.Throws <ArgumentException>(() => AssemblyMetadata.Create(new List <ModuleMetadata>(new ModuleMetadata[] { m1.Copy(), m2.Copy(), m3.Copy() }))); Assert.Throws <ArgumentNullException>(() => AssemblyMetadata.Create(ImmutableArray.Create(m1, m2, null))); Assert.Throws <ArgumentNullException>(() => AssemblyMetadata.Create(ImmutableArray.Create((ModuleMetadata)null))); Assert.Throws <ArgumentNullException>(() => AssemblyMetadata.CreateFromFile((string)null)); Assert.Throws <ArgumentException>(() => AssemblyMetadata.CreateFromFile("foo.dll")); Assert.Throws <ArgumentException>(() => AssemblyMetadata.CreateFromFile("c:foo.dll")); Assert.Throws <ArgumentException>(() => AssemblyMetadata.CreateFromFile(@".\foo.dll")); Assert.Throws <ArgumentException>(() => AssemblyMetadata.CreateFromFile(@"\foo.dll")); }
public static IEnumerable <MetadataReference> GetMetadataReferences(this LibraryExport export, bool throwOnError = true) { var references = new List <MetadataReference>(); AssemblyMetadata assemblyMetadata; foreach (var lib in export.CompilationAssemblies) { try { using (var stream = File.OpenRead(lib.ResolvedPath)) { var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata); assemblyMetadata = AssemblyMetadata.Create(moduleMetadata); references.Add(assemblyMetadata.GetReference()); } } catch (Exception ex) when(ex is FileNotFoundException || ex is DirectoryNotFoundException || ex is NotSupportedException || ex is ArgumentException || ex is ArgumentOutOfRangeException || ex is BadImageFormatException || ex is IOException || ex is ArgumentNullException) { // TODO: Log this if (throwOnError) { throw ex; } continue; } } return(references); }
public void EmptyStream() { ModuleMetadata.CreateFromStream(new MemoryStream(), PEStreamOptions.Default); Assert.Throws <BadImageFormatException>(() => ModuleMetadata.CreateFromStream(new MemoryStream(), PEStreamOptions.PrefetchMetadata)); Assert.Throws <BadImageFormatException>(() => ModuleMetadata.CreateFromStream(new MemoryStream(), PEStreamOptions.PrefetchMetadata | PEStreamOptions.PrefetchEntireImage)); }
public unsafe void CreateFromImage() { Assert.Throws <ArgumentNullException>(() => ModuleMetadata.CreateFromImage(IntPtr.Zero, 0)); Assert.Throws <ArgumentOutOfRangeException>(() => { fixed(byte *ptr = new byte[] { 1, 2, 3 }) ModuleMetadata.CreateFromImage((IntPtr)ptr, 0); }); Assert.Throws <ArgumentOutOfRangeException>(() => { fixed(byte *ptr = new byte[] { 1, 2, 3 }) ModuleMetadata.CreateFromImage((IntPtr)ptr, -1); }); Assert.Throws <ArgumentNullException>(() => ModuleMetadata.CreateFromImage(default(ImmutableArray <byte>))); IEnumerable <byte> enumerableImage = null; Assert.Throws <ArgumentNullException>(() => ModuleMetadata.CreateFromImage(enumerableImage)); byte[] arrayImage = null; Assert.Throws <ArgumentNullException>(() => ModuleMetadata.CreateFromImage(arrayImage)); // It's not particularly important that this not throw. The parsing of the metadata is now lazy, and the result is that an exception // will be thrown when something tugs on the metadata later. ModuleMetadata.CreateFromImage(TestResources.MetadataTests.Invalid.EmptyModuleTable); }
public void DependencyVersionWildcardsCollisions() { string srcLib01 = @" [assembly: System.Reflection.AssemblyVersion(""1.0.0.1"")] public class D { } "; string srcLib02 = @" [assembly: System.Reflection.AssemblyVersion(""1.0.0.2"")] public class D { } "; string srcLib11 = @" [assembly: System.Reflection.AssemblyVersion(""1.0.1.1"")] public class D { } "; string srcLib12 = @" [assembly: System.Reflection.AssemblyVersion(""1.0.1.2"")] public class D { } "; string src0 = @" extern alias L0; extern alias L1; class C { public static int F(L0::D a, L1::D b) => 1; } "; string src1 = @" extern alias L0; extern alias L1; class C { public static int F(L0::D a, L1::D b) => 2; } "; var lib01 = CreateCompilationWithMscorlib(srcLib01, assemblyName: "Lib", options: s_signedDll).VerifyDiagnostics(); var ref01 = lib01.ToMetadataReference(ImmutableArray.Create("L0")); var lib02 = CreateCompilationWithMscorlib(srcLib02, assemblyName: "Lib", options: s_signedDll).VerifyDiagnostics(); var ref02 = lib02.ToMetadataReference(ImmutableArray.Create("L0")); var lib11 = CreateCompilationWithMscorlib(srcLib11, assemblyName: "Lib", options: s_signedDll).VerifyDiagnostics(); var ref11 = lib11.ToMetadataReference(ImmutableArray.Create("L1")); var lib12 = CreateCompilationWithMscorlib(srcLib12, assemblyName: "Lib", options: s_signedDll).VerifyDiagnostics(); var ref12 = lib12.ToMetadataReference(ImmutableArray.Create("L1")); var compilation0 = CreateCompilation(src0, new[] { MscorlibRef, ref01, ref11 }, assemblyName: "C", options: TestOptions.DebugDll); var compilation1 = compilation0.WithSource(src1).WithReferences(new[] { MscorlibRef, ref02, ref12 }); var v0 = CompileAndVerify(compilation0); var f0 = compilation0.GetMember <MethodSymbol>("C.F"); var f1 = compilation1.GetMember <MethodSymbol>("C.F"); var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData); var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider); var diff1 = compilation1.EmitDifference( generation0, ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, f0, f1))); // TODO: message should be: Changing the version of an assembly reference is not allowed during debugging diff1.EmitResult.Diagnostics.Verify( // error CS7038: Failed to emit module 'C'. Diagnostic(ErrorCode.ERR_ModuleEmitFailure).WithArguments("C")); }
/// <summary> /// There are no comments for ModuleMetadataSet in the schema. /// </summary> public void AddToModuleMetadataSet(ModuleMetadata moduleMetadata) { base.AddObject("ModuleMetadataSet", moduleMetadata); }
private void WriteTo(ModuleMetadata metadata, ObjectWriter writer, CancellationToken cancellationToken) { writer.WriteInt32((int)metadata.Kind); WriteTo(metadata.GetMetadataReader(), writer, cancellationToken); }
private void TestDependencyVersionWildcards(string sourceVersion, Version version0, Version version1, Version version2) { string srcLib = $@" [assembly: System.Reflection.AssemblyVersion(""{sourceVersion}"")] public class D {{ }} "; string src0 = @" class C { public static int F(D a) { return 1; } } "; string src1 = @" class C { public static int F(D a) { return 2; } } "; string src2 = @" class C { public static int F(D a) { return 3; } public static int G(D a) { return 4; } } "; var lib0 = CreateCompilationWithMscorlib(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); ((SourceAssemblySymbol)lib0.Assembly).lazyAssemblyIdentity = new AssemblyIdentity("Lib", version0); lib0.VerifyDiagnostics(); var lib1 = CreateCompilationWithMscorlib(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); ((SourceAssemblySymbol)lib1.Assembly).lazyAssemblyIdentity = new AssemblyIdentity("Lib", version1); lib1.VerifyDiagnostics(); var lib2 = CreateCompilationWithMscorlib(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); ((SourceAssemblySymbol)lib2.Assembly).lazyAssemblyIdentity = new AssemblyIdentity("Lib", version2); lib2.VerifyDiagnostics(); var compilation0 = CreateCompilation(src0, new[] { MscorlibRef, lib0.ToMetadataReference() }, assemblyName: "C", options: TestOptions.DebugDll); var compilation1 = compilation0.WithSource(src1).WithReferences(new[] { MscorlibRef, lib1.ToMetadataReference() }); var compilation2 = compilation1.WithSource(src2).WithReferences(new[] { MscorlibRef, lib2.ToMetadataReference() }); var v0 = CompileAndVerify(compilation0); var v1 = CompileAndVerify(compilation1); var v2 = CompileAndVerify(compilation2); var f0 = compilation0.GetMember <MethodSymbol>("C.F"); var f1 = compilation1.GetMember <MethodSymbol>("C.F"); var f2 = compilation2.GetMember <MethodSymbol>("C.F"); var g2 = compilation2.GetMember <MethodSymbol>("C.G"); var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData); var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider); var diff1 = compilation1.EmitDifference( generation0, ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, f0, f1))); var diff2 = compilation2.EmitDifference( diff1.NextGeneration, ImmutableArray.Create( new SemanticEdit(SemanticEditKind.Update, f1, f2), new SemanticEdit(SemanticEditKind.Insert, null, g2))); var md1 = diff1.GetMetadata(); var md2 = diff2.GetMetadata(); var aggReader = new AggregatedMetadataReader(md0.MetadataReader, md1.Reader, md2.Reader); // all references to Lib should be to the baseline version: VerifyAssemblyReferences(aggReader, new[] { "mscorlib, 4.0.0.0", "Lib, " + lib0.Assembly.Identity.Version, "mscorlib, 4.0.0.0", "Lib, " + lib0.Assembly.Identity.Version, "mscorlib, 4.0.0.0", "Lib, " + lib0.Assembly.Identity.Version, }); }
/// <summary> /// Verify the set of module metadata blocks /// contains all blocks referenced by the set. /// </summary> internal static void VerifyAllModules(this ImmutableArray <ModuleInstance> modules) { var blocks = modules.SelectAsArray(m => m.MetadataBlock).SelectAsArray(b => ModuleMetadata.CreateFromMetadata(b.Pointer, b.Size)); var names = new HashSet <string>(blocks.Select(b => b.Name)); foreach (var block in blocks) { foreach (var name in block.GetModuleNames()) { Assert.True(names.Contains(name)); } } }
private void WriteMvidTo(ModuleMetadata metadata, ObjectWriter writer, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); writer.WriteInt32((int)metadata.Kind); var metadataReader = metadata.GetMetadataReader(); var mvidHandle = metadataReader.GetModuleDefinition().Mvid; var guid = metadataReader.GetGuid(mvidHandle); writer.WriteValue(guid.ToByteArray()); }
/// <summary> /// Get the ModuleMetadata from a cmdlet assembly. /// </summary> /// <param name="assmeblyPath">Path to the cmdlet assembly.</param> /// <returns>ModuleMetadata containing information about the cmdlets found in the given assembly.</returns> public ModuleMetadata GetModuleMetadata(string assemblyPath) { List <CmdletMetadata> results = new List <CmdletMetadata>(); ModuleMetadata = new ModuleMetadata(); try { var assembly = Assembly.LoadFrom(assemblyPath); foreach (var type in assembly.GetCmdletTypes()) { var cmdlet = type.GetAttribute <CmdletAttribute>(); var outputs = type.GetAttributes <OutputTypeAttribute>(); var parameters = type.GetParameters(); var cmdletMetadata = new CmdletMetadata { VerbName = cmdlet.VerbName, NounName = cmdlet.NounName, ConfirmImpact = cmdlet.ConfirmImpact, SupportsPaging = cmdlet.SupportsPaging, SupportsShouldProcess = cmdlet.SupportsShouldProcess, ClassName = type.FullName, DefaultParameterSetName = cmdlet.DefaultParameterSetName ?? "__AllParameterSets" }; if (type.HasAttribute <AliasAttribute>()) { var aliases = type.GetAttributes <AliasAttribute>(); cmdletMetadata.AliasList.AddRange( aliases.SelectMany(a => a.AliasNames)); } foreach (var output in outputs) { foreach (var outputType in output.Type) { var outputMetadata = new OutputMetadata { Type = outputType.Type }; outputMetadata.ParameterSets.AddRange(output.ParameterSetName); cmdletMetadata.OutputTypes.Add(outputMetadata); } } List <Parameter> globalParameters = new List <Parameter>(); foreach (var parameter in parameters) { if (string.Equals(parameter.Name, "Force", StringComparison.OrdinalIgnoreCase) && parameter.PropertyType == typeof(SwitchParameter)) { cmdletMetadata.HasForceSwitch = true; } var parameterData = new Models.ParameterMetadata { Type = parameter.PropertyType, Name = parameter.Name }; if (parameter.HasAttribute <AliasAttribute>()) { var aliases = parameter.GetAttributes <AliasAttribute>(); parameterData.AliasList.AddRange( aliases.SelectMany(a => a.AliasNames)); } if (parameter.HasAttribute <ValidateSetAttribute>()) { var validateSet = parameter.GetAttribute <ValidateSetAttribute>(); parameterData.ValidateSet.AddRange(validateSet.ValidValues); } if (parameter.HasAttribute <ValidateRangeAttribute>()) { var validateRange = parameter.GetAttribute <ValidateRangeAttribute>(); parameterData.ValidateRangeMin = Convert.ToInt64(validateRange.MinRange); parameterData.ValidateRangeMax = Convert.ToInt64(validateRange.MaxRange); } parameterData.ValidateNotNullOrEmpty = parameter.HasAttribute <ValidateNotNullOrEmptyAttribute>(); cmdletMetadata.Parameters.Add(parameterData); foreach (var parameterSet in parameter.GetAttributes <ParameterAttribute>()) { var parameterSetMetadata = cmdletMetadata.ParameterSets.FirstOrDefault(s => s.Name.Equals(parameterSet.ParameterSetName)); if (parameterSetMetadata == null) { parameterSetMetadata = new Models.ParameterSetMetadata() { Name = parameterSet.ParameterSetName ?? "__AllParameterSets" }; } Parameter param = new Parameter { ParameterMetadata = parameterData, Mandatory = parameterSet.Mandatory, Position = parameterSet.Position, ValueFromPipeline = parameterSet.ValueFromPipeline, ValueFromPipelineByPropertyName = parameterSet.ValueFromPipelineByPropertyName }; if (parameterSet.ParameterSetName.Equals("__AllParameterSets")) { globalParameters.Add(param); } parameterSetMetadata.Parameters.Add(param); if (parameterSetMetadata.Parameters.Count == 1) { cmdletMetadata.ParameterSets.Add(parameterSetMetadata); } } } foreach (var parameterSet in cmdletMetadata.ParameterSets) { if (parameterSet.Name.Equals("__AllParameterSets")) { continue; } foreach (var parameter in globalParameters) { var param = parameterSet.Parameters.FirstOrDefault(p => p.ParameterMetadata.Name.Equals(parameter.ParameterMetadata.Name)); if (param == null) { parameterSet.Parameters.Add(parameter); } } } if (!cmdletMetadata.ParameterSets .Where(p => p.Name.Equals(cmdletMetadata.DefaultParameterSetName, StringComparison.OrdinalIgnoreCase)) .Any()) { var defaultSet = new Models.ParameterSetMetadata() { Name = cmdletMetadata.DefaultParameterSetName }; cmdletMetadata.ParameterSets.Add(defaultSet); } results.Add(cmdletMetadata); } } catch (Exception ex) { throw ex; } ModuleMetadata.Cmdlets = results; return(ModuleMetadata); }
public static void Main() { try { // code for class A var classAString = @"public class A { public static string Print() { return ""Hello ""; } }"; // code for class B (to spice it up, it is a // subclass of A even though it is almost not needed // for the demonstration) var classBString = @"public class B : A { public static string Print() { return ""World!""; } }"; // the main class Program contain static void Main() // that calls A.Print() and B.Print() methods var mainProgramString = @"public class Program { public static void Main() { System.Console.Write(A.Print()); System.Console.WriteLine(B.Print()); } }"; #region class A compilation into A.netmodule // create Roslyn compilation for class A var compilationA = CreateCompilationWithMscorlib ( "A", classAString, compilerOptions: new CSharpCompilationOptions(OutputKind.NetModule) ); // emit the compilation result to a byte array // corresponding to A.netmodule byte code byte[] compilationAResult = compilationA.EmitToArray(); // create a reference to A.netmodule MetadataReference referenceA = ModuleMetadata .CreateFromImage(compilationAResult) .GetReference(display: "A.netmodule"); #endregion class A compilation into A.netmodule #region class B compilation into B.netmodule // create Roslyn compilation for class A var compilationB = CreateCompilationWithMscorlib ( "B", classBString, compilerOptions: new CSharpCompilationOptions(OutputKind.NetModule), // since class B extends A, we need to // add a reference to A.netmodule references: new[] { referenceA } ); // emit the compilation result to a byte array // corresponding to B.netmodule byte code byte[] compilationBResult = compilationB.EmitToArray(); // create a reference to B.netmodule MetadataReference referenceB = ModuleMetadata .CreateFromImage(compilationBResult) .GetReference(display: "B.netmodule"); #endregion class B compilation into B.netmodule #region main program compilation into the assembly // create the Roslyn compilation for the main program with // ConsoleApplication compilation options // adding references to A.netmodule and B.netmodule var mainCompilation = CreateCompilationWithMscorlib ( "program", mainProgramString, // note that here we pass the OutputKind set to ConsoleApplication compilerOptions: new CSharpCompilationOptions(OutputKind.ConsoleApplication), references: new[] { referenceA, referenceB } ); // Emit the byte result of the compilation byte[] result = mainCompilation.EmitToArray(); // Load the resulting assembly into the domain. Assembly assembly = Assembly.Load(result); #endregion main program compilation into the assembly // load the A.netmodule and B.netmodule into the assembly. assembly.LoadModule("A.netmodule", compilationAResult); assembly.LoadModule("B.netmodule", compilationBResult); #region Test the program // here we get the Program type and // call its static method Main() // to test the program. // It should write "Hello world!" // to the console // get the type Program from the assembly Type programType = assembly.GetType("Program"); // Get the static Main() method info from the type MethodInfo method = programType.GetMethod("Main"); // invoke Program.Main() static method method.Invoke(null, null); #endregion Test the program } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }
public void GenericType() { var source = @"using System.Diagnostics; class A<T> where T : class { [DebuggerDisplay(""{F(default(T), default(U))}"")] internal class B<U> { static object F<X, Y>(X x, Y y) where X : class { return x ?? (object)y; } } }"; var compilation0 = CreateCompilation( source, options: TestOptions.DebugDll, assemblyName: ExpressionCompilerUtilities.GenerateUniqueName() ); WithRuntimeInstance( compilation0, runtime => { var context = CreateTypeContext(runtime, "A.B"); string error; var testData = new CompilationTestData(); var result = context.CompileExpression( "F(default(T), default(U))", out error, testData ); string actualIL = testData.GetMethodData("<>x<T, U>.<>m0").GetMethodIL(); AssertEx.AssertEqualToleratingWhitespaceDifferences( actualIL, @"{ // Code size 24 (0x18) .maxstack 2 .locals init (T V_0, U V_1) IL_0000: ldloca.s V_0 IL_0002: initobj ""T"" IL_0008: ldloc.0 IL_0009: ldloca.s V_1 IL_000b: initobj ""U"" IL_0011: ldloc.1 IL_0012: call ""object A<T>.B<U>.F<T, U>(T, U)"" IL_0017: ret }" ); // Verify generated type is generic, but method is not. using ( var metadata = ModuleMetadata.CreateFromImage( ImmutableArray.CreateRange(result.Assembly) ) ) { var reader = metadata.MetadataReader; var typeDef = reader.GetTypeDef(result.TypeName); reader.CheckTypeParameters(typeDef.GetGenericParameters(), "T", "U"); var methodDef = reader.GetMethodDef(typeDef, result.MethodName); reader.CheckTypeParameters(methodDef.GetGenericParameters()); } } ); }
private void GetMetadata(Stream stream, long length, out ModuleMetadata metadata, out object lifeTimeObject) { var directAccess = stream as ISupportDirectMemoryAccess; if (directAccess != null) { metadata = ModuleMetadata.CreateFromMetadata(directAccess.GetPointer(), (int)length); lifeTimeObject = stream; return; } PinnedObject pinnedObject; ArraySegment<byte> buffer; var memory = stream as MemoryStream; if (memory != null && memory.TryGetBuffer(out buffer) && buffer.Offset == 0) { pinnedObject = new PinnedObject(buffer.Array, buffer.Count); } else { var array = new byte[length]; stream.Read(array, 0, (int)length); pinnedObject = new PinnedObject(array, length); } metadata = ModuleMetadata.CreateFromMetadata(pinnedObject.GetPointer(), (int)length); lifeTimeObject = pinnedObject; }
/// <summary> /// Create a new ModuleMetadata object. /// </summary> /// <param name="moduleName">Initial value of ModuleName.</param> public static ModuleMetadata CreateModuleMetadata(string moduleName) { ModuleMetadata moduleMetadata = new ModuleMetadata(); moduleMetadata.ModuleName = moduleName; return moduleMetadata; }
public void DependencyVersionWildcards_Metadata() { string srcLib = @" [assembly: System.Reflection.AssemblyVersion(""1.0.*"")] public class D { } "; string src0 = @" class C { public static int F(D a) { return 1; } } "; string src1 = @" class C { public static int F(D a) { return 2; } } "; string src2 = @" class C { public static int F(D a) { return 3; } public static int G(D a) { return 4; } } "; var lib0 = CreateCompilation(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); ((SourceAssemblySymbol)lib0.Assembly).lazyAssemblyIdentity = new AssemblyIdentity("Lib", new Version(1, 0, 2000, 1001)); lib0.VerifyDiagnostics(); var lib1 = CreateCompilation(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); ((SourceAssemblySymbol)lib1.Assembly).lazyAssemblyIdentity = new AssemblyIdentity("Lib", new Version(1, 0, 2000, 1002)); lib1.VerifyDiagnostics(); var lib2 = CreateCompilation(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); ((SourceAssemblySymbol)lib2.Assembly).lazyAssemblyIdentity = new AssemblyIdentity("Lib", new Version(1, 0, 2000, 1003)); lib2.VerifyDiagnostics(); var compilation0 = CreateEmptyCompilation(src0, new[] { MscorlibRef, lib0.EmitToImageReference() }, assemblyName: "C", options: TestOptions.DebugDll); var compilation1 = compilation0.WithSource(src1).WithReferences(new[] { MscorlibRef, lib1.EmitToImageReference() }); var compilation2 = compilation1.WithSource(src2).WithReferences(new[] { MscorlibRef, lib2.EmitToImageReference() }); var v0 = CompileAndVerify(compilation0); var v1 = CompileAndVerify(compilation1); var v2 = CompileAndVerify(compilation2); var f0 = compilation0.GetMember <MethodSymbol>("C.F"); var f1 = compilation1.GetMember <MethodSymbol>("C.F"); var f2 = compilation2.GetMember <MethodSymbol>("C.F"); var g2 = compilation2.GetMember <MethodSymbol>("C.G"); var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData); var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider); var diff1 = compilation1.EmitDifference( generation0, ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, f0, f1))); diff1.EmitResult.Diagnostics.Verify( // error CS7038: Failed to emit module 'C': Changing the version of an assembly reference is not allowed during debugging: // 'Lib, Version=1.0.2000.1001, Culture=neutral, PublicKeyToken=null' changed version to '1.0.2000.1002'. Diagnostic(ErrorCode.ERR_ModuleEmitFailure).WithArguments("C", string.Format(CodeAnalysisResources.ChangingVersionOfAssemblyReferenceIsNotAllowedDuringDebugging, "Lib, Version=1.0.2000.1001, Culture=neutral, PublicKeyToken=null", "1.0.2000.1002"))); }
internal static string Visualize(ModuleMetadata baseline, params PinnedMetadata[] deltas) { var result = new StringWriter(); new MetadataVisualizer(new[] { baseline.MetadataReader }.Concat(deltas.Select(d => d.Reader)).ToArray(), result).VisualizeAllGenerations(); return result.ToString(); }
public void CurrentComplationVersionWildcards() { var source0 = MarkedSource(@" using System; [assembly: System.Reflection.AssemblyVersion(""1.0.0.*"")] class C { static void M() { new Action(<N:0>() => { Console.WriteLine(1); }</N:0>).Invoke(); } static void F() { } }"); var source1 = MarkedSource(@" using System; [assembly: System.Reflection.AssemblyVersion(""1.0.0.*"")] class C { static void M() { new Action(<N:0>() => { Console.WriteLine(1); }</N:0>).Invoke(); new Action(<N:1>() => { Console.WriteLine(2); }</N:1>).Invoke(); } static void F() { } }"); var source2 = MarkedSource(@" using System; [assembly: System.Reflection.AssemblyVersion(""1.0.0.*"")] class C { static void M() { new Action(<N:0>() => { Console.WriteLine(1); }</N:0>).Invoke(); new Action(<N:1>() => { Console.WriteLine(2); }</N:1>).Invoke(); } static void F() { Console.WriteLine(1); } }"); var source3 = MarkedSource(@" using System; [assembly: System.Reflection.AssemblyVersion(""1.0.0.*"")] class C { static void M() { new Action(<N:0>() => { Console.WriteLine(1); }</N:0>).Invoke(); new Action(<N:1>() => { Console.WriteLine(2); }</N:1>).Invoke(); new Action(<N:2>() => { Console.WriteLine(3); }</N:2>).Invoke(); new Action(<N:3>() => { Console.WriteLine(4); }</N:3>).Invoke(); } static void F() { Console.WriteLine(1); } }"); var options = ComSafeDebugDll.WithCryptoPublicKey(TestResources.TestKeys.PublicKey_ce65828c82a341f2); var compilation0 = CreateCompilationWithMscorlib(source0.Tree, options: options.WithCurrentLocalTime(new DateTime(2016, 1, 1, 1, 0, 0))); var compilation1 = compilation0.WithSource(source1.Tree).WithOptions(options.WithCurrentLocalTime(new DateTime(2016, 1, 1, 1, 0, 10))); var compilation2 = compilation1.WithSource(source2.Tree).WithOptions(options.WithCurrentLocalTime(new DateTime(2016, 1, 1, 1, 0, 20))); var compilation3 = compilation2.WithSource(source3.Tree).WithOptions(options.WithCurrentLocalTime(new DateTime(2016, 1, 1, 1, 0, 30))); var v0 = CompileAndVerify(compilation0, verify: false); var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData); var reader0 = md0.MetadataReader; var m0 = compilation0.GetMember <MethodSymbol>("C.M"); var m1 = compilation1.GetMember <MethodSymbol>("C.M"); var m2 = compilation2.GetMember <MethodSymbol>("C.M"); var m3 = compilation3.GetMember <MethodSymbol>("C.M"); var f1 = compilation1.GetMember <MethodSymbol>("C.F"); var f2 = compilation2.GetMember <MethodSymbol>("C.F"); var generation0 = EmitBaseline.CreateInitialBaseline(md0, v0.CreateSymReader().GetEncMethodDebugInfo); // First update adds some new synthesized members (lambda related) var diff1 = compilation1.EmitDifference( generation0, ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, m0, m1, GetSyntaxMapFromMarkers(source0, source1), preserveLocalVariables: true))); diff1.VerifySynthesizedMembers( "C: {<>c}", "C.<>c: {<>9__0_0, <>9__0_1#1, <M>b__0_0, <M>b__0_1#1}"); // Second update is to a method that doesn't produce any synthesized members var diff2 = compilation2.EmitDifference( diff1.NextGeneration, ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, f1, f2, GetSyntaxMapFromMarkers(source1, source2), preserveLocalVariables: true))); diff2.VerifySynthesizedMembers( "C: {<>c}", "C.<>c: {<>9__0_0, <>9__0_1#1, <M>b__0_0, <M>b__0_1#1}"); // Last update again adds some new synthesized members (lambdas). // Synthesized members added in the first update need to be mapped to the current compilation. // Their containing assembly version is different than the version of the previous assembly and // hence we need to account for wildcards when comparing the versions. var diff3 = compilation3.EmitDifference( diff2.NextGeneration, ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, m2, m3, GetSyntaxMapFromMarkers(source2, source3), preserveLocalVariables: true))); diff3.VerifySynthesizedMembers( "C: {<>c}", "C.<>c: {<>9__0_0, <>9__0_1#1, <>9__0_2#3, <>9__0_3#3, <M>b__0_0, <M>b__0_1#1, <M>b__0_2#3, <M>b__0_3#3}"); }
private void GetMetadata(Stream stream, long length, out ModuleMetadata metadata, out object lifeTimeObject) { var directAccess = stream as ISupportDirectMemoryAccess; if (directAccess != null) { metadata = ModuleMetadata.CreateFromMetadata(directAccess.GetPointer(), (int)length); lifeTimeObject = stream; return; } PinnedObject pinnedObject; var memory = stream as MemoryStream; if (memory != null && PortableShim.MemoryStream.GetBuffer != null) { pinnedObject = new PinnedObject((byte[])PortableShim.MemoryStream.GetBuffer.Invoke(memory, null), length); } else { var array = new byte[length]; stream.Read(array, 0, (int)length); pinnedObject = new PinnedObject(array, length); } metadata = ModuleMetadata.CreateFromMetadata(pinnedObject.GetPointer(), (int)length); lifeTimeObject = pinnedObject; }
public void MethodExtents(DebugInformationFormat format) { var source0 = MarkedSource(@"#pragma checksum ""C:\Enc1.cs"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""1111111111111111111111111111111111111111"" using System; public class C { int A() => 1; void F() { #line 10 ""C:\F\A.cs"" Console.WriteLine(); #line 20 ""C:\F\B.cs"" Console.WriteLine(); #line default } int E() => 1; void G() { Func<int> H1 = <N:0>() => 1</N:0>; Action H2 = <N:1>() => { Func<int> H3 = <N:2>() => 3</N:2>; }</N:1>; } } ", fileName: @"C:\Enc1.cs"); var source1 = MarkedSource(@"#pragma checksum ""C:\Enc1.cs"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""2222222222222222222222222222222222222222"" using System; public class C { int A() => 1; void F() { #line 10 ""C:\F\A.cs"" Console.WriteLine(); #line 10 ""C:\F\C.cs"" Console.WriteLine(); #line default } void G() { Func<int> H1 = <N:0>() => 1</N:0>; Action H2 = <N:1>() => { Func<int> H3 = <N:2>() => 3</N:2>; Func<int> H4 = <N:3>() => 4</N:3>; }</N:1>; } int E() => 1; } ", fileName: @"C:\Enc1.cs"); var source2 = MarkedSource(@"#pragma checksum ""C:\Enc1.cs"" ""{ff1816ec-aa5e-4d10-87f7-6f4963833460}"" ""3333333333333333333333333333333333333333"" using System; public class C { int A() => 3; void F() { #line 10 ""C:\F\B.cs"" Console.WriteLine(); #line 10 ""C:\F\E.cs"" Console.WriteLine(); #line default } void G() { Action H2 = <N:1>() => { Func<int> H4 = <N:3>() => 4</N:3>; }</N:1>; } int E() => 1; int B() => 4; } ", fileName: @"C:\Enc1.cs"); var compilation0 = CreateCompilationWithMscorlib(source0.Tree, options: ComSafeDebugDll.WithMetadataImportOptions(MetadataImportOptions.All), assemblyName: "EncMethodExtents"); var compilation1 = compilation0.WithSource(source1.Tree); var compilation2 = compilation1.WithSource(source2.Tree); compilation0.VerifyDiagnostics(); compilation1.VerifyDiagnostics(); compilation2.VerifyDiagnostics(); var v0 = CompileAndVerify(compilation0, emitOptions: EmitOptions.Default.WithDebugInformationFormat(format)); var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData); var f0 = compilation0.GetMember <MethodSymbol>("C.F"); var f1 = compilation1.GetMember <MethodSymbol>("C.F"); var f2 = compilation2.GetMember <MethodSymbol>("C.F"); var g0 = compilation0.GetMember <MethodSymbol>("C.G"); var g1 = compilation1.GetMember <MethodSymbol>("C.G"); var g2 = compilation2.GetMember <MethodSymbol>("C.G"); var a1 = compilation1.GetMember <MethodSymbol>("C.A"); var a2 = compilation2.GetMember <MethodSymbol>("C.A"); var b2 = compilation2.GetMember <MethodSymbol>("C.B"); var generation0 = EmitBaseline.CreateInitialBaseline(md0, v0.CreateSymReader().GetEncMethodDebugInfo); var syntaxMap1 = GetSyntaxMapFromMarkers(source0, source1); var diff1 = compilation1.EmitDifference( generation0, ImmutableArray.Create( new SemanticEdit(SemanticEditKind.Update, f0, f1, syntaxMap1, preserveLocalVariables: true), new SemanticEdit(SemanticEditKind.Update, g0, g1, syntaxMap1, preserveLocalVariables: true))); diff1.VerifySynthesizedMembers( "C: {<>c}", "C.<>c: {<>9__3_0, <>9__3_2, <>9__3_3#1, <>9__3_1, <G>b__3_0, <G>b__3_1, <G>b__3_2, <G>b__3_3#1}"); var reader1 = diff1.GetMetadata().Reader; CheckEncLogDefinitions(reader1, Row(3, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(4, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddField), Row(5, TableIndex.Field, EditAndContinueOperation.Default), Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(8, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(10, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(3, TableIndex.TypeDef, EditAndContinueOperation.AddMethod), Row(11, TableIndex.MethodDef, EditAndContinueOperation.Default)); if (format == DebugInformationFormat.PortablePdb) { using (var pdbProvider = MetadataReaderProvider.FromPortablePdbImage(diff1.PdbDelta)) { CheckEncMap(pdbProvider.GetMetadataReader(), Handle(2, TableIndex.MethodDebugInformation), Handle(4, TableIndex.MethodDebugInformation), Handle(8, TableIndex.MethodDebugInformation), Handle(9, TableIndex.MethodDebugInformation), Handle(10, TableIndex.MethodDebugInformation), Handle(11, TableIndex.MethodDebugInformation)); } } diff1.VerifyPdb(Enumerable.Range(0x06000001, 20), @" <symbols> <files> <file id=""1"" name=""C:\Enc1.cs"" language=""3f5162f8-07c6-11d3-9053-00c04fa302a1"" languageVendor=""994b45c4-e6e9-11d2-903f-00c04fa302a1"" documentType=""5a869d0b-6611-11d3-bd2a-0000f80849bd"" checkSumAlgorithmId=""ff1816ec-aa5e-4d10-87f7-6f4963833460"" checkSum=""D1, 84, C6, 3, AA, 83, C0, CF, 49, E2, 52, 48, BB, 35, 99, 51, 88, 2B, 6C, D6, "" /> <file id=""2"" name=""C:\F\A.cs"" language=""3f5162f8-07c6-11d3-9053-00c04fa302a1"" languageVendor=""994b45c4-e6e9-11d2-903f-00c04fa302a1"" documentType=""5a869d0b-6611-11d3-bd2a-0000f80849bd"" /> <file id=""3"" name=""C:\F\C.cs"" language=""3f5162f8-07c6-11d3-9053-00c04fa302a1"" languageVendor=""994b45c4-e6e9-11d2-903f-00c04fa302a1"" documentType=""5a869d0b-6611-11d3-bd2a-0000f80849bd"" /> </files> <methods> <method token=""0x6000002""> <customDebugInfo> <using> <namespace usingCount=""1"" /> </using> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""9"" startColumn=""5"" endLine=""9"" endColumn=""6"" document=""1"" /> <entry offset=""0x1"" startLine=""10"" startColumn=""9"" endLine=""10"" endColumn=""29"" document=""2"" /> <entry offset=""0x7"" startLine=""10"" startColumn=""9"" endLine=""10"" endColumn=""29"" document=""3"" /> <entry offset=""0xd"" startLine=""15"" startColumn=""5"" endLine=""15"" endColumn=""6"" document=""1"" /> </sequencePoints> <scope startOffset=""0x0"" endOffset=""0xe""> <namespace name=""System"" /> </scope> </method> <method token=""0x6000004""> <customDebugInfo> <forward token=""0x6000002"" /> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""18"" startColumn=""5"" endLine=""18"" endColumn=""6"" document=""1"" /> <entry offset=""0x1"" startLine=""19"" startColumn=""9"" endLine=""19"" endColumn=""43"" document=""1"" /> <entry offset=""0x21"" startLine=""21"" startColumn=""9"" endLine=""25"" endColumn=""17"" document=""1"" /> <entry offset=""0x41"" startLine=""26"" startColumn=""5"" endLine=""26"" endColumn=""6"" document=""1"" /> </sequencePoints> <scope startOffset=""0x0"" endOffset=""0x42""> <local name=""H1"" il_index=""2"" il_start=""0x0"" il_end=""0x42"" attributes=""0"" /> <local name=""H2"" il_index=""3"" il_start=""0x0"" il_end=""0x42"" attributes=""0"" /> </scope> </method> <method token=""0x6000008""> <customDebugInfo> <forward token=""0x6000002"" /> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""19"" startColumn=""35"" endLine=""19"" endColumn=""36"" document=""1"" /> </sequencePoints> </method> <method token=""0x6000009""> <customDebugInfo> <forward token=""0x6000002"" /> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""22"" startColumn=""9"" endLine=""22"" endColumn=""10"" document=""1"" /> <entry offset=""0x1"" startLine=""23"" startColumn=""13"" endLine=""23"" endColumn=""47"" document=""1"" /> <entry offset=""0x21"" startLine=""24"" startColumn=""13"" endLine=""24"" endColumn=""47"" document=""1"" /> <entry offset=""0x41"" startLine=""25"" startColumn=""9"" endLine=""25"" endColumn=""10"" document=""1"" /> </sequencePoints> <scope startOffset=""0x0"" endOffset=""0x42""> <local name=""H3"" il_index=""1"" il_start=""0x0"" il_end=""0x42"" attributes=""0"" /> <local name=""H4"" il_index=""2"" il_start=""0x0"" il_end=""0x42"" attributes=""0"" /> </scope> </method> <method token=""0x600000a""> <customDebugInfo> <forward token=""0x6000002"" /> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""23"" startColumn=""39"" endLine=""23"" endColumn=""40"" document=""1"" /> </sequencePoints> </method> <method token=""0x600000b""> <customDebugInfo> <forward token=""0x6000002"" /> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""24"" startColumn=""39"" endLine=""24"" endColumn=""40"" document=""1"" /> </sequencePoints> </method> </methods> </symbols> "); var syntaxMap2 = GetSyntaxMapFromMarkers(source1, source2); var diff2 = compilation2.EmitDifference( diff1.NextGeneration, ImmutableArray.Create( new SemanticEdit(SemanticEditKind.Update, f1, f2, syntaxMap2, preserveLocalVariables: true), new SemanticEdit(SemanticEditKind.Update, g1, g2, syntaxMap2, preserveLocalVariables: true), new SemanticEdit(SemanticEditKind.Update, a1, a2, syntaxMap2, preserveLocalVariables: true), new SemanticEdit(SemanticEditKind.Insert, null, b2))); diff2.VerifySynthesizedMembers( "C: {<>c}", "C.<>c: {<>9__3_3#1, <>9__3_1, <G>b__3_1, <G>b__3_3#1, <>9__3_0, <>9__3_2, <G>b__3_0, <G>b__3_2}"); var reader2 = diff2.GetMetadata().Reader; CheckEncLogDefinitions(reader2, Row(5, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(6, TableIndex.StandAloneSig, EditAndContinueOperation.Default), Row(1, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(2, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(4, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(9, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(11, TableIndex.MethodDef, EditAndContinueOperation.Default), Row(2, TableIndex.TypeDef, EditAndContinueOperation.AddMethod), Row(12, TableIndex.MethodDef, EditAndContinueOperation.Default)); if (format == DebugInformationFormat.PortablePdb) { using (var pdbProvider = MetadataReaderProvider.FromPortablePdbImage(diff2.PdbDelta)) { CheckEncMap(pdbProvider.GetMetadataReader(), Handle(1, TableIndex.MethodDebugInformation), Handle(2, TableIndex.MethodDebugInformation), Handle(4, TableIndex.MethodDebugInformation), Handle(9, TableIndex.MethodDebugInformation), Handle(11, TableIndex.MethodDebugInformation), Handle(12, TableIndex.MethodDebugInformation)); } } diff2.VerifyPdb(Enumerable.Range(0x06000001, 20), @" <symbols> <files> <file id=""1"" name=""C:\Enc1.cs"" language=""3f5162f8-07c6-11d3-9053-00c04fa302a1"" languageVendor=""994b45c4-e6e9-11d2-903f-00c04fa302a1"" documentType=""5a869d0b-6611-11d3-bd2a-0000f80849bd"" checkSumAlgorithmId=""ff1816ec-aa5e-4d10-87f7-6f4963833460"" checkSum=""4D, 14, 76, DE, 68, ED, ED, C1, 88, DF, C, 85, 1C, 6B, 15, F7, BE, C0, 34, 34, "" /> <file id=""2"" name=""C:\F\B.cs"" language=""3f5162f8-07c6-11d3-9053-00c04fa302a1"" languageVendor=""994b45c4-e6e9-11d2-903f-00c04fa302a1"" documentType=""5a869d0b-6611-11d3-bd2a-0000f80849bd"" /> <file id=""3"" name=""C:\F\E.cs"" language=""3f5162f8-07c6-11d3-9053-00c04fa302a1"" languageVendor=""994b45c4-e6e9-11d2-903f-00c04fa302a1"" documentType=""5a869d0b-6611-11d3-bd2a-0000f80849bd"" /> </files> <methods> <method token=""0x6000001""> <customDebugInfo> <using> <namespace usingCount=""1"" /> </using> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""6"" startColumn=""16"" endLine=""6"" endColumn=""17"" document=""1"" /> </sequencePoints> <scope startOffset=""0x0"" endOffset=""0x2""> <namespace name=""System"" /> </scope> </method> <method token=""0x6000002""> <customDebugInfo> <forward token=""0x6000001"" /> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""9"" startColumn=""5"" endLine=""9"" endColumn=""6"" document=""1"" /> <entry offset=""0x1"" startLine=""10"" startColumn=""9"" endLine=""10"" endColumn=""29"" document=""2"" /> <entry offset=""0x7"" startLine=""10"" startColumn=""9"" endLine=""10"" endColumn=""29"" document=""3"" /> <entry offset=""0xd"" startLine=""15"" startColumn=""5"" endLine=""15"" endColumn=""6"" document=""1"" /> </sequencePoints> </method> <method token=""0x6000004""> <customDebugInfo> <forward token=""0x6000001"" /> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""18"" startColumn=""5"" endLine=""18"" endColumn=""6"" document=""1"" /> <entry offset=""0x1"" startLine=""21"" startColumn=""9"" endLine=""25"" endColumn=""17"" document=""1"" /> <entry offset=""0x22"" startLine=""26"" startColumn=""5"" endLine=""26"" endColumn=""6"" document=""1"" /> </sequencePoints> <scope startOffset=""0x0"" endOffset=""0x23""> <local name=""H2"" il_index=""4"" il_start=""0x0"" il_end=""0x23"" attributes=""0"" /> </scope> </method> <method token=""0x6000009""> <customDebugInfo> <forward token=""0x6000001"" /> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""22"" startColumn=""9"" endLine=""22"" endColumn=""10"" document=""1"" /> <entry offset=""0x1"" startLine=""24"" startColumn=""13"" endLine=""24"" endColumn=""47"" document=""1"" /> <entry offset=""0x21"" startLine=""25"" startColumn=""9"" endLine=""25"" endColumn=""10"" document=""1"" /> </sequencePoints> <scope startOffset=""0x0"" endOffset=""0x22""> <local name=""H4"" il_index=""1"" il_start=""0x0"" il_end=""0x22"" attributes=""0"" /> </scope> </method> <method token=""0x600000b""> <customDebugInfo> <forward token=""0x6000001"" /> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""24"" startColumn=""39"" endLine=""24"" endColumn=""40"" document=""1"" /> </sequencePoints> </method> <method token=""0x600000c""> <customDebugInfo> <forward token=""0x6000001"" /> </customDebugInfo> <sequencePoints> <entry offset=""0x0"" startLine=""30"" startColumn=""16"" endLine=""30"" endColumn=""17"" document=""1"" /> </sequencePoints> </method> </methods> </symbols> "); }
public void ChangingCompilationDependencies() { string srcLib = @" public class D { } "; string src0 = @" class C { public static int F(D a) { return 1; } } "; string src1 = @" class C { public static int F(D a) { return 2; } } "; string src2 = @" class C { public static int F(D a) { return 3; } } "; var lib0 = CreateCompilationWithMscorlib(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); lib0.VerifyDiagnostics(); var lib1 = CreateCompilationWithMscorlib(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); lib1.VerifyDiagnostics(); var lib2 = CreateCompilationWithMscorlib(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); lib2.VerifyDiagnostics(); var compilation0 = CreateCompilation(src0, new[] { MscorlibRef, lib0.ToMetadataReference() }, assemblyName: "C", options: TestOptions.DebugDll); var compilation1 = compilation0.WithSource(src1).WithReferences(new[] { MscorlibRef, lib1.ToMetadataReference() }); var compilation2 = compilation1.WithSource(src2).WithReferences(new[] { MscorlibRef, lib2.ToMetadataReference() }); var v0 = CompileAndVerify(compilation0); var v1 = CompileAndVerify(compilation1); var v2 = CompileAndVerify(compilation2); var f0 = compilation0.GetMember <MethodSymbol>("C.F"); var f1 = compilation1.GetMember <MethodSymbol>("C.F"); var f2 = compilation2.GetMember <MethodSymbol>("C.F"); var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData); var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider); var diff1 = compilation1.EmitDifference( generation0, ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, f0, f1))); diff1.EmitResult.Diagnostics.Verify(); var diff2 = compilation2.EmitDifference( diff1.NextGeneration, ImmutableArray.Create( new SemanticEdit(SemanticEditKind.Update, f1, f2))); diff2.EmitResult.Diagnostics.Verify(); }
internal static MetadataReference GetILModuleReference(string ilSource, bool prependDefaultHeader = true) { EmitILToArray(ilSource, prependDefaultHeader, includePdb: false, assemblyBytes: out var assemblyBytes, pdbBytes: out var pdbBytes); return(ModuleMetadata.CreateFromImage(assemblyBytes).GetReference()); }
public void DependencyVersionWildcards_Metadata() { string srcLib = @" [assembly: System.Reflection.AssemblyVersion(""1.0.*"")] public class D { } "; string src0 = @" class C { public static int F(D a) { return 1; } } "; string src1 = @" class C { public static int F(D a) { return 2; } } "; string src2 = @" class C { public static int F(D a) { return 3; } public static int G(D a) { return 4; } } "; var lib0 = CreateCompilationWithMscorlib(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); ((SourceAssemblySymbol)lib0.Assembly).lazyAssemblyIdentity = new AssemblyIdentity("Lib", new Version(1, 0, 2000, 1001)); lib0.VerifyDiagnostics(); var lib1 = CreateCompilationWithMscorlib(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); ((SourceAssemblySymbol)lib1.Assembly).lazyAssemblyIdentity = new AssemblyIdentity("Lib", new Version(1, 0, 2000, 1002)); lib1.VerifyDiagnostics(); var lib2 = CreateCompilationWithMscorlib(srcLib, assemblyName: "Lib", options: TestOptions.DebugDll); ((SourceAssemblySymbol)lib2.Assembly).lazyAssemblyIdentity = new AssemblyIdentity("Lib", new Version(1, 0, 2000, 1003)); lib2.VerifyDiagnostics(); var compilation0 = CreateCompilation(src0, new[] { MscorlibRef, lib0.EmitToImageReference() }, assemblyName: "C", options: TestOptions.DebugDll); var compilation1 = compilation0.WithSource(src1).WithReferences(new[] { MscorlibRef, lib1.EmitToImageReference() }); var compilation2 = compilation1.WithSource(src2).WithReferences(new[] { MscorlibRef, lib2.EmitToImageReference() }); var v0 = CompileAndVerify(compilation0); var v1 = CompileAndVerify(compilation1); var v2 = CompileAndVerify(compilation2); var f0 = compilation0.GetMember <MethodSymbol>("C.F"); var f1 = compilation1.GetMember <MethodSymbol>("C.F"); var f2 = compilation2.GetMember <MethodSymbol>("C.F"); var g2 = compilation2.GetMember <MethodSymbol>("C.G"); var md0 = ModuleMetadata.CreateFromImage(v0.EmittedAssemblyData); var generation0 = EmitBaseline.CreateInitialBaseline(md0, EmptyLocalsProvider); var diff1 = compilation1.EmitDifference( generation0, ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, f0, f1))); diff1.EmitResult.Diagnostics.Verify( // error CS7038: Failed to emit module 'C'. Diagnostic(ErrorCode.ERR_ModuleEmitFailure).WithArguments("C")); }
public void AddResourceToModule() { bool metadataOnly = false; Func <Compilation, Stream, ResourceDescription[], CodeAnalysis.Emit.EmitResult> emit; emit = (c, s, r) => c.Emit(s, manifestResources: r, options: new EmitOptions(metadataOnly: metadataOnly)); var sourceTree = SyntaxFactory.ParseSyntaxTree(""); // Do not name the compilation, a unique guid is used as a name by default. It prevents conflicts with other assemblies loaded via Assembly.ReflectionOnlyLoad. var c1 = CSharpCompilation.Create( Guid.NewGuid().ToString(), new[] { sourceTree }, new[] { MscorlibRef }, TestOptions.ReleaseModule); var resourceFileName = "RoslynResourceFile.goo"; var output = new MemoryStream(); const string r1Name = "some.dotted.NAME"; const string r2Name = "another.DoTtEd.NAME"; var arrayOfEmbeddedData = new byte[] { 1, 2, 3, 4, 5 }; var resourceFileData = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; var result = emit(c1, output, new ResourceDescription[] { new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true), new ResourceDescription(r2Name, resourceFileName, () => new MemoryStream(resourceFileData), false) }); Assert.False(result.Success); Assert.NotEmpty(result.Diagnostics.Where(x => x.Code == (int)ErrorCode.ERR_CantRefResource)); result = emit(c1, output, new ResourceDescription[] { new ResourceDescription(r2Name, resourceFileName, () => new MemoryStream(resourceFileData), false), new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true) }); Assert.False(result.Success); Assert.NotEmpty(result.Diagnostics.Where(x => x.Code == (int)ErrorCode.ERR_CantRefResource)); result = emit(c1, output, new ResourceDescription[] { new ResourceDescription(r2Name, resourceFileName, () => new MemoryStream(resourceFileData), false) }); Assert.False(result.Success); Assert.NotEmpty(result.Diagnostics.Where(x => x.Code == (int)ErrorCode.ERR_CantRefResource)); var c_mod1 = CSharpCompilation.Create( Guid.NewGuid().ToString(), new[] { sourceTree }, new[] { MscorlibRef }, TestOptions.ReleaseModule); var output_mod1 = new MemoryStream(); result = emit(c_mod1, output_mod1, new ResourceDescription[] { new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true) }); Assert.True(result.Success); var mod1 = ModuleMetadata.CreateFromImage(output_mod1.ToImmutable()); var ref_mod1 = mod1.GetReference(); Assert.Equal(ManifestResourceAttributes.Public, mod1.Module.GetEmbeddedResourcesOrThrow()[0].Attributes); { var c2 = CreateCompilation(sourceTree, new[] { ref_mod1 }, TestOptions.ReleaseDll); var output2 = new MemoryStream(); var result2 = c2.Emit(output2); Assert.True(result2.Success); var assembly = System.Reflection.Assembly.ReflectionOnlyLoad(output2.ToArray()); assembly.ModuleResolve += (object sender, ResolveEventArgs e) => { if (e.Name.Equals(c_mod1.SourceModule.Name)) { return(assembly.LoadModule(e.Name, output_mod1.ToArray())); } return(null); }; string[] resourceNames = assembly.GetManifestResourceNames(); Assert.Equal(1, resourceNames.Length); var rInfo = assembly.GetManifestResourceInfo(r1Name); Assert.Equal(System.Reflection.ResourceLocation.Embedded, rInfo.ResourceLocation); Assert.Equal(c_mod1.SourceModule.Name, rInfo.FileName); var rData = assembly.GetManifestResourceStream(r1Name); var rBytes = new byte[rData.Length]; rData.Read(rBytes, 0, (int)rData.Length); Assert.Equal(arrayOfEmbeddedData, rBytes); } var c_mod2 = CSharpCompilation.Create( Guid.NewGuid().ToString(), new[] { sourceTree }, new[] { MscorlibRef }, TestOptions.ReleaseModule); var output_mod2 = new MemoryStream(); result = emit(c_mod2, output_mod2, new ResourceDescription[] { new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), true), new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), true) }); Assert.True(result.Success); var ref_mod2 = ModuleMetadata.CreateFromImage(output_mod2.ToImmutable()).GetReference(); { var c3 = CreateCompilation(sourceTree, new[] { ref_mod2 }, TestOptions.ReleaseDll); var output3 = new MemoryStream(); var result3 = c3.Emit(output3); Assert.True(result3.Success); var assembly = Assembly.ReflectionOnlyLoad(output3.ToArray()); assembly.ModuleResolve += (object sender, ResolveEventArgs e) => { if (e.Name.Equals(c_mod2.SourceModule.Name)) { return(assembly.LoadModule(e.Name, output_mod2.ToArray())); } return(null); }; string[] resourceNames = assembly.GetManifestResourceNames(); Assert.Equal(2, resourceNames.Length); var rInfo = assembly.GetManifestResourceInfo(r1Name); Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); Assert.Equal(c_mod2.SourceModule.Name, rInfo.FileName); var rData = assembly.GetManifestResourceStream(r1Name); var rBytes = new byte[rData.Length]; rData.Read(rBytes, 0, (int)rData.Length); Assert.Equal(arrayOfEmbeddedData, rBytes); rInfo = assembly.GetManifestResourceInfo(r2Name); Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); Assert.Equal(c_mod2.SourceModule.Name, rInfo.FileName); rData = assembly.GetManifestResourceStream(r2Name); rBytes = new byte[rData.Length]; rData.Read(rBytes, 0, (int)rData.Length); Assert.Equal(resourceFileData, rBytes); } var c_mod3 = CSharpCompilation.Create( Guid.NewGuid().ToString(), new[] { sourceTree }, new[] { MscorlibRef }, TestOptions.ReleaseModule); var output_mod3 = new MemoryStream(); result = emit(c_mod3, output_mod3, new ResourceDescription[] { new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), false) }); Assert.True(result.Success); var mod3 = ModuleMetadata.CreateFromImage(output_mod3.ToImmutable()); var ref_mod3 = mod3.GetReference(); Assert.Equal(ManifestResourceAttributes.Private, mod3.Module.GetEmbeddedResourcesOrThrow()[0].Attributes); { var c4 = CreateCompilation(sourceTree, new[] { ref_mod3 }, TestOptions.ReleaseDll); var output4 = new MemoryStream(); var result4 = c4.Emit(output4, manifestResources: new ResourceDescription[] { new ResourceDescription(r1Name, () => new MemoryStream(arrayOfEmbeddedData), false) }); Assert.True(result4.Success); var assembly = System.Reflection.Assembly.ReflectionOnlyLoad(output4.ToArray()); assembly.ModuleResolve += (object sender, ResolveEventArgs e) => { if (e.Name.Equals(c_mod3.SourceModule.Name)) { return(assembly.LoadModule(e.Name, output_mod3.ToArray())); } return(null); }; string[] resourceNames = assembly.GetManifestResourceNames(); Assert.Equal(2, resourceNames.Length); var rInfo = assembly.GetManifestResourceInfo(r1Name); Assert.Equal(ResourceLocation.Embedded | ResourceLocation.ContainedInManifestFile, rInfo.ResourceLocation); var rData = assembly.GetManifestResourceStream(r1Name); var rBytes = new byte[rData.Length]; rData.Read(rBytes, 0, (int)rData.Length); Assert.Equal(arrayOfEmbeddedData, rBytes); rInfo = assembly.GetManifestResourceInfo(r2Name); Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); Assert.Equal(c_mod3.SourceModule.Name, rInfo.FileName); rData = assembly.GetManifestResourceStream(r2Name); rBytes = new byte[rData.Length]; rData.Read(rBytes, 0, (int)rData.Length); Assert.Equal(resourceFileData, rBytes); } { var c5 = CreateCompilation(sourceTree, new[] { ref_mod1, ref_mod3 }, TestOptions.ReleaseDll); var output5 = new MemoryStream(); var result5 = emit(c5, output5, null); Assert.True(result5.Success); var assembly = Assembly.ReflectionOnlyLoad(output5.ToArray()); assembly.ModuleResolve += (object sender, ResolveEventArgs e) => { if (e.Name.Equals(c_mod1.SourceModule.Name)) { return(assembly.LoadModule(e.Name, output_mod1.ToArray())); } else if (e.Name.Equals(c_mod3.SourceModule.Name)) { return(assembly.LoadModule(e.Name, output_mod3.ToArray())); } return(null); }; string[] resourceNames = assembly.GetManifestResourceNames(); Assert.Equal(2, resourceNames.Length); var rInfo = assembly.GetManifestResourceInfo(r1Name); Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); Assert.Equal(c_mod1.SourceModule.Name, rInfo.FileName); var rData = assembly.GetManifestResourceStream(r1Name); var rBytes = new byte[rData.Length]; rData.Read(rBytes, 0, (int)rData.Length); Assert.Equal(arrayOfEmbeddedData, rBytes); rInfo = assembly.GetManifestResourceInfo(r2Name); Assert.Equal(ResourceLocation.Embedded, rInfo.ResourceLocation); Assert.Equal(c_mod3.SourceModule.Name, rInfo.FileName); rData = assembly.GetManifestResourceStream(r2Name); rBytes = new byte[rData.Length]; rData.Read(rBytes, 0, (int)rData.Length); Assert.Equal(resourceFileData, rBytes); } { var c6 = CreateCompilation(sourceTree, new[] { ref_mod1, ref_mod2 }, TestOptions.ReleaseDll); var output6 = new MemoryStream(); var result6 = emit(c6, output6, null); if (metadataOnly) { Assert.True(result6.Success); } else { Assert.False(result6.Success); result6.Diagnostics.Verify( // error CS1508: Resource identifier 'some.dotted.NAME' has already been used in this assembly Diagnostic(ErrorCode.ERR_ResourceNotUnique).WithArguments("some.dotted.NAME") ); } result6 = emit(c6, output6, new ResourceDescription[] { new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), false) }); if (metadataOnly) { Assert.True(result6.Success); } else { Assert.False(result6.Success); result6.Diagnostics.Verify( // error CS1508: Resource identifier 'some.dotted.NAME' has already been used in this assembly Diagnostic(ErrorCode.ERR_ResourceNotUnique).WithArguments("some.dotted.NAME"), // error CS1508: Resource identifier 'another.DoTtEd.NAME' has already been used in this assembly Diagnostic(ErrorCode.ERR_ResourceNotUnique).WithArguments("another.DoTtEd.NAME") ); } c6 = CreateCompilation(sourceTree, new[] { ref_mod1, ref_mod2 }, TestOptions.ReleaseModule); result6 = emit(c6, output6, new ResourceDescription[] { new ResourceDescription(r2Name, () => new MemoryStream(resourceFileData), false) }); Assert.True(result6.Success); } }
private EmitBaseline( EmitBaseline initialBaseline, ModuleMetadata module, Compilation compilation, CommonPEModuleBuilder moduleBuilder, Guid moduleVersionId, int ordinal, Guid encId, IReadOnlyDictionary <Cci.ITypeDefinition, uint> typesAdded, IReadOnlyDictionary <Cci.IEventDefinition, uint> eventsAdded, IReadOnlyDictionary <Cci.IFieldDefinition, uint> fieldsAdded, IReadOnlyDictionary <Cci.IMethodDefinition, uint> methodsAdded, IReadOnlyDictionary <Cci.IPropertyDefinition, uint> propertiesAdded, IReadOnlyDictionary <uint, uint> eventMapAdded, IReadOnlyDictionary <uint, uint> propertyMapAdded, IReadOnlyDictionary <MethodImplKey, uint> methodImplsAdded, ImmutableArray <int> tableEntriesAdded, int blobStreamLengthAdded, int stringStreamLengthAdded, int userStringStreamLengthAdded, int guidStreamLengthAdded, IReadOnlyDictionary <AnonymousTypeKey, AnonymousTypeValue> anonymousTypeMap, ImmutableDictionary <Cci.ITypeDefinition, ImmutableArray <Cci.ITypeDefinitionMember> > synthesizedMembers, IReadOnlyDictionary <uint, AddedOrChangedMethodInfo> methodsAddedOrChanged, Func <MethodDefinitionHandle, EditAndContinueMethodDebugInformation> debugInformationProvider, IReadOnlyDictionary <uint, uint> typeToEventMap, IReadOnlyDictionary <uint, uint> typeToPropertyMap, IReadOnlyDictionary <MethodImplKey, uint> methodImpls) { Debug.Assert(module != null); Debug.Assert((ordinal == 0) == (encId == default(Guid))); Debug.Assert((ordinal == 0) == (initialBaseline == null)); Debug.Assert(encId != module.GetModuleVersionId()); Debug.Assert(debugInformationProvider != null); Debug.Assert(typeToEventMap != null); Debug.Assert(typeToPropertyMap != null); Debug.Assert(moduleVersionId != default(Guid)); Debug.Assert(moduleVersionId == module.GetModuleVersionId()); Debug.Assert(synthesizedMembers != null); Debug.Assert(tableEntriesAdded.Length == MetadataTokens.TableCount); // The size of each table is the total number of entries added in all previous // generations after the initial generation. Depending on the table, some of the // entries may not be available in the current generation (say, a synthesized type // from a method that was not recompiled for instance) Debug.Assert(tableEntriesAdded[(int)TableIndex.TypeDef] >= typesAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.Event] >= eventsAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.Field] >= fieldsAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.MethodDef] >= methodsAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.Property] >= propertiesAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.EventMap] >= eventMapAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.PropertyMap] >= propertyMapAdded.Count); var reader = module.Module.MetadataReader; this.InitialBaseline = initialBaseline ?? this; this.OriginalMetadata = module; this.Compilation = compilation; this.PEModuleBuilder = moduleBuilder; this.ModuleVersionId = moduleVersionId; this.Ordinal = ordinal; this.EncId = encId; this.TypesAdded = typesAdded; this.EventsAdded = eventsAdded; this.FieldsAdded = fieldsAdded; this.MethodsAdded = methodsAdded; this.PropertiesAdded = propertiesAdded; this.EventMapAdded = eventMapAdded; this.PropertyMapAdded = propertyMapAdded; this.MethodImplsAdded = methodImplsAdded; this.TableEntriesAdded = tableEntriesAdded; this.BlobStreamLengthAdded = blobStreamLengthAdded; this.StringStreamLengthAdded = stringStreamLengthAdded; this.UserStringStreamLengthAdded = userStringStreamLengthAdded; this.GuidStreamLengthAdded = guidStreamLengthAdded; this._anonymousTypeMap = anonymousTypeMap; this.SynthesizedMembers = synthesizedMembers; this.AddedOrChangedMethods = methodsAddedOrChanged; this.DebugInformationProvider = debugInformationProvider; this.TableSizes = CalculateTableSizes(reader, this.TableEntriesAdded); this.TypeToEventMap = typeToEventMap; this.TypeToPropertyMap = typeToPropertyMap; this.MethodImpls = methodImpls; }
private MetadataReader GetMetadataReader(ModuleMetadata metadata) { // TODO: right now, use reflection, but this API will be added as public API soon. when that happen, remove reflection var metadataReaderPropertyInfo = metadata.GetType().GetTypeInfo().GetDeclaredProperty("MetadataReader"); var metadataReader = (MetadataReader)metadataReaderPropertyInfo.GetValue(metadata); return metadataReader; }
public void CreateFromImageStream() { Assert.Throws <ArgumentNullException>(() => ModuleMetadata.CreateFromStream(peStream: null)); Assert.Throws <ArgumentException>(() => ModuleMetadata.CreateFromStream(new TestStream(canRead: false, canSeek: true))); Assert.Throws <ArgumentException>(() => ModuleMetadata.CreateFromStream(new TestStream(canRead: true, canSeek: false))); }
private void CompileTimeAndRuntimeAssemblies( ImmutableArray <MetadataReference> compileReferences, ImmutableArray <MetadataReference> runtimeReferences, string storageAssemblyName) { var source = @"class C { static void M(LibraryA.A a, LibraryB.B b, Windows.Data.Text.TextSegment t, Windows.Storage.StorageFolder f) { } }"; var compilation0 = CreateEmptyCompilation(source, compileReferences, TestOptions.DebugDll); WithRuntimeInstance(compilation0, runtimeReferences, runtime => { var context = CreateMethodContext(runtime, "C.M"); string error; var testData = new CompilationTestData(); context.CompileExpression("(object)a ?? (object)b ?? (object)t ?? f", out error, testData); Assert.Null(error); testData.GetMethodData("<>x.<>m0").VerifyIL( @"{ // Code size 17 (0x11) .maxstack 2 IL_0000: ldarg.0 IL_0001: dup IL_0002: brtrue.s IL_0010 IL_0004: pop IL_0005: ldarg.1 IL_0006: dup IL_0007: brtrue.s IL_0010 IL_0009: pop IL_000a: ldarg.2 IL_000b: dup IL_000c: brtrue.s IL_0010 IL_000e: pop IL_000f: ldarg.3 IL_0010: ret }"); testData = new CompilationTestData(); var result = context.CompileExpression("default(Windows.Storage.StorageFolder)", out error, testData); Assert.Null(error); var methodData = testData.GetMethodData("<>x.<>m0"); methodData.VerifyIL( @"{ // Code size 2 (0x2) .maxstack 1 IL_0000: ldnull IL_0001: ret }"); // Check return type is from runtime assembly. var assemblyReference = AssemblyMetadata.CreateFromImage(result.Assembly).GetReference(); var compilation = CSharpCompilation.Create( assemblyName: ExpressionCompilerUtilities.GenerateUniqueName(), references: runtimeReferences.Concat(ImmutableArray.Create <MetadataReference>(assemblyReference))); var assembly = ImmutableArray.CreateRange(result.Assembly); using (var metadata = ModuleMetadata.CreateFromImage(ImmutableArray.CreateRange(assembly))) { var reader = metadata.MetadataReader; var typeDef = reader.GetTypeDef("<>x"); var methodHandle = reader.GetMethodDefHandle(typeDef, "<>m0"); var module = (PEModuleSymbol)compilation.GetMember("<>x").ContainingModule; var metadataDecoder = new MetadataDecoder(module); SignatureHeader signatureHeader; BadImageFormatException metadataException; var parameters = metadataDecoder.GetSignatureForMethod(methodHandle, out signatureHeader, out metadataException); Assert.Equal(5, parameters.Length); var actualReturnType = parameters[0].Type; Assert.Equal(TypeKind.Class, actualReturnType.TypeKind); // not error var expectedReturnType = compilation.GetMember("Windows.Storage.StorageFolder"); Assert.Equal(expectedReturnType, actualReturnType); Assert.Equal(storageAssemblyName, actualReturnType.ContainingAssembly.Name); } }); }
public unsafe void CreateFromMetadata_Errors() { Assert.Throws <ArgumentNullException>(() => ModuleMetadata.CreateFromMetadata(IntPtr.Zero, 0)); Assert.Throws <ArgumentOutOfRangeException>(() => { fixed(byte *ptr = new byte[] { 1, 2, 3 }) ModuleMetadata.CreateFromMetadata((IntPtr)ptr, 0); }); Assert.Throws <ArgumentOutOfRangeException>(() => { fixed(byte *ptr = new byte[] { 1, 2, 3 }) ModuleMetadata.CreateFromMetadata((IntPtr)ptr, -1); }); fixed(byte *ptr = new byte[] { 1, 2, 3 }) { var metadata = ModuleMetadata.CreateFromMetadata((IntPtr)ptr, 3); Assert.Throws <BadImageFormatException>(() => metadata.GetModuleNames()); } }
private static PortableExecutableReference MakeAssemblyMetadata(ModuleMetadata metadata, Dictionary<string, ModuleMetadata> modulesByName) { Debug.Assert(metadata.Module.IsManifestModule); var builder = ArrayBuilder<ModuleMetadata>.GetInstance(); builder.Add(metadata); // Include any associated netmodules from the manifest. if (modulesByName != null) { try { var reader = metadata.MetadataReader; foreach (var handle in reader.AssemblyFiles) { var assemblyFile = reader.GetAssemblyFile(handle); if (assemblyFile.ContainsMetadata) { var name = reader.GetString(assemblyFile.Name); // Find the assembly file in the set of netmodules with that name. // The file may be missing if the file is not a module (say a resource) // or if the module has not been loaded yet. The value will be null // if the name was ambiguous. ModuleMetadata module; if (!modulesByName.TryGetValue(name, out module)) { // AssemblyFile names may contain file information (".dll", etc). modulesByName.TryGetValue(GetFileNameWithoutExtension(name), out module); } if (module != null) { builder.Add(module); } } } } catch (Exception e) when (IsBadMetadataException(e)) { // Ignore modules with "bad" metadata. } } var assemblyMetadata = AssemblyMetadata.Create(builder.ToImmutableAndFree()); return assemblyMetadata.GetReference(embedInteropTypes: false, display: metadata.Name); }
private EmitBaseline( ModuleMetadata module, Compilation compilation, CommonPEModuleBuilder moduleBuilder, Guid moduleVersionId, int ordinal, Guid encId, IReadOnlyDictionary<ITypeDefinition, uint> typesAdded, IReadOnlyDictionary<IEventDefinition, uint> eventsAdded, IReadOnlyDictionary<IFieldDefinition, uint> fieldsAdded, IReadOnlyDictionary<IMethodDefinition, uint> methodsAdded, IReadOnlyDictionary<IPropertyDefinition, uint> propertiesAdded, IReadOnlyDictionary<uint, uint> eventMapAdded, IReadOnlyDictionary<uint, uint> propertyMapAdded, ImmutableArray<int> tableEntriesAdded, int blobStreamLengthAdded, int stringStreamLengthAdded, int userStringStreamLengthAdded, int guidStreamLengthAdded, IReadOnlyDictionary<AnonymousTypeKey, AnonymousTypeValue> anonymousTypeMap, IReadOnlyDictionary<uint, ImmutableArray<EncLocalInfo>> localsForMethodsAddedOrChanged, LocalVariableNameProvider localNames, IReadOnlyDictionary<uint, uint> typeToEventMap, IReadOnlyDictionary<uint, uint> typeToPropertyMap) { Debug.Assert(module != null); Debug.Assert((ordinal == 0) == (encId == default(Guid))); Debug.Assert(encId != module.GetModuleVersionId()); Debug.Assert(localNames != null); Debug.Assert(typeToEventMap != null); Debug.Assert(typeToPropertyMap != null); Debug.Assert(tableEntriesAdded.Length == MetadataTokens.TableCount); // The size of each table is the total number of entries added in all previous // generations after the initial generation. Depending on the table, some of the // entries may not be available in the current generation (say, a synthesized type // from a method that was not recompiled for instance) Debug.Assert(tableEntriesAdded[(int)TableIndex.TypeDef] >= typesAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.Event] >= eventsAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.Field] >= fieldsAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.MethodDef] >= methodsAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.Property] >= propertiesAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.EventMap] >= eventMapAdded.Count); Debug.Assert(tableEntriesAdded[(int)TableIndex.PropertyMap] >= propertyMapAdded.Count); var reader = module.Module.MetadataReader; this.OriginalMetadata = module; this.Compilation = compilation; this.PEModuleBuilder = moduleBuilder; this.ModuleVersionId = moduleVersionId; this.Ordinal = ordinal; this.EncId = encId; this.TypesAdded = typesAdded; this.EventsAdded = eventsAdded; this.FieldsAdded = fieldsAdded; this.MethodsAdded = methodsAdded; this.PropertiesAdded = propertiesAdded; this.EventMapAdded = eventMapAdded; this.PropertyMapAdded = propertyMapAdded; this.TableEntriesAdded = tableEntriesAdded; this.BlobStreamLengthAdded = blobStreamLengthAdded; this.StringStreamLengthAdded = stringStreamLengthAdded; this.UserStringStreamLengthAdded = userStringStreamLengthAdded; this.GuidStreamLengthAdded = guidStreamLengthAdded; this.AnonymousTypeMap = anonymousTypeMap; this.LocalsForMethodsAddedOrChanged = localsForMethodsAddedOrChanged; this.LocalNames = localNames; this.TableSizes = CalculateTableSizes(reader, this.TableEntriesAdded); this.TypeToEventMap = typeToEventMap; this.TypeToPropertyMap = typeToPropertyMap; }
private static ModuleMetadata CreateModuleMetadata(FileStream stream) { // The Stream is held by the ModuleMetadata to read metadata on demand. // We hand off the responsibility for closing the stream to the metadata object. return(ModuleMetadata.CreateFromStream(stream, leaveOpen: false)); }
/// <summary> /// Serialize the cmdlets so they can be compared to change modules later /// </summary> /// <param name="fileName">Name of the file cmdlets are being serialized to.</param> /// <param name="cmdlets">List of cmdlets that are to be serialized.</param> private void SerializeCmdlets(string fileName, ModuleMetadata moduleMetadata) { string json = JsonConvert.SerializeObject(moduleMetadata, Formatting.Indented); File.WriteAllText(fileName, json); }
private static bool IsPrimaryModule(ModuleMetadata metadata) { return metadata.Module.IsManifestModule; }
/// <summary> /// Validates that the given stream is marked as signed, the signature matches /// the public key, and the header checksum is correct. /// </summary> public static bool IsStreamFullSigned(Stream moduleContents) { var savedPosition = moduleContents.Position; try { moduleContents.Position = 0; var peHeaders = new PEHeaders(moduleContents); moduleContents.Position = 0; using (var metadata = ModuleMetadata.CreateFromStream(moduleContents, leaveOpen: true)) { var metadataReader = metadata.MetadataReader; var peReader = metadata.Module.PEReaderOpt; var flags = peHeaders.CorHeader.Flags; if (CorFlags.StrongNameSigned != (flags & CorFlags.StrongNameSigned)) { return(false); } var snDirectory = peReader.PEHeaders.CorHeader.StrongNameSignatureDirectory; if (!peHeaders.TryGetDirectoryOffset(snDirectory, out int snOffset)) { return(false); } moduleContents.Position = 0; int peSize; try { peSize = checked ((int)moduleContents.Length); } catch { return(false); } var peImage = new BlobBuilder(peSize); if (peSize != peImage.TryWriteBytes(moduleContents, peSize)) { return(false); } byte[] buffer = GetBlobBuffer(peImage.GetBlobs().Single()); uint expectedChecksum = peHeaders.PEHeader.CheckSum; Blob checksumBlob = MakeBlob(buffer, peHeaders.PEHeaderStartOffset + ChecksumOffset, sizeof(uint)); if (expectedChecksum != PeWriter.CalculateChecksum(peImage, checksumBlob)) { return(false); } int snSize = snDirectory.Size; byte[] hash = ComputeSigningHash(peImage, peHeaders, checksumBlob, snOffset, snSize); ImmutableArray <byte> publicKeyBlob = metadataReader.GetBlobContent(metadataReader.GetAssemblyDefinition().PublicKey); // RSA parameters start after the public key offset byte[] publicKeyParams = new byte[publicKeyBlob.Length - CryptoBlobParser.s_publicKeyHeaderSize]; publicKeyBlob.CopyTo(CryptoBlobParser.s_publicKeyHeaderSize, publicKeyParams, 0, publicKeyParams.Length); var snKey = publicKeyParams.ToRSAParameters(includePrivateParameters: false); using (var rsa = RSA.Create()) { rsa.ImportParameters(snKey); var reversedSignature = peReader.GetSectionData(snDirectory.RelativeVirtualAddress).GetContent(0, snSize).ToArray(); // Unknown why the signature is reversed, but this matches the behavior of the CLR // signing implementation. Array.Reverse(reversedSignature); if (!rsa.VerifyHash(hash, reversedSignature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1)) { return(false); } } return(true); } } finally { moduleContents.Position = savedPosition; } }
public void ForwardedTypesAreEmittedInADeterministicOrder() { var forwardedToCode = @" namespace Namespace2 { public class GenericType1<T> {} public class GenericType3<T> {} public class GenericType2<T> {} } namespace Namespace1 { public class Type3 {} public class Type2 {} public class Type1 {} } namespace Namespace4 { namespace Embedded { public class Type2 {} public class Type1 {} } } namespace Namespace3 { public class GenericType {} public class GenericType<T> {} public class GenericType<T, U> {} } "; var forwardedToCompilation = CreateEmptyCompilation(forwardedToCode); var forwardedToReference = new CSharpCompilationReference(forwardedToCompilation); var forwardingCode = @" using System.Runtime.CompilerServices; [assembly: TypeForwardedTo(typeof(Namespace2.GenericType1<int>))] [assembly: TypeForwardedTo(typeof(Namespace2.GenericType3<int>))] [assembly: TypeForwardedTo(typeof(Namespace2.GenericType2<int>))] [assembly: TypeForwardedTo(typeof(Namespace1.Type3))] [assembly: TypeForwardedTo(typeof(Namespace1.Type2))] [assembly: TypeForwardedTo(typeof(Namespace1.Type1))] [assembly: TypeForwardedTo(typeof(Namespace4.Embedded.Type2))] [assembly: TypeForwardedTo(typeof(Namespace4.Embedded.Type1))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType<int>))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType<int, int>))] "; var forwardingCompilation = CreateCompilation(forwardingCode, new MetadataReference[] { forwardedToReference }); var sortedFullNames = new string[] { "Namespace1.Type1", "Namespace1.Type2", "Namespace1.Type3", "Namespace2.GenericType1`1", "Namespace2.GenericType2`1", "Namespace2.GenericType3`1", "Namespace3.GenericType", "Namespace3.GenericType`1", "Namespace3.GenericType`2", "Namespace4.Embedded.Type1", "Namespace4.Embedded.Type2" }; using (var stream = forwardingCompilation.EmitToStream()) { using (var block = ModuleMetadata.CreateFromStream(stream)) { var metadataFullNames = MetadataValidation.GetExportedTypesFullNames(block.MetadataReader); Assert.Equal(sortedFullNames, metadataFullNames); } } }
public void ForwardedTypesAreEmittedInADeterministicOrder() { var forwardedToCode = @" namespace Namespace2 { public class GenericType1<T> {} public class GenericType3<T> {} public class GenericType2<T> {} } namespace Namespace1 { public class Type3 {} public class Type2 {} public class Type1 {} } namespace Namespace4 { namespace Embedded { public class Type2 {} public class Type1 {} } } namespace Namespace3 { public class GenericType {} public class GenericType<T> {} public class GenericType<T, U> {} } "; var forwardedToCompilation1 = CreateCompilation(forwardedToCode, assemblyName: "ForwardedTo"); var forwardedToReference1 = new CSharpCompilationReference(forwardedToCompilation1); var forwardingCode = @" using System.Runtime.CompilerServices; [assembly: TypeForwardedTo(typeof(Namespace2.GenericType1<int>))] [assembly: TypeForwardedTo(typeof(Namespace2.GenericType3<int>))] [assembly: TypeForwardedTo(typeof(Namespace2.GenericType2<int>))] [assembly: TypeForwardedTo(typeof(Namespace1.Type3))] [assembly: TypeForwardedTo(typeof(Namespace1.Type2))] [assembly: TypeForwardedTo(typeof(Namespace1.Type1))] [assembly: TypeForwardedTo(typeof(Namespace4.Embedded.Type2))] [assembly: TypeForwardedTo(typeof(Namespace4.Embedded.Type1))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType<int>))] [assembly: TypeForwardedTo(typeof(Namespace3.GenericType<int, int>))] "; var forwardingCompilation = CreateCompilation(forwardingCode, new MetadataReference[] { forwardedToReference1 }); var forwardingReference = new CSharpCompilationReference(forwardingCompilation); var sortedFullNames = new string[] { "Namespace1.Type1", "Namespace1.Type2", "Namespace1.Type3", "Namespace2.GenericType1`1", "Namespace2.GenericType2`1", "Namespace2.GenericType3`1", "Namespace3.GenericType", "Namespace3.GenericType`1", "Namespace3.GenericType`2", "Namespace4.Embedded.Type1", "Namespace4.Embedded.Type2" }; Action <ModuleSymbol> metadataValidator = module => { var assembly = module.ContainingAssembly; Assert.Equal(sortedFullNames, getNamesOfForwardedTypes(assembly)); }; CompileAndVerify(forwardingCompilation, symbolValidator: metadataValidator, sourceSymbolValidator: metadataValidator, verify: Verification.Skipped); using (var stream = forwardingCompilation.EmitToStream()) { using (var block = ModuleMetadata.CreateFromStream(stream)) { var metadataFullNames = MetadataValidation.GetExportedTypesFullNames(block.MetadataReader); Assert.Equal(sortedFullNames, metadataFullNames); } } var forwardedToCompilation2 = CreateCompilation(forwardedToCode, assemblyName: "ForwardedTo"); var forwardedToReference2 = new CSharpCompilationReference(forwardedToCompilation2); var withRetargeting = CreateCompilation("", new MetadataReference[] { forwardedToReference2, forwardingReference }); var retargeting = (RetargetingAssemblySymbol)withRetargeting.GetReferencedAssemblySymbol(forwardingReference); Assert.Equal(sortedFullNames, getNamesOfForwardedTypes(retargeting)); foreach (var type in getForwardedTypes(retargeting)) { Assert.Same(forwardedToCompilation2.Assembly.GetPublicSymbol(), type.ContainingAssembly); }
public void DuplicateValueTupleBetweenMscorlibAndLibrary() { var versionTemplate = @"[assembly: System.Reflection.AssemblyVersion(""{0}.0.0.0"")]"; var corlib_cs = @" namespace System { public class Object { } public struct Int32 { } public struct Boolean { } public class String { } public class ValueType { } public struct Void { } public class Attribute { } } namespace System.Reflection { public class AssemblyVersionAttribute : Attribute { public AssemblyVersionAttribute(String version) { } } }"; string valuetuple_cs = @" namespace System { public struct ValueTuple<T1, T2> { public T1 Item1; public T2 Item2; public ValueTuple(T1 item1, T2 item2) => (Item1, Item2) = (item1, item2); } }"; var corlibWithoutVT = CreateEmptyCompilation(new[] { Parse(String.Format(versionTemplate, "1") + corlib_cs) }, assemblyName: "corlib"); corlibWithoutVT.VerifyDiagnostics(); var corlibWithoutVTRef = corlibWithoutVT.EmitToImageReference(); var corlibWithVT = CreateEmptyCompilation(new[] { Parse(String.Format(versionTemplate, "2") + corlib_cs + valuetuple_cs) }, assemblyName: "corlib"); corlibWithVT.VerifyDiagnostics(); var source = @"class C { static (int, int) M() { (int, int) t = (1, 2); return t; } } "; var app = CreateEmptyCompilation(source + valuetuple_cs, references: new[] { corlibWithoutVTRef }, options: TestOptions.DebugDll); app.VerifyDiagnostics(); // Create EE context with app assembly (including ValueTuple) and a more recent corlib (also including ValueTuple) var runtime = CreateRuntimeInstance(new[] { app.ToModuleInstance(), corlibWithVT.ToModuleInstance() }); var evalContext = CreateMethodContext(runtime, "C.M"); string error; var testData = new CompilationTestData(); var compileResult = evalContext.CompileExpression("(1, 2)", out error, testData); Assert.Null(error); using (ModuleMetadata block = ModuleMetadata.CreateFromStream(new MemoryStream(compileResult.Assembly))) { var reader = block.MetadataReader; var appRef = app.Assembly.Identity.Name; AssertEx.SetEqual(new[] { "corlib 2.0", appRef + " 0.0" }, reader.DumpAssemblyReferences()); AssertEx.SetEqual(new[] { "Object, System, AssemblyReference:corlib", "ValueTuple`2, System, AssemblyReference:" + appRef // ValueTuple comes from app, not corlib }, reader.DumpTypeReferences()); } }