• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

moosetechnology / VerveineJ / 20030831789

08 Dec 2025 02:05PM UTC coverage: 50.923% (-0.07%) from 50.991%
20030831789

Pull #178

github

web-flow
Merge 6433323b6 into ccd766c89
Pull Request #178: Some cleanings

1898 of 3934 branches covered (48.25%)

Branch coverage included in aggregate %.

90 of 105 new or added lines in 7 files covered. (85.71%)

2 existing lines in 2 files now uncovered.

4255 of 8149 relevant lines covered (52.21%)

2.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.89
/app/src/main/java/fr/inria/verveine/extractor/java/visitors/refvisitors/VisitorInvocRef.java
1
package fr.inria.verveine.extractor.java.visitors.refvisitors;
2

3
import fr.inria.verveine.extractor.java.EntityDictionary;
4
import fr.inria.verveine.extractor.java.VerveineJOptions;
5
import fr.inria.verveine.extractor.java.utils.NodeTypeChecker;
6
import fr.inria.verveine.extractor.java.utils.StubBinding;
7
import fr.inria.verveine.extractor.java.utils.Util;
8
import org.eclipse.jdt.core.dom.Type;
9
import org.eclipse.jdt.core.dom.*;
10
import org.moosetechnology.model.famix.famixjavaentities.*;
11
import org.moosetechnology.model.famix.famixtraits.*;
12

13
import java.io.RandomAccessFile;
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.List;
17

