diff --git a/src/Famix-Value-Entities-Extensions/FamixValueOfObject.extension.st b/src/Famix-Value-Entities-Extensions/FamixValueOfObject.extension.st index cc9360e..5fc4f37 100644 --- a/src/Famix-Value-Entities-Extensions/FamixValueOfObject.extension.st +++ b/src/Famix-Value-Entities-Extensions/FamixValueOfObject.extension.st @@ -1,16 +1,5 @@ Extension { #name : 'FamixValueOfObject' } -{ #category : '*Famix-Value-Entities-Extensions' } -FamixValueOfObject >> constructorSignature [ - - ^ String streamContents: [ :s | - s << self type name << '('. - value - do: [ :attribute | s << attribute attribute declaredType name ] - separatedBy: [ s nextPut: $, ]. - s nextPut: $) ] -] - { #category : '*Famix-Value-Entities-Extensions' } FamixValueOfObject >> containsCollection [ diff --git a/src/Famix-Value-Entities/FamixTType.extension.st b/src/Famix-Value-Entities/FamixTType.extension.st index c598ce5..6aabf69 100644 --- a/src/Famix-Value-Entities/FamixTType.extension.st +++ b/src/Famix-Value-Entities/FamixTType.extension.st @@ -1,37 +1,37 @@ Extension { #name : 'FamixTType' } { #category : '*Famix-Value-Entities-accessing' } -FamixTType >> valueReferences [ - "Relation named: #valueReferences type: #FamixValueOfTypeReference opposite: #value" +FamixTType >> valueInstances [ + "Relation named: #valueInstances type: #FamixValueOfType opposite: #type" - + - ^ self attributeAt: #valueReferences ifAbsentPut: [ FMMultivalueLink on: self opposite: #value: ] + ^ self attributeAt: #valueInstances ifAbsentPut: [ FMMultivalueLink on: self opposite: #type: ] ] { #category : '*Famix-Value-Entities-accessing' } -FamixTType >> valueReferences: anObject [ +FamixTType >> valueInstances: anObject [ - self valueReferences value: anObject + self valueInstances value: anObject ] { #category : '*Famix-Value-Entities-accessing' } -FamixTType >> values [ - "Relation named: #values type: #FamixValueOfType opposite: #type" +FamixTType >> valueReferences [ + "Relation named: #valueReferences type: #FamixValueOfTypeReference opposite: #value" - + - ^ self attributeAt: #values ifAbsentPut: [ FMMultivalueLink on: self opposite: #type: ] + ^ self attributeAt: #valueReferences ifAbsentPut: [ FMMultivalueLink on: self opposite: #value: ] ] { #category : '*Famix-Value-Entities-accessing' } -FamixTType >> values: anObject [ +FamixTType >> valueReferences: anObject [ - self values value: anObject + self valueReferences value: anObject ] diff --git a/src/Famix-Value-Entities/FamixValueOfType.class.st b/src/Famix-Value-Entities/FamixValueOfType.class.st index 037fafb..2a0784a 100644 --- a/src/Famix-Value-Entities/FamixValueOfType.class.st +++ b/src/Famix-Value-Entities/FamixValueOfType.class.st @@ -10,7 +10,7 @@ Abstract superclass of all ValueOf_Type_ entities. | `attributeInObjects` | `FamixValueOfType` | `value` | `FamixValueOfObjectAttribute` | | | `elementInCollections` | `FamixValueOfType` | `value` | `FamixValueOfCollectionElement` | | | `keyInDictionaries` | `FamixValueOfType` | `key` | `FamixValueOfDictionaryAssociation` | | -| `type` | `FamixValueOfType` | `values` | `FamixTType` | | +| `type` | `FamixValueOfType` | `valueInstances` | `FamixTType` | | | `typedEntity` | `FamixValueOfType` | `values` | `FamixTTypedEntity` | | | `valueInDictionaries` | `FamixValueOfType` | `value` | `FamixValueOfDictionaryAssociation` | | | `variableInClosures` | `FamixValueOfType` | `value` | `FamixValueOfClosureVariable` | | @@ -137,10 +137,10 @@ FamixValueOfType >> keyInDictionaries: anObject [ { #category : 'accessing' } FamixValueOfType >> type [ - "Relation named: #type type: #FamixTType opposite: #values" + "Relation named: #type type: #FamixTType opposite: #valueInstances" - + ^ self attributeAt: #type ifAbsent: [ nil ] ] @@ -148,7 +148,7 @@ FamixValueOfType >> type [ FamixValueOfType >> type: anObject [ - self attributeAt: #type put: (FMMultivalueLink on: self update: #values from: self type to: anObject). + self attributeAt: #type put: (FMMultivalueLink on: self update: #valueInstances from: self type to: anObject). ] { #category : 'accessing' } diff --git a/src/Famix-Value-Entities/FamixValueUnknownType.class.st b/src/Famix-Value-Entities/FamixValueUnknownType.class.st index 4552b23..cbdcd97 100644 --- a/src/Famix-Value-Entities/FamixValueUnknownType.class.st +++ b/src/Famix-Value-Entities/FamixValueUnknownType.class.st @@ -19,8 +19,8 @@ An unknown type. |---| | `sourceAnchor` | `FamixTSourceEntity` | `element` | `FamixTSourceAnchor` | SourceAnchor entity linking to the original source code for this entity| | `typedEntities` | `FamixTType` | `declaredType` | `FamixTTypedEntity` | Entities that have this type as declaredType| +| `valueInstances` | `FamixTType` | `type` | `FamixValueOfType` | | | `valueReferences` | `FamixTType` | `value` | `FamixValueOfTypeReference` | | -| `values` | `FamixTType` | `type` | `FamixValueOfType` | | ## Properties diff --git a/src/Famix-Value-Exporter/FASTJavaBuilder.class.st b/src/Famix-Value-Exporter/FASTJavaBuilder.class.st index 5119680..3e86337 100644 --- a/src/Famix-Value-Exporter/FASTJavaBuilder.class.st +++ b/src/Famix-Value-Exporter/FASTJavaBuilder.class.st @@ -25,11 +25,13 @@ FASTJavaBuilder >> fullyQualifiedPackageNameFor: aFamixJavaPackage [ { #category : 'ast' } FASTJavaBuilder >> fullyQualifiedTypeNameFor: aFamixJavaType [ + "A type can be in another type or a package" ^ self model newQualifiedTypeName name: aFamixJavaType baseName; namespace: - (self fullyQualifiedPackageNameFor: aFamixJavaType typeContainer) + (aFamixJavaType typeContainer fullyQualifiedTypeNameOn: + self model) ] { #category : 'initialization' } @@ -42,7 +44,7 @@ FASTJavaBuilder >> initialize [ FASTJavaBuilder >> makeImportDeclaration: aFamixType [ ^ self model newImportDeclaration qualifiedName: - (model newQualifiedName name: aFamixType mooseNameWithDots) + (aFamixType fullyQualifiedNameOn: self model) ] { #category : 'ast' } diff --git a/src/Famix-Value-Exporter/FASTJavaVariableExpression.extension.st b/src/Famix-Value-Exporter/FASTJavaVariableExpression.extension.st index 2f55cb0..ef8991f 100644 --- a/src/Famix-Value-Exporter/FASTJavaVariableExpression.extension.st +++ b/src/Famix-Value-Exporter/FASTJavaVariableExpression.extension.st @@ -24,5 +24,14 @@ FASTJavaVariableExpression >> accessedAttributesOf: aFamixJavaClass [ ifFalse: [ (method parameters at: (invoc arguments indexOf: self)) allAccessedAttributesOf: aFamixJavaClass ] ]. + receiverOwner ifNotNil: [ :receiver | "receiver of a method, reiterate on the variable 'this'" + | method | + ^ (method := receiver famixInvocation anyCandidate) isStub + ifTrue: [ "ignore stubs" { } ] + ifFalse: [ + method implicitVariables + detect: [ :var | var isSelf ] + ifFound: [ :var | var allAccessedAttributesOf: aFamixJavaClass ] + ifNone: [ { } ] ] ]. self error: 'TODO: what else can be using the parameter?' ] diff --git a/src/Famix-Value-Exporter/FamixJavaInterface.extension.st b/src/Famix-Value-Exporter/FamixJavaInterface.extension.st new file mode 100644 index 0000000..29b2553 --- /dev/null +++ b/src/Famix-Value-Exporter/FamixJavaInterface.extension.st @@ -0,0 +1,15 @@ +Extension { #name : 'FamixJavaInterface' } + +{ #category : '*Famix-Value-Exporter' } +FamixJavaInterface >> withSubHierarchy [ + "Includes subinterfaces and their implementing classes" + + | result | + result := Set new. + self withSubclassHierarchy do: [ :interface | + result add: interface. + interface implementations do: [ :implementation | + implementation implementingClass withSubclassesDo: [ :class | + result add: class ] ] ]. + ^ result asOrderedCollection +] diff --git a/src/Famix-Value-Exporter/FamixJavaPackage.extension.st b/src/Famix-Value-Exporter/FamixJavaPackage.extension.st new file mode 100644 index 0000000..7b6adb6 --- /dev/null +++ b/src/Famix-Value-Exporter/FamixJavaPackage.extension.st @@ -0,0 +1,24 @@ +Extension { #name : 'FamixJavaPackage' } + +{ #category : '*Famix-Value-Exporter' } +FamixJavaPackage >> fullyQualifiedNameOn: aFASTJavaModel [ + + ^ parentPackage + ifNil: [ aFASTJavaModel newQualifiedName name: name ] + ifNotNil: [ + aFASTJavaModel newQualifiedName + name: name; + namespace: (parentPackage fullyQualifiedNameOn: aFASTJavaModel) ] +] + +{ #category : '*Famix-Value-Exporter' } +FamixJavaPackage >> fullyQualifiedTypeNameOn: aFASTJavaModel [ + + ^ parentPackage + ifNil: [ aFASTJavaModel newQualifiedTypeName name: name ] + ifNotNil: [ + aFASTJavaModel newQualifiedTypeName + name: name; + namespace: + (parentPackage fullyQualifiedTypeNameOn: aFASTJavaModel) ] +] diff --git a/src/Famix-Value-Exporter/FamixJavaType.extension.st b/src/Famix-Value-Exporter/FamixJavaType.extension.st index e5b1149..4167593 100644 --- a/src/Famix-Value-Exporter/FamixJavaType.extension.st +++ b/src/Famix-Value-Exporter/FamixJavaType.extension.st @@ -44,6 +44,29 @@ FamixJavaType >> decorate: aFamixJavaType asFASTJavaTypeExpressionOn: visitor [ ifFalse: [ aFamixJavaType asFASTJavaTypeExpressionOn: visitor ] ] +{ #category : '*Famix-Value-Exporter' } +FamixJavaType >> fullyQualifiedNameOn: aFASTJavaModel [ + + ^ typeContainer + ifNil: [ aFASTJavaModel newQualifiedName name: name ] + ifNotNil: [ + aFASTJavaModel newQualifiedName + name: name; + namespace: (typeContainer fullyQualifiedNameOn: aFASTJavaModel) ] +] + +{ #category : '*Famix-Value-Exporter' } +FamixJavaType >> fullyQualifiedTypeNameOn: aFASTJavaModel [ + + ^ typeContainer + ifNil: [ aFASTJavaModel newQualifiedTypeName name: name ] + ifNotNil: [ + aFASTJavaModel newQualifiedTypeName + name: name; + namespace: + (typeContainer fullyQualifiedTypeNameOn: aFASTJavaModel) ] +] + { #category : '*Famix-Value-Exporter' } FamixJavaType >> needsJavaImport [ diff --git a/src/Famix-Value-Exporter/FamixJavaWildcard.extension.st b/src/Famix-Value-Exporter/FamixJavaWildcard.extension.st new file mode 100644 index 0000000..f726731 --- /dev/null +++ b/src/Famix-Value-Exporter/FamixJavaWildcard.extension.st @@ -0,0 +1,7 @@ +Extension { #name : 'FamixJavaWildcard' } + +{ #category : '*Famix-Value-Exporter' } +FamixJavaWildcard >> needsJavaImport [ + + ^ false +] diff --git a/src/Famix-Value-Exporter/FamixTMethod.extension.st b/src/Famix-Value-Exporter/FamixTMethod.extension.st index 3a45ec6..66e8d88 100644 --- a/src/Famix-Value-Exporter/FamixTMethod.extension.st +++ b/src/Famix-Value-Exporter/FamixTMethod.extension.st @@ -55,8 +55,19 @@ FamixTMethod >> mapConstructorParametersToAttributes [ (parameter fastAccesses flatCollectAsSet: [ :access | access accessedAttributesOf: parentType ]) ifNotEmpty: [ :attributes | - attributes size = 1 - ifTrue: [ attributes anyOne ] - ifFalse: [ self error: 'Expected only one attribute.' ] ] + | attribute | + attributes size = 1 ifFalse: [ + FamixValueExporterError signal: 'Expected only one attribute.' ]. + (attribute := attributes anyOne) declaredType + ifNil: [ "TODO should not happen, fix Java parser" nil ] + ifNotNil: [ :attributeType | + (attributeType withSubHierarchy includes: + parameter declaredType) + ifTrue: [ attribute ] + ifFalse: [ "parameter is used to set the attribute, but not directly because they are of different types + a common occurence is an array-to-collection transformation: + setValues(String... values) { this.values = Arrays.asList(values); } + however reality is often more complex, so for now we ignore this parameter-to-attribute mapping (10/24)" + nil ] ] ] ifEmpty: [ "parameter is not mapped to an attribute" nil ] ] ] diff --git a/src/Famix-Value-Exporter/FamixTWithInheritances.extension.st b/src/Famix-Value-Exporter/FamixTWithInheritances.extension.st new file mode 100644 index 0000000..e7d9230 --- /dev/null +++ b/src/Famix-Value-Exporter/FamixTWithInheritances.extension.st @@ -0,0 +1,8 @@ +Extension { #name : 'FamixTWithInheritances' } + +{ #category : '*Famix-Value-Exporter' } +FamixTWithInheritances >> withSubHierarchy [ + "Returns the complete sub-hierarchy, see implementors for special cases" + + ^ self withSubclassHierarchy +] diff --git a/src/Famix-Value-Exporter/FamixValue2FASTJavaVisitor.class.st b/src/Famix-Value-Exporter/FamixValue2FASTJavaVisitor.class.st index b6c9d5a..7651494 100644 --- a/src/Famix-Value-Exporter/FamixValue2FASTJavaVisitor.class.st +++ b/src/Famix-Value-Exporter/FamixValue2FASTJavaVisitor.class.st @@ -33,7 +33,10 @@ FamixValue2FASTJavaVisitor >> addAttributesFrom: object asArgumentsTo: invocatio invocation addArgument: (paramAttribute ifNil: [ "constructor parameter is not mapped to an attribute" (constructor parameters at: index) declaredType - asFASTJavaDefaultValueOn: self model ] + ifNil: [ "TODO fix Java parser; if it's unknown then it must be a class, otherwise the parser would have found it" + FamixJavaClass new asFASTJavaDefaultValueOn: self model ] + ifNotNil: [ :declaredType | + declaredType asFASTJavaDefaultValueOn: self model ] ] ifNotNil: [ object value detect: [ :objAttribute | "find the matching value attribute" @@ -58,6 +61,8 @@ FamixValue2FASTJavaVisitor >> constructObject: object [ | constructor invocation | constructor := self findConstructorFor: object. + constructor thrownExceptions ifNotEmpty: [ + self shouldBeImplemented "handle exceptions thrown by the chosen constructor" ]. self reflections at: constructor ifPresent: [ :varName | "reflective constructor call, the variable contains the Constructor object" @@ -69,9 +74,13 @@ FamixValue2FASTJavaVisitor >> constructObject: object [ variable: (self makeVariableExpression: object); expression: invocation) ] ifAbsent: [ "regular constructor call" - invocation := (self statementBlock addStatement: - (self makeVarDeclStatement: object)) declarators - first expression ]. + | statement | + statement := self makeVarDeclStatement: object. + invocation := statement declarators first expression. + constructor thrownExceptions ifNotEmpty: [ :exceptions | "rethrow as RuntimeException" + self shouldBeImplemented. + exceptions do: [ :exception | ] ]. + self statementBlock addStatement: statement ]. "call with arguments to match constructor parameters" constructor parameters ifNotEmpty: [ self @@ -90,13 +99,13 @@ FamixValue2FASTJavaVisitor >> ensureReflection [ | declarations declaration initStatementBlock | declarations := self objectExportStrategy declarations. "does not work for inline strategy..." - self reflections ifNotEmpty: [ + self reflections ifNotEmpty: [ "body of initializeReflection()" ^ (declarations at: -3) statementBlock ]. "static { try { initializeReflection(); - } catch (NoSuchFieldException | SecurityException e) { + } catch (Exception e) { new RuntimeException(e); } }" @@ -109,13 +118,8 @@ FamixValue2FASTJavaVisitor >> ensureReflection [ { (model newExpressionStatement expression: (model newMethodInvocation name: 'initializeReflection')) }); catches: { (model newCatchPartStatement - catchedTypes: { - (model newClassTypeExpression typeName: - (model newTypeName name: 'NoSuchFieldException')). - (model newClassTypeExpression typeName: - (model newTypeName name: 'SecurityException')). - (model newClassTypeExpression typeName: - (model newTypeName name: 'NoSuchMethodException')) }; + catchedTypes: { (model newClassTypeExpression typeName: + (model newTypeName name: 'Exception')) }; body: (model newStatementBlock statements: { (model newThrowStatement expression: (model newNewExpression @@ -125,8 +129,8 @@ FamixValue2FASTJavaVisitor >> ensureReflection [ { (model newVariableExpression name: 'e') })) }); parameter: (model newVariableExpression name: 'e')) }) }). - "private static void initializeReflection() throws NoSuchFieldException, SecurityException { - // fields will be obtained and set as accessible here + "private static void initializeReflection() throws NoSuchFieldException, NoSuchMethodException, SecurityException { + // fields and constructors will be obtained and set as accessible here }" declaration := model newMethodEntity name: 'initializeReflection'. declaration attributeAt: 'order' put: -3. @@ -140,9 +144,9 @@ FamixValue2FASTJavaVisitor >> ensureReflection [ (model newClassTypeExpression typeName: (model newTypeName name: 'NoSuchFieldException')). (model newClassTypeExpression typeName: - (model newTypeName name: 'SecurityException')). + (model newTypeName name: 'NoSuchMethodException')). (model newClassTypeExpression typeName: - (model newTypeName name: 'NoSuchMethodException')) }; + (model newTypeName name: 'SecurityException')) }; statementBlock: (initStatementBlock := model newStatementBlock). "public static void setField(Object object, Field field, Object value) { @@ -199,7 +203,7 @@ FamixValue2FASTJavaVisitor >> ensureReflection [ T instance; try { instance = constructor.newInstance(arguments); - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + } catch (Exception e) { throw new RuntimeException(e); } return instance; @@ -248,13 +252,8 @@ FamixValue2FASTJavaVisitor >> ensureReflection [ { (model newVariableExpression name: 'arguments') }); operator: '=')) }); catches: { (model newCatchPartStatement - catchedTypes: { - (model newClassTypeExpression typeName: - (model newTypeName name: 'InstantiationException')). - (model newClassTypeExpression typeName: - (model newTypeName name: 'IllegalAccessException')). - (model newClassTypeExpression typeName: - (model newTypeName name: 'InvocationTargetException')) }; + catchedTypes: { (model newClassTypeExpression typeName: + (model newTypeName name: 'Exception')) }; body: (model newStatementBlock statements: { (model newThrowStatement expression: (model newNewExpression @@ -422,7 +421,7 @@ FamixValue2FASTJavaVisitor >> findStaticAttributeMatching: object [ type := object type. ((objAttributes := object relevantAttributes) allSatisfy: [ :attribute | attribute value isOfPrimitiveType ]) ifFalse: [ ^ nil ]. - "eligible attributes are public, static, of the same type, and have an initializer expression; the conditions are ordered for maximum time efficiency" + "eligible attributes are public, static, of the same type, and have an initializer expression; the conditions are ordered for time efficiency" staticAttributes := staticAttributesCache at: type ifAbsentPut: [ type attributes select: [ :attribute | attribute declaredType == object type and: [ @@ -552,6 +551,24 @@ FamixValue2FASTJavaVisitor >> makeSetterInvocation: setter for: attribute named: famixMethod: setter)) ] +{ #category : 'ast' } +FamixValue2FASTJavaVisitor >> makeTry: statement catch: exceptions [ + "Wrap the statement in a try-catch for the given exceptions, and rethrow as an unchecked RuntimeException." + + ^ self model newTryCatchStatement + try: (model newStatementBlock statements: { statement }); + catches: { (model newCatchPartStatement + catchedTypes: (exceptions collect: [ :exception | + exception asFASTJavaTypeExpressionOn: self ]); + parameter: (model newVariableExpression name: 'e'); + body: (model newStatementBlock statements: + { (model newThrowStatement expression: + (model newNewExpression + type: (model newClassTypeExpression typeName: + (model newTypeName name: 'RuntimeException')); + arguments: { (model newVariableExpression name: 'e') })) })) } +] + { #category : 'ast' } FamixValue2FASTJavaVisitor >> makeVarDeclStatement: value [ @@ -710,7 +727,7 @@ FamixValue2FASTJavaVisitor >> visitObjectOfRegularType: object [ FamixValue2FASTJavaVisitor >> visitObjectStub: object [ "Previously tried to recreate stubs by deserializing their JSON representation, but getting a correct JSON string is a challenge." - self shouldBeImplemented + FamixUTStubError signal: object type ] { #category : 'visiting' } @@ -721,6 +738,25 @@ FamixValue2FASTJavaVisitor >> visitPrimitive: primitive [ yourself ] +{ #category : 'visiting' } +FamixValue2FASTJavaVisitor >> visitTypeReference: aFamixValueOfTypeReference [ + "Class xxx = MyClass.class;" + + ^ self statementBlock + addStatement: (model newVarDeclStatement + type: (self makeClassTypeExpression: 'Class'); + addDeclarator: (model newVariableDeclarator + variable: + (self makeVariableExpression: aFamixValueOfTypeReference); + expression: (model newClassProperty + type: + (self makeClassTypeExpression: + aFamixValueOfTypeReference value name); + fieldName: 'class')); + yourself); + yourself +] + { #category : 'visiting' } FamixValue2FASTJavaVisitor >> visitValueOfUnknownType: value [ diff --git a/src/Famix-Value-Exporter/FamixValueExporterError.class.st b/src/Famix-Value-Exporter/FamixValueExporterError.class.st new file mode 100644 index 0000000..4c41d95 --- /dev/null +++ b/src/Famix-Value-Exporter/FamixValueExporterError.class.st @@ -0,0 +1,7 @@ +Class { + #name : 'FamixValueExporterError', + #superclass : 'Error', + #category : 'Famix-Value-Exporter-Exceptions', + #package : 'Famix-Value-Exporter', + #tag : 'Exceptions' +} diff --git a/src/Famix-Value-Exporter/FamixValueHelperObjectExportStrategy.class.st b/src/Famix-Value-Exporter/FamixValueHelperObjectExportStrategy.class.st index 87fb5cd..f77c838 100644 --- a/src/Famix-Value-Exporter/FamixValueHelperObjectExportStrategy.class.st +++ b/src/Famix-Value-Exporter/FamixValueHelperObjectExportStrategy.class.st @@ -27,6 +27,10 @@ FamixValueHelperObjectExportStrategy >> buildMethodFor: object withParametersFor Use only the relevant attributes that are given, rather than all attributes." | model oldStatementBlock helper | + object type isPublic ifFalse: [ + FamixValueExporterError signal: + 'Cannot (yet) recreate object of non-public class: ' + , object type name ]. model := visitor model. "swap visitor context: the 'sheet' on which the visitor writes" oldStatementBlock := visitor statementBlock. @@ -93,10 +97,11 @@ FamixValueHelperObjectExportStrategy >> export: object on: visitor [ variable: (model newVariableExpression name: (visitor varNameFor: object)); - expression: (model newMethodInvocation - name: helper name; - arguments: (attributes collect: [ :attribute | - visitor makeVariableExpression: attribute value ]))); + expression: + (self + makeHelperInvocation: helper + arguments: attributes + on: visitor)); yourself) ] @@ -106,6 +111,29 @@ FamixValueHelperObjectExportStrategy >> initialize [ declarations := Dictionary new ] +{ #category : 'exporting' } +FamixValueHelperObjectExportStrategy >> makeHelperInvocation: helper arguments: arguments on: visitor [ + + | model | + model := visitor model. + ^ model newMethodInvocation + name: helper name; + arguments: (arguments + with: helper parameters + collect: [ :argument :parameter | "reference the value with a variable" + | ref | + ref := visitor makeVariableExpression: argument value. + ((argument value type name sameAs: 'long') not and: [ + (FASTJavaExportVisitor new export: parameter type) sameAs: + 'long' ]) + ifTrue: [ "try casting" + model newCastExpression + type: (model newClassTypeExpression typeName: + (model newTypeName name: 'long')); + expression: ref ] + ifFalse: [ ref ] ]) +] + { #category : 'ast' } FamixValueHelperObjectExportStrategy >> makeMethodFor: aFamixType withParametersFor: attributes on: visitor [ "Make the method entity, handles its signature and modifiers." @@ -144,7 +172,13 @@ FamixValueHelperObjectExportStrategy >> makeSetterInvocationsFor: attributes on: visitor makeSetterInvocation: setter for: attribute - named: attribute varName ] + named: attribute varName. + + "handle setters that can throw exceptions to rethrow an unchecked exception" + setter thrownExceptions ifNotEmpty: [ :exceptions | + visitor statementBlock addStatement: (visitor + makeTry: visitor statementBlock statements last + catch: exceptions) ] ] ifNil: [ visitor makeReflectionSetterInvocation: attribute ] ] ] diff --git a/src/Famix-Value-Exporter/FamixValueJavaArray.extension.st b/src/Famix-Value-Exporter/FamixValueJavaArray.extension.st new file mode 100644 index 0000000..a723552 --- /dev/null +++ b/src/Famix-Value-Exporter/FamixValueJavaArray.extension.st @@ -0,0 +1,12 @@ +Extension { #name : 'FamixValueJavaArray' } + +{ #category : '*Famix-Value-Exporter' } +FamixValueJavaArray >> decorate: aFamixJavaType asFASTJavaTypeExpressionOn: visitor [ + "Add array brackets to the type name." + + | expression | + expression := aFamixJavaType asFASTJavaTypeExpressionOn: visitor. + expression typeName name: + expression typeName name , ('[]' repeat: dimensions). + ^ expression +] diff --git a/src/Famix-Value-Exporter/FamixValueOfObject.extension.st b/src/Famix-Value-Exporter/FamixValueOfObject.extension.st index 4503b67..213fe1d 100644 --- a/src/Famix-Value-Exporter/FamixValueOfObject.extension.st +++ b/src/Famix-Value-Exporter/FamixValueOfObject.extension.st @@ -19,3 +19,19 @@ FamixValueOfObject >> asPharoInitializationAST [ receiver: (RBVariableNode named: self type name) selector: #new ] + +{ #category : '*Famix-Value-Exporter' } +FamixValueOfObject >> constructorSignature [ + + ^ String streamContents: [ :s | + s << self type name << '('. + value + do: [ :attribute | + attribute attribute declaredType + ifNotNil: [ :declaredType | s << declaredType name ] + ifNil: [ "TODO this should not be happening, fix parser then fix this + Use the name in the meantime, since this is only used for hashing at this moment, and that should keep the unicity" + attribute attribute name ] ] + separatedBy: [ s nextPut: $, ]. + s nextPut: $) ] +] diff --git a/src/Famix-Value-Exporter/FamixValueUnknownType.extension.st b/src/Famix-Value-Exporter/FamixValueUnknownType.extension.st index b2ecc19..41474b3 100644 --- a/src/Famix-Value-Exporter/FamixValueUnknownType.extension.st +++ b/src/Famix-Value-Exporter/FamixValueUnknownType.extension.st @@ -6,6 +6,24 @@ FamixValueUnknownType >> asFASTJavaTypeExpressionOn: visitor [ ^ visitor builder referType: self ] +{ #category : '*Famix-Value-Exporter' } +FamixValueUnknownType >> decorate: aFamixJavaType asFASTJavaTypeExpressionOn: visitor [ + + ^ self asFASTJavaTypeExpressionOn: visitor +] + +{ #category : '*Famix-Value-Exporter' } +FamixValueUnknownType >> fullyQualifiedNameOn: aFASTJavaModel [ + + ^ aFASTJavaModel newQualifiedName name: name +] + +{ #category : '*Famix-Value-Exporter' } +FamixValueUnknownType >> fullyQualifiedTypeNameOn: aFASTJavaModel [ + + ^ aFASTJavaModel newQualifiedTypeName name: name +] + { #category : '*Famix-Value-Exporter' } FamixValueUnknownType >> needsJavaImport [ diff --git a/src/Famix-Value-Generator/FamixValueGenerator.class.st b/src/Famix-Value-Generator/FamixValueGenerator.class.st index 8938d97..64cb862 100644 --- a/src/Famix-Value-Generator/FamixValueGenerator.class.st +++ b/src/Famix-Value-Generator/FamixValueGenerator.class.st @@ -139,7 +139,7 @@ FamixValueGenerator >> defineProperties [ { #category : 'definition' } FamixValueGenerator >> defineRelations [ - value *- (tType property: #values). + value *- (tType property: #valueInstances). value *- ((self remoteTrait: #TTypedEntity withPrefix: #Famix) property: #values). diff --git a/src/Famix-Value-Importer/Collection.extension.st b/src/Famix-Value-Importer/Collection.extension.st index 9607815..d5331b7 100644 --- a/src/Famix-Value-Importer/Collection.extension.st +++ b/src/Famix-Value-Importer/Collection.extension.st @@ -5,7 +5,12 @@ Collection >> asJavaJacksonValueOn: importer [ "List values are serialized as an array containing [1] the type name and [2] the array of elements." | type | - type := importer entityFinder findTypeNamed: (self at: 1). + type := self hasJavaJacksonTypeInformation ifTrue: [ + importer entityFinder findTypeNamed: (self at: 1) ]. + type ifNil: [ type := importer loadType ]. + + type mooseName = 'java::lang::Class' ifTrue: [ + ^ importer importTypeReference: (self at: 2) of: type ]. "might be an evident Jackson TypeInfo wrapper" self hasJavaJacksonTypeInformation ifTrue: [ @@ -16,11 +21,15 @@ Collection >> asJavaJacksonValueOn: importer [ ^ importer importEnumValue: (self at: 2) of: type ]. "might be a special object" - (importer importSpecialObject: (self at: 2) of: type) ifNotNil: [ - :value | ^ value ]. + type ifNotNil: [ + (importer importSpecialObject: (self at: 2) of: type) ifNotNil: [ + :value | ^ value ] ]. + + type isPrimitiveType ifTrue: [ "an array of primitives" + self shouldBeImplemented ]. "must be a regular list" - ^ importer importValueFromList: self of: importer loadType + ^ importer importValueFromList: self of: type ] { #category : '*Famix-Value-Importer' } @@ -43,5 +52,10 @@ Collection >> asPharoSTONValueOn: importer [ Collection >> hasJavaJacksonTypeInformation [ ^ self size = 2 and: [ - (self at: 1) isString and: [ (self at: 2) isString not ] ] + (self at: 1) ifNil: [ false ] ifNotNil: [ :first | + first isString and: [ + first isNotEmpty and: [ + (self at: 2) + ifNil: [ false ] + ifNotNil: [ :second | second isString not ] ] ] ] ] ] diff --git a/src/Famix-Value-Importer/FamixEntityFinder.class.st b/src/Famix-Value-Importer/FamixEntityFinder.class.st index e924ae8..7c0c1ed 100644 --- a/src/Famix-Value-Importer/FamixEntityFinder.class.st +++ b/src/Famix-Value-Importer/FamixEntityFinder.class.st @@ -49,7 +49,7 @@ FamixEntityFinder >> findMethodWithSignature: signature in: class [ self signatureOf: method matches: signature ]. candidates size = 1 ifTrue: [ ^ candidates anyOne ]. candidates ifEmpty: [ - NotFound signalFor: signature in: class methods ]. + FamixEntityNotFound signalFor: signature in: class ]. "consider returning a specific candidate; TODO: better" self error: 'Found multiple methods matching signature: ' , signature ] diff --git a/src/Famix-Value-Importer/FamixEntityNotFound.class.st b/src/Famix-Value-Importer/FamixEntityNotFound.class.st new file mode 100644 index 0000000..ae3cc3d --- /dev/null +++ b/src/Famix-Value-Importer/FamixEntityNotFound.class.st @@ -0,0 +1,13 @@ +Class { + #name : 'FamixEntityNotFound', + #superclass : 'NotFound', + #category : 'Famix-Value-Importer', + #package : 'Famix-Value-Importer' +} + +{ #category : 'private' } +FamixEntityNotFound >> standardMessageText [ + + ^ String streamContents: [ :stream | + stream << self object << ' not found in ' << self collection name ] +] diff --git a/src/Famix-Value-Importer/FamixJavaEntityFinder.class.st b/src/Famix-Value-Importer/FamixJavaEntityFinder.class.st index d1c7bba..3a384d4 100644 --- a/src/Famix-Value-Importer/FamixJavaEntityFinder.class.st +++ b/src/Famix-Value-Importer/FamixJavaEntityFinder.class.st @@ -108,7 +108,10 @@ FamixJavaEntityFinder >> translateFieldDescriptors: parameters on: stream [ do: [ :parameter | | translation index | translation := self translateFieldDescriptor: parameter. - index := translation lastIndexOf: $.. + index := translation + lastIndexOfAnyOf: '.$' + startingAt: translation size + ifAbsent: 0. stream nextPutAll: (index = 0 ifTrue: [ translation ] ifFalse: [ translation allButFirst: index ]) ] diff --git a/src/Famix-Value-Importer/FamixTClass.extension.st b/src/Famix-Value-Importer/FamixTClass.extension.st index 8fc40a6..ed96283 100644 --- a/src/Famix-Value-Importer/FamixTClass.extension.st +++ b/src/Famix-Value-Importer/FamixTClass.extension.st @@ -3,6 +3,8 @@ Extension { #name : 'FamixTClass' } { #category : '*Famix-Value-Importer' } FamixTClass >> findAttributeNamed: attributeName [ + (self isParametricEntity and: [ self isGenericEntity not ]) ifTrue: [ + ^ self genericEntity findAttributeNamed: attributeName ]. ^ (self cacheAt: #resolvedAttributes ifAbsentPut: [ Dictionary new ]) at: attributeName ifAbsentPut: [ diff --git a/src/Famix-Value-Importer/FamixValueAbstractImporter.class.st b/src/Famix-Value-Importer/FamixValueAbstractImporter.class.st index 48a8b1f..05fdad7 100644 --- a/src/Famix-Value-Importer/FamixValueAbstractImporter.class.st +++ b/src/Famix-Value-Importer/FamixValueAbstractImporter.class.st @@ -74,7 +74,7 @@ FamixValueAbstractImporter >> importCollection: rawValue of: type [ ] { #category : 'importing' } -FamixValueAbstractImporter >> importDictionary: rawValue of: type [ +FamixValueAbstractImporter >> importDictionary: rawDictionary of: type [ "infer from type arguments, e.g. Map" | dictionary keyType valueType assoc | @@ -84,15 +84,16 @@ FamixValueAbstractImporter >> importDictionary: rawValue of: type [ keyType := paramTypeInferences at: 1. valueType := paramTypeInferences at: 2 ] ifEmpty: [ keyType := valueType := nil ]. - rawValue associationsDo: [ :rawAssoc | + + self iterate: rawDictionary keysAndValuesDo: [ :rawKey :rawValue | assoc := self model newOfDictionaryAssociation dictionary: dictionary. self withTypeInference: keyType - do: [ assoc key: (self importValue: rawAssoc key) ]. + do: [ assoc key: (self importValue: rawKey) ]. self withTypeInference: valueType - do: [ assoc value: (self importValue: rawAssoc value) ] ]. + do: [ assoc value: (self importValue: rawValue) ] ]. ^ dictionary ] @@ -113,7 +114,7 @@ FamixValueAbstractImporter >> importObject: rawObject of: type [ object := self model newOfObject type: type. (self getObjectIdentity: rawObject) ifNotNil: [ :id | objectDict at: id put: object ]. - rawObject keysAndValuesDo: [ :name :value | + self iterate: rawObject keysAndValuesDo: [ :name :value | (self importObjectAttribute: value of: type named: name) ifNotNil: [ :attribute | attribute object: object ] ]. ^ object @@ -155,6 +156,12 @@ FamixValueAbstractImporter >> initialize [ self reset ] +{ #category : 'importing' } +FamixValueAbstractImporter >> iterate: rawObject keysAndValuesDo: aBlock [ + + rawObject keysAndValuesDo: aBlock +] + { #category : 'enumerating' } FamixValueAbstractImporter >> loadType [ "Return the inferred type if it exists, otherwise the type is unknown." diff --git a/src/Famix-Value-Importer/FamixValueImporterError.class.st b/src/Famix-Value-Importer/FamixValueImporterError.class.st new file mode 100644 index 0000000..46be330 --- /dev/null +++ b/src/Famix-Value-Importer/FamixValueImporterError.class.st @@ -0,0 +1,6 @@ +Class { + #name : 'FamixValueImporterError', + #superclass : 'Error', + #category : 'Famix-Value-Importer', + #package : 'Famix-Value-Importer' +} diff --git a/src/Famix-Value-Importer/FamixValueJavaJacksonImporter.class.st b/src/Famix-Value-Importer/FamixValueJavaJacksonImporter.class.st index 9dad0ad..c843351 100644 --- a/src/Famix-Value-Importer/FamixValueJavaJacksonImporter.class.st +++ b/src/Famix-Value-Importer/FamixValueJavaJacksonImporter.class.st @@ -34,13 +34,13 @@ FamixValueJavaJacksonImporter >> getObjectIdentity: rawObject [ "Keep track of objects by using the id given by Jackson. References to previously seen objects are serialized by using this id." - ^ rawObject removeKey: self idKey ifAbsent: nil + ^ rawObject at: self idKey ifAbsent: nil ] { #category : 'enumerating' } FamixValueJavaJacksonImporter >> getObjectType: rawObject [ - ^ rawObject removeKey: self typeKey ifAbsent: nil + ^ rawObject at: self typeKey ifAbsent: nil ] { #category : 'accessing' } @@ -58,20 +58,47 @@ FamixValueJavaJacksonImporter >> idKey: aString [ { #category : 'importing' } FamixValueJavaJacksonImporter >> importObjectAttribute: rawValue of: type named: name [ - | attribute | + | attribute inference | type isInterface ifTrue: [ Error signal: 'Cannot find attributes in interfaces. Signaled for attribute `' , name , '` and interface `' , type name , '`.' ]. - (attribute := type findAttributeNamed: name) ifNotNil: [ "Skip transient attributes." - attribute isTransient ifTrue: [ ^ nil ] ]. - ^ self - withTypeInference: - (attribute ifNotNil: [ attribute declaredType ]) - do: [ - self model newOfObjectAttribute - value: (self importValue: rawValue); - attribute: attribute ] + (attribute := type findAttributeNamed: name) + ifNil: [ + FamixValueImporterError signal: + 'Attribute `' , name , '` not found in hierarchy of `' + , type mooseName , '`' ] + ifNotNil: [ "Skip transient attributes." + attribute isTransient ifTrue: [ ^ nil ] ]. + + "If the attribute type is a TypeParameter, and the runtime type is a concretization + => inference is the concretization of the TypeParameter" + inference := nil. + attribute ifNotNil: [ + attribute declaredType ifNotNil: [ :declaredType | + declaredType isParameterType + ifFalse: [ "not parametric" inference := declaredType ] + ifTrue: [ + declaredType concretizations + detect: [ :paramType | + paramType concretizations first concreteEntity == type ] + ifFound: [ :paramType | + inference := paramType concreteParameter ] ] ] ]. + + (rawValue isCollection and: [ + inference isNotNil and: [ self isPrimitiveType: inference ] ]) + ifTrue: [ + ^ self model newOfObjectAttribute + value: (self + importCollection: rawValue + of: ((FamixValueJavaArray wrapping: inference) dimensions: + (self readDimensionsOfAttribute: attribute))); + attribute: attribute ]. + + ^ self withTypeInference: inference do: [ + self model newOfObjectAttribute + value: (self importValue: rawValue); + attribute: attribute ] ] { #category : 'importing' } @@ -130,7 +157,15 @@ FamixValueJavaJacksonImporter >> importValueFromList: rawValue of: type [ FamixValueJavaJacksonImporter >> isPrimitiveType: type [ ^ type isPrimitiveType or: [ "Classes wrapping primitives are also considered primitives." - type isPrimitiveWrapper ] + type isClass and: [ type isPrimitiveWrapper ] ] +] + +{ #category : 'importing' } +FamixValueJavaJacksonImporter >> iterate: rawValue keysAndValuesDo: aBlock [ + + rawValue keysAndValuesDo: [ :key :value | + (key = self idKey or: [ key = self typeKey ]) ifFalse: [ + aBlock value: key value: value ] ] ] { #category : 'parsing' } @@ -140,15 +175,46 @@ FamixValueJavaJacksonImporter >> parseList: serializedValues [ rawValues := super parseList: serializedValues. ^ rawValues hasJavaJacksonTypeInformation ifTrue: [ "ignore the type information of the top level list." - rawValues at: 2 ] + ^ rawValues "TODO only a specific version of jackson does this, investigate" + "rawValues at: 2" ] ifFalse: [ rawValues ] ] +{ #category : 'private - utility' } +FamixValueJavaJacksonImporter >> readDimensionsOfAttribute: attribute [ + + | source index char dimensions | + source := WriteStream on: ''. + attribute sourceAnchor fileReference readStreamDo: [ :rs | + 1 to: attribute sourceAnchor endPos do: [ :i | + source nextPut: rs next ]. + "read from endPos until: + - next declarator, eg. `int a, b` + - end of definition, eg. `int a;` + - initialization, eg. `int a = 1`" + [ ',;=' includes: (source nextPut: rs next) ] whileFalse. + source := source contents ]. + index := source size. + dimensions := 0. + [ "read backwards until: + - block opener, eg. `class { int a;` + - block closer, eg. `int f(){} int a;` + - end of statement, eg. int b; int a;" + char := source at: (index := index - 1). + char == $] + ifTrue: [ + dimensions := dimensions + 1. + false ] + ifFalse: [ '{};' includes: char ] ] whileFalse. + ^ dimensions +] + { #category : 'accessing' } FamixValueJavaJacksonImporter >> specialTypes [ ^ specialTypes ifNil: [ (specialTypes := Dictionary new) + at: 'java.util.Calendar' put: FamixValueJavaCalendar; at: 'java.util.Date' put: FamixValueJavaDate; at: 'java.sql.Date' put: FamixValueJavaSQLDate; at: 'java.sql.Timestamp' put: FamixValueJavaDate; diff --git a/src/Famix-Value-Importer/Integer.extension.st b/src/Famix-Value-Importer/Integer.extension.st index c8d3071..127b377 100644 --- a/src/Famix-Value-Importer/Integer.extension.st +++ b/src/Famix-Value-Importer/Integer.extension.st @@ -11,6 +11,10 @@ Integer >> asJavaJacksonValueOn: importer [ 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' + "if none of the above holds true, this must be a regular integer (or long)" + ^ importer + importPrimitive: self + of: ((self > 2147483647 or: [ self < -2147483648 ]) + ifTrue: [ 'long' ] + ifFalse: [ 'int' ]) ] diff --git a/src/Famix-Value-Importer/OrderedDictionary.extension.st b/src/Famix-Value-Importer/OrderedDictionary.extension.st index 426a509..64a4cfc 100644 --- a/src/Famix-Value-Importer/OrderedDictionary.extension.st +++ b/src/Famix-Value-Importer/OrderedDictionary.extension.st @@ -9,7 +9,11 @@ OrderedDictionary >> asJavaJacksonValueOn: importer [ ifNil: [ importer typeInference ifNil: [ Error signal: 'Cannot determine type.' ] ]. - ^ (type isUnknownType or: [ type isDictionaryType ]) + (type isUnknownType not and: [ type isParameterType ]) ifTrue: [ + Warning signal: + 'ParameterType should not be applicable as a value type?' ]. + ^ (type isUnknownType or: [ + type isDictionaryType or: [ type isParameterType ] ]) ifTrue: [ importer importDictionary: self of: type ] ifFalse: [ importer importObject: self of: type ] ] diff --git a/src/Famix-Value-Importer/String.extension.st b/src/Famix-Value-Importer/String.extension.st index 2aa74b3..1f900ca 100644 --- a/src/Famix-Value-Importer/String.extension.st +++ b/src/Famix-Value-Importer/String.extension.st @@ -3,16 +3,17 @@ Extension { #name : 'String' } { #category : '*Famix-Value-Importer' } String >> asJavaJacksonValueOn: importer [ - | typeInference | - typeInference := importer typeInference. - ^ (typeInference isNotNil and: [ typeInference name = 'Class' ]) - ifTrue: [ importer importTypeReference: self of: typeInference ] - ifFalse: [ "import regular string, escape special characters" - importer - importPrimitive: (self - copyWithRegex: '\\|"' - matchesTranslatedUsing: [ :match | match copyWithFirst: $\ ]) - of: 'java.lang.String' ] + importer typeInference ifNotNil: [ :typeInference | + typeInference name = 'Class' ifTrue: [ + ^ importer importTypeReference: self of: typeInference ]. + (typeInference usesFamixTrait: FamixTEnum) ifTrue: [ + ^ importer importEnumValue: self of: typeInference ] ]. + "import regular string, escape special characters" + ^ importer + importPrimitive: (self + copyWithRegex: '\\|"' + matchesTranslatedUsing: [ :match | match copyWithFirst: $\ ]) + of: 'java.lang.String' ] { #category : '*Famix-Value-Importer' } diff --git a/src/Famix-Value-Types/FamixValueJavaArray.class.st b/src/Famix-Value-Types/FamixValueJavaArray.class.st index 5d8bcba..1a978ec 100644 --- a/src/Famix-Value-Types/FamixValueJavaArray.class.st +++ b/src/Famix-Value-Types/FamixValueJavaArray.class.st @@ -4,15 +4,16 @@ Famix does not take dimensions into account because it is a dependency model. However, arrays are required to represent values faithfully, and that is my purpose. " Class { - #name : #FamixValueJavaArray, - #superclass : #FamixValueSpecialType, + #name : 'FamixValueJavaArray', + #superclass : 'FamixValueSpecialType', #instVars : [ 'dimensions' ], - #category : #'Famix-Value-Types' + #category : 'Famix-Value-Types', + #package : 'Famix-Value-Types' } -{ #category : #visiting } +{ #category : 'visiting' } FamixValueJavaArray >> acceptValueVisitor: visitor forCollection: array [ | model arrayType initializer | @@ -40,30 +41,19 @@ FamixValueJavaArray >> acceptValueVisitor: visitor forCollection: array [ yourself ] -{ #category : #visiting } -FamixValueJavaArray >> decorate: aFamixJavaType asFASTJavaTypeExpressionOn: visitor [ - "Add array brackets to the type name." - - | expression | - expression := aFamixJavaType asFASTJavaTypeExpressionOn: visitor. - expression typeName name: - expression typeName name , ('[]' repeat: dimensions). - ^ expression -] - -{ #category : #accessing } +{ #category : 'accessing' } FamixValueJavaArray >> dimensions [ ^ dimensions ] -{ #category : #accessing } +{ #category : 'accessing' } FamixValueJavaArray >> dimensions: anInteger [ dimensions := anInteger ] -{ #category : #importing } +{ #category : 'importing' } FamixValueJavaArray >> import: rawValue on: importer [ self shouldNotImplement diff --git a/src/Famix-Value-Types/FamixValueJavaCalendar.class.st b/src/Famix-Value-Types/FamixValueJavaCalendar.class.st new file mode 100644 index 0000000..3cd277d --- /dev/null +++ b/src/Famix-Value-Types/FamixValueJavaCalendar.class.st @@ -0,0 +1,19 @@ +" +A representation of `java.util.Calendar` and its subclasses. +They are serialized with a single `long` value, presumably(?) for the `time` attribute, which is ""the currently set time for this calendar, expressed in milliseconds after January 1, 1970, 0:00:00 GMT"". +" +Class { + #name : 'FamixValueJavaCalendar', + #superclass : 'FamixValueSpecialClass', + #category : 'Famix-Value-Types', + #package : 'Famix-Value-Types' +} + +{ #category : 'importing' } +FamixValueJavaCalendar >> importSpecial: rawValue on: importer [ + "No clue what the value is supposed to be, maybe the gregorianCutover? (long)" + + ^ importer model newOfPrimitiveType + value: rawValue; + type: (importer entityFinder findTypeNamed: 'long') +] diff --git a/src/Famix-Value-Types/FamixValueJavaDate.class.st b/src/Famix-Value-Types/FamixValueJavaDate.class.st index db0005e..ce3f121 100644 --- a/src/Famix-Value-Types/FamixValueJavaDate.class.st +++ b/src/Famix-Value-Types/FamixValueJavaDate.class.st @@ -3,12 +3,13 @@ A representation of Java date types such as `java.util.Date` or `java.sql.Timest This family of types has a special serialization format: all attributes are transient, and only a `long` is used to measure the distance to the epoch in milliseconds. " Class { - #name : #FamixValueJavaDate, - #superclass : #FamixValueSpecialClass, - #category : #'Famix-Value-Types' + #name : 'FamixValueJavaDate', + #superclass : 'FamixValueSpecialClass', + #category : 'Famix-Value-Types', + #package : 'Famix-Value-Types' } -{ #category : #visiting } +{ #category : 'visiting' } FamixValueJavaDate >> acceptValueVisitor: visitor forObject: object [ "Skip visiting the attribute, it is added as a constructor argument." @@ -17,7 +18,7 @@ FamixValueJavaDate >> acceptValueVisitor: visitor forObject: object [ yourself ] -{ #category : #importing } +{ #category : 'importing' } FamixValueJavaDate >> importSpecial: rawValue on: importer [ "The value is the distance to the epoch in milliseconds, represented with a long." @@ -26,7 +27,7 @@ FamixValueJavaDate >> importSpecial: rawValue on: importer [ type: (importer entityFinder findTypeNamed: 'long') ] -{ #category : #converting } +{ #category : 'converting' } FamixValueJavaDate >> value: date asFASTJavaExpressionOn: visitor [ "Add epoch time attribute as constructor argument." diff --git a/src/Famix-Value-Types/FamixValueJavaSQLDate.class.st b/src/Famix-Value-Types/FamixValueJavaSQLDate.class.st index f3f12a3..e42d62c 100644 --- a/src/Famix-Value-Types/FamixValueJavaSQLDate.class.st +++ b/src/Famix-Value-Types/FamixValueJavaSQLDate.class.st @@ -2,12 +2,13 @@ A representation of the `java.sql.Date` type which is serialized using a String representation. " Class { - #name : #FamixValueJavaSQLDate, - #superclass : #FamixValueJavaDate, - #category : #'Famix-Value-Types' + #name : 'FamixValueJavaSQLDate', + #superclass : 'FamixValueJavaDate', + #category : 'Famix-Value-Types', + #package : 'Famix-Value-Types' } -{ #category : #importing } +{ #category : 'importing' } FamixValueJavaSQLDate >> importSpecial: rawValue on: importer [ "The value is the string representation in 'yyyy-mm-dd' format." @@ -16,7 +17,7 @@ FamixValueJavaSQLDate >> importSpecial: rawValue on: importer [ type: (importer entityFinder findTypeNamed: 'String') ] -{ #category : #converting } +{ #category : 'converting' } FamixValueJavaSQLDate >> value: date asFASTJavaExpressionOn: visitor [ "Call java.sql.Date#valueOf(String) to recreate this date." diff --git a/src/Famix-Value-Types/FamixValueSpecialClass.class.st b/src/Famix-Value-Types/FamixValueSpecialClass.class.st index 0fed5b6..f4aa457 100644 --- a/src/Famix-Value-Types/FamixValueSpecialClass.class.st +++ b/src/Famix-Value-Types/FamixValueSpecialClass.class.st @@ -4,18 +4,19 @@ FamixValueSpecialClass represents a class that requires custom handling due to i My subclasses are responsible for implementing the specific behavior required to handle special classes in a particular language. " Class { - #name : #FamixValueSpecialClass, - #superclass : #FamixValueSpecialType, - #category : #'Famix-Value-Types' + #name : 'FamixValueSpecialClass', + #superclass : 'FamixValueSpecialType', + #category : 'Famix-Value-Types', + #package : 'Famix-Value-Types' } -{ #category : #testing } +{ #category : 'testing' } FamixValueSpecialClass class >> isAbstract [ ^ self == FamixValueSpecialClass ] -{ #category : #importing } +{ #category : 'importing' } FamixValueSpecialClass >> import: rawValue on: importer [ "Wrap the value as a field in an object." @@ -26,7 +27,7 @@ FamixValueSpecialClass >> import: rawValue on: importer [ yourself ] -{ #category : #importing } +{ #category : 'importing' } FamixValueSpecialClass >> importSpecial: rawValue on: importer [ "By default, let the value import itself. Redefine this method to implement specific import logic." diff --git a/src/Famix-Value-Types/FamixValueSpecialType.class.st b/src/Famix-Value-Types/FamixValueSpecialType.class.st index 5cf20fa..d9a81ad 100644 --- a/src/Famix-Value-Types/FamixValueSpecialType.class.st +++ b/src/Famix-Value-Types/FamixValueSpecialType.class.st @@ -6,54 +6,55 @@ These special types are wrapped using encapsulation, allowing for custom import My subclasses are responsible for implementing the specific behavior required to handle special types in a particular language. " Class { - #name : #FamixValueSpecialType, - #superclass : #Object, + #name : 'FamixValueSpecialType', + #superclass : 'Object', #instVars : [ 'type' ], - #category : #'Famix-Value-Types' + #category : 'Famix-Value-Types', + #package : 'Famix-Value-Types' } -{ #category : #'instance creation' } +{ #category : 'instance creation' } FamixValueSpecialType class >> import: rawValue wrapping: type on: importer [ "Wrap an object and use custom import mechanism." ^ (self new type: type) import: rawValue on: importer ] -{ #category : #testing } +{ #category : 'testing' } FamixValueSpecialType class >> isAbstract [ ^ self == FamixValueSpecialType ] -{ #category : #'instance creation' } +{ #category : 'instance creation' } FamixValueSpecialType class >> wrapping: aFamixTType [ "Wrap an object for custom import/export mechanisms." ^ self new type: aFamixTType ] -{ #category : #'reflective operations' } +{ #category : 'reflective operations' } FamixValueSpecialType >> doesNotUnderstand: aMessage [ "Defer to the wrapped type." ^ type perform: aMessage selector withArguments: aMessage arguments ] -{ #category : #importing } +{ #category : 'importing' } FamixValueSpecialType >> import: rawValue on: importer [ self subclassResponsibility ] -{ #category : #accessing } +{ #category : 'accessing' } FamixValueSpecialType >> type [ ^ type ] -{ #category : #accessing } +{ #category : 'accessing' } FamixValueSpecialType >> type: aFamixTType [ type := aFamixTType diff --git a/src/Famix-Value-Types/package.st b/src/Famix-Value-Types/package.st index 178ac48..e7e80ec 100644 --- a/src/Famix-Value-Types/package.st +++ b/src/Famix-Value-Types/package.st @@ -1 +1 @@ -Package { #name : #'Famix-Value-Types' } +Package { #name : 'Famix-Value-Types' }