/// <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));
        }
        public async Task <IRule> GetRuleAsync(IDependency dependency, IProjectCatalogSnapshot catalogs)
        {
            Requires.NotNull(dependency, nameof(dependency));

            ConfiguredProject project = null;

            if (dependency.TargetFramework.Equals(TargetFramework.Any))
            {
                project = ActiveConfiguredProject;
            }
            else
            {
                project = await DependenciesHost.GetConfiguredProject(dependency.TargetFramework)
                          .ConfigureAwait(false) ?? ActiveConfiguredProject;
            }

            ConfiguredProjectExports configuredProjectExports = GetActiveConfiguredProjectExports(project);
            IImmutableDictionary <string, IPropertyPagesCatalog> namedCatalogs = await GetNamedCatalogsAsync(catalogs).ConfigureAwait(false);

            Requires.NotNull(namedCatalogs, nameof(namedCatalogs));

            IPropertyPagesCatalog browseObjectsCatalog = namedCatalogs[PropertyPageContexts.BrowseObject];
            Rule   schema   = browseObjectsCatalog.GetSchema(dependency.SchemaName);
            string itemSpec = string.IsNullOrEmpty(dependency.OriginalItemSpec) ? dependency.Path : dependency.OriginalItemSpec;
            var    context  = ProjectPropertiesContext.GetContext(UnconfiguredProject,
                                                                  itemType: dependency.SchemaItemType,
                                                                  itemName: itemSpec);

            IRule rule = null;

            if (schema != null)
            {
                if (dependency.Resolved)
                {
                    rule = configuredProjectExports.RuleFactory.CreateResolvedReferencePageRule(
                        schema,
                        context,
                        dependency.Name,
                        dependency.Properties);
                }
                else
                {
                    rule = browseObjectsCatalog.BindToContext(schema.Name, context);
                }
            }
            else
            {
                // Since we have no browse object, we still need to create *something* so
                // that standard property pages can pop up.
                Rule emptyRule = RuleExtensions.SynthesizeEmptyRule(context.ItemType);
                return(configuredProjectExports.PropertyPagesDataModelProvider.GetRule(
                           emptyRule,
                           context.File,
                           context.ItemType,
                           context.ItemName));
            }

            return(rule);
        }
        /// <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));
            }
        }
Exemple #4
0
        public async Task <IRule?> GetRuleAsync(IDependency dependency, IProjectCatalogSnapshot?catalogs)
        {
            Requires.NotNull(dependency, nameof(dependency));

            ConfiguredProject project = dependency.TargetFramework.Equals(TargetFramework.Any)
                ? ActiveConfiguredProject
                : _dependenciesHost.GetConfiguredProject(dependency.TargetFramework) ?? ActiveConfiguredProject;

            IImmutableDictionary <string, IPropertyPagesCatalog> namedCatalogs = await GetNamedCatalogsAsync();

            Requires.NotNull(namedCatalogs, nameof(namedCatalogs));

            if (!namedCatalogs.TryGetValue(PropertyPageContexts.BrowseObject, out IPropertyPagesCatalog browseObjectsCatalog))
            {
                // Issue https://github.com/dotnet/project-system/issues/4860 suggests this code path
                // can exist, however a repro was not found to dig deeper into the underlying cause.
                // For now just return null as the upstream caller handles null correctly anyway.
                return(null);
            }

            Rule   schema   = browseObjectsCatalog.GetSchema(dependency.SchemaName);
            string itemSpec = string.IsNullOrEmpty(dependency.OriginalItemSpec) ? dependency.Path : dependency.OriginalItemSpec;
            var    context  = ProjectPropertiesContext.GetContext(UnconfiguredProject,
                                                                  itemType: dependency.SchemaItemType,
                                                                  itemName: itemSpec);

            if (schema == null)
            {
                // Since we have no browse object, we still need to create *something* so
                // that standard property pages can pop up.
                Rule emptyRule = RuleExtensions.SynthesizeEmptyRule(context.ItemType);
                return(GetActiveConfiguredProjectExports(project).PropertyPagesDataModelProvider.GetRule(
                           emptyRule,
                           context.File,
                           context.ItemType,
                           context.ItemName));
            }

            if (dependency.Resolved)
            {
                return(GetActiveConfiguredProjectExports(project).RuleFactory.CreateResolvedReferencePageRule(
                           schema,
                           context,
                           dependency.Name,
                           dependency.Properties));
            }

            return(browseObjectsCatalog.BindToContext(schema.Name, context));

            async Task <IImmutableDictionary <string, IPropertyPagesCatalog> > GetNamedCatalogsAsync()
            {
                if (catalogs != null)
                {
                    return(catalogs.NamedCatalogs);
                }

                if (_namedCatalogs == null)
                {
                    // Note: it is unlikely that we end up here, however for cases when node providers
                    // getting their node data not from Design time build events, we might have OnDependenciesChanged
                    // event coming before initial design time build event updates NamedCatalogs in this class.
                    // Thus, just in case, explicitly request it here (GetCatalogsAsync will acquire a project read lock)
                    _namedCatalogs = await ActiveConfiguredProject.Services
                                     .PropertyPagesCatalog
                                     .GetCatalogsAsync(CancellationToken.None);
                }

                return(_namedCatalogs);
            }
        }