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); } }
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); } }
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, }); }