From 6da7a2c9b568fa05809c868e5d9e7d825d370136 Mon Sep 17 00:00:00 2001 From: yann Date: Sat, 18 May 2024 19:52:51 -0400 Subject: [PATCH] More tests about attributes and variables --- src/MoosePy/MSEPythonImporterTest.class.st | 175 +++++++++++++++--- .../MSEPythonToFamixImporterVisitor.class.st | 18 +- src/MoosePy/ManifestMoosePy.class.st | 15 ++ 3 files changed, 175 insertions(+), 33 deletions(-) create mode 100644 src/MoosePy/ManifestMoosePy.class.st diff --git a/src/MoosePy/MSEPythonImporterTest.class.st b/src/MoosePy/MSEPythonImporterTest.class.st index 457ac9f..62d8bb3 100644 --- a/src/MoosePy/MSEPythonImporterTest.class.st +++ b/src/MoosePy/MSEPythonImporterTest.class.st @@ -134,6 +134,34 @@ def greet(name): self assert: anno annotationType name equals: 'classmethod' ] +{ #category : #'tests - attributes' } +MSEPythonImporterTest >> testClassAttributes [ + + | classA classB | + importer accept: (self parseCode: ' +class A: + a = 1 + b = 2 +class B: + a = 2 +'). + + self + assert: (importer model allWithType: FamixPythonClass) size + equals: 3. + + classA := importer classNamed: 'A'. + self assert: classA isNotNil. + self assert: classA attributes size equals: 2. + self assert: classA attributes first name equals: 'a'. + self assert: classA attributes second name equals: 'b'. + + classB := importer classNamed: 'B'. + self assert: classB isNotNil. + self assert: classB attributes size equals: 1. + self assert: classB attributes first name equals: 'a' +] + { #category : #'tests - classes' } MSEPythonImporterTest >> testClassIsInModel [ @@ -572,6 +600,42 @@ from maths import add, subtract equals: 'maths' ] +{ #category : #'tests - attributes' } +MSEPythonImporterTest >> testInstanceAttributes [ + + | classA classB localVariableA localVariableB | + importer accept: (self parseCode: ' +class A: + def foo(self): + a = 1 + b = 2 +class B: + a = 2 +'). + + self + assert: (importer model allWithType: FamixPythonClass) size + equals: 3. + + classA := importer classNamed: 'A'. + self assert: classA isNotNil. + self assert: classA attributes size equals: 0. + self assert: classA methods first localVariables size equals: 2. + + localVariableA := classA methods first localVariables first. + self assert: localVariableA isNotNil. + self assert: localVariableA name equals: 'a'. + + localVariableB := classA methods first localVariables second. + self assert: localVariableB isNotNil. + self assert: localVariableB name equals: 'b'. + + classB := importer classNamed: 'B'. + self assert: classB isNotNil. + self assert: classB attributes size equals: 1. + self assert: classB attributes first name equals: 'a' +] + { #category : #'tests - module' } MSEPythonImporterTest >> testInvocation [ @@ -821,8 +885,66 @@ MSEPythonImporterTest >> testParseWithFile [ self assert: doc filename basename equals: 'sprite_collect_blocks.py' ] +{ #category : #tests } +MSEPythonImporterTest >> testSameAnnotationType [ + + importer accept: (self parseCode: ' +@classmethod +def greet(name): + print ''Hello'', name +@classmethod +def goodbye(name): + print ''Bye-bye'', name +'). + + self assert: (importer model allWithType: FamixPythonAnnotationType) size equals: 1. + self + assert: (importer functionNamed: 'greet') annotationInstances anyOne annotationType + equals: (importer functionNamed: 'goodbye') annotationInstances anyOne annotationType +] + +{ #category : #'tests - extensions' } +MSEPythonImporterTest >> testShiftEqualIsAssignment [ + + | smaccAST | + smaccAST := self parseCode: ' +x >>= 12 +'. + + self assert: smaccAST statements anyOne stmts anyOne isAssignment +] + +{ #category : #'tests - metaclasses' } +MSEPythonImporterTest >> testSingleClasSingleFQNMetaclass [ + + | classA classMeta classAMeta | + importer accept: (self parseCode: ' +class Meta(type): + pass +class A(metaclass=pygame.sprite.Sprite): + def foo: + pass +'). + + self + assert: (importer model allWithType: FamixPythonClass) size + equals: 5. + + classA := importer classNamed: 'A'. + self assert: classA isNotNil. + self assert: (classA superInheritances first target name) equals: 'object'. + + classMeta := importer classNamed: 'Meta'. + self assert: classMeta isNotNil. + self assert: (classMeta superInheritances first target name) equals: 'type'. + + classAMeta := classA metaclass. + self assert: classAMeta isNotNil. + self assert: classAMeta name equals: 'pygame.sprite.Sprite' +] + { #category : #'tests - metaclasses' } -MSEPythonImporterTest >> testSSingleClassExplicitSuperclass [ +MSEPythonImporterTest >> testSingleClassExplicitSuperclass [ | classS classA | importer accept: (self parseCode: ' @@ -847,7 +969,26 @@ class A(S): ] { #category : #'tests - metaclasses' } -MSEPythonImporterTest >> testSSingleClassingleMetaclass [ +MSEPythonImporterTest >> testSingleClassFQNSuperclass [ + + | classA classMeta classAMeta | + importer accept: (self parseCode: ' +class A(pygame.sprite.Sprite): + def foo: + pass +'). + + self + assert: (importer model allWithType: FamixPythonClass) size + equals: 2. + + classA := importer classNamed: 'A'. + self assert: classA isNotNil. + self assert: (classA superInheritances first target name) equals: 'pygame.sprite.Sprite'. +] + +{ #category : #'tests - metaclasses' } +MSEPythonImporterTest >> testSingleClassingleMetaclass [ | classA classMeta classAMeta | importer accept: (self parseCode: ' @@ -875,33 +1016,19 @@ class A(metaclass=Meta): self assert: classAMeta name equals: 'Meta' ] -{ #category : #tests } -MSEPythonImporterTest >> testSameAnnotationType [ +{ #category : #'tests - metaclasses' } +MSEPythonImporterTest >> testTwoClassesObjectShouldNotBeDuplicated [ importer accept: (self parseCode: ' -@classmethod -def greet(name): - print ''Hello'', name -@classmethod -def goodbye(name): - print ''Bye-bye'', name +class A: + pass +class B: + pass '). - self assert: (importer model allWithType: FamixPythonAnnotationType) size equals: 1. self - assert: (importer functionNamed: 'greet') annotationInstances anyOne annotationType - equals: (importer functionNamed: 'goodbye') annotationInstances anyOne annotationType -] - -{ #category : #'tests - extensions' } -MSEPythonImporterTest >> testShiftEqualIsAssignment [ - - | smaccAST | - smaccAST := self parseCode: ' -x >>= 12 -'. - - self assert: smaccAST statements anyOne stmts anyOne isAssignment + assert: (importer model allWithType: FamixPythonClass) size + equals: 3 ] { #category : #'tests - module' } diff --git a/src/MoosePy/MSEPythonToFamixImporterVisitor.class.st b/src/MoosePy/MSEPythonToFamixImporterVisitor.class.st index a91b1ea..22e4be2 100644 --- a/src/MoosePy/MSEPythonToFamixImporterVisitor.class.st +++ b/src/MoosePy/MSEPythonToFamixImporterVisitor.class.st @@ -111,11 +111,7 @@ MSEPythonToFamixImporterVisitor >> createClass: smaCCClass [ superClasses do: [ :s | | superName superObject inheritance | superName := s name. - superObject := self classNamed: superName. - superObject ifNil: [ - superObject := model newClass - name: superName; - stub: true ]. + superObject := self ensureClassNamed: superName. inheritance := model newInheritance. inheritance superclass: superObject; @@ -124,11 +120,9 @@ MSEPythonToFamixImporterVisitor >> createClass: smaCCClass [ "Case for object, only if needed!" superClasses ifEmpty: [ | inheritance object | + object := self ensureClassNamed: 'object'. + object isStub: true. inheritance := model newInheritance. - object := model newClass. - object - name: 'object'; - isStub: true. inheritance superclass: object yourself; subclass: famixClass ]. @@ -275,6 +269,12 @@ MSEPythonToFamixImporterVisitor >> ensureClass: aClassNode [ self createClass: aClassNode ] ] +{ #category : #'private-entity-creation' } +MSEPythonToFamixImporterVisitor >> ensureClassNamed: aName [ + + ^ (self classNamed: aName) ifNil: [ model newClass name: aName ] +] + { #category : #'private-entity-creation' } MSEPythonToFamixImporterVisitor >> ensureFunction: aFunctionNode [ diff --git a/src/MoosePy/ManifestMoosePy.class.st b/src/MoosePy/ManifestMoosePy.class.st new file mode 100644 index 0000000..aabad55 --- /dev/null +++ b/src/MoosePy/ManifestMoosePy.class.st @@ -0,0 +1,15 @@ +" +Please describe the package using the class comment of the included manifest class. The manifest class also includes other additional metadata for the package. These meta data are used by other tools such as the SmalllintManifestChecker and the critics Browser +" +Class { + #name : #ManifestMoosePy, + #superclass : #PackageManifest, + #category : #'MoosePy-Manifest' +} + +{ #category : #'code-critics' } +ManifestMoosePy class >> ruleLongMethodsRuleV1FalsePositive [ + + + ^ #(#(#(#RGMethodDefinition #(#MSEPythonToFamixImporterVisitor #createClass: #false)) #'2024-05-16T22:52:10.257-04:00') ) +]