示例#1
0
        /// <summary>
        /// Creates new compilation options from parsed command line arguments, with additional workspace specific options appended.
        /// It is expected that derived types which need to add more specific options will fetch the base options and override those options.
        /// </summary>
        protected virtual CompilationOptions CreateCompilationOptions(CommandLineArguments commandLineArguments, ParseOptions newParseOptions)
        {
            Contract.ThrowIfNull(commandLineArguments);

            // Get options from command line arguments.
            var options = commandLineArguments.CompilationOptions;

            // Now set the default workspace options (these are not set by the command line parser).
            string projectDirectory = this.ContainingDirectoryPathOpt;

            // TODO: #r support, should it include bin path?
            var referenceSearchPaths = ImmutableArray <string> .Empty;

            // TODO: #load support
            var sourceSearchPaths = ImmutableArray <string> .Empty;

            MetadataReferenceResolver referenceResolver;

            if (Workspace != null)
            {
                referenceResolver = new WorkspaceMetadataFileReferenceResolver(
                    Workspace.CurrentSolution.Services.MetadataService,
                    new RelativePathResolver(referenceSearchPaths, projectDirectory));
            }
            else
            {
                // can only happen in tests
                referenceResolver = null;
            }

            // Explicitly disable concurrent build.
            options = options.WithConcurrentBuild(concurrent: false);

            // Set default resolvers.
            options = options.WithMetadataReferenceResolver(referenceResolver)
                      .WithXmlReferenceResolver(new XmlFileResolver(projectDirectory))
                      .WithSourceReferenceResolver(new SourceFileResolver(sourceSearchPaths, projectDirectory))
                      .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
                      .WithStrongNameProvider(new DesktopStrongNameProvider(GetStrongNameKeyPaths()));

            return(options);
        }
示例#2
0
        /// <summary>
        /// Creates new compilation options from parsed command line arguments, with additional workspace specific options appended.
        /// It is expected that derived types which need to add more specific options will fetch the base options and override those options.
        /// </summary>
        protected virtual CompilationOptions CreateCompilationOptions(CommandLineArguments commandLineArguments, ParseOptions newParseOptions)
        {
            Contract.ThrowIfNull(commandLineArguments);

            // Get options from command line arguments.
            var options = commandLineArguments.CompilationOptions;

            // Now set the default workspace options (these are not set by the command line parser).
            string projectDirectory = this.ContainingDirectoryPathOpt;

            // TODO: #r support, should it include bin path?
            var referenceSearchPaths = ImmutableArray<string>.Empty;

            // TODO: #load support
            var sourceSearchPaths = ImmutableArray<string>.Empty;

            MetadataReferenceResolver referenceResolver;
            if (Workspace != null)
            {
                referenceResolver = new WorkspaceMetadataFileReferenceResolver(
                    Workspace.CurrentSolution.Services.MetadataService,
                    new RelativePathResolver(referenceSearchPaths, projectDirectory));
            }
            else
            {
                // can only happen in tests
                referenceResolver = null;
            }

            // Explicitly disable concurrent build.
            options = options.WithConcurrentBuild(concurrent: false);

            // Set default resolvers.
            options = options.WithMetadataReferenceResolver(referenceResolver)
                .WithXmlReferenceResolver(new XmlFileResolver(projectDirectory))
                .WithSourceReferenceResolver(new SourceFileResolver(sourceSearchPaths, projectDirectory))
                .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
                .WithStrongNameProvider(new DesktopStrongNameProvider(GetStrongNameKeyPaths()));

            return options;
        }
        public int CompileTempPE(string pszOutputFileName, int sourceCount, string[] fileNames, string[] fileContents, int optionCount, string[] optionNames, object[] optionValues)
        {
            var baseDirectory = Path.GetDirectoryName(pszOutputFileName);
            var parsedArguments = ParseCommandLineArguments(baseDirectory, optionNames, optionValues);

            Contract.ThrowIfFalse(fileNames.Length == fileContents.Length);

            var trees = new List<SyntaxTree>(capacity: sourceCount);

            for (int i = 0; i < fileNames.Length; i++)
            {
                // create a parse tree w/o encoding - the tree won't be used to emit PDBs
                trees.Add(SyntaxFactory.ParseSyntaxTree(fileContents[i], parsedArguments.ParseOptions, fileNames[i]));
            }

            // TODO (tomat): Revisit compilation options: app.config, strong name, search paths, etc? (bug #869604)
            // TODO (tomat): move resolver initialization (With* methods below) to CommandLineParser.Parse

            var metadataResolver = new WorkspaceMetadataFileReferenceResolver(
                _metadataService,
                new RelativePathResolver(ImmutableArray<string>.Empty, baseDirectory: null));

            var compilation = CSharpCompilation.Create(
                Path.GetFileName(pszOutputFileName),
                trees,
                parsedArguments.ResolveMetadataReferences(metadataResolver).Where(m => !(m is UnresolvedMetadataReference)),
                parsedArguments.CompilationOptions
                    .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
                    .WithSourceReferenceResolver(SourceFileResolver.Default)
                    .WithXmlReferenceResolver(XmlFileResolver.Default)
                    .WithMetadataReferenceResolver(metadataResolver));

            var result = compilation.Emit(pszOutputFileName);

            return result.Success ? VSConstants.S_OK : VSConstants.S_FALSE;
        }
        public int CompileTempPE(string pszOutputFileName, int sourceCount, string[] fileNames, string[] fileContents, int optionCount, string[] optionNames, object[] optionValues)
        {
            var baseDirectory   = Path.GetDirectoryName(pszOutputFileName);
            var parsedArguments = ParseCommandLineArguments(baseDirectory, optionNames, optionValues);

            Contract.ThrowIfFalse(fileNames.Length == fileContents.Length);

            var trees = new List <SyntaxTree>(capacity: sourceCount);

            for (int i = 0; i < fileNames.Length; i++)
            {
                // create a parse tree w/o encoding - the tree won't be used to emit PDBs
                trees.Add(SyntaxFactory.ParseSyntaxTree(fileContents[i], parsedArguments.ParseOptions, fileNames[i]));
            }

            // TODO (tomat): Revisit compilation options: app.config, strong name, search paths, etc? (bug #869604)
            // TODO (tomat): move resolver initialization (With* methods below) to CommandLineParser.Parse

            var metadataResolver = new WorkspaceMetadataFileReferenceResolver(
                _metadataService,
                new RelativePathResolver(ImmutableArray <string> .Empty, baseDirectory: null));

            var compilation = CSharpCompilation.Create(
                Path.GetFileName(pszOutputFileName),
                trees,
                parsedArguments.ResolveMetadataReferences(metadataResolver).Where(m => !(m is UnresolvedMetadataReference)),
                parsedArguments.CompilationOptions
                .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
                .WithSourceReferenceResolver(SourceFileResolver.Default)
                .WithXmlReferenceResolver(XmlFileResolver.Default)
                .WithMetadataReferenceResolver(metadataResolver));

            var result = compilation.Emit(pszOutputFileName);

            return(result.Success ? VSConstants.S_OK : VSConstants.S_FALSE);
        }
