Skip to content

Commit

Permalink
#82: Add initial support for F# migrations projects
Browse files Browse the repository at this point in the history
  • Loading branch information
seclerp committed Oct 8, 2022
1 parent 6c2dff1 commit 3cf5823
Show file tree
Hide file tree
Showing 19 changed files with 141 additions and 58 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [223.1.0] - 2022-10-20
### Added
- Support for F# migrations projects

## [223.0.0] - 2022-09-30
### Added
- Enable support for Rider 2022.3 EAP
Expand Down
9 changes: 2 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ task setBuildTool {
ext.args << "/p:Configuration=${BuildConfiguration}"
ext.args << "/p:HostFullIdentifier="
ext.args << "/p:SdkVersion=${RiderSdkVersion}"
ext.args << "/p:RiderVersion=${ProductVersion}"
}
}

Expand Down Expand Up @@ -99,13 +100,7 @@ intellij {
downloadSources = false
instrumentCode = false
// TODO: add plugins
// HACK: -- Load F# plugin from custom repository (our local disk)
plugins = ["com.jetbrains.rider.fsharp"]
pluginsRepositories {
marketplace()
custom(new File("${buildDir}/dependencies").toURI().toURL().toString())
}
// /--
plugins = ["rider-fsharp"]

patchPluginXml {
changeNotes = changelog.get(PluginVersion).toHTML()
Expand Down
13 changes: 8 additions & 5 deletions protocol/src/main/kotlin/model/rider/RiderEfCoreModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,13 @@ object RiderEfCoreModel : Ext(SolutionModel.Solution) {
field("migrationShortName", string)
field("migrationLongName", string)
field("migrationFolderAbsolutePath", string)
field("language", enum {
+"Unknown"
+"CSharp"
+"FSharp"
})
field("language", language)
}

private val DbContextInfo = structdef {
field("name", string)
field("fullName", string)
field("language", language)
}

private val EfToolDefinition = structdef {
Expand All @@ -54,6 +51,12 @@ object RiderEfCoreModel : Ext(SolutionModel.Solution) {
})
}

private val language = enum {
+"Unknown"
+"CSharp"
+"FSharp"
}

init {
setting(CSharp50Generator.Namespace, "Rider.Plugins.EfCore.Rd")
setting(Kotlin11Generator.Namespace, "me.seclerp.rider.plugins.efcore.rd")
Expand Down
1 change: 1 addition & 0 deletions src/dotnet/Plugin.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<SdkVersion Condition=" '$(SdkVersion)' == '' ">2022.3.0-eap01</SdkVersion>
<RiderVersion Condition=" '$(RiderVersion)' == '' ">2022.3-EAP1-SNAPSHOT</RiderVersion>

<Title>Entity Framework Core</Title>
<Description>JetBrains Rider plugin for Entity Framework Core</Description>
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ public SupportedMigrationsProjectsProvider(ISolution solution)
public IEnumerable<IProject> GetSupportedMigrationProjects()
{
var supportedMigrationProjects = _solution.GetAllProjects()
.Where(project => project.TargetFrameworkIds.Any(IsSupportedInMigrationsProject))
.Where(project => project.ProjectFileLocation.ExtensionNoDot == "csproj");
.Where(project => project.TargetFrameworkIds.Any(IsSupportedTargetFramework))
.Where(project => IsSupportedProjectExtension(project.ProjectFileLocation.ExtensionNoDot));

return supportedMigrationProjects;
}

private static bool IsSupportedInMigrationsProject(TargetFrameworkId targetFrameworkId) =>
private static bool IsSupportedProjectExtension(string extensionNoDot) =>
extensionNoDot == "csproj"
|| extensionNoDot == "fsproj";

private static bool IsSupportedTargetFramework(TargetFrameworkId targetFrameworkId) =>
targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net5)
|| targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net6)
|| targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net7)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,23 @@ public IEnumerable<IProject> GetSupportedStartupProjects()

