Esempio n. 1
0
        /// <summary>
        /// Create a context for evaluating expressions at a type scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="moduleVersionId">Module containing type</param>
        /// <param name="typeToken">Type metadata token</param>
        /// <returns>Evaluation context</returns>
        /// <remarks>
        /// No locals since locals are associated with methods, not types.
        /// </remarks>
        internal static EvaluationContext CreateTypeContext(
            CSharpMetadataContext previous,
            ImmutableArray <MetadataBlock> metadataBlocks,
            Guid moduleVersionId,
            int typeToken)
        {
            Debug.Assert(MetadataTokens.Handle(typeToken).Kind == HandleKind.TypeDefinition);

            // Re-use the previous compilation if possible.
            var compilation = metadataBlocks.HaveNotChanged(previous) ?
                              previous.Compilation :
                              metadataBlocks.ToCompilation();

            MetadataDecoder metadataDecoder;
            var             currentType = compilation.GetType(moduleVersionId, typeToken, out metadataDecoder);

            Debug.Assert((object)currentType != null);
            Debug.Assert(metadataDecoder != null);
            var currentFrame = new SynthesizedContextMethodSymbol(currentType);

            return(new EvaluationContext(
                       metadataBlocks,
                       null,
                       compilation,
                       metadataDecoder,
                       currentFrame,
                       default(ImmutableArray <LocalSymbol>),
                       ImmutableSortedSet <int> .Empty,
                       default(MethodDebugInfo)));
        }
Esempio n. 2
0
        /// <summary>
        /// Create a context for evaluating expressions at a type scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="moduleVersionId">Module containing type</param>
        /// <param name="typeToken">Type metadata token</param>
        /// <returns>Evaluation context</returns>
        /// <remarks>
        /// No locals since locals are associated with methods, not types.
        /// </remarks>
        internal static EvaluationContext CreateTypeContext(
            CSharpMetadataContext previous,
            ImmutableArray<MetadataBlock> metadataBlocks,
            Guid moduleVersionId,
            int typeToken)
        {
            Debug.Assert(MetadataTokens.Handle(typeToken).Kind == HandleKind.TypeDefinition);

            // Re-use the previous compilation if possible.
            var compilation = metadataBlocks.HaveNotChanged(previous) ?
                previous.Compilation :
                metadataBlocks.ToCompilation();

            MetadataDecoder metadataDecoder;
            var currentType = compilation.GetType(moduleVersionId, typeToken, out metadataDecoder);
            Debug.Assert((object)currentType != null);
            Debug.Assert(metadataDecoder != null);
            var currentFrame = new SynthesizedContextMethodSymbol(currentType);
            return new EvaluationContext(
                metadataBlocks,
                null,
                compilation,
                metadataDecoder,
                currentFrame,
                default(ImmutableArray<LocalSymbol>),
                ImmutableSortedSet<int>.Empty,
                default(ImmutableArray<ImmutableArray<string>>),
                default(ImmutableArray<string>));
        }
Esempio n. 3
0
        /// <summary>
        /// Create a context for evaluating expressions at a type scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="moduleVersionId">Module containing type</param>
        /// <param name="typeToken">Type metadata token</param>
        /// <returns>Evaluation context</returns>
        /// <remarks>
        /// No locals since locals are associated with methods, not types.
        /// </remarks>
        internal static EvaluationContext CreateTypeContext(
            CSharpMetadataContext previous,
            ImmutableArray<MetadataBlock> metadataBlocks,
            Guid moduleVersionId,
            int typeToken)
        {
            // Re-use the previous compilation if possible.
            var compilation = previous.Matches(metadataBlocks) ?
                previous.Compilation :
                metadataBlocks.ToCompilation();

            return CreateTypeContext(compilation, moduleVersionId, typeToken);
        }
        /// <summary>
        /// Create a context for evaluating expressions at a type scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="moduleVersionId">Module containing type</param>
        /// <param name="typeToken">Type metadata token</param>
        /// <returns>Evaluation context</returns>
        /// <remarks>
        /// No locals since locals are associated with methods, not types.
        /// </remarks>
        internal static EvaluationContext CreateTypeContext(
            CSharpMetadataContext previous,
            ImmutableArray <MetadataBlock> metadataBlocks,
            Guid moduleVersionId,
            int typeToken)
        {
            // Re-use the previous compilation if possible.
            var compilation = previous.Matches(metadataBlocks) ?
                              previous.Compilation :
                              metadataBlocks.ToCompilation();

            return(CreateTypeContext(compilation, moduleVersionId, typeToken));
        }
        internal static EvaluationContext CreateTypeContext <TAppDomain>(
            TAppDomain appDomain,
            GetMetadataContextDelegate <TAppDomain> getMetadataContext,
            ImmutableArray <MetadataBlock> metadataBlocks,
            Guid moduleVersionId,
            int typeToken,
            MakeAssemblyReferencesKind kind)
        {
            CSharpCompilation?compilation;

            if (kind == MakeAssemblyReferencesKind.DirectReferencesOnly)
            {
                // Avoid using the cache for referenced assemblies only
                // since this should be the exceptional case.
                compilation = metadataBlocks.ToCompilationReferencedModulesOnly(moduleVersionId);
                return(EvaluationContext.CreateTypeContext(
                           compilation,
                           moduleVersionId,
                           typeToken));
            }

            var contextId = MetadataContextId.GetContextId(moduleVersionId, kind);
            var previous  = getMetadataContext(appDomain);
            CSharpMetadataContext previousMetadataContext = default;

            if (previous.Matches(metadataBlocks))
            {
                previous.AssemblyContexts.TryGetValue(contextId, out previousMetadataContext);
            }

            // Re-use the previous compilation if possible.
            compilation = previousMetadataContext.Compilation;
            if (compilation == null)
            {
                compilation = metadataBlocks.ToCompilation(moduleVersionId, kind);
            }

            var context = EvaluationContext.CreateTypeContext(
                compilation,
                moduleVersionId,
                typeToken);

            // New type context is not attached to the AppDomain since it is less
            // re-usable than the previous attached method context. (We could hold
            // on to it if we don't have a previous method context but it's unlikely
            // that we evaluated a type-level expression before a method-level.)
            Debug.Assert(context != previousMetadataContext.EvaluationContext);

            return(context);
        }
        /// <summary>
        /// Create a context for evaluating expressions within a method scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="symReader"><see cref="ISymUnmanagedReader"/> for PDB associated with <paramref name="moduleVersionId"/></param>
        /// <param name="moduleVersionId">Module containing method</param>
        /// <param name="methodToken">Method metadata token</param>
        /// <param name="methodVersion">Method version.</param>
        /// <param name="ilOffset">IL offset of instruction pointer in method</param>
        /// <param name="localSignatureToken">Method local signature token</param>
        /// <returns>Evaluation context</returns>
        internal static EvaluationContext CreateMethodContext(
            CSharpMetadataContext previous,
            ImmutableArray <MetadataBlock> metadataBlocks,
            object symReader,
            Guid moduleVersionId,
            int methodToken,
            int methodVersion,
            uint ilOffset,
            int localSignatureToken)
        {
            var offset = NormalizeILOffset(ilOffset);

            // Re-use the previous compilation if possible.
            CSharpCompilation compilation;

            if (previous.Matches(metadataBlocks))
            {
                // Re-use entire context if method scope has not changed.
                var previousContext = previous.EvaluationContext;
                if (previousContext != null &&
                    previousContext.MethodContextReuseConstraints.HasValue &&
                    previousContext.MethodContextReuseConstraints.GetValueOrDefault().AreSatisfied(moduleVersionId, methodToken, methodVersion, offset))
                {
                    return(previousContext);
                }
                compilation = previous.Compilation;
            }
            else
            {
                compilation = metadataBlocks.ToCompilation();
            }

            return(CreateMethodContext(
                       compilation,
                       symReader,
                       moduleVersionId,
                       methodToken,
                       methodVersion,
                       offset,
                       localSignatureToken));
        }
