示例#1
0
        /// <summary>
        /// Resolves metadata references stored in command line arguments and reports errors for those that can't be resolved.
        /// </summary>
        internal List <MetadataReference> ResolveMetadataReferences(
            MetadataFileReferenceResolver externalReferenceResolver,
            MetadataFileReferenceProvider metadataProvider,
            List <DiagnosticInfo> diagnostics,
            AssemblyIdentityComparer assemblyIdentityComparer,
            TouchedFileLogger touchedFiles,
            out MetadataFileReferenceResolver referenceDirectiveResolver)
        {
            List <MetadataReference> resolved = new List <MetadataReference>();

            Arguments.ResolveMetadataReferences(new AssemblyReferenceResolver(externalReferenceResolver, metadataProvider), diagnostics, this.MessageProvider, resolved);

            if (Arguments.IsInteractive)
            {
                referenceDirectiveResolver = externalReferenceResolver;
            }
            else
            {
                // when compiling into an assembly (csc/vbc) we only allow #r that match references given on command line:
                referenceDirectiveResolver = new ExistingReferencesResolver(
                    resolved.Where(r => r.Properties.Kind == MetadataImageKind.Assembly).OfType <PortableExecutableReference>().AsImmutable(),
                    Arguments.ReferencePaths,
                    Arguments.BaseDirectory,
                    assemblyIdentityComparer,
                    touchedFiles);
            }

            return(resolved);
        }
            public ExistingReferencesResolver(
                MetadataFileReferenceResolver resolver,
                ImmutableArray <PortableExecutableReference> availableReferences,
                AssemblyIdentityComparer assemblyIdentityComparer)
            {
                Debug.Assert(!availableReferences.Any(r => r.Properties.Kind != MetadataImageKind.Assembly));

                _resolver                 = resolver;
                _availableReferences      = availableReferences;
                _assemblyIdentityComparer = assemblyIdentityComparer;
            }
            public ExistingReferencesResolver(
                MetadataFileReferenceResolver resolver,
                ImmutableArray<PortableExecutableReference> availableReferences,
                AssemblyIdentityComparer assemblyIdentityComparer)
            {
                Debug.Assert(!availableReferences.Any(r => r.Properties.Kind != MetadataImageKind.Assembly));

                _resolver = resolver;
                _availableReferences = availableReferences;
                _assemblyIdentityComparer = assemblyIdentityComparer;
            }
示例#4
0
        /// <summary>
        /// Create a ProjectInfo structure initialized from a compilers command line arguments.
        /// </summary>
        public static ProjectInfo CreateProjectInfo(Workspace workspace, string projectName, string language, IEnumerable <string> commandLineArgs, string projectDirectory)
        {
            // TODO (tomat): the method may throw all sorts of exceptions.

            var languageServices = workspace.Services.GetLanguageServices(language);

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

            var commandLineArgumentsFactory = languageServices.GetService <ICommandLineArgumentsFactoryService>();
            var commandLineArguments        = commandLineArgumentsFactory.CreateCommandLineArguments(commandLineArgs, projectDirectory, isInteractive: false);

            // TODO (tomat): to match csc.exe/vbc.exe we should use CommonCommandLineCompiler.ExistingReferencesResolver to deal with #r's
            var referenceResolver  = new MetadataFileReferenceResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory);
            var referenceProvider  = MetadataFileReferenceProvider.Default;
            var xmlFileResolver    = new XmlFileResolver(commandLineArguments.BaseDirectory);
            var strongNameProvider = new DesktopStrongNameProvider(commandLineArguments.KeyFileSearchPaths);

            // resolve all metadata references.
            var boundMetadataReferences      = commandLineArguments.ResolveMetadataReferences(referenceResolver, referenceProvider);
            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.
            var boundAnalyzerReferences      = commandLineArguments.ResolveAnalyzerReferences();
            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>();
            var ids  = new HashSet <DocumentId>();

            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 = !Path.IsPathRooted(relativePath);

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

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

                docs.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)
                .WithMetadataReferenceResolver(referenceResolver)
                .WithMetadataReferenceProvider(referenceProvider),
                parseOptions: commandLineArguments.ParseOptions,
                documents: docs,
                metadataReferences: boundMetadataReferences,
                analyzerReferences: boundAnalyzerReferences);

            return(projectInfo);
        }
        /// <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 commandLineArgumentsFactory = languageServices.GetRequiredService<ICommandLineArgumentsFactoryService>();
            var commandLineArguments = commandLineArgumentsFactory.CreateCommandLineArguments(commandLineArgs, projectDirectory, isInteractive: false);

            // TODO (tomat): to match csc.exe/vbc.exe we should use CommonCommandLineCompiler.ExistingReferencesResolver to deal with #r's
            var referenceResolver = new MetadataFileReferenceResolver(commandLineArguments.ReferencePaths, commandLineArguments.BaseDirectory);
            var referenceProvider = tmpWorkspace.Services.GetRequiredService<IMetadataService>().GetProvider();
            var analyzerService = tmpWorkspace.Services.GetRequiredService<IAnalyzerService>();
            var xmlFileResolver = new XmlFileResolver(commandLineArguments.BaseDirectory);
            var strongNameProvider = new DesktopStrongNameProvider(commandLineArguments.KeyFileSearchPaths);

            // resolve all metadata references.
            var boundMetadataReferences = commandLineArguments.ResolveMetadataReferences(new AssemblyReferenceResolver(referenceResolver, referenceProvider));
            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.
            var boundAnalyzerReferences = commandLineArguments.ResolveAnalyzerReferences(analyzerService.GetAnalyzer);
            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)
                    .WithMetadataReferenceResolver(new AssemblyReferenceResolver(referenceResolver, referenceProvider)),
                parseOptions: commandLineArguments.ParseOptions,
                documents: docs,
                additionalDocuments: additionalDocs,
                metadataReferences: boundMetadataReferences,
                analyzerReferences: boundAnalyzerReferences);

            return projectInfo;
        }
            private void GetReferences(
                CSharpCompilerInputs compilerInputs,
                MSB.Execution.ProjectInstance executedProject,
                out IEnumerable<MetadataReference> metadataReferences,
                out IEnumerable<AnalyzerReference> analyzerReferences)
            {
                // use command line parser to do reference translation same as command line compiler

                var args = new List<string>();

                if (compilerInputs.LibPaths != null && compilerInputs.LibPaths.Count > 0)
                {
                    args.Add("/lib:\"" + string.Join(";", compilerInputs.LibPaths) + "\"");
                }

                foreach (var mr in compilerInputs.References)
                {
                    if (!IsProjectReferenceOutputAssembly(mr))
                    {
                        var filePath = GetDocumentFilePath(mr);

                        var aliases = GetAliases(mr);
                        if (aliases.IsDefaultOrEmpty)
                        {
                            args.Add("/r:\"" + filePath + "\"");
                        }
                        else
                        {
                            foreach (var alias in aliases)
                            {
                                args.Add("/r:" + alias + "=\"" + filePath + "\"");
                            }
                        }
                    }
                }

                foreach (var ar in compilerInputs.AnalyzerReferences)
                {
                    var filePath = GetDocumentFilePath(ar);
                    args.Add("/a:\"" + filePath + "\"");
                }

                if (compilerInputs.NoStandardLib)
                {
                    args.Add("/nostdlib");
                }

                var commandLineArgs = _commandLineArgumentsFactoryService.CreateCommandLineArguments(args, executedProject.Directory, isInteractive: false, sdkDirectory: RuntimeEnvironment.GetRuntimeDirectory());

                var resolver = new MetadataFileReferenceResolver(commandLineArgs.ReferencePaths, commandLineArgs.BaseDirectory);
                metadataReferences = commandLineArgs.ResolveMetadataReferences(new AssemblyReferenceResolver(resolver, _metadataService.GetProvider()));

                var analyzerLoader = _analyzerService.GetLoader();
                foreach (var path in commandLineArgs.AnalyzerReferences.Select(r => r.FilePath))
                {
                    analyzerLoader.AddDependencyLocation(path);
                }
                analyzerReferences = commandLineArgs.ResolveAnalyzerReferences(analyzerLoader);
            }
示例#7
0
        /// <summary>
        /// Resolves metadata references stored in command line arguments and reports errors for those that can't be resolved.
        /// </summary>
        internal List<MetadataReference> ResolveMetadataReferences(
            MetadataFileReferenceResolver externalReferenceResolver,
            MetadataFileReferenceProvider metadataProvider,
            List<DiagnosticInfo> diagnostics,
            AssemblyIdentityComparer assemblyIdentityComparer,
            TouchedFileLogger touchedFiles,
            out MetadataFileReferenceResolver referenceDirectiveResolver)
        {
            List<MetadataReference> resolved = new List<MetadataReference>();
            Arguments.ResolveMetadataReferences(new AssemblyReferenceResolver(externalReferenceResolver, metadataProvider), diagnostics, this.MessageProvider, resolved);

            if (Arguments.IsInteractive)
            {
                referenceDirectiveResolver = externalReferenceResolver;
            }
            else
            {
                // when compiling into an assembly (csc/vbc) we only allow #r that match references given on command line:
                referenceDirectiveResolver = new ExistingReferencesResolver(
                    CreateLoggingMetadataResolver(touchedFiles),
                    resolved.Where(r => r.Properties.Kind == MetadataImageKind.Assembly).OfType<PortableExecutableReference>().AsImmutable(),
                    assemblyIdentityComparer);
            }

            return resolved;
        }
 public LoggingMetadataReferencesResolver(MetadataFileReferenceResolver resolver, TouchedFileLogger logger)
 {
     Debug.Assert(logger != null);
     _resolver = resolver;
     _logger = logger;
 }
