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