private void AddPackageRootFilesFromItems(ICollection <ProjectItemInstance> items, string projectFolder, string packageRootPath, ProjectPredictionReporter predictionReporter)
        {
            foreach (ProjectItemInstance item in items)
            {
                string relativePath = item.EvaluatedInclude;

                // If it's not a valid path, don't process it.
                if (relativePath.IndexOfAny(Path.GetInvalidPathChars()) != -1)
                {
                    continue;
                }

                // Check whether the file is directly included from within the package root folder.
                string packageFileFullPath = Path.GetFullPath(Path.Combine(projectFolder, relativePath));
                if (packageFileFullPath.StartsWith(packageRootPath, StringComparison.OrdinalIgnoreCase))
                {
                    predictionReporter.ReportInputFile(packageFileFullPath);
                    continue;
                }

                // Check whether the file is referenced elsewhere but linked to be under the package root folder.
                string linkMetadata = item.GetMetadataValue("Link");
                if (!string.IsNullOrEmpty(linkMetadata))
                {
                    string linkFullPath = Path.GetFullPath(Path.Combine(projectFolder, linkMetadata));
                    if (linkFullPath.StartsWith(packageRootPath, StringComparison.OrdinalIgnoreCase))
                    {
                        predictionReporter.ReportInputFile(packageFileFullPath);
                        continue;
                    }
                }
            }
        }
コード例 #2
0
        private void ReportInputAndRelatedFiles(
            string referencePath,
            string projectDirectory,
            List <string> relatedFileExtensions,
            ProjectPredictionReporter predictionReporter)
        {
            var referenceFullPath = Path.GetFullPath(Path.Combine(projectDirectory, referencePath));

            predictionReporter.ReportInputFile(referenceFullPath);

            // If the reference doesn't exist, it might be generated by the build.
            // In that case, we can't know for sure whether there will be related
            // files or not, so don't bother trying in that case.
            if (!File.Exists(referenceFullPath))
            {
                return;
            }

            foreach (var ext in relatedFileExtensions)
            {
                var relatedFile = Path.ChangeExtension(referenceFullPath, ext);
                if (File.Exists(relatedFile))
                {
                    predictionReporter.ReportInputFile(relatedFile);
                }
            }
        }
コード例 #3
0
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            // This predictor only applies to sqlproj files
            if (!projectInstance.FullPath.EndsWith(".sqlproj", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            foreach (ProjectItemInstance item in projectInstance.GetItems(BuildItemName))
            {
                predictionReporter.ReportInputFile(item.EvaluatedInclude);
            }

            foreach (ProjectItemInstance item in projectInstance.GetItems(PostDeployItemName))
            {
                predictionReporter.ReportInputFile(item.EvaluatedInclude);
            }

            foreach (ProjectItemInstance item in projectInstance.GetItems(PreDeployItemName))
            {
                predictionReporter.ReportInputFile(item.EvaluatedInclude);
            }
        }
        /// <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);
                    }
                }
            }
        }
コード例 #5
0
 /// <inheritdoc/>
 public void PredictInputsAndOutputs(
     ProjectInstance projectInstance,
     ProjectPredictionReporter predictionReporter)
 {
     predictionReporter.ReportInputFile(projectInstance.FullPath);
     foreach (string importPath in projectInstance.ImportPaths)
     {
         predictionReporter.ReportInputFile(importPath);
     }
 }
            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)));
                    }
                }
            }
        private static void ReportCopyToPublishDirectoryItems(
            ProjectInstance projectInstance,
            string itemName,
            string publishDir,
            ProjectPredictionReporter predictionReporter)
        {
            foreach (ProjectItemInstance item in projectInstance.GetItems(itemName))
            {
                var copyToPublishDirectoryValue = item.GetMetadataValue(CopyToPublishDirectoryMetadataName);
                if (copyToPublishDirectoryValue.Equals("Always", StringComparison.OrdinalIgnoreCase) ||
                    copyToPublishDirectoryValue.Equals("PreserveNewest", StringComparison.OrdinalIgnoreCase))
                {
                    // The item will be relative to the project instance passed in, not the current project instance, so make the path absolute.
                    predictionReporter.ReportInputFile(Path.Combine(projectInstance.Directory, item.EvaluatedInclude));

                    if (!string.IsNullOrEmpty(publishDir))
                    {
                        string targetPath = item.GetTargetPath();
                        if (!string.IsNullOrEmpty(targetPath))
                        {
                            predictionReporter.ReportOutputFile(Path.Combine(publishDir, targetPath));
                        }
                    }
                }
            }
        }
