Пример #1
0
        public static EmitResult Emit(
            this Compilation compilation,
            string outputPath,
            string?pdbPath            = null,
            string?xmlDocPath         = null,
            string?win32ResourcesPath = null,
            IEnumerable <ResourceDescription>?manifestResources = null,
            CancellationToken cancellationToken = default)
        {
            if (compilation == null)
            {
                throw new ArgumentNullException(nameof(compilation));
            }

            using (var outputStream = FileUtilities.CreateFileStreamChecked(File.Create, outputPath, nameof(outputPath)))
                using (var pdbStream = (pdbPath == null ? null : FileUtilities.CreateFileStreamChecked(File.Create, pdbPath, nameof(pdbPath))))
                    using (var xmlDocStream = (xmlDocPath == null ? null : FileUtilities.CreateFileStreamChecked(File.Create, xmlDocPath, nameof(xmlDocPath))))
                        using (var win32ResourcesStream = (win32ResourcesPath == null ? null : FileUtilities.CreateFileStreamChecked(File.OpenRead, win32ResourcesPath, nameof(win32ResourcesPath))))
                        {
                            return(compilation.Emit(
                                       outputStream,
                                       pdbStream: pdbStream,
                                       xmlDocumentationStream: xmlDocStream,
                                       win32Resources: win32ResourcesStream,
                                       manifestResources: manifestResources,
                                       options: new EmitOptions(pdbFilePath: pdbPath),
                                       cancellationToken: cancellationToken));
                        }
        }
        internal override Stream CreateInputStream()
        {
            var path = PortableShim.Path.GetTempFileName();
            Func <string, Stream> streamConstructor = lPath => new TempFileStream(lPath, PortableShim.FileStream.Create(lPath, PortableShim.FileMode.Create, PortableShim.FileAccess.ReadWrite, PortableShim.FileShare.ReadWrite));

            return(FileUtilities.CreateFileStreamChecked(streamConstructor, path));
        }
Пример #3
0
        /// <summary>
        /// Emit the IL for the compilation into the specified stream.
        /// </summary>
        /// <param name="compilation">Compilation.</param>
        /// <param name="outputPath">Path of the file to which the compilation will be written.</param>
        /// <param name="pdbPath">Path of the file to which the compilation's debug info will be written.
        /// Also embedded in the output file.  Null to forego PDB generation.
        /// </param>
        /// <param name="xmlDocPath">Path of the file to which the compilation's XML documentation will be written.  Null to forego XML generation.</param>
        /// <param name="win32ResourcesPath">Path of the file from which the compilation's Win32 resources will be read (in RES format).
        /// Null to indicate that there are none.</param>
        /// <param name="manifestResources">List of the compilation's managed resources.  Null to indicate that there are none.</param>
        /// <param name="cancellationToken">To cancel the emit process.</param>
        /// <exception cref="ArgumentNullException">Compilation or path is null.</exception>
        /// <exception cref="ArgumentException">Path is empty or invalid.</exception>
        /// <exception cref="IOException">An error occurred while reading or writing a file.</exception>
        public static EmitResult Emit(
            this Compilation compilation,
            string outputPath,
            string pdbPath            = null,
            string xmlDocPath         = null,
            string win32ResourcesPath = null,
            IEnumerable <ResourceDescription> manifestResources = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (compilation == null)
            {
                throw new ArgumentNullException("compilation");
            }

            using (var outputStream = FileUtilities.CreateFileStreamChecked(File.Create, outputPath, "outputPath"))
                using (var pdbStream = (pdbPath == null ? null : FileUtilities.CreateFileStreamChecked(File.Create, pdbPath, "pdbPath")))
                    using (var xmlDocStream = (xmlDocPath == null ? null : FileUtilities.CreateFileStreamChecked(File.Create, xmlDocPath, "xmlDocPath")))
                        using (var win32ResourcesStream = (win32ResourcesPath == null ? null : FileUtilities.CreateFileStreamChecked(File.OpenRead, win32ResourcesPath, "win32ResourcesPath")))
                        {
                            return(compilation.Emit(
                                       outputStream,
                                       outputName: null,
                                       pdbFilePath: pdbPath,
                                       pdbStream: pdbStream,
                                       xmlDocumentationStream: xmlDocStream,
                                       win32Resources: win32ResourcesStream,
                                       manifestResources: manifestResources,
                                       cancellationToken: cancellationToken));
                        }
        }