var result = projectsWithNugetPacks
.Concat(referencingProjects)
.Where(project => project.TargetFrameworkIds.Any(IsSupportedInStartupProject))
.Where(project => project.TargetFrameworkIds.Any(IsSupportedTargetFramework))
.Distinct();

return result;
}

private bool StartupProjectPackagesInstalled(IProject project) =>
_nugetTracker.HasPackage(project, EfCoreRequiredPackages.EfCoreToolsNugetId)
|| _nugetTracker.HasPackage(project, EfCoreRequiredPackages.EfCoreDesignNugetId);
_nugetTracker.HasPackage(project, KnownNuGetPackages.EfCoreToolsNugetId)
|| _nugetTracker.HasPackage(project, KnownNuGetPackages.EfCoreDesignNugetId);

private IEnumerable<IProject> GetReferencingProjects(IProject project) =>
project.TargetFrameworkIds
.SelectMany(x => project.GetReferencingProjectsEx(x))
.Select(x => x.Value)
.ToList();

private static bool IsSupportedInStartupProject(TargetFrameworkId targetFrameworkId) =>
private static bool IsSupportedTargetFramework(TargetFrameworkId targetFrameworkId) =>
targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net5)
|| targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net6)
|| targetFrameworkId.UniqueString.StartsWith(SupportedTargetFrameworks.Net7)
Expand Down
11 changes: 10 additions & 1 deletion src/dotnet/Rider.Plugins.EfCore/DbContext/DbContextProvider.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Plugins.FSharp.Psi;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp;
using JetBrains.ReSharper.Psi.Modules;
using JetBrains.RiderTutorials.Utils;
using Rider.Plugins.EfCore.Extensions;
Expand Down Expand Up @@ -38,7 +40,14 @@ private static bool TryGetDbContextInfo(IClass @class, out DbContextInfo dbConte
return false;
}

dbContextInfo = new DbContextInfo(@class.ShortName, @class.GetFullClrName());
var language = @class.PresentationLanguage switch
{
CSharpLanguage _ => Language.CSharp,
FSharpLanguage _ => Language.FSharp,
_ => Language.Unknown
};

dbContextInfo = new DbContextInfo(@class.ShortName, @class.GetFullClrName(), language);

