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

moosetechnology / VerveineJ / 15191557690

22 May 2025 04:10PM UTC coverage: 50.616% (+0.6%) from 49.972%
15191557690

push

github

web-flow
Merge pull request #127 from moosetechnology/new-generics-implementation

New generics implementation

1884 of 3956 branches covered (47.62%)

Branch coverage included in aggregate %.

513 of 1119 new or added lines in 53 files covered. (45.84%)

53 existing lines in 10 files now uncovered.

4277 of 8216 relevant lines covered (52.06%)

2.08 hits per line

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

72.1
/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
                visitCompilationUnit(node);
4✔
45
                return super.visit(node);
4✔
46
        }
47

48
        public void endVisit(CompilationUnit node) {
49
                endVisitCompilationUnit(node);
3✔
50
        }
1✔
51

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

64
        public void endVisit(TypeDeclaration node) {
65
                endVisitTypeDeclaration(node);
3✔
66
        }
1✔
67

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

84
                possiblyAnonymousClassDeclaration(node);
3✔
85

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

95
                        // create an invocation to the constructor
96
                        if (fmx == null) {
2!
97
                                typName = findTypeName(clazz);
×
98
                        } else {
99
                                typName = fmx.getName();
3✔
100
                        }
101
                }
102

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

116
        public boolean visit(AnonymousClassDeclaration node) {
117
                if (visitAnonymousClassDeclaration(node) != null) {
4!
118
                        return super.visit(node);
4✔
119
                } else {
UNCOV
120
                        return false;
×
121
                }
122
        }
123

124
        public void endVisit(AnonymousClassDeclaration node) {
125
                endVisitAnonymousClassDeclaration(node);
3✔
126
        }
1✔
127

128
        public boolean visit(EnumDeclaration node) {
129
                if (visitEnumDeclaration(node) != null) {
4!
130
                        return super.visit(node);
4✔
131
                } else {
UNCOV
132
                        return false;
×
133
                }
134
        }
135

136
        public void endVisit(EnumDeclaration node) {
137
                endVisitEnumDeclaration(node);
3✔
138
        }
1✔
139

140
        public boolean visit(AnnotationTypeDeclaration node) {
141
                if (visitAnnotationTypeDeclaration(node) != null) {
4!
142
                        return super.visit(node);
4✔
143
                } else {
UNCOV
144
                        return false;
×
145
                }
146
        }
147

148
        public void endVisit(AnnotationTypeDeclaration node) {
149
                endVisitAnnotationTypeDeclaration(node);
3✔
150
        }
1✔
151

152
        public boolean visit(AnnotationTypeMemberDeclaration node) {
153
                if (visitAnnotationTypeMemberDeclaration(node) != null) {
4!
154
                        return super.visit(node);
4✔
155
                } else {
156
                        return false;
×
157
                }
158
        }
159

160
        public void endVisit(AnnotationTypeMemberDeclaration node) {
161
                this.context.popAnnotationMember();
4✔
162
                super.endVisit(node);
3✔
163
        }
1✔
164

165
        public boolean visit(MethodDeclaration node) {
166
                TMethod fmx = visitMethodDeclaration(node);
4✔
167

168
                if (fmx != null) {
2!
169
                        if (node.getBody() != null) {
3✔
170
                                context.setLastInvocation(null);
4✔
171
                        }
172
                        return super.visit(node);
4✔
173
                } else {
174
                        return false;
×
175
                }
176
        }
177

178
        @Override
179
        public void endVisit(MethodDeclaration node) {
180
                endVisitMethodDeclaration(node);
3✔
181
        }
1✔
182

183
        @Override
184
        public boolean visit(Initializer node) {
185
                if (visitInitializer(node) != null) {
4!
186
                        return super.visit(node);
4✔
187
                } else {
UNCOV
188
                        return false;
×
189
                }
190
        }
191

192
        @Override
193
        public void endVisit(Initializer node) {
194
                endVisitInitializer(node);
3✔
195
        }
1✔
196

197
        /**
198
         * FieldDeclaration ::=
199
         * [Javadoc] { ExtendedModifier } Type VariableDeclarationFragment
200
         * { , VariableDeclarationFragment } ;
201
         */
202
        @Override
203
        public boolean visit(FieldDeclaration node) {
204
                hasInitBlock(node); // to recover optional EntityDictionary.INIT_BLOCK_NAME method
4✔
205
                return true;
2✔
206
        }
