diff --git a/src/Famix-Value-Entities-Extensions/FamixValueUnknownType.extension.st b/src/Famix-Value-Entities-Extensions/FamixValueUnknownType.extension.st index 7d1898d..6bfb87c 100644 --- a/src/Famix-Value-Entities-Extensions/FamixValueUnknownType.extension.st +++ b/src/Famix-Value-Entities-Extensions/FamixValueUnknownType.extension.st @@ -13,7 +13,7 @@ FamixValueUnknownType >> concreteTypeName [ ] { #category : #'*Famix-Value-Entities-Extensions' } -FamixValueUnknownType >> isParameterizedType [ +FamixValueUnknownType >> isParametricEntity [ ^ false ] diff --git a/src/Famix-Value-Exporter-Tests/FamixValue2FASTJavaVisitorTest.class.st b/src/Famix-Value-Exporter-Tests/FamixValue2FASTJavaVisitorTest.class.st index d55fb87..be2990d 100644 --- a/src/Famix-Value-Exporter-Tests/FamixValue2FASTJavaVisitorTest.class.st +++ b/src/Famix-Value-Exporter-Tests/FamixValue2FASTJavaVisitorTest.class.st @@ -44,10 +44,13 @@ FamixValue2FASTJavaVisitorTest >> testVisitCollection [ | collection | collection := FamixValueOfCollection new type: - (FamixJavaParameterizedType new - parameterizableClass: - (FamixJavaParameterizableClass new name: 'List'); - arguments: { (FamixJavaClass new name: 'String') }). + (FamixJavaParametricClass new + name: 'List'; + genericization: + (FamixJavaConcretization new genericEntity: + (FamixJavaParametricInterface named: 'List')); + concreteParameters: + { (FamixJavaClass named: 'String') }). self assert: collection asJavaSourceCode equals: '{ List list0 = new ArrayList(); @@ -78,28 +81,33 @@ FamixValue2FASTJavaVisitorTest >> testVisitCollection [ { #category : #tests } FamixValue2FASTJavaVisitorTest >> testVisitDeepCollection [ - | collection inner | + | list object collection element | + list := FamixJavaParametricInterface named: 'List'. + object := FamixJavaParametricInterface named: 'Object'. collection := FamixValueOfCollection new type: - (FamixJavaParameterizedType new - parameterizableClass: - (FamixJavaParameterizableClass new name: 'List'); - arguments: { (FamixJavaParameterizedType new - parameterizableClass: - (FamixJavaParameterizableClass new name: 'List'); - arguments: - { (FamixJavaClass new name: 'Object') }) }). - inner := FamixValueOfCollection new type: - (FamixJavaParameterizedType new - parameterizableClass: - (FamixJavaParameterizableClass new name: 'List'); - arguments: { (FamixJavaClass new name: 'Object') }). + (FamixJavaParametricInterface new + genericization: + (FamixJavaConcretization new genericEntity: list); + concreteParameters: + { (FamixJavaParametricInterface new + name: 'List'; + genericization: + (FamixJavaConcretization new genericEntity: list); + concreteParameters: { object }) }). + element := FamixValueOfCollection new type: + (FamixJavaParametricInterface new + name: 'List'; + genericization: + (FamixJavaConcretization new genericEntity: list); + concreteParameters: { object }). self assert: collection asJavaSourceCode equals: '{ List> list0 = new ArrayList>(); } '. - collection addValue: (FamixValueOfCollectionElement new value: inner). + collection addValue: + (FamixValueOfCollectionElement new value: element). self assert: collection asJavaSourceCode equals: '{ List> list0 = new ArrayList>(); List list1 = new ArrayList(); @@ -107,7 +115,8 @@ FamixValue2FASTJavaVisitorTest >> testVisitDeepCollection [ } '. - inner addValue: (FamixValueOfCollectionElement new value: nullString). + element addValue: + (FamixValueOfCollectionElement new value: nullString). self assert: collection asJavaSourceCode equals: '{ List> list0 = new ArrayList>(); List list1 = new ArrayList(); @@ -123,10 +132,14 @@ FamixValue2FASTJavaVisitorTest >> testVisitDictionary [ | dictionary | dictionary := FamixValueOfDictionary new type: - (FamixJavaParameterizedType new - parameterizableClass: - (FamixJavaParameterizableClass new name: 'Map'); - arguments: { (FamixJavaClass new name: 'Object') }). + (FamixJavaParametricInterface new + name: 'Map'; + genericization: + (FamixJavaConcretization new genericEntity: + (FamixJavaParametricInterface named: 'Map')); + concreteParameters: + { (FamixJavaClass named: 'Object') }). + self assert: dictionary asJavaSourceCode equals: '{ Map map0 = new HashMap(); } diff --git a/src/Famix-Value-Exporter-Tests/FamixValueExtensionsTest.class.st b/src/Famix-Value-Exporter-Tests/FamixValueExtensionsTest.class.st index b76e93f..d340199 100644 --- a/src/Famix-Value-Exporter-Tests/FamixValueExtensionsTest.class.st +++ b/src/Famix-Value-Exporter-Tests/FamixValueExtensionsTest.class.st @@ -5,7 +5,78 @@ Class { } { #category : #tests } -FamixValueExtensionsTest >> testSplitJavaArguments [ +FamixValueExtensionsTest >> test_FamixTParametricEntity_keyType [ + + | string integer | + string := FamixJavaClass named: 'String'. + integer := FamixJavaClass named: 'Integer'. + + self + assert: (FamixJavaParametricClass new concreteParameters: { + string. + integer }) keyType + equals: string. + self + assert: (FamixJavaParametricClass new concreteParameters: { + integer. + string }) keyType + equals: integer. + self + assert: + (FamixJavaParametricClass new concreteParameters: { string }) + keyType + equals: string +] + +{ #category : #tests } +FamixValueExtensionsTest >> test_FamixTParametricEntity_typeName [ + + | map string integer | + map := FamixJavaParametricClass named: 'Map'. + string := FamixJavaClass named: 'String'. + integer := FamixJavaClass named: 'Integer'. + + self + assert: (map concreteParameters: { + string. + integer }) typeName + equals: 'Map'. + self + assert: (map concreteParameters: { + integer. + string }) typeName + equals: 'Map'. + self + assert: (map concreteParameters: { string }) typeName + equals: 'Map' +] + +{ #category : #tests } +FamixValueExtensionsTest >> test_FamixTParametricEntity_valueType [ + + | string integer | + string := FamixJavaClass named: 'String'. + integer := FamixJavaClass named: 'Integer'. + + self + assert: (FamixJavaParametricClass new concreteParameters: { + string. + integer }) valueType + equals: integer. + self + assert: (FamixJavaParametricClass new concreteParameters: { + integer. + string }) valueType + equals: string. + self + assert: + (FamixJavaParametricClass new concreteParameters: { string }) + valueType + equals: string +] + +{ #category : #tests } +FamixValueExtensionsTest >> test_String_splitJavaArguments [ self assert: '' splitJavaArguments equals: { }. self diff --git a/src/Famix-Value-Exporter/FASTJavaBuilder.class.st b/src/Famix-Value-Exporter/FASTJavaBuilder.class.st index 49f95fc..e291320 100644 --- a/src/Famix-Value-Exporter/FASTJavaBuilder.class.st +++ b/src/Famix-Value-Exporter/FASTJavaBuilder.class.st @@ -53,11 +53,11 @@ FASTJavaBuilder >> makeImportDeclarations [ FASTJavaBuilder >> processType: aFamixType [ | type | - type := aFamixType isParameterizedType + type := aFamixType isParametricEntity ifTrue: [ - aFamixType arguments do: [ :argument | - self processType: argument ]. - aFamixType parameterizableClass ] + aFamixType concreteParameters do: [ :parameter | + self processType: parameter ]. + aFamixType genericEntity ] ifFalse: [ aFamixType ]. type needsJavaImport ifTrue: [ self registerType: type ] ] @@ -73,8 +73,8 @@ FASTJavaBuilder >> referType: aFamixType [ ^ self model newClassTypeExpression typeName: ((registeredType == aFamixType or: [ aFamixType needsJavaImport not or: [ - aFamixType isParameterizedType and: [ - registeredType == aFamixType parameterizableClass ] ] ]) + aFamixType isParametricEntity and: [ + registeredType == aFamixType genericEntity ] ] ]) ifTrue: [ "has import" model newTypeName name: aFamixType baseName ] ifFalse: [ "no import" diff --git a/src/Famix-Value-Exporter/FamixJavaParameterizableClass.extension.st b/src/Famix-Value-Exporter/FamixJavaParameterizableClass.extension.st deleted file mode 100644 index e43ad77..0000000 --- a/src/Famix-Value-Exporter/FamixJavaParameterizableClass.extension.st +++ /dev/null @@ -1,39 +0,0 @@ -Extension { #name : #FamixJavaParameterizableClass } - -{ #category : #'*Famix-Value-Exporter' } -FamixJavaParameterizableClass >> concreteBaseNameOn: stream [ - - (#( Map Set ) includes: name) - ifTrue: [ stream nextPutAll: 'Hash' ] - ifFalse: [ 'List' = name ifTrue: [ stream nextPutAll: 'Array' ] ]. - stream nextPutAll: name -] - -{ #category : #'*Famix-Value-Exporter' } -FamixJavaParameterizableClass >> concreteTypeNameOn: stream [ - - self concreteBaseNameOn: stream. - stream nextPutAll: '<>' -] - -{ #category : #'*Famix-Value-Exporter' } -FamixJavaParameterizableClass >> typeArgumentNamesOn: stream [ - "TODO: deal with generics?" - - stream nextPut: $<. - self parameters - do: [ :parameter | - parameter isParameterType - ifTrue: [ stream nextPutAll: 'Object' ] - ifFalse: [ parameter typeNameOn: stream ] ] - separatedBy: [ stream nextPutAll: ', ' ]. - stream nextPut: $> -] - -{ #category : #'*Famix-Value-Exporter' } -FamixJavaParameterizableClass >> typeNameOn: stream [ - - stream nextPutAll: name - "type arguments of parameterizable classes can be generics, and we cannot use them without defining them" - "self typeArgumentNamesOn: stream" -] diff --git a/src/Famix-Value-Exporter/FamixJavaParameterizedType.extension.st b/src/Famix-Value-Exporter/FamixJavaParameterizedType.extension.st deleted file mode 100644 index 0327922..0000000 --- a/src/Famix-Value-Exporter/FamixJavaParameterizedType.extension.st +++ /dev/null @@ -1,43 +0,0 @@ -Extension { #name : #FamixJavaParameterizedType } - -{ #category : #'*Famix-Value-Exporter' } -FamixJavaParameterizedType >> asFASTJavaDefaultValueOn: aFASTJavaModel [ - - ^ aFASTJavaModel newNullLiteral -] - -{ #category : #'*Famix-Value-Exporter' } -FamixJavaParameterizedType >> baseName [ - - ^ parameterizableClass name -] - -{ #category : #'*Famix-Value-Exporter' } -FamixJavaParameterizedType >> concreteTypeNameOn: stream [ - - parameterizableClass concreteBaseNameOn: stream. - self typeArgumentNamesOn: stream -] - -{ #category : #'*Famix-Value-Exporter' } -FamixJavaParameterizedType >> typeArgumentNamesOn: stream [ - - stream nextPut: $<. - self isDictionaryType - ifTrue: [ - self keyArgument typeNameOn: stream. - stream nextPutAll: ', '. - self valueArgument typeNameOn: stream ] - ifFalse: [ - arguments - do: [ :argument | argument typeNameOn: stream ] - separatedBy: [ stream nextPutAll: ', ' ] ]. - stream nextPut: $> -] - -{ #category : #'*Famix-Value-Exporter' } -FamixJavaParameterizedType >> typeNameOn: stream [ - - stream nextPutAll: parameterizableClass name. - self typeArgumentNamesOn: stream -] diff --git a/src/Famix-Value-Exporter/FamixJavaParametricClass.extension.st b/src/Famix-Value-Exporter/FamixJavaParametricClass.extension.st new file mode 100644 index 0000000..6f1c2c7 --- /dev/null +++ b/src/Famix-Value-Exporter/FamixJavaParametricClass.extension.st @@ -0,0 +1,8 @@ +Extension { #name : #FamixJavaParametricClass } + +{ #category : #'*Famix-Value-Exporter' } +FamixJavaParametricClass >> concreteTypeNameOn: stream [ + + stream nextPutAll: name. + stream nextPutAll: '<>' +] diff --git a/src/Famix-Value-Exporter/FamixJavaParametricInterface.extension.st b/src/Famix-Value-Exporter/FamixJavaParametricInterface.extension.st new file mode 100644 index 0000000..3e7bece --- /dev/null +++ b/src/Famix-Value-Exporter/FamixJavaParametricInterface.extension.st @@ -0,0 +1,11 @@ +Extension { #name : #FamixJavaParametricInterface } + +{ #category : #'*Famix-Value-Exporter' } +FamixJavaParametricInterface >> concreteTypeNameOn: stream [ + + (#( Map Set ) includes: name) + ifTrue: [ stream nextPutAll: 'Hash' ] + ifFalse: [ 'List' = name ifTrue: [ stream nextPutAll: 'Array' ] ]. + stream nextPutAll: name. + stream nextPutAll: '<>' +] diff --git a/src/Famix-Value-Exporter/FamixTClass.extension.st b/src/Famix-Value-Exporter/FamixTClass.extension.st index 5557060..e15f6bb 100644 --- a/src/Famix-Value-Exporter/FamixTClass.extension.st +++ b/src/Famix-Value-Exporter/FamixTClass.extension.st @@ -12,6 +12,8 @@ FamixTClass >> constructorsOrderedByScore [ { #category : #'*Famix-Value-Exporter' } FamixTClass >> findSetterOf: aFamixAttribute [ + (self isParametricEntity and: [ self isConcreteEntity ]) ifTrue: [ + ^ self genericEntity findSetterOf: aFamixAttribute ]. ^ self methods detect: [ :method | method isSetterLax and: [ diff --git a/src/Famix-Value-Exporter/FamixTParameterizedType.extension.st b/src/Famix-Value-Exporter/FamixTParameterizedType.extension.st deleted file mode 100644 index f930a85..0000000 --- a/src/Famix-Value-Exporter/FamixTParameterizedType.extension.st +++ /dev/null @@ -1,19 +0,0 @@ -Extension { #name : #FamixTParameterizedType } - -{ #category : #'*Famix-Value-Exporter' } -FamixTParameterizedType >> constructorScore [ - - ^ parameterizableClass constructorScore -] - -{ #category : #'*Famix-Value-Exporter' } -FamixTParameterizedType >> findSetterOf: aFamixAttribute [ - - ^ parameterizableClass findSetterOf: aFamixAttribute -] - -{ #category : #'*Famix-Value-Exporter' } -FamixTParameterizedType >> publicConstructorsWithMostImpact [ - - ^ parameterizableClass publicConstructorsWithMostImpact -] diff --git a/src/Famix-Value-Exporter/FamixTParametricEntity.extension.st b/src/Famix-Value-Exporter/FamixTParametricEntity.extension.st new file mode 100644 index 0000000..f317edc --- /dev/null +++ b/src/Famix-Value-Exporter/FamixTParametricEntity.extension.st @@ -0,0 +1,42 @@ +Extension { #name : #FamixTParametricEntity } + +{ #category : #'*Famix-Value-Exporter' } +FamixTParametricEntity >> keyType [ + + ^ self allTypeParameters first +] + +{ #category : #'*Famix-Value-Exporter' } +FamixTParametricEntity >> typeNameOn: stream [ + + stream nextPutAll: self name. + self typeParameterNamesOn: stream +] + +{ #category : #'*Famix-Value-Exporter' } +FamixTParametricEntity >> typeParameterNamesOn: stream [ + + stream nextPut: $<. + self isDictionaryType + ifTrue: [ + self keyType typeNameOn: stream. + stream nextPutAll: ', '. + self valueType typeNameOn: stream ] + ifFalse: [ + self allTypeParameters + do: [ :parameter | + parameter isParameterType + ifTrue: [ stream nextPutAll: 'Object' ] + ifFalse: [ parameter typeNameOn: stream ] ] + separatedBy: [ stream nextPutAll: ', ' ] ]. + stream nextPut: $> +] + +{ #category : #'*Famix-Value-Exporter' } +FamixTParametricEntity >> valueType [ + + | typeParameters | + ^ (typeParameters := self allTypeParameters) size = 1 + ifTrue: [ typeParameters first ] + ifFalse: [ typeParameters second ] +] diff --git a/src/Famix-Value-Importer/FamixEntityFinder.class.st b/src/Famix-Value-Importer/FamixEntityFinder.class.st index a690381..f14b067 100644 --- a/src/Famix-Value-Importer/FamixEntityFinder.class.st +++ b/src/Famix-Value-Importer/FamixEntityFinder.class.st @@ -62,7 +62,11 @@ FamixEntityFinder >> findMethodsWithName: name in: class [ FamixEntityFinder >> findTypeNamed: name [ "Main API for finding a type, should not be overridden." - ^ self cache at: name ifAbsentPut: [ self parseTypeName: name ] + ^ self cache at: name ifAbsentPut: [ + | type | + (type := self parseTypeName: name) isParametricEntity + ifTrue: [ type genericEntity ] + ifFalse: [ type ] ] ] { #category : #enumerating } diff --git a/src/Famix-Value-Importer/FamixTParameterizedType.extension.st b/src/Famix-Value-Importer/FamixTParameterizedType.extension.st deleted file mode 100644 index 9695c46..0000000 --- a/src/Famix-Value-Importer/FamixTParameterizedType.extension.st +++ /dev/null @@ -1,7 +0,0 @@ -Extension { #name : #FamixTParameterizedType } - -{ #category : #'*Famix-Value-Importer' } -FamixTParameterizedType >> findAttributeNamed: attributeName [ - - ^ parameterizableClass findAttributeNamed: attributeName -] diff --git a/src/Famix-Value-Importer/FamixTWithParameterizedTypeUsers.extension.st b/src/Famix-Value-Importer/FamixTWithParameterizedTypeUsers.extension.st deleted file mode 100644 index 5baecb9..0000000 --- a/src/Famix-Value-Importer/FamixTWithParameterizedTypeUsers.extension.st +++ /dev/null @@ -1,21 +0,0 @@ -Extension { #name : #FamixTWithParameterizedTypeUsers } - -{ #category : #'*Famix-Value-Importer' } -FamixTWithParameterizedTypeUsers >> keyArgument [ - - ^ (arguments size = 1 or: [ - arguments first name = 'String' or: [ - arguments second name ~= 'String' ] ]) - ifTrue: [ arguments first ] - ifFalse: [ arguments second ] -] - -{ #category : #'*Famix-Value-Importer' } -FamixTWithParameterizedTypeUsers >> valueArgument [ - - ^ (arguments size = 1 or: [ - arguments second name = 'String' or: [ - arguments first name ~= 'String' ] ]) - ifTrue: [ arguments first ] - ifFalse: [ arguments second ] -] diff --git a/src/Famix-Value-Importer/FamixValueAbstractImporter.class.st b/src/Famix-Value-Importer/FamixValueAbstractImporter.class.st index a254fbb..34ae2b3 100644 --- a/src/Famix-Value-Importer/FamixValueAbstractImporter.class.st +++ b/src/Famix-Value-Importer/FamixValueAbstractImporter.class.st @@ -63,7 +63,8 @@ FamixValueAbstractImporter >> importCollection: rawValue of: type [ collection := self model newOfCollection type: type. self withTypeInference: - (type isParameterizedType ifTrue: [ type arguments first ]) + ((self parametricTypeInferencesOf: type) ifNotNil: [ :inferences | + inferences first ]) do: [ rawValue do: [ :rawElement | collection addValue: (self model newOfCollectionElement value: @@ -77,11 +78,11 @@ FamixValueAbstractImporter >> importDictionary: rawValue of: type [ | dictionary keyType valueType assoc | dictionary := self model newOfDictionary type: type. - (type isUnknownType not and: [ type isParameterizedType ]) - ifTrue: [ - keyType := type keyArgument. - valueType := type valueArgument ] - ifFalse: [ keyType := valueType := nil ]. + (self parametricTypeInferencesOf: type) + ifNotNil: [ :paramTypeInferences | + keyType := paramTypeInferences at: 1. + valueType := paramTypeInferences at: 2 ] + ifNil: [ keyType := valueType := nil ]. rawValue associationsDo: [ :rawAssoc | assoc := self model newOfDictionaryAssociation dictionary: dictionary. @@ -179,6 +180,23 @@ FamixValueAbstractImporter >> newReader [ ^ NeoJSONReader new mapClass: OrderedDictionary ] +{ #category : #enumerating } +FamixValueAbstractImporter >> parametricTypeInferencesOf: type [ + + type isParametricEntity ifFalse: [ ^ nil ]. + ^ type isGenericEntity + ifTrue: [ + self typeInference ifNotNil: [ :inference | + (inference isDictionaryType and: [ + inference concreteParameters size = 1 ]) + ifTrue: [ + { + (inference concreteParameters at: 1). + (inference concreteParameters at: 1) } ] + ifFalse: [ inference concreteParameters ] ] ] + ifFalse: [ type allTypeParameters ] +] + { #category : #parsing } FamixValueAbstractImporter >> parseList: serializedValues [ "Reify the raw values from a serialized list, useful for iterating." diff --git a/src/Famix-Value-Importer/FamixValueJavaJacksonImporter.class.st b/src/Famix-Value-Importer/FamixValueJavaJacksonImporter.class.st index eec4d05..53d368a 100644 --- a/src/Famix-Value-Importer/FamixValueJavaJacksonImporter.class.st +++ b/src/Famix-Value-Importer/FamixValueJavaJacksonImporter.class.st @@ -69,7 +69,7 @@ FamixValueJavaJacksonImporter >> importSpecialObject: rawValue of: type [ (#( Date Timestamp ) includes: type name) ifTrue: [ ^ self importDateObject: rawValue of: type ]. - self error: 'Unknown special object: ' , type mooseNameWithDots + ^ nil ] { #category : #importing } diff --git a/src/Famix-Value-Importer/Integer.extension.st b/src/Famix-Value-Importer/Integer.extension.st index 562e60f..57b5c2f 100644 --- a/src/Famix-Value-Importer/Integer.extension.st +++ b/src/Famix-Value-Importer/Integer.extension.st @@ -4,13 +4,13 @@ Extension { #name : #Integer } Integer >> asJavaJacksonValueOn: importer [ | typeInference | - typeInference := importer typeInference. - ^ (typeInference isNotNil and: [ - (importer isPrimitiveType: typeInference) not ]) - ifTrue: [ "object reference, solved by the importer" - importer - getObjectFromIdentity: self - ifAbsent: [ "might be a special object with missing runtime type information" - importer importSpecialObject: self of: typeInference ] ] - ifFalse: [ importer importPrimitive: self of: 'int' ] + ((typeInference := importer typeInference) isNotNil and: [ + (importer isPrimitiveType: typeInference) not ]) ifTrue: [ "object reference, solved by the importer" + (importer + getObjectFromIdentity: self + ifAbsent: [ "*might* be a special object with missing runtime type information" + importer importSpecialObject: self of: typeInference ]) + ifNotNil: [ :value | ^ value ] ]. + "if none of the above holds true, this must be a regular integer" + ^ importer importPrimitive: self of: 'int' ]