private static CreationResultStatus DisplayHelpForAmbiguousTemplateGroup(TemplateListResolutionResult templateResolutionResult, IEngineEnvironmentSettings environmentSettings, INewCommandInput commandInput, IHostSpecificDataLoader hostDataLoader, ITelemetryLogger telemetryLogger, string defaultLanguage)
        {
            if (!string.IsNullOrEmpty(commandInput.TemplateName) &&
                templateResolutionResult.GetBestTemplateMatchList(true).Count > 0 &&
                templateResolutionResult.GetBestTemplateMatchList(true).All(x => x.MatchDisposition.Any(d => d.Location == MatchLocation.Language && d.Kind == MatchKind.Mismatch)))
            {
                string errorMessage = GetLanguageMismatchErrorMessage(commandInput);
                Reporter.Error.WriteLine(errorMessage.Bold().Red());
                Reporter.Error.WriteLine(string.Format(LocalizableStrings.RunHelpForInformationAboutAcceptedParameters, $"{commandInput.CommandName} {commandInput.TemplateName}").Bold().Red());
                return(CreationResultStatus.NotFound);
            }

            // The following occurs when:
            //      --alias <value> is specifed
            //      --help is specified
            //      template (group) can't be resolved
            if (!string.IsNullOrWhiteSpace(commandInput.Alias))
            {
                Reporter.Error.WriteLine(LocalizableStrings.InvalidInputSwitch.Bold().Red());
                Reporter.Error.WriteLine("  " + commandInput.TemplateParamInputFormat("--alias").Bold().Red());
                return(CreationResultStatus.NotFound);
            }

            bool hasInvalidParameters = false;
            IReadOnlyList <ITemplateMatchInfo> templatesForDisplay = templateResolutionResult.GetBestTemplateMatchList(true);

            GetParametersInvalidForTemplatesInList(templatesForDisplay, out IReadOnlyList <string> invalidForAllTemplates, out IReadOnlyList <string> invalidForSomeTemplates);
            if (invalidForAllTemplates.Any() || invalidForSomeTemplates.Any())
            {
                hasInvalidParameters = true;
                DisplayInvalidParameters(invalidForAllTemplates);
                DisplayParametersInvalidForSomeTemplates(invalidForSomeTemplates, LocalizableStrings.PartialTemplateMatchSwitchesNotValidForAllMatches);
            }

            ShowContextAndTemplateNameMismatchHelp(templateResolutionResult, commandInput.TemplateName, commandInput.TypeFilter, out bool shouldShowTemplateList);
            if (shouldShowTemplateList)
            {
                DisplayTemplateList(templatesForDisplay, environmentSettings, commandInput.Language, defaultLanguage);
            }

            if (!commandInput.IsListFlagSpecified)
            {
                TemplateUsageHelp.ShowInvocationExamples(templateResolutionResult, hostDataLoader, commandInput.CommandName);
            }

            if (hasInvalidParameters)
            {
                return(CreationResultStatus.NotFound);
            }
            else if (commandInput.IsListFlagSpecified || commandInput.IsHelpFlagSpecified)
            {
                return(!templateResolutionResult.IsNoTemplatesMatchedState ? CreationResultStatus.Success :  CreationResultStatus.NotFound);
            }
            else
            {
                return(CreationResultStatus.OperationNotSpecified);
            }
        }