示例#9
0
 public LoggingMetadataReferencesResolver(MetadataFileReferenceResolver resolver, TouchedFileLogger logger)
 {
     Debug.Assert(logger != null);
     _resolver = resolver;
     _logger   = logger;
 }
示例#10
0
 public AssemblyReferenceResolver(MetadataFileReferenceResolver pathResolver, MetadataFileReferenceProvider provider)
 {
     Debug.Assert(pathResolver != null && provider != null);
     this.PathResolver = pathResolver;
     this.Provider     = provider;
 }
            private void GetReferences(
                CSharpCompilerInputs compilerInputs,
                MSB.Execution.ProjectInstance executedProject,
                out IEnumerable<MetadataReference> metadataReferences,
                out IEnumerable<AnalyzerReference> analyzerReferences)
            {
                // use command line parser to do reference translation same as command line compiler

                var args = new List<string>();

                if (compilerInputs.LibPaths != null && compilerInputs.LibPaths.Count > 0)
                {
                    args.Add("/lib:\"" + string.Join(";", compilerInputs.LibPaths) + "\"");
                }

                foreach (var mr in compilerInputs.References)
                {
                    var filePath = GetDocumentFilePath(mr);

                    var aliases = GetAliases(mr);
                    if (aliases.IsDefaultOrEmpty)
                    {
                        args.Add("/r:\"" + filePath + "\"");
                    }
                    else
                    {
                        foreach (var alias in aliases)
                        {
                            args.Add("/r:" + alias + "=\"" + filePath + "\"");
                        }
                    }
                }

                foreach (var ar in compilerInputs.AnalyzerReferences)
                {
                    var filePath = GetDocumentFilePath(ar);
                    args.Add("/a:\"" + filePath + "\"");
                }

                if (compilerInputs.NoStandardLib)
                {
                    args.Add("/nostdlib");
                }

                var commandLineParser = CSharpCommandLineParser.Default;
                var commandLineArgs = commandLineParser.Parse(args, executedProject.Directory);

                var resolver = new MetadataFileReferenceResolver(commandLineArgs.ReferencePaths, commandLineArgs.BaseDirectory);
                metadataReferences = commandLineArgs.ResolveMetadataReferences(new AssemblyReferenceResolver(resolver, _metadataService.GetProvider()));
                analyzerReferences = commandLineArgs.ResolveAnalyzerReferences();
            }
示例#12
0
        /// <summary>
        /// Creates a new <see cref="ScriptOptions"/> with the reference resolver specified.
        /// </summary>
        internal ScriptOptions WithReferenceResolver(MetadataFileReferenceResolver resolver)
        {
            if (resolver == _referenceResolver.PathResolver)
            {
                return this;
            }

            return With(resolver: new AssemblyReferenceResolver(resolver, _referenceResolver.Provider));
        }
示例#13
0
        private async Task<ProjectId> LoadProjectAsync(string projectFilePath, IProjectFileLoader loader, bool preferMetadata, Dictionary<ProjectId, ProjectInfo> loadedProjects, CancellationToken cancellationToken)
        {
            Debug.Assert(projectFilePath != null);
            Debug.Assert(loader != null);

            var projectId = this.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 = this.Services.GetLanguageServices(loader.Language).GetService<ICommandLineParserService>();
            var metadataService = this.Services.GetService<IMetadataService>();
            var analyzerService = this.Services.GetService<IAnalyzerService>();

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

            var resolver = new MetadataFileReferenceResolver(commandLineArgs.ReferencePaths, commandLineArgs.BaseDirectory);
            var metadataReferences = commandLineArgs.ResolveMetadataReferences(new AssemblyReferenceResolver(resolver, metadataService.GetProvider()));

            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 this.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))
                    .WithMetadataReferenceResolver(
                        new AssemblyReferenceResolver(
                            new MetadataFileReferenceResolver(ImmutableArray<string>.Empty, projectDirectory),
                            MetadataFileReferenceProvider.Default))
                    .WithStrongNameProvider(new DesktopStrongNameProvider(ImmutableArray.Create(projectDirectory, outputFilePath)))
                    .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default);

            loadedProjects.Add(
                projectId,
                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;
        }
 public AssemblyReferenceResolver(MetadataFileReferenceResolver pathResolver, MetadataFileReferenceProvider provider)
 {
     Debug.Assert(pathResolver != null && provider != null);
     this.PathResolver = pathResolver;
     this.Provider = provider;
 }