From e3f6906dc0a2df452e6c8525c3ecb93f3f9f1d34 Mon Sep 17 00:00:00 2001 From: fabiovandewaeter Date: Wed, 10 Jul 2024 16:23:25 +0200 Subject: [PATCH] add support for Closure --- .../FamixValueOfType.extension.st | 1 + .../FamixValueOfClosureVariable.class.st | 6 +++ .../FamixStMethod.extension.st | 6 +++ .../FamixValue2PharoVisitor.class.st | 33 ++++++++-------- .../FamixValuePharoJacksonImporter.class.st | 39 ++++++++++++++++--- 5 files changed, 63 insertions(+), 22 deletions(-) diff --git a/src/Famix-Value-Entities-Extensions/FamixValueOfType.extension.st b/src/Famix-Value-Entities-Extensions/FamixValueOfType.extension.st index 35e906d..063306f 100644 --- a/src/Famix-Value-Entities-Extensions/FamixValueOfType.extension.st +++ b/src/Famix-Value-Entities-Extensions/FamixValueOfType.extension.st @@ -59,6 +59,7 @@ FamixValueOfType >> referenceCount [ ^ attributeInObjects size + elementInCollections size + keyInDictionaries size + valueInDictionaries size + + variableInClosures size ] { #category : #'*Famix-Value-Entities-Extensions' } diff --git a/src/Famix-Value-Entities/FamixValueOfClosureVariable.class.st b/src/Famix-Value-Entities/FamixValueOfClosureVariable.class.st index 6fe4698..6b3e3f6 100644 --- a/src/Famix-Value-Entities/FamixValueOfClosureVariable.class.st +++ b/src/Famix-Value-Entities/FamixValueOfClosureVariable.class.st @@ -83,3 +83,9 @@ FamixValueOfClosureVariable >> value: anObject [ value := anObject ] + +{ #category : #generate } +FamixValueOfClosureVariable >> varName [ + + ^ name +] diff --git a/src/Famix-Value-Exporter/FamixStMethod.extension.st b/src/Famix-Value-Exporter/FamixStMethod.extension.st index d8163c0..fd98995 100644 --- a/src/Famix-Value-Exporter/FamixStMethod.extension.st +++ b/src/Famix-Value-Exporter/FamixStMethod.extension.st @@ -1,5 +1,11 @@ Extension { #name : #FamixStMethod } +{ #category : #'*Famix-Value-Exporter' } +FamixStMethod >> isSetterLax [ + + ^ self isSetter +] + { #category : #'*Famix-Value-Exporter' } FamixStMethod >> varName [ diff --git a/src/Famix-Value-Exporter/FamixValue2PharoVisitor.class.st b/src/Famix-Value-Exporter/FamixValue2PharoVisitor.class.st index d4cb92e..1f2c0a0 100644 --- a/src/Famix-Value-Exporter/FamixValue2PharoVisitor.class.st +++ b/src/Famix-Value-Exporter/FamixValue2PharoVisitor.class.st @@ -32,8 +32,9 @@ FamixValue2PharoVisitor >> ensureVisited: value [ ifPresent: [ :name | RBVariableNode named: name ] ifAbsent: [ | name node | + name := self varNameFor: value. value isOfPrimitiveType ifFalse: [ - self varNameDict at: value put: (name := self varNameFor: value) ]. + self varNameDict at: value put: name ]. node := value accept: self. value isReferencedInLoop ifTrue: [ @@ -70,20 +71,17 @@ FamixValue2PharoVisitor >> visitClassReference: aFamixValueOfClassReference [ { #category : #visiting } FamixValue2PharoVisitor >> visitClosure: object [ - | objectNode attributeNodes | - object value detect: [ :a | a attribute isNil ]. - objectNode := RBMessageNode - receiver: (RBVariableNode named: object type name) - selector: #new. - attributeNodes := (object value - collect: [ :attribute | - self visitObjectAttribute: attribute ] - as: OrderedCollection) reject: #isNil. - attributeNodes ifEmpty: [ ^ objectNode ]. - attributeNodes first receiver: objectNode. - attributeNodes add: - (RBMessageNode receiver: RBVariableNode new selector: #yourself). - ^ RBCascadeNode messages: attributeNodes + object variables do: [ :var | + | visitedVar | + visitedVar := self ensureVisited: var value. + statementBlock addNodeFirst: (RBAssignmentNode + variable: (RBVariableNode named: var name) + value: visitedVar) ]. + ^ [ RBParser parseExpression: object sourceCode ] + on: SyntaxErrorNotification + do: [ :error | "TODO: fix reflective opperation on block when metalink is installed" + Transcript crShow: error description. + error pass ] ] { #category : #visiting } @@ -95,8 +93,9 @@ FamixValue2PharoVisitor >> visitCollection: collection [ | newNode | newNode := self ensureVisited: element value. (element value isReferencedInLoop and: [ - newNode isVariable not ]) - ifTrue: [ newNode addParenthesisToVariable] + newNode isVariable not and: [ + newNode value isLiteralNode not ] ]) + ifTrue: [ newNode addParenthesisToVariable ] ifFalse: [ newNode ] ]). ^ collection type name = 'Array' ifTrue: [ collectionNode ] diff --git a/src/Famix-Value-Importer/FamixValuePharoJacksonImporter.class.st b/src/Famix-Value-Importer/FamixValuePharoJacksonImporter.class.st index d4ae209..6eaf50d 100644 --- a/src/Famix-Value-Importer/FamixValuePharoJacksonImporter.class.st +++ b/src/Famix-Value-Importer/FamixValuePharoJacksonImporter.class.st @@ -5,7 +5,8 @@ Class { 'typeKey', 'idKey', 'refKey', - 'specialTypes' + 'specialTypes', + 'closureSources' ], #category : #'Famix-Value-Importer' } @@ -87,16 +88,31 @@ FamixValuePharoJacksonImporter >> importClassReference: rawValue of: type [ { #category : #importing } FamixValuePharoJacksonImporter >> importClosure: value of: type [ - self flag: #TODO. "handle FullBlockClosure, add FamixValueOfClosure entity with `variables` relation to FamixValueOfType" - ^ self model newOfPrimitiveType - value: nil; - type: type + | closure compiledBlock source | + compiledBlock := value at: 'compiledBlock'. + source := compiledBlock + at: '@ref' + ifPresent: [ :id | closureSources at: id ] + ifAbsent: [ + closureSources + at: (self getObjectIdentity: compiledBlock) + put: (compiledBlock at: 'source') ]. + closure := self model newOfClosure + type: type; + sourceCode: source. + value at: 'vars' ifPresent: [ :vars | + vars associationsDo: [ :assoc | + closure addVariable: (self model newOfClosureVariable + name: assoc key; + value: (self importValue: assoc value)) ] ]. + ^ closure ] { #category : #importing } FamixValuePharoJacksonImporter >> importCollection: rawValue of: type [ | collection | + type name = 'Array2D' ifTrue: [ self halt ]. collection := self model newOfCollection type: type. objectDict at: (self getObjectIdentity: rawValue) put: collection. (rawValue at: '@') do: [ :rawElement | @@ -141,6 +157,14 @@ FamixValuePharoJacksonImporter >> importValue: rawValue [ ^ rawValue asPharoJacksonValueOn: self ] +{ #category : #initialization } +FamixValuePharoJacksonImporter >> initialize [ + + super initialize. + + closureSources := Dictionary new +] + { #category : #importing } FamixValuePharoJacksonImporter >> newReader [ @@ -184,6 +208,11 @@ FamixValuePharoJacksonImporter >> specialTypes [ specialTypes at: 'Set' put: [ :value :type | self importCollection: value of: type ]. + specialTypes + at: 'ConstantBlockClosure' + put: [ :value :type | self importClosure: value of: type ]. specialTypes + at: 'CleanBlockClosure' + put: [ :value :type | self importClosure: value of: type ]. specialTypes at: 'FullBlockClosure' put: [ :value :type | self importClosure: value of: type ].