Skip to content

Commit a9cf9df

Browse files
committed
Fix constructor bindings
Identify constructors by their binding. Constructors without binding (null) are implicit/default.
1 parent 6d6ebf0 commit a9cf9df

5 files changed

Lines changed: 82 additions & 56 deletions

File tree

app/src/main/java/fr/inria/verveine/extractor/java/EntityDictionary.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2252,7 +2252,7 @@ public Method ensureFamixMethod(IMethodBinding bnd) {
22522252
}
22532253

22542254
/**
2255-
* Returns a Famix Method associated with the IMethodBinding. The Entity is created if it does not exist.
2255+
* Returns a Famix Method associated with the IMethodBinding.
22562256
* The Entity is created if it does not exist.
22572257
* @param name -- the name of the Famix Method (MUST NOT be null, but this is not checked)
22582258
* @param ret -- Famix Type returned by the method (ideally should only be null in case of a constructor, but will accept it in any case)
@@ -2422,7 +2422,7 @@ public Initializer ensureFamixInitializer(TWithMethods owner, Boolean isStatic,
24222422
}
24232423

24242424

2425-
public Initializer ensureImplicitConstructor(TWithMethods owner, String name, Collection<String> parameterTypesNames) {
2425+
public Initializer ensureImplicitConstructor(IMethodBinding binding, TWithMethods owner, String name, Collection<String> parameterTypesNames) {
24262426
Initializer fmx = null;
24272427

24282428
if (owner != null) {
@@ -2439,10 +2439,17 @@ public Initializer ensureImplicitConstructor(TWithMethods owner, String name, Co
24392439
}
24402440

24412441
if (fmx == null) {
2442-
fmx = ensureFamixEntity(Initializer.class, null, name);
2443-
fmx.setParentType(owner);
2444-
fmx.setSignature(name + "()");
2445-
2442+
int modifiers = (binding != null) ? binding.getModifiers() : EntityDictionary.UNKNOWN_MODIFIERS;
2443+
if (binding == null) {
2444+
// OK! Binding is null, this is the default constructor!!
2445+
// It has no source code :)
2446+
fmx = ensureFamixEntity(Initializer.class, null, name);
2447+
fmx.setParentType(owner);
2448+
fmx.setSignature(name + "()");
2449+
} else {
2450+
// But, if we have the binding, that means the constructor exists. Let's just go the normal way
2451+
fmx = (Initializer) this.ensureFamixMethod(binding, name, parameterTypesNames, /*ret type*/null, owner, modifiers);
2452+
}
24462453
}
24472454

24482455
return fmx;