示例#5
0
        private async Task <ProjectId> LoadProjectAsync(string projectFilePath, IProjectFileLoader loader, bool preferMetadata, LoadState loadedProjects, CancellationToken cancellationToken)
        {
            Debug.Assert(projectFilePath != null);
            Debug.Assert(loader != null);

            var projectId   = loadedProjects.GetOrCreateProjectId(projectFilePath);
            var projectName = Path.GetFileNameWithoutExtension(projectFilePath);

            var projectFile = await loader.LoadProjectFileAsync(projectFilePath, _properties, cancellationToken).ConfigureAwait(false);

            if (projectFile.ErrorMessage != null)
            {
                ReportFailure(ReportMode.Log, GetMsbuildFailedMessage(projectFilePath, projectFile.ErrorMessage));

                // if we failed during load there won't be any project file info, so bail early with empty project.
                loadedProjects.Add(CreateEmptyProjectInfo(projectId, projectFilePath, loader.Language));
                return(projectId);
            }

            var projectFileInfo = await projectFile.GetProjectFileInfoAsync(cancellationToken).ConfigureAwait(false);

            if (projectFileInfo.ErrorMessage != null)
            {
                ReportFailure(ReportMode.Log, GetMsbuildFailedMessage(projectFilePath, projectFileInfo.ErrorMessage));
            }

            var projectDirectory = Path.GetDirectoryName(projectFilePath);
            var outputFilePath   = projectFileInfo.OutputFilePath;
            var outputDirectory  = Path.GetDirectoryName(outputFilePath);

            var version = GetProjectVersion(projectFilePath);

            // translate information from command line args
            var commandLineParser = _workspace.Services.GetLanguageServices(loader.Language).GetService <ICommandLineParserService>();
            var metadataService   = _workspace.Services.GetService <IMetadataService>();
            var analyzerService   = _workspace.Services.GetService <IAnalyzerService>();

            var commandLineArgs = commandLineParser.Parse(
                arguments: projectFileInfo.CommandLineArgs,
                baseDirectory: projectDirectory,
                isInteractive: false,
                sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());

            // we only support file paths in /r command line arguments
            var resolver           = new WorkspaceMetadataFileReferenceResolver(metadataService, new RelativePathResolver(commandLineArgs.ReferencePaths, commandLineArgs.BaseDirectory));
            var metadataReferences = commandLineArgs.ResolveMetadataReferences(resolver);

            var analyzerLoader = analyzerService.GetLoader();

            foreach (var path in commandLineArgs.AnalyzerReferences.Select(r => r.FilePath))
            {
                analyzerLoader.AddDependencyLocation(path);
            }

            var analyzerReferences = commandLineArgs.ResolveAnalyzerReferences(analyzerLoader);

            var defaultEncoding = commandLineArgs.Encoding;

            // docs & additional docs
            var docFileInfos           = projectFileInfo.Documents.ToImmutableArrayOrEmpty();
            var additionalDocFileInfos = projectFileInfo.AdditionalDocuments.ToImmutableArrayOrEmpty();

            // check for duplicate documents
            var allDocFileInfos = docFileInfos.AddRange(additionalDocFileInfos);

            CheckDocuments(allDocFileInfos, projectFilePath, projectId);

            var docs = new List <DocumentInfo>();

            foreach (var docFileInfo in docFileInfos)
            {
                GetDocumentNameAndFolders(docFileInfo.LogicalPath, out var name, out var folders);

                docs.Add(DocumentInfo.Create(
                             DocumentId.CreateNewId(projectId, debugName: docFileInfo.FilePath),
                             name,
                             folders,
                             projectFile.GetSourceCodeKind(docFileInfo.FilePath),
                             new FileTextLoader(docFileInfo.FilePath, defaultEncoding),
                             docFileInfo.FilePath,
                             docFileInfo.IsGenerated));
            }

            var additionalDocs = new List <DocumentInfo>();

            foreach (var docFileInfo in additionalDocFileInfos)
            {
                GetDocumentNameAndFolders(docFileInfo.LogicalPath, out var name, out var folders);

                additionalDocs.Add(DocumentInfo.Create(
                                       DocumentId.CreateNewId(projectId, debugName: docFileInfo.FilePath),
                                       name,
                                       folders,
                                       SourceCodeKind.Regular,
                                       new FileTextLoader(docFileInfo.FilePath, defaultEncoding),
                                       docFileInfo.FilePath,
                                       docFileInfo.IsGenerated));
            }

            // project references
            var resolvedReferences = await ResolveProjectReferencesAsync(
                projectId, projectFilePath, projectFileInfo.ProjectReferences, preferMetadata, loadedProjects, cancellationToken).ConfigureAwait(false);

            // add metadata references for project refs converted to metadata refs
            metadataReferences = metadataReferences.Concat(resolvedReferences.MetadataReferences);

            // if the project file loader couldn't figure out an assembly name, make one using the project's file path.
            var assemblyName = commandLineArgs.CompilationName;

            if (string.IsNullOrWhiteSpace(assemblyName))
            {
                assemblyName = GetAssemblyNameFromProjectPath(projectFilePath);
            }

            // make sure that doc-comments at least get parsed.
            var parseOptions = commandLineArgs.ParseOptions;

            if (parseOptions.DocumentationMode == DocumentationMode.None)
            {
                parseOptions = parseOptions.WithDocumentationMode(DocumentationMode.Parse);
            }

            // add all the extra options that are really behavior overrides
            var compOptions = commandLineArgs.CompilationOptions
                              .WithXmlReferenceResolver(new XmlFileResolver(projectDirectory))
                              .WithSourceReferenceResolver(new SourceFileResolver(ImmutableArray <string> .Empty, projectDirectory))
                              // TODO: https://github.com/dotnet/roslyn/issues/4967
                              .WithMetadataReferenceResolver(new WorkspaceMetadataFileReferenceResolver(metadataService, new RelativePathResolver(ImmutableArray <string> .Empty, projectDirectory)))
                              .WithStrongNameProvider(new DesktopStrongNameProvider(ImmutableArray.Create(projectDirectory, outputFilePath)))
                              .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);

            loadedProjects.Add(
                ProjectInfo.Create(
                    projectId,
                    version,
                    projectName,
                    assemblyName,
                    loader.Language,
                    projectFilePath,
                    outputFilePath,
                    compilationOptions: compOptions,
                    parseOptions: parseOptions,
                    documents: docs,
                    projectReferences: resolvedReferences.ProjectReferences,
                    metadataReferences: metadataReferences,
                    analyzerReferences: analyzerReferences,
                    additionalDocuments: additionalDocs,
                    isSubmission: false,
                    hostObjectType: null));

            return(projectId);
        }
