refactoring TemplateInserter process to be applied per language and per project component

This commit is contained in:
Ken Schlobohm 2021-03-05 10:51:24 -06:00
Родитель 9835406635
Коммит 7bd4dd702b
11 изменённых файлов: 36 добавлений и 21 удалений

Просмотреть файл

@ -10,7 +10,7 @@
"PackageMapPath": "PackageMaps"
},
"TemplateInserter": {
"TemplatePath": "Templates"
"TemplateConfigFiles": [ "Templates\\CSharpWebAppTemplates\\TemplateConfig.json" ]
},
"TFMSelector": {
"CurrentTFMBase": "net5.0",

Просмотреть файл

@ -1,7 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.DotNet.UpgradeAssistant.Steps.Templates
{
@ -14,6 +16,23 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Templates
public ItemSpec[]? TemplateItems { get; set; }
public bool UpdateWebAppsOnly { get; set; }
public ProjectComponents[]? TemplateAppliesTo { get; set; }
public Language? TemplateLanguage { get; set; }
internal bool AppliesToProject(IProject project)
{
if (TemplateAppliesTo is not null && !TemplateAppliesTo.All(flag => project.Components.HasFlag(flag)))
{
return false;
}
if (TemplateLanguage is not null && TemplateLanguage != project.Language)
{
return false;
}
return true;
}
}
}

Просмотреть файл

@ -5,6 +5,6 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Templates
{
public class TemplateInserterOptions
{
public string? TemplatePath { get; set; }
public string[]? TemplateConfigFiles { get; set; }
}
}

Просмотреть файл

@ -71,7 +71,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Templates
}
}
protected override bool IsApplicableImpl(IUpgradeContext context) => context?.CurrentProject is not null && context.CurrentProject.Language == Language.CSharp && _templateProvider.TemplateConfigFileNames.Any();
protected override bool IsApplicableImpl(IUpgradeContext context) => context?.CurrentProject is not null && _templateProvider.TemplateConfigFileNames.Any();
protected override async Task<UpgradeStepInitializeResult> InitializeImplAsync(IUpgradeContext context, CancellationToken token)
{
@ -84,7 +84,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Templates
try
{
_itemsToAdd = (await _templateProvider.GetTemplatesAsync(IsWebApp(project), token).ConfigureAwait(false))
_itemsToAdd = (await _templateProvider.GetTemplatesAsync(project, token).ConfigureAwait(false))
.Where(kvp => IsTemplateNeeded(project, kvp.Value))
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

Просмотреть файл

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.DotNet.UpgradeAssistant.Extensions;
@ -15,12 +16,11 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Templates
{
public class TemplateProvider
{
private const string TemplateConfigFileName = "TemplateConfig.json";
private const string TemplateInserterOptionsSectionName = "TemplateInserter";
private static readonly JsonSerializerOptions JsonOptions = new()
{
Converters = { new JsonStringProjectItemTypeConverter() }
Converters = { new JsonStringProjectItemTypeConverter(), new JsonStringEnumConverter() }
};
private readonly AggregateExtension _extensions;
@ -37,7 +37,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Templates
_templateConfigFiles = _extensions.ExtensionProviders.ToDictionary(e => e, e => GetTemplateConfigFiles(e));
}
internal async Task<Dictionary<string, RuntimeItemSpec>> GetTemplatesAsync(bool isWebApp, CancellationToken token)
internal async Task<Dictionary<string, RuntimeItemSpec>> GetTemplatesAsync(IProject project, CancellationToken token)
{
var templates = new Dictionary<string, RuntimeItemSpec>();
@ -52,7 +52,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Templates
// If there was a problem reading the configuration or the configuration only applies to web apps and the
// current project isn't a web app, continue to the next config file.
if (templateConfig?.TemplateItems is null || (!isWebApp && templateConfig.UpdateWebAppsOnly))
if (templateConfig?.TemplateItems is null || !templateConfig.AppliesToProject(project))
{
_logger.LogDebug("Skipping inapplicable template config file {TemplateConfigFile}", configFile);
continue;
@ -98,6 +98,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Templates
}
}
/// <summary>
/// Gets template config files in an extension location.
/// </summary>
@ -107,7 +108,7 @@ namespace Microsoft.DotNet.UpgradeAssistant.Steps.Templates
{
_logger.LogDebug("Looking for template config files in extension {Extension}", extension.Name);
var options = extension.GetOptions<TemplateInserterOptions>(TemplateInserterOptionsSectionName);
var configFiles = options?.TemplatePath is null ? Enumerable.Empty<string>() : extension.GetFiles(options.TemplatePath, TemplateConfigFileName);
var configFiles = options?.TemplateConfigFiles ?? Enumerable.Empty<string>();
_logger.LogDebug("Found {TemplateCount} template config files in extension {Extension}", configFiles.Count(), extension.Name);
return configFiles;
}

Просмотреть файл

@ -30,5 +30,6 @@
"Keywords": []
}
],
"UpdateWebAppsOnly": true
"TemplateLanguage": "CSharp",
"TemplateAppliesTo": [ "Web" ]
}

Просмотреть файл

@ -19,27 +19,21 @@ namespace Microsoft.DotNet.UpgradeAssistant.Tests.Checks
public static IEnumerable<object[]> TestData =>
new List<object[]>
{
new object[] { new IProject[] { GetValidProject() }, true },
new object[] { new IProject[] { GetValidProject(), GetValidProject() }, true },
new object[] { new IProject[] { GetInvalidProject() }, false },
new object[] { new IProject[] { GetValidProject(), GetInvalidProject(), GetValidProject() }, false },
new object[] { Array.Empty<IProject>(), true },
new object[] { GetValidProject(), true },
new object[] { GetInvalidProject(), false },
};
[Theory]
[MemberData(nameof(TestData))]
public async Task OnlyVisualBasicWpfApplicationsFailCheck(IProject[] projects, bool isReady)
public async Task OnlyVisualBasicWpfApplicationsFailCheck(IProject project, bool isReady)
{
// Arrange
using var mock = AutoMock.GetLoose();
var context = mock.Mock<IUpgradeContext>();
context.Setup(c => c.Projects).Returns(projects);
var readyCheck = mock.Create<VisualBasicWpfCheck>();
// Act
var result = await readyCheck.IsReadyAsync(context.Object, CancellationToken.None).ConfigureAwait(false);
var result = await readyCheck.IsReadyAsync(project, CancellationToken.None).ConfigureAwait(false);
// Assert
Assert.Equal(isReady, result);