207

208
        @Override
209
        public void endVisit(FieldDeclaration node) {
210
                endVisitFieldDeclaration(node);
3✔
211
        }
1✔
212

213
        public boolean visit(EnumConstantDeclaration node) {
214
                return visitEnumConstantDeclaration(node);
4✔
215
        }
216

217
        public void endVisit(EnumConstantDeclaration node) {
218
                endVisitEnumConstantDeclaration(node);
3✔
219
        }
1✔
220

221
        @SuppressWarnings("unchecked")
222
        public boolean visit(MethodInvocation node) {
223
                Expression callingExpr = node.getExpression();
3✔
224
                TNamedEntity receiver = getReceiver(callingExpr);
4✔
225

226
                IMethodBinding bnd = node.resolveMethodBinding();
3✔
227

228
                String calledName = node.getName().getFullyQualifiedName();
4✔
229

230
                if (bnd == null) {
2✔
231
                        methodInvocation(bnd, calledName, receiver, getInvokedMethodOwner(callingExpr, receiver), node.arguments());
13✔
232
                } else {
233
                        methodInvocation(bnd, calledName, receiver, /* owner */null, node.arguments());
9✔
234
                }
235

236
                // TODO could be TInvocation but it does not extends THassignature and we need
237
                // it a bit latter (see 'lastInvok.getSignature()')
238
                Invocation lastInvocation = (Invocation) context.getLastInvocation();
5✔
239
                if (options.withAnchors(VerveineJOptions.AnchorOptions.assoc)
8!
240
                                // check that lastInvocation correspond to current one
241
                                && (lastInvocation != null) && (lastInvocation.getSender() == context.topMethod())
6!
242
                                && (lastInvocation.getReceiver() == receiver)
4!
243
                                && (lastInvocation.getSignature().startsWith(calledName))) {
4!
244
                        dico.addSourceAnchor(lastInvocation, node);
6✔
245
                }
246

247
                return super.visit(node);
4✔
248
        }
249

250
        @SuppressWarnings("unchecked")
251
        public boolean visit(SuperMethodInvocation node) {
252
                // ConstructorInvocation (i.e. 'this(...)' ) happen in constructor, so the name
253
                // is the same
254
                TNamedEntity receiver = this.dico.ensureFamixImplicitVariable(
7✔
255
                                EntityDictionary.SUPER_NAME,
256
                                this.context.topType(),
3✔
257
                                context.topMethod());
1✔
258
                IMethodBinding bnd = node.resolveMethodBinding();
3✔
259
                String calledName = node.getName().getFullyQualifiedName();
4✔
260

261
                if (bnd == null) {
2✔
262
                        TType superClass = (TType) ((TWithInheritances) this.context.topType()).getSuperInheritances().iterator()
6✔
NEW
263
                                        .next();
×
UNCOV
264
                        methodInvocation(bnd, calledName, receiver, superClass, node.arguments());
×
UNCOV
265
                } else {
×
266
                        methodInvocation(bnd, calledName, receiver, /* owner */null, node.arguments());
9✔
267
                }
268

269
                Invocation lastInvok = (Invocation) context.getLastInvocation();
5✔
270
                if (options.withAnchors(VerveineJOptions.AnchorOptions.assoc)
5!
271
                                // check that lastInvocation correspond to current one
272
                                && (lastInvok != null) && (lastInvok.getSender() == context.topMethod())
×
273
                                && (lastInvok.getReceiver() == receiver) && (lastInvok.getSignature().startsWith(calledName))) {
×
274
                        dico.addSourceAnchor(lastInvok, node);
×
275
                }
276

277
                return super.visit(node);
4✔
278
        }
279