Пример #4
0
            /// <summary>
            /// Create the stream which should be used for Emit. This should only be called one time.
            /// </summary>
            private Stream?CreateStream(DiagnosticBag diagnostics)
            {
                RoslynDebug.Assert(_stream == null);
                RoslynDebug.Assert(diagnostics != null);

                if (diagnostics.HasAnyErrors())
                {
                    return(null);
                }

                _stream = _emitStreamProvider.GetOrCreateStream(diagnostics);
                if (_stream == null)
                {
                    return(null);
                }

                // If the current strong name provider is the Desktop version, signing can only be done to on-disk files.
                // If this binary is configured to be signed, create a temp file, output to that
                // then stream that to the stream that this method was called with. Otherwise output to the
                // stream that this method was called with.
                if (_emitStreamSignKind == EmitStreamSignKind.SignedWithFile)
                {
                    RoslynDebug.Assert(_strongNameProvider != null);

                    Stream tempStream;
                    string tempFilePath;
                    try
                    {
                        var fileSystem = _strongNameProvider.FileSystem;
                        Func <string, Stream> streamConstructor = path =>
                                                                  fileSystem.CreateFileStream(
                            path,
                            FileMode.Create,
                            FileAccess.ReadWrite,
                            FileShare.ReadWrite
                            );

                        var tempDir = fileSystem.GetTempPath();
                        tempFilePath = Path.Combine(tempDir, Guid.NewGuid().ToString("N"));
                        tempStream   = FileUtilities.CreateFileStreamChecked(
                            streamConstructor,
                            tempFilePath
                            );
                    }
                    catch (IOException e)
                    {
                        throw new Cci.PeWritingException(e);
                    }

                    _tempInfo = (tempStream, tempFilePath);
                    return(tempStream);
                }
                else
                {
                    return(_stream);
                }
            }
        /// <exception cref="IOException"></exception>
        internal override Stream CreateInputStream()
        {
            Func <string, Stream> streamConstructor = lPath => new TempFileStream(lPath,
                                                                                  new FileStream(lPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));

            string tempPath = _tempPath ?? Path.GetTempPath();
            string tempName = Path.Combine(tempPath, Guid.NewGuid().ToString("N"));

            return(FileUtilities.CreateFileStreamChecked(streamConstructor, tempName));
        }
Пример #6
0
        private ComHandle <EnvDTE80.FileCodeModel2, FileCodeModel> GetFileCodeModel(object location)
        {
            if (location is string locationString)
            {
                var vsProject      = _parentHandle.Value;
                var vsProjectItems = vsProject.ProjectItems;

                if (vsProjectItems == null)
                {
                    throw Exceptions.ThrowEFail();
                }

                var project          = GetProject();
                var projectDirectory = Path.GetDirectoryName(project.FilePath);
                var absoluteFilePath = Path.GetFullPath(
                    Path.Combine(projectDirectory, locationString)
                    );

                var foundFile = false;
                foreach (var documentId in project.DocumentIds)
                {
                    var document = project.GetDocument(documentId);
                    if (
                        document.FilePath != null &&
                        string.Equals(
                            absoluteFilePath,
                            document.FilePath,
                            StringComparison.OrdinalIgnoreCase
                            )
                        )
                    {
                        foundFile = true;
                        break;
                    }
                }

                if (!foundFile)
                {
                    // File doesn't belong to the project, prepare & add it to project
                    using (FileUtilities.CreateFileStreamChecked(File.Create, absoluteFilePath))
                    {
                        // Note: We just want to create an empty file here, so we immediately close it.
                    }

                    vsProjectItems.AddFromFile(absoluteFilePath);
                }

                return(this.State.ProjectCodeModelFactory
                       .GetProjectCodeModel(_projectId)
                       .GetOrCreateFileCodeModel(absoluteFilePath));
            }

            throw Exceptions.ThrowEInvalidArg();
        }
Пример #7
0
        private ComHandle <EnvDTE80.FileCodeModel2, FileCodeModel> GetFileCodeModel(object location)
        {
            if (location is string)
            {
                var vsProject      = (EnvDTE.Project)_parentHandle.Value;
                var vsProjectItems = vsProject.ProjectItems;

                if (vsProjectItems == null)
                {
                    throw Exceptions.ThrowEFail();
                }

                var locationString = (string)location;

                var project          = GetProject();
                var projectDirectory = Path.GetDirectoryName(project.FilePath);
                var absoluteFilePath = Path.GetFullPath(Path.Combine(projectDirectory, locationString));

                string fileName = null;
                foreach (var documentId in project.DocumentIds)
                {
                    var document = project.GetDocument(documentId);
                    if (document.FilePath != null && string.Equals(absoluteFilePath, document.FilePath, StringComparison.OrdinalIgnoreCase))
                    {
                        var vsProjectItem = vsProjectItems.Item(Path.GetFileName(locationString));
                        fileName = vsProjectItem.get_FileNames(1);
                    }
                }

                if (fileName == null)
                {
                    // File doesn't belong to the project, prepare & add it to project
                    using (FileUtilities.CreateFileStreamChecked(File.Create, absoluteFilePath))
                    {
                        // Note: We just want to create an empty file here, so we immediately close it.
                    }

                    vsProjectItems.AddFromFile(absoluteFilePath);
                    fileName = absoluteFilePath;
                }

                var hostProject      = ((VisualStudioWorkspaceImpl)Workspace).ProjectTracker.GetProject(_projectId);
                var projectCodeModel = ((IProjectCodeModelProvider)hostProject).ProjectCodeModel;
                return(projectCodeModel.GetFileCodeModelInstance(fileName).Value);
            }
            else
            {
                throw Exceptions.ThrowEInvalidArg();
            }
        }
