public MetadataFileReference(string fullPath, MetadataReferenceProperties properties, DocumentationProvider documentation = null)
     : base(properties, fullPath, initialDocumentation: documentation ?? DocumentationProvider.Default)
 {
     if (fullPath == null)
     {
         throw new ArgumentNullException("fullPath");
     }
 }
 protected PortableExecutableReference(
     MetadataReferenceProperties properties,
     string fullPath = null,
     DocumentationProvider initialDocumentation = null)
     : base(properties)
 {
     _filePath = fullPath;
     _lazyDocumentation = initialDocumentation;
 }
        public MetadataReference CreateReference(ImmutableArray<string> aliases, bool embedInteropTypes, DocumentationProvider documentationProvider)
        {
            if (this.IsEmpty)
            {
                return null;
            }

            // first see whether we can use native memory directly.
            var stream = _storage.ReadStream();
            var supportNativeMemory = stream as ISupportDirectMemoryAccess;
            if (supportNativeMemory != null)
            {
                // this is unfortunate that if we give stream, compiler will just re-copy whole content to 
                // native memory again. this is a way to get around the issue by we getting native memory ourselves and then
                // give them pointer to the native memory. also we need to handle lifetime ourselves.
                var metadata = AssemblyMetadata.Create(ModuleMetadata.CreateFromImage(supportNativeMemory.GetPointer(), (int)stream.Length));

                var referenceWithNativeMemory = metadata.GetReference(
                    documentation: documentationProvider,
                    aliases: aliases,
                    embedInteropTypes: embedInteropTypes,
                    display: _assemblyName);

                // tie lifetime of stream to metadata reference we created. native memory's lifetime is tied to
                // stream internally and stream is shared between same temporary storage. so here, we should be 
                // sharing same native memory for all skeleton assemblies from same project snapshot.
                s_lifetime.GetValue(referenceWithNativeMemory, _ => stream);

                return referenceWithNativeMemory;
            }

            // Otherwise, we just let it use stream. Unfortunately, if we give stream, compiler will
            // internally copy it to native memory again. since compiler owns lifetime of stream,
            // it would be great if compiler can be little bit smarter on how it deals with stream.

            // We don't deterministically release the resulting metadata since we don't know 
            // when we should. So we leave it up to the GC to collect it and release all the associated resources.
            var metadataFromStream = AssemblyMetadata.CreateFromStream(stream);

            return metadataFromStream.GetReference(
                documentation: documentationProvider,
                aliases: aliases,
                embedInteropTypes: embedInteropTypes,
                display: _assemblyName);
        }
        protected PortableExecutableReference(
            MetadataReferenceProperties properties,
            string fullPath = null,
            DocumentationProvider initialDocumentation = null)
            : base(properties)
        {
            // TODO: remove full path normalization
            if (fullPath != null)
            {
                CompilerPathUtilities.RequireAbsolutePath(fullPath, "fullPath");

                try
                {
                    this.fullPath = Path.GetFullPath(fullPath);
                }
                catch (Exception e)
                {
                    throw new ArgumentException(e.Message, "fullPath");
                }
            }

            this.lazyDocumentation = initialDocumentation;
        }
Example #5
0
 private MetadataImageReference(Metadata metadata, DocumentationProvider documentation, MetadataReferenceProperties properties, string fullPath, string display)
     : base(properties, fullPath, documentation ?? DocumentationProvider.Default)
 {
     this.display  = display;
     this.metadata = metadata;
 }
