예제 #1
0
        private static void UpdateCodeAnalysisRuleSetPropertyInConfiguration(EnvDTE.Configuration config, string oldRuleSetFilePath, string newRuleSetFilePath, string projectDirectoryFullPath)
        {
            EnvDTE.Properties properties = config.Properties;
            try
            {
                EnvDTE.Property codeAnalysisRuleSetFileProperty = properties?.Item("CodeAnalysisRuleSet");

                if (codeAnalysisRuleSetFileProperty != null)
                {
                    string codeAnalysisRuleSetFileName = codeAnalysisRuleSetFileProperty.Value as string;
                    if (!string.IsNullOrWhiteSpace(codeAnalysisRuleSetFileName))
                    {
                        string codeAnalysisRuleSetFullPath = FileUtilities.ResolveRelativePath(codeAnalysisRuleSetFileName, projectDirectoryFullPath);
                        codeAnalysisRuleSetFullPath = FileUtilities.NormalizeAbsolutePath(codeAnalysisRuleSetFullPath);
                        oldRuleSetFilePath          = FileUtilities.NormalizeAbsolutePath(codeAnalysisRuleSetFullPath);

                        if (codeAnalysisRuleSetFullPath.Equals(oldRuleSetFilePath, StringComparison.OrdinalIgnoreCase))
                        {
                            string newRuleSetRelativePath = FilePathUtilities.GetRelativePath(projectDirectoryFullPath, newRuleSetFilePath);
                            codeAnalysisRuleSetFileProperty.Value = newRuleSetRelativePath;
                        }
                    }
                }
            }
            catch (ArgumentException)
            {
                // Unfortunately the properties collection sometimes throws an ArgumentException
                // instead of returning null if the current configuration doesn't support CodeAnalysisRuleSet.
                // Ignore it and move on.
            }
        }
예제 #2
0
        public bool TryGetSerializationPrefixAndVersion(Solution solution, string assemblyFilePath, out string prefix, out VersionStamp version)
        {
            prefix  = FilePathUtilities.GetRelativePath(solution.FilePath, assemblyFilePath);
            version = VersionStamp.Create(File.GetLastWriteTimeUtc(assemblyFilePath));

            return(true);
        }