18
public class VisitorInvocRef extends AbstractRefVisitor {
19

20
        /**
21
         * Useful to keep the FamixType created in the specific case of "new
22
         * SomeClass().someMethod()"
23
         */
24
        private final org.moosetechnology.model.famix.famixjavaentities.Type classInstanceCreated = null;
3✔
25

26
        /**
27
         * The source code of the visited AST.
28
         * Used to find back the contents of non-javadoc comments
29
         */
30
        protected RandomAccessFile source;
31

32
        /**
33
         * Whether a variable access is lhs (write) or not
34
         */
35
        protected boolean inAssignmentLHS = false;
3✔
36

37
        public VisitorInvocRef(EntityDictionary dico, VerveineJOptions options) {
38
                super(dico, options);
4✔
39
        }
1✔
40

41
        // VISITOR METHODS
42

43
        public boolean visit(CompilationUnit node) {
44
                //System.err.println("visit(CompilationUnit) ");
45
                visitCompilationUnit(node);
4✔
46
                return super.visit(node);
4✔
47
        }
48

49
        public void endVisit(CompilationUnit node) {
50
                //System.err.println("endVisit(CompilationUnit) ");
51
                endVisitCompilationUnit(node);
3✔
52
        }
1✔
53

54
        /*
55
         * Can only be a class or interface declaration
56
         * Local type: see comment of visit(ClassInstanceCreation node)
57
         */
58
        public boolean visit(TypeDeclaration node) {
59
                //System.err.println("visit(TypeDeclaration) ");
60
                if (visitTypeDeclaration(node) != null) {
4!
61
                        return super.visit(node);
4✔
62
                } else {
63
                        return false;
×
64
                }
65
        }
66

67
        public void endVisit(TypeDeclaration node) {
68
                //System.err.println("endVisit(TypeDeclaration) ");
69
                endVisitTypeDeclaration(node);
3✔
70
        }
1✔
71

72
        /**
73
         * Creates an invocation to the constructor of the class
74
         *
75
         * <pre>
76
         * ClassInstanceCreation ::=
77
         *         [ Expression . ]
78
         *             new [ &lt; Type { , Type } &gt; ]
79
         *             Type ( [ Expression { , Expression } ] )
80
         *             [ AnonymousClassDeclaration ]
81
         * </pre>
82
         */
83
        @SuppressWarnings("unchecked")
84
        public boolean visit(ClassInstanceCreation node) {
85
                //System.err.println("visit(ClassInstanceCreation) ");
86
                String typName;
87
                TType fmx;
88

89
                possiblyAnonymousClassDeclaration(node);
3✔
90

91
                if (node.getAnonymousClassDeclaration() != null) {
3✔
92
                        ITypeBinding bnd = (ITypeBinding) StubBinding.getDeclarationBinding(node.getAnonymousClassDeclaration());
5✔
93
                        fmx = this.dico.getFamixClass(bnd, Util.stringForAnonymousName(getAnonymousSuperTypeName(), context),
12✔
94
                                        /* owner */(ContainerEntity) context.top());
2✔
95
                        typName = fmx.getName();
3✔
96
                } else {
1✔
97
                        Type clazz = node.getType();
3✔
98
                        fmx = referredType(clazz, (ContainerEntity) context.top(), true);
9✔
99

100
                        // create an invocation to the constructor
101
                        if (fmx == null) {
2!
102
                                typName = findTypeName(clazz);
×
103
                        } else {
104
                                typName = fmx.getName();
3✔
105
                        }
106
                }
107

108
                methodInvocation(node.resolveConstructorBinding(), typName, /* receiver */null, /* methOwner */fmx,
9✔
109
                                (List<Expression>) node.arguments());
1✔
110
                Invocation lastInvok = (Invocation) context.getLastInvocation();
5✔
111
                if (options.withAnchors(VerveineJOptions.AnchorOptions.assoc)
8!
112
                                && (lastInvok != null)
113
                                && (lastInvok.getSender() == context.topMethod())
6!
114
                                && (lastInvok.getReceiver() == null)
3!
115
                                && (lastInvok.getSignature().startsWith(typName))) {
4!
116
                        dico.addSourceAnchor(lastInvok, node);
6✔
117
                }
118
                return super.visit(node);
4✔
119
        }
120

121
        public boolean visit(AnonymousClassDeclaration node) {
122
                //System.err.println("visit(AnonymousClassDeclaration) ");
123
                if (visitAnonymousClassDeclaration(node) != null) {
4!
124
                        return super.visit(node);
4✔
125
                } else {
126
                        return false;
×
127
                }
128
        }
129

130
        public void endVisit(AnonymousClassDeclaration node) {
131
                //System.err.println("endVisit(AnonymousClassDeclaration) ");
132
                endVisitAnonymousClassDeclaration(node);
3✔
133
        }
1✔
134

135
        public boolean visit(EnumDeclaration node) {
136
                //System.err.println("visit(EnumDeclaration) ");
137
                if (visitEnumDeclaration(node) != null) {
4!
138
                        return super.visit(node);
4✔
139
                } else {
140
                        return false;
×
141
                }
142
        }
143

144
        public void endVisit(EnumDeclaration node) {
145
                //System.err.println("endVisit(EnumDeclaration) ");
146
                endVisitEnumDeclaration(node);
3✔
147
        }
1✔
148

149
        public boolean visit(AnnotationTypeDeclaration node) {
150
                //System.err.println("visit(AnnotationTypeDeclaration) ");
151
                if (visitAnnotationTypeDeclaration(node) != null) {
4!
152
                        return super.visit(node);
4✔
153
                } else {
154
                        return false;
×
155
                }
156
        }
157

158
        public void endVisit(AnnotationTypeDeclaration node) {
159
                //System.err.println("endVisit(AnnotationTypeDeclaration) ");
160
                endVisitAnnotationTypeDeclaration(node);
3✔
161
        }
1✔
162

163
        public boolean visit(AnnotationTypeMemberDeclaration node) {
164
                //System.err.println("visit(AnnotationTypeMemberDeclaration) ");
165
                if (visitAnnotationTypeMemberDeclaration(node) != null) {
4!
166
                        return super.visit(node);
4✔
167
                } else {
168
                        return false;
×
169
                }
170
        }
171

172
        public void endVisit(AnnotationTypeMemberDeclaration node) {
173
                //System.err.println("endVisit(AnnotationTypeMemberDeclaration) ");
174
                this.context.popAnnotationMember();
4✔
175
                super.endVisit(node);
3✔
176
        }
1✔
177

178
        public boolean visit(MethodDeclaration node) {
179
                //System.err.println("visit(MethodDeclaration): " + node.getName().getIdentifier());
180
                TMethod fmx = visitMethodDeclaration(node);
4✔
181

182
                if (fmx != null) {
2!
183
                        if (node.getBody() != null) {
3✔
184
                                context.setLastInvocation(null);
4✔
185
                        }
186
                        return super.visit(node);
4✔
187
                } else {
188
                        return false;
×
189
                }
190
        }
191

192
        @Override
193
        public void endVisit(MethodDeclaration node) {
194
                //System.err.println("endVisit(MethodDeclaration) ");
195
                endVisitMethodDeclaration(node);
3✔
196
        }
1✔
197

198
        @Override
199
        public boolean visit(Initializer node) {
200
                //System.err.println("visit(Initializer) ");
201
                if (visitInitializer(node) != null) {
4!
202
                        return super.visit(node);
4✔
203
                } else {
204
                        return false;
×
205
                }
206
        }
207

208
        @Override
209
        public void endVisit(Initializer node) {
210
                //System.err.println("endVisit(Initializer) ");
211
                endVisitInitializer(node);
3✔
212
        }
1✔
213

214
        /**
215
         * FieldDeclaration ::=
216
         * [Javadoc] { ExtendedModifier } Type VariableDeclarationFragment
217
         * { , VariableDeclarationFragment } ;
218
         */
219
        @Override
220
        public boolean visit(FieldDeclaration node) {
221
                //System.err.println("visit(FieldDeclaration) ");
222
                hasInitBlock(node); // to recover optional EntityDictionary.INIT_BLOCK_NAME method
4✔
223
                return true;
2✔
224
        }
225

226
        @Override
227
        public void endVisit(FieldDeclaration node) {
228
                //System.err.println("endVisit(FieldDeclaration) ");
229
                endVisitFieldDeclaration(node);
3✔
230
        }
1✔
231

232
        public boolean visit(EnumConstantDeclaration node) {
233
                //System.err.println("visit(EnumConstantDeclaration) ");
234
                return visitEnumConstantDeclaration(node);
4✔
235
        }
236

237
        public void endVisit(EnumConstantDeclaration node) {
238
                //.err.println("endVisit(EnumConstantDeclaration) ");
239
                endVisitEnumConstantDeclaration(node);
3✔
240
        }
1✔
241

242
        @SuppressWarnings("unchecked")
243
        public boolean visit(MethodInvocation node) {
244
                //System.err.println("visit(MethodInvocation): " + node.getName().getFullyQualifiedName());
245
                Expression callingExpr = node.getExpression();
3✔
246
                TNamedEntity receiver = getReceiver(callingExpr);
4✔
247

248
                IMethodBinding bnd = node.resolveMethodBinding();
3✔
249

250
                String calledName = node.getName().getFullyQualifiedName();
4✔
251

252
                if (bnd == null) {
2✔
253
                        methodInvocation(bnd, calledName, receiver, getInvokedMethodOwner(callingExpr, receiver), node.arguments());
13✔
254
                } else {
255
                        methodInvocation(bnd, calledName, receiver, /* owner */null, node.arguments());
9✔
256
                }
257

258
                // TODO could be TInvocation but it does not extends THassignature and we need
259
                // it a bit latter (see 'lastInvok.getSignature()')
260
                Invocation lastInvocation = (Invocation) context.getLastInvocation();
5✔
261
                if (options.withAnchors(VerveineJOptions.AnchorOptions.assoc)
8!
262
                                // check that lastInvocation correspond to current one
263
                                && (lastInvocation != null) && (lastInvocation.getSender() == context.topMethod())
6!
264
                                && (lastInvocation.getReceiver() == receiver)
4!
265
                                && (lastInvocation.getSignature().startsWith(calledName))) {
4!
266
                        dico.addSourceAnchor(lastInvocation, node);
6✔
267
                }
268

269
                return super.visit(node);
4✔
270
        }
271

272
        @SuppressWarnings("unchecked")
273
        public boolean visit(SuperMethodInvocation node) {
274
                //System.err.println("visit(SuperMethodInvocation) ");
275
                TNamedEntity receiver = this.dico.ensureFamixImplicitVariable(
7✔
276
                                EntityDictionary.SUPER_NAME,
277
                                this.context.topType(),
3✔
278
                                context.topMethod());
1✔
279
                IMethodBinding bnd = node.resolveMethodBinding();
3✔
280
                String calledName = node.getName().getFullyQualifiedName();
4✔
281

282
                if (bnd == null) {
2✔
283
                        TType superClass = (TType) ((TWithInheritances) this.context.topType()).getSuperInheritances().iterator().next().getSuperclass();
11✔
284
                        methodInvocation(bnd, calledName, receiver, superClass, node.arguments());
9✔
285
                } else {
1✔
286
                        methodInvocation(bnd, calledName, receiver, /* owner */null, node.arguments());
9✔
287
                }
288

289
                Invocation lastInvok = (Invocation) context.getLastInvocation();
5✔
290
                if (options.withAnchors(VerveineJOptions.AnchorOptions.assoc)
5!
291
                                // check that lastInvocation correspond to current one
292
                                && (lastInvok != null) && (lastInvok.getSender() == context.topMethod())
×
293
                                && (lastInvok.getReceiver() == receiver) && (lastInvok.getSignature().startsWith(calledName))) {
×
294
                        dico.addSourceAnchor(lastInvok, node);
×
295
                }
296

297
                return super.visit(node);
4✔
298
        }
299

300
        public boolean visit(ConstructorInvocation node) {
301
                //System.err.println("visit(ConstructorInvocation) ");
302
                // ConstructorInvocation (i.e. 'this(...)' ) happen in constructor, so the name
303
                // is the same
304

305
                int modifiers = (node.resolveConstructorBinding() != null) ? node.resolveConstructorBinding().getModifiers()
7!
306
                                : EntityDictionary.UNKNOWN_MODIFIERS;
1✔
307

308
                String name = context.topMethod().getName();
5✔
309
                TMethod invoked = dico.ensureFamixMethod(node.resolveConstructorBinding(), name,
11✔
310
                                /* paramTypes */null, /* retType */null, (TWithMethods) /* owner */context.topType(), modifiers);
3✔
311
                // constructor don't have return type so no need to create a reference from this
312
                // class to the "declared return type" class when classSummary is TRUE
313
                // also no parameters specified here, so no references to create for them either
314

315
                String signature = node.toString();
3✔
316
                if (signature.endsWith("\n")) {
4!
317
                        signature = signature.substring(0, signature.length() - 1);
8✔
318
                }
319
                if (signature.endsWith(";")) {
4!
320
                        signature = signature.substring(0, signature.length() - 1);
8✔
321
                }
322
                ImplicitVariable receiver = dico.ensureFamixImplicitVariable(
7✔
323
                                EntityDictionary.THIS_NAME,
324
                                context.topType(),
3✔
325
                                context.topMethod());
1✔
326

327
                TInvocation invok = dico.addFamixInvocation(context.topMethod(), invoked, receiver, signature,
12✔
328
                                context.getLastInvocation(), node.resolveConstructorBinding());
3✔
329
                context.setLastInvocation(invok);
4✔
330

331
                if (options.withAnchors(VerveineJOptions.AnchorOptions.assoc) && (invok != null)) {
5!
332
                        dico.addSourceAnchor(invok, node);
×
333
                }
334

335
                return super.visit(node);
4✔
336
        }
337

338
        public boolean visit(SuperConstructorInvocation node) {
339
                //System.err.println("visit(SuperConstructorInvocation) ");
340
                // ConstructorInvocation (i.e. 'super(...)' ) happen in constructor, so the name
341
                // is that of the superclass
342
                // Class superC = superClass();
343
                Method invoked = null;
2✔
344

345
                // if (superC != null) {
346
                // invoked = this.dico.ensureFamixMethod(node.resolveConstructorBinding(),
347
                // superC.getName(), /*paramsType*/(Collection<String>) null, superC,
348
                // EntityDictionary.UNKNOWN_MODIFIERS, /*persistIt*/!classSummary);
349
                // }
350
                // else {
351
                invoked = this.dico.ensureFamixMethod(node.resolveConstructorBinding());
6✔
352
                // }
353

354
                if (invoked != null) {
2✔
355
                        String signature = node.toString();
3✔
356
                        if (signature.endsWith("\n")) {
4!
357
                                signature = signature.substring(0, signature.length() - 1);
8✔
358
                        }
359
                        if (signature.endsWith(";")) {
4!
360
                                signature = signature.substring(0, signature.length() - 1);
8✔
361
                        }
362
                        ImplicitVariable receiver = dico.ensureFamixImplicitVariable(
7✔
363
                                        EntityDictionary.SUPER_NAME,
364
                                        context.topType(),
3✔
365
                                        context.topMethod());
1✔
366
                        Invocation invok = dico.addFamixInvocation(context.topMethod(), invoked, receiver, signature,
12✔
367
                                        context.getLastInvocation(), node.resolveConstructorBinding());
3✔
368
                        context.setLastInvocation(invok);
4✔
369
                        if (options.withAnchors(VerveineJOptions.AnchorOptions.assoc)) {
5!
370
                                dico.addSourceAnchor(invok, node);
×
371
                        }
372
                }
373

374
                return super.visit(node);
4✔
375
        }
376

377
        // UTILITY METHODS
378

379
        /**
380
         * Handles an invocation of a method by creating the corresponding Famix Entity.
381
         *
382
         * @param calledBnd  -- a binding for the method invoked
383
         * @param calledName of the method invoked
384
         * @param receiver   of the call, i.e. the object to which the message is sent
385
         * @param methOwner  -- owner of the method invoked. Might be a subtype of the
386
         *                   receiver's type
387
         * @param l_args     -- list of the method's parameters
388
         *                   TODO Why are Invocations, Accesses and References not
389
         *                   created through a method in JavaDictionnary ?
390
         */
391
        private Invocation methodInvocation(IMethodBinding calledBnd, String calledName, TNamedEntity receiver,
392
                        TType methOwner, Collection<Expression> l_args) {
393
                //System.err.println("methodInvocation(): " + calledName);
394

395
                TMethod sender = this.context.topMethod();
4✔
396
                TMethod invoked;
397
                Invocation invok;
398

399
                // If the method is parametric, get the generic method.
400
                IMethodBinding actualCalledMethodBnd = (calledBnd == null ? null : calledBnd.getMethodDeclaration());
7✔
401

402
                if ((receiver != null) && (receiver.getName().equals("class")) && (actualCalledMethodBnd != null)
10!
403
                                && (actualCalledMethodBnd.getDeclaringClass() == null)) {
2!
404
                        /* bug with JDT apparently has to do with invoking a method of a meta-class */
405
                        // humm ... we do not create the FamixInvocation ? Seems like a bug ...
406
                        return null;
×
407
                } else if ((actualCalledMethodBnd != null) && (actualCalledMethodBnd.isAnnotationMember())) {
5✔
408
                        // if this is not an AnnotationType member, it is similar to creating a
409
                        // FamixAttribute access
410
                        return null;
2✔
411
                } else if (sender == null) {
2!
412
                        return null;
×
413
                }
414

415
                Collection<String> unkwnArgs = new ArrayList<String>();
4✔
416
                if (l_args != null) {
2!
417
                        for (@SuppressWarnings("unused")
418
                        Expression a : l_args) {
10✔
419
                                unkwnArgs.add("?");
4✔
420
                        }
1✔
421
                }
422

423
                int modifiers = (actualCalledMethodBnd != null) ? actualCalledMethodBnd.getModifiers() : EntityDictionary.UNKNOWN_MODIFIERS;
7✔
424

425
                if ((receiver != null) && (receiver instanceof TStructuralEntity)) {
5✔
426
                        invoked = this.dico.ensureFamixMethod(actualCalledMethodBnd, calledName, unkwnArgs, /* retType */null,
12✔
427
                                        (TWithMethods) methOwner, modifiers);
428
                } else {
429
                        TType owner;
430

431
                        if (receiver != null)
2✔
432
                                owner = (TType) receiver;
4✔
433
                        else {
434
                                if (actualCalledMethodBnd != null && actualCalledMethodBnd.getDeclaringClass().isParameterizedType()) {
6!
435
                                        owner = this.dico.ensureFamixType(actualCalledMethodBnd.getDeclaringClass().getErasure());
×
436
                                } else {
437
                                        owner = methOwner;
2✔
438
                                }
439
                        }
440

441
                        // static method called on the class (or null receiver)
442
                        invoked = this.dico.ensureFamixMethod(actualCalledMethodBnd, calledName, unkwnArgs, /* retType */null,
11✔
443
                                        (TWithMethods) /* owner */owner, modifiers);
444
                }
445

446
                String signature = "";
2✔
447
                if (actualCalledMethodBnd != null && actualCalledMethodBnd.isParameterizedMethod()) {
5!
448
                        signature += "<";
×
449
                        int size = ((ParametricMethod) invoked).getTypeParameters().size();
×
450
                        int i = 0;
×
451
                        for (TTypeParameter param : ((ParametricMethod) invoked).getTypeParameters()) {
×
452
                                signature += ((TNamedEntity) param).getName() + (i < size - 1 ? "," : "");
×
453
                                i++;
×
454
                        }
×
455
                        signature += "> ";
×
456
                }
457
                signature += calledName + "(";
4✔
458

459
                if (l_args != null) {
2!
460
                        boolean first = true;
2✔
461
                        for (Expression a : l_args) {
10✔
462
                                if (first) {
2✔
463
                                        signature += a.toString();
5✔
464
                                        first = false;
3✔
465
                                } else {
466
                                        signature += "," + a.toString();
5✔
467
                                }
468
                        }
1✔
469
                }
470
                signature += ")";
3✔
471
                
472
                invok = dico.addFamixInvocation(sender, invoked, (TInvocationsReceiver) receiver, signature,
11✔
473
                                context.getLastInvocation(), calledBnd);
2✔
474
                // TODO add FileAnchor to Invocation
475
                context.setLastInvocation(invok);
4✔
476

477
                return invok;
2✔
478

479
        }
480

481
        /**
482
         * Finds and/or create the Famix Entity receiving a message
483
         * Can be: ImplicitVariable (this, super), GlobalVariable, LocalVariable,
484
         * Attribute, UnknownVariable, Parameter
485
         * 
486
         * @param expr -- the Java expression describing the receiver
487
         * @return the Famix Entity or null if could not find it
488
         */
489
        @SuppressWarnings("static-access")
490
        private TNamedEntity getReceiver(Expression expr) {
491
                // msg(), same as ThisExpression
492
                if (expr == null) {
2✔
493
                        return this.dico.ensureFamixImplicitVariable(dico.THIS_NAME, this.context.topType(), context.topMethod());
14✔
494
                }
495

496
                // array[i].msg()
497
                if (NodeTypeChecker.isArrayAccess(expr)) {
3!
498
                        return getReceiver(((ArrayAccess) expr).getArray());
×
499
                }
500

501
                // new type[].msg()
502
                if (NodeTypeChecker.isArrayCreation(expr)) {
3!
UNCOV
503
                        return null;
×
504
                }
505

506
                // (variable = value).msg()
507
                if (NodeTypeChecker.isAssignment(expr)) {
3!
508
                        return getReceiver(((Assignment) expr).getLeftHandSide());
×
509
                }
510

511
                // ((type)expr).msg()
512
                if (NodeTypeChecker.isCastExpression(expr)) {
3!
513
                        return getReceiver(((CastExpression) expr).getExpression());
×
514
                }
515

516
                // new Class().msg()
517
                if (NodeTypeChecker.isClassInstanceCreation(expr)) {
3✔
518
                        return null;
2✔
519
                }
520

521
                // (cond-expr ? then-expr : else-expr).msg()
522
                if (NodeTypeChecker.isConditionalExpression(expr)) {
3!
523
                        // can be one or the other (then-expr/else-expr) so we choose one
524
                        TNamedEntity ret = getReceiver(((ConditionalExpression) expr).getThenExpression());
×
525
                        if (ret == null) {
×
526
                                // can as well try the other
527
                                ret = getReceiver(((ConditionalExpression) expr).getElseExpression());
×
528
                        }
529
                        return ret;
×
530
                }
531

532
                // field.msg()
533
                if (NodeTypeChecker.isFieldAccess(expr)) {
3✔
534
                        IVariableBinding bnd = ((FieldAccess) expr).resolveFieldBinding();
4✔
535
                        return dico.getEntityByKey(bnd);
5✔
536
                }
537

538
                // (left-expr oper right-expr).msg()
539
                if (NodeTypeChecker.isInfixExpression(expr)) {
3!
540
                        // anonymous receiver
541
                        return null;
×
542
                }
543

544
                // msg1().msg()
545
                if (NodeTypeChecker.isMethodInvocation(expr)) {
3✔
546
                        return null;
2✔
547
                }
548

549
                // name.msg()
550
                if (NodeTypeChecker.isName(expr)) {
3✔
551
                        // can be a class or a variable name
552
                        IBinding bnd = ((Name) expr).resolveBinding();
4✔
553
                        if (bnd == null) {
2✔
554
                                return null;
2✔
555
                        }
556
                        TNamedEntity ret = null;
2✔
557
                        if (bnd.getKind() == IBinding.TYPE) {
4✔
558
                                // msg() is a static method of Name so name should be a class, except if its an
559
                                // Enum
560
                                ret = dico.getEntityByKey(bnd);
5✔
561
                        }
562

563
                        if (bnd.getKind() == IBinding.VARIABLE) {
4✔
564
                                // a bit convoluted, but sometimes 'bnd' is not directly the binding of the
565
                                // variable's declaration from which the Famix entity was created
566
                                return dico.getEntityByKey(((IVariableBinding) bnd).getVariableDeclaration());
7✔
567
                        }
568

569
                        return ret;
2✔
570
                }
571

572
                // (expr).msg()
573
                if (NodeTypeChecker.isParenthesizedExpression(expr)) {
3!
574
                        return getReceiver(((ParenthesizedExpression) expr).getExpression());
×
575
                }
576

577
                // "string".msg()
578
                if (NodeTypeChecker.isStringLiteral(expr)) {
3✔
579
                        return null;
2✔
580
                }
581

582
                // <text block>.msg()
583
                // <text block> are created with triple quotes to allow defining multi-line string literals
584
                // they are reported as NullLiteral in JDT and there does not seem to be a better way to test them
585
                if (expr instanceof NullLiteral) {
3!
586
                        return null;
×
587
                }
588

589
                // super.field.msg()
590
                if (NodeTypeChecker.isSuperFieldAccess(expr)) {
3!
NEW
591
                        return dico.getEntityByKey(((SuperFieldAccess) expr).resolveFieldBinding());
×
592
                }
593

594
                // super.msg1().msg()
595
                if (NodeTypeChecker.isSuperMethodInvocation(expr)) {
3!
596
                        return null;
×
597
                }
598

599
                // this.msg()
600
                if (NodeTypeChecker.isThisExpression(expr)) {
3✔
601
                        return this.dico.ensureFamixImplicitVariable(EntityDictionary.THIS_NAME, context.topType(),
10✔
602
                                        context.topMethod());
1✔
603
                }
604

605
                // type.class.msg()
606
                if (NodeTypeChecker.isTypeLiteral(expr)) {
3!
607
                        // similar to a field access
608
                        return dico.getFamixAttribute(null, "class", dico.ensureFamixMetaClass(null));
10✔
609
                }
610

611
                // ... OTHER POSSIBLE EXPRESSIONS ?
612
                System.err.println("WARNING: Unexpected receiver expression: " + expr.getClass().getName()
×
613
                                + " (method called is" + expr.getClass().getName() + ".aMethod(...))");
×
614
                return null;
×
615
        }
616

617
        /**
618
         * Tries its best to find the type of a receiver without using the bindings.
619
         * Most of the time, the type is that of the receiver, but not always (if there
620
         * is a cast or if receiver is null)
621
         *
622
         * @param expr     -- the Java expression describing the receiver
623
         * @param receiver -- the FAMIX Entity describing the receiver
624
         * @return the Famix Entity or null if could not find it
625
         */
626
        private TType getInvokedMethodOwner(Expression expr, TNamedEntity receiver) {
627
                // ((type)expr).msg()
628
                if (NodeTypeChecker.isCastExpression(expr)) {
3!
629
                        Type tcast = ((CastExpression) expr).getType();
×
630
                        return referredType(tcast, (ContainerEntity) this.context.top(), true);
×
631
                }
632

633
                // new Class().msg()
634
                else if (NodeTypeChecker.isClassInstanceCreation(expr)) {
3!
635
                        return this.classInstanceCreated;
×
636
                }
637

638
                // msg1().msg()
639
                else if (NodeTypeChecker.isMethodInvocation(expr)) {
3✔
640
                        IMethodBinding callerBnd = ((MethodInvocation) expr).resolveMethodBinding();
4✔
641
                        if (callerBnd != null) {
2!
642
                                return referredType(callerBnd.getReturnType(), (ContainerEntity) this.context.top(), true);
10✔
643
                        } else {
644
                                return null;
×
645
                        }
646
                }
647

648
                // (expr).msg()
649
                else if (NodeTypeChecker.isParenthesizedExpression(expr)) {
3!
650
                        return getInvokedMethodOwner(((ParenthesizedExpression) expr).getExpression(), receiver);
×
651
                }
652

653
                // "string".msg()
654
                else if (NodeTypeChecker.isStringLiteral(expr)) {
3!
655
                        return dico.ensureFamixType(/* binding */null, "String", dico.ensureFamixPackageJavaLang(null),
×
656
                                        /* context */null, EntityDictionary.UNKNOWN_MODIFIERS); // creating FamixClass java.lang.String
657
                }
658

659
                // super.msg1().msg()
660
                else if (NodeTypeChecker.isSuperMethodInvocation(expr)) {
3!
661
                        IMethodBinding superBnd = ((SuperMethodInvocation) expr).resolveMethodBinding();
×
662
                        if (superBnd != null) {
×
663
                                return this.referredType(superBnd.getReturnType(), (ContainerEntity) context.topType(), true);
×
664
                        } else {
665
                                return null;
×
666
                        }
667
                }
668

669
                // everything else, see the receiver
670
                else {
671
                        if (receiver == null) {
2✔
672
                                return null;
2✔
673
                        }
674
                        else if (receiver instanceof TTypedEntity) {
3!
675
                                return ((TTypedEntity) receiver).getDeclaredType();
4✔
676
                        } else if (receiver instanceof org.moosetechnology.model.famix.famixjavaentities.Type) {
×
677
                                return (org.moosetechnology.model.famix.famixjavaentities.Type) receiver;
×
678
                        }
679
                        // ... what else ?
680
                        else {
681
                                return null;
×
682
                        }
683
                }
684
        }
685

686
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc