Add a subsystem for detecting versions
This adds the beginning of an API for detecting versions from the project. We will flesh out this API more when we do tooling extensiblity.
This commit is contained in:
parent
0155cf2c73
commit
ca844afe5a
|
|
@ -0,0 +1,101 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
// This is hardcoded for now. A more complete design would fan out to a list of providers.
|
||||
internal class DefaultProjectExtensibilityConfigurationFactory : ProjectExtensibilityConfigurationFactory
|
||||
{
|
||||
private const string MvcAssemblyName = "Microsoft.AspNetCore.Mvc.Razor";
|
||||
private const string RazorV1AssemblyName = "Microsoft.AspNetCore.Razor";
|
||||
private const string RazorV2AssemblyName = "Microsoft.AspNetCore.Razor.Language";
|
||||
|
||||
// Using MaxValue here so that we ignore patch and build numbers. We only want to compare major/minor.
|
||||
private static readonly Version MaxSupportedRazorVersion = new Version(2, 0, Int32.MaxValue, Int32.MaxValue);
|
||||
private static readonly Version MaxSupportedMvcVersion = new Version(2, 0, Int32.MaxValue, Int32.MaxValue);
|
||||
|
||||
private static readonly Version DefaultRazorVersion = new Version(2, 0, 0, 0);
|
||||
private static readonly Version DefaultMvcVersion = new Version(2, 0, 0, 0);
|
||||
|
||||
public async override Task<ProjectExtensibilityConfiguration> GetConfigurationAsync(Project project, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (project == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(project));
|
||||
}
|
||||
|
||||
var compilation = await project.GetCompilationAsync(cancellationToken);
|
||||
return GetConfiguration(compilation.ReferencedAssemblyNames);
|
||||
}
|
||||
|
||||
// internal/separate for testing.
|
||||
internal ProjectExtensibilityConfiguration GetConfiguration(IEnumerable<AssemblyIdentity> references)
|
||||
{
|
||||
// Avoiding ToDictionary here because we don't want a crash if there is a duplicate name.
|
||||
var assemblies = new Dictionary<string, AssemblyIdentity>();
|
||||
foreach (var assembly in references)
|
||||
{
|
||||
assemblies[assembly.Name] = assembly;
|
||||
}
|
||||
|
||||
// First we look for the V2+ Razor Assembly. If we find this then its version is the correct Razor version.
|
||||
AssemblyIdentity razorAssembly;
|
||||
if (assemblies.TryGetValue(RazorV2AssemblyName, out razorAssembly))
|
||||
{
|
||||
if (razorAssembly.Version == null || razorAssembly.Version > MaxSupportedRazorVersion)
|
||||
{
|
||||
// This is a newer Razor version than we know, treat it as a fallback case.
|
||||
razorAssembly = null;
|
||||
}
|
||||
}
|
||||
else if (assemblies.TryGetValue(RazorV1AssemblyName, out razorAssembly))
|
||||
{
|
||||
// This assembly only counts as the 'Razor' assembly if it's a version lower than 2.0.0.
|
||||
if (razorAssembly.Version == null || razorAssembly.Version >= new Version(2, 0, 0, 0))
|
||||
{
|
||||
razorAssembly = null;
|
||||
}
|
||||
}
|
||||
|
||||
AssemblyIdentity mvcAssembly;
|
||||
if (assemblies.TryGetValue(MvcAssemblyName, out mvcAssembly))
|
||||
{
|
||||
if (mvcAssembly.Version == null || mvcAssembly.Version > MaxSupportedMvcVersion)
|
||||
{
|
||||
// This is a newer MVC version than we know, treat it as a fallback case.
|
||||
mvcAssembly = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (razorAssembly != null && mvcAssembly != null)
|
||||
{
|
||||
// This means we've definitely found a supported Razor version and an MVC version.
|
||||
return new MvcExtensibilityConfiguration(
|
||||
ProjectExtensibilityConfigurationKind.ApproximateMatch,
|
||||
new ProjectExtensibilityAssembly(razorAssembly),
|
||||
new ProjectExtensibilityAssembly(mvcAssembly));
|
||||
}
|
||||
|
||||
// If we get here it means we didn't find everything, so we have to guess.
|
||||
if (razorAssembly == null || razorAssembly.Version == null)
|
||||
{
|
||||
razorAssembly = new AssemblyIdentity(RazorV2AssemblyName, DefaultRazorVersion);
|
||||
}
|
||||
|
||||
if (mvcAssembly == null || mvcAssembly.Version == null)
|
||||
{
|
||||
mvcAssembly = new AssemblyIdentity(MvcAssemblyName, DefaultMvcVersion);
|
||||
}
|
||||
|
||||
return new MvcExtensibilityConfiguration(
|
||||
ProjectExtensibilityConfigurationKind.Fallback,
|
||||
new ProjectExtensibilityAssembly(razorAssembly),
|
||||
new ProjectExtensibilityAssembly(mvcAssembly));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Composition;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
using Microsoft.CodeAnalysis.Host.Mef;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
[Shared]
|
||||
[ExportLanguageServiceFactory(typeof(ProjectExtensibilityConfigurationFactory), RazorLanguage.Name)]
|
||||
internal class DefaultProjectExtensibilityConfigurationFactoryFactory : ILanguageServiceFactory
|
||||
{
|
||||
public ILanguageService CreateLanguageService(HostLanguageServices languageServices)
|
||||
{
|
||||
if (languageServices == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(languageServices));
|
||||
}
|
||||
|
||||
return new DefaultProjectExtensibilityConfigurationFactory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal class MvcExtensibilityConfiguration : ProjectExtensibilityConfiguration
|
||||
{
|
||||
public MvcExtensibilityConfiguration(
|
||||
ProjectExtensibilityConfigurationKind kind,
|
||||
ProjectExtensibilityAssembly razorAssembly,
|
||||
ProjectExtensibilityAssembly mvcAssembly)
|
||||
{
|
||||
if (razorAssembly == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(razorAssembly));
|
||||
}
|
||||
|
||||
if (mvcAssembly == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(mvcAssembly));
|
||||
}
|
||||
|
||||
Kind = kind;
|
||||
RazorAssembly = razorAssembly;
|
||||
MvcAssembly = mvcAssembly;
|
||||
|
||||
Assemblies = new[] { RazorAssembly, MvcAssembly, };
|
||||
}
|
||||
|
||||
public override IReadOnlyList<ProjectExtensibilityAssembly> Assemblies { get; }
|
||||
|
||||
public override ProjectExtensibilityConfigurationKind Kind { get; }
|
||||
|
||||
public override ProjectExtensibilityAssembly RazorAssembly { get; }
|
||||
|
||||
public ProjectExtensibilityAssembly MvcAssembly { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal sealed class ProjectExtensibilityAssembly
|
||||
{
|
||||
public ProjectExtensibilityAssembly(AssemblyIdentity identity)
|
||||
{
|
||||
if (identity == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(identity));
|
||||
}
|
||||
|
||||
Identity = identity;
|
||||
}
|
||||
|
||||
public AssemblyIdentity Identity { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal abstract class ProjectExtensibilityConfiguration
|
||||
{
|
||||
public abstract IReadOnlyList<ProjectExtensibilityAssembly> Assemblies { get; }
|
||||
|
||||
public abstract ProjectExtensibilityConfigurationKind Kind { get; }
|
||||
|
||||
public abstract ProjectExtensibilityAssembly RazorAssembly { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CodeAnalysis.Host;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
internal abstract class ProjectExtensibilityConfigurationFactory : ILanguageService
|
||||
{
|
||||
public abstract Task<ProjectExtensibilityConfiguration> GetConfigurationAsync(Project project, CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes how closely the configuration of Razor tooling matches the actual project dependencies.
|
||||
/// </summary>
|
||||
internal enum ProjectExtensibilityConfigurationKind
|
||||
{
|
||||
ApproximateMatch,
|
||||
Fallback,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem
|
||||
{
|
||||
public class DefaultProjectExtensibilityConfigurationFactoryTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("1.0.0.0", "1.0.0.0")]
|
||||
[InlineData("1.1.0.0", "1.1.0.0")]
|
||||
[InlineData("2.0.0.0", "2.0.0.0")]
|
||||
[InlineData("2.0.2.0", "2.0.2.0")]
|
||||
public void GetConfiguration_FindsSupportedConfiguration_ForNewRazor(string razorVersion, string mvcVersion)
|
||||
{
|
||||
// Arrange
|
||||
var references = new AssemblyIdentity[]
|
||||
{
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Razor.Language", new Version(razorVersion)),
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Mvc.Razor", new Version(mvcVersion)),
|
||||
};
|
||||
|
||||
var factory = new DefaultProjectExtensibilityConfigurationFactory();
|
||||
|
||||
// Act
|
||||
var result = factory.GetConfiguration(references);
|
||||
|
||||
// Assert
|
||||
var configuration = Assert.IsType<MvcExtensibilityConfiguration>(result);
|
||||
Assert.Equal(ProjectExtensibilityConfigurationKind.ApproximateMatch, configuration.Kind);
|
||||
Assert.Equal(razorVersion, configuration.RazorAssembly.Identity.Version.ToString());
|
||||
Assert.Equal(mvcVersion, configuration.MvcAssembly.Identity.Version.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1.0.0.0", "1.0.0.0")]
|
||||
[InlineData("1.1.0.0", "1.1.0.0")]
|
||||
[InlineData("1.9.9.9", "2.0.0.0")] // MVC version is ignored
|
||||
public void GetConfiguration_FindsSupportedConfiguration_ForOldRazor(string razorVersion, string mvcVersion)
|
||||
{
|
||||
// Arrange
|
||||
var references = new AssemblyIdentity[]
|
||||
{
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Razor", new Version(razorVersion)),
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Mvc.Razor", new Version(mvcVersion)),
|
||||
};
|
||||
|
||||
var factory = new DefaultProjectExtensibilityConfigurationFactory();
|
||||
|
||||
// Act
|
||||
var result = factory.GetConfiguration(references);
|
||||
|
||||
// Assert
|
||||
var configuration = Assert.IsType<MvcExtensibilityConfiguration>(result);
|
||||
Assert.Equal(ProjectExtensibilityConfigurationKind.ApproximateMatch, configuration.Kind);
|
||||
Assert.Equal(razorVersion, configuration.RazorAssembly.Identity.Version.ToString());
|
||||
Assert.Equal(mvcVersion, configuration.MvcAssembly.Identity.Version.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetConfiguration_RazorVersion_NewAssemblyWinsOverOld()
|
||||
{
|
||||
// Arrange
|
||||
var references = new AssemblyIdentity[]
|
||||
{
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Razor", new Version("1.0.0.0")),
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Razor.Language", new Version("2.0.0.0")),
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Mvc.Razor", new Version("2.0.0.0")),
|
||||
};
|
||||
|
||||
var factory = new DefaultProjectExtensibilityConfigurationFactory();
|
||||
|
||||
// Act
|
||||
var result = factory.GetConfiguration(references);
|
||||
|
||||
// Assert
|
||||
var configuration = Assert.IsType<MvcExtensibilityConfiguration>(result);
|
||||
Assert.Equal(ProjectExtensibilityConfigurationKind.ApproximateMatch, configuration.Kind);
|
||||
Assert.Equal("2.0.0.0", configuration.RazorAssembly.Identity.Version.ToString());
|
||||
Assert.Equal("2.0.0.0", configuration.MvcAssembly.Identity.Version.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetConfiguration_RazorVersion_OldAssemblyIgnoredPastV1()
|
||||
{
|
||||
// Arrange
|
||||
var references = new AssemblyIdentity[]
|
||||
{
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Razor", new Version("2.0.0.0")),
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Mvc.Razor", new Version("2.0.0.0")),
|
||||
};
|
||||
|
||||
var factory = new DefaultProjectExtensibilityConfigurationFactory();
|
||||
|
||||
// Act
|
||||
var result = factory.GetConfiguration(references);
|
||||
|
||||
// Assert
|
||||
var configuration = Assert.IsType<MvcExtensibilityConfiguration>(result);
|
||||
Assert.Equal(ProjectExtensibilityConfigurationKind.Fallback, configuration.Kind);
|
||||
Assert.Equal("2.0.0.0", configuration.RazorAssembly.Identity.Version.ToString());
|
||||
Assert.Equal("2.0.0.0", configuration.MvcAssembly.Identity.Version.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetConfiguration_NoRazorVersion_ChoosesDefault()
|
||||
{
|
||||
// Arrange
|
||||
var references = new AssemblyIdentity[]
|
||||
{
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Mvc.Razor", new Version("2.0.0.0")),
|
||||
};
|
||||
|
||||
var factory = new DefaultProjectExtensibilityConfigurationFactory();
|
||||
|
||||
// Act
|
||||
var result = factory.GetConfiguration(references);
|
||||
|
||||
// Assert
|
||||
var configuration = Assert.IsType<MvcExtensibilityConfiguration>(result);
|
||||
Assert.Equal(ProjectExtensibilityConfigurationKind.Fallback, configuration.Kind);
|
||||
Assert.Equal("2.0.0.0", configuration.RazorAssembly.Identity.Version.ToString());
|
||||
Assert.Equal("2.0.0.0", configuration.MvcAssembly.Identity.Version.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetConfiguration_UnsupportedRazorVersion_ChoosesDefault()
|
||||
{
|
||||
// Arrange
|
||||
var references = new AssemblyIdentity[]
|
||||
{
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Razor.Language", new Version("3.0.0.0")),
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Mvc.Razor", new Version("2.0.0.0")),
|
||||
};
|
||||
|
||||
var factory = new DefaultProjectExtensibilityConfigurationFactory();
|
||||
|
||||
// Act
|
||||
var result = factory.GetConfiguration(references);
|
||||
|
||||
// Assert
|
||||
var configuration = Assert.IsType<MvcExtensibilityConfiguration>(result);
|
||||
Assert.Equal(ProjectExtensibilityConfigurationKind.Fallback, configuration.Kind);
|
||||
Assert.Equal("2.0.0.0", configuration.RazorAssembly.Identity.Version.ToString());
|
||||
Assert.Equal("2.0.0.0", configuration.MvcAssembly.Identity.Version.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetConfiguration_NoMvcVersion_ChoosesDefault()
|
||||
{
|
||||
// Arrange
|
||||
var references = new AssemblyIdentity[]
|
||||
{
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Razor.Language", new Version("2.0.0.0")),
|
||||
};
|
||||
|
||||
var factory = new DefaultProjectExtensibilityConfigurationFactory();
|
||||
|
||||
// Act
|
||||
var result = factory.GetConfiguration(references);
|
||||
|
||||
// Assert
|
||||
var configuration = Assert.IsType<MvcExtensibilityConfiguration>(result);
|
||||
Assert.Equal(ProjectExtensibilityConfigurationKind.Fallback, configuration.Kind);
|
||||
Assert.Equal("2.0.0.0", configuration.RazorAssembly.Identity.Version.ToString());
|
||||
Assert.Equal("2.0.0.0", configuration.MvcAssembly.Identity.Version.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetConfiguration_UnsupportedMvcVersion_ChoosesDefault()
|
||||
{
|
||||
// Arrange
|
||||
var references = new AssemblyIdentity[]
|
||||
{
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Razor.Language", new Version("2.0.0.0")),
|
||||
new AssemblyIdentity("Microsoft.AspNetCore.Mvc.Razor", new Version("3.0.0.0")),
|
||||
};
|
||||
|
||||
var factory = new DefaultProjectExtensibilityConfigurationFactory();
|
||||
|
||||
// Act
|
||||
var result = factory.GetConfiguration(references);
|
||||
|
||||
// Assert
|
||||
var configuration = Assert.IsType<MvcExtensibilityConfiguration>(result);
|
||||
Assert.Equal(ProjectExtensibilityConfigurationKind.Fallback, configuration.Kind);
|
||||
Assert.Equal("2.0.0.0", configuration.RazorAssembly.Identity.Version.ToString());
|
||||
Assert.Equal("2.0.0.0", configuration.MvcAssembly.Identity.Version.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue