• 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

87.5
/app/src/main/java/fr/inria/verveine/extractor/java/visitors/defvisitors/VisitorVarsDef.java
1
package fr.inria.verveine.extractor.java.visitors.defvisitors;
2

3
import fr.inria.verveine.extractor.java.EntityDictionary;
4
import fr.inria.verveine.extractor.java.VerveineJOptions;
5
import fr.inria.verveine.extractor.java.visitors.GetVisitedEntityAbstractVisitor;
6
import fr.inria.verveine.extractor.java.utils.StructuralEntityKinds;
7

8
import org.eclipse.jdt.core.dom.*;
9
import org.eclipse.jdt.core.dom.Initializer;
10
import org.moosetechnology.model.famix.famixjavaentities.*;
11
import org.moosetechnology.model.famix.famixjavaentities.Class;
12
import org.moosetechnology.model.famix.famixjavaentities.Enum;
13
import org.moosetechnology.model.famix.famixtraits.TAttribute;
14
import org.moosetechnology.model.famix.famixtraits.TNamedEntity;
15
import org.moosetechnology.model.famix.famixtraits.TStructuralEntity;
16
import org.moosetechnology.model.famix.famixtraits.TWithAttributes;
17

18
import java.util.List;
19

20
/**
21
 * AST Visitor that defines all the (Famix) entities of interest
22
 * Famix entities are stored in a Map along with the IBindings to which they correspond
23
 */
