/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { ProjectInstance projectInstance = projectGraphNode.ProjectInstance; // The GetCopyToOutputDirectoryItems target gets called on all dependencies, unless UseCommonOutputDirectory is set to true. var useCommonOutputDirectory = projectInstance.GetPropertyValue(UseCommonOutputDirectoryPropertyName); if (!useCommonOutputDirectory.Equals("true", StringComparison.OrdinalIgnoreCase)) { string outDir = projectInstance.GetPropertyValue(OutDirPropertyName); // Note that GetCopyToOutputDirectoryItems effectively only is able to go one project reference deep despite being recursive as // it uses @(_MSBuildProjectReferenceExistent) to recurse, which is not set in the recursive calls. // See: https://github.com/microsoft/msbuild/blob/master/src/Tasks/Microsoft.Common.CurrentVersion.targets foreach (ProjectGraphNode dependency in projectGraphNode.ProjectReferences) { // Process each item type considered in GetCopyToOutputDirectoryItems. Yes, Compile is considered. ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, ContentItemsPredictor.ContentItemName, outDir, predictionReporter); ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, EmbeddedResourceItemsPredictor.EmbeddedResourceItemName, outDir, predictionReporter); ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, CompileItemsPredictor.CompileItemName, outDir, predictionReporter); ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, NoneItemsPredictor.NoneItemName, outDir, predictionReporter); // Process each item type considered in GetCopyToOutputDirectoryXamlAppDefs ReportCopyToOutputDirectoryItemsAsInputs(dependency.ProjectInstance, XamlAppDefPredictor.XamlAppDefItemName, outDir, predictionReporter); } } }
public static void AssertOuterBuildAsNonRoot( ProjectGraphNode outerBuild, ProjectGraph graph, Dictionary <string, string> additionalGlobalProperties = null, int expectedInnerBuildCount = 2) { additionalGlobalProperties ??= new Dictionary <string, string>(); AssertOuterBuildEvaluation(outerBuild, additionalGlobalProperties); outerBuild.ProjectReferences.ShouldBeEmpty(); outerBuild.ReferencingProjects.ShouldNotBeEmpty(); foreach (var outerBuildReferencer in outerBuild.ReferencingProjects) { var innerBuilds = outerBuildReferencer.ProjectReferences.Where( p => IsInnerBuild(p) && p.ProjectInstance.FullPath == outerBuild.ProjectInstance.FullPath).ToArray(); innerBuilds.Length.ShouldBe(expectedInnerBuildCount); foreach (var innerBuild in innerBuilds) { AssertInnerBuildEvaluation(innerBuild, true, additionalGlobalProperties); innerBuild.ReferencingProjects.ShouldContain(outerBuildReferencer); innerBuild.ReferencingProjects.ShouldNotContain(outerBuild); graph.TestOnly_Edges.HasEdge((outerBuild, innerBuild)).ShouldBeFalse(); var edgeToOuterBuild = graph.TestOnly_Edges[(outerBuildReferencer, outerBuild)];
public GraphVisNode(ProjectGraphNode node) { _node = node; var(name, label) = GetNodeInfo(node); Name = name; _label = label; }
private void ExpandGraphNode(SolutionGraph graph, ProjectGraphNode node) { if (node.IsAlreadyExpanded) { return; } foreach (var projectRef in node.Project.ProjectReferences) { var projectRefNode = TryCreateGraphNode(graph, projectRef); if (projectRefNode != null) { node.ProjectRequirements.Add(projectRefNode); } } var nugetPackages = _nugetReferenceReader.TryReadPackagesConfig(node.Project.ProjectDirectory); foreach (var fileReference in node.Project.FileReferences) { var nugetPackage = nugetPackages?.FindPackage(fileReference.Include.ID); if (nugetPackage != null) { var nugetReference = new NugetReference(node.Project, nugetPackage, fileReference.GetFile(), fileReference.VersionFromPath ?? VersionWithSuffix.Empty()); node.NugetPackageRequirements.Add(nugetReference); } else { var reference = new ReferencedFile(node.Project, fileReference.GetFile(), fileReference.Include.Version); node.FileRequirements.Add(reference); } } }
public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { foreach (ProjectGraphNode dependency in projectGraphNode.ProjectReferences) { var dependencyDir = dependency.ProjectInstance.Directory; foreach (string item in _inputFiles) { predictionReporter.ReportInputFile(Path.GetFullPath(Path.Combine(dependencyDir, item))); } foreach (string item in _inputDirectories) { predictionReporter.ReportInputDirectory(Path.GetFullPath(Path.Combine(dependencyDir, item))); } foreach (string item in _outputFiles) { predictionReporter.ReportOutputFile(Path.GetFullPath(Path.Combine(dependencyDir, item))); } foreach (string item in _outputDirectories) { predictionReporter.ReportOutputDirectory(Path.GetFullPath(Path.Combine(dependencyDir, item))); } } }
/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { var seenGraphNodes = new HashSet <ProjectGraphNode>(projectGraphNode.ProjectReferences); var graphNodesToProcess = new Queue <ProjectGraphNode>(projectGraphNode.ProjectReferences); while (graphNodesToProcess.Count > 0) { ProjectGraphNode currentNode = graphNodesToProcess.Dequeue(); // Predict the project file itself and all its imports. predictionReporter.ReportInputFile(currentNode.ProjectInstance.FullPath); foreach (string import in currentNode.ProjectInstance.ImportPaths) { predictionReporter.ReportInputFile(import); } // Recurse transitively foreach (ProjectGraphNode projectReference in currentNode.ProjectReferences) { if (seenGraphNodes.Add(projectReference)) { graphNodesToProcess.Enqueue(projectReference); } } } }
public GraphVisNode(ProjectGraphNode node, IEnumerable <string> entryTargets) { _node = node; _entryTargets = entryTargets; var(name, label) = GetNodeInfo(node); Name = name; _label = label; }
/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { if (IsPublishing(projectGraphNode.ProjectInstance)) { string publishDir = projectGraphNode.ProjectInstance.GetPropertyValue(PublishDirPropertyName); PredictInputsAndOutputs(projectGraphNode, publishDir, predictionReporter); } }
public SolutionGraph BuildGraph(Project project) { var graph = new SolutionGraph(null); var root = new ProjectGraphNode(project, graph); graph.AddNode(root, true); ExpandGraphNode(graph, root); return(graph); }
private ProjectGraphNodeAdapter(ProjectGraphNode adaptedNode, NodeProvider nodeProvider) { AdaptedNode = adaptedNode; _parents = new Lazy <IReadOnlyCollection <IGraphNode> >( () => adaptedNode.ReferencingProjects.Select(n => nodeProvider.FromProjectGraphNode(n)).ToArray()); _children = new Lazy <IReadOnlyCollection <IGraphNode> >( () => adaptedNode.ProjectReferences.Select(n => nodeProvider.FromProjectGraphNode(n)).ToArray()); }
public void ConstructWithMultipleNodes() { using (var env = TestEnvironment.Create()) { CreateProjectFile(env, 1, new[] { 4, 5 }); TransientTestFile entryProject = CreateProjectFile(env, 2, new[] { 3, 5, 6 }); CreateProjectFile(env, 3); CreateProjectFile(env, 4); CreateProjectFile(env, 5, new[] { 7 }); CreateProjectFile(env, 6, new[] { 1 }); CreateProjectFile(env, 7); ProjectGraph graph = new ProjectGraph(entryProject.Path); graph.ProjectNodes.Count.ShouldBe(7); ProjectGraphNode node1 = GetNodeForProject(graph, 1); ProjectGraphNode node2 = GetNodeForProject(graph, 2); ProjectGraphNode node3 = GetNodeForProject(graph, 3); ProjectGraphNode node4 = GetNodeForProject(graph, 4); ProjectGraphNode node5 = GetNodeForProject(graph, 5); ProjectGraphNode node6 = GetNodeForProject(graph, 6); ProjectGraphNode node7 = GetNodeForProject(graph, 7); node1.ProjectReferences.Count.ShouldBe(2); node2.ProjectReferences.Count.ShouldBe(3); node3.ProjectReferences.Count.ShouldBe(0); node4.ProjectReferences.Count.ShouldBe(0); node5.ProjectReferences.Count.ShouldBe(1); node6.ProjectReferences.Count.ShouldBe(1); node7.ProjectReferences.Count.ShouldBe(0); node1.ReferencingProjects.Count.ShouldBe(1); node2.ReferencingProjects.Count.ShouldBe(0); node3.ReferencingProjects.Count.ShouldBe(1); node4.ReferencingProjects.Count.ShouldBe(1); node5.ReferencingProjects.Count.ShouldBe(2); node6.ReferencingProjects.Count.ShouldBe(1); node7.ReferencingProjects.Count.ShouldBe(1); // confirm that there is a path from 2 -> 6 -> 1 -> 5 -> 7 node2.ProjectReferences.ShouldContain(node6); node6.ProjectReferences.ShouldContain(node1); node1.ProjectReferences.ShouldContain(node5); node5.ProjectReferences.ShouldContain(node7); // confirm that there is a path from 7 -> 5 -> 1 -> 6 -> 2 using ReferencingProjects node7.ReferencingProjects.ShouldContain(node5); node5.ReferencingProjects.ShouldContain(node1); node1.ReferencingProjects.ShouldContain(node6); node6.ReferencingProjects.ShouldContain(node2); } }
internal static void PredictInputsAndOutputs( ProjectGraphNode projectGraphNode, string publishDir, ProjectPredictionReporter predictionReporter) { ReportCopyToPublishDirectoryItems(projectGraphNode.ProjectInstance, publishDir, predictionReporter); // Note that GetCopyToPublishDirectoryItems effectively only is able to go one project reference deep despite appearing recursive for the same reasons as GetCopyToOutputDirectoryItems. // See: https://github.com/dotnet/sdk/blob/master/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets foreach (ProjectGraphNode dependency in projectGraphNode.ProjectReferences) { ReportCopyToPublishDirectoryItems(dependency.ProjectInstance, publishDir, predictionReporter); } }
/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { ProjectInstance projectInstance = projectGraphNode.ProjectInstance; // This predictor only applies to sfproj files if (!projectInstance.FullPath.EndsWith(".sfproj", StringComparison.OrdinalIgnoreCase)) { return; } if (projectGraphNode.ProjectReferences.Count == 0) { return; } string servicePackageRootFolder = projectInstance.GetPropertyValue(ServicePackageRootFolderPropertyName); if (string.IsNullOrEmpty(servicePackageRootFolder)) { return; } foreach (ProjectGraphNode projectReference in projectGraphNode.ProjectReferences) { // This emulates the behavior of the GetPackageRootFiles task. // We do not emulate the behavior of the FilterPackageFiles task as it requires parsing the service manifest // and the extra cost and complexity does not outweigh the slight overprediction. // For the same reason we are not doing output prediction. string projectFolder = Path.GetFullPath(Path.GetDirectoryName(projectReference.ProjectInstance.FullPath)); string fullPackageRootPath = Path.Combine(projectFolder, servicePackageRootFolder); if (fullPackageRootPath[fullPackageRootPath.Length - 1] != Path.DirectorySeparatorChar) { fullPackageRootPath += Path.DirectorySeparatorChar; } // Add files from none and content items under the package root path. // This is basically the same as the directory enumeration below, but there are some slight differences, so emulating // the odd behavior of GetPackageRootFiles is preferable to potentially being wrong. AddPackageRootFilesFromItems(projectReference.ProjectInstance.GetItems(NoneItemsPredictor.NoneItemName), projectFolder, fullPackageRootPath, predictionReporter); AddPackageRootFilesFromItems(projectReference.ProjectInstance.GetItems(ContentItemsPredictor.ContentItemName), projectFolder, fullPackageRootPath, predictionReporter); // Add files under the package root path. string[] packageRootFilesInFileSystem = Directory.GetFiles(fullPackageRootPath, "*", SearchOption.AllDirectories); foreach (string packageRootFileInFileSystem in packageRootFilesInFileSystem) { predictionReporter.ReportInputFile(packageRootFileInFileSystem); } } }
private TreeNode AdaptGraphNode(ProjectGraphNode node) { Interlocked.Increment(ref _counts); TreeNode treeNode = new TreeNode(node.ProjectInstance.FullPath) { Tag = node }; foreach (var child in node.ProjectReferences) { treeNode.Nodes.Add(AdaptGraphNode(child)); } return(treeNode); }
private static (string, string) GetNodeInfo(ProjectGraphNode node) { var label = Path.GetFileNameWithoutExtension(node.ProjectInstance.FullPath); if (!_nodes.ContainsKey(node)) { _nodes.Add(node, label.Replace(".", string.Empty) + _count); _count++; } var name = _nodes[node]; //var name = _current;//label + Program.HashGlobalProps(node.ProjectInstance.GlobalProperties); return(name, label); }
private static (string, string) GetNodeInfo(ProjectGraphNode node) { // labels with '-' in them screw up graphvis so replace them with '_' var label = Path.GetFileNameWithoutExtension(node.ProjectInstance.FullPath).Replace("-", "_"); if (!Nodes.ContainsKey(node)) { Nodes.Add(node, label.Replace(".", string.Empty) + Count); Count++; } var name = Nodes[node]; //var name = _current;//label + Program.HashGlobalProps(node.ProjectInstance.GlobalProperties); return(name, label); }
void AddProjectToGraph(ReferenceGraph graph, Project project) { ProjectGraphNode root = (graph.Add <ProjectGraphNode>(project) as ProjectGraphNode); foreach (Project reference in project.References) { ProjectGraphNode child = graph.Nodes.Where(x => x.File == reference).FirstOrDefault() as ProjectGraphNode; if (child == null) { child = (graph.Add <ProjectGraphNode>(root, reference) as ProjectGraphNode); } else { child.AddDependency(root); } } }
public static IEnumerable <ProjectGraphNode> FindNodesThatDependOn( this ProjectGraph graph, ProjectGraphNode targetNode) { var targetNodeIsKnown = false; foreach (var currentNode in graph.ProjectNodes) { // ignore the target node if (currentNode == targetNode) { targetNodeIsKnown = true; continue; } foreach (var dependency in currentNode.ProjectReferences) { // current project depends on targetNode if (dependency == targetNode) { // if targetNode changes, currentNode will be affected. yield return(currentNode); // since currentNode depends on targetNode, // we also need to check which projects the currentNode depends on // since they could be affected by the changes made on targetNode foreach (var childDep in graph.FindNodesThatDependOn(currentNode)) { yield return(childDep); } } } } if (!targetNodeIsKnown) { throw new InvalidOperationException($"Requested to find {targetNode.ProjectInstance.FullPath} but its not present in known projects"); } }
public static void PrintProjectInstanceContents(ProjectGraphNode node) { if (!DebugBuild) { return; } Console.WriteLine( $"->->-> {node.CacheFileName()}.ProjectReferenceTargetsForBuild = {node.ProjectInstance.GetProperty("ProjectReferenceTargetsForBuild").EvaluatedValue}"); var projectReferenceTargetsItems = node.ProjectInstance.GetItems("ProjectReferenceTargets"); Console.WriteLine($"->->-> ProjectReferenceTargets count: {projectReferenceTargetsItems.Count}"); foreach (var item in projectReferenceTargetsItems) { Console.WriteLine($"->->-> {node.CacheFileName()}.{item.ItemType} = {item.EvaluatedInclude}"); foreach (var metadata in item.Metadata) { Console.WriteLine($"\t{metadata.Name}={metadata.EvaluatedValue}"); } } }
private static void ExecuteAllPredictors( ProjectGraphNode projectGraphNode, ValueAndTypeName <IProjectPredictor>[] projectPredictors, ValueAndTypeName <IProjectGraphPredictor>[] projectGraphPredictors, IProjectPredictionCollector projectPredictionCollector) { ProjectInstance projectInstance = projectGraphNode.ProjectInstance; // Run the project predictors. Use single-threaded prediction since we're already parallelizing on projects. ProjectPredictionExecutor.ExecuteProjectPredictors(projectInstance, projectPredictors, projectPredictionCollector, maxDegreeOfParallelism: 1); // Run the graph predictors for (var i = 0; i < projectGraphPredictors.Length; i++) { var predictionReporter = new ProjectPredictionReporter( projectPredictionCollector, projectInstance, projectGraphPredictors[i].TypeName); projectGraphPredictors[i].Value.PredictInputsAndOutputs( projectGraphNode, predictionReporter); } }
/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { ProjectInstance projectInstance = projectGraphNode.ProjectInstance; // This predictor only applies to sfproj files if (!projectInstance.FullPath.EndsWith(".sfproj", StringComparison.OrdinalIgnoreCase)) { return; } // A service fabric project publishes its dependencies with its own publish dir. However, we're not providing the publish dir // since that requires cracking open the service manifest to find the correct subdir. Instead we'll just predict the directory. foreach (ProjectGraphNode projectReference in projectGraphNode.ProjectReferences) { GetCopyToPublishDirectoryItemsGraphPredictor.PredictInputsAndOutputs(projectReference, publishDir: null, predictionReporter); } string publishDir = projectInstance.GetPropertyValue(GetCopyToPublishDirectoryItemsGraphPredictor.PublishDirPropertyName); if (!string.IsNullOrEmpty(publishDir)) { predictionReporter.ReportOutputDirectory(publishDir); } }
public static string CacheFileName(this ProjectGraphNode node) { return($"{Path.GetFileNameWithoutExtension(node.ProjectInstance.FullPath)}-{node.GetHashCode()}"); }
private static bool NotTraversalNode(ProjectGraphNode node) { // Really anything that ends in .proj probably shouldn't be loaded in VS (file copy projects, etc.) return(!node.ProjectInstance.FullPath.Contains(".proj")); }
public ProjectGraphBuildRequest(ProjectGraphNode node, ImmutableList <string> targets) { Node = node ?? throw new ArgumentNullException(nameof(node)); RequestedTargets = targets ?? throw new ArgumentNullException(nameof(targets)); }
private static bool TryConstructGraph( ProjectGraph projectGraph, GraphBuilderReporter reporter, ConcurrentDictionary <ProjectInstance, Project> projectInstanceToProjectCache, IReadOnlyCollection <string> entryPointTargets, IReadOnlyCollection <IProjectPredictor> projectPredictorsForTesting, bool allowProjectsWithoutTargetProtocol, out ProjectGraphWithPredictions projectGraphWithPredictions, out string failure) { Contract.Assert(projectGraph != null); var projectNodes = new ProjectWithPredictions[projectGraph.ProjectNodes.Count]; var nodes = projectGraph.ProjectNodes.ToArray(); // Compute the list of targets to run per project reporter.ReportMessage("Computing targets to execute for each project..."); // This dictionary should be exclusively read only at this point, and therefore thread safe var targetsPerProject = projectGraph.GetTargetLists(entryPointTargets.ToArray()); // Bidirectional access from nodes with predictions to msbuild nodes in order to compute node references in the second pass // TODO: revisit the structures, since the projects are known upfront we might be able to use lock-free structures var nodeWithPredictionsToMsBuildNodes = new ConcurrentDictionary <ProjectWithPredictions, ProjectGraphNode>(Environment.ProcessorCount, projectNodes.Length); var msBuildNodesToNodeWithPredictionIndex = new ConcurrentDictionary <ProjectGraphNode, ProjectWithPredictions>(Environment.ProcessorCount, projectNodes.Length); reporter.ReportMessage("Statically predicting inputs and outputs..."); // Create the registered predictors and initialize the prediction executor // The prediction executor potentially initializes third-party predictors, which may contain bugs. So let's be very defensive here IReadOnlyCollection <IProjectPredictor> predictors; try { predictors = projectPredictorsForTesting ?? ProjectPredictors.AllPredictors; } catch (Exception ex) { failure = $"Cannot create standard predictors. An unexpected error occurred. Please contact BuildPrediction project owners with this stack trace: {ex.ToString()}"; projectGraphWithPredictions = new ProjectGraphWithPredictions(new ProjectWithPredictions <string>[] { }); return(false); } // Using single-threaded prediction since we're parallelizing on project nodes instead. var predictionExecutor = new ProjectPredictionExecutor(predictors, new ProjectPredictionOptions { MaxDegreeOfParallelism = 1 }); // Each predictor may return unexpected/incorrect results and targets may not be able to be predicted. We put those failures here for post-processing. ConcurrentQueue <(string predictorName, string failure)> predictionFailures = new ConcurrentQueue <(string, string)>(); var predictedTargetFailures = new ConcurrentQueue <string>(); // The predicted targets to execute (per project) go here var computedTargets = new ConcurrentBigMap <ProjectGraphNode, PredictedTargetsToExecute>(); // When projects are allowed to not implement the target protocol, its references need default targets as a post-processing step var pendingAddDefaultTargets = new ConcurrentBigSet <ProjectGraphNode>(); // First pass // Predict all projects in the graph in parallel and populate ProjectNodes Parallel.For(0, projectNodes.Length, (int i) => { ProjectGraphNode msBuildNode = nodes[i]; ProjectInstance projectInstance = msBuildNode.ProjectInstance; Project project = projectInstanceToProjectCache[projectInstance]; var outputFolderPredictions = new List <string>(); var predictionCollector = new MsBuildOutputPredictionCollector(outputFolderPredictions, predictionFailures); try { // Again, be defensive when using arbitrary predictors predictionExecutor.PredictInputsAndOutputs(project, predictionCollector); } catch (Exception ex) { predictionFailures.Enqueue(( "Unknown predictor", $"Cannot run static predictor on project '{project.FullPath ?? "Unknown project"}'. An unexpected error occurred. Please contact BuildPrediction project owners with this stack trace: {ex.ToString()}")); }
/// <summary> /// Indexer which sets or returns results for the specified node /// </summary> /// <param name="node">The node</param> /// <returns>The results for the specified node</returns> /// <exception>KeyNotFoundException is returned if the specified node doesn't exist when reading this property.</exception> public BuildResult this[ProjectGraphNode node] => ResultsByNode[node];
public CacheResult GetCacheResultForNode(ProjectGraphNode node) { throw new NotImplementedException(); }
private static string ProjectNumber(ProjectGraphNode node) => Path.GetFileNameWithoutExtension(node.ProjectInstance.FullPath);
/// <inheritdoc/> public void PredictInputsAndOutputs(ProjectGraphNode projectGraphNode, ProjectPredictionReporter predictionReporter) { ProjectInstance projectInstance = projectGraphNode.ProjectInstance; // This predictor only applies to ccproj files if (!projectInstance.FullPath.EndsWith(".ccproj", StringComparison.OrdinalIgnoreCase)) { return; } // Emulates the behavior of the PrepareRoleItems target, specifically for web roles. ICollection <ProjectItemInstance> projectReferences = projectInstance.GetItems(ProjectReferenceItemName); var webRoleProjects = new HashSet <string>(projectReferences.Count, StringComparer.OrdinalIgnoreCase); foreach (var projectReferenceItem in projectReferences) { if (projectReferenceItem.GetMetadataValue(RoleTypeMetadataName).Equals("Web", StringComparison.OrdinalIgnoreCase)) { string webRoleProjectFullPath = Path.GetFullPath(Path.Combine(projectInstance.Directory, projectReferenceItem.EvaluatedInclude)); webRoleProjects.Add(webRoleProjectFullPath); } } // The PipelineTransformPhase target will be called on all web role projects foreach (ProjectGraphNode projectReference in projectGraphNode.ProjectReferences) { ProjectInstance referencedProjectInstance = projectReference.ProjectInstance; if (!webRoleProjects.Contains(referencedProjectInstance.FullPath)) { continue; } // The CompileTypeScript target gets triggered as a dependent target, so add predictions for TypeScriptCompile items foreach (ProjectItemInstance item in referencedProjectInstance.GetItems(TypeScriptCompileItemsPredictor.TypeScriptCompileItemName)) { // The item will be relative to the referenced project, not the current ccproj, so make the path absolute. string fullPath = Path.Combine(referencedProjectInstance.Directory, item.EvaluatedInclude); predictionReporter.ReportInputFile(fullPath); } // The PipelineTransformPhase target builds up FilesForPackagingFromProject items in a bunch of different CollectFilesFrom* dependent targets. // Only the ones deemed important and not covered by other predictors will be handled here. // Emulates the CollectFilesFromContent target. Note that this target grabs all Content items regardless of whether they're marked as CopyToOutputDirectory foreach (ProjectItemInstance item in referencedProjectInstance.GetItems(ContentItemsPredictor.ContentItemName)) { // The item will be relative to the referenced project, not the current ccproj, so make the path absolute. string fullPath = Path.Combine(referencedProjectInstance.Directory, item.EvaluatedInclude); predictionReporter.ReportInputFile(fullPath); } // Emulates the CollectFilesFromReference target. foreach (ProjectItemInstance item in referencedProjectInstance.GetItems(ReferenceItemsPredictor.ReferenceItemName)) { if (ReferenceItemsPredictor.TryGetReferenceItemFilePath(referencedProjectInstance, item, out string filePath)) { // The item will be relative to the referenced project, not the current ccproj, so make the path absolute. string fullPath = Path.GetFullPath(Path.Combine(referencedProjectInstance.Directory, filePath)); predictionReporter.ReportInputFile(fullPath); } } } }
private string RelativePathString(ProjectGraphNode node) { // Projects listed in the slnf need to be relative to the sln not the slnf file even // though the sln file is relative to the slnf location. return(MakeRelative(_slnDirectory, node.ProjectInstance.FullPath)); }