C#: Add ObjectInitMethod as enclosing callable for the instance initializers.

This commit is contained in:
Anders Schack-Mulligen
2026-03-17 13:29:36 +01:00
parent c24b43d01e
commit 19faf8f30b
3 changed files with 32 additions and 30 deletions

View File

@@ -336,6 +336,22 @@ class ExtensionTypeExtensionMethod extends ExtensionMethodImpl {
ExtensionTypeExtensionMethod() { this.isInExtension() }
}
/**
* A non-static member with an initializer, for example a field `int Field = 0`.
*/
private class InitializedInstanceMember extends Member {
private AssignExpr ae;
InitializedInstanceMember() {
not this.isStatic() and
expr_parent_top_level(ae, _, this) and
not ae = getExpressionBody(_)
}
/** Gets the initializer expression. */
AssignExpr getInitializer() { result = ae }
}
/**
* An object initializer method.
*
@@ -347,6 +363,17 @@ class ExtensionTypeExtensionMethod extends ExtensionMethodImpl {
*/
class ObjectInitMethod extends Method {
ObjectInitMethod() { this.getName() = "<object initializer>" }
/**
* Holds if this object initializer method performs the initialization
* of a member via assignment `init`.
*/
predicate initializes(AssignExpr init) {
exists(InitializedInstanceMember m |
this.getDeclaringType().getAMember() = m and
init = m.getInitializer()
)
}
}
/**

View File

@@ -214,6 +214,8 @@ private module Cached {
parent*(enclosingStart(cfe), c.(Constructor).getInitializer())
or
parent*(cfe, c.(Constructor).getObjectInitializerCall())
or
parent*(cfe, any(AssignExpr init | c.(ObjectInitMethod).initializes(init)))
}
/** Holds if the enclosing statement of expression `e` is `s`. */

View File

@@ -10,42 +10,15 @@ private import semmle.code.csharp.ExprOrStmtParent
private import semmle.code.csharp.commons.Compilation
private module Initializers {
/**
* A non-static member with an initializer, for example a field `int Field = 0`.
*/
class InitializedInstanceMember extends Member {
private AssignExpr ae;
InitializedInstanceMember() {
not this.isStatic() and
expr_parent_top_level(ae, _, this) and
not ae = any(Callable c).getExpressionBody()
}
/** Gets the initializer expression. */
AssignExpr getInitializer() { result = ae }
}
/**
* Holds if `obinit` is an object initializer method that performs the initialization
* of a member via assignment `init`.
*/
predicate obinitInitializes(ObjectInitMethod obinit, AssignExpr init) {
exists(InitializedInstanceMember m |
obinit.getDeclaringType().getAMember() = m and
init = m.getInitializer()
)
}
/**
* Gets the `i`th member initializer expression for object initializer method `obinit`
* in compilation `comp`.
*/
AssignExpr initializedInstanceMemberOrder(ObjectInitMethod obinit, CompilationExt comp, int i) {
obinitInitializes(obinit, result) and
obinit.initializes(result) and
result =
rank[i + 1](AssignExpr ae0, Location l |
obinitInitializes(obinit, ae0) and
obinit.initializes(ae0) and
l = ae0.getLocation() and
getCompilation(l.getFile()) = comp
|
@@ -74,7 +47,7 @@ class CfgScope extends Element, @top_level_exprorstmt_parent {
any(Callable c |
c.(Constructor).hasInitializer()
or
Initializers::obinitInitializes(c, _)
c.(ObjectInitMethod).initializes(_)
or
c.hasBody()
)