280
        public boolean visit(ConstructorInvocation node) {
281
                // ConstructorInvocation (i.e. 'this(...)' ) happen in constructor, so the name
282
                // is the same
283

284
                int modifiers = (node.resolveConstructorBinding() != null) ? node.resolveConstructorBinding().getModifiers()
7!
285
                                : EntityDictionary.UNKNOWN_MODIFIERS;
1✔
286

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

294
                String signature = node.toString();
3✔
295
                if (signature.endsWith("\n")) {
4!
296
                        signature = signature.substring(0, signature.length() - 1);
8✔
297
                }
298
                if (signature.endsWith(";")) {
4!
299
                        signature = signature.substring(0, signature.length() - 1);
8✔
300
                }
301
                ImplicitVariable receiver = dico.ensureFamixImplicitVariable(
7✔
302
                                EntityDictionary.SELF_NAME,
303
                                context.topType(),
3✔
304
                                context.topMethod());
1✔
305

306
                TInvocation invok = dico.addFamixInvocation(context.topMethod(), invoked, receiver, signature,
12✔
307
                                context.getLastInvocation(), node.resolveConstructorBinding());
3✔
308
                context.setLastInvocation(invok);
4✔
309

310
                if (options.withAnchors(VerveineJOptions.AnchorOptions.assoc) && (invok != null)) {
5!
UNCOV
311
                        dico.addSourceAnchor(invok, node);
×
312
                }
313

314
                return super.visit(node);
4✔
315
        }
316

317
        public boolean visit(SuperConstructorInvocation node) {
318
                // ConstructorInvocation (i.e. 'super(...)' ) happen in constructor, so the name
319
                // is that of the superclass
320
                // Class superC = superClass();
321
                Method invoked = null;
2✔
322

323
                // if (superC != null) {
324
                // invoked = this.dico.ensureFamixMethod(node.resolveConstructorBinding(),
325
                // superC.getName(), /*paramsType*/(Collection<String>) null, superC,
326
                // EntityDictionary.UNKNOWN_MODIFIERS, /*persistIt*/!classSummary);
327
                // }
328
                // else {
329
                invoked = this.dico.ensureFamixMethod(node.resolveConstructorBinding());
6✔
330
                // }
331

332
                if (invoked != null) {
2✔
333
                        String signature = node.toString();
3✔
334
                        if (signature.endsWith("\n")) {
4!
335
                                signature = signature.substring(0, signature.length() - 1);
8✔
336
                        }
337
                        if (signature.endsWith(";")) {
4!
338
                                signature = signature.substring(0, signature.length() - 1);
8✔
339
                        }
340
                        ImplicitVariable receiver = dico.ensureFamixImplicitVariable(
7✔
341
                                        EntityDictionary.SUPER_NAME,
342
                                        context.topType(),
3✔
343
                                        context.topMethod());
1✔
344
                        Invocation invok = dico.addFamixInvocation(context.topMethod(), invoked, receiver, signature,
12✔
345
                                        context.getLastInvocation(), node.resolveConstructorBinding());
3✔
346
                        context.setLastInvocation(invok);
4✔
347
                        if (options.withAnchors(VerveineJOptions.AnchorOptions.assoc)) {
5!
348
                                dico.addSourceAnchor(invok, node);
×
349
                        }
350
                }
351

352
                return super.visit(node);
4✔
353
        }
354

355
        // UTILITY METHODS
356

357
        /**
358
         * Handles an invocation of a method by creating the corresponding Famix Entity.
359
         *
360
         * @param calledBnd  -- a binding for the method invoked
361
         * @param calledName of the method invoked
362
         * @param receiver   of the call, i.e. the object to which the message is sent
363
         * @param methOwner  -- owner of the method invoked. Might be a subtype of the
364
         *                   receiver's type
365
         * @param l_args     -- list of the method's parameters
366
         *                   TODO Why are Invocations, Accesses and References not
367
         *                   created through a method in JavaDictionnary ?
368
         */