示例#6
0
        private async Task<ProjectId> LoadProjectAsync(string projectFilePath, IProjectFileLoader loader, bool preferMetadata, LoadState loadedProjects, CancellationToken cancellationToken)
        {
            Debug.Assert(projectFilePath != null);
            Debug.Assert(loader != null);

            var projectId = loadedProjects.GetOrCreateProjectId(projectFilePath);

            var projectName = Path.GetFileNameWithoutExtension(projectFilePath);

            var projectFile = await loader.LoadProjectFileAsync(projectFilePath, _properties, cancellationToken).ConfigureAwait(false);
            var projectFileInfo = await projectFile.GetProjectFileInfoAsync(cancellationToken).ConfigureAwait(false);

            var projectDirectory = Path.GetDirectoryName(projectFilePath);
            var outputFilePath = projectFileInfo.OutputFilePath;
            var outputDirectory = Path.GetDirectoryName(outputFilePath);

            VersionStamp version;
            if (!string.IsNullOrEmpty(projectFilePath) && File.Exists(projectFilePath))
            {
                version = VersionStamp.Create(File.GetLastWriteTimeUtc(projectFilePath));
            }
            else
            {
                version = VersionStamp.Create();
            }

            // translate information from command line args
            var commandLineParser = _workspace.Services.GetLanguageServices(loader.Language).GetService<ICommandLineParserService>();
            var metadataService = _workspace.Services.GetService<IMetadataService>();
            var analyzerService = _workspace.Services.GetService<IAnalyzerService>();

            var commandLineArgs = commandLineParser.Parse(
                arguments: projectFileInfo.CommandLineArgs,
                baseDirectory: projectDirectory,
                isInteractive: false,
                sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());

            // we only support file paths in /r command line arguments
            var resolver = new WorkspaceMetadataFileReferenceResolver(metadataService, new RelativePathResolver(commandLineArgs.ReferencePaths, commandLineArgs.BaseDirectory));
            var metadataReferences = commandLineArgs.ResolveMetadataReferences(resolver);

            var analyzerLoader = analyzerService.GetLoader();
            foreach (var path in commandLineArgs.AnalyzerReferences.Select(r => r.FilePath))
            {
                analyzerLoader.AddDependencyLocation(path);
            }

            var analyzerReferences = commandLineArgs.ResolveAnalyzerReferences(analyzerLoader);

            var defaultEncoding = commandLineArgs.Encoding;

            // docs & additional docs
            var docFileInfos = projectFileInfo.Documents.ToImmutableArrayOrEmpty();
            var additionalDocFileInfos = projectFileInfo.AdditionalDocuments.ToImmutableArrayOrEmpty();

            // check for duplicate documents
            var allDocFileInfos = docFileInfos.AddRange(additionalDocFileInfos);
            CheckDocuments(allDocFileInfos, projectFilePath, projectId);

            var docs = new List<DocumentInfo>();
            foreach (var docFileInfo in docFileInfos)
            {
                string name;
                ImmutableArray<string> folders;
                GetDocumentNameAndFolders(docFileInfo.LogicalPath, out name, out folders);

                docs.Add(DocumentInfo.Create(
                    DocumentId.CreateNewId(projectId, debugName: docFileInfo.FilePath),
                    name,
                    folders,
                    projectFile.GetSourceCodeKind(docFileInfo.FilePath),
                    new FileTextLoader(docFileInfo.FilePath, defaultEncoding),
                    docFileInfo.FilePath,
                    docFileInfo.IsGenerated));
            }

            var additionalDocs = new List<DocumentInfo>();
            foreach (var docFileInfo in additionalDocFileInfos)
            {
                string name;
                ImmutableArray<string> folders;
                GetDocumentNameAndFolders(docFileInfo.LogicalPath, out name, out folders);

                additionalDocs.Add(DocumentInfo.Create(
                    DocumentId.CreateNewId(projectId, debugName: docFileInfo.FilePath),
                    name,
                    folders,
                    SourceCodeKind.Regular,
                    new FileTextLoader(docFileInfo.FilePath, defaultEncoding),
                    docFileInfo.FilePath,
                    docFileInfo.IsGenerated));
            }

            // project references
            var resolvedReferences = await ResolveProjectReferencesAsync(
                projectId, projectFilePath, projectFileInfo.ProjectReferences, preferMetadata, loadedProjects, cancellationToken).ConfigureAwait(false);

            // add metadata references for project refs converted to metadata refs
            metadataReferences = metadataReferences.Concat(resolvedReferences.MetadataReferences);

            // if the project file loader couldn't figure out an assembly name, make one using the project's file path.
            var assemblyName = commandLineArgs.CompilationName;
            if (string.IsNullOrWhiteSpace(assemblyName))
            {
                assemblyName = Path.GetFileNameWithoutExtension(projectFilePath);

                // if this is still unreasonable, use a fixed name.
                if (string.IsNullOrWhiteSpace(assemblyName))
                {
                    assemblyName = "assembly";
                }
            }

            // make sure that doc-comments at least get parsed.
            var parseOptions = commandLineArgs.ParseOptions;
            if (parseOptions.DocumentationMode == DocumentationMode.None)
            {
                parseOptions = parseOptions.WithDocumentationMode(DocumentationMode.Parse);
            }

            // add all the extra options that are really behavior overrides
            var compOptions = commandLineArgs.CompilationOptions
                    .WithXmlReferenceResolver(new XmlFileResolver(projectDirectory))
                    .WithSourceReferenceResolver(new SourceFileResolver(ImmutableArray<string>.Empty, projectDirectory))
                    // TODO: https://github.com/dotnet/roslyn/issues/4967
                    .WithMetadataReferenceResolver(new WorkspaceMetadataFileReferenceResolver(metadataService, new RelativePathResolver(ImmutableArray<string>.Empty, projectDirectory)))
                    .WithStrongNameProvider(new DesktopStrongNameProvider(ImmutableArray.Create(projectDirectory, outputFilePath)))
                    .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);

            loadedProjects.Add(
                ProjectInfo.Create(
                    projectId,
                    version,
                    projectName,
                    assemblyName,
                    loader.Language,
                    projectFilePath,
                    outputFilePath,
                    compilationOptions: compOptions,
                    parseOptions: parseOptions,
                    documents: docs,
                    projectReferences: resolvedReferences.ProjectReferences,
                    metadataReferences: metadataReferences,
                    analyzerReferences: analyzerReferences,
                    additionalDocuments: additionalDocs,
                    isSubmission: false,
                    hostObjectType: null));

            return projectId;
        }