Esempio n. 7
0
        internal override CSharpCompilation GetCompilation(DkmClrModuleInstance moduleInstance)
        {
            var appDomain      = moduleInstance.AppDomain;
            var previous       = appDomain.GetDataItem <CSharpMetadataContext>();
            var metadataBlocks = moduleInstance.RuntimeInstance.GetMetadataBlocks(appDomain);

            CSharpCompilation compilation;

            if (metadataBlocks.HaveNotChanged(previous))
            {
                compilation = previous.Compilation;
            }
            else
            {
                var dataItem = new CSharpMetadataContext(metadataBlocks);
                appDomain.SetDataItem(DkmDataCreationDisposition.CreateAlways, dataItem);
                compilation = dataItem.Compilation;
            }

            return(compilation);
        }
Esempio n. 8
0
        internal override PEMethodSymbol GetMethod(DkmClrInstructionAddress instructionAddress)
        {
            var moduleInstance = instructionAddress.ModuleInstance;
            var appDomain      = moduleInstance.AppDomain;
            var previous       = appDomain.GetDataItem <CSharpMetadataContext>();
            var metadataBlocks = instructionAddress.Process.GetMetadataBlocks(appDomain);

            CSharpCompilation compilation;

            if (metadataBlocks.HaveNotChanged(previous))
            {
                compilation = previous.Compilation;
            }
            else
            {
                var dataItem = new CSharpMetadataContext(metadataBlocks);
                appDomain.SetDataItem(DkmDataCreationDisposition.CreateAlways, dataItem);
                compilation = dataItem.Compilation;
            }

            return(compilation.GetSourceMethod(moduleInstance.Mvid, instructionAddress.MethodId.Token));
        }
Esempio n. 9
0
        /// <summary>
        /// Create a context for evaluating expressions within a method scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="symReader"><see cref="ISymUnmanagedReader"/> for PDB associated with <paramref name="moduleVersionId"/></param>
        /// <param name="moduleVersionId">Module containing method</param>
        /// <param name="methodToken">Method metadata token</param>
        /// <param name="methodVersion">Method version.</param>
        /// <param name="ilOffset">IL offset of instruction pointer in method</param>
        /// <param name="localSignatureToken">Method local signature token</param>
        /// <returns>Evaluation context</returns>
        internal static EvaluationContext CreateMethodContext(
            CSharpMetadataContext previous,
            ImmutableArray <MetadataBlock> metadataBlocks,
            object symReader,
            Guid moduleVersionId,
            int methodToken,
            int methodVersion,
            uint ilOffset,
            int localSignatureToken)
        {
            var offset = NormalizeILOffset(ilOffset);

            CSharpCompilation compilation = metadataBlocks.ToCompilation(default(Guid), MakeAssemblyReferencesKind.AllAssemblies);

            return(CreateMethodContext(
                       compilation,
                       symReader,
                       moduleVersionId,
                       methodToken,
                       methodVersion,
                       offset,
                       localSignatureToken));
        }
Esempio n. 10
0
        /// <summary>
        /// Create a context for evaluating expressions within a method scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="symReader"><see cref="ISymUnmanagedReader"/> for PDB associated with <paramref name="moduleVersionId"/></param>
        /// <param name="moduleVersionId">Module containing method</param>
        /// <param name="methodToken">Method metadata token</param>
        /// <param name="methodVersion">Method version.</param>
        /// <param name="ilOffset">IL offset of instruction pointer in method</param>
        /// <param name="localSignatureToken">Method local signature token</param>
        /// <returns>Evaluation context</returns>
        internal static EvaluationContext CreateMethodContext(
            CSharpMetadataContext previous,
            ImmutableArray<MetadataBlock> metadataBlocks,
            object symReader,
            Guid moduleVersionId,
            int methodToken,
            int methodVersion,
            int ilOffset,
            int localSignatureToken)
        {
            // Re-use the previous compilation if possible.
            CSharpCompilation compilation;
            if (previous.Matches(metadataBlocks))
            {
                // Re-use entire context if method scope has not changed.
                var previousContext = previous.EvaluationContext;
                if (previousContext != null &&
                    previousContext.MethodContextReuseConstraints.HasValue &&
                    previousContext.MethodContextReuseConstraints.GetValueOrDefault().AreSatisfied(moduleVersionId, methodToken, methodVersion, ilOffset))
                {
                    return previousContext;
                }
                compilation = previous.Compilation;
            }
            else
            {
                compilation = metadataBlocks.ToCompilation();
            }

            return CreateMethodContext(
                compilation,
                symReader,
                moduleVersionId,
                methodToken,
                methodVersion,
                ilOffset,
                localSignatureToken);
        }
