Skip to content

Commit

Permalink
Generate chained type-qualified calls too
Browse files Browse the repository at this point in the history
  • Loading branch information
roji committed Aug 11, 2021
1 parent ad51db0 commit c4c2822
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 43 deletions.
60 changes: 38 additions & 22 deletions src/EFCore.Design/Design/Internal/CSharpHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -982,13 +982,21 @@ private string Fragment(MethodCallCodeFragment fragment, bool typeQualified, str

if (typeQualified)
{
if (instanceIdentifier is null || fragment.MethodInfo is null || fragment.ChainedCall is not null)
if (instanceIdentifier is null || fragment.MethodInfo is null)
{
throw new ArgumentException(DesignStrings.CannotGenerateTypeQualifiedMethodCal);
}

builder.Append(fragment.DeclaringType!);

if (current.ChainedCall is not null)
{
builder
.AppendLine()
.IncrementIndent();
}

builder
.Append(fragment.DeclaringType!)
.Append('.')
.Append(fragment.Method)
.Append('(')
Expand All @@ -1001,6 +1009,14 @@ private string Fragment(MethodCallCodeFragment fragment, bool typeQualified, str
}

builder.Append(')');

if (current.ChainedCall is null)
{
return builder.ToString();
}

builder.AppendLine();
current = current.ChainedCall;
}
else
{
Expand All @@ -1015,34 +1031,34 @@ private string Fragment(MethodCallCodeFragment fragment, bool typeQualified, str
.IncrementIndent();
}
}
}

while (true)
{
builder
.Append('.')
.Append(current.Method)
.Append('(');
while (true)
{
builder
.Append('.')
.Append(current.Method)
.Append('(');

for (var i = 0; i < current.Arguments.Count; i++)
for (var i = 0; i < current.Arguments.Count; i++)
{
if (i != 0)
{
if (i != 0)
{
builder.Append(", ");
}

Arg(current.Arguments[i]);
builder.Append(", ");
}

builder.Append(')');
Arg(current.Arguments[i]);
}

if (current.ChainedCall is null)
{
break;
}
builder.Append(')');

builder.AppendLine();
current = current.ChainedCall;
if (current.ChainedCall is null)
{
break;
}

builder.AppendLine();
current = current.ChainedCall;
}

return builder.ToString();
Expand Down
35 changes: 20 additions & 15 deletions src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1525,8 +1525,8 @@ private void GenerateRemainingAnnotations(
{
var fluentApiCalls = Dependencies.AnnotationCodeGenerator.GenerateFluentApiCalls(annotatable, annotations);

MethodCallCodeFragment? chainedCall = null;
var typeQualifiedCalls = new List<MethodCallCodeFragment>();
MethodCallCodeFragment? nonQualifiedCalls = null;
MethodCallCodeFragment? typeQualifiedCalls = null;

// Chain together all Fluent API calls which we can, and leave the others to be generated as type-qualified
foreach (var call in fluentApiCalls)
Expand All @@ -1536,11 +1536,11 @@ private void GenerateRemainingAnnotations(
&& (call.MethodInfo.DeclaringType is null
|| call.MethodInfo.DeclaringType.Assembly != typeof(RelationalModelBuilderExtensions).Assembly))
{
typeQualifiedCalls.Add(call);
typeQualifiedCalls = typeQualifiedCalls is null ? call : typeQualifiedCalls.Chain(call);
}
else
{
chainedCall = chainedCall is null ? call : chainedCall.Chain(call);
nonQualifiedCalls = nonQualifiedCalls is null ? call : nonQualifiedCalls.Chain(call);
}
}

Expand All @@ -1549,17 +1549,17 @@ private void GenerateRemainingAnnotations(
{
// var call = new MethodCallCodeFragment("HasAnnotation", annotation.Name, annotation.Value);
var call = new MethodCallCodeFragment(_hasAnnotationMethodInfo, annotation.Name, annotation.Value);
chainedCall = chainedCall is null ? call : chainedCall.Chain(call);
nonQualifiedCalls = nonQualifiedCalls is null ? call : nonQualifiedCalls.Chain(call);
}

// First generate single Fluent API call chain
if (chainedCall is not null)
if (nonQualifiedCalls is not null)
{
if (inChainedCall)
{
stringBuilder
.AppendLine()
.AppendLines(Code.Fragment(chainedCall), skipFinalNewline: true);
.AppendLines(Code.Fragment(nonQualifiedCalls), skipFinalNewline: true);
}
else
{
Expand All @@ -1568,8 +1568,9 @@ private void GenerateRemainingAnnotations(
stringBuilder.AppendLine();
}

stringBuilder.AppendLines(Code.Fragment(chainedCall, builderName), skipFinalNewline: true);
stringBuilder.AppendLine(";");
stringBuilder
.AppendLines(Code.Fragment(nonQualifiedCalls, builderName), skipFinalNewline: true)
.AppendLine(";");
}

leadingNewline = true;
Expand All @@ -1582,18 +1583,22 @@ private void GenerateRemainingAnnotations(
}

// Then generate separate fully-qualified calls
if (typeQualifiedCalls.Count > 0)
if (typeQualifiedCalls is not null)
{
if (leadingNewline)
{
stringBuilder.AppendLine();
}

foreach (var call in typeQualifiedCalls)
{
stringBuilder.Append(Code.Fragment(call, builderName, typeQualified: true));
stringBuilder.AppendLine(";");
}
stringBuilder
.AppendLines(Code.Fragment(typeQualifiedCalls, builderName, typeQualified: true), skipFinalNewline: true)
.AppendLine(";");

// foreach (var call in typeQualifiedCalls)
// {
// stringBuilder.Append(Code.Fragment(call, builderName, typeQualified: true));
// stringBuilder.AppendLine(";");
// }
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore.Design/Properties/DesignStrings.Designer.cs

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

2 changes: 1 addition & 1 deletion src/EFCore.Design/Properties/DesignStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
<value>Could not find type mapping for column '{columnName}' with data type '{dateType}'. Skipping column.</value>
</data>
<data name="CannotGenerateTypeQualifiedMethodCall" xml:space="preserve">
<value>A type-qualified method call requires an instance identifier, a MethodInfo and no chained calls.</value>
<value>A type-qualified method call requires an instance identifier and a MethodInfo.</value>
</data>
<data name="CompiledModelConstructorBinding" xml:space="preserve">
<value>The entity type '{entityType}' has a custom constructor binding. This is usually caused by using proxies. Compiled model can't be generated, because dynamic proxy types are not supported. If you are not using proxies configure the custom constructor binding in '{customize}' in a partial '{className}' class instead.</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,11 @@ public virtual void Model_annotations_are_stored_in_snapshot()
.HasAnnotation(""AnnotationName"", ""AnnotationValue"")
.HasAnnotation(""Relational:MaxIdentifierLength"", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1);
SqlServerModelBuilderExtensions.HasDatabaseMaxSize(modelBuilder, ""100 MB"");
SqlServerModelBuilderExtensions.HasServiceTierSql(modelBuilder, ""'basic'"");
SqlServerModelBuilderExtensions.HasPerformanceLevelSql(modelBuilder, ""'S0'"");"),
SqlServerModelBuilderExtensions
.UseIdentityColumns(modelBuilder, 1L, 1)
.HasDatabaseMaxSize(""100 MB"")
.HasServiceTierSql(""'basic'"")
.HasPerformanceLevelSql(""'S0'"");"),
o =>
{
Assert.Equal(8, o.GetAnnotations().Count());
Expand Down

0 comments on commit c4c2822

Please sign in to comment.