24
public class VisitorVarsDef extends GetVisitedEntityAbstractVisitor {
25

26
        /**
27
         * set in parent of structuralEntity declaration to indicate what kind of structuralentity it is
28
         */
29
        private StructuralEntityKinds structuralType;
30

31
        public VisitorVarsDef(EntityDictionary dico, VerveineJOptions options) {
32
                super(dico, options);
4✔
33
        }
1✔
34

35
        // VISITOR METHODS
36

37
        @Override
38
        public boolean visit(CompilationUnit node) {
39
                visitCompilationUnit(node);
4✔
40
                return super.visit(node);
4✔
41
        }
42

43
        @Override
44
        public void endVisit(CompilationUnit node) {
45
                endVisitCompilationUnit(node);
3✔
46
        }
1✔
47

48
        @Override
49
        public boolean visit(TypeDeclaration node) {
50
                if (visitTypeDeclaration( node) != null) {
4!
51
                        return super.visit(node);
4✔
52
                } else {
53
                        return false;
×
54
                }
55
        }
56

57
        @Override
58
        public void endVisit(TypeDeclaration node) {
59
                endVisitTypeDeclaration(node);
3✔
60
        }
1✔
61

62
        /*
63
         * Records are immutable data classes that require only the type and name of fields.
64
         * The equals, hashCode, and toString methods, as well as the private, final fields and public constructor, are generated by the Java compiler.
65
         * A record is always a final class never an interface or exception.
66
         */
67
        @Override
68
        public boolean visit(RecordDeclaration node) {
69
                //System.err.println("TRACE, Visiting RecordDeclaration: "+node.getName().getIdentifier());
70
                if (visitTypeDeclaration( node) != null) {
4!
71
                        structuralType = StructuralEntityKinds.ATTRIBUTE;
3✔
72

73
                        return super.visit(node);
4✔
74
                } else {
NEW
75
                        return false;
×
76
                }
77
        }
78

79
        @Override
80
        public void endVisit(RecordDeclaration node) {
81
                Class record = (Class) this.context.popType();
5✔
82
                for (TAttribute att : record.getAttributes()) {
11✔
83
                        ((Attribute)att).setIsFinal(true);
5✔
84
                        ((Attribute)att).setVisibility("private");                        
4✔
85
                }
1✔
86
                super.endVisit(node);
3✔
87
        }
1✔
88

89
        @Override
90
        public boolean visit(ClassInstanceCreation node) {
91
                possiblyAnonymousClassDeclaration( node);
3✔
92
                return super.visit(node);
4✔
93
        }
94

95
        @Override
96
        public boolean visit(AnonymousClassDeclaration node) {
97
                if (visitAnonymousClassDeclaration( node) != null) {
4!
98
                        return super.visit(node);
4✔
99
                }
100
                else {
101
                        return false;
×
102
                }
103
        }
104

105
        @Override
106
        public void endVisit(AnonymousClassDeclaration node) {
107
                endVisitAnonymousClassDeclaration( node);
3✔
108
        }
1✔
109

110
        @Override
111
        public boolean visit(EnumDeclaration node) {
112
                if (visitEnumDeclaration( node) != null) {
4!
113
                        return super.visit(node);
4✔
114
                }
115
                else {
116
                        return false;
×
117
                }
118
        }
119

120
        @Override
121
        public void endVisit(EnumDeclaration node) {
122
                endVisitEnumDeclaration( node);
3✔
123
        }
1✔
124

125
        @Override
126
        public boolean visit(AnnotationTypeDeclaration node) {
127
                if (visitAnnotationTypeDeclaration( node) != null) {
4!
128
                        return super.visit(node);
4✔
129
                }
130
                else {
131
                        return false;
×
132
                }
133
        }
134

135
        @Override
136
        public void endVisit(AnnotationTypeDeclaration node) {
137
                endVisitAnnotationTypeDeclaration(node);
3✔
138
        }
1✔
139

140
        @Override
141
        public boolean visit(AnnotationTypeMemberDeclaration node) {
142
                IMethodBinding bnd = node.resolveBinding();
3✔
143

144
                AnnotationTypeAttribute fmx = dico.ensureFamixAnnotationTypeAttribute(
6✔
145
                                bnd, 
146
                                node.getName().getIdentifier(), 
4✔
147
                                (AnnotationType) context.topType());
2✔
148
                if (fmx != null) {
2!
149
                        fmx.setIsStub(false);
4✔
150
                        if (options.withAnchors()) {
4!
151
                                dico.addSourceAnchor(fmx, node);
6✔
152
                        }
153

154
                        context.pushAnnotationMember(fmx);
4✔
155
                        return super.visit(node);
4✔
156
                } else {
157
                        context.pushAnnotationMember(null);
×
158
                        return false;
×
159
                }
160
        }
161

162
        @Override
163
        public void endVisit(AnnotationTypeMemberDeclaration node) {
164
                this.context.popAnnotationMember();
4✔
165
                super.endVisit(node);
3✔
166
        }
1✔
167

168
        @Override
169
        public boolean visit(MethodDeclaration node) {
170
                //System.err.println("visit(MethodDeclaration) " + node.getName().getIdentifier());
171
                visitMethodDeclaration( node);
4✔
172
                structuralType = StructuralEntityKinds.PARAMETER;
3✔
173

174
                return super.visit(node);
4✔
175
        }
176

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

182
        @Override
183
        public boolean visit(Initializer node) {
184
                visitInitializer(node);
4✔
185
                return super.visit(node);
4✔
186
        }
187

188
        @Override
189
        public void endVisit(Initializer node) {
190
                endVisitInitializer(node);
3✔
191
        }
1✔
192

193
        /**
194
         * Currently not defining lambdas. Only parse their body and consider their parameters as local variables
195
         * of the parent method
196
         *
197
         *  LambdaExpression:
198
         *     Identifier -> Body
199
         *     ( [ Identifier { , Identifier } ] ) -> Body
200
         *     ( [ FormalParameter { , FormalParameter } ] ) -> Body
201
         */
202
        @Override
203
        public boolean visit(LambdaExpression node) {
204
                structuralType = StructuralEntityKinds.LOCALVAR;  // actually, should already be the case since we must be in a method
3✔
205
                return super.visit(node);
4✔
206
        }
207

208
        @Override
209
        public void endVisit(LambdaExpression node) {
210

211
        }
1✔
212

213
        @Override
214
        public boolean visit(Block node) {
215
                structuralType = StructuralEntityKinds.LOCALVAR;
3✔
216

217
                return super.visit(node);
4✔
218
        }
219

220
        @Override
221
        public boolean visit(EnumConstantDeclaration node) {
222
        EnumValue ev = dico.ensureFamixEnumValue(node.resolveVariable(), node.getName().getIdentifier(), /*owner*/(Enum)context.topType());
13✔
223
                ev.setIsStub(false);
4✔
224
                return super.visit(node);
4✔
225
        }
226

227
        @SuppressWarnings("unchecked")
228
        @Override
229
        public boolean visit(FieldDeclaration node) {
230
                StructuralEntityKinds saved = structuralType;
3✔
231
                structuralType = StructuralEntityKinds.ATTRIBUTE;
3✔
232

233
                // creating the attribute(s)
234
                for (var variableDeclaration : (List<VariableDeclaration>)node.fragments() ) {
11✔
235
                        createStructuralEntity( structuralType, variableDeclaration, context.top());
9✔
236
                }
1✔
237

238
                // Possible local variables in optional initializer
239
                if (hasInitBlock(node)) {  // recovers optional Initializer and push it on the context stack.
4✔
240
                        structuralType = StructuralEntityKinds.LOCALVAR;
3✔
241
                        for (var variableDeclaration : (List<VariableDeclaration>)node.fragments() ) {
11✔
242
                                if (variableDeclaration.getInitializer() != null) {
3✔
243
                                        variableDeclaration.getInitializer().accept(this);
4✔
244
                                }
245
                        }
1✔
246
                }
247
                structuralType = saved;
3✔
248
                return false;  // already visited all children
2✔
249
        }
250

251
        @Override
252
        public void endVisit(FieldDeclaration node) {
253
                endVisitFieldDeclaration(node);
3✔
254
        }
1✔
255

256
        @Override
257
        public boolean visit(VariableDeclarationExpression node) {
258
                // we usually don't declare local variables that have a primitive type
259
                // because we are assuming that the user is not interested in them
260
                // note that non primitive types are important because of the dependencies they create (eg invocation receiver)
261
                if ( ! options.withLocals() && node.getType().isPrimitiveType() && (structuralType == StructuralEntityKinds.LOCALVAR) ) {
12!
262
                        return false;  // FIXME could be a mistake, but not too sure: what about var declaration with complex initialization (eg including an anonymous class)?
2✔
263
                }
264

265
                return super.visit(node);
4✔
266
        }
267

268
        @Override
269
        public boolean visit(VariableDeclarationStatement node) {
270
                // about the same node as VariableDeclarationExpression (but is a statement instead of an expression)
271

272
                if ( ! options.withLocals() && node.getType().isPrimitiveType() && (structuralType == StructuralEntityKinds.LOCALVAR) ) {
12!
273
                        return false;  // FIXME could be a mistake, but not too sure: what about var declaration with complex initialization (eg including an anonymous class)?
2✔
274
                }
275

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

279
        @Override
280
        public boolean visit(VariableDeclarationFragment node) {
281
                createStructuralEntity( structuralType, node, context.top());
9✔
282

283
                return true;  // e.g. with an initialization containing an anonymous class definition
2✔
284
        }
285

286
        @Override
287
        public boolean visit(SingleVariableDeclaration node) {
288
                if ( options.withLocals() || (! node.getType().isPrimitiveType()) || (structuralType != StructuralEntityKinds.LOCALVAR) ) {
12✔
289
                        createStructuralEntity( structuralType, node, context.top());
9✔
290
                }
291
                return true;  // e.g. with an initialization containing an anonymous class definition
2✔
292
        }
293

294
        public boolean visit(SuperMethodInvocation node) {
295
                dico.ensureFamixImplicitVariable(EntityDictionary.SUPER_NAME, context.topType(), context.topMethod());
11✔
296
                return super.visit(node);
4✔
297
        }
298

299
        public boolean visit(ConstructorInvocation node) {
300
                dico.ensureFamixImplicitVariable(EntityDictionary.THIS_NAME, context.topType(), context.topMethod());
11✔
301

302
                return super.visit(node);
4✔
303
        }
304

305
        public boolean visit(SuperConstructorInvocation node) {
306
                // access to "super" ???
307
                dico.ensureFamixImplicitVariable(EntityDictionary.SUPER_NAME, context.topType(), context.topMethod());
11✔
308

309
                return super.visit(node);
4✔
310
        }
311

312
        // "SomeClass.class"
313
        public boolean visit(TypeLiteral node) {
314
                org.moosetechnology.model.famix.famixjavaentities.Type javaMetaClass = dico.getFamixMetaClass(null);
5✔
315
                dico.ensureFamixAttribute(null, "class", javaMetaClass, (TWithAttributes) javaMetaClass);
9✔
316

317
                return super.visit(node);
4✔
318
        }
319

320
        // UTILITY METHODS
321

322
        private TStructuralEntity createStructuralEntity(StructuralEntityKinds structKind, VariableDeclaration varDecl, TNamedEntity owner) {
323
                TStructuralEntity fmx;
324
                IVariableBinding bnd = varDecl.resolveBinding();
3✔
325
                String name = varDecl.getName().getIdentifier();
4✔
326

327
                switch (structKind) {
5!
328
                        case PARAMETER:        fmx = dico.ensureFamixParameter(bnd, name, null, (Method) owner);                                break;
10✔
329
                        case ATTRIBUTE: fmx = dico.ensureFamixAttribute(bnd, name, (TWithAttributes) owner);                                break;
9✔
330
                        case LOCALVAR:         fmx = dico.ensureFamixLocalVariable(bnd, name, (Method) owner);                                                break;
9✔
331
                        default:                fmx = null;
×
332
                }
333

334
                if (fmx != null) {
2!
335
                        fmx.setIsStub(false);
4✔
336
                        if (options.withAnchors()) {
4!
337
                                dico.addSourceAnchor(fmx, varDecl);
6✔
338
                        }
339
                }
340

341
                return fmx;
2✔
342
        }
343

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