예제 #3
0
        public void AddMetadataReference(MetadataReference reference, AssemblyIdentity identity)
        {
            var peRef = reference as PortableExecutableReference;

            if (peRef != null && peRef.FilePath != null)
            {
                var metadata = new Dictionary <string, string>();
                if (!peRef.Properties.Aliases.IsEmpty)
                {
                    metadata.Add("Aliases", string.Join(",", peRef.Properties.Aliases));
                }

                if (IsInGAC(peRef.FilePath) && identity != null)
                {
                    // Since the location of the reference is in GAC, need to use full identity name to find it again.
                    // This typically happens when you base the reference off of a reflection assembly location.
                    _loadedProject.AddItem("Reference", identity.GetDisplayName(), metadata);
                }
                else if (IsFrameworkReferenceAssembly(peRef.FilePath))
                {
                    // just use short name since this will be resolved by msbuild relative to the known framework reference assemblies.
                    var fileName = identity != null ? identity.Name : Path.GetFileNameWithoutExtension(peRef.FilePath);
                    _loadedProject.AddItem("Reference", fileName, metadata);
                }
                else // other location -- need hint to find correct assembly
                {
                    string relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, peRef.FilePath);
                    var    fileName     = Path.GetFileNameWithoutExtension(peRef.FilePath);
                    metadata.Add("HintPath", relativePath);
                    _loadedProject.AddItem("Reference", fileName, metadata);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// this is for a metadata reference in a solution
        /// </summary>
        private static async Task <SymbolTreeInfo> LoadOrCreateAsync(Solution solution, IAssemblySymbol assembly, string filePath, CancellationToken cancellationToken)
        {
            // if assembly is not from a file, just create one on the fly
            if (filePath == null || !File.Exists(filePath) || !FilePathUtilities.PartOfFrameworkOrReferencePaths(filePath))
            {
                return(Create(VersionStamp.Default, assembly, cancellationToken));
            }

            // if solution is not from a disk, just create one.
            if (solution.FilePath == null || !File.Exists(solution.FilePath))
            {
                return(Create(VersionStamp.Default, assembly, cancellationToken));
            }

            // okay, see whether we can get one from persistence service.
            var relativePath = FilePathUtilities.GetRelativePath(solution.FilePath, filePath);
            var version      = VersionStamp.Create(File.GetLastWriteTimeUtc(filePath));

            var persistentStorageService = solution.Workspace.Services.GetService <IPersistentStorageService>();

            // attempt to load from persisted state. metadata reference is solution wise information
            SymbolTreeInfo info;

            using (var storage = persistentStorageService.GetStorage(solution))
            {
                var key = PrefixMetadataSymbolTreeInfo + relativePath;
                using (var stream = await storage.ReadStreamAsync(key, cancellationToken).ConfigureAwait(false))
                {
                    if (stream != null)
                    {
                        using (var reader = new ObjectReader(stream))
                        {
                            info = ReadFrom(reader);
                            if (info != null && VersionStamp.CanReusePersistedVersion(version, info.version))
                            {
                                return(info);
                            }
                        }
                    }
                }

                cancellationToken.ThrowIfCancellationRequested();

                // compute it if we couldn't load it from cache
                info = Create(version, assembly, cancellationToken);
                if (info != null)
                {
                    using (var stream = SerializableBytes.CreateWritableStream())
                        using (var writer = new ObjectWriter(stream, cancellationToken: cancellationToken))
                        {
                            info.WriteTo(writer);
                            stream.Position = 0;

                            await storage.WriteStreamAsync(key, stream, cancellationToken).ConfigureAwait(false);
                        }
                }
            }

            return(info);
        }
예제 #5
0
        public void RemoveDocument(string filePath)
        {
            var relativePath = FilePathUtilities.GetRelativePath(this.loadedProject.DirectoryPath, filePath);

            foreach (var item in this.loadedProject.GetItems("Compile").Where(i => i.EvaluatedInclude == relativePath).ToList())
            {
                this.loadedProject.RemoveItem(item);
            }
        }
예제 #6
0
        public void GetRelativePath_OnADifferentDrive()
        {
            string baseDirectory = @"C:\Alpha\Beta\Gamma";
            string fullPath      = @"D:\Alpha\Beta\Gamma\Doc.txt";

            string result = FilePathUtilities.GetRelativePath(baseDirectory, fullPath);

            Assert.Equal(expected: @"D:\Alpha\Beta\Gamma\Doc.txt", actual: result);
        }
예제 #7
0
        public void GetRelativePath_UpTwoLevelsAndThenDown()
        {
            string baseDirectory = @"C:\Alpha\Beta\Gamma";
            string fullPath      = @"C:\Alpha\Phi\Omega\Doc.txt";

            string result = FilePathUtilities.GetRelativePath(baseDirectory, fullPath);

            Assert.Equal(expected: @"..\..\Phi\Omega\Doc.txt", actual: result);
        }
예제 #8
0
        public void GetRelativePath_NestedTwoLevelsDown()
        {
            string baseDirectory = @"C:\Alpha\Beta\Gamma";
            string fullPath      = @"C:\Alpha\Beta\Gamma\Delta\Epsilon\Doc.txt";

            string result = FilePathUtilities.GetRelativePath(baseDirectory, fullPath);

            Assert.Equal(expected: @"Delta\Epsilon\Doc.txt", actual: result);
        }
        public void GetRelativePath_WithBaseDirectoryMatchingIncompletePortionOfFullPath()
        {
            string baseDirectory = @"C:\Alpha\Beta";
            string fullPath      = @"C:\Alpha\Beta2\Gamma";

            string result = FilePathUtilities.GetRelativePath(baseDirectory, fullPath);

            Assert.Equal(expected: @"..\Beta2\Gamma", actual: result);
        }
예제 #10
0
        public void RemoveProjectReference(string projectName, string projectFilePath)
        {
            string relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, projectFilePath);
            var    item         = FindProjectReferenceItem(projectName, projectFilePath);

            if (item != null)
            {
                _loadedProject.RemoveItem(item);
            }
        }
예제 #11
0
        public void AddAnalyzerReference(AnalyzerReference reference)
        {
            var fileRef = reference as AnalyzerFileReference;

            if (fileRef != null)
            {
                string relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, fileRef.FullPath);
                _loadedProject.AddItem("Analyzer", relativePath);
            }
        }
