Skip to content

Commit

Permalink
Use symbol resolution for inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
jecisc committed Nov 5, 2024
1 parent ae64a51 commit 683da3e
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 44 deletions.
13 changes: 13 additions & 0 deletions src/Famix-Python-Importer-Tests/FamixPythonProject1Test.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -1751,6 +1751,19 @@ FamixPythonProject1Test >> testSuperclass2 [
"Compared to the first test on superclasses, the order of parsing make it important that symbol resolution works in this case."

| class |
self assert: (self model allClasses select: [ :aClass | aClass name = 'AbstractAnimal' ]) size equals: 1.
self assert: (self model allClasses select: [ :aClass | aClass name = 'Animal' ]) size equals: 1.
self assert: (self model allClasses select: [ :aClass | aClass name = 'Fish' ]) size equals: 1.

class := self classNamed: 'Animal'.

self assert: class class equals: FamixPythonClass.
self assert: class name equals: 'Animal'.
self assert: class typeContainer equals: (self packageNamed: 'root').
self assert: class superclass equals: (self classNamed: 'AbstractAnimal').
self deny: class isStub.
self deny: class superclass isStub.

class := self classNamed: 'Fish'.

self assert: class class equals: FamixPythonClass.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ FamixPythonFromImportResolvable >> entityName: anObject [
entityName := anObject
]

{ #category : 'accessing' }
FamixPythonFromImportResolvable >> identifier [

^ super identifier , ' -> ' , self entityName
]

{ #category : 'resolution' }
FamixPythonFromImportResolvable >> resolveInScope: aScope currentEntity: currentEntity [
"If we have a dot at first, we have a relative path. Else it's an absolute path"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ FamixPythonImportResolvable >> entity: anObject [
entity := anObject
]

{ #category : 'accessing' }
FamixPythonImportResolvable >> identifier [
^ self subclassResponsibility
]

{ #category : 'accessing' }
FamixPythonImportResolvable >> path [
^ path
Expand Down
71 changes: 32 additions & 39 deletions src/Famix-Python-Importer/FamixPythonImporterVisitor.class.st
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,26 @@ FamixPythonImporterVisitor >> classNamed: aName [
{ #category : 'private-entity-creation' }
FamixPythonImporterVisitor >> createClass: classDefinitionNode [

| famixClass superClasses |
famixClass := model newClass.
famixClass name: classDefinitionNode pythonClassName.

"Reject all metaclass declarations, keep only superclasses (if any)"
"TODO Handle PyTrailersNode"
superClasses := classDefinitionNode superClasses reject: [ :s | s class = PyMetaclassNode ].
superClasses do: [ :fieldAccessNode |
| superName superObject inheritance |
superName := fieldAccessNode name.
superObject := self ensureClassNamed: superName.
inheritance := model newInheritance.
inheritance
superclass: superObject;
subclass: famixClass ].

"Case for object, only if needed!"
superClasses ifEmpty: [
| inheritance object |
object := self ensureClassNamed: 'object'.
object isStub: true.
inheritance := model newInheritance.
inheritance
superclass: object yourself;
subclass: famixClass ].

| famixClass |
famixClass := model newClassNamed: classDefinitionNode pythonClassName.

(classDefinitionNode superClasses reject: [ :class | class class = PyMetaclassNode ])
ifEmpty: [
model newInheritance
superclass: (self ensureStubClassNamed: 'object');
subclass: famixClass ]
ifNotEmpty: [ :superclasses |
superclasses do: [ :superclass |
| inheritance |
inheritance := model newInheritance.
inheritance subclass: famixClass.
self
resolve: ((SRIdentifierWithNode identifier: superclass name)
expectedKind: FamixPythonClass;
notFoundReplacementEntity: [ :unresolvedSuperclass :currentEntity | self ensureStubClassNamed: unresolvedSuperclass identifier ];
yourself)
foundAction: [ :entity :currentEntity | inheritance superclass: entity ] ] ].

famixClass typeContainer: self currentEntity.

^ self setSourceAnchor: famixClass from: classDefinitionNode
Expand Down Expand Up @@ -221,18 +215,6 @@ FamixPythonImporterVisitor >> createParameter: aParameter inBehavioural: aFamixC
^ self setSourceAnchor: parameter from: aParameter
]

{ #category : 'private-entity-creation' }
FamixPythonImporterVisitor >> ensureClass: aClassNode [

^ (self classNamed: aClassNode pythonClassName) ifNil: [ self createClass: aClassNode ]
]

{ #category : 'private-entity-creation' }
FamixPythonImporterVisitor >> ensureClassNamed: aName [

^ (self classNamed: aName) ifNil: [ model newClass name: aName ]
]

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

Expand Down Expand Up @@ -264,6 +246,17 @@ FamixPythonImporterVisitor >> ensureParameter: parameter inBehavioural: aBehavio
ifNil: [ self createParameter: parameter inBehavioural: aBehavioralEntity ]
]

{ #category : 'private-entity-creation' }
FamixPythonImporterVisitor >> ensureStubClassNamed: aName [

^ model allClasses
detect: [ :class | class isStub and: [ class name = aName ] ]
ifNone: [
(model newClassNamed: aName)
isStub: true;
yourself ]
]

{ #category : 'private-entity-creation' }
FamixPythonImporterVisitor >> ensureStubContainerNamed: aString [

Expand Down Expand Up @@ -663,7 +656,7 @@ FamixPythonImporterVisitor >> visitAssignmentStatement: anAssignmentStatement [
{ #category : 'visiting' }
FamixPythonImporterVisitor >> visitClassDefinition: aClassDef [

^ self useCurrentEntity: (self ensureClass: aClassDef) during: [ super visitClassDefinition: aClassDef ]
^ self useCurrentEntity: (self createClass: aClassDef) during: [ super visitClassDefinition: aClassDef ]
]

{ #category : 'generated' }
Expand Down

0 comments on commit 683da3e

Please sign in to comment.