Esempio n. 11
0
        /// <summary>
        /// Create a context for evaluating expressions within a method scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="symReader"><see cref="ISymUnmanagedReader"/> for PDB associated with <paramref name="moduleVersionId"/></param>
        /// <param name="moduleVersionId">Module containing method</param>
        /// <param name="methodToken">Method metadata token</param>
        /// <param name="methodVersion">Method version.</param>
        /// <param name="ilOffset">IL offset of instruction pointer in method</param>
        /// <param name="localSignatureToken">Method local signature token</param>
        /// <returns>Evaluation context</returns>
        internal static EvaluationContext CreateMethodContext(
            CSharpMetadataContext previous,
            ImmutableArray <MetadataBlock> metadataBlocks,
            object symReader,
            Guid moduleVersionId,
            int methodToken,
            int methodVersion,
            int ilOffset,
            int localSignatureToken)
        {
            Debug.Assert(MetadataTokens.Handle(methodToken).Kind == HandleKind.MethodDefinition);

            var typedSymReader = (ISymUnmanagedReader)symReader;
            var scopes         = ArrayBuilder <ISymUnmanagedScope> .GetInstance();

            typedSymReader.GetScopes(methodToken, methodVersion, ilOffset, IsLocalScopeEndInclusive, scopes);
            var scope = scopes.GetMethodScope(methodToken, methodVersion);

            // Re-use the previous compilation if possible.
            CSharpCompilation compilation;

            if (metadataBlocks.HaveNotChanged(previous))
            {
                // Re-use entire context if method scope has not changed.
                var previousContext = previous.EvaluationContext;
                if ((scope != null) && (previousContext != null) && scope.Equals(previousContext.MethodScope))
                {
                    return(previousContext);
                }
                compilation = previous.Compilation;
            }
            else
            {
                compilation = metadataBlocks.ToCompilation();
            }

            var localNames = scopes.GetLocalNames();

            var dynamicLocalMap            = ImmutableDictionary <int, ImmutableArray <bool> > .Empty;
            var dynamicLocalConstantMap    = ImmutableDictionary <string, ImmutableArray <bool> > .Empty;
            var inScopeHoistedLocalIndices = ImmutableSortedSet <int> .Empty;
            var methodDebugInfo            = default(MethodDebugInfo);

            if (typedSymReader != null)
            {
                try
                {
                    var cdi = typedSymReader.GetCustomDebugInfoBytes(methodToken, methodVersion);
                    if (cdi != null)
                    {
                        CustomDebugInfoReader.GetCSharpDynamicLocalInfo(
                            cdi,
                            methodToken,
                            methodVersion,
                            localNames.FirstOrDefault(),
                            out dynamicLocalMap,
                            out dynamicLocalConstantMap);

                        inScopeHoistedLocalIndices = CustomDebugInfoReader.GetCSharpInScopeHoistedLocalIndices(
                            cdi,
                            methodToken,
                            methodVersion,
                            ilOffset);
                    }

                    // TODO (acasey): switch on the type of typedSymReader and call the appropriate helper. (GH #702)
                    methodDebugInfo = typedSymReader.GetMethodDebugInfo(methodToken, methodVersion);
                }
                catch (InvalidOperationException)
                {
                    // bad CDI, ignore
                }
            }

            var methodHandle = (MethodDefinitionHandle)MetadataTokens.Handle(methodToken);
            var currentFrame = compilation.GetMethod(moduleVersionId, methodHandle);

            Debug.Assert((object)currentFrame != null);
            var metadataDecoder = new MetadataDecoder((PEModuleSymbol)currentFrame.ContainingModule, currentFrame);
            var localInfo       = metadataDecoder.GetLocalInfo(localSignatureToken);
            var localBuilder    = ArrayBuilder <LocalSymbol> .GetInstance();

            var sourceAssembly = compilation.SourceAssembly;

            GetLocals(localBuilder, currentFrame, localNames, localInfo, dynamicLocalMap, sourceAssembly);
            GetConstants(localBuilder, currentFrame, scopes.GetConstantSignatures(), metadataDecoder, dynamicLocalConstantMap, sourceAssembly);
            scopes.Free();

            var locals = localBuilder.ToImmutableAndFree();

            return(new EvaluationContext(
                       metadataBlocks,
                       scope,
                       compilation,
                       metadataDecoder,
                       currentFrame,
                       locals,
                       inScopeHoistedLocalIndices,
                       methodDebugInfo));
        }