app/src/main/java/fr/inria/verveine/extractor/java/visitors/refvisitors/VisitorInvocRef.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ private Invocation methodInvocation(IMethodBinding calledBnd, String calledName,
442442
if (calledBnd != null) {
443443
parameterTypesNames = Arrays.stream(calledBnd.getParameterTypes()).map(ITypeBinding::getName).toList();
444444
}
445-
invoked = dico.ensureImplicitConstructor((TWithMethods) owner, calledName, parameterTypesNames );
445+
446+
invoked = dico.ensureImplicitConstructor(calledBnd, (TWithMethods) owner, calledName, parameterTypesNames );
446447
} else {
447448
// static method called on the class (or null receiver)
448449
invoked = this.dico.ensureFamixMethod(actualCalledMethodBnd, calledName, unkwnArgs, /* retType */null,

app/src/test/java/fr/inria/verveine/extractor/java/VerveineJTest_Initializers.java

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.moosetechnology.model.famix.famixjavaentities.Class;
77
import org.moosetechnology.model.famix.famixtraits.TInvocation;
88
import org.moosetechnology.model.famix.famixtraits.TMethod;
9+
import org.moosetechnology.model.famix.famixtraits.TNamedEntity;
910

1011
import java.lang.Exception;
1112
import java.util.Collection;
@@ -28,61 +29,47 @@ public void setUp() throws Exception {
2829
public void testNumberOfMethods() {
2930
Collection<Method> methods = entitiesOfType(Method.class);
3031
/*
31-
In class SuperClassWithImplicitConstructor: 1
32-
SuperClassWithImplicitConstructor(), the implicit constructor
33-
34-
In class SuperclassWithConstructor: 3
35-
<Initializer>
36-
SuperclassWithConstructor()
37-
initializeFromSuperAttributeDefinition()
38-
39-
In class ClassWithInitializers: 14
40-
- Initializers (4):
41-
Static <Initializer> = Static attribute definitions
42-
Static initialization block
43-
<Initializer> = Attribute definition
44-
Initialization block
45-
- Constructors (3):
46-
ClassWithInitializers()
47-
ClassWithInitializers(String)
48-
ClassWithInitializers(Boolean)
49-
- Methods (7):
50-
initializeFromStaticAttributeDefinition()
51-
initializeFromStaticInitializationBlock()
52-
initializeFromStaticInitializationBlock2()
53-
initializeFromAttributeDefinition()
54-
initializeFromInstantiationBlock()
55-
initializeFromSecondInstantiationBlock()
56-
initializeFromConstructor()
57-
58-
In ClassWithInnerClass: 1
59-
<Initializer>
60-
61-
In class _Anonymous(InnerClass) (in ClassWithInnerClass): 2
62-
<Initializer>
63-
ClassWithInnerClass(), the implicit constructor
64-
32+
_Anonymous(InnerClass)._Anonymous(InnerClass)() isStatic:false isInitializationBlock: false
33+
ClassWithInitializers.ClassWithInitializers(Boolean) isStatic:false isInitializationBlock: false
34+
ClassWithInitializers.<Initializer>() isStatic:true isInitializationBlock: true
35+
ClassWithInitializers.initializeFromStaticAttributeDefinition() isStatic:true
36+
_Anonymous(InnerClass).<Initializer>() isStatic:false isInitializationBlock: false
37+
ClassWithInitializers.<Initializer>() isStatic:false isInitializationBlock: false
38+
ClassWithInitializers.initializeFromInstantiationBlock() isStatic:false
39+
ClassWithInitializers.ClassWithInitializers() isStatic:false isInitializationBlock: false
40+
ClassWithInitializers.initializeFromSecondInstantiationBlock() isStatic:false
41+
ClassWithInitializers.initializeFromConstructor() isStatic:false
42+
SuperclassWithImplicitConstructor.SuperclassWithImplicitConstructor() isStatic:false isInitializationBlock: false
43+
ClassWithInitializers.initializeFromStaticInitializationBlock2() isStatic:true
44+
SuperclassWithConstructor.SuperclassWithConstructor() isStatic:false isInitializationBlock: false
45+
SuperclassWithConstructor.<Initializer>() isStatic:false isInitializationBlock: false
46+
ClassWithInnerClass.<Initializer>() isStatic:false isInitializationBlock: false
47+
MyClassUserInInitializer.<Initializer>() isStatic:true isInitializationBlock: false
48+
ClassWithInitializers.<Initializer>() isStatic:false isInitializationBlock: true
49+
SuperclassWithConstructor.initializeFromSuperAttributeDefinition() isStatic:false
50+
ClassWithInitializers.ClassWithInitializers(String) isStatic:false isInitializationBlock: false
51+
Object.Object() isStatic:false isInitializationBlock: false
52+
ClassWithInitializers.<Initializer>() isStatic:true isInitializationBlock: false
53+
ClassWithInitializers.initializeFromAttributeDefinition() isStatic:false
54+
ClassWithInitializers.initializeFromStaticInitializationBlock() isStatic:true
55+
MyClass.MyClass() isStatic:false isInitializationBlock: false
6556
*/
66-
for (Class c : entitiesOfType(Class.class)) {
67-
if(!c.getIsStub()) {
68-
System.out.println(c.getName());
69-
for (TMethod m : c.getMethods()) {
70-
System.out.print(" " + m.getName() + " isStatic:" + ((Method) m).getIsClassSide());
71-
if (((Method) m).getIsInitializer()) {
72-
System.out.println(" isInitializationBlock: " + ((Initializer) m).getIsInitializationBlock());
73-
} else {
74-
System.out.println(" ");
75-
}
76-
}
57+
for (TMethod m : methods) {
58+
System.out.print(((TNamedEntity)m.getParentType()).getName() + "." + m.getSignature() + " isStatic:" + ((Method) m).getIsClassSide());
59+
if (((Method) m).getIsInitializer()) {
60+
System.out.println(" isInitializationBlock: " + ((Initializer) m).getIsInitializationBlock());
61+
} else {
62+
System.out.println(" ");
7763
}
78-
};
79-
assertEquals(21,methods.size());
64+
}
65+
66+
assertEquals(24,methods.size());
8067
}
8168

8269
@Test
8370
public void testNumberOfInitializers() {
8471
Collection<Initializer> initializers = entitiesOfType(Initializer.class);
85-
assertEquals(13, initializers.size());
72+
assertEquals(16, initializers.size());
8673
}
8774

8875
@Test
@@ -97,9 +84,11 @@ public void testConstructors() {
9784
ClassWithInitializers(String)
9885
ClassWithInitializers(Boolean)
9986
In class InnerClass (in ClassWithInnerClass): 1, the implicit constructor.
87+
MyClass()
88+
Object() default constructor
10089
*/
10190

102-
assertEquals(6, constructors.size());
91+
assertEquals(8, constructors.size());
10392

10493
for (Initializer constructor : constructors) {
10594
assertEquals(((Type)constructor.getParentType()).getName(), constructor.getName());
@@ -175,5 +164,20 @@ public void testInnerClass() {
175164
var foundAttribute = firstElt(firstElt(initializer.getAccesses()).getCandidates());
176165
assertEquals(firstElt(innerClass.getAttributes()), foundAttribute);
177166
}
167+
168+
@Test
169+
public void testInitializerOfClassUsedInStaticInitializer() {
170+
parser = new VerveineJParser();
171+
repo = parser.getFamixRepo();
172+
parser.configure( new String[] {
173+
"src/test/resources/initializers/MyClassUserInInitializer.java",
174+
"src/test/resources/initializers/MyClass.java"
175+
});
176+
parser.parse();
177+
178+
PrimitiveType voidType = detectFamixElement(PrimitiveType.class, "void");
179+
Initializer initializer = (Initializer)detectFamixElement(Class.class, "MyClass").getMethods().iterator().next();
180+
assertEquals(voidType, initializer.getTyping().getDeclaredType());
181+
}
178182

179183
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package initializers;
2+
3+
public class MyClass {
4+
public MyClass() {
5+
super();
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package initializers;
2+
3+
public class MyClassUserInInitializer {
4+
5+
public static final MyClass X = new MyClass();
6+
7+
}

0 commit comments

Comments
 (0)