Exemplo n.º 2
0
        private static CreationResultStatus DisplayListOrHelpForAmbiguousTemplateGroup(ListOrHelpTemplateListResolutionResult templateResolutionResult, IEngineEnvironmentSettings environmentSettings, INewCommandInput commandInput, IHostSpecificDataLoader hostDataLoader, ITelemetryLogger telemetryLogger, string defaultLanguage)
        {
            // The following occurs when:
            //      --alias <value> is specifed
            //      --help is specified
            //      template (group) can't be resolved
            if (!string.IsNullOrWhiteSpace(commandInput.Alias))
            {
                Reporter.Error.WriteLine(LocalizableStrings.InvalidInputSwitch.Bold().Red());
                Reporter.Error.WriteLine("  " + commandInput.TemplateParamInputFormat("--alias").Bold().Red());
                return(CreationResultStatus.NotFound);
            }

            bool hasInvalidParameters = false;
            IReadOnlyCollection <ITemplateMatchInfo> templatesForDisplay = templateResolutionResult.ExactMatchedTemplates;

            GetParametersInvalidForTemplatesInList(templatesForDisplay, out IReadOnlyList <string> invalidForAllTemplates, out IReadOnlyList <string> invalidForSomeTemplates);
            if (invalidForAllTemplates.Any() || invalidForSomeTemplates.Any())
            {
                hasInvalidParameters = true;
                DisplayInvalidParameters(invalidForAllTemplates);
                DisplayParametersInvalidForSomeTemplates(invalidForSomeTemplates, LocalizableStrings.PartialTemplateMatchSwitchesNotValidForAllMatches);
            }


            if (templateResolutionResult.HasExactMatches)
            {
                IReadOnlyCollection <IGrouping <string, ITemplateMatchInfo> > groupedTemplatesForDisplay = templateResolutionResult.ExactMatchedTemplatesGrouped;
                ShowTemplatesFoundMessage(commandInput);
                DisplayTemplateList(groupedTemplatesForDisplay, environmentSettings, commandInput, defaultLanguage);
            }
            else
            {
                ShowContextAndTemplateNameMismatchHelp(templateResolutionResult, commandInput);
            }

            if (!commandInput.IsListFlagSpecified)
            {
                TemplateUsageHelp.ShowInvocationExamples(templateResolutionResult, hostDataLoader, commandInput.CommandName);
            }

            if (hasInvalidParameters)
            {
                return(CreationResultStatus.NotFound);
            }
            else if (commandInput.IsListFlagSpecified || commandInput.IsHelpFlagSpecified)
            {
                return(templateResolutionResult.HasExactMatches ? CreationResultStatus.Success : CreationResultStatus.NotFound);
            }
            else
            {
                return(CreationResultStatus.OperationNotSpecified);
            }
        }