Esempio n. 12
0
        /// <summary>
        /// Create a context for evaluating expressions within a method scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="symReader"><see cref="ISymUnmanagedReader"/> for PDB associated with <paramref name="moduleVersionId"/></param>
        /// <param name="moduleVersionId">Module containing method</param>
        /// <param name="methodToken">Method metadata token</param>
        /// <param name="methodVersion">Method version.</param>
        /// <param name="ilOffset">IL offset of instruction pointer in method</param>
        /// <param name="localSignatureToken">Method local signature token</param>
        /// <returns>Evaluation context</returns>
        internal static EvaluationContext CreateMethodContext(
            CSharpMetadataContext previous,
            ImmutableArray<MetadataBlock> metadataBlocks,
            object symReader,
            Guid moduleVersionId,
            int methodToken,
            int methodVersion,
            int ilOffset,
            int localSignatureToken)
        {
            Debug.Assert(MetadataTokens.Handle(methodToken).Kind == HandleKind.MethodDefinition);

            var typedSymReader = (ISymUnmanagedReader)symReader;
            var scopes = ArrayBuilder<ISymUnmanagedScope>.GetInstance();
            typedSymReader.GetScopes(methodToken, methodVersion, ilOffset, IsLocalScopeEndInclusive, scopes);
            var scope = scopes.GetMethodScope(methodToken, methodVersion);

            // Re-use the previous compilation if possible.
            CSharpCompilation compilation;
            if (metadataBlocks.HaveNotChanged(previous))
            {
                // Re-use entire context if method scope has not changed.
                var previousContext = previous.EvaluationContext;
                if ((scope != null) && (previousContext != null) && scope.Equals(previousContext.MethodScope))
                {
                    return previousContext;
                }
                compilation = previous.Compilation;
            }
            else
            {
                compilation = metadataBlocks.ToCompilation();
            }

            var localNames = scopes.GetLocalNames();

            var dynamicLocalMap = ImmutableDictionary<int, ImmutableArray<bool>>.Empty;
            var dynamicLocalConstantMap = ImmutableDictionary<string, ImmutableArray<bool>>.Empty;
            var inScopeHoistedLocalIndices = ImmutableSortedSet<int>.Empty;
            var groupedImportStrings = default(ImmutableArray<ImmutableArray<string>>);
            var externAliasStrings = default(ImmutableArray<string>);

            if (typedSymReader != null)
            {
                try
                {
                    var cdi = typedSymReader.GetCustomDebugInfo(methodToken, methodVersion);
                    if (cdi != null)
                    {
                        CustomDebugInfoReader.GetCSharpDynamicLocalInfo(
                            cdi,
                            methodToken,
                            methodVersion,
                            localNames.FirstOrDefault(),
                            out dynamicLocalMap,
                            out dynamicLocalConstantMap);

                        inScopeHoistedLocalIndices = CustomDebugInfoReader.GetCSharpInScopeHoistedLocalIndices(
                            cdi,
                            methodToken,
                            methodVersion,
                            ilOffset);
                    }

                    groupedImportStrings = typedSymReader.GetCSharpGroupedImportStrings(methodToken, methodVersion, out externAliasStrings);
                }
                catch (InvalidOperationException)
                {
                    // bad CDI, ignore
                }
            }

            var methodHandle = (MethodDefinitionHandle)MetadataTokens.Handle(methodToken);
            var currentFrame = compilation.GetMethod(moduleVersionId, methodHandle);
            Debug.Assert((object)currentFrame != null);
            var metadataDecoder = new MetadataDecoder((PEModuleSymbol)currentFrame.ContainingModule, currentFrame);
            var localInfo = metadataDecoder.GetLocalInfo(localSignatureToken);
            var localBuilder = ArrayBuilder<LocalSymbol>.GetInstance();
            var sourceAssembly = compilation.SourceAssembly;
            GetLocals(localBuilder, currentFrame, localNames, localInfo, dynamicLocalMap, sourceAssembly);
            GetConstants(localBuilder, currentFrame, scopes.GetConstantSignatures(), metadataDecoder, dynamicLocalConstantMap, sourceAssembly);
            scopes.Free();

            var locals = localBuilder.ToImmutableAndFree();

            return new EvaluationContext(
                metadataBlocks,
                scope,
                compilation,
                metadataDecoder,
                currentFrame,
                locals,
                inScopeHoistedLocalIndices,
                groupedImportStrings,
                externAliasStrings);
        }