369
        private Invocation methodInvocation(IMethodBinding calledBnd, String calledName, TNamedEntity receiver,
370
                        TType methOwner, Collection<Expression> l_args) {
371

372
                TMethod sender = this.context.topMethod();
4✔
373
                TMethod invoked;
374
                Invocation invok;
375

376
                // If the method is parametric, get the generic method.
377
                IMethodBinding actualCalledMethodBnd = (calledBnd == null ? null : calledBnd.getMethodDeclaration());
7✔
378

379
                if ((receiver != null) && (receiver.getName().equals("class")) && (actualCalledMethodBnd != null)
10!
380
                                && (actualCalledMethodBnd.getDeclaringClass() == null)) {
2!
381
                        /* bug with JDT apparently has to do with invoking a method of a meta-class */
382
                        // humm ... we do not create the FamixInvocation ? Seems like a bug ...
NEW
383
                        return null;
×
384
                } else if ((actualCalledMethodBnd != null) && (actualCalledMethodBnd.isAnnotationMember())) {
5✔
385
                        // if this is not an AnnotationType member, it is similar to creating a
386
                        // FamixAttribute access
387
                        return null;
2✔
388
                } else if (sender == null) {
2!
NEW
389
                        return null;
×
390
                }
391

392
                Collection<String> unkwnArgs = new ArrayList<String>();
4✔
393
                if (l_args != null) {
2!
394
                        for (@SuppressWarnings("unused")
395
                        Expression a : l_args) {
10✔
396
                                unkwnArgs.add("?");
4✔
397
                        }
1✔
398
                }
399

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

402
                if ((receiver != null) && (receiver instanceof TStructuralEntity)) {
5✔
403
                        invoked = this.dico.ensureFamixMethod(actualCalledMethodBnd, calledName, unkwnArgs, /* retType */null,
12✔
404
                                        (TWithMethods) methOwner, modifiers);
405
                } else {
406
                        TType owner;
407

408
                        if (receiver != null)
2✔
409
                                owner = (TType) receiver;
4✔
410
                        else {
411
                                if (actualCalledMethodBnd != null && actualCalledMethodBnd.getDeclaringClass().isParameterizedType()) {
6!
NEW
412
                                        owner = this.dico.ensureFamixType(actualCalledMethodBnd.getDeclaringClass().getErasure());
×
413
                                } else {
414
                                        owner = methOwner;
2✔
415
                                }
416
                        }
417

418
                        // static method called on the class (or null receiver)
419
                        invoked = this.dico.ensureFamixMethod(actualCalledMethodBnd, calledName, unkwnArgs, /* retType */null,
11✔
420
                                        (TWithMethods) /* owner */owner, modifiers);
421
                }
422

423
                String signature = "";
2✔
424
                if (actualCalledMethodBnd != null && actualCalledMethodBnd.isParameterizedMethod()) {
5!
NEW
425
                        signature += "<";
×
NEW
426
                        int size = ((ParametricMethod) invoked).getTypeParameters().size();
×
NEW
427
                        int i = 0;
×
NEW
428
                        for (TTypeParameter param : ((ParametricMethod) invoked).getTypeParameters()) {
×
NEW
429
                                signature += ((TNamedEntity) param).getName() + (i < size - 1 ? "," : "");
×
NEW
430
                                i++;
×
NEW
431
                        }
×
NEW
432
                        signature += "> ";
×
433
                }
434
                signature += calledName + "(";
4✔
435

436
                if (l_args != null) {
2!
437
                        boolean first = true;
2✔
438
                        for (Expression a : l_args) {
10✔
439
                                if (first) {
2✔
440
                                        signature += a.toString();
5✔
441
                                        first = false;
3✔
442
                                } else {
443
                                        signature += "," + a.toString();
5✔
444
                                }
445
                        }
1✔
446
                }
447
                signature += ")";
3✔
448
                
449
                invok = dico.addFamixInvocation(sender, invoked, (TInvocationsReceiver) receiver, signature,
11✔
450
                                context.getLastInvocation(), calledBnd);
2✔
451
                // TODO add FileAnchor to Invocation
452
                context.setLastInvocation(invok);
4✔
453

454
                return invok;
2✔
455

456
        }
457

458
        /**
459
         * Finds and/or create the Famix Entity receiving a message
460
         * Can be: ImplicitVariable (this, super), GlobalVariable, LocalVariable,
461
         * Attribute, UnknownVariable, Parameter
462
         * 
463
         * @param expr -- the Java expression describing the receiver
464
         * @return the Famix Entity or null if could not find it
465
         */
466
        @SuppressWarnings("static-access")
