/// <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); }
/// <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); }
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); }
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; }
/// <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); }
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)); }
/// <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; }
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())); }