Esempio n. 13
0
        public void ReuseEvaluationContext()
        {
            var sourceA =
@"public interface I
{
}";
            var sourceB =
@"class C
{
    static void F(I o)
    {
        object x = 1;
        if (o == null)
        {
            object y = 2;
            y = x;
        }
        else
        {
            object z;
        }
        x = 3;
    }
    static void G()
    {
    }
}";
            var compilationA = CreateCompilationWithMscorlib(
                sourceA,
                options: TestOptions.DebugDll,
                assemblyName: ExpressionCompilerUtilities.GenerateUniqueName());
            var referenceA = compilationA.EmitToImageReference();
            var compilationB = CreateCompilationWithMscorlib(
                sourceB,
                options: TestOptions.DebugDll,
                assemblyName: ExpressionCompilerUtilities.GenerateUniqueName(),
                references: new MetadataReference[] { referenceA });
            byte[] exeBytes;
            byte[] pdbBytes;
            ImmutableArray<MetadataReference> references;
            compilationB.EmitAndGetReferences(out exeBytes, out pdbBytes, out references);
            const int methodVersion = 1;

            CSharpMetadataContext previous = default(CSharpMetadataContext);
            int startOffset;
            int endOffset;
            var runtime = CreateRuntimeInstance(ExpressionCompilerUtilities.GenerateUniqueName(), references, exeBytes, new SymReader(pdbBytes));
            ImmutableArray<MetadataBlock> typeBlocks;
            ImmutableArray<MetadataBlock> methodBlocks;
            Guid moduleVersionId;
            ISymUnmanagedReader symReader;
            int typeToken;
            int methodToken;
            int localSignatureToken;
            GetContextState(runtime, "C", out typeBlocks, out moduleVersionId, out symReader, out typeToken, out localSignatureToken);
            GetContextState(runtime, "C.F", out methodBlocks, out moduleVersionId, out symReader, out methodToken, out localSignatureToken);

            // Get non-empty scopes.
            var scopes = symReader.GetScopes(methodToken, methodVersion, EvaluationContext.IsLocalScopeEndInclusive).WhereAsArray(s => s.Locals.Length > 0);
            Assert.True(scopes.Length >= 3);
            var outerScope = scopes.First(s => s.Locals.Contains("x"));

            startOffset = outerScope.StartOffset;
            endOffset = outerScope.EndOffset - 1;

            // At start of outer scope.
            var context = EvaluationContext.CreateMethodContext(previous, methodBlocks, symReader, moduleVersionId, methodToken, methodVersion, (uint)startOffset, localSignatureToken);
            Assert.Equal(default(CSharpMetadataContext), previous);
            previous = new CSharpMetadataContext(methodBlocks, context);

            // At end of outer scope - not reused because of the nested scope.
            context = EvaluationContext.CreateMethodContext(previous, methodBlocks, symReader, moduleVersionId, methodToken, methodVersion, (uint)endOffset, localSignatureToken);
            Assert.NotEqual(context, previous.EvaluationContext); // Not required, just documentary.

            // At type context.
            context = EvaluationContext.CreateTypeContext(previous, typeBlocks, moduleVersionId, typeToken);
            Assert.NotEqual(context, previous.EvaluationContext);
            Assert.Null(context.MethodContextReuseConstraints);
            Assert.Equal(context.Compilation, previous.Compilation);

            // Step through entire method.
            var previousScope = (Scope)null;
            previous = new CSharpMetadataContext(typeBlocks, context);
            for (int offset = startOffset; offset <= endOffset; offset++)
            {
                var scope = scopes.GetInnermostScope(offset);
                var constraints = previous.EvaluationContext.MethodContextReuseConstraints;
                if (constraints.HasValue)
                {
                    Assert.Equal(scope == previousScope, constraints.GetValueOrDefault().AreSatisfied(moduleVersionId, methodToken, methodVersion, offset));
                }

                context = EvaluationContext.CreateMethodContext(previous, methodBlocks, symReader, moduleVersionId, methodToken, methodVersion, (uint)offset, localSignatureToken);
                if (scope == previousScope)
                {
                    Assert.Equal(context, previous.EvaluationContext);
                }
                else
                {
                    // Different scope. Should reuse compilation.
                    Assert.NotEqual(context, previous.EvaluationContext);
                    if (previous.EvaluationContext != null)
                    {
                        Assert.NotEqual(context.MethodContextReuseConstraints, previous.EvaluationContext.MethodContextReuseConstraints);
                        Assert.Equal(context.Compilation, previous.Compilation);
                    }
                }
                previousScope = scope;
                previous = new CSharpMetadataContext(methodBlocks, context);
            }

            // With different references.
            var fewerReferences = references.Remove(referenceA);
            Assert.Equal(fewerReferences.Length, references.Length - 1);
            runtime = CreateRuntimeInstance(ExpressionCompilerUtilities.GenerateUniqueName(), fewerReferences, exeBytes, new SymReader(pdbBytes));
            GetContextState(runtime, "C.F", out methodBlocks, out moduleVersionId, out symReader, out methodToken, out localSignatureToken);

            // Different references. No reuse.
            context = EvaluationContext.CreateMethodContext(previous, methodBlocks, symReader, moduleVersionId, methodToken, methodVersion, (uint)endOffset, localSignatureToken);
            Assert.NotEqual(context, previous.EvaluationContext);
            Assert.True(previous.EvaluationContext.MethodContextReuseConstraints.Value.AreSatisfied(moduleVersionId, methodToken, methodVersion, endOffset));
            Assert.NotEqual(context.Compilation, previous.Compilation);
            previous = new CSharpMetadataContext(methodBlocks, context);

            // Different method. Should reuse Compilation.
            GetContextState(runtime, "C.G", out methodBlocks, out moduleVersionId, out symReader, out methodToken, out localSignatureToken);
            context = EvaluationContext.CreateMethodContext(previous, methodBlocks, symReader, moduleVersionId, methodToken, methodVersion, ilOffset: 0, localSignatureToken: localSignatureToken);
            Assert.NotEqual(context, previous.EvaluationContext);
            Assert.False(previous.EvaluationContext.MethodContextReuseConstraints.Value.AreSatisfied(moduleVersionId, methodToken, methodVersion, 0));
            Assert.Equal(context.Compilation, previous.Compilation);

            // No EvaluationContext. Should reuse Compilation
            previous = new CSharpMetadataContext(previous.MetadataBlocks, previous.Compilation);
            context = EvaluationContext.CreateMethodContext(previous, methodBlocks, symReader, moduleVersionId, methodToken, methodVersion, ilOffset: 0, localSignatureToken: localSignatureToken);
            Assert.Null(previous.EvaluationContext);
            Assert.NotNull(context);
            Assert.Equal(context.Compilation, previous.Compilation);
        }
        /// <summary>
        /// Create a context for evaluating expressions within a method scope.
        /// </summary>
        /// <param name="previous">Previous context, if any, for possible re-use.</param>
        /// <param name="metadataBlocks">Module metadata</param>
        /// <param name="symReader"><see cref="ISymUnmanagedReader"/> for PDB associated with <paramref name="moduleVersionId"/></param>
        /// <param name="moduleVersionId">Module containing method</param>
        /// <param name="methodToken">Method metadata token</param>
        /// <param name="methodVersion">Method version.</param>
        /// <param name="ilOffset">IL offset of instruction pointer in method</param>
        /// <param name="localSignatureToken">Method local signature token</param>
        /// <returns>Evaluation context</returns>
        internal static EvaluationContext CreateMethodContext(
            CSharpMetadataContext previous,
            ImmutableArray <MetadataBlock> metadataBlocks,
            object symReader,
            Guid moduleVersionId,
            int methodToken,
            int methodVersion,
            int ilOffset,
            int localSignatureToken)
        {
            Debug.Assert(MetadataTokens.Handle(methodToken).Kind == HandleKind.MethodDefinition);

            // Re-use the previous compilation if possible.
            CSharpCompilation compilation;

            if (metadataBlocks.HaveNotChanged(previous))
            {
                // Re-use entire context if method scope has not changed.
                var previousContext = previous.EvaluationContext;
                if (previousContext != null &&
                    previousContext.MethodContextReuseConstraints.HasValue &&
                    previousContext.MethodContextReuseConstraints.GetValueOrDefault().AreSatisfied(methodToken, methodVersion, ilOffset))
                {
                    return(previousContext);
                }
                compilation = previous.Compilation;
            }
            else
            {
                compilation = metadataBlocks.ToCompilation();
            }

            var typedSymReader = (ISymUnmanagedReader)symReader;
            var allScopes      = ArrayBuilder <ISymUnmanagedScope> .GetInstance();

            var containingScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance();

            typedSymReader.GetScopes(methodToken, methodVersion, ilOffset, IsLocalScopeEndInclusive, allScopes, containingScopes);
            var methodContextReuseConstraints = allScopes.GetReuseConstraints(methodToken, methodVersion, ilOffset, IsLocalScopeEndInclusive);

            allScopes.Free();

            var localNames = containingScopes.GetLocalNames();

            var inScopeHoistedLocalIndices = ImmutableSortedSet <int> .Empty;
            var methodDebugInfo            = default(MethodDebugInfo);

            if (typedSymReader != null)
            {
                try
                {
                    // TODO (https://github.com/dotnet/roslyn/issues/702): switch on the type of typedSymReader and call the appropriate helper.
                    methodDebugInfo            = typedSymReader.GetMethodDebugInfo(methodToken, methodVersion, localNames.FirstOrDefault());
                    inScopeHoistedLocalIndices = methodDebugInfo.GetInScopeHoistedLocalIndices(ilOffset, ref methodContextReuseConstraints);
                }
                catch (InvalidOperationException)
                {
                    // bad CDI, ignore
                }
            }

            var methodHandle = (MethodDefinitionHandle)MetadataTokens.Handle(methodToken);
            var currentFrame = compilation.GetMethod(moduleVersionId, methodHandle);

            Debug.Assert((object)currentFrame != null);
            var metadataDecoder = new MetadataDecoder((PEModuleSymbol)currentFrame.ContainingModule, currentFrame);
            var localInfo       = metadataDecoder.GetLocalInfo(localSignatureToken);
            var localBuilder    = ArrayBuilder <LocalSymbol> .GetInstance();

            var sourceAssembly = compilation.SourceAssembly;

            GetLocals(localBuilder, currentFrame, localNames, localInfo, methodDebugInfo.DynamicLocalMap, sourceAssembly);
            GetConstants(localBuilder, currentFrame, containingScopes.GetConstantSignatures(), metadataDecoder, methodDebugInfo.DynamicLocalConstantMap, sourceAssembly);
            containingScopes.Free();

            var locals = localBuilder.ToImmutableAndFree();

            return(new EvaluationContext(
                       metadataBlocks,
                       methodContextReuseConstraints,
                       compilation,
                       metadataDecoder,
                       currentFrame,
                       locals,
                       inScopeHoistedLocalIndices,
                       methodDebugInfo));
        }
        public void AssemblyDuplicateReferences()
        {
            var sourceA =
@"public class A
{
}";
            var sourceB =
@"public class B
{
    public A F = new A();
}";
            var sourceC =
@"class C
{
    private B F = new B();
    static void M()
    {
    }
}";
            // Assembly A, multiple versions, strong name.
            var assemblyNameA = ExpressionCompilerUtilities.GenerateUniqueName();
            var publicKeyA = ImmutableArray.CreateRange(new byte[] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xED, 0xD3, 0x22, 0xCB, 0x6B, 0xF8, 0xD4, 0xA2, 0xFC, 0xCC, 0x87, 0x37, 0x04, 0x06, 0x04, 0xCE, 0xE7, 0xB2, 0xA6, 0xF8, 0x4A, 0xEE, 0xF3, 0x19, 0xDF, 0x5B, 0x95, 0xE3, 0x7A, 0x6A, 0x28, 0x24, 0xA4, 0x0A, 0x83, 0x83, 0xBD, 0xBA, 0xF2, 0xF2, 0x52, 0x20, 0xE9, 0xAA, 0x3B, 0xD1, 0xDD, 0xE4, 0x9A, 0x9A, 0x9C, 0xC0, 0x30, 0x8F, 0x01, 0x40, 0x06, 0xE0, 0x2B, 0x95, 0x62, 0x89, 0x2A, 0x34, 0x75, 0x22, 0x68, 0x64, 0x6E, 0x7C, 0x2E, 0x83, 0x50, 0x5A, 0xCE, 0x7B, 0x0B, 0xE8, 0xF8, 0x71, 0xE6, 0xF7, 0x73, 0x8E, 0xEB, 0x84, 0xD2, 0x73, 0x5D, 0x9D, 0xBE, 0x5E, 0xF5, 0x90, 0xF9, 0xAB, 0x0A, 0x10, 0x7E, 0x23, 0x48, 0xF4, 0xAD, 0x70, 0x2E, 0xF7, 0xD4, 0x51, 0xD5, 0x8B, 0x3A, 0xF7, 0xCA, 0x90, 0x4C, 0xDC, 0x80, 0x19, 0x26, 0x65, 0xC9, 0x37, 0xBD, 0x52, 0x81, 0xF1, 0x8B, 0xCD });
            var compilationAS1 = CreateCompilation(
                new AssemblyIdentity(assemblyNameA, new Version(1, 1, 1, 1), cultureName: "", publicKeyOrToken: publicKeyA, hasPublicKey: true),
                new[] { sourceA },
                references: new[] { MscorlibRef },
                options: TestOptions.DebugDll.WithDelaySign(true));
            var referenceAS1 = compilationAS1.EmitToImageReference();
            var identityAS1 = referenceAS1.GetAssemblyIdentity();
            var compilationAS2 = CreateCompilation(
                new AssemblyIdentity(assemblyNameA, new Version(2, 1, 1, 1), cultureName: "", publicKeyOrToken: publicKeyA, hasPublicKey: true),
                new[] { sourceA },
                references: new[] { MscorlibRef },
                options: TestOptions.DebugDll.WithDelaySign(true));
            var referenceAS2 = compilationAS2.EmitToImageReference();
            var identityAS2 = referenceAS2.GetAssemblyIdentity();

            // Assembly B, multiple versions, not strong name.
            var assemblyNameB = ExpressionCompilerUtilities.GenerateUniqueName();
            var compilationBN1 = CreateCompilation(
                new AssemblyIdentity(assemblyNameB, new Version(1, 1, 1, 1)),
                new[] { sourceB },
                references: new[] { MscorlibRef, referenceAS1 },
                options: TestOptions.DebugDll);
            var referenceBN1 = compilationBN1.EmitToImageReference();
            var identityBN1 = referenceBN1.GetAssemblyIdentity();
            var compilationBN2 = CreateCompilation(
                new AssemblyIdentity(assemblyNameB, new Version(2, 2, 2, 1)),
                new[] { sourceB },
                references: new[] { MscorlibRef, referenceAS1 },
                options: TestOptions.DebugDll);
            var referenceBN2 = compilationBN2.EmitToImageReference();
            var identityBN2 = referenceBN2.GetAssemblyIdentity();

            // Assembly B, multiple versions, strong name.
            var publicKeyB = ImmutableArray.CreateRange(new byte[] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x53, 0x52, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xED, 0xD3, 0x22, 0xCB, 0x6B, 0xF8, 0xD4, 0xA2, 0xFC, 0xCC, 0x87, 0x37, 0x04, 0x06, 0x04, 0xCE, 0xE7, 0xB2, 0xA6, 0xF8, 0x4A, 0xEE, 0xF3, 0x19, 0xDF, 0x5B, 0x95, 0xE3, 0x7A, 0x6A, 0x28, 0x24, 0xA4, 0x0A, 0x83, 0x83, 0xBD, 0xBA, 0xF2, 0xF2, 0x52, 0x20, 0xE9, 0xAA, 0x3B, 0xD1, 0xDD, 0xE4, 0x9A, 0x9A, 0x9C, 0xC0, 0x30, 0x8F, 0x01, 0x40, 0x06, 0xE0, 0x2B, 0x95, 0x62, 0x89, 0x2A, 0x34, 0x75, 0x22, 0x68, 0x64, 0x6E, 0x7C, 0x2E, 0x83, 0x50, 0x5A, 0xCE, 0x7B, 0x0B, 0xE8, 0xF8, 0x71, 0xE6, 0xF7, 0x73, 0x8E, 0xEB, 0x84, 0xD2, 0x73, 0x5D, 0x9D, 0xBE, 0x5E, 0xF5, 0x90, 0xF9, 0xAB, 0x0A, 0x10, 0x7E, 0x23, 0x48, 0xF4, 0xAD, 0x70, 0x2E, 0xF7, 0xD4, 0x51, 0xD5, 0x8B, 0x3A, 0xF7, 0xCA, 0x90, 0x4C, 0xDC, 0x80, 0x19, 0x26, 0x65, 0xC9, 0x37, 0xBD, 0x52, 0x81, 0xF1, 0x8B, 0xCD });
            var compilationBS1 = CreateCompilation(
                new AssemblyIdentity(assemblyNameB, new Version(1, 1, 1, 1), cultureName: "", publicKeyOrToken: publicKeyB, hasPublicKey: true),
                new[] { sourceB },
                references: new[] { MscorlibRef, referenceAS1 },
                options: TestOptions.DebugDll.WithDelaySign(true));
            var referenceBS1 = compilationBS1.EmitToImageReference();
            var identityBS1 = referenceBS1.GetAssemblyIdentity();
            var compilationBS2 = CreateCompilation(
                new AssemblyIdentity(assemblyNameB, new Version(2, 2, 2, 1), cultureName: "", publicKeyOrToken: publicKeyB, hasPublicKey: true),
                new[] { sourceB },
                references: new[] { MscorlibRef, referenceAS2 },
                options: TestOptions.DebugDll.WithDelaySign(true));
            var referenceBS2 = compilationBS2.EmitToImageReference();
            var identityBS2 = referenceBS2.GetAssemblyIdentity();

            var mscorlibIdentity = MscorlibRef.GetAssemblyIdentity();
            var mscorlib20Identity = MscorlibRef_v20.GetAssemblyIdentity();
            var systemRefIdentity = SystemRef.GetAssemblyIdentity();
            var systemRef20Identity = SystemRef_v20.GetAssemblyIdentity();

            // No duplicates.
            VerifyAssemblyReferences(
                referenceBN1,
                ImmutableArray.Create(MscorlibRef, referenceAS1, referenceBN1),
                ImmutableArray.Create(mscorlibIdentity, identityAS1, identityBN1));
            // No duplicates, extra references.
            VerifyAssemblyReferences(
                referenceAS1,
                ImmutableArray.Create(MscorlibRef, referenceBN1, referenceAS1, referenceBS2),
                ImmutableArray.Create(mscorlibIdentity, identityAS1));
            // Strong-named, non-strong-named, and framework duplicates, same version (no aliases).
            VerifyAssemblyReferences(
                referenceBN2,
                ImmutableArray.Create(MscorlibRef, referenceAS1, MscorlibRef, referenceBN2, referenceBN2, referenceAS1, referenceAS1),
                ImmutableArray.Create(mscorlibIdentity, identityAS1, identityBN2));
            // Strong-named, non-strong-named, and framework duplicates, different versions.
            VerifyAssemblyReferences(
                referenceBN1,
                ImmutableArray.Create(MscorlibRef, referenceAS1, MscorlibRef_v20, referenceAS2, referenceBN2, referenceBN1, referenceAS2, referenceAS1, referenceBN1),
                ImmutableArray.Create(mscorlibIdentity, identityAS2, identityBN2));
            VerifyAssemblyReferences(
                referenceBN2,
                ImmutableArray.Create(MscorlibRef, referenceAS1, MscorlibRef_v20, referenceAS2, referenceBN2, referenceBN1, referenceAS2, referenceAS1, referenceBN1),
                ImmutableArray.Create(mscorlibIdentity, identityAS2, identityBN2));
            // Strong-named, different versions.
            VerifyAssemblyReferences(
                referenceBS1,
                ImmutableArray.Create(MscorlibRef, referenceAS1, referenceAS2, referenceBS2, referenceBS1, referenceAS2, referenceAS1, referenceBS1),
                ImmutableArray.Create(mscorlibIdentity, identityAS2, identityBS2));
            VerifyAssemblyReferences(
                referenceBS2,
                ImmutableArray.Create(MscorlibRef, referenceAS1, referenceAS2, referenceBS2, referenceBS1, referenceAS2, referenceAS1, referenceBS1),
                ImmutableArray.Create(mscorlibIdentity, identityAS2, identityBS2));

            // Assembly C, multiple versions, not strong name.
            var assemblyNameC = ExpressionCompilerUtilities.GenerateUniqueName();
            var compilationCN1 = CreateCompilation(
                new AssemblyIdentity(assemblyNameC, new Version(1, 1, 1, 1)),
                new[] { sourceC },
                references: new[] { MscorlibRef, referenceBS1 },
                options: TestOptions.DebugDll);
            byte[] exeBytesC1;
            byte[] pdbBytesC1;
            ImmutableArray<MetadataReference> references;
            compilationCN1.EmitAndGetReferences(out exeBytesC1, out pdbBytesC1, out references);
            var compilationCN2 = CreateCompilation(
                new AssemblyIdentity(assemblyNameC, new Version(2, 1, 1, 1)),
                new[] { sourceC },
                references: new[] { MscorlibRef, referenceBS2 },
                options: TestOptions.DebugDll);
            byte[] exeBytesC2;
            byte[] pdbBytesC2;
            compilationCN1.EmitAndGetReferences(out exeBytesC2, out pdbBytesC2, out references);

            // Duplicate assemblies, target module referencing BS1.
            using (var runtime = CreateRuntimeInstance(
                assemblyNameC,
                ImmutableArray.Create(MscorlibRef, referenceAS1, referenceAS2, referenceBS2, referenceBS1, referenceBS2),
                exeBytesC1,
                new SymReader(pdbBytesC1)))
            {
                ImmutableArray<MetadataBlock> typeBlocks;
                ImmutableArray<MetadataBlock> methodBlocks;
                Guid moduleVersionId;
                ISymUnmanagedReader symReader;
                int typeToken;
                int methodToken;
                int localSignatureToken;
                GetContextState(runtime, "C", out typeBlocks, out moduleVersionId, out symReader, out typeToken, out localSignatureToken);
                GetContextState(runtime, "C.M", out methodBlocks, out moduleVersionId, out symReader, out methodToken, out localSignatureToken);
                int ilOffset = ExpressionCompilerTestHelpers.GetOffset(methodToken, symReader);

                // Compile expression with type context with all modules.
                var context = EvaluationContext.CreateTypeContext(
                    default(CSharpMetadataContext),
                    typeBlocks,
                    moduleVersionId,
                    typeToken);
                string error;
                // A is ambiguous.
                var testData = new CompilationTestData();
                context.CompileExpression("new A()", out error, testData);
                Assert.True(error.StartsWith("error CS0433: The type 'A' exists in both "));
                testData = new CompilationTestData();
                // B is ambiguous.
                context.CompileExpression("new B()", out error, testData);
                Assert.True(error.StartsWith("error CS0433: The type 'B' exists in both "));
                var previous = new CSharpMetadataContext(typeBlocks, context);

                // Compile expression with type context with referenced modules only.
                context = EvaluationContext.CreateTypeContext(
                    typeBlocks.ToCompilationReferencedModulesOnly(moduleVersionId),
                    moduleVersionId,
                    typeToken);
                // A is unrecognized since there were no direct references to AS1 or AS2.
                testData = new CompilationTestData();
                context.CompileExpression("new A()", out error, testData);
                Assert.Equal(error, "error CS0246: The type or namespace name 'A' could not be found (are you missing a using directive or an assembly reference?)");
                testData = new CompilationTestData();
                // B should be resolved to BS2.
                context.CompileExpression("new B()", out error, testData);
                var methodData = testData.GetMethodData("<>x.<>m0");
                methodData.VerifyIL(
@"{
  // Code size        6 (0x6)
  .maxstack  1
  IL_0000:  newobj     ""B..ctor()""
  IL_0005:  ret
}");
                Assert.Equal(methodData.Method.ReturnType.ContainingAssembly.ToDisplayString(), identityBS2.GetDisplayName());
                // B.F should result in missing assembly AS2 since there were no direct references to AS2.
                ResultProperties resultProperties;
                ImmutableArray<AssemblyIdentity> missingAssemblyIdentities;
                testData = new CompilationTestData();
                context.CompileExpression(
                    InspectionContextFactory.Empty,
                    "(new B()).F",
                    DkmEvaluationFlags.None,
                    DiagnosticFormatter.Instance,
                    out resultProperties,
                    out error,
                    out missingAssemblyIdentities,
                    EnsureEnglishUICulture.PreferredOrNull,
                    testData);
                AssertEx.Equal(missingAssemblyIdentities, ImmutableArray.Create(identityAS2));

                // Compile expression with method context with all modules.
                context = EvaluationContext.CreateMethodContext(
                    previous,
                    methodBlocks,
                    symReader,
                    moduleVersionId,
                    methodToken: methodToken,
                    methodVersion: 1,
                    ilOffset: ilOffset,
                    localSignatureToken: localSignatureToken);
                Assert.Equal(previous.Compilation, context.Compilation); // re-use type context compilation
                testData = new CompilationTestData();
                // A is ambiguous.
                testData = new CompilationTestData();
                context.CompileExpression("new A()", out error, testData);
                Assert.True(error.StartsWith("error CS0433: The type 'A' exists in both "));
                testData = new CompilationTestData();
                // B is ambiguous.
                context.CompileExpression("new B()", out error, testData);
                Assert.True(error.StartsWith("error CS0433: The type 'B' exists in both "));

                // Compile expression with method context with referenced modules only.
                context = EvaluationContext.CreateMethodContext(
                    methodBlocks.ToCompilationReferencedModulesOnly(moduleVersionId),
                    symReader,
                    moduleVersionId,
                    methodToken: methodToken,
                    methodVersion: 1,
                    ilOffset: ilOffset,
                    localSignatureToken: localSignatureToken);
                // A is unrecognized since there were no direct references to AS1 or AS2.
                testData = new CompilationTestData();
                context.CompileExpression("new A()", out error, testData);
                Assert.Equal(error, "error CS0246: The type or namespace name 'A' could not be found (are you missing a using directive or an assembly reference?)");
                testData = new CompilationTestData();
                // B should be resolved to BS2.
                context.CompileExpression("new B()", out error, testData);
                methodData = testData.GetMethodData("<>x.<>m0");
                methodData.VerifyIL(
@"{
  // Code size        6 (0x6)
  .maxstack  1
  IL_0000:  newobj     ""B..ctor()""
  IL_0005:  ret
}");
                Assert.Equal(methodData.Method.ReturnType.ContainingAssembly.ToDisplayString(), identityBS2.GetDisplayName());
                // B.F should result in missing assembly AS2 since there were no direct references to AS2.
                testData = new CompilationTestData();
                context.CompileExpression(
                    InspectionContextFactory.Empty,
                    "(new B()).F",
                    DkmEvaluationFlags.None,
                    DiagnosticFormatter.Instance,
                    out resultProperties,
                    out error,
                    out missingAssemblyIdentities,
                    EnsureEnglishUICulture.PreferredOrNull,
                    testData);
                AssertEx.Equal(missingAssemblyIdentities, ImmutableArray.Create(identityAS2));
            }
        }
        internal static EvaluationContext CreateMethodContext(
            RuntimeInstance runtime,
            string methodName,
            int atLineNumber = -1,
            CSharpMetadataContext previous = null)
        {
            ImmutableArray<MetadataBlock> blocks;
            Guid moduleVersionId;
            ISymUnmanagedReader symReader;
            int methodToken;
            int localSignatureToken;
            GetContextState(runtime, methodName, out blocks, out moduleVersionId, out symReader, out methodToken, out localSignatureToken);

            int ilOffset = ExpressionCompilerTestHelpers.GetOffset(methodToken, symReader, atLineNumber);

            return EvaluationContext.CreateMethodContext(
                previous,
                blocks,
                symReader,
                moduleVersionId,
                methodToken: methodToken,
                methodVersion: 1,
                ilOffset: ilOffset,
                localSignatureToken: localSignatureToken);
        }