コード例 #8
0
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            string ruleSetPath = projectInstance.GetPropertyValue(CodeAnalysisRuleSetPropertyName);

            if (string.IsNullOrWhiteSpace(ruleSetPath))
            {
                // Bail out fast if no rulset is configured.
                return;
            }

            string        ruleSetDirectoriesStr = projectInstance.GetPropertyValue(CodeAnalysisRuleSetDirectoriesPropertyName);
            List <string> ruleSetDirectories    = string.IsNullOrWhiteSpace(ruleSetDirectoriesStr)
                ? _emptyList
                : ruleSetDirectoriesStr.SplitStringList();

            HashSet <string> inputs = ParseRuleset(
                ruleSetPath,
                ruleSetDirectories,
                projectInstance.Directory,
                visitedRuleSets: null,
                isInCycle: false);

            foreach (string input in inputs)
            {
                predictionReporter.ReportInputFile(input);
            }
        }
コード例 #9
0
 /// <inheritdoc/>
 public void PredictInputsAndOutputs(
     ProjectInstance projectInstance,
     ProjectPredictionReporter predictionReporter)
 {
     foreach (ProjectItemInstance item in projectInstance.GetItems(PageItemName))
     {
         predictionReporter.ReportInputFile(item.EvaluatedInclude);
     }
 }
コード例 #10
0
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            var assemblyOriginatorKeyFile = projectInstance.GetPropertyValue(ApplicationIconPropertyName);

            if (!string.IsNullOrEmpty(assemblyOriginatorKeyFile))
            {
                predictionReporter.ReportInputFile(assemblyOriginatorKeyFile);
            }
        }
コード例 #11
0
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            // This predictor only applies to ccproj files
            if (!projectInstance.FullPath.EndsWith(".ccproj", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            foreach (ProjectItemInstance item in projectInstance.GetItems(ServiceConfigurationItemName))
            {
                predictionReporter.ReportInputFile(item.EvaluatedInclude);
            }

            foreach (ProjectItemInstance item in projectInstance.GetItems(ServiceDefinitionItemName))
            {
                predictionReporter.ReportInputFile(item.EvaluatedInclude);
            }
        }
        private void ReportInputsForItemType(ProjectPredictionReporter reporter, ProjectInstance projectInstance, string itemType)
        {
            ICollection <ProjectItemInstance> items = projectInstance.GetItems(itemType);

            if (items.Count == 0)
            {
                return;
            }

            foreach (ProjectItemInstance item in items)
            {
                reporter.ReportInputFile(item.EvaluatedInclude);
            }
        }
        /// <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);
                }
            }
        }
コード例 #14
0
 /// <inheritdoc/>
 public void PredictInputsAndOutputs(
     ProjectInstance projectInstance,
     ProjectPredictionReporter predictionReporter)
 {
     foreach (ProjectItemInstance item in projectInstance.GetItems(ClIncludeItemName))
     {
         // ClInclude items aren't directly used by the build process, but they're usually read during compilation of a cpp file via #include
         // Because of this, they're merely a hint and might not actually be read, so check for file existence.
         string clIncludeFullPath = Path.Combine(projectInstance.Directory, item.EvaluatedInclude);
         if (File.Exists(clIncludeFullPath))
         {
             predictionReporter.ReportInputFile(clIncludeFullPath);
         }
     }
 }
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            var availableItemNames = new HashSet <string>(
                projectInstance.GetItems(AvailableItemName).Select(item => item.EvaluatedInclude),
                StringComparer.OrdinalIgnoreCase);

            foreach (string availableItemName in availableItemNames)
            {
                foreach (ProjectItemInstance item in projectInstance.GetItems(availableItemName))
                {
                    predictionReporter.ReportInputFile(item.EvaluatedInclude);
                }
            }
        }