Пример #8
0
        public async Task <bool> CompileAsync(IWorkspaceProjectContext context, string outputFileName, ISet <string> filesToInclude, CancellationToken cancellationToken)
        {
            if (filesToInclude == null || filesToInclude.Count == 0)
            {
                throw new ArgumentException(nameof(filesToInclude), "Must specify some files to compile.");
            }
            if (outputFileName == null)
            {
                throw new ArgumentException(nameof(outputFileName), "Must specify an output file name.");
            }

            var project = _workspace.CurrentSolution.GetProject(context.Id);

            // Remove all files except the ones we care about
            var documents = project.Documents;

            foreach (var document in documents)
            {
                if (!filesToInclude.Contains(document.FilePath))
                {
                    project = project.RemoveDocument(document.Id);
                }

                cancellationToken.ThrowIfCancellationRequested();
            }

            var options = project.LanguageServices.GetRequiredService <ICompilationFactoryService>().GetDefaultCompilationOptions()
                          // copied from the old TempPE compiler used by legacy, for parity.
                          // See: https://github.com/dotnet/roslyn/blob/fab7134296816fc80019c60b0f5bef7400cf23ea/src/VisualStudio/CSharp/Impl/ProjectSystemShim/TempPECompilerService.cs#L58
                          .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
                          .WithSourceReferenceResolver(SourceFileResolver.Default)
                          .WithXmlReferenceResolver(XmlFileResolver.Default)
                          // we always want to produce a DLL
                          .WithOutputKind(OutputKind.DynamicallyLinkedLibrary);

            project = project.WithCompilationOptions(options);

            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            var outputPath = Path.GetDirectoryName(outputFileName);

            Directory.CreateDirectory(outputPath);

            using (var file = FileUtilities.CreateFileStreamChecked(File.Create, outputFileName, nameof(outputFileName)))
            {
                return(compilation.Emit(file, cancellationToken: cancellationToken).Success);
            }
        }
Пример #9
0
        public async Task <bool> CompileAsync(IWorkspaceProjectContext context, string outputFileName, ISet <string> filesToInclude, CancellationToken cancellationToken)
        {
            if (filesToInclude == null || filesToInclude.Count == 0)
            {
                throw new ArgumentException(nameof(filesToInclude), "Must specify some files to compile.");
            }
            if (outputFileName == null)
            {
                throw new ArgumentException(nameof(outputFileName), "Must specify an output file name.");
            }

            var project = _workspace.CurrentSolution.GetProject(context.Id);

            // Remove all files except the ones we care about
            var documents = project.Documents;

            foreach (var document in documents)
            {
                if (!filesToInclude.Contains(document.FilePath))
                {
                    project = project.RemoveDocument(document.Id);
                }

                cancellationToken.ThrowIfCancellationRequested();
            }

            // We need to inherit most of the projects options, mainly for VB (RootNamespace, GlobalImports etc.), but we need to override about some specific things surrounding the output
            var options = project.CompilationOptions
                          // copied from the old TempPE compiler used by legacy, for parity.
                          // See: https://github.com/dotnet/roslyn/blob/fab7134296816fc80019c60b0f5bef7400cf23ea/src/VisualStudio/CSharp/Impl/ProjectSystemShim/TempPECompilerService.cs#L58
                          .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
                          .WithSourceReferenceResolver(SourceFileResolver.Default)
                          .WithXmlReferenceResolver(XmlFileResolver.Default)
                          // We always want to produce a debug, AnyCPU DLL
                          .WithOutputKind(OutputKind.DynamicallyLinkedLibrary)
                          .WithPlatform(Platform.AnyCpu)
                          .WithOptimizationLevel(OptimizationLevel.Debug)
                          // Turn off any warnings as errors just in case
                          .WithGeneralDiagnosticOption(ReportDiagnostic.Suppress)
                          .WithReportSuppressedDiagnostics(false)
                          .WithSpecificDiagnosticOptions(null)
                          // Turn off any signing and strong naming
                          .WithDelaySign(false)
                          .WithCryptoKeyFile(null)
                          .WithPublicSign(false)
                          .WithStrongNameProvider(null);

            project = project
                      .WithCompilationOptions(options)
                      // AssemblyName should be set to the filename of the output file because multiple TempPE DLLs can be created for the same project
                      .WithAssemblyName(Path.GetFileName(outputFileName));

            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();

            var outputPath = Path.GetDirectoryName(outputFileName);

            Directory.CreateDirectory(outputPath);

            using (var file = FileUtilities.CreateFileStreamChecked(File.Create, outputFileName, nameof(outputFileName)))
            {
                return(compilation.Emit(file, cancellationToken: cancellationToken).Success);
            }
        }