Skip to content

Commit

Permalink
Manage assignation of multiple ivar via a tuple
Browse files Browse the repository at this point in the history
I refactored the way we managed the parsing of assignations to just remember if we are in the left side of an assignation and letting the visit of the children nodes create the corresponding objects
  • Loading branch information
jecisc committed Oct 30, 2024
1 parent 5144146 commit e2f14f9
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 54 deletions.
28 changes: 28 additions & 0 deletions src/Famix-Python-Importer-Tests/FamixPythonProject1Test.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,34 @@ FamixPythonProject1Test >> testInstanceVariableSourceAnchor [
self assert: variable sourceAnchor endPos equals: 361
]

{ #category : 'tests - attributes' }
FamixPythonProject1Test >> testInstanceVariablesAssignedWithATuple [

| variable |
self denyEmpty: self model allAttributes.

variable := self attributeNamed: 'ivarTuple1'.

self assert: variable class equals: FamixPythonAttribute.
self assert: variable name equals: 'ivarTuple1'.
self assert: variable parentType equals: (self classNamed: 'ClassWithTuples').
self deny: variable isClassSide.

variable := self attributeNamed: 'ivarTuple2'.

self assert: variable class equals: FamixPythonAttribute.
self assert: variable name equals: 'ivarTuple2'.
self assert: variable parentType equals: (self classNamed: 'ClassWithTuples').
self deny: variable isClassSide.

variable := self attributeNamed: 'ivarTuple3'.

self assert: variable class equals: FamixPythonAttribute.
self assert: variable name equals: 'ivarTuple3'.
self assert: variable parentType equals: (self classNamed: 'ClassWithTuples').
self deny: variable isClassSide
]

{ #category : 'tests - attributes' }
FamixPythonProject1Test >> testInstanceVariablesWithSameNameButDifferenClass [

Expand Down
79 changes: 35 additions & 44 deletions src/Famix-Python-Importer/FamixPythonImporterVisitor.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ Class {
#classTraits : 'SRTSolverUserVisitor classTrait',
#instVars : [
'model',
'rootFilePath'
'rootFilePath',
'isInLeftSideOfAssignation'
],
#category : 'Famix-Python-Importer-Visitors',
#package : 'Famix-Python-Importer',
Expand Down Expand Up @@ -232,25 +233,6 @@ FamixPythonImporterVisitor >> ensureClassNamed: aName [
^ (self classNamed: aName) ifNil: [ model newClass name: aName ]
]

{ #category : 'private-entity-creation' }
FamixPythonImporterVisitor >> ensureInstanceVariableFromAssignation: anAssignmentStatement [

| class |
class := self currentEntityOfType: FamixPythonClass.

^ (class childOfType: FamixTAttribute named: anAssignmentStatement lhs name) ifNil: [
| variable |
variable := self model newAttribute
name: anAssignmentStatement lhs name;
parentType: class;
isClassSide: false;
yourself.

"We select the lhs node because the source anchor should not be the full assignation."
self setSourceAnchor: variable from: anAssignmentStatement lhs.
variable ]
]

{ #category : 'private-entity-creation' }
FamixPythonImporterVisitor >> ensureMethod: aMethodNode [

Expand Down Expand Up @@ -333,28 +315,6 @@ FamixPythonImporterVisitor >> ensureVariable: aName localTo: aFamixEntity [
ifAbsent: [ aFamixEntity createLocalVariable: aName ]
]

{ #category : 'visiting' }
FamixPythonImporterVisitor >> ensureVariableFromAssignationStatement: anAssignmentStatement [
"I am really not sure what is the best thing to do here. So for now I'll write some code that will keep all the tests I'm adding green and when the parser will cover most cases I might come back to refactore this code into something better with less #isKindOf: or ifs."

"This is to manage global variables, class variables, local variables."
(anAssignmentStatement lhs isKindOf: PyVariableExpressionNode) ifTrue: [
^ (self currentEntity childOfType: FamixTStructuralEntity named: anAssignmentStatement lhs name) ifNil: [
| variable |
variable := self currentEntity createLocalVariable: anAssignmentStatement lhs name.
"We select the lhs node because the source anchor should not be the full assignation."
self setSourceAnchor: variable from: anAssignmentStatement lhs.
^ variable ] ].

anAssignmentStatement isInstanceVariableAssignation ifTrue: [
self assert: self currentEntity isMethod. "Maybe this could be removed when the parser is stable?"
^ self ensureInstanceVariableFromAssignation: anAssignmentStatement ].

self flag: #todo. "manage other cases."
"self error: 'We should not end up here.'"
^ nil
]

{ #category : 'accessing' }
FamixPythonImporterVisitor >> extractArgumentsInformation: aSignature [

Expand Down Expand Up @@ -510,7 +470,8 @@ FamixPythonImporterVisitor >> initialize [

super initialize.
model := FamixPythonModel new name: 'default Python Model'.
self initialiseSolver
self initialiseSolver.
isInLeftSideOfAssignation := false "In Python variables are created during their assignation. So it is good to know if some nodes are visited during this assignation."
]

{ #category : 'private - searching' }
Expand Down Expand Up @@ -692,7 +653,11 @@ FamixPythonImporterVisitor >> unknownImportedNamed: aString [
{ #category : 'visiting' }
FamixPythonImporterVisitor >> visitAssignmentStatement: anAssignmentStatement [

^ self useCurrentEntity: (self ensureVariableFromAssignationStatement: anAssignmentStatement) during: [ super visitAssignmentStatement: anAssignmentStatement ]
| oldValue |
oldValue := isInLeftSideOfAssignation.
isInLeftSideOfAssignation := true.
[ self acceptNode: anAssignmentStatement lhs ] ensure: [ isInLeftSideOfAssignation := oldValue ].
^ super visitAssignmentStatement: anAssignmentStatement
]

{ #category : 'visiting' }
Expand All @@ -703,6 +668,23 @@ FamixPythonImporterVisitor >> visitClassDefinition: aClassDef [

{ #category : 'generated' }
FamixPythonImporterVisitor >> visitFieldAccessExpression: aFieldAccessExpression [
"If the receiver is self in an assignation then we have an assignation to an instance variable"

(isInLeftSideOfAssignation and: [ aFieldAccessExpression receiver name = #self ]) ifTrue: [
| class |
class := self currentEntityOfType: FamixPythonClass.

^ (class childOfType: FamixTAttribute named: aFieldAccessExpression name) ifNil: [
| variable |
variable := self model newAttribute
name: aFieldAccessExpression name;
parentType: class;
isClassSide: false;
yourself.

"We select the lhs node because the source anchor should not be the full assignation."
self setSourceAnchor: variable from: aFieldAccessExpression.
variable ] ].

^ aFieldAccessExpression source
]
Expand Down Expand Up @@ -821,6 +803,15 @@ FamixPythonImporterVisitor >> visitString: aStringNode [

{ #category : 'visiting' }
FamixPythonImporterVisitor >> visitVariableExpression: aVariableExpression [
"This node is used in multiple situations. If it is in an assignation we need to check if the variable we assign is created. Other uses can be for example in an import, in this case we want to only return the name."

isInLeftSideOfAssignation ifTrue: [
(self currentEntity childOfType: FamixTStructuralEntity named: aVariableExpression name) ifNil: [
| variable |
variable := self currentEntity createLocalVariable: aVariableExpression name.
"We select the lhs node because the source anchor should not be the full assignation."
self setSourceAnchor: variable from: aVariableExpression.
^ variable ] ].

^ aVariableExpression name
]
10 changes: 0 additions & 10 deletions src/Famix-Python-Importer/PyAssignmentStatementNode.extension.st

This file was deleted.

0 comments on commit e2f14f9

Please sign in to comment.