Skip to content

Commit

Permalink
Flow project's nullable setting into design-time code
Browse files Browse the repository at this point in the history
Part of dotnet#15520
  • Loading branch information
bricelam committed May 7, 2021
1 parent fe2e2ec commit 6a44672
Show file tree
Hide file tree
Showing 19 changed files with 76 additions and 6 deletions.
4 changes: 4 additions & 0 deletions src/EFCore.Design/Design/Internal/DatabaseOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class DatabaseOperations
private readonly string _projectDir;
private readonly string? _rootNamespace;
private readonly string? _language;
private readonly bool _nullable;
private readonly DesignTimeServicesBuilder _servicesBuilder;
private readonly string[] _args;

Expand All @@ -39,6 +40,7 @@ public DatabaseOperations(
string projectDir,
string? rootNamespace,
string? language,
bool nullable,
string[]? args)
{
Check.NotNull(reporter, nameof(reporter));
Expand All @@ -49,6 +51,7 @@ public DatabaseOperations(
_projectDir = projectDir;
_rootNamespace = rootNamespace;
_language = language;
_nullable = nullable;
_args = args ?? Array.Empty<string>();

_servicesBuilder = new DesignTimeServicesBuilder(assembly, startupAssembly, reporter, _args);
Expand Down Expand Up @@ -108,6 +111,7 @@ public virtual SavedModelFiles ScaffoldContext(
ModelNamespace = finalModelNamespace,
ContextNamespace = finalContextNamespace,
Language = _language,
Nullable = _nullable,
ContextDir = MakeDirRelative(outputDir, outputContextDir),
ContextName = dbContextClassName,
SuppressOnConfiguring = suppressOnConfiguring
Expand Down
4 changes: 4 additions & 0 deletions src/EFCore.Design/Design/Internal/MigrationsOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class MigrationsOperations
private readonly string _projectDir;
private readonly string? _rootNamespace;
private readonly string? _language;
private readonly bool _nullable;
private readonly DesignTimeServicesBuilder _servicesBuilder;
private readonly DbContextOperations _contextOperations;
private readonly string[] _args;
Expand All @@ -46,6 +47,7 @@ public MigrationsOperations(
string projectDir,
string? rootNamespace,
string? language,
bool nullable,
string[]? args)
{
Check.NotNull(reporter, nameof(reporter));
Expand All @@ -58,6 +60,7 @@ public MigrationsOperations(
_projectDir = projectDir;
_rootNamespace = rootNamespace;
_language = language;
_nullable = nullable;
_args = args ?? Array.Empty<string>();
_contextOperations = new DbContextOperations(
reporter,
Expand Down Expand Up @@ -105,6 +108,7 @@ public virtual MigrationFiles AddMigration(
var scaffolder = scope.ServiceProvider.GetRequiredService<IMigrationsScaffolder>();
var migration =
string.IsNullOrEmpty(@namespace)
// TODO: Honor _nullable (issue #18950)
? scaffolder.ScaffoldMigration(name, _rootNamespace ?? string.Empty, subNamespace, _language)
: scaffolder.ScaffoldMigration(name, null, @namespace, _language);
return scaffolder.Save(_projectDir, migration, outputDir);
Expand Down
5 changes: 5 additions & 0 deletions src/EFCore.Design/Design/OperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class OperationExecutor : MarshalByRefObject
private readonly string _startupTargetName;
private readonly string? _rootNamespace;
private readonly string? _language;
private readonly bool _nullable;
private readonly string[]? _designArgs;
private readonly OperationReporter _reporter;

Expand All @@ -47,6 +48,7 @@ public class OperationExecutor : MarshalByRefObject
/// <para><c>projectDir</c>--The target project's root directory.</para>
/// <para><c>rootNamespace</c>--The target project's root namespace.</para>
/// <para><c>language</c>--The programming language to be used to generate classes.</para>
/// <para><c>nullable</c>--A value indicating whether nullable reference types are enabled.</para>
/// <para><c>remainingArguments</c>--Extra arguments passed into the operation.</para>
/// </summary>
/// <param name="reportHandler"> The <see cref="IOperationReportHandler" />. </param>
Expand All @@ -62,6 +64,7 @@ public OperationExecutor(IOperationReportHandler reportHandler, IDictionary args
_projectDir = (string)args["projectDir"]!;
_rootNamespace = (string?)args["rootNamespace"];
_language = (string?)args["language"];
_nullable = (bool)(args["nullable"] ?? false);
_designArgs = (string[]?)args["remainingArguments"];

var toolsVersion = (string?)args["toolsVersion"];
Expand Down Expand Up @@ -108,6 +111,7 @@ private MigrationsOperations MigrationsOperations
_projectDir,
_rootNamespace,
_language,
_nullable,
_designArgs);

private DbContextOperations ContextOperations
Expand All @@ -127,6 +131,7 @@ private DatabaseOperations DatabaseOperations
_projectDir,
_rootNamespace,
_language,
_nullable,
_designArgs);

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public override ScaffoldedModel GenerateModel(
CoreStrings.ArgumentPropertyNull(nameof(options.ConnectionString), nameof(options)), nameof(options));
}

// TODO: Honor options.Nullable (issue #15520)
var generatedCode = CSharpDbContextGenerator.WriteCode(
model,
options.ContextName,
Expand All @@ -113,6 +114,7 @@ public override ScaffoldedModel GenerateModel(

foreach (var entityType in model.GetEntityTypes())
{
// TODO: Honor options.Nullable (issue #15520)
generatedCode = CSharpEntityTypeGenerator.WriteCode(entityType, options.ModelNamespace, options.UseDataAnnotations);

// output EntityType poco .cs file
Expand Down
6 changes: 6 additions & 0 deletions src/EFCore.Design/Scaffolding/ModelCodeGenerationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ public class ModelCodeGenerationOptions
/// <value> The programming language to scaffold for. </value>
public virtual string? Language { get; set; }

/// <summary>
/// Gets or sets a value indicating whether nullable reference types are enabled.
/// </summary>
/// <value> A value indicating whether nullable reference types are enabled. </value>
public virtual bool Nullable { get; set; }

/// <summary>
/// Gets or sets the DbContext output directory.
/// </summary>
Expand Down
16 changes: 16 additions & 0 deletions src/EFCore.Tools/tools/EntityFrameworkCore.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,7 @@ function EF($project, $startupProject, $params, $applicationArgs, [switch] $skip
$targetPath = Join-Path $targetDir $targetFileName
$rootNamespace = GetProperty $project.Properties 'RootNamespace'
$language = GetLanguage $project
$nullable = GetNullable $project

$params += '--verbose',
'--no-color',
Expand All @@ -1130,6 +1131,11 @@ function EF($project, $startupProject, $params, $applicationArgs, [switch] $skip
$params += '--root-namespace', $rootNamespace
}

if ($nullable -in 'enable', 'annotations')
{
$params += '--nullable'
}

$arguments = ToArguments $params
if ($applicationArgs)
{
Expand Down Expand Up @@ -1275,6 +1281,16 @@ function GetLanguage($project)
return GetMSBuildProperty $project 'Language'
}

function GetNullable($project)
{
if (IsCpsProject $project)
{
return GetCpsProperty $project 'Nullable'
}

return GetMSBuildProperty $project 'Nullable'
}

function GetVsHierarchy($project)
{
$solution = Get-VSService 'Microsoft.VisualStudio.Shell.Interop.SVsSolution' 'Microsoft.VisualStudio.Shell.Interop.IVsSolution'
Expand Down
4 changes: 3 additions & 1 deletion src/dotnet-ef/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public Project(string file, string? framework, string? configuration, string? ru
public string? RuntimeFrameworkVersion { get; set; }
public string? TargetFileName { get; set; }
public string? TargetFrameworkMoniker { get; set; }
public string? Nullable { get; set; }

public static Project FromFile(
string file,
Expand Down Expand Up @@ -133,7 +134,8 @@ public static Project FromFile(
RootNamespace = metadata["RootNamespace"],
RuntimeFrameworkVersion = metadata["RuntimeFrameworkVersion"],
TargetFileName = metadata["TargetFileName"],
TargetFrameworkMoniker = metadata["TargetFrameworkMoniker"]
TargetFrameworkMoniker = metadata["TargetFrameworkMoniker"],
Nullable = metadata["Nullable"]
};
}

Expand Down
1 change: 1 addition & 0 deletions src/dotnet-ef/Resources/EntityFrameworkCore.targets
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<EFProjectMetadata Include="RuntimeFrameworkVersion: $(RuntimeFrameworkVersion)" />
<EFProjectMetadata Include="TargetFileName: $(TargetFileName)" />
<EFProjectMetadata Include="TargetFrameworkMoniker: $(TargetFrameworkMoniker)" />
<EFProjectMetadata Include="Nullable: $(Nullable)" />
</ItemGroup>
<WriteLinesToFile Condition=" '$(TargetFramework)' != '' "
File="$(EFProjectMetadataFile)"
Expand Down
7 changes: 7 additions & 0 deletions src/dotnet-ef/RootCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ protected override int Execute(string[] _)
args.Add(project.RootNamespace!);
args.Add("--language");
args.Add(project.Language!);

if (string.Equals(project.Nullable, "enable", StringComparison.OrdinalIgnoreCase)
|| string.Equals(project.Nullable, "annotations", StringComparison.OrdinalIgnoreCase))
{
args.Add("--nullable");
}

args.Add("--working-dir");
args.Add(Directory.GetCurrentDirectory());

Expand Down
4 changes: 3 additions & 1 deletion src/ef/AppDomainOperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ public AppDomainOperationExecutor(
string? dataDirectory,
string? rootNamespace,
string? language,
bool nullable,
string[] remainingArguments)
: base(assembly, startupAssembly, projectDir, rootNamespace, language, remainingArguments)
: base(assembly, startupAssembly, projectDir, rootNamespace, language, nullable, remainingArguments)
{
var info = new AppDomainSetup { ApplicationBase = AppBasePath };

Expand Down Expand Up @@ -67,6 +68,7 @@ public AppDomainOperationExecutor(
{ "projectDir", ProjectDirectory },
{ "rootNamespace", RootNamespace },
{ "language", Language },
{ "nullable", Nullable },
{ "toolsVersion", ProductInfo.GetVersion() },
{ "remainingArguments", RemainingArguments }
}
Expand Down
4 changes: 4 additions & 0 deletions src/ef/Commands/ProjectCommandBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal abstract class ProjectCommandBase : EFCommandBase
private CommandOption? _projectDir;
private CommandOption? _rootNamespace;
private CommandOption? _language;
private CommandOption? _nullable;

protected CommandOption? WorkingDir { get; private set; }

Expand All @@ -34,6 +35,7 @@ public override void Configure(CommandLineApplication command)
_projectDir = command.Option("--project-dir <PATH>", Resources.ProjectDirDescription);
_rootNamespace = command.Option("--root-namespace <NAMESPACE>", Resources.RootNamespaceDescription);
_language = command.Option("--language <LANGUAGE>", Resources.LanguageDescription);
_nullable = command.Option("--nullable", Resources.NullableDescription);
WorkingDir = command.Option("--working-dir <PATH>", Resources.WorkingDirDescription);

base.Configure(command);
Expand Down Expand Up @@ -63,6 +65,7 @@ protected IOperationExecutor CreateExecutor(string[] remainingArguments)
_dataDir!.Value(),
_rootNamespace!.Value(),
_language!.Value(),
_nullable!.HasValue(),
remainingArguments);
}
catch (MissingMethodException) // NB: Thrown with EF Core 3.1
Expand Down Expand Up @@ -99,6 +102,7 @@ protected IOperationExecutor CreateExecutor(string[] remainingArguments)
_dataDir!.Value(),
_rootNamespace!.Value(),
_language!.Value(),
_nullable!.HasValue(),
remainingArguments);
}
catch (FileNotFoundException ex)
Expand Down
3 changes: 3 additions & 0 deletions src/ef/OperationExecutorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ internal abstract class OperationExecutorBase : IOperationExecutor
protected string ProjectDirectory { get; }
protected string RootNamespace { get; }
protected string? Language { get; }
protected bool Nullable { get; }
protected string[] RemainingArguments { get; }

protected OperationExecutorBase(
Expand All @@ -31,6 +32,7 @@ protected OperationExecutorBase(
string? projectDir,
string? rootNamespace,
string? language,
bool nullable,
string[] remainingArguments)
{
AssemblyFileName = Path.GetFileNameWithoutExtension(assembly);
Expand All @@ -44,6 +46,7 @@ protected OperationExecutorBase(
RootNamespace = rootNamespace ?? AssemblyFileName;
ProjectDirectory = projectDir ?? Directory.GetCurrentDirectory();
Language = language;
Nullable = nullable;
RemainingArguments = remainingArguments ?? Array.Empty<string>();

Reporter.WriteVerbose(Resources.UsingAssembly(AssemblyFileName));
Expand Down
7 changes: 6 additions & 1 deletion src/ef/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/ef/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@
<data name="NoTransactionsDescription" xml:space="preserve">
<value>Don't generate SQL transaction statements.</value>
</data>
<data name="NullableDescription" xml:space="preserve">
<value>Enable nullable reference types.</value>
</data>
<data name="Options" xml:space="preserve">
<value>Options: {options}</value>
</data>
Expand Down
4 changes: 3 additions & 1 deletion src/ef/ReflectionOperationExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ public ReflectionOperationExecutor(
string? dataDirectory,
string? rootNamespace,
string? language,
bool nullable,
string[] remainingArguments)
: base(assembly, startupAssembly, projectDir, rootNamespace, language, remainingArguments)
: base(assembly, startupAssembly, projectDir, rootNamespace, language, nullable, remainingArguments)
{
if (dataDirectory != null)
{
Expand Down Expand Up @@ -57,6 +58,7 @@ public ReflectionOperationExecutor(
{ "projectDir", ProjectDirectory },
{ "rootNamespace", RootNamespace },
{ "language", Language },
{ "nullable", Nullable },
{ "toolsVersion", ProductInfo.GetVersion() },
{ "remainingArguments", RemainingArguments }
})!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public void Can_pass_null_args()
"projectDir",
"RootNamespace",
"C#",
nullable: false,
args: null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public void Can_pass_null_args()
"projectDir",
"RootNamespace",
"C#",
nullable: false,
args: null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ public TestDatabaseOperations(
string projectDir,
string rootNamespace,
string language,
bool nullable,
string[] args)
: base(reporter, assembly, startupAssembly, projectDir, rootNamespace, language, args)
: base(reporter, assembly, startupAssembly, projectDir, rootNamespace, language, nullable, args)
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ public TestMigrationsOperations(
string projectDir,
string rootNamespace,
string language,
bool nullable,
string[] args)
: base(reporter, assembly, startupAssembly, projectDir, rootNamespace, language, args)
: base(reporter, assembly, startupAssembly, projectDir, rootNamespace, language, nullable, args)
{
}
}
Expand Down

0 comments on commit 6a44672

Please sign in to comment.