コード例 #16
0
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter)
        {
            // This predictor only applies when StyleCop exists and is enabled.
            if (!projectInstance.Targets.ContainsKey(StyleCopTargetName) ||
                projectInstance.GetPropertyValue(StyleCopEnabledPropertyName).Equals("false", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            // Find the StyleCop settings file as an input. If the override settings file is specified and valid,
            // it's used. Else fall back to finding the project settings file. Note that the validation or lack thereof
            // mimics what StyleCop actually does.
            string styleCopSettingsFile = TryGetOverrideSettingsFile(projectInstance, out string styleCopOverrideSettingsFile)
                ? styleCopOverrideSettingsFile
                : GetProjectSettingsFile(projectInstance.Directory);

            if (!string.IsNullOrEmpty(styleCopSettingsFile))
            {
                predictionReporter.ReportInputFile(styleCopSettingsFile);
            }

            // For Completeness we should consider Compile items as well since they're passed to StyleCop, but in practice another predictor will take care of that.

            // StyleCop addins as input directories
            foreach (ProjectItemInstance item in projectInstance.GetItems(StyleCopAdditionalAddinPathsItemName))
            {
                string addinPath         = item.GetMetadataValue("FullPath");
                string expandedAddinPath = Environment.ExpandEnvironmentVariables(addinPath);
                if (Directory.Exists(expandedAddinPath))
                {
                    predictionReporter.ReportInputDirectory(expandedAddinPath);
                }
            }

            // StyleCop violations file as an output
            string styleCopOutputFile = projectInstance.GetPropertyValue(StyleCopOutputFilePropertyName);

            if (!string.IsNullOrEmpty(styleCopOutputFile))
            {
                predictionReporter.ReportOutputFile(styleCopOutputFile);
            }

            // When StyleCopCacheResults is true, a StyleCop.Cache file is written adjacent to the project.
            // Currently we want to avoid predicting this as predicting outputs to non-output directories generally leads to problems in the consumers of this library.
            // If the need for absolute completeness arises, it should be added and those consumers will just need to deal.
        }
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            // This predictor only applies to ccproj files
            if (!projectInstance.FullPath.EndsWith(".ccproj", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            /*
             *  From Microsoft.WindowsAzure.targets in the CollectWorkerRoleFiles target:
             *      <MSBuild
             *        Projects="$(_WorkerRoleProject)"
             *        Targets="SourceFilesProjectOutputGroup"
             *        Properties="$(_WorkerRoleSetConfiguration);$(_WorkerRoleSetPlatform)"
             *        ContinueOnError="false">
             *        <Output TaskParameter="TargetOutputs" ItemName="SourceFilesOutputGroup" />
             *      </MSBuild>
             *
             *      <!-- Add the app config file from SourceFilesOutputGroup -->
             *      <ItemGroup>
             *        <WorkerFiles Include="@(SourceFilesOutputGroup)" Condition=" '%(SourceFilesOutputGroup.TargetPath)' == '$(WorkerEntryPoint).config' " >
             *          <TargetPath>%(TargetPath)</TargetPath>
             *          <RoleOwner>$(_WorkerRoleProject)</RoleOwner>
             *          <RoleOwnerName>$(_WorkerRoleProjectName)</RoleOwnerName>
             *        </WorkerFiles>
             *      </ItemGroup>
             *
             *  Effectively, it just finds project references' app.config files to copy. Note that in theory the app.config can be already named <assembly-name>.config,
             *  but this should be uncommon so for now this is a gap we're willing to live with.
             *
             *  TODO: There is a lot more logic adding WorkerFiles. However, they're generally all in the project reference's output directory or from nuget packages,
             *  neither of which require as precise prediction. Perhaps when we have a better way to make predictions based on dependencies we can be more accurate here.
             */
            foreach (var projectReferenceItem in projectInstance.GetItems(ProjectReferenceItemName))
            {
                var projectReferenceRootDir   = projectReferenceItem.GetMetadataValue("RootDir");
                var projectReferenceDirectory = projectReferenceItem.GetMetadataValue("Directory");
                var appConfigFile             = projectReferenceRootDir + projectReferenceDirectory + AppConfigFileName;
                if (File.Exists(appConfigFile))
                {
                    predictionReporter.ReportInputFile(appConfigFile);
                }
            }
        }
コード例 #18
0
        private void ReportInputs(ProjectPredictionReporter reporter, ProjectItemInstance masmItem, HashSet <string> reportedIncludes)
        {
            reporter.ReportInputFile(masmItem.EvaluatedInclude);

            string[] includePaths = masmItem.GetMetadataValue(IncludePathsMetadata)
                                    .Split(IncludePathsSeparator, StringSplitOptions.RemoveEmptyEntries);

            // Avoid reporting paths that we've already reported for this project.
            foreach (string includePath in includePaths)
            {
                string trimmedPath = includePath.Trim();
                if (!string.IsNullOrEmpty(trimmedPath) && reportedIncludes.Add(trimmedPath))
                {
                    reporter.ReportInputDirectory(trimmedPath);
                }
            }
        }
コード例 #19
0
        private static void ProcessFile(
            string sourceFile,
            string fileName,
            string[] destinationFolders,
            string destinationSubDirectory,
            ProjectPredictionReporter predictionReporter)
        {
            // Inputs
            predictionReporter.ReportInputFile(sourceFile);

            // Outputs
            foreach (string destination in destinationFolders)
            {
                string destinationFile = !string.IsNullOrEmpty(destinationSubDirectory)
                    ? Path.Combine(destination, destinationSubDirectory, fileName)
                    : Path.Combine(destination, fileName);
                predictionReporter.ReportOutputFile(destinationFile);
            }
        }
コード例 #20
0
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            // The key file is only an input when signing is enabled.
            var signAssembly = projectInstance.GetPropertyValue(SignAssemblyPropertyName);

            if (!signAssembly.Equals("true", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            var assemblyOriginatorKeyFile = projectInstance.GetPropertyValue(AssemblyOriginatorKeyFilePropertyName);

            if (!string.IsNullOrEmpty(assemblyOriginatorKeyFile))
            {
                predictionReporter.ReportInputFile(assemblyOriginatorKeyFile);
            }
        }
コード例 #21
0
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            string outDir = projectInstance.GetPropertyValue(OutDirPropertyName);

            foreach (ProjectItemInstance item in projectInstance.GetItems(ContentItemName))
            {
                predictionReporter.ReportInputFile(item.EvaluatedInclude);

                if (!string.IsNullOrEmpty(outDir) && item.ShouldCopyToOutputDirectory())
                {
                    string targetPath = item.GetTargetPath();
                    if (!string.IsNullOrEmpty(targetPath))
                    {
                        predictionReporter.ReportOutputFile(Path.Combine(outDir, targetPath));
                    }
                }
            }
        }
コード例 #22
0
        private static void ReportCopyToOutputDirectoryItemsAsInputs(
            ProjectInstance projectInstance,
            string itemName,
            string outDir,
            ProjectPredictionReporter predictionReporter)
        {
            foreach (ProjectItemInstance item in projectInstance.GetItems(itemName))
            {
                if (item.ShouldCopyToOutputDirectory())
                {
                    // The item will be relative to the project instance passed in, not the current project instance, so make the path absolute.
                    predictionReporter.ReportInputFile(Path.Combine(projectInstance.Directory, item.EvaluatedInclude));

                    if (!string.IsNullOrEmpty(outDir))
                    {
                        string targetPath = item.GetTargetPath();
                        if (!string.IsNullOrEmpty(targetPath))
                        {
                            predictionReporter.ReportOutputFile(Path.Combine(outDir, targetPath));
                        }
                    }
                }
            }
        }
            public void PredictInputsAndOutputs(
                ProjectInstance projectInstance,
                ProjectPredictionReporter predictionReporter)
            {
                foreach (var item in _inputFiles)
                {
                    predictionReporter.ReportInputFile(item);
                }

                foreach (var item in _inputDirectories)
                {
                    predictionReporter.ReportInputDirectory(item);
                }

                foreach (var item in _outputFiles)
                {
                    predictionReporter.ReportOutputFile(item);
                }

                foreach (var item in _outputDirectories)
                {
                    predictionReporter.ReportOutputDirectory(item);
                }
            }
コード例 #24
0
        /// <summary>
        /// Parses the input and output files for copy tasks of given target.
        /// </summary>
        private static void ParseCopyTask(
            ProjectTargetInstance target,
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            // Get all Copy tasks from targets.
            List <ProjectTaskInstance> tasks = target.Tasks
                                               .Where(task => string.Equals(task.Name, CopyTaskName, StringComparison.Ordinal))
                                               .ToList();

            if (tasks.Any() && projectInstance.EvaluateConditionCarefully(target.Condition))
            {
                foreach (ProjectTaskInstance task in tasks)
                {
                    if (projectInstance.EvaluateConditionCarefully(task.Condition))
                    {
                        var inputs = new FileExpressionList(
                            task.Parameters[CopyTaskSourceFiles],
                            projectInstance,
                            task);
                        if (inputs.NumExpressions == 0)
                        {
                            continue;
                        }

                        foreach (var file in inputs.DedupedFiles)
                        {
                            predictionReporter.ReportInputFile(file);
                        }

                        bool hasDestinationFolder = task.Parameters.TryGetValue(
                            CopyTaskDestinationFolder,
                            out string destinationFolder);
                        bool hasDestinationFiles = task.Parameters.TryGetValue(
                            CopyTaskDestinationFiles,
                            out string destinationFiles);

                        if (hasDestinationFiles || hasDestinationFolder)
                        {
                            // Having both is an MSBuild violation, which it will complain about.
                            if (hasDestinationFolder && hasDestinationFiles)
                            {
                                continue;
                            }

                            string destination = destinationFolder ?? destinationFiles;

                            var outputs = new FileExpressionList(destination, projectInstance, task);

                            // When using batch tokens, the user should specify exactly one total token, and it must appear in both the input and output.
                            // Doing otherwise should be a BuildCop error. If not using batch tokens, then any number of other tokens is fine.
                            if ((outputs.NumBatchExpressions == 1 && outputs.NumExpressions == 1 &&
                                 inputs.NumBatchExpressions == 1 && inputs.NumExpressions == 1) ||
                                (outputs.NumBatchExpressions == 0 && inputs.NumBatchExpressions == 0))
                            {
                                ProcessOutputs(inputs, outputs, hasDestinationFolder, predictionReporter);
                            }
                            else
                            {
                                // Ignore case we cannot handle.
                            }
                        }
                        else
                        {
                            // Ignore malformed case.
                        }
                    }
                }
            }
        }
コード例 #25
0
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            // This predictor only applies to sfproj files
            if (!projectInstance.FullPath.EndsWith(".sfproj", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            /*
             *  From Microsoft.VisualStudio.Azure.Fabric.ApplicationProject.targets in the FixUpServiceFabricApplicationManifest target:
             *    <ItemGroup>
             *      <_ServiceManifestFullPath Include="@(ProjectReference -> '%(RootDir)%(Directory)$(ServicePackageRootFolder)\ServiceManifest.xml')" />
             *    </ItemGroup>
             *
             *    <FindServiceManifests ApplicationPackageRootFolder="$(ApplicationPackageRootFolder)">
             *      <Output TaskParameter="ServiceManifestFiles" ItemName="_ServiceManifestFullPath" />
             *    </FindServiceManifests>
             *
             *  Then it runs a cleanup util on @(_ServiceManifestFullPath), making them all inputs.
             */

            // FixUpServiceFabricApplicationManifest has a condition: '@(ProjectReference)' != '' AND '$(UpdateServiceFabricApplicationManifestEnabled)' == 'true'
            // Weirdly the target is skipped if there are no project references even if there are extra service manifests in the ApplicationPackageRootFolder
            var updateServiceFabricApplicationManifestEnabled = projectInstance.GetPropertyValue(UpdateServiceFabricApplicationManifestEnabledPropertyName);
            var projectReferenceItems = projectInstance.GetItems(ProjectReferenceItemName);

            if (projectReferenceItems.Count == 0 || !updateServiceFabricApplicationManifestEnabled.Equals("true", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            var servicePackageRootFolder = projectInstance.GetPropertyValue(ServicePackageRootFolderPropertyName);

            foreach (var projectReferenceItem in projectReferenceItems)
            {
                // Equivalent of '%(RootDir)%(Directory)$(ServicePackageRootFolder)\ServiceManifest.xml'
                var projectReferenceRootDir   = projectReferenceItem.GetMetadataValue("RootDir");
                var projectReferenceDirectory = projectReferenceItem.GetMetadataValue("Directory");
                var serviceManifestFile       = projectReferenceRootDir + projectReferenceDirectory + servicePackageRootFolder + Path.DirectorySeparatorChar + ServiceManifestFileName;
                predictionReporter.ReportInputFile(serviceManifestFile);
            }

            // The FindServiceManifests task simply enumerates the directories in $(ApplicationPackageRootFolder) looking for ServiceManifest.xml files.
            var applicationPackageRootFolder = projectInstance.GetPropertyValue(ApplicationPackageRootFolderPropertyName);

            if (!Path.IsPathRooted(applicationPackageRootFolder))
            {
                applicationPackageRootFolder = Path.Combine(projectInstance.Directory, applicationPackageRootFolder);
            }

            foreach (string directory in Directory.EnumerateDirectories(applicationPackageRootFolder))
            {
                string serviceManifestFile = Path.Combine(directory, ServiceManifestFileName);
                if (File.Exists(serviceManifestFile))
                {
                    predictionReporter.ReportInputFile(serviceManifestFile);
                }
            }
        }
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            // This is based on NuGet.Build.Tasks.Pack.targets and GetPackOutputItemsTask
            // See: https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Build.Tasks.Pack/NuGet.Build.Tasks.Pack.targets
            // See: https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Core/NuGet.Build.Tasks.Pack/GetPackOutputItemsTask.cs
            var generatePackageOnBuild = projectInstance.GetPropertyValue(GeneratePackageOnBuildPropertyName);

            if (!generatePackageOnBuild.Equals("true", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            var packageId                     = projectInstance.GetPropertyValue(PackageIdPropertyName);
            var packageVersion                = projectInstance.GetPropertyValue(PackageVersionPropertyName);
            var packageOutputPath             = projectInstance.GetPropertyValue(PackageOutputPathPropertyName);
            var nuspecOutputPath              = projectInstance.GetPropertyValue(NuspecOutputPathPropertyName);
            var includeSource                 = projectInstance.GetPropertyValue(IncludeSourcePropertyName).Equals("true", StringComparison.OrdinalIgnoreCase);
            var includeSymbols                = projectInstance.GetPropertyValue(IncludeSymbolsPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase);
            var outputFileNamesWithoutVersion = projectInstance.GetPropertyValue(OutputFileNamesWithoutVersionPropertyName).Equals("true", StringComparison.OrdinalIgnoreCase);

            var symbolPackageFormat = projectInstance.GetPropertyValue(SymbolPackageFormatPropertyName);

            // PackageOutputPath defaults to OutputPath in the _CalculateInputsOutputsForPack target, not statically.
            if (string.IsNullOrEmpty(packageOutputPath))
            {
                packageOutputPath = projectInstance.GetPropertyValue(OutputPathPropertyName);
            }

            // All params are effectively required
            if (!string.IsNullOrEmpty(packageId) &&
                !string.IsNullOrEmpty(packageVersion) &&
                !string.IsNullOrEmpty(packageOutputPath) &&
                !string.IsNullOrEmpty(nuspecOutputPath) &&
                !string.IsNullOrEmpty(symbolPackageFormat))
            {
                var fileBaseName = outputFileNamesWithoutVersion ? packageId : $"{packageId}.{packageVersion}";

                // Nuspec files can also be provided instead of generated, in which case we should treat it like an input, not an output.
                var nuspecFile = projectInstance.GetPropertyValue(NuspecFilePropertyName);

                predictionReporter.ReportOutputFile(Path.Combine(packageOutputPath, fileBaseName + ".nupkg"));
                if (string.IsNullOrEmpty(nuspecFile))
                {
                    predictionReporter.ReportOutputFile(Path.Combine(nuspecOutputPath, fileBaseName + ".nuspec"));
                }
                else
                {
                    predictionReporter.ReportInputFile(nuspecFile);
                }

                if (includeSource || includeSymbols)
                {
                    predictionReporter.ReportOutputFile(Path.Combine(packageOutputPath, fileBaseName + (symbolPackageFormat.Equals("snupkg", StringComparison.OrdinalIgnoreCase) ? ".snupkg" : ".symbols.nupkg")));
                    if (string.IsNullOrEmpty(nuspecFile))
                    {
                        predictionReporter.ReportOutputFile(Path.Combine(nuspecOutputPath, fileBaseName + ".symbols.nuspec"));
                    }
                }
            }
        }
コード例 #27
0
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(
            ProjectInstance projectInstance,
            ProjectPredictionReporter predictionReporter)
        {
            List <string> configFiles = FindConfigFiles(projectInstance);

            foreach (string configFile in configFiles)
            {
                string configFileFullPath = Path.Combine(projectInstance.Directory, configFile);
                string configFileContent  = File.ReadAllText(configFileFullPath);
                bool   isTsConfig         = Path.GetFileName(configFile).Equals(TsConfigFileName, PathComparer.Comparison);

                TsConfig tsConfig;
                try
                {
                    tsConfig = JsonSerializer.Deserialize <TsConfig>(configFileContent, _jsonSerializerOptions);
                }
                catch (JsonException)
                {
                    // Ignore invalid config files
                    continue;
                }

                string configFileDir = Path.GetDirectoryName(configFileFullPath);

                tsConfig.ApplyDefaults();

                if (tsConfig.Files != null)
                {
                    foreach (string file in tsConfig.Files)
                    {
                        string fileFullPath = PathUtilities.NormalizePath(Path.Combine(configFileDir, file));
                        predictionReporter.ReportInputFile(fileFullPath);
                    }
                }

                // Reuse MSBuild's globbing logic as it should match what tsc does.
                if (tsConfig.Include != null)
                {
                    var directoriesToEnumerate = new Queue <string>();

                    var includeGlobs = new MSBuildGlob[tsConfig.Include.Count];
                    for (var i = 0; i < tsConfig.Include.Count; i++)
                    {
                        string      include     = tsConfig.Include[i];
                        MSBuildGlob includeGlob = MSBuildGlob.Parse(configFileDir, include);
                        directoriesToEnumerate.Enqueue(includeGlob.FixedDirectoryPart);
                        includeGlobs[i] = includeGlob;
                    }

                    var excludeGlobs = new MSBuildGlob[tsConfig.Exclude.Count];
                    for (var i = 0; i < tsConfig.Exclude.Count; i++)
                    {
                        string exclude = tsConfig.Exclude[i];

                        // Handle the case where just a folder name is used as an exclude value
                        if (exclude.IndexOf('*', StringComparison.Ordinal) == -1)
                        {
                            exclude += "/**";
                        }

                        excludeGlobs[i] = MSBuildGlob.Parse(configFileDir, exclude);
                    }

                    var finalGlob          = new MSBuildGlobWithGaps(new CompositeGlob(includeGlobs), excludeGlobs);
                    var visitedDirectories = new HashSet <string>(PathComparer.Instance);
                    while (directoriesToEnumerate.Count > 0)
                    {
                        string directoryToEnumerate = directoriesToEnumerate.Dequeue();

                        // In case the initial globs has parent/child relationships
                        if (!visitedDirectories.Add(directoryToEnumerate))
                        {
                            continue;
                        }

                        // Some globs might point to non-existent paths.
                        if (!Directory.Exists(directoryToEnumerate))
                        {
                            continue;
                        }

                        foreach (string file in Directory.EnumerateFiles(directoryToEnumerate, "*", SearchOption.TopDirectoryOnly))
                        {
                            if (finalGlob.IsMatch(file))
                            {
                                predictionReporter.ReportInputFile(file);
                            }
                        }

                        foreach (string directory in Directory.EnumerateDirectories(directoryToEnumerate, "*", SearchOption.TopDirectoryOnly))
                        {
                            directoriesToEnumerate.Enqueue(directory);
                        }
                    }
                }

                if (isTsConfig && tsConfig.CompilerOptions != null)
                {
                    if (!string.IsNullOrEmpty(tsConfig.CompilerOptions.OutFile))
                    {
                        string outFileFullPath = PathUtilities.NormalizePath(Path.Combine(configFileDir, tsConfig.CompilerOptions.OutFile));
                        predictionReporter.ReportOutputFile(outFileFullPath);
                    }

                    if (!string.IsNullOrEmpty(tsConfig.CompilerOptions.OutDir))
                    {
                        string outDirFullPath = PathUtilities.NormalizePath(Path.Combine(configFileDir, tsConfig.CompilerOptions.OutDir));
                        predictionReporter.ReportOutputDirectory(outDirFullPath);
                    }
                }
            }
        }
コード例 #28
0
        /// <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);
                    }
                }
            }
        }
コード例 #29
0
        /// <inheritdoc/>
        public void PredictInputsAndOutputs(ProjectInstance projectInstance, ProjectPredictionReporter predictionReporter)
        {
            // Non-ClickOnce applications use $(Win32Manifest) as an input to CSC, and the _SetEmbeddedWin32ManifestProperties target sets $(Win32Manifest) = $(ApplicationManifest).
            // ClickOnce applications don't use $(Win32Manifest) but do use $(ApplicationManifest) as an input anyway, so just always consider it an input.
            string applicationManifest = projectInstance.GetPropertyValue(ApplicationManifestPropertyName);

            if (!string.IsNullOrEmpty(applicationManifest))
            {
                predictionReporter.ReportInputFile(applicationManifest);
            }

            // ClickOnce applications
            if (projectInstance.GetPropertyValue(GenerateClickOnceManifestsPropertyName).Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase))
            {
                // $(_DeploymentBaseManifest) is an input to the GenerateApplicationManifest target/task, which in the _SetExternalWin32ManifestProperties
                // target is defined as $(ApplicationManifest) if it's set, which we've already predicted as an input above.
                if (string.IsNullOrEmpty(applicationManifest))
                {
                    // If $(ApplicationManifest) isn't set, $(_DeploymentBaseManifest) is set to @(_DeploymentBaseManifestWithTargetPath), which in the AssignTargetPaths target
                    // is set to @(BaseApplicationManifest) if any or @(None) items with the '.manifest' extension otherwise.
                    var baseApplicationManifests = projectInstance.GetItems(BaseApplicationManifestItemName);
                    if (baseApplicationManifests.Count > 0)
                    {
                        foreach (ProjectItemInstance item in baseApplicationManifests)
                        {
                            predictionReporter.ReportInputFile(item.EvaluatedInclude);
                        }
                    }
                    else
                    {
                        var none = projectInstance.GetItems(NoneItemName);
                        foreach (ProjectItemInstance item in none)
                        {
                            if (item.EvaluatedInclude.EndsWith(ManifestExtension, StringComparison.OrdinalIgnoreCase))
                            {
                                predictionReporter.ReportInputFile(item.EvaluatedInclude);
                            }
                        }
                    }
                }

                // Application manifest
                var applicationManifestName = projectInstance.GetPropertyValue(OutputTypePropertyName).Equals("library", StringComparison.OrdinalIgnoreCase)
                    ? "Native." + projectInstance.GetPropertyValue(AssemblyNamePropertyName) + ManifestExtension
                    : projectInstance.GetPropertyValue(TargetFileNamePropertyName) + ManifestExtension;
                predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(IntermediateOutputPathPropertyName) + applicationManifestName);
                predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(OutDirPropertyName) + applicationManifestName);

                // Deployment manifest
                var deploymentManifestName = projectInstance.GetPropertyValue(HostInBrowserPropertyName).Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)
                    ? projectInstance.GetPropertyValue(AssemblyNamePropertyName) + ".xbap"
                    : projectInstance.GetPropertyValue(AssemblyNamePropertyName) + ".application";
                predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(IntermediateOutputPathPropertyName) + deploymentManifestName);
                predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(OutDirPropertyName) + deploymentManifestName);

                // Intermediate Trust info file
                if (!string.IsNullOrEmpty(projectInstance.GetPropertyValue(TargetZonePropertyName)))
                {
                    predictionReporter.ReportOutputFile(projectInstance.GetPropertyValue(IntermediateOutputPathPropertyName) + projectInstance.GetPropertyValue(TargetFileNamePropertyName) + ".TrustInfo.xml");
                }
            }
        }