return true;
}
Expand Down
7 changes: 4 additions & 3 deletions src/dotnet/Rider.Plugins.EfCore/Extensions/PsiExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using JetBrains.Application.Progress;
using JetBrains.Metadata.Reader.API;
using JetBrains.Metadata.Reader.Impl;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Feature.Services.Navigation.Requests;
using JetBrains.ReSharper.Feature.Services.Occurrences;
Expand All @@ -12,10 +13,10 @@ namespace Rider.Plugins.EfCore.Extensions
{
public static class PsiExtensions
{
public static IAttributeInstance GetAttributeInstance(this IAttributesSet @class, string attributeShortName) =>
public static IAttributeInstance GetAttributeInstance(this IAttributesSet @class, string attributeLongName) =>
@class
.GetAttributeInstances(AttributesSource.All)
.SingleOrDefault(attribute => attribute.GetAttributeShortName() == attributeShortName);
.GetAttributeInstances(new ClrTypeName(attributeLongName), AttributesSource.All)
.SingleOrDefault();

public static IEnumerable<IClass> FindInheritorsOf(this IPsiModule module, IProject project,
IClrTypeName clrTypeName)
Expand Down
5 changes: 4 additions & 1 deletion src/dotnet/Rider.Plugins.EfCore/IRiderEfCoreZone.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using JetBrains.Platform.RdFramework.Actions.Backend;
using JetBrains.ProjectModel.NuGet;
using JetBrains.ReSharper.Feature.Services.Daemon;
using JetBrains.ReSharper.Plugins.FSharp;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp;

Expand All @@ -13,7 +14,9 @@ public interface IRiderEfCoreZone : IPsiLanguageZone,
IRequire<ILanguageCSharpZone>,
IRequire<DaemonZone>,
IRequire<INuGetZone>,
IRequire<IRdActionsBackendZone>
IRequire<IRdActionsBackendZone>,
IRequire<ISinceClr4HostZone>,
IRequire<ILanguageFSharpZone>
{
}
}
8 changes: 8 additions & 0 deletions src/dotnet/Rider.Plugins.EfCore/KnownAttributes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Rider.Plugins.EfCore
{
public static class KnownAttributes
{
public const string MigrationAttribute = "Microsoft.EntityFrameworkCore.Migrations.MigrationAttribute";
public const string DbContextAttribute = "Microsoft.EntityFrameworkCore.Infrastructure.DbContextAttribute";
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Rider.Plugins.EfCore
{
public static class EfCoreRequiredPackages
public static class KnownNuGetPackages
{
public const string EfCoreDesignNugetId = "Microsoft.EntityFrameworkCore.Design";
public const string EfCoreToolsNugetId = "Microsoft.EntityFrameworkCore.Tools";
Expand Down
44 changes: 36 additions & 8 deletions src/dotnet/Rider.Plugins.EfCore/Migrations/MigrationsProvider.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
using System.Collections.Generic;
using System.Linq;
using FSharp.Compiler.Symbols;
using JetBrains.Metadata.Reader.API;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Plugins.FSharp.Psi;
using JetBrains.ReSharper.Plugins.FSharp.Psi.Impl;
using JetBrains.ReSharper.Plugins.FSharp.Psi.Util;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp;
using JetBrains.ReSharper.Psi.Modules;
using JetBrains.RiderTutorials.Utils;
using Rider.Plugins.EfCore.Extensions;
Expand Down Expand Up @@ -48,8 +54,8 @@ private static bool TryGetMigrationInfo(IClass @class, out MigrationInfo migrati
migrationInfo = null;

var migrationShortName = @class.ShortName;
var migrationAttribute = @class.GetAttributeInstance("MigrationAttribute");
var dbContextAttribute = @class.GetAttributeInstance("DbContextAttribute");
var migrationAttribute = @class.GetAttributeInstance(KnownAttributes.MigrationAttribute);
var dbContextAttribute = @class.GetAttributeInstance(KnownAttributes.DbContextAttribute);

if (dbContextAttribute is null || migrationAttribute is null)
{
Expand All @@ -61,11 +67,7 @@ private static bool TryGetMigrationInfo(IClass @class, out MigrationInfo migrati
.ConstantValue
.StringValue;

var dbContextClass = dbContextAttribute
.PositionParameter(0)
.TypeValue
?.GetScalarType()
?.GetClrName();
var dbContextClass = ExtractDbContextClrName(dbContextAttribute);

if (migrationLongName is null || dbContextClass is null)
{
Expand All @@ -76,13 +78,39 @@ private static bool TryGetMigrationInfo(IClass @class, out MigrationInfo migrati
.FirstOrDefault()
.GetLocation().Directory.FileAccessPath;

var language = @class.PresentationLanguage switch
{
CSharpLanguage _ => Language.CSharp,
FSharpLanguage _ => Language.FSharp,
_ => Language.Unknown
};

migrationInfo = new MigrationInfo(
dbContextClass.FullName,
migrationShortName,
migrationLongName,
migrationFolderAbsolutePath);
migrationFolderAbsolutePath,
language);

return true;
}

private static IClrTypeName ExtractDbContextClrName(IAttributeInstance attributeInstance) =>
attributeInstance switch
{
FSharpAttributeInstance fsharpAttribute =>
(fsharpAttribute
.AttrConstructorArgs
.First()
.Item2 as FSharpType)?
.TypeDefinition
.GetClrName(),

_ => attributeInstance
.PositionParameter(0)
.TypeValue
?.GetScalarType()
?.GetClrName()
};
}
}
18 changes: 18 additions & 0 deletions src/dotnet/Rider.Plugins.EfCore/Rider.Plugins.EfCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@
<ItemGroup>
<PackageReference Include="JetBrains.Rider.SDK" Version="$(SdkVersion)" />
</ItemGroup>

<ItemGroup>
<Reference Include="FSharp.Compiler.Service, Version=2022.3.0-dev, Culture=neutral, PublicKeyToken=3099b8d9d20e74bf">
<HintPath>..\..\..\build\riderRD-$(RiderVersion)\plugins\rider-fsharp\dotnet\FSharp.Compiler.Service.dll</HintPath>
</Reference>
<Reference Include="JetBrains.ReSharper.Plugins.FSharp.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=333a98252ac829ae">
<HintPath>..\..\..\build\riderRD-$(RiderVersion)\plugins\rider-fsharp\dotnet\JetBrains.ReSharper.Plugins.FSharp.Common.dll</HintPath>
</Reference>
<Reference Include="JetBrains.ReSharper.Plugins.FSharp.ProjectModelBase, Version=1.0.0.0, Culture=neutral, PublicKeyToken=333a98252ac829ae">
<HintPath>..\..\..\build\riderRD-$(RiderVersion)\plugins\rider-fsharp\dotnet\JetBrains.ReSharper.Plugins.FSharp.ProjectModelBase.dll</HintPath>
</Reference>
<Reference Include="JetBrains.ReSharper.Plugins.FSharp.Psi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=333a98252ac829ae">
<HintPath>..\..\..\build\riderRD-$(RiderVersion)\plugins\rider-fsharp\dotnet\JetBrains.ReSharper.Plugins.FSharp.Psi.dll</HintPath>
</Reference>
<Reference Include="JetBrains.ReSharper.Plugins.FSharp.Psi.Features, Version=1.0.0.0, Culture=neutral, PublicKeyToken=333a98252ac829ae">
<HintPath>..\..\..\build\riderRD-$(RiderVersion)\plugins\rider-fsharp\dotnet\JetBrains.ReSharper.Plugins.FSharp.Psi.Features.dll</HintPath>
</Reference>
</ItemGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,27 @@ import com.intellij.openapi.project.Project
import me.seclerp.observables.*
import me.seclerp.rider.plugins.efcore.features.shared.ObservableMigrations
import me.seclerp.rider.plugins.efcore.features.shared.dialog.CommonDataContext
import me.seclerp.rider.plugins.efcore.rd.Language
import me.seclerp.rider.plugins.efcore.rd.MigrationInfo

class GenerateScriptDataContext(
intellijProject: Project
): CommonDataContext(intellijProject, true) {
val availableFromMigrationNames = observableList<String>()
val availableToMigrationNames = observableList<String>()
val availableFromMigrations = observableList<MigrationInfo>()
val availableToMigrations = observableList<MigrationInfo>()

val fromMigration = observable<String?>(null)
val toMigration = observable<String?>(null)
val fromMigration = observable<MigrationInfo?>(null)
val toMigration = observable<MigrationInfo?>(null)
val outputFilePath = observable("script.sql")
val idempotent = observable(false)
val noTransactions = observable(false)

private val observableMigrations = ObservableMigrations(intellijProject, migrationsProject, dbContext)
private val availableMigrationNames = observableList<String>()
private val availableMigrations = observableList<MigrationInfo>()
.apply {
bind(observableMigrations) { migrations -> migrations
.map { it.migrationLongName }
.sortedByDescending { it }
.map { it }
.sortedByDescending { it.migrationLongName }
}
}

Expand All @@ -31,14 +33,14 @@ class GenerateScriptDataContext(

observableMigrations.initBinding()

availableFromMigrationNames.bind(availableMigrationNames) {
availableFromMigrations.bind(availableMigrations) {
buildList {
addAll(it)
add("0")
add(MigrationInfo("", "0", "0", "", it.lastOrNull()?.language ?: Language.Unknown))
}
}

availableToMigrationNames.bind(availableMigrationNames) {
availableToMigrations.bind(availableMigrations) {
buildList {
addAll(it)
}
Expand Down
Loading

0 comments on commit 3cf5823

Please sign in to comment.