@@ -25,7 +25,7 @@ private module Ast implements AstSig<Location> {
2525
2626 class AstNode = ControlFlowElementOrCallable ;
2727
28- private predicate skipControlFlow ( AstNode e ) {
28+ additional predicate skipControlFlow ( AstNode e ) {
2929 e instanceof TypeAccess and
3030 not e instanceof TypeAccessPatternExpr
3131 or
@@ -82,13 +82,8 @@ private module Ast implements AstSig<Location> {
8282
8383 AstNode callableGetBody ( Callable c ) {
8484 not skipControlFlow ( result ) and
85- (
86- result = c .getBody ( ) or
87- result = c .( Constructor ) .getObjectInitializerCall ( ) or
88- result = c .( Constructor ) .getInitializer ( ) or
89- c .( ObjectInitMethod ) .initializes ( result ) or
90- Initializers:: staticMemberInitializer ( c , result )
91- )
85+ result = c .getBody ( ) and
86+ not c instanceof Constructor // handled in `callableGetBodyPart`
9287 }
9388
9489 class Stmt = CS:: Stmt ;
@@ -222,10 +217,21 @@ private module Ast implements AstSig<Location> {
222217 * Unlike the standard `Compilation` class, this class also supports buildless
223218 * extraction.
224219 */
225- private newtype CompilationExt =
220+ private newtype TCompilationExt =
226221 TCompilation ( Compilation c ) { not extractionIsStandalone ( ) } or
227222 TBuildless ( ) { extractionIsStandalone ( ) }
228223
224+ private class CompilationExt extends TCompilationExt {
225+ string toString ( ) {
226+ exists ( Compilation c |
227+ this = TCompilation ( c ) and
228+ result = c .toString ( )
229+ )
230+ or
231+ this = TBuildless ( ) and result = "buildless compilation"
232+ }
233+ }
234+
229235/** Gets the compilation that source file `f` belongs to. */
230236private CompilationExt getCompilation ( File f ) {
231237 exists ( Compilation c |
@@ -286,32 +292,18 @@ private module Initializers {
286292 }
287293
288294 /**
289- * Gets the `i`th member initializer expression for object initializer method `obinit`
290- * in compilation `comp`.
295+ * Gets the `i`th member initializer expression for object initializer method `obinit`.
291296 */
292- AssignExpr initializedInstanceMemberOrder ( ObjectInitMethod obinit , CompilationExt comp , int i ) {
293- obinit .initializes ( result ) and
297+ AssignExpr initializedInstanceMemberOrder ( ObjectInitMethod obinit , int i ) {
294298 result =
295299 rank [ i + 1 ] ( AssignExpr ae0 , Location l , string filepath , int startline , int startcolumn |
296300 obinit .initializes ( ae0 ) and
297301 l = ae0 .getLocation ( ) and
298- l .hasLocationInfo ( filepath , startline , startcolumn , _, _) and
299- getCompilation ( l .getFile ( ) ) = comp
302+ l .hasLocationInfo ( filepath , startline , startcolumn , _, _)
300303 |
301304 ae0 order by startline , startcolumn , filepath
302305 )
303306 }
304-
305- /**
306- * Gets the last member initializer expression for object initializer method `obinit`
307- * in compilation `comp`.
308- */
309- AssignExpr lastInitializer ( ObjectInitMethod obinit , CompilationExt comp ) {
310- exists ( int i |
311- result = initializedInstanceMemberOrder ( obinit , comp , i ) and
312- not exists ( initializedInstanceMemberOrder ( obinit , comp , i + 1 ) )
313- )
314- }
315307}
316308
317309private module Exceptions {
@@ -424,6 +416,31 @@ private module Input implements InputSig1, InputSig2 {
424416 l = TLblGoto ( n .( LabelStmt ) .getLabel ( ) )
425417 }
426418
419+ class CallableBodyPartContext = CompilationExt ;
420+
421+ pragma [ nomagic]
422+ Ast:: AstNode callableGetBodyPart ( Callable c , CallableBodyPartContext ctx , int index ) {
423+ not Ast:: skipControlFlow ( result ) and
424+ ctx = getCompilation ( result .getFile ( ) ) and
425+ (
426+ result = Initializers:: initializedInstanceMemberOrder ( c , index )
427+ or
428+ result = Initializers:: initializedStaticMemberOrder ( c , index )
429+ or
430+ exists ( Constructor ctor , int i , int staticMembers |
431+ c = ctor and
432+ staticMembers = count ( Expr init | Initializers:: staticMemberInitializer ( ctor , init ) ) and
433+ index = staticMembers + i + 1
434+ |
435+ i = 0 and result = ctor .getObjectInitializerCall ( )
436+ or
437+ i = 1 and result = ctor .getInitializer ( )
438+ or
439+ i = 2 and result = ctor .getBody ( )
440+ )
441+ )
442+ }
443+
427444 private Expr getQualifier ( QualifiableExpr qe ) {
428445 result = qe .getQualifier ( ) or
429446 result = qe .( ExtensionMethodCall ) .getArgument ( 0 )
@@ -474,80 +491,7 @@ private module Input implements InputSig1, InputSig2 {
474491 )
475492 }
476493
477- pragma [ noinline]
478- private MethodCall getObjectInitializerCall ( Constructor ctor , CompilationExt comp ) {
479- result = ctor .getObjectInitializerCall ( ) and
480- comp = getCompilation ( result .getFile ( ) )
481- }
482-
483- pragma [ noinline]
484- private ConstructorInitializer getInitializer ( Constructor ctor , CompilationExt comp ) {
485- result = ctor .getInitializer ( ) and
486- comp = getCompilation ( result .getFile ( ) )
487- }
488-
489- pragma [ noinline]
490- private Ast:: AstNode getBody ( Constructor ctor , CompilationExt comp ) {
491- result = ctor .getBody ( ) and
492- comp = getCompilation ( result .getFile ( ) )
493- }
494-
495494 predicate step ( PreControlFlowNode n1 , PreControlFlowNode n2 ) {
496- exists ( Constructor ctor |
497- n1 .( EntryNodeImpl ) .getEnclosingCallable ( ) = ctor and
498- if Initializers:: staticMemberInitializer ( ctor , _)
499- then n2 .isBefore ( Initializers:: initializedStaticMemberOrder ( ctor , 0 ) )
500- else
501- if exists ( ctor .getObjectInitializerCall ( ) )
502- then n2 .isBefore ( ctor .getObjectInitializerCall ( ) )
503- else
504- if exists ( ctor .getInitializer ( ) )
505- then n2 .isBefore ( ctor .getInitializer ( ) )
506- else n2 .isBefore ( ctor .getBody ( ) )
507- or
508- exists ( int i | n1 .isAfter ( Initializers:: initializedStaticMemberOrder ( ctor , i ) ) |
509- n2 .isBefore ( Initializers:: initializedStaticMemberOrder ( ctor , i + 1 ) )
510- or
511- not exists ( Initializers:: initializedStaticMemberOrder ( ctor , i + 1 ) ) and
512- n2 .isBefore ( ctor .getBody ( ) )
513- )
514- or
515- exists ( CompilationExt comp |
516- n1 .isAfter ( getObjectInitializerCall ( ctor , comp ) ) and
517- if exists ( getInitializer ( ctor , comp ) )
518- then n2 .isBefore ( getInitializer ( ctor , comp ) )
519- else
520- // This is only relevant in the context of compilation errors, since
521- // normally the existence of an object initializer call implies the
522- // existence of an initializer.
523- if exists ( getBody ( ctor , comp ) )
524- then n2 .isBefore ( getBody ( ctor , comp ) )
525- else n2 .( NormalExitNodeImpl ) .getEnclosingCallable ( ) = ctor
526- or
527- n1 .isAfter ( getInitializer ( ctor , comp ) ) and
528- if exists ( getBody ( ctor , comp ) )
529- then n2 .isBefore ( getBody ( ctor , comp ) )
530- else n2 .( NormalExitNodeImpl ) .getEnclosingCallable ( ) = ctor
531- )
532- or
533- n1 .isAfter ( ctor .getBody ( ) ) and
534- n2 .( NormalExitNodeImpl ) .getEnclosingCallable ( ) = ctor
535- )
536- or
537- exists ( ObjectInitMethod obinit |
538- n1 .( EntryNodeImpl ) .getEnclosingCallable ( ) = obinit and
539- n2 .isBefore ( Initializers:: initializedInstanceMemberOrder ( obinit , _, 0 ) )
540- or
541- exists ( CompilationExt comp , int i |
542- // Flow from one member initializer to the next
543- n1 .isAfter ( Initializers:: initializedInstanceMemberOrder ( obinit , comp , i ) ) and
544- n2 .isBefore ( Initializers:: initializedInstanceMemberOrder ( obinit , comp , i + 1 ) )
545- )
546- or
547- n1 .isAfter ( Initializers:: lastInitializer ( obinit , _) ) and
548- n2 .( NormalExitNodeImpl ) .getEnclosingCallable ( ) = obinit
549- )
550- or
551495 exists ( QualifiableExpr qe | qe .isConditional ( ) |
552496 n1 .isBefore ( qe ) and n2 .isBefore ( getQualifier ( qe ) )
553497 or
0 commit comments