467
        private TNamedEntity getReceiver(Expression expr) {
468
                // msg(), same as ThisExpression
469
                if (expr == null) {
2✔
470
                        return this.dico.ensureFamixImplicitVariable(dico.SELF_NAME, this.context.topType(), context.topMethod());
14✔
471
                }
472

473
                // array[i].msg()
474
                if (NodeTypeChecker.isArrayAccess(expr)) {
3!
475
                        return getReceiver(((ArrayAccess) expr).getArray());
×
476
                }
477

478
                // new type[].msg()
479
                if (NodeTypeChecker.isArrayCreation(expr)) {
3!
480
                        // System.err.println("WARNING: Ignored receiver expression in method call:
481
                        // ArrayCreation");
UNCOV
482
                        return null;
×
483
                }
484

485
                // (variable = value).msg()
486
                if (NodeTypeChecker.isAssignment(expr)) {
3!
487
                        return getReceiver(((Assignment) expr).getLeftHandSide());
×
488
                }
489

490
                // ((type)expr).msg()
491
                if (NodeTypeChecker.isCastExpression(expr)) {
3!
492
                        return getReceiver(((CastExpression) expr).getExpression());
×
493
                }
494

495
                // new Class().msg()
496
                if (NodeTypeChecker.isClassInstanceCreation(expr)) {
3✔
497
                        return null;
2✔
498
                }
499

500
                // (cond-expr ? then-expr : else-expr).msg()
501
                if (NodeTypeChecker.isConditionalExpression(expr)) {
3!
502
                        // can be one or the other (then-expr/else-expr) so we choose one
503
                        TNamedEntity ret = getReceiver(((ConditionalExpression) expr).getThenExpression());
×
504
                        if (ret == null) {
×
505
                                // can as well try the other
506
                                ret = getReceiver(((ConditionalExpression) expr).getElseExpression());
×
507
                        }
508
                        return ret;
×
509
                }
510

511
                // field.msg()
512
                if (NodeTypeChecker.isFieldAccess(expr)) {
3✔
513
                        IVariableBinding bnd = ((FieldAccess) expr).resolveFieldBinding();
4✔
514
                        TNamedEntity fld = (TNamedEntity) dico.getEntityByKey(bnd);
5✔
515
                        /*
516
                         * StructuralEntity fld = ensureAccessedStructEntity(bnd, ((FieldAccess)
517
                         * expr).getName().getIdentifier(),
518
                         * /*type* /null, /*owner* /null, /*accessor* /null);
519
                         */
520
                        return fld;
2✔
521
                }
522

523
                // (left-expr oper right-expr).msg()
524
                if (NodeTypeChecker.isInfixExpression(expr)) {
3!
525
                        // anonymous receiver
526
                        return null;
×
527
                }
528

529
                // msg1().msg()
530
                if (NodeTypeChecker.isMethodInvocation(expr)) {
3✔
531
                        return null;
2✔
532
                }
533

534
                // name.msg()
535
                if (NodeTypeChecker.isName(expr)) {
3✔
536
                        // can be a class or a variable name
537
                        IBinding bnd = ((Name) expr).resolveBinding();
4✔
538
                        if (bnd == null) {
2✔
539
                                return null;
2✔
540
                        }
541
                        TNamedEntity ret = null;
2✔
542
                        if (bnd.getKind() == IBinding.TYPE) {
4✔
543
                                // msg() is a static method of Name so name should be a class, except if its an
544
                                // Enum
545
                                ret = (TNamedEntity) dico.getEntityByKey(bnd);
5✔
546
                        }
547

548
                        if (bnd.getKind() == IBinding.VARIABLE) {
4✔
549
                                // a bit convoluted, but sometimes 'bnd' is not directly the binding of the
550
                                // variable's declaration from which the Famix entity was created
551
                                return (TNamedEntity) dico.getEntityByKey(((IVariableBinding) bnd).getVariableDeclaration());
7✔
552
                        }
553

554
                        return ret;
2✔
555
                }
556

557
                // (expr).msg()
558
                if (NodeTypeChecker.isParenthesizedExpression(expr)) {
3!
559
                        return getReceiver(((ParenthesizedExpression) expr).getExpression());
×
560
                }
561

562
                // "string".msg()
563
                if (NodeTypeChecker.isStringLiteral(expr)) {
3!
564
                        return null;
×
565
                }
566

567
                // super.field.msg()
568
                if (NodeTypeChecker.isSuperFieldAccess(expr)) {
3!
569
                        return (TNamedEntity) dico.getEntityByKey(((SuperFieldAccess) expr).resolveFieldBinding());
×
570
                        /*
571
                         * return ensureAccessedStructEntity(((SuperFieldAccess)
572
                         * expr).resolveFieldBinding(),
573
                         * ((SuperFieldAccess) expr).getName().getIdentifier(), /*typ* /null, /*owner*
574
                         * /null, /*accessor* /null);
575
                         */
576
                }
577

578
                // super.msg1().msg()
579
                if (NodeTypeChecker.isSuperMethodInvocation(expr)) {
3!
580
                        return null;
×
581
                }
582

583
                // this.msg()
584
                if (NodeTypeChecker.isThisExpression(expr)) {
3✔
585
                        return this.dico.ensureFamixImplicitVariable(EntityDictionary.SELF_NAME, context.topType(),
10✔
586
                                        context.topMethod());
1✔
587
                }
588

589
                // type.class.msg()
590
                if (NodeTypeChecker.isTypeLiteral(expr)) {
3!
591
                        // similar to a field access
592
                        return dico.getFamixAttribute(null, "class", dico.ensureFamixMetaClass(null));
10✔
593
                }
594

595
                // ... OTHER POSSIBLE EXPRESSIONS ?
596
                System.err.println("WARNING: Unexpected receiver expression: " + expr.getClass().getName()
×
NEW
597
                                + " (method called is" + expr.getClass().getName() + ".aMethod(...))");
×
598
                return null;
×
599
        }
