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

moosetechnology / VerveineJ / 28750184792

05 Jul 2026 06:12PM UTC coverage: 52.626% (+0.2%) from 52.433%
28750184792

push

github

web-flow
Merge pull request #264 from moosetechnology/feat/record

Dealing with record declaration

2023 of 4018 branches covered (50.35%)

Branch coverage included in aggregate %.

44 of 58 new or added lines in 5 files covered. (75.86%)

1 existing line in 1 file now uncovered.

4469 of 8318 relevant lines covered (53.73%)

2.22 hits per line

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

86.35
/app/src/main/java/fr/inria/verveine/extractor/java/visitors/refvisitors/VisitorAccessRef.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.ImplicitVarBinding;
6
import fr.inria.verveine.extractor.java.utils.NodeTypeChecker;
7

8
import org.eclipse.jdt.core.dom.ASTNode;
9
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
10
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
11
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
12
import org.eclipse.jdt.core.dom.ArrayAccess;
13
import org.eclipse.jdt.core.dom.AssertStatement;
14
import org.eclipse.jdt.core.dom.Assignment;
15
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
16
import org.eclipse.jdt.core.dom.CompilationUnit;
17
import org.eclipse.jdt.core.dom.DoStatement;
18
import org.eclipse.jdt.core.dom.EnhancedForStatement;
19
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
20
import org.eclipse.jdt.core.dom.EnumDeclaration;
21
import org.eclipse.jdt.core.dom.Expression;
22
import org.eclipse.jdt.core.dom.FieldAccess;
23
import org.eclipse.jdt.core.dom.FieldDeclaration;
24
import org.eclipse.jdt.core.dom.ForStatement;
25
import org.eclipse.jdt.core.dom.IBinding;
26
import org.eclipse.jdt.core.dom.IVariableBinding;
27
import org.eclipse.jdt.core.dom.IfStatement;
28
import org.eclipse.jdt.core.dom.InfixExpression;
29
import org.eclipse.jdt.core.dom.Initializer;
30
import org.eclipse.jdt.core.dom.LambdaExpression;
31
import org.eclipse.jdt.core.dom.MethodDeclaration;
32
import org.eclipse.jdt.core.dom.MethodInvocation;
33
import org.eclipse.jdt.core.dom.PostfixExpression;
34
import org.eclipse.jdt.core.dom.PrefixExpression;
35
import org.eclipse.jdt.core.dom.QualifiedName;
36
import org.eclipse.jdt.core.dom.RecordDeclaration;
37
import org.eclipse.jdt.core.dom.ReturnStatement;
38
import org.eclipse.jdt.core.dom.SimpleName;
39
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
40
import org.eclipse.jdt.core.dom.SwitchCase;
41
import org.eclipse.jdt.core.dom.SwitchStatement;
42
import org.eclipse.jdt.core.dom.SynchronizedStatement;
43
import org.eclipse.jdt.core.dom.ThisExpression;
44
import org.eclipse.jdt.core.dom.ThrowStatement;
45
import org.eclipse.jdt.core.dom.TypeDeclaration;
46
import org.eclipse.jdt.core.dom.TypeLiteral;
47
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
48
import org.eclipse.jdt.core.dom.WhileStatement;
49
import org.moosetechnology.model.famix.famixjavaentities.Attribute;
50
import org.moosetechnology.model.famix.famixjavaentities.ContainerEntity;
51
import org.moosetechnology.model.famix.famixjavaentities.Enum;
52
import org.moosetechnology.model.famix.famixjavaentities.EnumValue;
53
import org.moosetechnology.model.famix.famixjavaentities.ImplicitVariable;
54
import org.moosetechnology.model.famix.famixjavaentities.LocalVariable;
55
import org.moosetechnology.model.famix.famixjavaentities.Method;
56
import org.moosetechnology.model.famix.famixjavaentities.Parameter;
57
import org.moosetechnology.model.famix.famixtraits.TAccess;
58
import org.moosetechnology.model.famix.famixtraits.TAttribute;
59
import org.moosetechnology.model.famix.famixtraits.TMethod;
60
import org.moosetechnology.model.famix.famixtraits.TNamedEntity;
61
import org.moosetechnology.model.famix.famixtraits.TStructuralEntity;
62
import org.moosetechnology.model.famix.famixtraits.TWithAttributes;
63

