-
Notifications
You must be signed in to change notification settings - Fork 1.8k
C# 12: Primary constructor inititalizers. #15625
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C# 12: Primary constructor inititalizers. #15625
Conversation
b6737bb
to
a149bde
Compare
…ailing dataflow test.
…ise we get missing post update nodes to to reverseRead in the data flow consistency queries.
Sadly DCA doesn't show any new results. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added some minor comments/question.
@@ -10,8 +12,16 @@ namespace Semmle.Extraction.CSharp.Entities | |||
{ | |||
internal class Constructor : Method | |||
{ | |||
private readonly Lazy<List<SyntaxNode>> DeclaringReferenceSyntax; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do we gain with Lazy<>
? I think we're using these nodes in the ReportingLocation
. Doesn't this mean that we need the DeclaringReferenceSyntax
for all constructors?
Minor: fields should start with lower case letters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I will just initialize it directly in the constructor.
if (IsPrimary) | ||
{ | ||
// Create a synthetic empty body for primary constructors. | ||
Statements.SyntheticEmptyBlock.Create(Context, this, 0, Location); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed on Slack, this might also be useful for default constructors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is a good point!
I would prefer to make furthermore improvements on follow up PRs. Is that ok?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, a separate PR sounds good.
if (Block is null && ExpressionBody is null && !IsPrimary || | ||
!IsSourceDeclaration) | ||
{ | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed on Slack, this might also apply to default constructors too.
class Base {}
class Derived : Base {}
Derived
has a default constructor, which implicitly is calling base()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment as above (and thank you for putting it here!)
@@ -25,6 +25,7 @@ constructors.cs: | |||
# 23| -1: [TypeMention] object | |||
# 23| 1: [Parameter] s | |||
# 23| -1: [TypeMention] string | |||
# 23| 4: [BlockStmt] {...} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For generated expressions, we're using expr_compiler_generated
. Should we mark SyntheticEmptyBlock
s as compiler generated too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add it to the compiler_generated
table?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, that will require database changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could create stmt_compiler_generated
. Should we do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be fine to do this in a separate PR, so that you could merge this one.
Is there any benefit of having expr_compiler_generated
, compiler_generated
, and stmt_compiler_generated
? It looks like any solution would need a DB schema change. I think my preference would be merging all of this into compiler_generated
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be a nice simplification in any case. I will add that to my list of follow up items!
a149bde
to
f246272
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
I realized that I had forgotten to start the DCA experiment with flags to rebuild the extractor. |
It turns out that the extraction of primary constructors didn't extract initialisers correctly. This is fixed in this PR.
That is, for
We need to extract
object
constructor) for the primary constructor onC1
.C1
constructor) for the primary constructor onC2
.This is needed for
object
constructor.C2
into theC1
base class constructor).It also turns out that we also need to extract at least an empty (synthetic) body for primary constructors to avoid lots of control flow issues.