600

601
        /**
602
         * Tries its best to find the type of a receiver without using the bindings.
603
         * Most of the time, the type is that of the receiver, but not always (if there
604
         * is a cast or if receiver is null)
605
         *
606
         * @param expr     -- the Java expression describing the receiver
607
         * @param receiver -- the FAMIX Entity describing the receiver
608
         * @return the Famix Entity or null if could not find it
609
         */
610
        private TType getInvokedMethodOwner(Expression expr, TNamedEntity receiver) {
611
                // ((type)expr).msg()
612
                if (NodeTypeChecker.isCastExpression(expr)) {
3!
613
                        Type tcast = ((CastExpression) expr).getType();
×
NEW
614
                        return referredType(tcast, (ContainerEntity) this.context.top(), true);
×
615
                }
616

617
                // new Class().msg()
618
                else if (NodeTypeChecker.isClassInstanceCreation(expr)) {
3!
619
                        return this.classInstanceCreated;
×
620
                }
621

622
                // msg1().msg()
623
                else if (NodeTypeChecker.isMethodInvocation(expr)) {
3✔
624
                        IMethodBinding callerBnd = ((MethodInvocation) expr).resolveMethodBinding();
4✔
625
                        if (callerBnd != null) {
2!
626
                                return referredType(callerBnd.getReturnType(), (ContainerEntity) this.context.top(), true);
10✔
627
                        } else {
628
                                return null;
×
629
                        }
630
                }
631

632
                // (expr).msg()
633
                else if (NodeTypeChecker.isParenthesizedExpression(expr)) {
3!
634
                        return getInvokedMethodOwner(((ParenthesizedExpression) expr).getExpression(), receiver);
×
635
                }
636

637
                // "string".msg()
638
                else if (NodeTypeChecker.isStringLiteral(expr)) {
3!
NEW
639
                        return dico.ensureFamixType(/* binding */null, "String", dico.ensureFamixPackageJavaLang(null),
×
640
                                        /* context */null, EntityDictionary.UNKNOWN_MODIFIERS); // creating FamixClass java.lang.String
641
                }
642

643
                // super.msg1().msg()
644
                else if (NodeTypeChecker.isSuperMethodInvocation(expr)) {
3!
645
                        IMethodBinding superBnd = ((SuperMethodInvocation) expr).resolveMethodBinding();
×
646
                        if (superBnd != null) {
×
NEW
647
                                return this.referredType(superBnd.getReturnType(), (ContainerEntity) context.topType(), true);
×
648
                        } else {
649
                                return null;
×
650
                        }
651
                }
652

653
                // everything else, see the receiver
654
                else {
655
                        if (receiver == null) {
2✔
656
                                return null;
2✔
657
                        }
658
                        /*
659
                         * else if (receiver instanceof ImplicitVariable) {
660
                         * if (receiver.getName().equals(EntityDictionary.SELF_NAME)) {
661
                         * return context.topType();
662
                         * }
663
                         * else { // receiver.getName().equals(EntityDictionary.SUPER_NAME)
664
                         * return
665
                         * context.topType().getSuperInheritances().iterator().next().getSuperclass();
666
                         * }
667
                         * }
668
                         */
669
                        else if (receiver instanceof TTypedEntity) {
3!
670
                                return ((TTypedEntity) receiver).getDeclaredType();
4✔
671
                        } else if (receiver instanceof org.moosetechnology.model.famix.famixjavaentities.Type) {
×
672
                                return (org.moosetechnology.model.famix.famixjavaentities.Type) receiver;
×
673
                        }
674
                        // ... what else ?
675
                        else {
676
                                return null;
×
677
                        }
678
                }
679
        }
680

681
}
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

© 2026 Coveralls, Inc