Skip to content

Commit

Permalink
Merge bf47b28
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiovandewaeter committed Jul 3, 2024
2 parents d55b885 + bf47b28 commit 01df2dd
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,11 @@ FamixValueOfObjectAttribute >> mooseNameOn: aStream [
ifNil: [ '<attribute>' ]) << $=.
value printValueOn: aStream
]

{ #category : #'*Famix-Value-Entities-Extensions' }
FamixValueOfObjectAttribute >> varName [

^ self attribute
ifNotNil: [ :attribute | attribute name ]
ifNil: [ value varName ]
]
8 changes: 0 additions & 8 deletions src/Famix-Value-Entities/FamixValueOfObjectAttribute.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,3 @@ FamixValueOfObjectAttribute >> value: anObject [
<generated>
value := anObject
]

{ #category : #generate }
FamixValueOfObjectAttribute >> varName [

^ self attribute
ifNotNil: [ :attribute | attribute name ]
ifNil: [ value varName ]
]
21 changes: 0 additions & 21 deletions src/Famix-Value-Entities/FamixValueOfType.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -70,27 +70,6 @@ FamixValueOfType >> addValueInDictionary: anObject [
^ self valueInDictionaries add: anObject
]

{ #category : #'ston persistence' }
FamixValueOfType >> asJsonString [
"Currently does not work. Ideas:
- Find a way to serialize any object while handling circular dependencies.
- Use the json stored in the root value to read it into raw objects and traverse the path to this value."

self flag: #TODO.
^ self asNeoJSONObject asString
]

{ #category : #'ston persistence' }
FamixValueOfType >> asNeoJSONObject [

self flag: #TODO. "see #asJsonString"
^ self typedEntity
ifNotNil: [ "at root"
NeoJSONObject fromString: (self cacheAt: #json ifAbsent: '{}') ]
ifNil: [ "how to iterate until root?"
NeoJSONObject fromString: (self cacheAt: #json ifAbsent: '{}') ]
]

{ #category : #accessing }
FamixValueOfType >> attributeInObjects [
"Relation named: #attributeInObjects type: #FamixValueOfObjectAttribute opposite: #value"
Expand Down
5 changes: 4 additions & 1 deletion src/Famix-Value-Exporter/FASTBuilder.class.st
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"
I am a helper for the `FamixValue2ASTVisitor` hierarchy of classes to build AST.
"
Class {
#name : #FASTBuilder,
#superclass : #Object,
#instVars : [
'model'
],
#category : #'Famix-Value-Exporter'
#category : #'Famix-Value-Exporter-Helpers'
}

{ #category : #testing }
Expand Down
5 changes: 4 additions & 1 deletion src/Famix-Value-Exporter/FASTJavaBuilder.class.st
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"
I am used to handle Java type references and imports.
"
Class {
#name : #FASTJavaBuilder,
#superclass : #FASTBuilder,
#instVars : [
'typeNameDictionary'
],
#category : #'Famix-Value-Exporter'
#category : #'Famix-Value-Exporter-Helpers'
}

{ #category : #ast }
Expand Down
2 changes: 1 addition & 1 deletion src/Famix-Value-Exporter/FamixValue2ASTVisitor.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Class {
'id',
'statementBlock'
],
#category : #'Famix-Value-Exporter'
#category : #'Famix-Value-Exporter-Visitors'
}

{ #category : #testing }
Expand Down
104 changes: 23 additions & 81 deletions src/Famix-Value-Exporter/FamixValue2FASTJavaVisitor.class.st
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"
A visitor for exporting a FamixValue model to FASTJava.
A visitor to export a FamixValue model to FASTJava.
The generated code is a block statement with a variable declared for each value.
Object attributes are initialized by finding the corresponding setters.
Collections and Dictionaries are constructed with the `add(element)` and `put(key, value)` methods respectively.
Collections and Dictionaries are constructed with the methods `add(element)` and `put(key, value)` respectively.
When exporting a `FamixValueOfObjectAttribute`, if the setter for its `FamixTAttribute` cannot be found, they are set using the Java Reflection API.
All attributes that fall in this category are added as `markedForReflection`.
When exporting a `FamixValueOfObjectAttribute`, if the setter for its `FamixTAttribute` cannot be found, it is set using the Java Reflection API.
All attributes that fall into this category are added as `markedForReflection`.
"
Class {
#name : #FamixValue2FASTJavaVisitor,
Expand All @@ -16,10 +16,9 @@ Class {
'markedForReflection',
'constructorCache',
'staticAttributesCache',
'objectExportStrategy',
'setterCache'
'objectExportStrategy'
],
#category : #'Famix-Value-Exporter'
#category : #'Famix-Value-Exporter-Visitors'
}

{ #category : #private }
Expand All @@ -37,8 +36,10 @@ FamixValue2FASTJavaVisitor >> addAttributesFrom: object asArgumentsTo: newExpres
object value
detect: [ :objAttribute | "find the matching value attribute"
objAttribute attribute == paramAttribute ]
ifFound: [ :objAttribute |
self makeVariableExpression: objAttribute value ]
ifFound: [ :objAttribute | "dispatch for var naming context"
objectExportStrategy
makeVariableExpression: objAttribute value
on: self ]
ifNone: [ "the object does not have the attribute set"
paramAttribute declaredType asFASTJavaDefaultValueOn:
self model ] ]) ]
Expand Down Expand Up @@ -72,21 +73,16 @@ FamixValue2FASTJavaVisitor >> constructObject: object [
FamixValue2FASTJavaVisitor >> filterAttributesToSet: attributes for: object [
"No need to set attributes that are set in the constructor."

^ (setterCache at: object type ifAbsentPut: [
| famixAttributes |
famixAttributes := attributes collect: [ :attribute |
attribute attribute ].
constructorCache
at: object type
ifPresent: [ :constructor |
constructorCache
at: constructor
ifPresent: [ :constructorAttributes |
famixAttributes difference: constructorAttributes ]
ifAbsent: [ famixAttributes ] ]
ifAbsent: [ famixAttributes ] ]) ifNotEmpty: [ :famixAttributes |
attributes select: [ :attribute |
famixAttributes includes: attribute attribute ] ]
^ constructorCache
at: object type
ifPresent: [ :constructor |
constructorCache
at: constructor
ifPresent: [ :constructorAttributes |
attributes reject: [ :attribute |
constructorAttributes includes: attribute attribute ] ]
ifAbsent: [ attributes ] ]
ifAbsent: [ attributes ]
]

{ #category : #private }
Expand Down Expand Up @@ -136,7 +132,6 @@ FamixValue2FASTJavaVisitor >> findStaticAttributeMatching: object [
FamixValue2FASTJavaVisitor >> initialize [

constructorCache := IdentityDictionary new.
setterCache := IdentityDictionary new.
staticAttributesCache := IdentityDictionary new
]

Expand Down Expand Up @@ -191,49 +186,7 @@ FamixValue2FASTJavaVisitor >> makeHelperClass [
expression:
(model newNewExpression type:
(model newClassTypeExpression typeName:
(model newTypeName name: 'ObjectMapper')))) }).
(model newMethodEntity
typeParameters:
{ (model newTypeParameterExpression name: 'T') };
type:
(model newClassTypeExpression typeName:
(model newTypeName name: 'T'));
name: 'deserialize';
parameters: {
(model newParameter
variable: (model newVariableExpression name: 'json');
type: (model newClassTypeExpression typeName:
(model newTypeName name: 'String'))).
(model newParameter
variable: (model newVariableExpression name: 'clazz');
type: (model newClassTypeExpression
typeName: (model newTypeName name: 'Class');
arguments: { (model newClassTypeExpression typeName:
(model newTypeName name: 'T')) })) };
modifiers: {
(model newModifier token: 'public').
(model newModifier token: 'static') };
statementBlock: (model newStatementBlock statements: {
(model newTryCatchStatement
try: (model newStatementBlock statements:
{ (model newReturnStatement expression:
(model newMethodInvocation
receiver: (model newIdentifier name: 'mapper');
name: 'readValue';
arguments: {
(model newVariableExpression name: 'json').
(model newVariableExpression name: 'clazz') })) });
catches: { (model newCatchPartStatement
catchedTypes:
{ (model newClassTypeExpression typeName:
(model newTypeName name: 'IOException')) };
body: (model newStatementBlock statements:
{ (model newExpressionStatement expression:
(model newMethodInvocation
receiver: (model newIdentifier name: 'e');
name: 'printStackTrace')) });
parameter: (model newVariableExpression name: 'e')) }).
(model newReturnStatement expression: model newNullLiteral) })) }
(model newTypeName name: 'ObjectMapper')))) }) }
]

{ #category : #ast }
Expand Down Expand Up @@ -455,20 +408,9 @@ FamixValue2FASTJavaVisitor >> visitObjectOfRegularType: object [

{ #category : #visiting }
FamixValue2FASTJavaVisitor >> visitObjectStub: object [
"Previously tried to recreate stubs by deserializing their JSON representation, but getting a correct JSON string is a challenge."

self statementBlock addStatement: (self model newVarDeclStatement
type: (object asFASTJavaTypeExpressionOn: self);
addDeclarator: (self model newVariableDeclarator
variable: (self makeVariableExpression: object);
expression: (model newMethodInvocation
name: 'deserialize';
arguments: {
(model newStringLiteral primitiveValue:
object asJsonString).
(model newClassProperty
type: (object asFASTJavaTypeExpressionOn: self);
fieldName: 'class') }));
yourself)
self shouldBeImplemented
]

{ #category : #visiting }
Expand Down
7 changes: 4 additions & 3 deletions src/Famix-Value-Exporter/FamixValue2PharoVisitor.class.st
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"
A visitor for exporting a FamixValue model to the Pharo AST, see `RBEntity` and `RBNode`.
A visitor for exporting a FamixValue model to the Pharo AST, see `RBNode`.
Object attributes are initialized by finding the corresponding setters.
Collections and Dictionaries are constructed with the `withAll:` class method.
Collections are constructed using the `withAll:` class method.
Dictionaries are constructed using the `newFrom:` class method.
"
Class {
#name : #FamixValue2PharoVisitor,
#superclass : #FamixValue2ASTVisitor,
#category : #'Famix-Value-Exporter'
#category : #'Famix-Value-Exporter-Visitors'
}

{ #category : #visiting }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"
I am a strategy for exporting objects used by the `FamixValue2ASTVisitor` hierarchy of classes.
Objects can be complex to recreate due to deep nesting and circular dependencies, resulting in a lot of code. My subclasses define where that code goes.
"
Class {
#name : #FamixValueAbstractObjectExportStrategy,
#superclass : #Object,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"
I generate the code to recreate objects in helper functions.
For each object, a dedicated function is generated that takes no arguments and returns the recreated object.
"
Class {
#name : #FamixValueHelperObjectExportStrategy,
#superclass : #FamixValueAbstractObjectExportStrategy,
Expand Down Expand Up @@ -133,3 +137,11 @@ FamixValueHelperObjectExportStrategy >> makeSetterInvocationsFor: attributes on:
named: attribute varName ]
ifNil: [ visitor makeReflectionSetterInvocation: attribute ] ]
]

{ #category : #ast }
FamixValueHelperObjectExportStrategy >> makeVariableExpression: value on: visitor [
"Used when constructing an object to correctly name the argument variable.
For helpers, the var name is the same as the helper method parameter."

^ visitor model newVariableExpression name: value varName
]
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"
I recreate objects inline.
The context of the visitor will contain the code to recreate the objects.
"
Class {
#name : #FamixValueInlineObjectExportStrategy,
#superclass : #FamixValueAbstractObjectExportStrategy,
Expand All @@ -11,3 +15,11 @@ FamixValueInlineObjectExportStrategy >> export: object on: visitor [
(visitor filterAttributesToSet: object relevantAttributes for: object)
do: [ :attribute | visitor visitObjectAttribute: attribute ]
]

{ #category : #ast }
FamixValueInlineObjectExportStrategy >> makeVariableExpression: value on: visitor [
"Used when constructing an object to correctly name the argument variable.
When inline, the visitor can handle naming the variable on its own."

^ visitor makeVariableExpression: value
]

0 comments on commit 01df2dd

Please sign in to comment.