/// <summary>
        /// Gets an IRule to attach to a project item so that browse object properties will be displayed.
        /// </summary>
        private IRule GetRuleForUnresolvableReference(IProjectPropertiesContext unresolvedContext,
                                                      IProjectCatalogSnapshot catalogs,
                                                      ConfiguredProjectExports configuredProjectExports)
        {
            Requires.NotNull(unresolvedContext, nameof(unresolvedContext));
            Requires.NotNull(configuredProjectExports, nameof(configuredProjectExports));

            var namedCatalogs = GetNamedCatalogs(catalogs);
            var schemas       = GetSchemaForReference(unresolvedContext.ItemType, false, namedCatalogs).ToList();

            if (schemas.Count == 1)
            {
                Requires.NotNull(namedCatalogs, nameof(namedCatalogs));
                var browseObjectCatalog = namedCatalogs[PropertyPageContexts.BrowseObject];
                return(browseObjectCatalog.BindToContext(schemas[0].Name, unresolvedContext));
            }

            if (schemas.Count > 1)
            {
                TraceUtilities.TraceWarning(
                    "Too many rule schemas ({0}) in the BrowseObject context were found. Only 1 is allowed.",
                    schemas.Count);
            }

            // Since we have no browse object, we still need to create *something* so that standard property
            // pages can pop up.
            var emptyRule = RuleExtensions.SynthesizeEmptyRule(unresolvedContext.ItemType);

            return(configuredProjectExports.PropertyPagesDataModelProvider.GetRule(
                       emptyRule,
                       unresolvedContext.File,
                       unresolvedContext.ItemType,
                       unresolvedContext.ItemName));
        }
        /// <summary>
        /// Gets an IRule to attach to a project item so that browse object properties will be displayed.
        /// </summary>
        private IRule GetRuleForResolvableReference(
            IProjectPropertiesContext unresolvedContext,
            KeyValuePair <string, IImmutableDictionary <string, string> > resolvedReference,
            IProjectCatalogSnapshot catalogs,
            ConfiguredProjectExports configuredProjectExports,
            bool isGenericDependency = true)
        {
            Requires.NotNull(unresolvedContext, nameof(unresolvedContext));

            var namedCatalogs = GetNamedCatalogs(catalogs);
            var schemas       = GetSchemaForReference(unresolvedContext.ItemType, isGenericDependency, namedCatalogs).ToList();

            if (schemas.Count == 1)
            {
                IRule rule = configuredProjectExports.RuleFactory.CreateResolvedReferencePageRule(
                    schemas[0],
                    unresolvedContext,
                    resolvedReference.Key,
                    resolvedReference.Value);
                return(rule);
            }
            else
            {
                if (schemas.Count > 1)
                {
                    TraceUtilities.TraceWarning(
                        "Too many rule schemas ({0}) in the BrowseObject context were found.  Only 1 is allowed.",
                        schemas.Count);
                }

                // Since we have no browse object, we still need to create *something* so that standard property
                // pages can pop up.
                var emptyRule = RuleExtensions.SynthesizeEmptyRule(unresolvedContext.ItemType);
                return(configuredProjectExports.PropertyPagesDataModelProvider.GetRule(
                           emptyRule,
                           unresolvedContext.File,
                           unresolvedContext.ItemType,
                           unresolvedContext.ItemName));
            }
        }
 private async Task HandleFileChangedAsync(CancellationToken cancellationToken = default)
 {
     try
     {
         // Only notify the project if the contents of the watched file have changed.
         // In the case if we fail to read the contents, we will opt to notify the project.
         byte[] newHash = GetFileHashOrNull(_fileBeingWatched);
         if (newHash == null || _previousContentsHash == null || !newHash.SequenceEqual(_previousContentsHash))
         {
             TraceUtilities.TraceVerbose("{0} changed on disk. Marking project dirty", _fileBeingWatched);
             _previousContentsHash = newHash;
             cancellationToken.ThrowIfCancellationRequested();
             await _projectServices.Project.Services.ProjectAsynchronousTasks.LoadedProjectAsync(async() =>
             {
                 await _projectServices.ProjectAccessor.EnterWriteLockAsync(async(collection, token) =>
                 {
                     // notify all the loaded configured projects
                     IEnumerable <ConfiguredProject> currentProjects = _projectServices.Project.LoadedConfiguredProjects;
                     foreach (ConfiguredProject configuredProject in currentProjects)
                     {
                         await _projectServices.ProjectAccessor.OpenProjectForWriteAsync(configuredProject, project =>
                         {
                             project.MarkDirty();
                             configuredProject.NotifyProjectChange();
                         }, cancellationToken).ConfigureAwait(true); // Stay on same thread that took lock
                     }
                 }, cancellationToken).ConfigureAwait(true);         // Stay on same thread that took lock
             });
         }
         else
         {
             TraceUtilities.TraceWarning("{0} changed on disk, but has no actual content change.", _fileBeingWatched);
         }
     }
     catch (OperationCanceledException)
     {
         // Project is already unloaded
     }
 }
Exemple #4
0
 private async Task HandleFileChangedAsync(CancellationToken cancellationToken = default(CancellationToken))
 {
     try
     {
         // Only notify the project if the contents of the watched file have changed.
         // In the case if we fail to read the contents, we will opt to notify the project.
         byte[] newHash = GetFileHashOrNull(_fileBeingWatched);
         if (newHash == null || _previousContentsHash == null || !newHash.SequenceEqual(_previousContentsHash))
         {
             TraceUtilities.TraceVerbose("{0} changed on disk. Marking project dirty", _fileBeingWatched);
             _previousContentsHash = newHash;
             cancellationToken.ThrowIfCancellationRequested();
             await _projectServices.Project.Services.ProjectAsynchronousTasks.LoadedProjectAsync(async() =>
             {
                 using (var access = await _projectServices.ProjectLockService.WriteLockAsync(cancellationToken))
                 {
                     // notify all the loaded configured projects
                     var currentProjects = _projectServices.Project.LoadedConfiguredProjects;
                     foreach (var configuredProject in currentProjects)
                     {
                         // Inside a write lock, we should get back to the same thread.
                         var project = await access.GetProjectAsync(configuredProject, cancellationToken).ConfigureAwait(true);
                         project.MarkDirty();
                         configuredProject.NotifyProjectChange();
                     }
                 }
             });
         }
         else
         {
             TraceUtilities.TraceWarning("{0} changed on disk, but has no actual content change.", _fileBeingWatched);
         }
     }
     catch (OperationCanceledException)
     {
         // Project is already unloaded
     }
 }
        internal static IVsProjectRestoreInfo Build(IEnumerable <IProjectVersionedValue <IProjectSubscriptionUpdate> > updates,
                                                    UnconfiguredProject project)
        {
            Requires.NotNull(updates, nameof(updates));
            Requires.NotNull(project, nameof(project));

            // if none of the underlying subscriptions have any changes
            if (!updates.Any(u => u.Value.ProjectChanges.Any(c => c.Value.Difference.AnyChanges)))
            {
                return(null);
            }

            string baseIntermediatePath     = null;
            string originalTargetFrameworks = null;
            var    targetFrameworks         = new TargetFrameworks();
            var    toolReferences           = new ReferenceItems();

            foreach (IProjectVersionedValue <IProjectSubscriptionUpdate> update in updates)
            {
                var nugetRestoreChanges = update.Value.ProjectChanges[NuGetRestore.SchemaName];
                baseIntermediatePath = baseIntermediatePath ??
                                       nugetRestoreChanges.After.Properties[NuGetRestore.BaseIntermediateOutputPathProperty];
                originalTargetFrameworks = originalTargetFrameworks ??
                                           nugetRestoreChanges.After.Properties[NuGetRestore.TargetFrameworksProperty];
                bool noTargetFramework =
                    !update.Value.ProjectConfiguration.Dimensions.TryGetValue(NuGetRestore.TargetFrameworkProperty, out string targetFramework) &&
                    !nugetRestoreChanges.After.Properties.TryGetValue(NuGetRestore.TargetFrameworkProperty, out targetFramework);

                if (noTargetFramework || string.IsNullOrEmpty(targetFramework))
                {
                    TraceUtilities.TraceWarning("Unable to find TargetFramework Property");
                    continue;
                }

                if (!targetFrameworks.Contains(targetFramework))
                {
                    var projectReferencesChanges = update.Value.ProjectChanges[ProjectReference.SchemaName];
                    var packageReferencesChanges = update.Value.ProjectChanges[PackageReference.SchemaName];

                    targetFrameworks.Add(new TargetFrameworkInfo
                    {
                        TargetFrameworkMoniker = targetFramework,
                        ProjectReferences      = GetProjectReferences(projectReferencesChanges.After.Items, project),
                        PackageReferences      = GetReferences(packageReferencesChanges.After.Items),
                        Properties             = GetProperties(nugetRestoreChanges.After.Properties)
                    });
                }

                var toolReferencesChanges = update.Value.ProjectChanges[DotNetCliToolReference.SchemaName];
                foreach (var item in toolReferencesChanges.After.Items)
                {
                    if (!toolReferences.Contains(item.Key))
                    {
                        toolReferences.Add(GetReferenceItem(item));
                    }
                }
            }

            // return nominate restore information if any target framework entries are found
            return(targetFrameworks.Any()
                ? new ProjectRestoreInfo
            {
                BaseIntermediatePath = baseIntermediatePath,
                OriginalTargetFrameworks = originalTargetFrameworks,
                TargetFrameworks = targetFrameworks,
                ToolReferences = toolReferences
            }
                : null);
        }
