public ExpandedVarargsMethodReference(Cci.IMethodReference underlyingMethod, ImmutableArray <Cci.IParameterTypeInformation> argListParams) { Debug.Assert(underlyingMethod.AcceptsExtraArguments); Debug.Assert(!argListParams.IsEmpty); this.underlyingMethod = underlyingMethod; this.argListParams = argListParams; }
public ExpandedVarargsMethodReference(Cci.IMethodReference underlyingMethod, ImmutableArray<Cci.IParameterTypeInformation> argListParams) { Debug.Assert(underlyingMethod.AcceptsExtraArguments); Debug.Assert(!argListParams.IsEmpty); this.underlyingMethod = underlyingMethod; this.argListParams = argListParams; }
public IEnumerable <Tuple <string, TextSpan> > AnalyzeMeAMethod( Microsoft.CodeAnalysis.Document document, MethodDeclarationSyntax methodDeclaration, CancellationToken cancellationToken) { var semanticModel = document.GetSemanticModel(cancellationToken); var semanticNode = semanticModel.GetDeclaredSymbol(methodDeclaration); Microsoft.Cci.IMethodReference cciMethod = null; this.sourceLocationProvider = new SourceLocationProvider(); string exceptionMessage = null; try { // Constructs a full metadata model for the assembly the semantic model is from var transformer = new NodeVisitor(this.host, semanticModel, sourceLocationProvider); // Constructs the method body for just this one method cciMethod = transformer.Visit(methodDeclaration) as Microsoft.Cci.IMethodReference; } catch (ConverterException e) { exceptionMessage = e.Message; } if (exceptionMessage != null) { yield return(Tuple.Create(exceptionMessage, methodDeclaration.Span)); yield break; } var unit = TypeHelper.GetDefiningUnitReference(cciMethod.ContainingType); this.host.RegisterUnit(unit.ResolvedUnit); this.cciProvider.MetaDataDecoder.RegisterSourceLocationProvider(unit, sourceLocationProvider); this.methodAnalyzer.Analyze(MethodReferenceAdaptor.AdaptorOf(cciMethod)); foreach (var result in this.analysisResults) { yield return(result); } }
/// <summary> /// general method reference /// </summary> /// <param name="method"></param> /// <returns></returns> private string ParseTargetMethodName(cci.IMethodReference method) { return(method.Name.Value); }
/// <summary> /// Emits the compilation into given <see cref="ModuleBuilder"/> using Reflection.Emit APIs. /// </summary> /// <param name="compilation">Compilation.</param> /// <param name="moduleBuilder"> /// The module builder to add the types into. Can be reused for multiple compilation units. /// </param> /// <param name="assemblyLoader"> /// Loads an assembly given an <see cref="AssemblyIdentity"/>. /// This callback is used for loading assemblies referenced by the compilation. /// <see cref="System.Reflection.Assembly.Load(AssemblyName)"/> is used if not specified. /// </param> /// <param name="assemblySymbolMapper"> /// Applied when converting assembly symbols to assembly references. /// <see cref="IAssemblySymbol"/> is mapped to its <see cref="IAssemblySymbol.Identity"/> by default. /// </param> /// <param name="cancellationToken">Can be used to cancel the emit process.</param> /// <param name="recoverOnError">If false the method returns an unsuccessful result instead of falling back to CCI writer.</param> /// <param name="compiledAssemblyImage">Assembly image, returned only if we fallback to CCI writer.</param> /// <param name="entryPoint">An entry point or null if not applicable or on failure.</param> /// <param name="diagnostics">Diagnostics.</param> /// <returns>True on success, false if a compilation error occurred or the compilation doesn't contain any code or declarations.</returns> /// <remarks> /// Reflection.Emit doesn't support all metadata constructs. If an unsupported construct is /// encountered a metadata writer that procudes uncollectible code is used instead. This is /// indicated by /// <see cref="ReflectionEmitResult.IsUncollectible"/> flag on the result. /// /// Reusing <see cref="System.Reflection.Emit.ModuleBuilder"/> may be beneficial in certain /// scenarios. For example, when emitting a sequence of code snippets one at a time (like in /// REPL). All the snippets can be compiled into a single module as long as the types being /// emitted have unique names. Reusing a single module/assembly reduces memory overhead. On /// the other hand, collectible assemblies are units of collection. Defining too many /// unrelated types in a single assemly might prevent the unused types to be collected. /// /// No need to provide a name override when using Reflection.Emit, since the assembly already /// exists. /// </remarks> /// <exception cref="InvalidOperationException">Referenced assembly can't be resolved.</exception> internal static bool Emit( this Compilation compilation, ModuleBuilder moduleBuilder, AssemblyLoader assemblyLoader, Func <IAssemblySymbol, AssemblyIdentity> assemblySymbolMapper, bool recoverOnError, DiagnosticBag diagnostics, CancellationToken cancellationToken, out MethodInfo entryPoint, out byte[] compiledAssemblyImage) { compiledAssemblyImage = default(byte[]); var moduleBeingBuilt = compilation.CreateModuleBuilder( emitOptions: EmitOptions.Default, manifestResources: null, assemblySymbolMapper: assemblySymbolMapper, testData: null, diagnostics: diagnostics, cancellationToken: cancellationToken); if (moduleBeingBuilt == null) { entryPoint = null; return(false); } if (!compilation.Compile( moduleBeingBuilt, win32Resources: null, xmlDocStream: null, generateDebugInfo: false, diagnostics: diagnostics, filterOpt: null, cancellationToken: cancellationToken)) { entryPoint = null; return(false); } Cci.IMethodReference cciEntryPoint = moduleBeingBuilt.EntryPoint; cancellationToken.ThrowIfCancellationRequested(); DiagnosticBag metadataDiagnostics = DiagnosticBag.GetInstance(); var context = new EmitContext((Cci.IModule)moduleBeingBuilt, null, metadataDiagnostics); // try emit via Reflection.Emit try { var referencedAssemblies = from referencedAssembly in compilation.GetBoundReferenceManager().GetReferencedAssemblies() let peReference = referencedAssembly.Key as PortableExecutableReference select KeyValuePair.Create( moduleBeingBuilt.Translate(referencedAssembly.Value, metadataDiagnostics), (peReference != null)?peReference.FilePath : null); entryPoint = ReflectionEmitter.Emit( context, referencedAssemblies, moduleBuilder, assemblyLoader ?? AssemblyLoader.Default, cciEntryPoint, cancellationToken); // translate metadata errors. return(compilation.FilterAndAppendAndFreeDiagnostics(diagnostics, ref metadataDiagnostics)); } catch (TypeLoadException) { // attempted to emit reference to a type that can't be loaded (has invalid metadata) } catch (NotSupportedException) { // nop } // TODO (tomat): // // Another possible approach would be to just return an error, that we can't emit via // Ref.Emit and let the user choose another method of emitting. For that we would want // to preserve the state of the Emit.Assembly object with all the compiled methods so // that the subsequent emit doesn't need to compile method bodies again. // TODO (tomat): // // If Ref.Emit fails to emit the code the type builders already created will stay // defined on the module builder. Ideally we would clean them up but Ref.Emit doesn't // provide any API to do so. In fact it also keeps baked TypeBuilders alive as well. if (!recoverOnError) { metadataDiagnostics.Free(); entryPoint = null; return(false); } using (var stream = new System.IO.MemoryStream()) { Cci.PeWriter.WritePeToStream( context, compilation.MessageProvider, stream, pdbWriterOpt: null, allowMissingMethodBodies: false, deterministic: false, cancellationToken: cancellationToken); compiledAssemblyImage = stream.ToArray(); } var compiledAssembly = Assembly.Load(compiledAssemblyImage); entryPoint = (cciEntryPoint != null) ? ReflectionEmitter.ResolveEntryPoint(compiledAssembly, cciEntryPoint, context) : null; // translate metadata errors. return(compilation.FilterAndAppendAndFreeDiagnostics(diagnostics, ref metadataDiagnostics)); }
public MethodImplementation(Cci.IMethodDefinition implementing, Cci.IMethodReference implemented) { this.implementing = implementing; this.implemented = implemented; }
internal void SetPEEntryPoint(IMethodSymbol method, DiagnosticBag diagnostics) { Debug.Assert(method == null || IsSourceDefinition((IMethodSymbol)method)); Debug.Assert(_outputKind.IsApplication()); _peEntryPoint = Translate(method, diagnostics, needDeclaration: true); }