示例#7
0
        /// <summary>
        /// Create a <see cref="ProjectInfo"/> structure initialized from a compilers command line arguments.
        /// </summary>
        public static ProjectInfo CreateProjectInfo(string projectName, string language, IEnumerable <string> commandLineArgs, string projectDirectory, Workspace workspace = null)
        {
            // TODO (tomat): the method may throw all sorts of exceptions.
            var tmpWorkspace     = workspace ?? new AdhocWorkspace(DesktopMefHostServices.DefaultServices);
            var languageServices = tmpWorkspace.Services.GetLanguageServices(language);

            if (languageServices == null)
            {
                throw new ArgumentException(WorkspacesResources.Unrecognized_language_name);
            }

            var commandLineParser    = languageServices.GetRequiredService <ICommandLineParserService>();
            var commandLineArguments = commandLineParser.Parse(commandLineArgs, projectDirectory, isInteractive: false, sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());

            var metadataService = tmpWorkspace.Services.GetRequiredService <IMetadataService>();

            // we only support file paths in /r command line arguments
            var commandLineMetadataReferenceResolver = new WorkspaceMetadataFileReferenceResolver(
                metadataService, new RelativePathResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory));

            var analyzerLoader     = tmpWorkspace.Services.GetRequiredService <IAnalyzerService>().GetLoader();
            var xmlFileResolver    = new XmlFileResolver(commandLineArguments.BaseDirectory);
            var strongNameProvider = new DesktopStrongNameProvider(commandLineArguments.KeyFileSearchPaths);

            // resolve all metadata references.
            var boundMetadataReferences      = commandLineArguments.ResolveMetadataReferences(commandLineMetadataReferenceResolver);
            var unresolvedMetadataReferences = boundMetadataReferences.FirstOrDefault(r => r is UnresolvedMetadataReference);

            if (unresolvedMetadataReferences != null)
            {
                throw new ArgumentException(string.Format(WorkspacesResources.Can_t_resolve_metadata_reference_colon_0, ((UnresolvedMetadataReference)unresolvedMetadataReferences).Reference));
            }

            // resolve all analyzer references.
            foreach (var path in commandLineArguments.AnalyzerReferences.Select(r => r.FilePath))
            {
                analyzerLoader.AddDependencyLocation(path);
            }

            var boundAnalyzerReferences      = commandLineArguments.ResolveAnalyzerReferences(analyzerLoader);
            var unresolvedAnalyzerReferences = boundAnalyzerReferences.FirstOrDefault(r => r is UnresolvedAnalyzerReference);

            if (unresolvedAnalyzerReferences != null)
            {
                throw new ArgumentException(string.Format(WorkspacesResources.Can_t_resolve_analyzer_reference_colon_0, ((UnresolvedAnalyzerReference)unresolvedAnalyzerReferences).Display));
            }

            AssemblyIdentityComparer assemblyIdentityComparer;

            if (commandLineArguments.AppConfigPath != null)
            {
                try
                {
                    using (var appConfigStream = new FileStream(commandLineArguments.AppConfigPath, FileMode.Open, FileAccess.Read))
                    {
                        assemblyIdentityComparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream);
                    }
                }
                catch (Exception e)
                {
                    throw new ArgumentException(string.Format(WorkspacesResources.An_error_occurred_while_reading_the_specified_configuration_file_colon_0, e.Message));
                }
            }
            else
            {
                assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default;
            }

            var projectId = ProjectId.CreateNewId(debugName: projectName);

            // construct file infos
            var docs = new List <DocumentInfo>();

            foreach (var fileArg in commandLineArguments.SourceFiles)
            {
                var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory)
                    ? Path.GetFullPath(fileArg.Path)
                    : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path));

                var relativePath    = FilePathUtilities.GetRelativePath(projectDirectory, absolutePath);
                var isWithinProject = FilePathUtilities.IsNestedPath(projectDirectory, absolutePath);

                var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : "";
                var folders    = isWithinProject ? GetFolders(relativePath) : null;
                var name       = Path.GetFileName(relativePath);
                var id         = DocumentId.CreateNewId(projectId, absolutePath);

                var doc = DocumentInfo.Create(
                    id: id,
                    name: name,
                    folders: folders,
                    sourceCodeKind: fileArg.IsScript ? SourceCodeKind.Script : SourceCodeKind.Regular,
                    loader: new FileTextLoader(absolutePath, commandLineArguments.Encoding),
                    filePath: absolutePath);

                docs.Add(doc);
            }

            // construct file infos for additional files.
            var additionalDocs = new List <DocumentInfo>();

            foreach (var fileArg in commandLineArguments.AdditionalFiles)
            {
                var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory)
                        ? Path.GetFullPath(fileArg.Path)
                        : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path));

                var relativePath    = FilePathUtilities.GetRelativePath(projectDirectory, absolutePath);
                var isWithinProject = FilePathUtilities.IsNestedPath(projectDirectory, absolutePath);

                var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : "";
                var folders    = isWithinProject ? GetFolders(relativePath) : null;
                var name       = Path.GetFileName(relativePath);
                var id         = DocumentId.CreateNewId(projectId, absolutePath);

                var doc = DocumentInfo.Create(
                    id: id,
                    name: name,
                    folders: folders,
                    sourceCodeKind: SourceCodeKind.Regular,
                    loader: new FileTextLoader(absolutePath, commandLineArguments.Encoding),
                    filePath: absolutePath);

                additionalDocs.Add(doc);
            }

            // If /out is not specified and the project is a console app the csc.exe finds out the Main method
            // and names the compilation after the file that contains it. We don't want to create a compilation,
            // bind Mains etc. here. Besides the msbuild always includes /out in the command line it produces.
            // So if we don't have the /out argument we name the compilation "<anonymous>".
            string assemblyName = (commandLineArguments.OutputFileName != null) ?
                                  Path.GetFileNameWithoutExtension(commandLineArguments.OutputFileName) : "<anonymous>";

            // TODO (tomat): what should be the assemblyName when compiling a netmodule? Should it be /moduleassemblyname

            var projectInfo = ProjectInfo.Create(
                projectId,
                VersionStamp.Create(),
                projectName,
                assemblyName,
                language: language,
                compilationOptions: commandLineArguments.CompilationOptions
                .WithXmlReferenceResolver(xmlFileResolver)
                .WithAssemblyIdentityComparer(assemblyIdentityComparer)
                .WithStrongNameProvider(strongNameProvider)
                // TODO (https://github.com/dotnet/roslyn/issues/4967):
                .WithMetadataReferenceResolver(new WorkspaceMetadataFileReferenceResolver(metadataService, new RelativePathResolver(ImmutableArray <string> .Empty, projectDirectory))),
                parseOptions: commandLineArguments.ParseOptions,
                documents: docs,
                additionalDocuments: additionalDocs,
                metadataReferences: boundMetadataReferences,
                analyzerReferences: boundAnalyzerReferences);

            return(projectInfo);
        }
示例#8
0
        protected CSharpCompilationOptions CreateCompilationOptions()
        {
            IDictionary <string, ReportDiagnostic> ruleSetSpecificDiagnosticOptions = null;

            // Get options from the ruleset file, if any, first. That way project-specific
            // options can override them.
            ReportDiagnostic?ruleSetGeneralDiagnosticOption = null;

            if (this.ruleSet != null)
            {
                ruleSetGeneralDiagnosticOption   = this.ruleSet.GetGeneralDiagnosticOption();
                ruleSetSpecificDiagnosticOptions = new Dictionary <string, ReportDiagnostic>(this.ruleSet.GetSpecificDiagnosticOptions());
            }
            else
            {
                ruleSetSpecificDiagnosticOptions = new Dictionary <string, ReportDiagnostic>();
            }

            UpdateRuleSetError(ruleSet);

            ReportDiagnostic generalDiagnosticOption;
            var warningsAreErrors = GetNullableBooleanOption(CompilerOptions.OPTID_WARNINGSAREERRORS);

            if (warningsAreErrors.HasValue)
            {
                generalDiagnosticOption = warningsAreErrors.Value ? ReportDiagnostic.Error : ReportDiagnostic.Default;
            }
            else if (ruleSetGeneralDiagnosticOption.HasValue)
            {
                generalDiagnosticOption = ruleSetGeneralDiagnosticOption.Value;
            }
            else
            {
                generalDiagnosticOption = ReportDiagnostic.Default;
            }

            // Start with the rule set options
            IDictionary <string, ReportDiagnostic> diagnosticOptions = new Dictionary <string, ReportDiagnostic>(ruleSetSpecificDiagnosticOptions);

            // Update the specific options based on the general settings
            if (warningsAreErrors.HasValue && warningsAreErrors.Value == true)
            {
                foreach (var pair in ruleSetSpecificDiagnosticOptions)
                {
                    if (pair.Value == ReportDiagnostic.Warn)
                    {
                        diagnosticOptions[pair.Key] = ReportDiagnostic.Error;
                    }
                }
            }

            // Update the specific options based on the specific settings
            foreach (var diagnosticID in ParseWarningCodes(CompilerOptions.OPTID_WARNASERRORLIST))
            {
                diagnosticOptions[diagnosticID] = ReportDiagnostic.Error;
            }

            foreach (var diagnosticID in ParseWarningCodes(CompilerOptions.OPTID_WARNNOTASERRORLIST))
            {
                ReportDiagnostic ruleSetOption;
                if (ruleSetSpecificDiagnosticOptions.TryGetValue(diagnosticID, out ruleSetOption))
                {
                    diagnosticOptions[diagnosticID] = ruleSetOption;
                }
                else
                {
                    diagnosticOptions[diagnosticID] = ReportDiagnostic.Default;
                }
            }

            foreach (var diagnosticID in ParseWarningCodes(CompilerOptions.OPTID_NOWARNLIST))
            {
                diagnosticOptions[diagnosticID] = ReportDiagnostic.Suppress;
            }

            Platform platform;

            if (!Enum.TryParse(GetStringOption(CompilerOptions.OPTID_PLATFORM, ""), ignoreCase: true, result: out platform))
            {
                platform = Platform.AnyCpu;
            }

            int warningLevel;

            if (!int.TryParse(GetStringOption(CompilerOptions.OPTID_WARNINGLEVEL, defaultValue: ""), out warningLevel))
            {
                warningLevel = 4;
            }

            string projectDirectory = this.ContainingDirectoryPathOpt;

            // TODO: #r support, should it include bin path?
            var referenceSearchPaths = ImmutableArray <string> .Empty;

            // TODO: #load support
            var sourceSearchPaths = ImmutableArray <string> .Empty;

            MetadataReferenceResolver referenceResolver;

            if (Workspace != null)
            {
                referenceResolver = new WorkspaceMetadataFileReferenceResolver(
                    Workspace.CurrentSolution.Services.MetadataService,
                    new RelativePathResolver(referenceSearchPaths, projectDirectory));
            }
            else
            {
                // can only happen in tests
                referenceResolver = null;
            }

            // TODO: appConfigPath: GetFilePathOption(CompilerOptions.OPTID_FUSIONCONFIG), bug #869604
            return(new CSharpCompilationOptions(
                       allowUnsafe: GetBooleanOption(CompilerOptions.OPTID_UNSAFE),
                       checkOverflow: GetBooleanOption(CompilerOptions.OPTID_CHECKED),
                       concurrentBuild: false,
                       cryptoKeyContainer: GetStringOption(CompilerOptions.OPTID_KEYNAME, defaultValue: null),
                       cryptoKeyFile: GetFilePathRelativeOption(CompilerOptions.OPTID_KEYFILE),
                       delaySign: GetNullableBooleanOption(CompilerOptions.OPTID_DELAYSIGN),
                       generalDiagnosticOption: generalDiagnosticOption,
                       mainTypeName: _mainTypeName,
                       moduleName: GetStringOption(CompilerOptions.OPTID_MODULEASSEMBLY, defaultValue: null),
                       optimizationLevel: GetBooleanOption(CompilerOptions.OPTID_OPTIMIZATIONS) ? OptimizationLevel.Release : OptimizationLevel.Debug,
                       outputKind: _outputKind,
                       platform: platform,
                       specificDiagnosticOptions: diagnosticOptions,
                       warningLevel: warningLevel,
                       xmlReferenceResolver: new XmlFileResolver(projectDirectory),
                       sourceReferenceResolver: new SourceFileResolver(sourceSearchPaths, projectDirectory),
                       metadataReferenceResolver: referenceResolver,
                       assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default,
                       strongNameProvider: new DesktopStrongNameProvider(GetStrongNameKeyPaths()),
                       deterministic: GetParsedCommandLineArguments().CompilationOptions.Deterministic,
                       publicSign: GetParsedCommandLineArguments().CompilationOptions.PublicSign));
        }