Example #6
0
 /// <summary>
 /// Creates a reference to the module metadata.
 /// </summary>
 /// <param name="documentation">Provider of XML documentation comments for the metadata symbols contained in the module.</param>
 /// <param name="filePath">Path describing the location of the metadata, or null if the metadata have no location.</param>
 /// <param name="display">Display string used in error messages to identity the reference.</param>
 /// <returns>A reference to the module metadata.</returns>
 public PortableExecutableReference GetReference(DocumentationProvider documentation = null, string filePath = null, string display = null)
 {
     return new MetadataImageReference(this, MetadataReferenceProperties.Module, documentation, filePath, display);
 }
        /// <summary>
        /// Creates a reference to a loaded assembly.
        /// </summary>
        /// <param name="assembly">Path to the module file.</param>
        /// <param name="properties">Reference properties (extern aliases, type embedding).</param>
        /// <param name="documentation">Provides XML documentation for symbol found in the reference.</param>
        /// <exception cref="ArgumentNullException"><paramref name="assembly"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="properties"/>.<see cref="MetadataReferenceProperties.Kind"/> is not <see cref="MetadataImageKind.Assembly"/>.</exception>
        /// <exception cref="NotSupportedException"><paramref name="assembly"/> is dynamic, doesn't have a location, or the platform doesn't support reading from the location.</exception>
        /// <remarks>
        /// Performance considerations:
        /// <para>
        /// It is recommended to use <see cref="AssemblyMetadata.CreateFromFile(string)"/> API when creating multiple references to the same assembly.
        /// Reusing <see cref="AssemblyMetadata"/> object allows for sharing data accross these references.
        /// </para>
        /// </remarks>
        public static MetadataReference CreateFromAssembly(
            Assembly assembly,
            MetadataReferenceProperties properties,
            DocumentationProvider documentation = null)
        {
            // Note: returns MetadataReference and not PortableExecutableReference so that we can in future support assemblies that
            // which are not backed by PE image.

            if (assembly == null)
            {
                throw new ArgumentNullException(nameof(assembly));
            }

            if (assembly.IsDynamic)
            {
                throw new NotSupportedException(CodeAnalysisResources.CantCreateReferenceToDynamicAssembly);
            }

            if (properties.Kind != MetadataImageKind.Assembly)
            {
                throw new ArgumentException(CodeAnalysisResources.CantCreateModuleReferenceToAssembly, nameof(properties));
            }

            string location = AssemblyLocationLightUp.GetAssemblyLocation(assembly);
            Stream peStream = FileStreamLightUp.OpenFileStream(location);

            // The file is locked by the CLR assembly loader, so we can create a lazily read metadata, 
            // which might also lock the file until the reference is GC'd.
            var metadata = AssemblyMetadata.CreateFromStream(peStream);

            return metadata.GetReference(filePath: location);
        }
        /// <summary>
        /// Creates a reference to an assembly or standalone module stored in a file.
        /// Reads the content of the file into memory.
        /// </summary>
        /// <param name="path">Path to the assembly file.</param>
        /// <param name="properties">Reference properties (extern aliases, type embedding, <see cref="MetadataImageKind"/>).</param>
        /// <param name="documentation">Provides XML documentation for symbol found in the reference.</param>
        /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="path"/> is invalid.</exception>
        /// <exception cref="IOException">An error occurred while reading the file.</exception>
        /// <remarks>
        /// Performance considerations:
        /// <para>
        /// It is recommended to use <see cref="AssemblyMetadata.CreateFromFile(string)"/> or <see cref="ModuleMetadata.CreateFromFile(string)"/> 
        /// API when creating multiple references to the same file.
        /// Reusing <see cref="Metadata"/> object allows for sharing data accross these references.
        /// </para> 
        /// <para>
        /// The method eagerly reads the entire content of the file into native heap. The native memory block is released 
        /// when the resulting reference becomes unreachable and GC collects it. To decrease memory footprint of the reference and/or manage
        /// the lifetime deterministically use <see cref="AssemblyMetadata.CreateFromFile(string)"/> 
        /// to create an <see cref="IDisposable"/> metadata object and 
        /// <see cref="AssemblyMetadata.GetReference(DocumentationProvider, ImmutableArray{string}, bool, string, string)"/> 
        /// to get a reference to it.
        /// </para>
        /// </remarks>
        public static PortableExecutableReference CreateFromFile(
            string path,
            MetadataReferenceProperties properties = default(MetadataReferenceProperties),
            DocumentationProvider documentation = null)
        {
            var peStream = FileStreamLightUp.OpenFileStream(path);

            // prefetch image, close stream to avoid locking it:
            var module = ModuleMetadata.CreateFromStream(peStream, PEStreamOptions.PrefetchEntireImage);

            if (properties.Kind == MetadataImageKind.Module)
            {
                return module.GetReference(documentation, path);
            }

            // any additional modules constituting the assembly will be read lazily:
            var assemblyMetadata = AssemblyMetadata.CreateFromFile(module, path);

            return assemblyMetadata.GetReference(documentation, properties.Aliases, properties.EmbedInteropTypes, path);
        }
        /// <summary>
        /// Creates a reference to a single-module assembly or a stand-alone module from data in specified stream. 
        /// Reads the content of the stream into memory and closes the stream upon return.
        /// </summary>
        /// <param name="peStream">Assembly image.</param>
        /// <param name="properties">Reference properties (extern aliases, type embedding, <see cref="MetadataImageKind"/>).</param>
        /// <param name="documentation">Provides XML documentation for symbol found in the reference.</param>
        /// <param name="filePath">Optional path that describes the location of the metadata. The file doesn't need to exist on disk. The path is opaque to the compiler.</param>
        /// <exception cref="ArgumentException"><paramref name="peStream"/> doesn't support read and seek operations.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="peStream"/> is null.</exception>
        /// <exception cref="IOException">An error occurred while reading the stream.</exception>
        /// <remarks>
        /// Performance considerations: 
        /// <para>
        /// It is recommended to use <see cref="AssemblyMetadata.CreateFromStream(Stream, PEStreamOptions)"/> or <see cref="ModuleMetadata.CreateFromStream(Stream, PEStreamOptions)"/> 
        /// API when creating multiple references to the same metadata.
        /// Reusing <see cref="Metadata"/> object to create multiple references allows for sharing data accross these references.
        /// </para> 
        /// <para>
        /// The method eagerly reads the entire content of <paramref name="peStream"/> into native heap. The native memory block is released 
        /// when the resulting reference becomes unreachable and GC collects it. To decrease memory footprint of the reference and/or manage
        /// the lifetime deterministically use <see cref="AssemblyMetadata.CreateFromStream(Stream, PEStreamOptions)"/> 
        /// to create an <see cref="IDisposable"/> metadata object and 
        /// <see cref="AssemblyMetadata.GetReference(DocumentationProvider, ImmutableArray{string}, bool, string, string)"/> to get a reference to it.
        /// to get a reference to it.
        /// </para>
        /// </remarks>
        public static PortableExecutableReference CreateFromStream(
            Stream peStream,
            MetadataReferenceProperties properties = default(MetadataReferenceProperties),
            DocumentationProvider documentation = null,
            string filePath = null)
        {
            // Prefetch data and close the stream. 
            var metadata = AssemblyMetadata.CreateFromStream(peStream, PEStreamOptions.PrefetchEntireImage);

            return new MetadataImageReference(metadata, properties, documentation, filePath, display: null);
        }
 /// <summary>
 /// Creates a reference to a single-module assembly or a standalone module stored in memory.
 /// </summary>
 /// <param name="peImage">Assembly image.</param>
 /// <param name="properties">Reference properties (extern aliases, type embedding, <see cref="MetadataImageKind"/>).</param>
 /// <param name="documentation">Provides XML documentation for symbol found in the reference.</param>
 /// <param name="filePath">Optional path that describes the location of the metadata. The file doesn't need to exist on disk. The path is opaque to the compiler.</param>
 /// <remarks>
 /// Performance considerations: 
 /// <para>
 /// It is recommended to use <see cref="AssemblyMetadata.CreateFromImage(IEnumerable{byte})"/> or <see cref="ModuleMetadata.CreateFromImage(IEnumerable{byte})"/> 
 /// API when creating multiple references to the same metadata.
 /// Reusing <see cref="Metadata"/> object to create multiple references allows for sharing data accross these references.
 /// </para> 
 /// <para>
 /// The method makes a copy of the data and pins it. To avoid making a copy use an overload that takes an <see cref="ImmutableArray{T}"/>.
 /// The pinned memory is released when the resulting reference becomes unreachable and GC collects it. To control the lifetime of the pinned memory 
 /// deterministically use <see cref="AssemblyMetadata.CreateFromStream(Stream, PEStreamOptions)"/> 
 /// to create an <see cref="IDisposable"/> metadata object and 
 /// <see cref="AssemblyMetadata.GetReference(DocumentationProvider, ImmutableArray{string}, bool, string, string)"/> to get a reference to it.
 /// to get a reference to it.
 /// </para>
 /// </remarks>
 /// <exception cref="ArgumentNullException"><paramref name="peImage"/> is null.</exception>
 public static PortableExecutableReference CreateFromImage(
     IEnumerable<byte> peImage,
     MetadataReferenceProperties properties = default(MetadataReferenceProperties),
     DocumentationProvider documentation = null,
     string filePath = null)
 {
     var metadata = AssemblyMetadata.CreateFromImage(peImage);
     return new MetadataImageReference(metadata, properties, documentation, filePath, display: null);
 }
