/// <summary>
        /// Attempt to find references to the C++ project in the C# project. First by id, then by name/path. Matching by id looks like it will always
        /// fail due to <see cref="MSBuildProjectLoader.Worker.ResolvedReferenceBuilder.ResolveReferencesAsync"/> which will create a dummy id for
        /// unrecognised projects, rather than reading the real id out of the solution file.
        /// </summary>
        private static bool ProjectReferencesProject(Project project, CppProject cppProject)
        {
            var referencedProjectIds = project.AllProjectReferences.Select(p => p.ProjectId);
            // Roslyn doesn't set ids for unrecognised projects so this probably won't match.
            bool anyIdsMatch = referencedProjectIds.Any(p => p.Id == cppProject.Id);

            if (anyIdsMatch)
            {
                return(true);
            }

            // Match on (debug) name since id is expected to fail.
            var debugNameExpression = new Regex($@"#{Constants.GuidExpression} - (?<DebugName>.*)\)");
            var debugNames          = referencedProjectIds.Select(p => debugNameExpression.Match(p.ToString()).Groups["DebugName"].Value);
            // Debug names contain relative paths to the referenced project. Turn them into absolute paths so they can be matched to the C++ projects.
            string root = new FileInfo(project.FilePath).DirectoryName;

            foreach (var projectId in referencedProjectIds)
            {
                string debugName     = debugNameExpression.Match(projectId.ToString()).Groups["DebugName"].Value;
                string referencePath = Path.Combine(root, debugName);
                string canonicalPath = Path.GetFullPath(referencePath);
                if (canonicalPath.Equals(cppProject.FilePath, StringComparison.OrdinalIgnoreCase))
                {
                    return(true);
                }
            }

            return(false);
        }
Ejemplo n.º 2
0
        private void LoadSolution_WorkspaceFailed(object sender, WorkspaceDiagnosticEventArgs e)
        {
            if (e.Diagnostic.Kind == WorkspaceDiagnosticKind.Failure && _cppProjectExpression.IsMatch(e.Diagnostic.Message))
            {
                string path    = _cppProjectExpression.Match(e.Diagnostic.Message).Groups["path"].Value;
                var    project = new CppProject();
                project.Load(path);
                var solutionProject = _solutionProjects.SingleOrDefault(p => p.FilePath.Equals(project.FilePath, StringComparison.OrdinalIgnoreCase));
                if (solutionProject == null)
                {
                    _log.Warning($"Failed to locate C++ project ${project.FilePath} in solution. Project id will be invalid for this project.");
                    project.SetId(Guid.NewGuid());
                }
                else
                {
                    project.SetId(solutionProject.Id);
                }

                // Add the project via the private property since the solution is not yet loaded.
                _cppProjects.Add(project);
                _log.Warning($"C++ project found at {path}. Analysis results may be unreliable due to lack of Roslyn support for vcxproj analysis. Custom analysis will be performed for C++ changes");
                ++_loadWarningCount;
                return;
            }

            switch (e.Diagnostic.Kind)
            {
            case WorkspaceDiagnosticKind.Failure:
                _log.Warning(e.Diagnostic.Message);
                ++_loadErrorCount;
                break;

            case WorkspaceDiagnosticKind.Warning:
                _log.Information(e.Diagnostic.Message);
                ++_loadWarningCount;
                break;
            }
        }
 private static AnalysisResult CreateAnalysisResult(CppProject cppProject, int distance) => new AnalysisResult(cppProject.Name, cppProject.FilePath, distance, $"{cppProject.AssemblyName}.dll");