示例#9
0
        /// <summary>
        /// Create a <see cref="ProjectInfo"/> structure initialized from a compilers command line arguments.
        /// </summary>
        public static ProjectInfo CreateProjectInfo(string projectName, string language, IEnumerable<string> commandLineArgs, string projectDirectory, Workspace workspace = null)
        {
            // TODO (tomat): the method may throw all sorts of exceptions.
            var tmpWorkspace = workspace ?? new AdhocWorkspace(DesktopMefHostServices.DefaultServices);
            var languageServices = tmpWorkspace.Services.GetLanguageServices(language);
            if (languageServices == null)
            {
                throw new ArgumentException(WorkspacesResources.UnrecognizedLanguageName);
            }

            var commandLineParser = languageServices.GetRequiredService<ICommandLineParserService>();
            var commandLineArguments = commandLineParser.Parse(commandLineArgs, projectDirectory, isInteractive: false, sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());

            var metadataService = tmpWorkspace.Services.GetRequiredService<IMetadataService>();

            // we only support file paths in /r command line arguments
            var commandLineMetadataReferenceResolver = new WorkspaceMetadataFileReferenceResolver(
                metadataService, new RelativePathResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory));

            var analyzerLoader = tmpWorkspace.Services.GetRequiredService<IAnalyzerService>().GetLoader();
            var xmlFileResolver = new XmlFileResolver(commandLineArguments.BaseDirectory);
            var strongNameProvider = new DesktopStrongNameProvider(commandLineArguments.KeyFileSearchPaths);

            // resolve all metadata references.
            var boundMetadataReferences = commandLineArguments.ResolveMetadataReferences(commandLineMetadataReferenceResolver);
            var unresolvedMetadataReferences = boundMetadataReferences.FirstOrDefault(r => r is UnresolvedMetadataReference);
            if (unresolvedMetadataReferences != null)
            {
                throw new ArgumentException(string.Format(WorkspacesResources.CantResolveMetadataReference, ((UnresolvedMetadataReference)unresolvedMetadataReferences).Reference));
            }

            // resolve all analyzer references.
            foreach (var path in commandLineArguments.AnalyzerReferences.Select(r => r.FilePath))
            {
                analyzerLoader.AddDependencyLocation(path);
            }

            var boundAnalyzerReferences = commandLineArguments.ResolveAnalyzerReferences(analyzerLoader);
            var unresolvedAnalyzerReferences = boundAnalyzerReferences.FirstOrDefault(r => r is UnresolvedAnalyzerReference);
            if (unresolvedAnalyzerReferences != null)
            {
                throw new ArgumentException(string.Format(WorkspacesResources.CantResolveAnalyzerReference, ((UnresolvedAnalyzerReference)unresolvedAnalyzerReferences).Display));
            }

            AssemblyIdentityComparer assemblyIdentityComparer;
            if (commandLineArguments.AppConfigPath != null)
            {
                try
                {
                    using (var appConfigStream = new FileStream(commandLineArguments.AppConfigPath, FileMode.Open, FileAccess.Read))
                    {
                        assemblyIdentityComparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream);
                    }
                }
                catch (Exception e)
                {
                    throw new ArgumentException(string.Format(WorkspacesResources.ErrorWhileReadingSpecifiedConfigFile, e.Message));
                }
            }
            else
            {
                assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default;
            }

            var projectId = ProjectId.CreateNewId(debugName: projectName);

            // construct file infos
            var docs = new List<DocumentInfo>();
            foreach (var fileArg in commandLineArguments.SourceFiles)
            {
                var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory)
                    ? Path.GetFullPath(fileArg.Path)
                    : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path));

                var relativePath = FilePathUtilities.GetRelativePath(projectDirectory, absolutePath);
                var isWithinProject = FilePathUtilities.IsNestedPath(projectDirectory, absolutePath);

                var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : "";
                var folders = isWithinProject ? GetFolders(relativePath) : null;
                var name = Path.GetFileName(relativePath);
                var id = DocumentId.CreateNewId(projectId, absolutePath);

                var doc = DocumentInfo.Create(
                   id: id,
                   name: name,
                   folders: folders,
                   sourceCodeKind: fileArg.IsScript ? SourceCodeKind.Script : SourceCodeKind.Regular,
                   loader: new FileTextLoader(absolutePath, commandLineArguments.Encoding),
                   filePath: absolutePath);

                docs.Add(doc);
            }

            // construct file infos for additional files.
            var additionalDocs = new List<DocumentInfo>();
            foreach (var fileArg in commandLineArguments.AdditionalFiles)
            {
                var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory)
                        ? Path.GetFullPath(fileArg.Path)
                        : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path));

                var relativePath = FilePathUtilities.GetRelativePath(projectDirectory, absolutePath);
                var isWithinProject = FilePathUtilities.IsNestedPath(projectDirectory, absolutePath);

                var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : "";
                var folders = isWithinProject ? GetFolders(relativePath) : null;
                var name = Path.GetFileName(relativePath);
                var id = DocumentId.CreateNewId(projectId, absolutePath);

                var doc = DocumentInfo.Create(
                   id: id,
                   name: name,
                   folders: folders,
                   sourceCodeKind: SourceCodeKind.Regular,
                   loader: new FileTextLoader(absolutePath, commandLineArguments.Encoding),
                   filePath: absolutePath);

                additionalDocs.Add(doc);
            }

            // If /out is not specified and the project is a console app the csc.exe finds out the Main method
            // and names the compilation after the file that contains it. We don't want to create a compilation, 
            // bind Mains etc. here. Besides the msbuild always includes /out in the command line it produces.
            // So if we don't have the /out argument we name the compilation "<anonymous>".
            string assemblyName = (commandLineArguments.OutputFileName != null) ?
                Path.GetFileNameWithoutExtension(commandLineArguments.OutputFileName) : "<anonymous>";

            // TODO (tomat): what should be the assemblyName when compiling a netmodule? Should it be /moduleassemblyname

            var projectInfo = ProjectInfo.Create(
                projectId,
                VersionStamp.Create(),
                projectName,
                assemblyName,
                language: language,
                compilationOptions: commandLineArguments.CompilationOptions
                    .WithXmlReferenceResolver(xmlFileResolver)
                    .WithAssemblyIdentityComparer(assemblyIdentityComparer)
                    .WithStrongNameProvider(strongNameProvider)
                    // TODO (https://github.com/dotnet/roslyn/issues/4967): 
                    .WithMetadataReferenceResolver(new WorkspaceMetadataFileReferenceResolver(metadataService, new RelativePathResolver(ImmutableArray<string>.Empty, projectDirectory))),
                parseOptions: commandLineArguments.ParseOptions,
                documents: docs,
                additionalDocuments: additionalDocs,
                metadataReferences: boundMetadataReferences,
                analyzerReferences: boundAnalyzerReferences);

            return projectInfo;
        }
示例#10
0
        private void AttachToDocument(uint docCookie, string moniker)
        {
            _foregroundThreadAffinitization.AssertIsForeground();

            var vsTextBuffer = (IVsTextBuffer)_runningDocumentTable.GetDocumentData(docCookie);
            var textBuffer   = _editorAdaptersFactoryService.GetDocumentBuffer(vsTextBuffer);

            if (_fileTrackingMetadataAsSourceService.TryAddDocumentToWorkspace(moniker, textBuffer))
            {
                // We already added it, so we will keep it excluded from the misc files workspace
                return;
            }

            // This should always succeed since we only got here if we already confirmed the moniker is acceptable
            var languageInformation = TryGetLanguageInformation(moniker);

            Contract.ThrowIfNull(languageInformation);

            var languageServices      = Services.GetLanguageServices(languageInformation.LanguageName);
            var compilationOptionsOpt = languageServices.GetService <ICompilationFactoryService>()?.GetDefaultCompilationOptions();
            var parseOptionsOpt       = languageServices.GetService <ISyntaxTreeFactoryService>()?.GetDefaultParseOptions();

            if (parseOptionsOpt != null &&
                compilationOptionsOpt != null &&
                PathUtilities.GetExtension(moniker) == languageInformation.ScriptExtension)
            {
                parseOptionsOpt = parseOptionsOpt.WithKind(SourceCodeKind.Script);

                var metadataService = Services.GetService <IMetadataService>();
                var directory       = PathUtilities.GetDirectoryName(moniker);

                // TODO (https://github.com/dotnet/roslyn/issues/5325, https://github.com/dotnet/roslyn/issues/13886):
                // - Need to have a way to specify these somewhere in VS options.
                // - Use RuntimeMetadataReferenceResolver like in InteractiveEvaluator.CreateMetadataReferenceResolver
                // - Add default namespace imports
                // - Add default script globals available in 'csi goo.csx' environment: CommandLineScriptGlobals

                var referenceSearchPaths = ImmutableArray <string> .Empty;
                var sourceSearchPaths    = ImmutableArray <string> .Empty;

                var referenceResolver = new WorkspaceMetadataFileReferenceResolver(
                    metadataService,
                    new RelativePathResolver(referenceSearchPaths, directory));

                compilationOptionsOpt = compilationOptionsOpt.
                                        WithMetadataReferenceResolver(referenceResolver).
                                        WithSourceReferenceResolver(new SourceFileResolver(sourceSearchPaths, directory));
            }

            // First, create the project
            var hostProject = new HostProject(this, CurrentSolution.Id, languageInformation.LanguageName, parseOptionsOpt, compilationOptionsOpt, _metadataReferences);

            // Now try to find the document. We accept any text buffer, since we've already verified it's an appropriate file in ShouldIncludeFile.
            var document = _documentProvider.TryGetDocumentForFile(
                hostProject,
                moniker,
                parseOptionsOpt?.Kind ?? SourceCodeKind.Regular,
                getFolderNames: _ => SpecializedCollections.EmptyReadOnlyList <string>(),
                canUseTextBuffer: _ => true);

            // If the buffer has not yet been initialized, we won't get a document.
            if (document == null)
            {
                return;
            }

            // Since we have a document, we can do the rest of the project setup.
            _hostProjects.Add(hostProject.Id, hostProject);
            OnProjectAdded(hostProject.CreateProjectInfoForCurrentState());

            OnDocumentAdded(document.GetInitialState());
            hostProject.Document = document;

            // Notify the document provider, so it knows the document is now open and a part of
            // the project
            _documentProvider.NotifyDocumentRegisteredToProjectAndStartToRaiseEvents(document);

            Contract.ThrowIfFalse(document.IsOpen);

            var buffer = document.GetOpenTextBuffer();

            OnDocumentOpened(document.Id, document.GetOpenTextContainer());

            _docCookiesToHostProject.Add(docCookie, hostProject);
        }
        public static ProjectInfo CreateProjectInfo(string projectName, string language, IEnumerable <string> commandLineArgs, string projectDirectory, Workspace workspace = null)