Example #11
0
 internal MetadataImageReference(Metadata metadata, MetadataReferenceProperties properties, DocumentationProvider documentation, string filePath, string display)
     : base(properties, filePath, documentation ?? DocumentationProvider.Default)
 {
     _display = display;
     _metadata = metadata;
 }
Example #12
0
 /// <summary>
 /// Creates a reference to a single-module assembly image.
 /// </summary>
 /// <param name="assemblyImage">Read-only assembly image.</param>
 /// <param name="documentation">Provides XML documentation for symbol found in the reference.</param>
 /// <param name="aliases">Reference aliases.</param>
 /// <param name="embedInteropTypes">True if interop types contained in the reference should be embedded to the compilation that uses the reference.</param>
 /// <param name="fullPath">Optional full path used for reference comparison when used in compilation. The file doesn't need to exist.</param>
 /// <param name="display">Display string for error reporting.</param>
 public MetadataImageReference(ImmutableArray <byte> assemblyImage, DocumentationProvider documentation = null, ImmutableArray <string> aliases = default(ImmutableArray <string>), bool embedInteropTypes = false, string fullPath = null, string display = null)
     : this(AssemblyMetadata.CreateFromImage(RequireNonNull(assemblyImage, "assemblyImage")), documentation, aliases, embedInteropTypes, fullPath, display)
 {
 }
 public MetadataFileReference(string fullPath, MetadataImageKind kind = MetadataImageKind.Assembly, ImmutableArray<string> aliases = default(ImmutableArray<string>), bool embedInteropTypes = false, DocumentationProvider documentation = null)
     : this(fullPath, new MetadataReferenceProperties(kind, aliases, embedInteropTypes), documentation)
 {
 }