64
import java.util.List;
65

66
/**
67
 * A visitor that extracts accesses to variables.
68
 * One difficulty is that variable are often SimpleName nodes
69
 * But many other things are also SimpleName nodes (ex: name of an invoked method)
70
 * So we need to differentiate them. The choice has been made to do this in the parent nodes of the SimpleName nodes
71
 */
72
public class VisitorAccessRef extends AbstractRefVisitor {
73

74
        /**
75
         * Whether a variable access is lhs (write) or not
76
         */
77
        protected boolean inAssignmentLHS = false;
3✔
78

79
        /**
80
         * Counts in how many nested lambdas we are
81
         * This is needed because Lambdas parameters are currently considered as local variables whereas JDT (rightly) reports them as parameters
82
         */
83
        private int inLambda = 0;
3✔
84

85
        /**
86
         * This variable indicates that the current class declaration is actually a record declaration
87
         * FIXME Temporary workaround because there is no FamixJavaRecord and we use FamixJavaClass
88
         */
89
        private boolean declarationIsRecord = false;
3✔
90

91
        public VisitorAccessRef(EntityDictionary dico, VerveineJOptions options) {
92
                super(dico, options);
4✔
93
                this.inLambda = 0;
3✔
94
        }
1✔
95

96
        // VISITOR METHODS
97

98
        @Override
99
        public boolean visit(CompilationUnit node) {
100
                visitCompilationUnit(node);
4✔
101
                return super.visit(node);
4✔
102
        }
103

104
        @Override
105
        public void endVisit(CompilationUnit node) {
106
                endVisitCompilationUnit(node);
3✔
107
        }
1✔
108

109
        @Override
110
        public boolean visit(TypeDeclaration node) {
111
                if (visitTypeDeclaration( node) != null) {
4!
112
                        return super.visit(node);
4✔
113
                } else {
NEW
114
                        return false;
×
115
                }
116
        }
117

118
        @Override
119
        public void endVisit(TypeDeclaration node) {
120
                endVisitTypeDeclaration(node);
3✔
121
        }
1✔
122

123
        @Override
124
        public boolean visit(RecordDeclaration node) {
125
                //System.err.println("TRACE, Visiting RecordDeclaration: "+node.getName().getIdentifier());
126
                if (visitTypeDeclaration( node) != null) {
4!
127
                        declarationIsRecord = true;
3✔
128
                        return super.visit(node);
4✔
129
                } else {
NEW
130
                        return false;
×
131
                }
132
        }
133

134
        @Override
135
        public void endVisit(RecordDeclaration node) {
136
                declarationIsRecord = false;
3✔
137

138
                super.endVisit(node);
3✔
139
        }
1✔
140

141
        @Override
142
        public boolean visit(ClassInstanceCreation node) {
143
                possiblyAnonymousClassDeclaration( node);
3✔
144
        visitIfNotNull(node.getExpression());
4✔
145
        for (Object arg : node.arguments()) {
10✔
146
            if (NodeTypeChecker.isSimpleName((ASTNode) arg)) {
4✔
147
                visitIfNotNull((ASTNode) arg);
5✔
148
            }
149
            else {
150
                    ((ASTNode) arg).accept(this);
4✔
151
                        }
152
        }
1✔
153
        if (node.getAnonymousClassDeclaration() != null) {
3✔
154
            node.getAnonymousClassDeclaration().accept(this);
4✔
155
        }
156
                return false;
2✔
157
        }
158

159
        @SuppressWarnings("unchecked")
160
        @Override
161
        public boolean visit(AnonymousClassDeclaration node) {
162
                if (visitAnonymousClassDeclaration( node) != null) {
4!
163
            visitNodeList(node.bodyDeclarations());
4✔
164
        }
165

166
                        return false;
2✔
167

168
        }
169

170
        @Override
171
        public void endVisit(AnonymousClassDeclaration node) {
172
                endVisitAnonymousClassDeclaration( node);
3✔
173
        }
1✔
174

175
        @SuppressWarnings("unchecked")
176
        @Override
177
        public boolean visit(EnumDeclaration node) {
178
                if (visitEnumDeclaration( node) != null) {
4!
179
            // no need to visit node.enumConstants() in this visitor
180
            visitNodeList(node.bodyDeclarations());
4✔
181
        }
182
                return false;
2✔
183
        }
184

185
    @Override
186
        public void endVisit(EnumDeclaration node) {
187
                endVisitEnumDeclaration( node);
3✔
188
        }
1✔
189

190
        @Override
191
        public boolean visit(AnnotationTypeDeclaration node) {
192
                if (visitAnnotationTypeDeclaration( node) != null) {
4!
193
                        return super.visit(node);
4✔
194
                }
195
                else {
196
                        return false;
×
197
                }
198
        }
199

200
        @Override
201
        public void endVisit(AnnotationTypeDeclaration node) {
202
                endVisitAnnotationTypeDeclaration(node);
3✔
203
        }
1✔
204

205
        public boolean visit(AnnotationTypeMemberDeclaration node) {
206
                if (visitAnnotationTypeMemberDeclaration( node) != null) {
4!
207
            visitIfNotNull(node.getDefault());
4✔
208
        }
209
                return false;
2✔
210
        }
211

212
        public void endVisit(AnnotationTypeMemberDeclaration node) {
213
                this.context.popAnnotationMember();
4✔
214
                super.endVisit(node);
3✔
215
        }
1✔
216

217
        public boolean visit(MethodDeclaration node) {
218
                Method fmx = visitMethodDeclaration( node);
4✔
219

220
                if (fmx != null) {
2!
221
                        if (node.getBody() != null) {
3✔
222
                                context.setLastAccess(null);
4✔
223
                node.getBody().accept(this);
4✔
224
                        }
225
        }
226
        return false;
2✔
227
        }
228

229
        @Override
230
        public void endVisit(MethodDeclaration node) {
231
                endVisitMethodDeclaration(node);
3✔
232
        }
1✔
233

234
        @Override
235
        public boolean visit(Initializer node) {
236
                if (visitInitializer(node) != null) {
4!
237
                        node.getBody().accept(this);
4✔
238
                }
239
                return false;
2✔
240
        }
241

242
        @Override
243
        public void endVisit(Initializer node) {
244
                endVisitInitializer(node);
3✔
245
        }
1✔
246

247
    /**
248
         * <pre>
249
         * {@code
250
     * MethodInvocation ::=
251
     *      [ Expression . ]
252
     *          [ < Type { , Type } > ]
253
     *          Identifier ( [ Expression { , Expression } ] )
254
     * }
255
         * </pre>
256
         **/
257
        @Override
258
        public boolean visit(MethodInvocation node) {
259
        visitIfNotNull( node.getExpression());
4✔
260
        for (Object arg : node.arguments()) {
10✔
261
            visitIfNotNull((ASTNode) arg);
4✔
262
        }
1✔
263
                return false;  // already visited the interesting children
2✔
264
        }
265

266
        /**
267
         * Currently not defining lambdas. Only parse their body and consider their parameters as local variables
268
         * of the parent method
269
         *<pre>
270
         * {@code
271
         *  LambdaExpression:
272
         *     Identifier -> Body
273
         *     ( [ Identifier { , Identifier } ] ) -> Body
274
         *     ( [ FormalParameter { , FormalParameter } ] ) -> Body
275
         * }
276
         * </pre>
277
         */
278
        @Override
279
        public boolean visit(LambdaExpression node) {
280
                inLambda++;
6✔
281
                node.getBody().accept(this);
4✔
282
                inLambda--;
6✔
283
                return false;  // only visit body of lambda
2✔
284
        }
285

286
        /**
287
         *  FieldDeclaration ::=
288
         *     [Javadoc] { ExtendedModifier } Type VariableDeclarationFragment
289
         *          { , VariableDeclarationFragment } ;
290
         */
291
        @SuppressWarnings("unchecked")
292
        @Override
293
        public boolean visit(FieldDeclaration node) {
294
            if (hasInitBlock(node)) {   // true if hasInitializer + recovers EntityDictionary.INIT_BLOCK_NAME method
4✔
295
            visitNodeList(node.fragments());
4✔
296
        }
297
        return false;
2✔
298
        }
299

300
        @Override
301
        public void endVisit(FieldDeclaration node) {
302
                endVisitFieldDeclaration(node);
3✔
303
        }
1✔
304

305
        public boolean visit(EnumConstantDeclaration node) {
306
        return visitEnumConstantDeclaration(node);
×
307
        }
308

309
        public void endVisit(EnumConstantDeclaration node) {
310
                endVisitEnumConstantDeclaration(node);
×
311
        }
×
312

313
        public boolean visit(FieldAccess node) {
314
            visitIfNotNull(node.getExpression());
4✔
315
                TMethod accessor = this.context.topMethod();
4✔
316
                IVariableBinding bnd = node.resolveFieldBinding();
3✔
317
                // FIXME if bnd == null we have a problem
318
                ensureAccessedStructEntity(bnd, node.getName().getIdentifier(), /*typ*/null, /*owner*/null, accessor);
10✔
319
                TAccess lastAccess = context.getLastAccess();
4✔
320
                if ( (options.withAnchors(VerveineJOptions.AnchorOptions.assoc))
8!
321
                                // check that lastAccess corresponds to current one
322
                                && (lastAccess != null) && (lastAccess.getAccessor() == accessor)
4!
323
                                && ((TNamedEntity) (lastAccess.getCandidates().iterator().next())).getName().equals(node.getName().getIdentifier())) {
10✔
324
                        dico.addSourceAnchor(lastAccess, node);
6✔
325
                }
326
                return false;
2✔
327
        }
328

329
        /*
330
         * Could be a FieldAccess (see JDT javadoc: class FieldAccess) 
331
         */
332
        public boolean visit(QualifiedName node) {
333
                IBinding bnd = node.resolveBinding();
3✔
334
                if ( (bnd != null) && (bnd.getKind() == IBinding.VARIABLE) ) {
6✔
335
                        // could be a field or an enumValue
336
                        TMethod accessor = this.context.topMethod();
4✔
337
                        ensureAccessedStructEntity((IVariableBinding) bnd, node.getName().getIdentifier(), /*typ*/null,
11✔
338
                                        /*owner*/null, accessor);
339
                        TAccess lastAccess = context.getLastAccess();
4✔
340
                        if ( (options.withAnchors(VerveineJOptions.AnchorOptions.assoc))
8!
341
                                        // check that lastAccess corresponds to current one
342
                                        && (lastAccess != null) && (lastAccess.getAccessor() == accessor)
4!
343
                                        && (((TNamedEntity) (lastAccess.getCandidates().iterator().next())).getName().equals(node.getName().getIdentifier()))) {
10!
344
                                dico.addSourceAnchor(lastAccess, node);
6✔
345
                        }
346
                }
347
                return false;
2✔
348
        }
349

350
    @SuppressWarnings("unchecked")
351
    public boolean visit(InfixExpression node) {
352
        visitIfNotNull( node.getLeftOperand());
4✔
353
        visitIfNotNull( node.getRightOperand());
4✔
354
        if (node.hasExtendedOperands()) {
3✔
355
            for (Expression op : (List<Expression>) node.extendedOperands()) {
11✔
356
                visitIfNotNull( op);
3✔
357
            }
1✔
358
        }
359
        return false;
2✔
360
    }
361

362
    @Override
363
    public boolean visit(PrefixExpression node) {
364
        visitIfNotNull( node.getOperand());
4✔
365
        return false;
2✔
366
    }
367

368
    @Override
369
    public boolean visit(PostfixExpression node) {
370
        visitIfNotNull( node.getOperand());
4✔
371
        return false;
2✔
372
    }
373

374
        // "SomeClass.class"
375
        public boolean visit(TypeLiteral node) {
376
                Attribute accessed = dico.getFamixAttribute(null, "class", dico.getFamixMetaClass(null));
10✔
377
                if (accessed != null) {
2!
378
                        createAccess(/*accessor*/context.topMethod(), accessed, inAssignmentLHS);
8✔
379
                }
380

381
                return super.visit(node);
4✔
382
        }
383

384
        public boolean visit(AssertStatement node) {
385
        visitIfNotNull( node.getExpression());
×
386
        visitIfNotNull( node.getMessage());
×
387
                return false;
×
388
        }
389

390
        public boolean visit(Assignment node) {
391
        visitAssignment(node.getLeftHandSide(), node.getRightHandSide());
6✔
392
                return false;
2✔
393
        }
394

395
    public boolean visit(ArrayAccess node) {
396
                // an array might be accessed in writing (see visit(Assignment node) ),
397
                // but it's index is accessed in reading
398
                boolean tmp = inAssignmentLHS;
3✔
399

400
                node.getArray().accept(this);
4✔
401

402
                inAssignmentLHS = false;  // array index is not lhs of an assignement
3✔
403
        visitIfNotNull( node.getIndex());
4✔
404
                inAssignmentLHS = tmp;
3✔
405

406
                return false;
2✔
407
        }
408

409
        public boolean visit(DoStatement node) {
410
        visitIfNotNull( node.getExpression());
×
411
        node.getBody().accept(this);
×
412
                return false;
×
413
        }
414

415
        public boolean visit(EnhancedForStatement node) {
416
        visitIfNotNull( node.getExpression());
4✔
417
        node.getBody().accept(this);
4✔
418
        return false;
2✔
419
        }
420

421
        @SuppressWarnings("unchecked")
422
        public boolean visit(ForStatement node) {
423
        visitNodeList(node.initializers());
4✔
424
        visitIfNotNull( node.getExpression());
4✔
425
        visitNodeList(node.updaters());
4✔
426
        node.getBody().accept(this);
4✔
427
        return false;
2✔
428
    }
429

430
        public boolean visit(IfStatement node) {
431
        visitIfNotNull( node.getExpression());
4✔
432
        node.getThenStatement().accept(this);
4✔
433
        if (node.getElseStatement() != null) {
3✔
434
            node.getElseStatement().accept(this);
4✔
435
        }
436
        return false;
2✔
437
    }
438

439
        public boolean visit(ReturnStatement node) {
440
        visitIfNotNull( node.getExpression());
4✔
441
        return false;
2✔
442
        }
443

444
        public boolean visit(SwitchCase node) {
445
                for ( Expression expr : (List<Expression>)node.expressions()) {
11✔
446
                        expr.accept(this);
3✔
447
                }
1✔
448
        return false;
2✔
449
        }
450

451
        @SuppressWarnings("unchecked")
452
        public boolean visit(SwitchStatement node) {
453
        visitIfNotNull( node.getExpression());
4✔
454
        visitNodeList(node.statements());
4✔
455
        return false;
2✔
456
        }
457

458
        public boolean visit(SynchronizedStatement node) {
459
        visitIfNotNull(node.getExpression());
×
460
        node.getBody().accept(this);
×
461
        return false;
×
462
        }
463

464
        public boolean visit(WhileStatement node) {
465
        visitIfNotNull(node.getExpression());
4✔
466
        node.getBody().accept(this);
4✔
467
        return false;
2✔
468
        }
469

470
        @Override
471
        public boolean visit(ThrowStatement node) {
472
                visitIfNotNull( node.getExpression());
4✔
473
                return false;
2✔
474
        }
475

476
        @Override
477
        public boolean visit(ThisExpression node) {
478
                IBinding bnd = ImplicitVarBinding.getInstance(context.topMethod(), EntityDictionary.THIS_NAME);
6✔
479
                ImplicitVariable fmx = dico.ensureFamixImplicitVariable(
8✔
480
                                bnd, 
481
                                EntityDictionary.THIS_NAME,
482
                                this.context.topType(), 
3✔
483
                                context.topMethod());
1✔
484
                if (fmx != null) {
2!
485
                        TMethod accessor = this.context.topMethod();
4✔
486

487
                        createAccess(accessor, fmx, inAssignmentLHS);
6✔
488

489
                        TAccess lastAccess = context.getLastAccess();
4✔
490
                        if ( (options.withAnchors(VerveineJOptions.AnchorOptions.assoc)) && (lastAccess != null) ) {
7!
491
                                dico.addSourceAnchor(lastAccess, node.getParent());
7✔
492
                        }
493
                }
494

495
                return false;
2✔
496
        }
497

498
        @Override
499
        public boolean visit(SingleVariableDeclaration node) {
500
                if (node.getInitializer() != null) {
3!
501
            visitAssignment(node.getName(), node.getInitializer());
×
502
                }
503
                return false;
2✔
504
        }
505

506
        @Override
507
        public boolean visit(VariableDeclarationFragment node) {
508
                if (node.getInitializer() != null) {
3✔
509
            visitAssignment(node.getName(), node.getInitializer());
6✔
510
                }
511
                return false;
2✔
512
        }
513

514
        @Override
515
        public boolean visit(SimpleName node) {
516
        //System.err.println("visit(SimpleName)");
517
        IBinding bnd = node.resolveBinding();
3✔
518
        if ( (bnd != null) && (bnd.getKind() == IBinding.VARIABLE) && (context.topMethod() != null) ) {
10!
519
            // could be a variable, a field, an enumValue, ...
520
            TMethod accessor = this.context.topMethod();
4✔
521
            ensureAccessedStructEntity((IVariableBinding) bnd, node.getIdentifier(), /*typ*/null, /*owner*/null,
10✔
522
                    accessor);
523
            TAccess lastAccess = context.getLastAccess();
4✔
524
            if ( options.withAnchors(VerveineJOptions.AnchorOptions.assoc)
8✔
525
                    // check that lastAccess corresponds to current one
526
                    && (lastAccess != null) && (lastAccess.getAccessor() == accessor)
4!
527
                    && (((TNamedEntity) (lastAccess.getCandidates().iterator().next())).getName().equals(node.getIdentifier()))) {
9✔
528
                dico.addSourceAnchor(lastAccess, node);
6✔
529
            }
530
        }
531
                return false;
2✔
532
        }
533

534
        // UTILITY METHODS
535

536
        private void visitIfNotNull(ASTNode node) {
537
                if (node != null) {
2✔
538
                        node.accept(this);
3✔
539
                }
540
        }
1✔
541

542
        private void visitAssignment(Expression lhs, Expression rhs) {
543
                inAssignmentLHS = true;
3✔
544
                visitIfNotNull(lhs);
3✔
545
                inAssignmentLHS = false;
3✔
546

547
                visitIfNotNull(rhs);
3✔
548
        }
1✔
549

550
        private TStructuralEntity ensureAccessedStructEntity(IVariableBinding bnd, String name,
551
                                                                                                                 org.moosetechnology.model.famix.famixjavaentities.Type typ, ContainerEntity owner, TMethod accessor) {
552
                TStructuralEntity accessed = null;
2✔
553

554
                if (bnd == null) {
2✔
555
                        // no way to know if it should be an attribute, EnumValue, variable, ...
556
                        return null;
2✔
557
                } else {
558
                        bnd = bnd.getVariableDeclaration();
3✔
559
                }
560

561
                // could also test: "owner instanceof Enum" in case bnd == null
562
                if (bnd.isEnumConstant()) {
3✔
563
                        accessed = dico.ensureFamixEnumValue(bnd, name, (Enum) owner);
9✔
564
                } else if (bnd.isField()) {
3✔
565
                        if (declarationIsRecord) {
3✔
566
                                accessed = findRecordField( name);
5✔
567
                        }
568
                        else {
569
                                accessed = dico.ensureFamixAttribute(bnd, name, typ, (TWithAttributes) owner);
9✔
570
                        }
571
                        if ((accessed != null) && (((Attribute) accessed).getParentType() == null)
6!
572
                                        && (((Attribute) accessed).getName().equals("length"))) {
×
573
                                // special case: length attribute of arrays in Java
574
                                ((Attribute) accessed).setParentType(dico.ensureFamixClassArray());
×
575
                        }
576
                } else if (bnd.isParameter() && notInALambda()) {
6✔
577
                        accessed = dico.ensureFamixParameter(bnd, name, typ, (Method) owner);
10✔
578
                } else {
579
                        // it seems it is a variable.
580
                        // if it is not already defined, we assume we are not interested
581
                        accessed = (TStructuralEntity) dico.getEntityByKey(bnd);
6✔
582
                }
583

584
                createAccess(accessor, accessed, inAssignmentLHS);
6✔
585

586
                return accessed;
2✔
587
        }
588

589
        /** finding the FamixJavaAttribute with <code>name</code>
590
         * this is necessary because in JDT (version 3.46.0) the binding for the declaration of a RecordComponent is different from the binding of the record Field used
591
         */
592
        private TStructuralEntity findRecordField(String name) {
593
                for (TStructuralEntity entity : ((org.moosetechnology.model.famix.famixjavaentities.Class)context.topType()).getAttributes()) {
14!
594
                        if (entity.getName().equals(name)) {
5✔
595
                                return entity;
2✔
596
                        }
597
                }
1✔
NEW
598
                return null;
×
599
        }
600

601
        /**
602
         * Creates a FamixAccess between an accessor and an accessed. Checks before that we are not in a local access to ignore.
603
         *
604
         * @param accessor -- the method accessing
605
         * @param accessed -- the variable accessed
606
         * @param isLHS    -- whether the access occurs on the LeftHandSide of an assignement (and therefore is a write access)
607
         */
608
        private void createAccess(TMethod accessor, TStructuralEntity accessed, boolean isLHS) {
609
                // create local accesses?
610
                if ((accessed != null) && (accessor != null)) {
4✔
611
                        if (options.withLocals() || (! localVariable(accessed, accessor)) ) {
9✔
612
                                context.setLastAccess(
10✔
613
                                                dico.addFamixAccess(accessor, (TStructuralEntity) accessed, /*isWrite*/isLHS, context.getLastAccess()));
2✔
614
                        }
615
                }
616
        }
1✔
617

618
        private boolean localVariable(TStructuralEntity accessed, TMethod accessor) {
619
                // TODO see issue 11 (https://github.com/NicolasAnquetil/VerveineJ/issues/11)
620

621
                // This is ugly.. but it allows us to not rewrite method in generated code
622
                if (accessed instanceof ImplicitVariable) {
3✔
623
                        return false;
2✔
624
                } else if (accessed instanceof Attribute && ((Attribute) accessed).getParentType() == accessor) {
8!
625
                        return true;
×
626
                } else if (accessed instanceof EnumValue && ((EnumValue) accessed).getParentEnum() == accessor) {
8!
627
                        return true;
×
628
                } 
629
                // Benoit Verhaeghe: Has been removed between VerveineJ 3.0.0 and VerveineJ 3.0.1
630
                // else if (accessed instanceof GlobalVariable && ((GlobalVariable) accessed).getParentScope() == accessor) {
631
                //         return true;
632
                // } 
633
                else if (accessed instanceof ImplicitVariable && ((ImplicitVariable) accessed).getParentBehaviouralEntity() == accessor) {
3!
634
                        return true;
×
635
                } else if (accessed instanceof LocalVariable && ((LocalVariable) accessed).getParentBehaviouralEntity() == accessor) {
8!
636
                        return true;
2✔
637
                } else if (accessed instanceof Parameter && ((Parameter) accessed).getParentBehaviouralEntity() == accessor) {
8!
638
                        return true;
2✔
639
                }
640
                if (((TNamedEntity) accessor.getParentType()).getName().startsWith(EntityDictionary.ANONYMOUS_NAME_PREFIX)) {
7✔
641
                        return localVariable(accessed, ((Method) ((org.moosetechnology.model.famix.famixjavaentities.Type) accessor.getParentType()).getTypeContainer()));
9✔
642
                }
643
                return false;
2✔
644
        }
645

646
        protected boolean notInALambda() {
647
                return (inLambda == 0);
7✔
648
        }
649

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