예제 #12
0
        private void SetActiveRuleSetHandler(object sender, EventArgs e)
        {
            if (_tracker.SelectedHierarchy.TryGetProject(out var project) &&
                _tracker.SelectedHierarchy.TryGetCanonicalName(_tracker.SelectedItemId, out var ruleSetFileFullPath))
            {
                string projectDirectoryFullPath = Path.GetDirectoryName(project.FullName);
                string ruleSetFileRelativePath  = FilePathUtilities.GetRelativePath(projectDirectoryFullPath, ruleSetFileFullPath);

                UpdateProjectConfigurationsToUseRuleSetFile(project, ruleSetFileRelativePath);
            }
        }
예제 #13
0
        public void RemoveDocument(string filePath)
        {
            var relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, filePath);

            var items = _loadedProject.GetItems("Compile");
            var item  = items.FirstOrDefault(it => FilePathUtilities.PathsEqual(it.EvaluatedInclude, relativePath) ||
                                             FilePathUtilities.PathsEqual(it.EvaluatedInclude, filePath));

            if (item != null)
            {
                _loadedProject.RemoveItem(item);
            }
        }
예제 #14
0
        public void AddProjectReference(string projectName, ProjectFileReference reference)
        {
            var metadata = new Dictionary <string, string>();

            metadata.Add("Name", projectName);

            if (!reference.Aliases.IsEmpty)
            {
                metadata.Add("Aliases", string.Join(",", reference.Aliases));
            }

            string relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, reference.Path);

            _loadedProject.AddItem("ProjectReference", relativePath, metadata);
        }
예제 #15
0
        public void AddDocument(string filePath, string logicalPath = null)
        {
            var relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, filePath);

            Dictionary <string, string> metadata = null;

            if (logicalPath != null && relativePath != logicalPath)
            {
                metadata = new Dictionary <string, string>();
                metadata.Add("link", logicalPath);
                relativePath = filePath; // link to full path
            }

            _loadedProject.AddItem("Compile", relativePath, metadata);
        }
예제 #16
0
        private MSB.Evaluation.ProjectItem FindReferenceItem(AssemblyIdentity identity, string filePath)
        {
            var references = _loadedProject.GetItems("Reference");

            MSB.Evaluation.ProjectItem item = null;

            var fileName = Path.GetFileNameWithoutExtension(filePath);

            if (identity != null)
            {
                var shortAssemblyName = identity.Name;
                var fullAssemblyName  = identity.GetDisplayName();

                // check for short name match
                item = references.FirstOrDefault(it => string.Compare(it.EvaluatedInclude, shortAssemblyName, StringComparison.OrdinalIgnoreCase) == 0);

                // check for full name match
                if (item == null)
                {
                    item = references.FirstOrDefault(it => string.Compare(it.EvaluatedInclude, fullAssemblyName, StringComparison.OrdinalIgnoreCase) == 0);
                }
            }

            // check for file path match
            if (item == null)
            {
                string relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, filePath);

                item = references.FirstOrDefault(it => FilePathUtilities.PathsEqual(it.EvaluatedInclude, filePath) ||
                                                 FilePathUtilities.PathsEqual(it.EvaluatedInclude, relativePath) ||
                                                 FilePathUtilities.PathsEqual(GetHintPath(it), filePath) ||
                                                 FilePathUtilities.PathsEqual(GetHintPath(it), relativePath));
            }

            // check for partial name match
            if (item == null && identity != null)
            {
                var partialName = identity.Name + ",";
                var items       = references.Where(it => it.EvaluatedInclude.StartsWith(partialName, StringComparison.OrdinalIgnoreCase)).ToList();
                if (items.Count == 1)
                {
                    item = items[0];
                }
            }

            return(item);
        }