Example #14
0
 public static MetadataReference CreateFromAssembly(
     Assembly assembly,
     MetadataReferenceProperties properties,
     DocumentationProvider documentation = null)
 {
     return CreateFromAssemblyInternal(assembly, properties, documentation);
 }
Example #15
0
 /// <summary>
 /// Creates a reference to the assembly metadata.
 /// </summary>
 /// <param name="documentation">Provider of XML documentation comments for the metadata symbols contained in the module.</param>
 /// <param name="aliases">Aliases that can be used to refer to the assembly from source code (see "extern alias" directive in C#).</param>
 /// <param name="embedInteropTypes">True to embed interop types from the referenced assembly to the referencing compilation. Must be false for a module.</param>
 /// <param name="filePath">Path describing the location of the metadata, or null if the metadata have no location.</param>
 /// <param name="display">Display string used in error messages to identity the reference.</param>
 /// <returns>A reference to the assembly metadata.</returns>
 public PortableExecutableReference GetReference(
     DocumentationProvider documentation = null,
     ImmutableArray<string> aliases = default(ImmutableArray<string>),
     bool embedInteropTypes = false,
     string filePath = null,
     string display = null)
 {
     return new MetadataImageReference(this, new MetadataReferenceProperties(MetadataImageKind.Assembly, aliases, embedInteropTypes), documentation, filePath, display);
 }