Exemple #6
0
        internal static IVsProjectRestoreInfo Build(IEnumerable <IProjectVersionedValue <IProjectSubscriptionUpdate> > updates)
        {
            Requires.NotNull(updates, nameof(updates));

            // if none of the underlying subscriptions have any changes
            if (!updates.Any(u => u.Value.ProjectChanges.Any(c => c.Value.Difference.AnyChanges)))
            {
                return(null);
            }

            string msbuildProjectExtensionsPath = null;
            string originalTargetFrameworks     = null;
            var    targetFrameworks             = ImmutableDictionary.Create <string, IVsTargetFrameworkInfo>(StringComparers.ItemNames);
            var    toolReferences = ImmutableDictionary.Create <string, IVsReferenceItem>(StringComparers.ItemNames);

            foreach (IProjectVersionedValue <IProjectSubscriptionUpdate> update in updates)
            {
                IProjectChangeDescription nugetRestoreChanges = update.Value.ProjectChanges[NuGetRestore.SchemaName];
                msbuildProjectExtensionsPath = msbuildProjectExtensionsPath ??
                                               nugetRestoreChanges.After.Properties[NuGetRestore.MSBuildProjectExtensionsPathProperty];
                originalTargetFrameworks = originalTargetFrameworks ??
                                           nugetRestoreChanges.After.Properties[NuGetRestore.TargetFrameworksProperty];
                bool noTargetFramework =
                    !update.Value.ProjectConfiguration.Dimensions.TryGetValue(NuGetRestore.TargetFrameworkProperty, out string targetFramework) &&
                    !nugetRestoreChanges.After.Properties.TryGetValue(NuGetRestore.TargetFrameworkProperty, out targetFramework);

                if (noTargetFramework || string.IsNullOrEmpty(targetFramework))
                {
                    TraceUtilities.TraceWarning("Unable to find TargetFramework Property");
                    continue;
                }

                if (!targetFrameworks.ContainsKey(targetFramework))
                {
                    IProjectChangeDescription projectReferencesChanges = update.Value.ProjectChanges[ProjectReference.SchemaName];
                    IProjectChangeDescription packageReferencesChanges = update.Value.ProjectChanges[PackageReference.SchemaName];

                    targetFrameworks = targetFrameworks.Add(targetFramework, new TargetFrameworkInfo(
                                                                targetFramework,
                                                                RestoreBuilder.ToReferenceItems(projectReferencesChanges.After.Items),
                                                                RestoreBuilder.ToReferenceItems(packageReferencesChanges.After.Items),
                                                                RestoreBuilder.ToProjectProperties(nugetRestoreChanges.After.Properties)
                                                                ));
                }

                IProjectChangeDescription toolReferencesChanges = update.Value.ProjectChanges[DotNetCliToolReference.SchemaName];
                foreach (KeyValuePair <string, IImmutableDictionary <string, string> > item in toolReferencesChanges.After.Items)
                {
                    if (!toolReferences.ContainsKey(item.Key))
                    {
                        toolReferences = toolReferences.Add(item.Key, RestoreBuilder.ToReferenceItem(item.Key, item.Value));
                    }
                }
            }

            // return nominate restore information if any target framework entries are found
            return(targetFrameworks.Count > 0
                ? new ProjectRestoreInfo(
                       // NOTE: We pass MSBuildProjectExtensionsPath as BaseIntermediatePath instead of using
                       // BaseIntermediateOutputPath. This is because NuGet switched from using BaseIntermediateOutputPath
                       // to MSBuildProjectExtensionsPath, since the value of BaseIntermediateOutputPath is often set too
                       // late (after *.g.props files would need to have been imported from it). Instead of modifying the
                       // IVsProjectRestoreInfo interface or introducing something like IVsProjectRestoreInfo with an
                       // MSBuildProjectExtensionsPath property, we opted to leave the interface the same but change the
                       // meaning of its BaseIntermediatePath property. See
                       // https://github.com/dotnet/project-system/issues/3466for for details.
                       msbuildProjectExtensionsPath,
                       originalTargetFrameworks,
                       new TargetFrameworks(targetFrameworks.Values),
                       new ReferenceItems(toolReferences.Values)
                       )
                : null);
        }