Exemplo n.º 3
0
        private static TemplateGroupParameterDetails DetermineParameterDispositionsForTemplateGroup(IReadOnlyList <ITemplateInfo> templateGroup, IEngineEnvironmentSettings environmentSettings, INewCommandInput commandInput, IHostSpecificDataLoader hostDataLoader, TemplateCreator templateCreator)
        {
            HashSet <string>     groupUserParamsWithInvalidValues                = new HashSet <string>(StringComparer.Ordinal);
            bool                 groupHasPostActionScriptRunner                  = false;
            List <IParameterSet> parameterSetsForAllTemplatesInGroup             = new List <IParameterSet>();
            IDictionary <string, InvalidParameterInfo> invalidParametersForGroup = new Dictionary <string, InvalidParameterInfo>(StringComparer.Ordinal);
            bool firstInList = true;

            Dictionary <string, IReadOnlyList <string> > defaultVariantsForCanonicals = new Dictionary <string, IReadOnlyList <string> >(StringComparer.Ordinal);
            Dictionary <string, IReadOnlyList <string> > groupVariantsForCanonicals   = new Dictionary <string, IReadOnlyList <string> >(StringComparer.Ordinal);

            HashSet <string>          groupUserParamsWithDefaultValues = new HashSet <string>(StringComparer.Ordinal);
            Dictionary <string, bool> parameterHidingDisposition       = new Dictionary <string, bool>(StringComparer.OrdinalIgnoreCase);
            HashSet <string>          parametersToAlwaysShow           = new HashSet <string>(StringComparer.Ordinal);

            foreach (ITemplateInfo templateInfo in templateGroup.OrderByDescending(x => x.Precedence))
            {
                TemplateUsageInformation usageInformation           = TemplateUsageHelp.GetTemplateUsageInformation(templateInfo, environmentSettings, commandInput, hostDataLoader, templateCreator);
                HostSpecificTemplateData hostSpecificTemplateData   = hostDataLoader.ReadHostSpecificTemplateData(templateInfo);
                HashSet <string>         parametersToExplicitlyHide = hostSpecificTemplateData?.HiddenParameterNames ?? new HashSet <string>(StringComparer.Ordinal);

                foreach (ITemplateParameter parameter in usageInformation.AllParameters.ParameterDefinitions)
                {
                    //If the parameter has previously been encountered...
                    if (parameterHidingDisposition.TryGetValue(parameter.Name, out bool isCurrentlyHidden))
                    {
                        //...and it was hidden, but it's not hidden in this template in the group,
                        //  remove its hiding, otherwise leave it as is
                        if (isCurrentlyHidden && !parametersToExplicitlyHide.Contains(parameter.Name))
                        {
                            parameterHidingDisposition[parameter.Name] = false;
                        }
                    }
                    else
                    {
                        //...otherwise, since this is the first time the parameter has been seen,
                        //  its hiding state should be used as the current disposition
                        parameterHidingDisposition[parameter.Name] = parametersToExplicitlyHide.Contains(parameter.Name);
                    }
                }

                if (firstInList)
                {
                    invalidParametersForGroup = usageInformation.InvalidParameters.ToDictionary(x => x.Canonical, x => x);
                    firstInList = false;
                }
                else
                {
                    invalidParametersForGroup = InvalidParameterInfo.IntersectWithExisting(invalidParametersForGroup, usageInformation.InvalidParameters);
                }

                groupUserParamsWithInvalidValues.IntersectWith(usageInformation.UserParametersWithInvalidValues);    // intersect because if the value is valid for any version, it's valid.
                groupHasPostActionScriptRunner |= usageInformation.HasPostActionScriptRunner;
                parameterSetsForAllTemplatesInGroup.Add(usageInformation.AllParameters);

                // If this template has name overrides (either long or short), it's opinionated.
                //      If it's the first opinionated template about the param, use its variants.
                // Else this template is not opinionated, note its values if there aren't defaults for the param already.
                // At the end, anything in the default list that isn't in the opinionated list will get merged in.
                // TODO: write tests for this code (and the rest of this method while we're at it)
                foreach (KeyValuePair <string, IReadOnlyList <string> > canonicalAndVariants in usageInformation.VariantsForCanonicals)
                {
                    if (hostSpecificTemplateData.LongNameOverrides.ContainsKey(canonicalAndVariants.Key) || hostSpecificTemplateData.ShortNameOverrides.ContainsKey(canonicalAndVariants.Key))
                    {
                        // this template is opinionated about this parameter. If no previous template is opinionated about this param, use this template's variants.
                        if (!groupVariantsForCanonicals.ContainsKey(canonicalAndVariants.Key))
                        {
                            groupVariantsForCanonicals[canonicalAndVariants.Key] = canonicalAndVariants.Value;
                        }
                    }
                    else
                    {
                        // this template is not opinionated about this parameter. If no previous template had defaults for this param, use this template's defaults.
                        if (!defaultVariantsForCanonicals.ContainsKey(canonicalAndVariants.Key))
                        {
                            defaultVariantsForCanonicals[canonicalAndVariants.Key] = canonicalAndVariants.Value;
                        }
                    }
                }

                // If any template says the user input value is the default, include it here.
                groupUserParamsWithDefaultValues.UnionWith(usageInformation.UserParametersWithDefaultValues);
                parametersToAlwaysShow.UnionWith(hostSpecificTemplateData.ParametersToAlwaysShow);
            }

            // aggregate the parameter variants
            foreach (KeyValuePair <string, IReadOnlyList <string> > defaultVariants in defaultVariantsForCanonicals)
            {
                if (!groupVariantsForCanonicals.ContainsKey(defaultVariants.Key))
                {
                    // there were no opinionated variants, take the preferred default.
                    groupVariantsForCanonicals[defaultVariants.Key] = defaultVariants.Value;
                }
            }

            IParameterSet    allGroupParameters = new TemplateGroupParameterSet(parameterSetsForAllTemplatesInGroup);
            string           parameterErrors    = InvalidParameterInfo.InvalidParameterListToString(invalidParametersForGroup.Values.ToList());
            HashSet <string> parametersToHide   = new HashSet <string>(parameterHidingDisposition.Where(x => x.Value).Select(x => x.Key), StringComparer.Ordinal);

            return(new TemplateGroupParameterDetails
            {
                AllParams = allGroupParameters,
                AdditionalInfo = parameterErrors,
                InvalidParams = groupUserParamsWithInvalidValues.ToList(),
                ExplicitlyHiddenParams = parametersToHide,
                GroupVariantsForCanonicals = groupVariantsForCanonicals,
                GroupUserParamsWithDefaultValues = groupUserParamsWithDefaultValues,
                HasPostActionScriptRunner = groupHasPostActionScriptRunner,
                ParametersToAlwaysShow = parametersToAlwaysShow,
            });
        }