Example #16
0
        internal static MetadataReference CreateFromAssemblyInternal(
            Assembly assembly,
            MetadataReferenceProperties properties,
            DocumentationProvider documentation = null)
        {
            // Note: returns MetadataReference and not PortableExecutableReference so that we can in future support assemblies that
            // which are not backed by PE image.

            if (assembly == null)
            {
                throw new ArgumentNullException(nameof(assembly));
            }

            if (assembly.IsDynamic)
            {
                throw new NotSupportedException(CodeAnalysisResources.CantCreateReferenceToDynamicAssembly);
            }

            if (properties.Kind != MetadataImageKind.Assembly)
            {
                throw new ArgumentException(CodeAnalysisResources.CantCreateModuleReferenceToAssembly, nameof(properties));
            }

            string location = CorLightup.Desktop.GetAssemblyLocation(assembly);
            if (string.IsNullOrEmpty(location))
            {
                throw new NotSupportedException(CodeAnalysisResources.CantCreateReferenceToAssemblyWithoutLocation);
            }

            Stream peStream = FileUtilities.OpenFileStream(location);

            // The file is locked by the CLR assembly loader, so we can create a lazily read metadata, 
            // which might also lock the file until the reference is GC'd.
            var metadata = AssemblyMetadata.CreateFromStream(peStream);

            return new MetadataImageReference(metadata, properties, documentation, location, display: null);
        }
Example #17
0
        public MetadataReference CreateReference(ImmutableArray<string> aliases, bool embedInteropTypes, DocumentationProvider documentationProvider)
        {
            if (this.IsEmpty)
            {
                return null;
            }

            // first see whether we can use native memory directly.
            var stream = _storage.ReadStream();
            var supportNativeMemory = stream as ISupportDirectMemoryAccess;
            AssemblyMetadata metadata;

            if (supportNativeMemory != null)
            {
                // this is unfortunate that if we give stream, compiler will just re-copy whole content to 
                // native memory again. this is a way to get around the issue by we getting native memory ourselves and then
                // give them pointer to the native memory. also we need to handle lifetime ourselves.
                metadata = AssemblyMetadata.Create(ModuleMetadata.CreateFromImage(supportNativeMemory.GetPointer(), (int)stream.Length));

                // Tie lifetime of stream to metadata we created. It is important to tie this to the Metadata and not the
                // metadata reference, as PE symbols hold onto just the Metadata. We can use Add here since we created
                // a brand new object in AssemblyMetadata.Create above.
                s_lifetime.Add(metadata, supportNativeMemory);
            }
            else
            { 
                // Otherwise, we just let it use stream. Unfortunately, if we give stream, compiler will
                // internally copy it to native memory again. since compiler owns lifetime of stream,
                // it would be great if compiler can be little bit smarter on how it deals with stream.

                // We don't deterministically release the resulting metadata since we don't know 
                // when we should. So we leave it up to the GC to collect it and release all the associated resources.
                metadata = AssemblyMetadata.CreateFromStream(stream);
            }

            return metadata.GetReference(
                documentation: documentationProvider,
                aliases: aliases,
                embedInteropTypes: embedInteropTypes,
                display: _assemblyName);
        }
Example #18
0
        internal PEAssemblySymbol(PEAssembly assembly, DocumentationProvider documentationProvider, bool isLinked, MetadataImportOptions importOptions)
        {
            Debug.Assert(assembly != null);
            Debug.Assert(documentationProvider != null);

            _assembly = assembly;
            _documentationProvider = documentationProvider;

            var modules = new ModuleSymbol[assembly.Modules.Length];

            for (int i = 0; i < assembly.Modules.Length; i++)
            {
                modules[i] = new PEModuleSymbol(this, assembly.Modules[i], importOptions, i);
            }

            _modules = modules.AsImmutableOrNull();
            _isLinked = isLinked;

            if (IsPchpCor(assembly))
            {
                _specialAssembly = SpecialAssembly.PchpCorLibrary;

                // initialize CoreTypes
                this.PrimaryModule.GlobalNamespace.GetTypeMembers();
            }
            else if (assembly.Identity.Name == "System.Runtime")
            {
                _specialAssembly = SpecialAssembly.CorLibrary;
            }
            else if (assembly.AssemblyReferences.Length == 0 && assembly.DeclaresTheObjectClass)
            {
                _specialAssembly = SpecialAssembly.CorLibrary;
            }
            else
            {
                // extension assembly ?
                //var attrs = this.GetAttributes();
            }
        }