internal Result <LoadIncrementalState> Correct(
            LoadState state
            , LoadIncrementalState prediction
            , StructureInfo info)
        {
            Result <LoadIncrementalState> result = new Result <LoadIncrementalState>();

            LoadState            initialState        = state;
            LoadState            currentState        = initialState;
            LoadIncrementalState predictionIncrement = prediction;

            for (int iteration = 1; iteration <= MaximumIterations; iteration++)
            {
                Result <LoadIncrementalState> correction = GetCorrection(currentState, predictionIncrement, info);
                if (correction.IsSuccess)
                {
                    predictionIncrement.Add(correction.Value);
                    LoadState     newState    = currentState.Add(correction.Value);
                    List <double> errors      = GetErrors(newState, currentState, info).ToList();
                    bool          convergence = CheckConvergence(errors, Tolerances);
                    currentState = newState;
                    if (convergence)
                    {
                        result.Value = currentState.Substract(initialState);
                        break;
                    }
                }
                else
                {
                    result.Errors.AddRange(correction.Errors);
                }

                if (iteration >= MaximumIterations)
                {
                    result.Errors.Add(new Error(Strings.MaxNumberOfIterationsReached));
                }
            }

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

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

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

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

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

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

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

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

            var version = GetProjectVersion(projectFilePath);

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

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

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

            var analyzerLoader = analyzerService.GetLoader();

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

            var analyzerReferences = commandLineArgs.ResolveAnalyzerReferences(analyzerLoader);

            var defaultEncoding = commandLineArgs.Encoding;

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

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

            CheckDocuments(allDocFileInfos, projectFilePath, projectId);

            var docs = new List <DocumentInfo>();

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

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

            var additionalDocs = new List <DocumentInfo>();

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

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

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

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

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

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

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

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

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

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

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

            var resolver           = new RelativePathReferenceResolver(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 RelativePathReferenceResolver(ImmutableArray <string> .Empty, projectDirectory),
                    MetadataFileReferenceProvider.Default))
                              .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);
        }