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

moosetechnology / Famix-Value / 11557114099

28 Oct 2024 03:20PM UTC coverage: 24.281% (-0.9%) from 25.209%
11557114099

push

github

Gabriel-Darbord
Major Java update
Model:
- rename relation TType's relation to ValueEntity from `values` to `valueInstances`, to avoid clash with TTypedEntity's relation to ValueEntity (because of FamixJavaParameterType which uses both)

Importer:
- handle class references
- handle enums
- do not remove @type and @id keys when iterating over raw values (that made debugging difficult)
- handle field descriptors with anonymous classes (using `$` as separator instead of a dot)
- search for attributes on parametric classes by asking the generic superclass
- infer using concrete parameter types
- read declared type array dimensions
- implicit switch from int to long when out of bounds

Exporter:
- handle class references
- throw error when reaching broken state instead of persevering and generating uncompilable code
- correctly export qualified names of any class using dispatch (there were problems with inner classes)
- when finding accessed attributes in a method, handle case where variable is the receiver
- add `withSubHierarchy` to also find interface implementors
- work around VerveineJ problems by adding nil checks where they should normally never occur
- better exception handling when using reflection
- more polymorphism on UnknownType
- add explicit cast to disambiguate between int and long when calling helpers
- WIP handling of exceptions thrown by constructors and accessors

Types:
- handle `java.util.Calendar`

13 of 207 new or added lines in 11 files covered. (6.28%)

3 existing lines in 2 files now uncovered.

760 of 3130 relevant lines covered (24.28%)

0.24 hits per line

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

0.0
/src/Famix-Value-Importer/FamixValueJavaJacksonImporter.class.st
1
"
2
I am a FamixValue importer for Java.
3
I understand the JSON format of the Jackson library up to and including version `2.10`.
4
The ObjectMapper must be configured to associate each value with the fully qualified name of its type.
5

6
```language=text
7
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = ""@id"")
8
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = ""@type"")
9
interface MixIn {}
10

11
new ObjectMapper().addMixIn(Object.class, MixIn.class);
12
```
13
"
14
Class {
15
        #name : 'FamixValueJavaJacksonImporter',
16
        #superclass : 'FamixValueAbstractImporter',
17
        #instVars : [
18
                'typeKey',
19
                'idKey',
20
                'specialTypes'
21
        ],
22
        #category : 'Famix-Value-Importer',
23
        #package : 'Famix-Value-Importer'
24
}
25

26
{ #category : 'enumerating' }
27
FamixValueJavaJacksonImporter >> getDefaultUnknownType [
×
28

×
29
        ^ self getUnknownTypeNamed: 'Object'
×
30
]
×
31

32
{ #category : 'enumerating' }
33
FamixValueJavaJacksonImporter >> getObjectIdentity: rawObject [
×
34
        "Keep track of objects by using the id given by Jackson.
×
35
        References to previously seen objects are serialized by using this id."
×
36

×
NEW
37
        ^ rawObject at: self idKey ifAbsent: nil
×
38
]
×
39

40
{ #category : 'enumerating' }
41
FamixValueJavaJacksonImporter >> getObjectType: rawObject [
×
42

×
NEW
43
        ^ rawObject at: self typeKey ifAbsent: nil
×
44
]
×
45

46
{ #category : 'accessing' }
47
FamixValueJavaJacksonImporter >> idKey [
×
48

×
49
        ^ idKey ifNil: [ idKey := '@id' ]
×
50
]
×
51

52
{ #category : 'accessing' }
53
FamixValueJavaJacksonImporter >> idKey: aString [
×
54

×
55
        idKey := aString
×
56
]
×
57

58
{ #category : 'importing' }
59
FamixValueJavaJacksonImporter >> importObjectAttribute: rawValue of: type named: name [
×
60

×
NEW
61
        | attribute inference |
×
62
        type isInterface ifTrue: [
×
63
                Error signal:
×
64
                        'Cannot find attributes in interfaces. Signaled for attribute `'
×
65
                        , name , '` and interface `' , type name , '`.' ].
×
NEW
66
        (attribute := type findAttributeNamed: name)
×
NEW
67
                ifNil: [
×
NEW
68
                        FamixValueImporterError signal:
×
NEW
69
                                'Attribute `' , name , '` not found in hierarchy of `'
×
NEW
70
                                , type mooseName , '`' ]
×
NEW
71
                ifNotNil: [ "Skip transient attributes."
×
NEW
72
                        attribute isTransient ifTrue: [ ^ nil ] ].
×
NEW
73

×
NEW
74
        "If the attribute type is a TypeParameter, and the runtime type is a concretization
×
NEW
75
        => inference is the concretization of the TypeParameter"
×
NEW
76
        inference := nil.
×
NEW
77
        attribute ifNotNil: [
×
NEW
78
                attribute declaredType ifNotNil: [ :declaredType |
×
NEW
79
                        declaredType isParameterType
×
NEW
80
                                ifFalse: [ "not parametric" inference := declaredType ]
×
NEW
81
                                ifTrue: [
×
NEW
82
                                        declaredType concretizations
×
NEW
83
                                                detect: [ :paramType |
×
NEW
84
                                                paramType concretizations first concreteEntity == type ]
×
NEW
85
                                                ifFound: [ :paramType |
×
NEW
86
                                                inference := paramType concreteParameter ] ] ] ].
×
NEW
87

×
NEW
88
        (rawValue isCollection and: [
×
NEW
89
                 inference isNotNil and: [ self isPrimitiveType: inference ] ])
×
NEW
90
                ifTrue: [
×
NEW
91
                        ^ self model newOfObjectAttribute
×
NEW
92
                                  value: (self
×
NEW
93
                                                   importCollection: rawValue
×
NEW
94
                                                   of: ((FamixValueJavaArray wrapping: inference) dimensions:
×
NEW
95
                                                                            (self readDimensionsOfAttribute: attribute)));
×
NEW
96
                                  attribute: attribute ].
×
NEW
97

×
NEW
98
        ^ self withTypeInference: inference do: [
×
NEW
99
                  self model newOfObjectAttribute
×
NEW
100
                          value: (self importValue: rawValue);
×
NEW
101
                          attribute: attribute ]
×
UNCOV
102
]
×
103

104
{ #category : 'importing' }
105
FamixValueJavaJacksonImporter >> importSpecialObject: rawValue of: type [
×
106
        "Some objects have special rules for serialization.
×
107
        They should have a corresponding type wrapper that knows how to handle them."
×
108

×
109
        self specialTypes
×
110
                at: type mooseNameWithDots
×
111
                ifPresent: [ :typeWrapper |
×
112
                        ^ typeWrapper import: rawValue wrapping: type on: self ].
×
113
        ^ nil
×
114
]
×
115

116
{ #category : 'importing' }
117
FamixValueJavaJacksonImporter >> importTypeReference: rawValue of: type [
×
118
        "The type has already been loaded during the inference.
×
119
        The raw value contains the fully qualified name of the referenced class."
×
120

×
121
        ^ self model newOfTypeReference
×
122
                  value: (self loadTypeNamed: rawValue);
×
123
                  type: type
×
124
]
×
125

126
{ #category : 'importing' }
127
FamixValueJavaJacksonImporter >> importValue: rawValue [
×
128
        "Import a raw value, which has been parsed from JSON in Jackson format.
×
129
        It can be: nil, boolean, integer, string, array or dictionary."
×
130

×
131
        ^ rawValue asJavaJacksonValueOn: self
×
132
]
×
133

134
{ #category : 'importing' }
135
FamixValueJavaJacksonImporter >> importValueFromList: rawValue of: type [
×
136
        "Jackson can serialize different types of values in a list, so we need to find out which it is."
×
137

×
138
        rawValue isCollection ifTrue: [
×
139
                ^ self importCollection: rawValue of: type ].
×
140
        type isUnknownType ifTrue: [
×
141
                ^ self model newOfUnknownType
×
142
                          value: rawValue;
×
143
                          type: type ].
×
144
        (type usesFamixTrait: FamixTEnum) ifTrue: [
×
145
                ^ self importEnumValue: rawValue of: type ].
×
146
        (self isPrimitiveType: type) ifTrue: [
×
147
                ^ self model newOfPrimitiveType
×
148
                          value: rawValue;
×
149
                          type: type ].
×
150
        type isClass ifTrue: [ "might be a special object"
×
151
                (self importSpecialObject: rawValue of: type) ifNotNil: [ :object |
×
152
                        ^ object ] ].
×
153
        self error: 'Unknown type: ' , type mooseNameWithDots
×
154
]
×
155

156
{ #category : 'private - utility' }
157
FamixValueJavaJacksonImporter >> isPrimitiveType: type [
×
158

×
159
        ^ type isPrimitiveType or: [ "Classes wrapping primitives are also considered primitives."
×
NEW
160
                  type isClass and: [ type isPrimitiveWrapper ] ]
×
NEW
161
]
×
162

163
{ #category : 'importing' }
NEW
164
FamixValueJavaJacksonImporter >> iterate: rawValue keysAndValuesDo: aBlock [
×
NEW
165

×
NEW
166
        rawValue keysAndValuesDo: [ :key :value |
×
NEW
167
                (key = self idKey or: [ key = self typeKey ]) ifFalse: [
×
NEW
168
                        aBlock value: key value: value ] ]
×
UNCOV
169
]
×
170

171
{ #category : 'parsing' }
172
FamixValueJavaJacksonImporter >> parseList: serializedValues [
×
173

×
174
        | rawValues |
×
175
        rawValues := super parseList: serializedValues.
×
176
        ^ rawValues hasJavaJacksonTypeInformation
×
177
                  ifTrue: [ "ignore the type information of the top level list."
×
NEW
178
                          ^ rawValues "TODO only a specific version of jackson does this, investigate"
×
NEW
179
                          "rawValues at: 2" ]
×
180
                  ifFalse: [ rawValues ]
×
181
]
×
182

183
{ #category : 'private - utility' }
NEW
184
FamixValueJavaJacksonImporter >> readDimensionsOfAttribute: attribute [
×
NEW
185

×
NEW
186
        | source index char dimensions |
×
NEW
187
        source := WriteStream on: ''.
×
NEW
188
        attribute sourceAnchor fileReference readStreamDo: [ :rs |
×
NEW
189
                1 to: attribute sourceAnchor endPos do: [ :i |
×
NEW
190
                source nextPut: rs next ].
×
NEW
191
                "read from endPos until:
×
NEW
192
                - next declarator, eg. `int a, b`
×
NEW
193
                - end of definition, eg. `int a;`
×
NEW
194
                - initialization, eg. `int a = 1`"
×
NEW
195
                [ ',;=' includes: (source nextPut: rs next) ] whileFalse.
×
NEW
196
                source := source contents ].
×
NEW
197
        index := source size.
×
NEW
198
        dimensions := 0.
×
NEW
199
        [ "read backwards until:
×
NEW
200
        - block opener, eg. `class { int a;`
×
NEW
201
        - block closer, eg. `int f(){} int a;`
×
NEW
202
        - end of statement, eg. int b; int a;"
×
NEW
203
        char := source at: (index := index - 1).
×
NEW
204
        char == $]
×
NEW
205
                ifTrue: [
×
NEW
206
                        dimensions := dimensions + 1.
×
NEW
207
                        false ]
×
NEW
208
                ifFalse: [ '{};' includes: char ] ] whileFalse.
×
NEW
209
        ^ dimensions
×
NEW
210
]
×
211

212
{ #category : 'accessing' }
213
FamixValueJavaJacksonImporter >> specialTypes [
×
214

×
215
        ^ specialTypes ifNil: [
×
216
                  (specialTypes := Dictionary new)
×
NEW
217
                          at: 'java.util.Calendar' put: FamixValueJavaCalendar;
×
218
                          at: 'java.util.Date' put: FamixValueJavaDate;
×
219
                          at: 'java.sql.Date' put: FamixValueJavaSQLDate;
×
220
                          at: 'java.sql.Timestamp' put: FamixValueJavaDate;
×
221
                          yourself ]
×
222
]
×
223

224
{ #category : 'accessing' }
225
FamixValueJavaJacksonImporter >> typeKey [
×
226

×
227
        ^ typeKey ifNil: [ typeKey := '@type' ]
×
228
]
×
229

230
{ #category : 'accessing' }
231
FamixValueJavaJacksonImporter >> typeKey: aString [
×
232

×
233
        typeKey := aString
×
234
]
×
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