예제 #17
0
        public void RemoveAnalyzerReference(AnalyzerReference reference)
        {
            var fileRef = reference as AnalyzerFileReference;

            if (fileRef != null)
            {
                string relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, fileRef.FullPath);

                var analyzers = _loadedProject.GetItems("Analyzer");
                var item      = analyzers.FirstOrDefault(it => FilePathUtilities.PathsEqual(it.EvaluatedInclude, relativePath) ||
                                                         FilePathUtilities.PathsEqual(it.EvaluatedInclude, fileRef.FullPath));
                if (item != null)
                {
                    _loadedProject.RemoveItem(item);
                }
            }
        }
예제 #18
0
        private MSB.Evaluation.ProjectItem FindProjectReferenceItem(string projectName, string projectFilePath)
        {
            var    references   = _loadedProject.GetItems("ProjectReference");
            string relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, projectFilePath);

            MSB.Evaluation.ProjectItem item = null;

            // find by project file path
            item = references.First(it => FilePathUtilities.PathsEqual(it.EvaluatedInclude, relativePath) ||
                                    FilePathUtilities.PathsEqual(it.EvaluatedInclude, projectFilePath));

            // try to find by project name
            if (item == null)
            {
                item = references.First(it => string.Compare(projectName, it.GetMetadataValue("Name"), StringComparison.OrdinalIgnoreCase) == 0);
            }

            return(item);
        }
예제 #19
0
        private bool TryGetUniqueId(string value, bool fileCheck, out int id)
        {
            id = default(int);

            if (string.IsNullOrWhiteSpace(value))
            {
                return(false);
            }

            // if we already know, get the id
            if (_nameTableCache.TryGetValue(value, out id))
            {
                return(true);
            }

            // we only persist for things that actually exist
            if (fileCheck && !File.Exists(value))
            {
                return(false);
            }

            try
            {
                id = _nameTableCache.GetOrAdd(value, v =>
                {
                    // okay, get one from esent
                    var relativePathFromSolution = FilePathUtilities.GetRelativePath(Path.GetDirectoryName(SolutionFilePath), v);
                    return(_esentStorage.GetUniqueId(relativePathFromSolution));
                });
            }
            catch (Exception ex)
            {
                // if we get fatal errors from esent such as disk out of space or log file corrupted by other process and etc
                // don't crash VS, but let VS know it can't use esent. we will gracefully recover issue by using memory.
                EsentLogger.LogException(ex);

                return(false);
            }

            return(true);
        }
예제 #20
0
        public void AddMetadataReference(MetadataReference reference, AssemblyIdentity identity)
        {
            var peRef = reference as PortableExecutableReference;

            if (peRef != null && peRef.FilePath != null)
            {
                var metadata = new Dictionary <string, string>();
                if (!peRef.Properties.Aliases.IsEmpty)
                {
                    metadata.Add("Aliases", string.Join(",", peRef.Properties.Aliases));
                }

                if (IsInGAC(peRef.FilePath) && identity != null)
                {
                    _loadedProject.AddItem("Reference", identity.GetDisplayName(), metadata);
                }
                else
                {
                    string relativePath = FilePathUtilities.GetRelativePath(_loadedProject.DirectoryPath, peRef.FilePath);
                    _loadedProject.AddItem("Reference", relativePath, metadata);
                }
            }
        }
예제 #21
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);
        }
예제 #22
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);
        }