#pragma warning restore RS0026 // Type is forwarded from MS.CA.Workspaces.Desktop.
        {
            // TODO (tomat): the method may throw all sorts of exceptions.
            var tmpWorkspace     = workspace ?? new AdhocWorkspace();
            var languageServices = tmpWorkspace.Services.GetLanguageServices(language);

            if (languageServices == null)
            {
                throw new ArgumentException(WorkspacesResources.Unrecognized_language_name);
            }

            var commandLineParser    = languageServices.GetRequiredService <ICommandLineParserService>();
            var commandLineArguments = commandLineParser.Parse(commandLineArgs, projectDirectory, isInteractive: false, sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());

            var metadataService = tmpWorkspace.Services.GetRequiredService <IMetadataService>();

            // we only support file paths in /r command line arguments
            var relativePathResolver =
                new RelativePathResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory);
            var commandLineMetadataReferenceResolver = new WorkspaceMetadataFileReferenceResolver(
                metadataService, relativePathResolver);

            var analyzerLoader     = tmpWorkspace.Services.GetRequiredService <IAnalyzerService>().GetLoader();
            var xmlFileResolver    = new XmlFileResolver(commandLineArguments.BaseDirectory);
            var strongNameProvider = new DesktopStrongNameProvider(commandLineArguments.KeyFileSearchPaths);

            // Resolve all metadata references.
            //
            // In the command line compiler, it's entirely possible that duplicate reference paths may appear in this list; in the compiler
            // each MetadataReference object is a distinct instance, and the deduplication is ultimately performed in the ReferenceManager
            // once the Compilation actually starts to read metadata. In this code however,  we're resolving with the IMetadataService, which
            // has a default implementation to cache and return the same MetadataReference instance for a duplicate. This means duplicate
            // reference path will create duplicate MetadataReference objects, which is disallowed by ProjectInfo.Create -- even though the
            // compiler eventually would have dealt with it just fine. It's reasonable the Workspace APIs disallow duplicate reference objects
            // since it makes the semantics of APIs like Add/RemoveMetadataReference tricky. But since we want to not break for command lines
            // with duplicate references, we'll do a .Distinct() here, and let the Compilation do any further deduplication
            // that isn't handled by this explicit instance check. This does mean that the Compilations produced through this API
            // won't produce the "duplicate metadata reference" diagnostic like the real command line compiler would, but that's probably fine.
            //
            // Alternately, we could change the IMetadataService behavior to simply not cache, but that could theoretically break other
            // callers that would now see references across projects not be the same, or hurt performance for users of MSBuildWorkspace. Given
            // this is an edge case, it's not worth the larger fix here.
            var boundMetadataReferences      = commandLineArguments.ResolveMetadataReferences(commandLineMetadataReferenceResolver).Distinct().ToList();
            var unresolvedMetadataReferences = boundMetadataReferences.FirstOrDefault(r => r is UnresolvedMetadataReference);

            if (unresolvedMetadataReferences != null)
            {
                throw new ArgumentException(string.Format(WorkspacesResources.Can_t_resolve_metadata_reference_colon_0, ((UnresolvedMetadataReference)unresolvedMetadataReferences).Reference));
            }

            // resolve all analyzer references.
            foreach (var path in commandLineArguments.AnalyzerReferences.Select(r => r.FilePath))
            {
                analyzerLoader.AddDependencyLocation(relativePathResolver.ResolvePath(path, baseFilePath: null));
            }

            var boundAnalyzerReferences      = commandLineArguments.ResolveAnalyzerReferences(analyzerLoader);
            var unresolvedAnalyzerReferences = boundAnalyzerReferences.FirstOrDefault(r => r is UnresolvedAnalyzerReference);

            if (unresolvedAnalyzerReferences != null)
            {
                throw new ArgumentException(string.Format(WorkspacesResources.Can_t_resolve_analyzer_reference_colon_0, ((UnresolvedAnalyzerReference)unresolvedAnalyzerReferences).Display));
            }

            AssemblyIdentityComparer assemblyIdentityComparer;

            if (commandLineArguments.AppConfigPath != null)
            {
                try
                {
                    using var appConfigStream = new FileStream(commandLineArguments.AppConfigPath, FileMode.Open, FileAccess.Read);

                    assemblyIdentityComparer = DesktopAssemblyIdentityComparer.LoadFromXml(appConfigStream);
                }
                catch (Exception e)
                {
                    throw new ArgumentException(string.Format(WorkspacesResources.An_error_occurred_while_reading_the_specified_configuration_file_colon_0, e.Message));
                }
            }
            else
            {
                assemblyIdentityComparer = DesktopAssemblyIdentityComparer.Default;
            }

            var projectId = ProjectId.CreateNewId(debugName: projectName);

            // construct file infos
            var docs = new List <DocumentInfo>();

            foreach (var fileArg in commandLineArguments.SourceFiles)
            {
                var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory)
                    ? Path.GetFullPath(fileArg.Path)
                    : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path));

                var relativePath    = PathUtilities.GetRelativePath(projectDirectory, absolutePath);
                var isWithinProject = PathUtilities.IsChildPath(projectDirectory, absolutePath);

                var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : "";
                var folders    = isWithinProject ? GetFolders(relativePath) : null;
                var name       = Path.GetFileName(relativePath);
                var id         = DocumentId.CreateNewId(projectId, absolutePath);

                var doc = DocumentInfo.Create(
                    id: id,
                    name: name,
                    folders: folders,
                    sourceCodeKind: fileArg.IsScript ? SourceCodeKind.Script : SourceCodeKind.Regular,
                    loader: new FileTextLoader(absolutePath, commandLineArguments.Encoding),
                    filePath: absolutePath);

                docs.Add(doc);
            }

            // construct file infos for additional files.
            var additionalDocs = new List <DocumentInfo>();

            foreach (var fileArg in commandLineArguments.AdditionalFiles)
            {
                var absolutePath = Path.IsPathRooted(fileArg.Path) || string.IsNullOrEmpty(projectDirectory)
                        ? Path.GetFullPath(fileArg.Path)
                        : Path.GetFullPath(Path.Combine(projectDirectory, fileArg.Path));

                var relativePath    = PathUtilities.GetRelativePath(projectDirectory, absolutePath);
                var isWithinProject = PathUtilities.IsChildPath(projectDirectory, absolutePath);

                var folderRoot = isWithinProject ? Path.GetDirectoryName(relativePath) : "";
                var folders    = isWithinProject ? GetFolders(relativePath) : null;
                var name       = Path.GetFileName(relativePath);
                var id         = DocumentId.CreateNewId(projectId, absolutePath);

                var doc = DocumentInfo.Create(
                    id: id,
                    name: name,
                    folders: folders,
                    sourceCodeKind: SourceCodeKind.Regular,
                    loader: new FileTextLoader(absolutePath, commandLineArguments.Encoding),
                    filePath: absolutePath);

                additionalDocs.Add(doc);
            }

            // If /out is not specified and the project is a console app the csc.exe finds out the Main method
            // and names the compilation after the file that contains it. We don't want to create a compilation,
            // bind Mains etc. here. Besides the msbuild always includes /out in the command line it produces.
            // So if we don't have the /out argument we name the compilation "<anonymous>".
            var assemblyName = (commandLineArguments.OutputFileName != null) ?
                               Path.GetFileNameWithoutExtension(commandLineArguments.OutputFileName) : "<anonymous>";

            // TODO (tomat): what should be the assemblyName when compiling a netmodule? Should it be /moduleassemblyname

            var projectInfo = ProjectInfo.Create(
                projectId,
                VersionStamp.Create(),
                projectName,
                assemblyName,
                language: language,
                compilationOptions: commandLineArguments.CompilationOptions
                .WithXmlReferenceResolver(xmlFileResolver)
                .WithAssemblyIdentityComparer(assemblyIdentityComparer)
                .WithStrongNameProvider(strongNameProvider)
                // TODO (https://github.com/dotnet/roslyn/issues/4967):
                .WithMetadataReferenceResolver(new WorkspaceMetadataFileReferenceResolver(metadataService, new RelativePathResolver(ImmutableArray <string> .Empty, projectDirectory))),
                parseOptions: commandLineArguments.ParseOptions,
                documents: docs,
                additionalDocuments: additionalDocs,
                metadataReferences: boundMetadataReferences,
                analyzerReferences: boundAnalyzerReferences);

            return(projectInfo);
        }
        protected override CSharpCompilationOptions CreateCompilationOptions()
        {
            IDictionary<string, ReportDiagnostic> ruleSetSpecificDiagnosticOptions = null;

            // Get options from the ruleset file, if any, first. That way project-specific
            // options can override them.
            ReportDiagnostic? ruleSetGeneralDiagnosticOption = null;
            if (this.ruleSet != null)
            {
                ruleSetGeneralDiagnosticOption = this.ruleSet.GetGeneralDiagnosticOption();
                ruleSetSpecificDiagnosticOptions = new Dictionary<string, ReportDiagnostic>(this.ruleSet.GetSpecificDiagnosticOptions());
            }
            else
            {
                ruleSetSpecificDiagnosticOptions = new Dictionary<string, ReportDiagnostic>();
            }

            UpdateRuleSetError(ruleSet);

            ReportDiagnostic generalDiagnosticOption;
            var warningsAreErrors = GetNullableBooleanOption(CompilerOptions.OPTID_WARNINGSAREERRORS);
            if (warningsAreErrors.HasValue)
            {
                generalDiagnosticOption = warningsAreErrors.Value ? ReportDiagnostic.Error : ReportDiagnostic.Default;
            }
            else if (ruleSetGeneralDiagnosticOption.HasValue)
            {
                generalDiagnosticOption = ruleSetGeneralDiagnosticOption.Value;
            }
            else
            {
                generalDiagnosticOption = ReportDiagnostic.Default;
            }

            // Start with the rule set options
            IDictionary<string, ReportDiagnostic> diagnosticOptions = new Dictionary<string, ReportDiagnostic>(ruleSetSpecificDiagnosticOptions);

            // Update the specific options based on the general settings
            if (warningsAreErrors.HasValue && warningsAreErrors.Value == true)
            {
                foreach (var pair in ruleSetSpecificDiagnosticOptions)
                {
                    if (pair.Value == ReportDiagnostic.Warn)
                    {
                        diagnosticOptions[pair.Key] = ReportDiagnostic.Error;
                    }
                }
            }

            // Update the specific options based on the specific settings
            foreach (var diagnosticID in ParseWarningCodes(CompilerOptions.OPTID_WARNASERRORLIST))
            {
                diagnosticOptions[diagnosticID] = ReportDiagnostic.Error;
            }

            foreach (var diagnosticID in ParseWarningCodes(CompilerOptions.OPTID_WARNNOTASERRORLIST))
            {
                ReportDiagnostic ruleSetOption;
                if (ruleSetSpecificDiagnosticOptions.TryGetValue(diagnosticID, out ruleSetOption))
                {
                    diagnosticOptions[diagnosticID] = ruleSetOption;
                }
                else
                {
                    diagnosticOptions[diagnosticID] = ReportDiagnostic.Default;
                }
            }

            foreach (var diagnosticID in ParseWarningCodes(CompilerOptions.OPTID_NOWARNLIST))
            {
                diagnosticOptions[diagnosticID] = ReportDiagnostic.Suppress;
            }

            Platform platform;

            if (!Enum.TryParse(GetStringOption(CompilerOptions.OPTID_PLATFORM, ""), ignoreCase: true, result: out platform))
            {
                platform = Platform.AnyCpu;
            }

            int warningLevel;

            if (!int.TryParse(GetStringOption(CompilerOptions.OPTID_WARNINGLEVEL, defaultValue: ""), out warningLevel))
            {
                warningLevel = 4;
            }

            string projectDirectory = this.ContainingDirectoryPathOpt;

            // TODO: #r support, should it include bin path?
            var referenceSearchPaths = ImmutableArray<string>.Empty;

            // TODO: #load support
            var sourceSearchPaths = ImmutableArray<string>.Empty;

            MetadataReferenceResolver referenceResolver;
            if (Workspace != null)
            {
                referenceResolver = new WorkspaceMetadataFileReferenceResolver(
                    Workspace.CurrentSolution.Services.MetadataService,
                    new RelativePathResolver(referenceSearchPaths, projectDirectory));
            }
            else
            {
                // can only happen in tests
                referenceResolver = null;
            }

            // TODO: appConfigPath: GetFilePathOption(CompilerOptions.OPTID_FUSIONCONFIG), bug #869604
            return new CSharpCompilationOptions(
                allowUnsafe: GetBooleanOption(CompilerOptions.OPTID_UNSAFE),
                checkOverflow: GetBooleanOption(CompilerOptions.OPTID_CHECKED),
                concurrentBuild: false,
                cryptoKeyContainer: GetStringOption(CompilerOptions.OPTID_KEYNAME, defaultValue: null),
                cryptoKeyFile: GetFilePathRelativeOption(CompilerOptions.OPTID_KEYFILE),
                delaySign: GetNullableBooleanOption(CompilerOptions.OPTID_DELAYSIGN),
                generalDiagnosticOption: generalDiagnosticOption,
                mainTypeName: _mainTypeName,
                moduleName: GetStringOption(CompilerOptions.OPTID_MODULEASSEMBLY, defaultValue: null),
                optimizationLevel: GetBooleanOption(CompilerOptions.OPTID_OPTIMIZATIONS) ? OptimizationLevel.Release : OptimizationLevel.Debug,
                outputKind: _outputKind,
                platform: platform,
                specificDiagnosticOptions: diagnosticOptions,
                warningLevel: warningLevel,
                xmlReferenceResolver: new XmlFileResolver(projectDirectory),
                sourceReferenceResolver: new SourceFileResolver(sourceSearchPaths, projectDirectory),
                metadataReferenceResolver: referenceResolver,
                assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default,
                strongNameProvider: new DesktopStrongNameProvider(GetStrongNameKeyPaths()));
        }