diff --git a/spoon-smpl/src/main/java/spoon/smpl/Substitutor.java b/spoon-smpl/src/main/java/spoon/smpl/Substitutor.java index c402737c3a5..62eb8b0036a 100644 --- a/spoon-smpl/src/main/java/spoon/smpl/Substitutor.java +++ b/spoon-smpl/src/main/java/spoon/smpl/Substitutor.java @@ -99,6 +99,7 @@ import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtRecord; import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtTypeParameter; @@ -710,4 +711,9 @@ public void visitCtCasePattern(CtCasePattern casePattern) { public void visitCtRecordPattern(CtRecordPattern recordPattern) { throw new NotImplementedException("Not implemented"); } + + @Override + public void visitCtReceiverParameter(CtReceiverParameter receiverParameter) { + throw new NotImplementedException("Not implemented"); + } } diff --git a/spoon-smpl/src/main/java/spoon/smpl/pattern/PatternBuilder.java b/spoon-smpl/src/main/java/spoon/smpl/pattern/PatternBuilder.java index bd0c9423477..75b47bdf18c 100644 --- a/spoon-smpl/src/main/java/spoon/smpl/pattern/PatternBuilder.java +++ b/spoon-smpl/src/main/java/spoon/smpl/pattern/PatternBuilder.java @@ -96,6 +96,7 @@ import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtRecord; import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtTypeParameter; @@ -851,6 +852,10 @@ public void visitCtRecordPattern(CtRecordPattern recordPattern) { throw new NotImplementedException("Not implemented"); } + @Override + public void visitCtReceiverParameter(CtReceiverParameter receiverParameter) { + throw new NotImplementedException("Not implemented"); + } /** * Parameter identifiers. diff --git a/src/main/java/spoon/metamodel/Metamodel.java b/src/main/java/spoon/metamodel/Metamodel.java index 4688cffbbab..57f84aaa231 100644 --- a/src/main/java/spoon/metamodel/Metamodel.java +++ b/src/main/java/spoon/metamodel/Metamodel.java @@ -33,6 +33,7 @@ import spoon.reflect.declaration.CtModuleDirective; import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtRecord; import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtType; @@ -42,9 +43,9 @@ import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.filter.AllTypeMembersFunction; import spoon.reflect.visitor.filter.TypeFilter; -import spoon.support.adaption.TypeAdaptor; import spoon.support.DefaultCoreFactory; import spoon.support.StandardEnvironment; +import spoon.support.adaption.TypeAdaptor; import spoon.support.compiler.FileSystemFolder; /** @@ -195,6 +196,7 @@ public static Set> getAllMetamodelInterfaces() { result.add(factory.Type().get(CtModuleDirective.class)); result.add(factory.Type().get(CtRecordComponent.class)); result.add(factory.Type().get(CtRecord.class)); + result.add(factory.Type().get(CtReceiverParameter.class)); return result; } diff --git a/src/main/java/spoon/reflect/code/CtLambda.java b/src/main/java/spoon/reflect/code/CtLambda.java index 8dc57de15a5..f20e6d20aa7 100644 --- a/src/main/java/spoon/reflect/code/CtLambda.java +++ b/src/main/java/spoon/reflect/code/CtLambda.java @@ -7,8 +7,10 @@ */ package spoon.reflect.code; +import org.jspecify.annotations.Nullable; import spoon.reflect.declaration.CtExecutable; import spoon.reflect.declaration.CtMethod; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.reference.CtTypeReference; import spoon.support.DerivedProperty; import spoon.reflect.annotations.PropertyGetter; @@ -77,4 +79,11 @@ public interface CtLambda extends CtExpression, CtExecutable { @Override @UnsettableProperty > T1 setThrownTypes(Set> thrownTypes); + + @UnsettableProperty + CtExecutable setReceiverParameter(CtReceiverParameter receiverParameter); + + @UnsettableProperty + @Nullable + CtReceiverParameter getReceiverParameter(); } diff --git a/src/main/java/spoon/reflect/declaration/CtAnnotationMethod.java b/src/main/java/spoon/reflect/declaration/CtAnnotationMethod.java index 14d46ee015f..4f6760d4ed3 100644 --- a/src/main/java/spoon/reflect/declaration/CtAnnotationMethod.java +++ b/src/main/java/spoon/reflect/declaration/CtAnnotationMethod.java @@ -7,6 +7,7 @@ */ package spoon.reflect.declaration; +import org.jspecify.annotations.Nullable; import spoon.reflect.code.CtBodyHolder; import spoon.reflect.code.CtExpression; import spoon.reflect.code.CtStatement; @@ -54,4 +55,10 @@ public interface CtAnnotationMethod extends CtMethod { @Override @UnsettableProperty > T1 setParameters(List> parameters); + @UnsettableProperty + CtExecutable setReceiverParameter(CtReceiverParameter receiverParameter); + + @UnsettableProperty + @Nullable + CtReceiverParameter getReceiverParameter(); } diff --git a/src/main/java/spoon/reflect/declaration/CtAnonymousExecutable.java b/src/main/java/spoon/reflect/declaration/CtAnonymousExecutable.java index 8cea3e9d789..7de160ec7b7 100644 --- a/src/main/java/spoon/reflect/declaration/CtAnonymousExecutable.java +++ b/src/main/java/spoon/reflect/declaration/CtAnonymousExecutable.java @@ -7,6 +7,7 @@ */ package spoon.reflect.declaration; +import org.jspecify.annotations.Nullable; import spoon.reflect.reference.CtTypeReference; import spoon.support.UnsettableProperty; @@ -50,4 +51,12 @@ public interface CtAnonymousExecutable extends CtExecutable, CtTypeMember @UnsettableProperty > T addThrownType(CtTypeReference throwType); + + @UnsettableProperty + CtExecutable setReceiverParameter(CtReceiverParameter receiverParameter); + + @UnsettableProperty + @Nullable + CtReceiverParameter getReceiverParameter(); + } diff --git a/src/main/java/spoon/reflect/declaration/CtExecutable.java b/src/main/java/spoon/reflect/declaration/CtExecutable.java index 61550a6dbad..bfb9f593814 100644 --- a/src/main/java/spoon/reflect/declaration/CtExecutable.java +++ b/src/main/java/spoon/reflect/declaration/CtExecutable.java @@ -7,10 +7,12 @@ */ package spoon.reflect.declaration; +import org.jspecify.annotations.Nullable; import spoon.reflect.annotations.PropertyGetter; import spoon.reflect.annotations.PropertySetter; import spoon.reflect.code.CtBlock; import spoon.reflect.code.CtBodyHolder; +import spoon.reflect.path.CtRole; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtTypeReference; import spoon.support.DerivedProperty; @@ -140,4 +142,11 @@ public interface CtExecutable extends CtNamedElement, CtTypedElement, CtBo @Override CtExecutable clone(); + + @PropertySetter(role = CtRole.RECEIVER_PARAMETER) + CtExecutable setReceiverParameter(CtReceiverParameter receiverParameter); + + @PropertyGetter(role = CtRole.RECEIVER_PARAMETER) + @Nullable + CtReceiverParameter getReceiverParameter(); } diff --git a/src/main/java/spoon/reflect/declaration/CtReceiverParameter.java b/src/main/java/spoon/reflect/declaration/CtReceiverParameter.java new file mode 100644 index 00000000000..176c192ba05 --- /dev/null +++ b/src/main/java/spoon/reflect/declaration/CtReceiverParameter.java @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: (MIT OR CECILL-C) + * + * Copyright (C) 2006-2023 INRIA and contributors + * + * Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) or the Cecill-C License (see LICENSE-CECILL-C.txt). You as the user are entitled to choose the terms under which to adopt Spoon. + */ +package spoon.reflect.declaration; + + +import spoon.reflect.reference.CtTypeReference; +/** + * This element represents a class declaration. + * + *
{@code
+ * class Foo {
+ *   // this is a receiver parameter
+ *   void bar(Foo this) {
+ *   }
+ * }}
+ * 
+ */ +public interface CtReceiverParameter extends CtTypedElement, CtShadowable, CtElement { + + @Override + CtTypeReference getType(); + + @Override + CtReceiverParameter clone(); + +} diff --git a/src/main/java/spoon/reflect/factory/CoreFactory.java b/src/main/java/spoon/reflect/factory/CoreFactory.java index 9f7751f0761..19f27026089 100644 --- a/src/main/java/spoon/reflect/factory/CoreFactory.java +++ b/src/main/java/spoon/reflect/factory/CoreFactory.java @@ -78,27 +78,28 @@ import spoon.reflect.declaration.CtEnum; import spoon.reflect.declaration.CtEnumValue; import spoon.reflect.declaration.CtField; +import spoon.reflect.declaration.CtImport; import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtModule; +import spoon.reflect.declaration.CtModuleRequirement; +import spoon.reflect.declaration.CtPackage; +import spoon.reflect.declaration.CtPackageDeclaration; import spoon.reflect.declaration.CtPackageExport; +import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtRecord; import spoon.reflect.declaration.CtRecordComponent; -import spoon.reflect.declaration.CtPackage; -import spoon.reflect.declaration.CtPackageDeclaration; -import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtTypeParameter; import spoon.reflect.declaration.CtUsedService; import spoon.reflect.reference.CtArrayTypeReference; import spoon.reflect.reference.CtCatchVariableReference; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtFieldReference; -import spoon.reflect.declaration.CtImport; import spoon.reflect.reference.CtIntersectionTypeReference; import spoon.reflect.reference.CtLocalVariableReference; import spoon.reflect.reference.CtModuleReference; -import spoon.reflect.declaration.CtModuleRequirement; import spoon.reflect.reference.CtPackageReference; import spoon.reflect.reference.CtParameterReference; import spoon.reflect.reference.CtTypeMemberWildcardImportReference; @@ -653,4 +654,10 @@ BodyHolderSourcePosition createBodyHolderSourcePosition( * {@return a record pattern} */ CtRecordPattern createRecordPattern(); + + /** + * Creates a receiver parameter. + * @return the created receiver parameter. + */ + CtReceiverParameter createReceiverParameter(); } diff --git a/src/main/java/spoon/reflect/meta/impl/ModelRoleHandlers.java b/src/main/java/spoon/reflect/meta/impl/ModelRoleHandlers.java index 0a8b23212f0..a248f3d5eb3 100644 --- a/src/main/java/spoon/reflect/meta/impl/ModelRoleHandlers.java +++ b/src/main/java/spoon/reflect/meta/impl/ModelRoleHandlers.java @@ -6,7 +6,7 @@ * Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) or the Cecill-C License (see LICENSE-CECILL-C.txt). You as the user are entitled to choose the terms under which to adopt Spoon. */ package spoon.reflect.meta.impl; -import java.lang.annotation.Annotation; + import spoon.reflect.code.BinaryOperatorKind; import spoon.reflect.code.CaseKind; import spoon.reflect.code.CtAbstractInvocation; @@ -86,6 +86,7 @@ import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtRecord; import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtSealable; @@ -113,6 +114,8 @@ import spoon.reflect.reference.CtVariableReference; import spoon.reflect.reference.CtWildcardReference; import spoon.support.reflect.CtExtendedModifier; + +import java.lang.annotation.Annotation; /** * Contains implementations of {@link RoleHandler}s for all {@link CtRole}s of all model elements */ @@ -120,7 +123,7 @@ class ModelRoleHandlers { private ModelRoleHandlers() { } - static final RoleHandler[] roleHandlers = new RoleHandler[]{ new CtTypeAccess_ACCESSED_TYPE_RoleHandler(), new CtClass_ANNONYMOUS_EXECUTABLE_RoleHandler(), new CtElement_ANNOTATION_RoleHandler(), new CtAnnotation_ANNOTATION_TYPE_RoleHandler(), new CtAbstractInvocation_ARGUMENT_RoleHandler(), new CtExecutableReference_ARGUMENT_TYPE_RoleHandler(), new CtAssignment_ASSIGNED_RoleHandler(), new CtRHSReceiver_ASSIGNMENT_RoleHandler(), new CtBodyHolder_BODY_RoleHandler(), new CtSynchronized_BODY_RoleHandler(), new CtIntersectionTypeReference_BOUND_RoleHandler(), new CtWildcardReference_BOUNDING_TYPE_RoleHandler(), new CtAbstractSwitch_CASE_RoleHandler(), new CtCase_CASE_KIND_RoleHandler(), new CtExpression_CAST_RoleHandler(), new CtTry_CATCH_RoleHandler(), new CtElement_COMMENT_RoleHandler(), new CtComment_COMMENT_CONTENT_RoleHandler(), new CtJavaDocTag_COMMENT_CONTENT_RoleHandler(), new CtJavaDoc_COMMENT_TAG_RoleHandler(), new CtComment_COMMENT_TYPE_RoleHandler(), new CtConstructor_COMPACT_CONSTRUCTOR_RoleHandler(), new CtAssert_CONDITION_RoleHandler(), new CtCasePattern_CONDITION_RoleHandler(), new CtConditional_CONDITION_RoleHandler(), new CtIf_CONDITION_RoleHandler(), new CtClass_CONSTRUCTOR_RoleHandler(), new CtPackage_CONTAINED_TYPE_RoleHandler(), new CtCompilationUnit_DECLARED_IMPORT_RoleHandler(), new CtCompilationUnit_DECLARED_MODULE_RoleHandler(), new CtCompilationUnit_DECLARED_MODULE_REF_RoleHandler(), new CtCompilationUnit_DECLARED_TYPE_RoleHandler(), new CtCompilationUnit_DECLARED_TYPE_REF_RoleHandler(), new CtExecutableReference_DECLARING_TYPE_RoleHandler(), new CtFieldReference_DECLARING_TYPE_RoleHandler(), new CtTypeReference_DECLARING_TYPE_RoleHandler(), new CtAnnotationMethod_DEFAULT_EXPRESSION_RoleHandler(), new CtCase_DEFAULT_EXPRESSION_RoleHandler(), new CtVariable_DEFAULT_EXPRESSION_RoleHandler(), new CtNewArray_DIMENSION_RoleHandler(), new CtJavaDocTag_DOCUMENTATION_TYPE_RoleHandler(), new CtJavaDocTag_DOCUMENTATION_TYPE_REALNAME_RoleHandler(), new CtConditional_ELSE_RoleHandler(), new CtIf_ELSE_RoleHandler(), new CtModifiable_EMODIFIER_RoleHandler(), new CtAbstractInvocation_EXECUTABLE_REF_RoleHandler(), new CtExecutableReferenceExpression_EXECUTABLE_REF_RoleHandler(), new CtModule_EXPORTED_PACKAGE_RoleHandler(), new CtAbstractSwitch_EXPRESSION_RoleHandler(), new CtArrayAccess_EXPRESSION_RoleHandler(), new CtAssert_EXPRESSION_RoleHandler(), new CtCase_EXPRESSION_RoleHandler(), new CtDo_EXPRESSION_RoleHandler(), new CtFor_EXPRESSION_RoleHandler(), new CtForEach_EXPRESSION_RoleHandler(), new CtLambda_EXPRESSION_RoleHandler(), new CtNewArray_EXPRESSION_RoleHandler(), new CtReturn_EXPRESSION_RoleHandler(), new CtSynchronized_EXPRESSION_RoleHandler(), new CtThrow_EXPRESSION_RoleHandler(), new CtUnaryOperator_EXPRESSION_RoleHandler(), new CtWhile_EXPRESSION_RoleHandler(), new CtYieldStatement_EXPRESSION_RoleHandler(), new CtType_FIELD_RoleHandler(), new CtTry_FINALIZER_RoleHandler(), new CtForEach_FOREACH_VARIABLE_RoleHandler(), new CtFor_FOR_INIT_RoleHandler(), new CtFor_FOR_UPDATE_RoleHandler(), new CtProvidedService_IMPLEMENTATION_TYPE_RoleHandler(), new CtImport_IMPORT_REFERENCE_RoleHandler(), new CtType_INTERFACE_RoleHandler(), new CtTypeInformation_INTERFACE_RoleHandler(), new CtMethod_IS_DEFAULT_RoleHandler(), new CtFieldReference_IS_FINAL_RoleHandler(), new CtElement_IS_IMPLICIT_RoleHandler(), new CtLocalVariable_IS_INFERRED_RoleHandler(), new CtParameter_IS_INFERRED_RoleHandler(), new CtShadowable_IS_SHADOW_RoleHandler(), new CtExecutableReference_IS_STATIC_RoleHandler(), new CtFieldReference_IS_STATIC_RoleHandler(), new CtWildcardReference_IS_UPPER_RoleHandler(), new CtParameter_IS_VARARGS_RoleHandler(), new CtJavaDocTag_JAVADOC_TAG_VALUE_RoleHandler(), new CtStatement_LABEL_RoleHandler(), new CtBinaryOperator_LEFT_OPERAND_RoleHandler(), new CtLiteral_LITERAL_BASE_RoleHandler(), new CtType_METHOD_RoleHandler(), new CtModifiable_MODIFIER_RoleHandler(), new CtModule_MODIFIER_RoleHandler(), new CtModuleRequirement_MODIFIER_RoleHandler(), new CtTypeInformation_MODIFIER_RoleHandler(), new CtModule_MODULE_DIRECTIVE_RoleHandler(), new CtModuleRequirement_MODULE_REF_RoleHandler(), new CtPackageExport_MODULE_REF_RoleHandler(), new CtMultiTypedElement_MULTI_TYPE_RoleHandler(), new CtNamedElement_NAME_RoleHandler(), new CtReference_NAME_RoleHandler(), new CtNewClass_NESTED_TYPE_RoleHandler(), new CtType_NESTED_TYPE_RoleHandler(), new CtModule_OPENED_PACKAGE_RoleHandler(), new CtPackageExport_OPENED_PACKAGE_RoleHandler(), new CtBinaryOperator_OPERATOR_KIND_RoleHandler(), new CtOperatorAssignment_OPERATOR_KIND_RoleHandler(), new CtUnaryOperator_OPERATOR_KIND_RoleHandler(), new CtCompilationUnit_PACKAGE_DECLARATION_RoleHandler(), new CtPackageDeclaration_PACKAGE_REF_RoleHandler(), new CtPackageExport_PACKAGE_REF_RoleHandler(), new CtTypeReference_PACKAGE_REF_RoleHandler(), new CtCatch_PARAMETER_RoleHandler(), new CtExecutable_PARAMETER_RoleHandler(), new CtCasePattern_PATTERN_RoleHandler(), new CtRecordPattern_PATTERN_RoleHandler(), new CtSealable_PERMITTED_TYPE_RoleHandler(), new CtElement_POSITION_RoleHandler(), new CtModule_PROVIDED_SERVICE_RoleHandler(), new CtRecord_RECORD_COMPONENT_RoleHandler(), new CtModule_REQUIRED_MODULE_RoleHandler(), new CtBinaryOperator_RIGHT_OPERAND_RoleHandler(), new CtModule_SERVICE_TYPE_RoleHandler(), new CtProvidedService_SERVICE_TYPE_RoleHandler(), new CtUsedService_SERVICE_TYPE_RoleHandler(), new CtCodeSnippet_SNIPPET_RoleHandler(), new CtStatementList_STATEMENT_RoleHandler(), new CtModule_SUB_PACKAGE_RoleHandler(), new CtPackage_SUB_PACKAGE_RoleHandler(), new CtType_SUPER_TYPE_RoleHandler(), new CtTypeInformation_SUPER_TYPE_RoleHandler(), new CtTargetedExpression_TARGET_RoleHandler(), new CtLabelledFlowBreak_TARGET_LABEL_RoleHandler(), new CtConditional_THEN_RoleHandler(), new CtIf_THEN_RoleHandler(), new CtExecutable_THROWN_RoleHandler(), new CtTryWithResource_TRY_RESOURCE_RoleHandler(), new CtArrayTypeReference_TYPE_RoleHandler(), new CtExecutableReference_TYPE_RoleHandler(), new CtTypedElement_TYPE_RoleHandler(), new CtVariableReference_TYPE_RoleHandler(), new CtActualTypeContainer_TYPE_ARGUMENT_RoleHandler(), new CtType_TYPE_MEMBER_RoleHandler(), new CtFormalTypeDeclarer_TYPE_PARAMETER_RoleHandler(), new CtRecordPattern_TYPE_REF_RoleHandler(), new CtTypeMemberWildcardImportReference_TYPE_REF_RoleHandler(), new CtAnnotation_VALUE_RoleHandler(), new CtEnum_VALUE_RoleHandler(), new CtLiteral_VALUE_RoleHandler(), new CtTextBlock_VALUE_RoleHandler(), new CtTypePattern_VARIABLE_RoleHandler(), new CtVariableAccess_VARIABLE_RoleHandler() }; + static final RoleHandler[] roleHandlers = new RoleHandler[]{ new CtTypeAccess_ACCESSED_TYPE_RoleHandler(), new CtClass_ANNONYMOUS_EXECUTABLE_RoleHandler(), new CtElement_ANNOTATION_RoleHandler(), new CtAnnotation_ANNOTATION_TYPE_RoleHandler(), new CtAbstractInvocation_ARGUMENT_RoleHandler(), new CtExecutableReference_ARGUMENT_TYPE_RoleHandler(), new CtAssignment_ASSIGNED_RoleHandler(), new CtRHSReceiver_ASSIGNMENT_RoleHandler(), new CtBodyHolder_BODY_RoleHandler(), new CtSynchronized_BODY_RoleHandler(), new CtIntersectionTypeReference_BOUND_RoleHandler(), new CtWildcardReference_BOUNDING_TYPE_RoleHandler(), new CtAbstractSwitch_CASE_RoleHandler(), new CtCase_CASE_KIND_RoleHandler(), new CtExpression_CAST_RoleHandler(), new CtTry_CATCH_RoleHandler(), new CtElement_COMMENT_RoleHandler(), new CtComment_COMMENT_CONTENT_RoleHandler(), new CtJavaDocTag_COMMENT_CONTENT_RoleHandler(), new CtJavaDoc_COMMENT_TAG_RoleHandler(), new CtComment_COMMENT_TYPE_RoleHandler(), new CtConstructor_COMPACT_CONSTRUCTOR_RoleHandler(), new CtAssert_CONDITION_RoleHandler(), new CtCasePattern_CONDITION_RoleHandler(), new CtConditional_CONDITION_RoleHandler(), new CtIf_CONDITION_RoleHandler(), new CtClass_CONSTRUCTOR_RoleHandler(), new CtPackage_CONTAINED_TYPE_RoleHandler(), new CtCompilationUnit_DECLARED_IMPORT_RoleHandler(), new CtCompilationUnit_DECLARED_MODULE_RoleHandler(), new CtCompilationUnit_DECLARED_MODULE_REF_RoleHandler(), new CtCompilationUnit_DECLARED_TYPE_RoleHandler(), new CtCompilationUnit_DECLARED_TYPE_REF_RoleHandler(), new CtExecutableReference_DECLARING_TYPE_RoleHandler(), new CtFieldReference_DECLARING_TYPE_RoleHandler(), new CtTypeReference_DECLARING_TYPE_RoleHandler(), new CtAnnotationMethod_DEFAULT_EXPRESSION_RoleHandler(), new CtCase_DEFAULT_EXPRESSION_RoleHandler(), new CtVariable_DEFAULT_EXPRESSION_RoleHandler(), new CtNewArray_DIMENSION_RoleHandler(), new CtJavaDocTag_DOCUMENTATION_TYPE_RoleHandler(), new CtJavaDocTag_DOCUMENTATION_TYPE_REALNAME_RoleHandler(), new CtConditional_ELSE_RoleHandler(), new CtIf_ELSE_RoleHandler(), new CtModifiable_EMODIFIER_RoleHandler(), new CtAbstractInvocation_EXECUTABLE_REF_RoleHandler(), new CtExecutableReferenceExpression_EXECUTABLE_REF_RoleHandler(), new CtModule_EXPORTED_PACKAGE_RoleHandler(), new CtAbstractSwitch_EXPRESSION_RoleHandler(), new CtArrayAccess_EXPRESSION_RoleHandler(), new CtAssert_EXPRESSION_RoleHandler(), new CtCase_EXPRESSION_RoleHandler(), new CtDo_EXPRESSION_RoleHandler(), new CtFor_EXPRESSION_RoleHandler(), new CtForEach_EXPRESSION_RoleHandler(), new CtLambda_EXPRESSION_RoleHandler(), new CtNewArray_EXPRESSION_RoleHandler(), new CtReturn_EXPRESSION_RoleHandler(), new CtSynchronized_EXPRESSION_RoleHandler(), new CtThrow_EXPRESSION_RoleHandler(), new CtUnaryOperator_EXPRESSION_RoleHandler(), new CtWhile_EXPRESSION_RoleHandler(), new CtYieldStatement_EXPRESSION_RoleHandler(), new CtType_FIELD_RoleHandler(), new CtTry_FINALIZER_RoleHandler(), new CtForEach_FOREACH_VARIABLE_RoleHandler(), new CtFor_FOR_INIT_RoleHandler(), new CtFor_FOR_UPDATE_RoleHandler(), new CtProvidedService_IMPLEMENTATION_TYPE_RoleHandler(), new CtImport_IMPORT_REFERENCE_RoleHandler(), new CtType_INTERFACE_RoleHandler(), new CtTypeInformation_INTERFACE_RoleHandler(), new CtMethod_IS_DEFAULT_RoleHandler(), new CtFieldReference_IS_FINAL_RoleHandler(), new CtElement_IS_IMPLICIT_RoleHandler(), new CtLocalVariable_IS_INFERRED_RoleHandler(), new CtParameter_IS_INFERRED_RoleHandler(), new CtShadowable_IS_SHADOW_RoleHandler(), new CtExecutableReference_IS_STATIC_RoleHandler(), new CtFieldReference_IS_STATIC_RoleHandler(), new CtWildcardReference_IS_UPPER_RoleHandler(), new CtParameter_IS_VARARGS_RoleHandler(), new CtJavaDocTag_JAVADOC_TAG_VALUE_RoleHandler(), new CtStatement_LABEL_RoleHandler(), new CtBinaryOperator_LEFT_OPERAND_RoleHandler(), new CtLiteral_LITERAL_BASE_RoleHandler(), new CtType_METHOD_RoleHandler(), new CtModifiable_MODIFIER_RoleHandler(), new CtModule_MODIFIER_RoleHandler(), new CtModuleRequirement_MODIFIER_RoleHandler(), new CtTypeInformation_MODIFIER_RoleHandler(), new CtModule_MODULE_DIRECTIVE_RoleHandler(), new CtModuleRequirement_MODULE_REF_RoleHandler(), new CtPackageExport_MODULE_REF_RoleHandler(), new CtMultiTypedElement_MULTI_TYPE_RoleHandler(), new CtNamedElement_NAME_RoleHandler(), new CtReference_NAME_RoleHandler(), new CtNewClass_NESTED_TYPE_RoleHandler(), new CtType_NESTED_TYPE_RoleHandler(), new CtModule_OPENED_PACKAGE_RoleHandler(), new CtPackageExport_OPENED_PACKAGE_RoleHandler(), new CtBinaryOperator_OPERATOR_KIND_RoleHandler(), new CtOperatorAssignment_OPERATOR_KIND_RoleHandler(), new CtUnaryOperator_OPERATOR_KIND_RoleHandler(), new CtCompilationUnit_PACKAGE_DECLARATION_RoleHandler(), new CtPackageDeclaration_PACKAGE_REF_RoleHandler(), new CtPackageExport_PACKAGE_REF_RoleHandler(), new CtTypeReference_PACKAGE_REF_RoleHandler(), new CtCatch_PARAMETER_RoleHandler(), new CtExecutable_PARAMETER_RoleHandler(), new CtCasePattern_PATTERN_RoleHandler(), new CtRecordPattern_PATTERN_RoleHandler(), new CtSealable_PERMITTED_TYPE_RoleHandler(), new CtElement_POSITION_RoleHandler(), new CtModule_PROVIDED_SERVICE_RoleHandler(), new CtExecutable_RECEIVER_PARAMETER_RoleHandler(), new CtRecord_RECORD_COMPONENT_RoleHandler(), new CtModule_REQUIRED_MODULE_RoleHandler(), new CtBinaryOperator_RIGHT_OPERAND_RoleHandler(), new CtModule_SERVICE_TYPE_RoleHandler(), new CtProvidedService_SERVICE_TYPE_RoleHandler(), new CtUsedService_SERVICE_TYPE_RoleHandler(), new CtCodeSnippet_SNIPPET_RoleHandler(), new CtStatementList_STATEMENT_RoleHandler(), new CtModule_SUB_PACKAGE_RoleHandler(), new CtPackage_SUB_PACKAGE_RoleHandler(), new CtType_SUPER_TYPE_RoleHandler(), new CtTypeInformation_SUPER_TYPE_RoleHandler(), new CtTargetedExpression_TARGET_RoleHandler(), new CtLabelledFlowBreak_TARGET_LABEL_RoleHandler(), new CtConditional_THEN_RoleHandler(), new CtIf_THEN_RoleHandler(), new CtExecutable_THROWN_RoleHandler(), new CtTryWithResource_TRY_RESOURCE_RoleHandler(), new CtArrayTypeReference_TYPE_RoleHandler(), new CtExecutableReference_TYPE_RoleHandler(), new CtTypedElement_TYPE_RoleHandler(), new CtVariableReference_TYPE_RoleHandler(), new CtActualTypeContainer_TYPE_ARGUMENT_RoleHandler(), new CtType_TYPE_MEMBER_RoleHandler(), new CtFormalTypeDeclarer_TYPE_PARAMETER_RoleHandler(), new CtRecordPattern_TYPE_REF_RoleHandler(), new CtTypeMemberWildcardImportReference_TYPE_REF_RoleHandler(), new CtAnnotation_VALUE_RoleHandler(), new CtEnum_VALUE_RoleHandler(), new CtLiteral_VALUE_RoleHandler(), new CtTextBlock_VALUE_RoleHandler(), new CtTypePattern_VARIABLE_RoleHandler(), new CtVariableAccess_VARIABLE_RoleHandler() }; static class CtVariableAccess_VARIABLE_RoleHandler extends SingleHandler> { private CtVariableAccess_VARIABLE_RoleHandler() { @@ -678,6 +681,23 @@ public void setValue(T element, U value) { } } + static class CtExecutable_RECEIVER_PARAMETER_RoleHandler extends SingleHandler { + private CtExecutable_RECEIVER_PARAMETER_RoleHandler() { + super(CtRole.RECEIVER_PARAMETER, CtExecutable.class, CtReceiverParameter.class); + } + + @SuppressWarnings("unchecked") + @Override + public U getValue(T element) { + return ((U) (Object) (castTarget(element).getReceiverParameter())); + } + + @Override + public void setValue(T element, U value) { + castTarget(element).setReceiverParameter(castValue(value)); + } + } + static class CtModule_PROVIDED_SERVICE_RoleHandler extends ListHandler { private CtModule_PROVIDED_SERVICE_RoleHandler() { super(CtRole.PROVIDED_SERVICE, CtModule.class, CtProvidedService.class); diff --git a/src/main/java/spoon/reflect/path/CtRole.java b/src/main/java/spoon/reflect/path/CtRole.java index e3b151d6617..eaf76ac785e 100644 --- a/src/main/java/spoon/reflect/path/CtRole.java +++ b/src/main/java/spoon/reflect/path/CtRole.java @@ -122,7 +122,8 @@ public enum CtRole { RECORD_COMPONENT, COMPACT_CONSTRUCTOR, PERMITTED_TYPE, - PATTERN; + PATTERN, + RECEIVER_PARAMETER; private final CtRole superRole; private final List subRoles; diff --git a/src/main/java/spoon/reflect/visitor/CtAbstractVisitor.java b/src/main/java/spoon/reflect/visitor/CtAbstractVisitor.java index 3837628b15f..de90a697751 100644 --- a/src/main/java/spoon/reflect/visitor/CtAbstractVisitor.java +++ b/src/main/java/spoon/reflect/visitor/CtAbstractVisitor.java @@ -7,6 +7,8 @@ */ package spoon.reflect.visitor; +import java.lang.annotation.Annotation; + import spoon.reflect.code.CtAnnotationFieldAccess; import spoon.reflect.code.CtArrayRead; import spoon.reflect.code.CtArrayWrite; @@ -71,36 +73,35 @@ import spoon.reflect.declaration.CtEnum; import spoon.reflect.declaration.CtEnumValue; import spoon.reflect.declaration.CtField; +import spoon.reflect.declaration.CtImport; import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtModule; -import spoon.reflect.declaration.CtPackageExport; -import spoon.reflect.declaration.CtProvidedService; -import spoon.reflect.declaration.CtRecord; -import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtModuleRequirement; import spoon.reflect.declaration.CtPackage; import spoon.reflect.declaration.CtPackageDeclaration; +import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtParameter; +import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; +import spoon.reflect.declaration.CtRecord; +import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtTypeParameter; import spoon.reflect.declaration.CtUsedService; import spoon.reflect.reference.CtArrayTypeReference; import spoon.reflect.reference.CtCatchVariableReference; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtFieldReference; -import spoon.reflect.declaration.CtImport; import spoon.reflect.reference.CtIntersectionTypeReference; import spoon.reflect.reference.CtLocalVariableReference; import spoon.reflect.reference.CtModuleReference; import spoon.reflect.reference.CtPackageReference; import spoon.reflect.reference.CtParameterReference; +import spoon.reflect.reference.CtTypeMemberWildcardImportReference; import spoon.reflect.reference.CtTypeParameterReference; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.reference.CtUnboundVariableReference; import spoon.reflect.reference.CtWildcardReference; -import spoon.reflect.reference.CtTypeMemberWildcardImportReference; - -import java.lang.annotation.Annotation; /** Provides an empty implementation of CtVisitor. * See {@link CtScanner} for a much more powerful implementation of CtVisitor. @@ -559,6 +560,10 @@ public void visitCtRecordComponent(CtRecordComponent recordComponent) { @Override public void visitCtCasePattern(CtCasePattern casePattern) { + } + @Override + public void visitCtReceiverParameter(CtReceiverParameter receiverParameter) { + } @Override diff --git a/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java b/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java index ff32f221322..c5f4745f3da 100644 --- a/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java +++ b/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java @@ -242,6 +242,7 @@ public void visitCtConstructor(final spoon.reflect.declaration.CtConstructor spoon.reflect.declaration.CtConstructor other = ((spoon.reflect.declaration.CtConstructor) (this.stack.peek())); enter(c); biScan(spoon.reflect.path.CtRole.ANNOTATION, c.getAnnotations(), other.getAnnotations()); + biScan(spoon.reflect.path.CtRole.RECEIVER_PARAMETER, c.getReceiverParameter(), other.getReceiverParameter()); biScan(spoon.reflect.path.CtRole.PARAMETER, c.getParameters(), other.getParameters()); biScan(spoon.reflect.path.CtRole.THROWN, c.getThrownTypes(), other.getThrownTypes()); biScan(spoon.reflect.path.CtRole.TYPE_PARAMETER, c.getFormalCtTypeParameters(), other.getFormalCtTypeParameters()); @@ -484,6 +485,7 @@ public void visitCtMethod(final spoon.reflect.declaration.CtMethod m) { biScan(spoon.reflect.path.CtRole.ANNOTATION, m.getAnnotations(), other.getAnnotations()); biScan(spoon.reflect.path.CtRole.TYPE_PARAMETER, m.getFormalCtTypeParameters(), other.getFormalCtTypeParameters()); biScan(spoon.reflect.path.CtRole.TYPE, m.getType(), other.getType()); + biScan(spoon.reflect.path.CtRole.RECEIVER_PARAMETER, m.getReceiverParameter(), other.getReceiverParameter()); biScan(spoon.reflect.path.CtRole.PARAMETER, m.getParameters(), other.getParameters()); biScan(spoon.reflect.path.CtRole.THROWN, m.getThrownTypes(), other.getThrownTypes()); biScan(spoon.reflect.path.CtRole.BODY, m.getBody(), other.getBody()); @@ -1080,6 +1082,17 @@ public void visitCtRecordComponent(spoon.reflect.declaration.CtRecordComponent r exit(recordType); } + // autogenerated by CtBiScannerGenerator + @java.lang.Override + public void visitCtReceiverParameter(spoon.reflect.declaration.CtReceiverParameter receiverParameter) { + spoon.reflect.declaration.CtReceiverParameter other = ((spoon.reflect.declaration.CtReceiverParameter) (this.stack.peek())); + enter(receiverParameter); + biScan(spoon.reflect.path.CtRole.ANNOTATION, receiverParameter.getAnnotations(), other.getAnnotations()); + biScan(spoon.reflect.path.CtRole.TYPE, receiverParameter.getType(), other.getType()); + biScan(spoon.reflect.path.CtRole.COMMENT, receiverParameter.getComments(), other.getComments()); + exit(receiverParameter); + } + // autogenerated by CtBiScannerGenerator @java.lang.Override public void visitCtCasePattern(spoon.reflect.code.CtCasePattern casePattern) { @@ -1090,7 +1103,6 @@ public void visitCtCasePattern(spoon.reflect.code.CtCasePattern casePattern) { biScan(spoon.reflect.path.CtRole.PATTERN, casePattern.getPattern(), other.getPattern()); biScan(spoon.reflect.path.CtRole.CONDITION, casePattern.getGuard(), other.getGuard()); biScan(spoon.reflect.path.CtRole.TYPE, casePattern.getType(), other.getType()); - biScan(spoon.reflect.path.CtRole.COMMENT, casePattern.getComments(), other.getComments()); exit(casePattern); } diff --git a/src/main/java/spoon/reflect/visitor/CtInheritanceScanner.java b/src/main/java/spoon/reflect/visitor/CtInheritanceScanner.java index 7461597a89e..764aa0e3697 100644 --- a/src/main/java/spoon/reflect/visitor/CtInheritanceScanner.java +++ b/src/main/java/spoon/reflect/visitor/CtInheritanceScanner.java @@ -97,6 +97,7 @@ import spoon.reflect.declaration.CtModuleDirective; import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtRecord; import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtModuleRequirement; @@ -1123,5 +1124,12 @@ public void visitCtRecordPattern(CtRecordPattern pattern) { scanCtVisitable(pattern); } + @Override + public void visitCtReceiverParameter(CtReceiverParameter e) { + scanCtTypedElement(e); + scanCtElement(e); + scanCtVisitable(e); + scanCtShadowable(e); + } } diff --git a/src/main/java/spoon/reflect/visitor/CtScanner.java b/src/main/java/spoon/reflect/visitor/CtScanner.java index a92d2526d04..4637485f1ae 100644 --- a/src/main/java/spoon/reflect/visitor/CtScanner.java +++ b/src/main/java/spoon/reflect/visitor/CtScanner.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Map; + import spoon.reflect.code.CtAnnotationFieldAccess; import spoon.reflect.code.CtArrayRead; import spoon.reflect.code.CtArrayWrite; @@ -78,17 +79,19 @@ import spoon.reflect.declaration.CtEnum; import spoon.reflect.declaration.CtEnumValue; import spoon.reflect.declaration.CtField; +import spoon.reflect.declaration.CtImport; import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtModule; -import spoon.reflect.declaration.CtPackageExport; -import spoon.reflect.declaration.CtProvidedService; -import spoon.reflect.declaration.CtRecord; -import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtModuleRequirement; import spoon.reflect.declaration.CtPackage; import spoon.reflect.declaration.CtPackageDeclaration; +import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtParameter; +import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; +import spoon.reflect.declaration.CtRecord; +import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtTypeParameter; import spoon.reflect.declaration.CtUsedService; import spoon.reflect.path.CtRole; @@ -96,17 +99,16 @@ import spoon.reflect.reference.CtCatchVariableReference; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtFieldReference; -import spoon.reflect.declaration.CtImport; import spoon.reflect.reference.CtIntersectionTypeReference; import spoon.reflect.reference.CtLocalVariableReference; import spoon.reflect.reference.CtModuleReference; import spoon.reflect.reference.CtPackageReference; import spoon.reflect.reference.CtParameterReference; +import spoon.reflect.reference.CtTypeMemberWildcardImportReference; import spoon.reflect.reference.CtTypeParameterReference; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.reference.CtUnboundVariableReference; import spoon.reflect.reference.CtWildcardReference; -import spoon.reflect.reference.CtTypeMemberWildcardImportReference; /** * This visitor implements a deep-search scan on the model. @@ -386,6 +388,7 @@ public void visitCtConditional(final CtConditional conditional) { public void visitCtConstructor(final CtConstructor c) { enter(c); scan(CtRole.ANNOTATION, c.getAnnotations()); + scan(CtRole.RECEIVER_PARAMETER, c.getReceiverParameter()); scan(CtRole.PARAMETER, c.getParameters()); scan(CtRole.THROWN, c.getThrownTypes()); scan(CtRole.TYPE_PARAMETER, c.getFormalCtTypeParameters()); @@ -586,6 +589,7 @@ public void visitCtMethod(final CtMethod m) { scan(CtRole.ANNOTATION, m.getAnnotations()); scan(CtRole.TYPE_PARAMETER, m.getFormalCtTypeParameters()); scan(CtRole.TYPE, m.getType()); + scan(CtRole.RECEIVER_PARAMETER, m.getReceiverParameter()); scan(CtRole.PARAMETER, m.getParameters()); scan(CtRole.THROWN, m.getThrownTypes()); scan(CtRole.BODY, m.getBody()); @@ -1080,6 +1084,15 @@ public void visitCtRecordComponent(CtRecordComponent recordType) { exit(recordType); } + @Override + public void visitCtReceiverParameter(CtReceiverParameter receiverParameter) { + enter(receiverParameter); + scan(CtRole.ANNOTATION, receiverParameter.getAnnotations()); + scan(CtRole.TYPE, receiverParameter.getType()); + scan(CtRole.COMMENT, receiverParameter.getComments()); + exit(receiverParameter); + } + @Override public void visitCtCasePattern(CtCasePattern casePattern) { enter(casePattern); diff --git a/src/main/java/spoon/reflect/visitor/CtVisitor.java b/src/main/java/spoon/reflect/visitor/CtVisitor.java index 60cb7ae10c5..74c5a376e58 100644 --- a/src/main/java/spoon/reflect/visitor/CtVisitor.java +++ b/src/main/java/spoon/reflect/visitor/CtVisitor.java @@ -7,6 +7,8 @@ */ package spoon.reflect.visitor; +import java.lang.annotation.Annotation; + import spoon.reflect.code.CtAnnotationFieldAccess; import spoon.reflect.code.CtArrayRead; import spoon.reflect.code.CtArrayWrite; @@ -71,36 +73,35 @@ import spoon.reflect.declaration.CtEnum; import spoon.reflect.declaration.CtEnumValue; import spoon.reflect.declaration.CtField; +import spoon.reflect.declaration.CtImport; import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtModule; -import spoon.reflect.declaration.CtPackageExport; -import spoon.reflect.declaration.CtProvidedService; -import spoon.reflect.declaration.CtRecord; -import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtModuleRequirement; import spoon.reflect.declaration.CtPackage; import spoon.reflect.declaration.CtPackageDeclaration; +import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtParameter; +import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; +import spoon.reflect.declaration.CtRecord; +import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtTypeParameter; import spoon.reflect.declaration.CtUsedService; import spoon.reflect.reference.CtArrayTypeReference; import spoon.reflect.reference.CtCatchVariableReference; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtFieldReference; -import spoon.reflect.declaration.CtImport; import spoon.reflect.reference.CtIntersectionTypeReference; import spoon.reflect.reference.CtLocalVariableReference; import spoon.reflect.reference.CtModuleReference; import spoon.reflect.reference.CtPackageReference; import spoon.reflect.reference.CtParameterReference; +import spoon.reflect.reference.CtTypeMemberWildcardImportReference; import spoon.reflect.reference.CtTypeParameterReference; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.reference.CtUnboundVariableReference; import spoon.reflect.reference.CtWildcardReference; -import spoon.reflect.reference.CtTypeMemberWildcardImportReference; - -import java.lang.annotation.Annotation; /** * This interface defines the visitor for the Spoon metamodel, as defined in @@ -570,4 +571,10 @@ void visitCtOperatorAssignment( * @param recordPattern the record pattern to visit. */ void visitCtRecordPattern(CtRecordPattern recordPattern); + + /** + * Visits a receiver parameter. + * @param receiverParameter the receiver parameter to visit. + */ + void visitCtReceiverParameter(CtReceiverParameter receiverParameter); } diff --git a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java index 995569c8d3d..57389c94573 100644 --- a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java +++ b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java @@ -100,6 +100,7 @@ import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtRecord; import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtType; @@ -2359,4 +2360,22 @@ public void visitCtRecordPattern(CtRecordPattern recordPattern) { elementPrinterHelper.printList(recordPattern.getPatternList(), null, false, "(", false, false, ",", true, false, ")", this::scan); } + + @Override + public void visitCtReceiverParameter(CtReceiverParameter receiverParameter) { + elementPrinterHelper.writeComment(receiverParameter); + elementPrinterHelper.writeAnnotations(receiverParameter); + + printer.writeIdentifier(receiverParameter.getType().getSimpleName()); + printer.writeSpace(); + // if the receiver parameter is in an inner class, we need to print the outer class name + boolean isInnerClass = !receiverParameter.getType().getTopLevelType().getQualifiedName().equals(receiverParameter.getParent(CtType.class).getQualifiedName()); + boolean isConstructor = receiverParameter.getParent() instanceof CtConstructor; + if (isConstructor && isInnerClass) { + // inside a ctor of an inner class, the identifier is $SimpleName.this + printer.writeSeparator(receiverParameter.getType().getSimpleName() + ".this"); + } else { + printer.writeSeparator("this"); + } + } } diff --git a/src/main/java/spoon/reflect/visitor/ElementPrinterHelper.java b/src/main/java/spoon/reflect/visitor/ElementPrinterHelper.java index a7ea652182d..6348b86d05d 100644 --- a/src/main/java/spoon/reflect/visitor/ElementPrinterHelper.java +++ b/src/main/java/spoon/reflect/visitor/ElementPrinterHelper.java @@ -146,10 +146,20 @@ public void writeImplementsClause(CtType type) { } } + /** + * Writes the executable parameters of the given executable. This includes the receiver parameter if it is present. + * For example, for a method `void foo(int a, int b)`, this method will write `(int a, int b)`. + * @param executable The executable to write the parameters for. This can be a method, constructor, or lambda. + */ public void writeExecutableParameters(CtExecutable executable) { - printList(executable.getParameters(), null, + List parameters = new ArrayList<>(); + if (executable.getReceiverParameter() != null) { + parameters.add(executable.getReceiverParameter()); + } + parameters.addAll(executable.getParameters()); + printList(parameters, null, false, "(", false, false, ",", true, false, ")", - p -> prettyPrinter.scan(p)); + prettyPrinter::scan); } /** writes the thrown exception with a ListPrinter */ diff --git a/src/main/java/spoon/support/DefaultCoreFactory.java b/src/main/java/spoon/support/DefaultCoreFactory.java index 9337e431cbb..ec468d1915b 100644 --- a/src/main/java/spoon/support/DefaultCoreFactory.java +++ b/src/main/java/spoon/support/DefaultCoreFactory.java @@ -11,6 +11,7 @@ import java.lang.annotation.Annotation; import java.util.HashSet; import java.util.Set; + import spoon.experimental.CtUnresolvedImport; import spoon.reflect.code.CtAnnotationFieldAccess; import spoon.reflect.code.CtArrayRead; @@ -91,6 +92,7 @@ import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtRecord; import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtTypeParameter; @@ -191,6 +193,7 @@ import spoon.support.reflect.declaration.CtPackageImpl; import spoon.support.reflect.declaration.CtParameterImpl; import spoon.support.reflect.declaration.CtProvidedServiceImpl; +import spoon.support.reflect.declaration.CtReceiverParameterImpl; import spoon.support.reflect.declaration.CtRecordComponentImpl; import spoon.support.reflect.declaration.CtRecordImpl; import spoon.support.reflect.declaration.CtTypeParameterImpl; @@ -1120,6 +1123,9 @@ public CtElement create(Class klass) { if (klass.equals(spoon.reflect.code.CtRecordPattern.class)) { return createRecordPattern(); } + if (klass.equals(spoon.reflect.declaration.CtReceiverParameter.class)) { + return createReceiverParameter(); + } throw new IllegalArgumentException("not instantiable by CoreFactory(): " + klass); } @@ -1217,4 +1223,11 @@ public CtRecordPattern createRecordPattern() { recordPattern.setFactory(getMainFactory()); return recordPattern; } + + @Override + public CtReceiverParameter createReceiverParameter() { + CtReceiverParameter receiverParameter = new CtReceiverParameterImpl(); + receiverParameter.setFactory(getMainFactory()); + return receiverParameter; + } } diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index 2d191835670..da6441b8d9f 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -7,15 +7,9 @@ */ package spoon.support.compiler.jdt; +import java.lang.invoke.MethodHandles; import java.util.Set; -import org.eclipse.jdt.internal.compiler.ast.Expression; -import org.eclipse.jdt.internal.compiler.ast.FakeDefaultLiteral; -import org.eclipse.jdt.internal.compiler.ast.GuardedPattern; -import org.eclipse.jdt.internal.compiler.ast.RecordPattern; -import org.eclipse.jdt.internal.compiler.ast.TypePattern; -import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding; -import org.slf4j.Logger; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression; @@ -48,13 +42,16 @@ import org.eclipse.jdt.internal.compiler.ast.DoubleLiteral; import org.eclipse.jdt.internal.compiler.ast.EqualExpression; import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; +import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral; +import org.eclipse.jdt.internal.compiler.ast.FakeDefaultLiteral; import org.eclipse.jdt.internal.compiler.ast.FalseLiteral; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.FloatLiteral; import org.eclipse.jdt.internal.compiler.ast.ForStatement; import org.eclipse.jdt.internal.compiler.ast.ForeachStatement; +import org.eclipse.jdt.internal.compiler.ast.GuardedPattern; import org.eclipse.jdt.internal.compiler.ast.IfStatement; import org.eclipse.jdt.internal.compiler.ast.ImportReference; import org.eclipse.jdt.internal.compiler.ast.Initializer; @@ -86,6 +83,7 @@ import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; import org.eclipse.jdt.internal.compiler.ast.Receiver; import org.eclipse.jdt.internal.compiler.ast.RecordComponent; +import org.eclipse.jdt.internal.compiler.ast.RecordPattern; import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression; import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; @@ -104,6 +102,7 @@ import org.eclipse.jdt.internal.compiler.ast.TryStatement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeParameter; +import org.eclipse.jdt.internal.compiler.ast.TypePattern; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.ast.UnaryExpression; import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; @@ -117,11 +116,13 @@ import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding; import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; +import org.slf4j.Logger; import org.slf4j.LoggerFactory; import spoon.SpoonException; import spoon.reflect.code.BinaryOperatorKind; @@ -161,6 +162,7 @@ import spoon.reflect.declaration.CtPackage; import spoon.reflect.declaration.CtPackageDeclaration; import spoon.reflect.declaration.CtParameter; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.CtTypeParameter; import spoon.reflect.declaration.ModifierKind; @@ -173,8 +175,6 @@ import spoon.support.reflect.CtExtendedModifier; import spoon.support.reflect.reference.CtArrayTypeReferenceImpl; -import java.lang.invoke.MethodHandles; - import static spoon.support.compiler.jdt.JDTTreeBuilderQuery.getBinaryOperatorKind; import static spoon.support.compiler.jdt.JDTTreeBuilderQuery.getModifiers; import static spoon.support.compiler.jdt.JDTTreeBuilderQuery.getUnaryOperator; @@ -958,6 +958,11 @@ public boolean visit(Argument argument, BlockScope scope) { return true; } boolean isVar = argument.type != null && argument.type.isTypeNameVar(scope); + if (argument instanceof Receiver receiver) { + CtReceiverParameter receiverParameter = helper.createReceiverParameter(receiver); + context.enter(receiverParameter, argument); + return true; + } CtParameter p = helper.createParameter(argument); if (isVar) { p.setInferred(true); @@ -1141,8 +1146,6 @@ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { context.enter(getFactory().Core().createBlock(), methodDeclaration); context.exit(methodDeclaration); } - - // We consider the receiver as a standard argument (i.e. as a parameter) Receiver receiver = methodDeclaration.receiver; if (receiver != null) { receiver.traverse(this, methodDeclaration.scope); @@ -1176,7 +1179,10 @@ public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope s // Create block context.enter(factory.Core().createBlock(), constructorDeclaration); context.exit(constructorDeclaration); - + Receiver receiver = constructorDeclaration.receiver; + if (receiver != null) { + receiver.traverse(this, constructorDeclaration.scope); + } return true; } diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java index 99d53b12929..2b30362a270 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilderHelper.java @@ -7,7 +7,6 @@ */ package spoon.support.compiler.jdt; -import java.util.Arrays; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; @@ -21,6 +20,7 @@ import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement; import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; +import org.eclipse.jdt.internal.compiler.ast.Receiver; import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression; import org.eclipse.jdt.internal.compiler.ast.RequiresStatement; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; @@ -58,6 +58,7 @@ import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtSealable; import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.CtUsedService; @@ -76,6 +77,7 @@ import spoon.support.reflect.CtExtendedModifier; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -753,6 +755,20 @@ CtParameter createParameter(Argument argument) { return p; } + /** + * Creates a receiver parameter for a method or constructor. + * + * @param argument the argument containing information about the parameter + * @return the created CtReceiverParameter object + */ + CtReceiverParameter createReceiverParameter(Receiver argument) { + CtReceiverParameter p = jdtTreeBuilder.getFactory().Core().createReceiverParameter(); + if (argument.type != null) { + p.setType(jdtTreeBuilder.getReferencesBuilder().getTypeReference(argument.type)); + } + return p; + } + /** * Creates an executable reference expression. * diff --git a/src/main/java/spoon/support/compiler/jdt/ParentExiter.java b/src/main/java/spoon/support/compiler/jdt/ParentExiter.java index 7bec0d6512a..f972f4898ca 100644 --- a/src/main/java/spoon/support/compiler/jdt/ParentExiter.java +++ b/src/main/java/spoon/support/compiler/jdt/ParentExiter.java @@ -30,7 +30,6 @@ import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.jspecify.annotations.Nullable; - import spoon.SpoonException; import spoon.reflect.code.BinaryOperatorKind; import spoon.reflect.code.CaseKind; @@ -97,6 +96,7 @@ import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtPackage; import spoon.reflect.declaration.CtParameter; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtRecord; import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtType; @@ -207,6 +207,8 @@ public void scanCtExecutable(CtExecutable e) { } else if (child instanceof CtBlock && !(e instanceof CtMethod || e instanceof CtConstructor)) { e.setBody((CtBlock) child); return; + } else if (child instanceof CtReceiverParameter ctReceiverParameter) { + e.setReceiverParameter(ctReceiverParameter); } super.scanCtExecutable(e); } diff --git a/src/main/java/spoon/support/reflect/code/CtLambdaImpl.java b/src/main/java/spoon/support/reflect/code/CtLambdaImpl.java index d88da66226a..da71b252a58 100644 --- a/src/main/java/spoon/support/reflect/code/CtLambdaImpl.java +++ b/src/main/java/spoon/support/reflect/code/CtLambdaImpl.java @@ -7,6 +7,7 @@ */ package spoon.support.reflect.code; +import org.jspecify.annotations.Nullable; import spoon.LovecraftException; import spoon.SpoonException; import spoon.reflect.annotations.MetamodelPropertyField; @@ -21,6 +22,7 @@ import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtNamedElement; import spoon.reflect.declaration.CtParameter; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.CtExecutable; import spoon.reflect.declaration.CtTypedElement; @@ -286,6 +288,18 @@ public CtLambda clone() { return (CtLambda) super.clone(); } + @Override + @UnsettableProperty + public CtExecutable setReceiverParameter(CtReceiverParameter receiverParameter) { + return this; + } + + @Override + @UnsettableProperty + public @Nullable CtReceiverParameter getReceiverParameter() { + return null; + } + @Override public C setType(CtTypeReference type) { if (type != null) { diff --git a/src/main/java/spoon/support/reflect/declaration/CtExecutableImpl.java b/src/main/java/spoon/support/reflect/declaration/CtExecutableImpl.java index 578dca12d96..570a0e1a430 100644 --- a/src/main/java/spoon/support/reflect/declaration/CtExecutableImpl.java +++ b/src/main/java/spoon/support/reflect/declaration/CtExecutableImpl.java @@ -7,13 +7,16 @@ */ package spoon.support.reflect.declaration; +import org.jspecify.annotations.Nullable; import spoon.reflect.annotations.MetamodelPropertyField; import spoon.reflect.code.CtBlock; import spoon.reflect.code.CtBodyHolder; import spoon.reflect.code.CtStatement; import spoon.reflect.declaration.CtExecutable; import spoon.reflect.declaration.CtParameter; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtType; +import spoon.reflect.path.CtRole; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtTypeReference; import spoon.support.util.QualifiedNameBasedSortedSet; @@ -46,6 +49,8 @@ public abstract class CtExecutableImpl extends CtNamedElementImpl implements @MetamodelPropertyField(role = THROWN) Set> thrownTypes = emptySet(); + @MetamodelPropertyField(role = CtRole.RECEIVER_PARAMETER) + private CtReceiverParameter receiverParameter; public CtExecutableImpl() { } @@ -192,4 +197,18 @@ public CtExecutableReference getReference() { public CtExecutable clone() { return (CtExecutable) super.clone(); } + + public CtExecutable setReceiverParameter(CtReceiverParameter receiverParameter) { + if (receiverParameter != null) { + receiverParameter.setParent(this); + } + this.receiverParameter = receiverParameter; + getFactory().getEnvironment().getModelChangeListener().onObjectUpdate(this, CtRole.RECEIVER_PARAMETER, receiverParameter, this.receiverParameter); + return this; + } + + @Nullable + public CtReceiverParameter getReceiverParameter() { + return receiverParameter; + } } diff --git a/src/main/java/spoon/support/reflect/declaration/CtReceiverParameterImpl.java b/src/main/java/spoon/support/reflect/declaration/CtReceiverParameterImpl.java new file mode 100644 index 00000000000..6eda457da4b --- /dev/null +++ b/src/main/java/spoon/support/reflect/declaration/CtReceiverParameterImpl.java @@ -0,0 +1,60 @@ +/* + * SPDX-License-Identifier: (MIT OR CECILL-C) + * + * Copyright (C) 2006-2023 INRIA and contributors + * + * Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) or the Cecill-C License (see LICENSE-CECILL-C.txt). You as the user are entitled to choose the terms under which to adopt Spoon. + */ +package spoon.support.reflect.declaration; + +import spoon.reflect.annotations.MetamodelPropertyField; +import spoon.reflect.declaration.CtReceiverParameter; +import spoon.reflect.declaration.CtShadowable; +import spoon.reflect.declaration.CtTypedElement; +import spoon.reflect.path.CtRole; +import spoon.reflect.reference.CtTypeReference; +import spoon.reflect.visitor.CtVisitor; + +public class CtReceiverParameterImpl extends CtElementImpl implements CtReceiverParameter { + + @MetamodelPropertyField(role = CtRole.TYPE) + private CtTypeReference type; + @MetamodelPropertyField(role = CtRole.IS_SHADOW) + private boolean isShadow; + + @Override + public boolean isShadow() { + return isShadow; + } + + @Override + public C setShadow(boolean isShadow) { + getFactory().getEnvironment().getModelChangeListener().onObjectUpdate(this, CtRole.IS_SHADOW, isShadow, this.isShadow); + this.isShadow = isShadow; + return (C) this; + } + @Override + public CtTypeReference getType() { + return type; + } + + @Override + public C setType(CtTypeReference type) { + if (type != null) { + type.setParent(this); + } + getFactory().getEnvironment().getModelChangeListener().onObjectUpdate(this, CtRole.TYPE, type, this.type); + this.type = type; + return (C) this; + } + + @Override + public void accept(CtVisitor visitor) { + visitor.visitCtReceiverParameter(this); + } + + @Override + public CtReceiverParameter clone() { + return (CtReceiverParameter) super.clone(); + } +} diff --git a/src/main/java/spoon/support/visitor/clone/CloneBuilder.java b/src/main/java/spoon/support/visitor/clone/CloneBuilder.java index 39fdd412621..1860501113b 100644 --- a/src/main/java/spoon/support/visitor/clone/CloneBuilder.java +++ b/src/main/java/spoon/support/visitor/clone/CloneBuilder.java @@ -314,4 +314,11 @@ public void visitCtRecordComponent(spoon.reflect.declaration.CtRecordComponent r ((spoon.reflect.declaration.CtRecordComponent) (other)).setShadow(recordComponent.isShadow()); super.visitCtRecordComponent(recordComponent); } + + // auto-generated, see spoon.generating.CloneVisitorGenerator + @java.lang.Override + public void visitCtReceiverParameter(spoon.reflect.declaration.CtReceiverParameter e) { + ((spoon.reflect.declaration.CtReceiverParameter) (other)).setShadow(e.isShadow()); + super.visitCtReceiverParameter(e); + } } diff --git a/src/main/java/spoon/support/visitor/clone/CloneVisitor.java b/src/main/java/spoon/support/visitor/clone/CloneVisitor.java index 4b32cd0e916..ad616be8226 100644 --- a/src/main/java/spoon/support/visitor/clone/CloneVisitor.java +++ b/src/main/java/spoon/support/visitor/clone/CloneVisitor.java @@ -236,6 +236,7 @@ public void visitCtConstructor(final spoon.reflect.declaration.CtConstructor spoon.reflect.declaration.CtConstructor aCtConstructor = c.getFactory().Core().createConstructor(); this.builder.copy(c, aCtConstructor); aCtConstructor.setAnnotations(this.cloneHelper.clone(c.getAnnotations())); + aCtConstructor.setReceiverParameter(this.cloneHelper.clone(c.getReceiverParameter())); aCtConstructor.setParameters(this.cloneHelper.clone(c.getParameters())); aCtConstructor.setThrownTypes(this.cloneHelper.clone(c.getThrownTypes())); aCtConstructor.setFormalCtTypeParameters(this.cloneHelper.clone(c.getFormalCtTypeParameters())); @@ -499,6 +500,7 @@ public void visitCtMethod(final spoon.reflect.declaration.CtMethod m) { aCtMethod.setAnnotations(this.cloneHelper.clone(m.getAnnotations())); aCtMethod.setFormalCtTypeParameters(this.cloneHelper.clone(m.getFormalCtTypeParameters())); aCtMethod.setType(this.cloneHelper.clone(m.getType())); + aCtMethod.setReceiverParameter(this.cloneHelper.clone(m.getReceiverParameter())); aCtMethod.setParameters(this.cloneHelper.clone(m.getParameters())); aCtMethod.setThrownTypes(this.cloneHelper.clone(m.getThrownTypes())); aCtMethod.setBody(this.cloneHelper.clone(m.getBody())); @@ -1146,6 +1148,18 @@ public void visitCtRecordComponent(spoon.reflect.declaration.CtRecordComponent r this.other = aCtRecordComponent; } + // auto-generated, see spoon.generating.CloneVisitorGenerator + @java.lang.Override + public void visitCtReceiverParameter(spoon.reflect.declaration.CtReceiverParameter receiverParameter) { + spoon.reflect.declaration.CtReceiverParameter aCtReceiverParameter = receiverParameter.getFactory().Core().createReceiverParameter(); + this.builder.copy(receiverParameter, aCtReceiverParameter); + aCtReceiverParameter.setAnnotations(this.cloneHelper.clone(receiverParameter.getAnnotations())); + aCtReceiverParameter.setType(this.cloneHelper.clone(receiverParameter.getType())); + aCtReceiverParameter.setComments(this.cloneHelper.clone(receiverParameter.getComments())); + this.cloneHelper.tailor(receiverParameter, aCtReceiverParameter); + this.other = aCtReceiverParameter; + } + // auto-generated, see spoon.generating.CloneVisitorGenerator @java.lang.Override public void visitCtCasePattern(spoon.reflect.code.CtCasePattern casePattern) { diff --git a/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java b/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java index 198073f567f..130fb14af6b 100644 --- a/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java +++ b/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java @@ -68,6 +68,20 @@ public void set(spoon.reflect.code.CtPattern replace) { } } + // auto-generated, see spoon.generating.ReplacementVisitorGenerator + static class CtReceiverParameterTypeReplaceListener implements spoon.support.visitor.replace.ReplaceListener { + private final spoon.reflect.declaration.CtTypedElement element; + + CtReceiverParameterTypeReplaceListener(spoon.reflect.declaration.CtTypedElement element) { + this.element = element; + } + + @java.lang.Override + public void set(spoon.reflect.reference.CtTypeReference replace) { + this.element.setType(replace); + } + } + // auto-generated, see spoon.generating.ReplacementVisitorGenerator static class CtRecordRecordComponentsReplaceListener implements spoon.support.visitor.replace.ReplaceSetListener { private final spoon.reflect.declaration.CtRecord element; @@ -1006,6 +1020,20 @@ public void set(java.util.List replace) { } } + // auto-generated, see spoon.generating.ReplacementVisitorGenerator + static class CtExecutableReceiverParameterReplaceListener implements spoon.support.visitor.replace.ReplaceListener { + private final spoon.reflect.declaration.CtExecutable element; + + CtExecutableReceiverParameterReplaceListener(spoon.reflect.declaration.CtExecutable element) { + this.element = element; + } + + @java.lang.Override + public void set(spoon.reflect.declaration.CtReceiverParameter replace) { + this.element.setReceiverParameter(replace); + } + } + // auto-generated, see spoon.generating.ReplacementVisitorGenerator static class CtConditionalElseExpressionReplaceListener implements spoon.support.visitor.replace.ReplaceListener { private final spoon.reflect.code.CtConditional element; @@ -1711,6 +1739,7 @@ public void visitCtConditional(final spoon.reflect.code.CtConditional con @java.lang.Override public void visitCtConstructor(final spoon.reflect.declaration.CtConstructor c) { replaceInListIfExist(c.getAnnotations(), new spoon.support.visitor.replace.ReplacementVisitor.CtElementAnnotationsReplaceListener(c)); + replaceElementIfExist(c.getReceiverParameter(), new spoon.support.visitor.replace.ReplacementVisitor.CtExecutableReceiverParameterReplaceListener(c)); replaceInListIfExist(c.getParameters(), new spoon.support.visitor.replace.ReplacementVisitor.CtExecutableParametersReplaceListener(c)); replaceInSetIfExist(c.getThrownTypes(), new spoon.support.visitor.replace.ReplacementVisitor.CtExecutableThrownTypesReplaceListener(c)); replaceInListIfExist(c.getFormalCtTypeParameters(), new spoon.support.visitor.replace.ReplacementVisitor.CtFormalTypeDeclarerFormalCtTypeParametersReplaceListener(c)); @@ -1909,6 +1938,7 @@ public void visitCtMethod(final spoon.reflect.declaration.CtMethod m) { replaceInListIfExist(m.getAnnotations(), new spoon.support.visitor.replace.ReplacementVisitor.CtElementAnnotationsReplaceListener(m)); replaceInListIfExist(m.getFormalCtTypeParameters(), new spoon.support.visitor.replace.ReplacementVisitor.CtFormalTypeDeclarerFormalCtTypeParametersReplaceListener(m)); replaceElementIfExist(m.getType(), new spoon.support.visitor.replace.ReplacementVisitor.CtTypedElementTypeReplaceListener(m)); + replaceElementIfExist(m.getReceiverParameter(), new spoon.support.visitor.replace.ReplacementVisitor.CtExecutableReceiverParameterReplaceListener(m)); replaceInListIfExist(m.getParameters(), new spoon.support.visitor.replace.ReplacementVisitor.CtExecutableParametersReplaceListener(m)); replaceInSetIfExist(m.getThrownTypes(), new spoon.support.visitor.replace.ReplacementVisitor.CtExecutableThrownTypesReplaceListener(m)); replaceElementIfExist(m.getBody(), new spoon.support.visitor.replace.ReplacementVisitor.CtExecutableBodyReplaceListener(m)); @@ -2371,6 +2401,14 @@ public void visitCtRecordComponent(spoon.reflect.declaration.CtRecordComponent r replaceInListIfExist(recordType.getComments(), new spoon.support.visitor.replace.ReplacementVisitor.CtElementCommentsReplaceListener(recordType)); } + // auto-generated, see spoon.generating.ReplacementVisitorGenerator + @java.lang.Override + public void visitCtReceiverParameter(spoon.reflect.declaration.CtReceiverParameter receiverParameter) { + replaceInListIfExist(receiverParameter.getAnnotations(), new spoon.support.visitor.replace.ReplacementVisitor.CtElementAnnotationsReplaceListener(receiverParameter)); + replaceElementIfExist(receiverParameter.getType(), new spoon.support.visitor.replace.ReplacementVisitor.CtReceiverParameterTypeReplaceListener(receiverParameter)); + replaceInListIfExist(receiverParameter.getComments(), new spoon.support.visitor.replace.ReplacementVisitor.CtElementCommentsReplaceListener(receiverParameter)); + } + // auto-generated, see spoon.generating.ReplacementVisitorGenerator @java.lang.Override public void visitCtCasePattern(spoon.reflect.code.CtCasePattern casePattern) { diff --git a/src/test/java/spoon/reflect/visitor/CtScannerTest.java b/src/test/java/spoon/reflect/visitor/CtScannerTest.java index b5188c82c92..d05767f6465 100644 --- a/src/test/java/spoon/reflect/visitor/CtScannerTest.java +++ b/src/test/java/spoon/reflect/visitor/CtScannerTest.java @@ -271,7 +271,7 @@ public void exit(CtElement o) { // this is a coarse-grain check to see if the scanner changes // no more exec ref in paramref // also takes into account the comments - assertEquals(3667, counter.nElement + countOfCommentsInCompilationUnits); + assertEquals(3704, counter.nElement + countOfCommentsInCompilationUnits); assertEquals(2449, counter.nEnter + countOfCommentsInCompilationUnits); assertEquals(2449, counter.nExit + countOfCommentsInCompilationUnits); @@ -370,7 +370,7 @@ public void scan(CtElement o) { } }.scan(c); // contract: the CtDequeScanner has the context information of the parents - assertEquals(45, l.size()); // we visited the whole tree + assertEquals(47, l.size()); // we visited the whole tree assertEquals(0, l.get(0)); assertEquals(1, l.get(1)); // visiting a child assertEquals(2, l.get(3)); // visiting a grand child diff --git a/src/test/java/spoon/test/annotation/AnnotationTest.java b/src/test/java/spoon/test/annotation/AnnotationTest.java index 334fa92baab..1e98d128442 100644 --- a/src/test/java/spoon/test/annotation/AnnotationTest.java +++ b/src/test/java/spoon/test/annotation/AnnotationTest.java @@ -105,7 +105,6 @@ import spoon.test.annotation.testclasses.typeandfield.SimpleClass; import static org.hamcrest.MatcherAssert.assertThat; - import static org.hamcrest.core.Is.is; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -1130,43 +1129,6 @@ public void testSpoonSpoonResult() { assertEquals("spoon.test.annotation.testclasses.PortRange", annotation.getAnnotationType().getQualifiedName(), "Annotation should be @spoon.test.annotation.testclasses.PortRange"); } - @Test - public void testGetAnnotationFromParameter() { - // contract: Java 8 receiver parameters are handled - Launcher spoon = new Launcher(); - spoon.addInputResource("src/test/resources/noclasspath/Initializer.java"); - String output = "target/spooned-" + this.getClass().getSimpleName() + "-firstspoon/"; - spoon.setSourceOutputDirectory(output); - spoon.getEnvironment().setNoClasspath(true); - Factory factory = spoon.getFactory(); - spoon.buildModel(); - - List methods = factory.getModel().getElements(new NamedElementFilter<>(CtMethod.class, "setField")); - assertThat(methods.size(), is(1)); - - CtMethod methodSet = methods.get(0); - assertThat(methodSet.getSimpleName(), is("setField")); - - List parameters = methodSet.getParameters(); - - assertThat(parameters.size(), is(1)); - - CtParameter thisParameter = parameters.get(0); - assertThat(thisParameter.getSimpleName(), is("this")); - - - CtTypeReference thisParamType = thisParameter.getType(); - assertThat(thisParamType.getSimpleName(), is("Initializer")); - - List> annotations = thisParameter.getType().getAnnotations(); - assertThat(annotations.size(), is(2)); - - CtAnnotation unknownInit = annotations.get(0); - CtAnnotation raw = annotations.get(1); - - assertThat(unknownInit.getAnnotationType().getSimpleName(), is("UnknownInitialization")); - assertThat(raw.getAnnotationType().getSimpleName(), is("Raw")); - } @Test public void annotationAddValue() { diff --git a/src/test/java/spoon/test/api/Metamodel.java b/src/test/java/spoon/test/api/Metamodel.java index e20b027d710..3779efb7bf8 100644 --- a/src/test/java/spoon/test/api/Metamodel.java +++ b/src/test/java/spoon/test/api/Metamodel.java @@ -16,6 +16,8 @@ */ package spoon.test.api; + +import spoon.metamodel.MetamodelConcept; import spoon.reflect.code.CtForEach; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtElement; @@ -248,7 +250,7 @@ private static void initTypes(List types) { * body of this method was generated by /spoon-core/src/test/java/spoon/generating/MetamodelGenerator.java * Run the method main and copy the System output here */ - types.add(new Type("CtConditional", spoon.reflect.code.CtConditional.class, spoon.support.reflect.code.CtConditionalImpl.class, fm -> fm + types.add(new Type("CtConditional", spoon.reflect.code.CtConditional.class, spoon.support.reflect.code.CtConditionalImpl.class, fm -> fm .field(CtRole.IS_IMPLICIT, false, false) .field(CtRole.POSITION, false, false) .field(CtRole.TYPE, false, false) @@ -440,6 +442,7 @@ private static void initTypes(List types) { .field(CtRole.POSITION, false, false) .field(CtRole.COMPACT_CONSTRUCTOR, false, false) .field(CtRole.ANNOTATION, false, false) + .field(CtRole.RECEIVER_PARAMETER, false, false) .field(CtRole.PARAMETER, false, false) .field(CtRole.THROWN, false, false) .field(CtRole.TYPE_PARAMETER, false, false) @@ -478,6 +481,7 @@ private static void initTypes(List types) { .field(CtRole.MODIFIER, false, false) .field(CtRole.EMODIFIER, true, true) .field(CtRole.POSITION, false, false) + .field(CtRole.RECEIVER_PARAMETER, true, true) .field(CtRole.ANNOTATION, false, false) .field(CtRole.BODY, false, false) .field(CtRole.COMMENT, false, false) @@ -624,6 +628,16 @@ private static void initTypes(List types) { )); + types.add(new Type("CtReceiverParameter", spoon.reflect.declaration.CtReceiverParameter.class, spoon.support.reflect.declaration.CtReceiverParameterImpl.class, fm -> fm + .field(CtRole.IS_SHADOW, false, false) + .field(CtRole.IS_IMPLICIT, false, false) + .field(CtRole.POSITION, false, false) + .field(CtRole.ANNOTATION, false, false) + .field(CtRole.TYPE, false, false) + .field(CtRole.COMMENT, false, false) + + )); + types.add(new Type("CtOperatorAssignment", spoon.reflect.code.CtOperatorAssignment.class, spoon.support.reflect.code.CtOperatorAssignmentImpl.class, fm -> fm .field(CtRole.IS_IMPLICIT, false, false) .field(CtRole.LABEL, false, false) @@ -672,6 +686,7 @@ private static void initTypes(List types) { .field(CtRole.EMODIFIER, true, true) .field(CtRole.TYPE_PARAMETER, true, true) .field(CtRole.POSITION, false, false) + .field(CtRole.RECEIVER_PARAMETER, true, true) .field(CtRole.ANNOTATION, false, false) .field(CtRole.TYPE, false, false) .field(CtRole.DEFAULT_EXPRESSION, false, false) @@ -1092,6 +1107,7 @@ private static void initTypes(List types) { .field(CtRole.ANNOTATION, false, false) .field(CtRole.TYPE_PARAMETER, false, false) .field(CtRole.TYPE, false, false) + .field(CtRole.RECEIVER_PARAMETER, false, false) .field(CtRole.PARAMETER, false, false) .field(CtRole.THROWN, false, false) .field(CtRole.BODY, false, false) @@ -1104,6 +1120,7 @@ private static void initTypes(List types) { .field(CtRole.IS_IMPLICIT, false, false) .field(CtRole.THROWN, true, true) .field(CtRole.POSITION, false, false) + .field(CtRole.RECEIVER_PARAMETER, true, true) .field(CtRole.ANNOTATION, false, false) .field(CtRole.TYPE, false, false) .field(CtRole.CAST, false, false) @@ -1350,8 +1367,8 @@ private static void initTypes(List types) { types.add(new Type("CtCasePattern", spoon.reflect.code.CtCasePattern.class, spoon.support.reflect.code.CtCasePatternImpl.class, fm -> fm .field(CtRole.IS_IMPLICIT, false, false) - .field(CtRole.CAST, false, false) .field(CtRole.POSITION, false, false) + .field(CtRole.CAST, false, false) .field(CtRole.ANNOTATION, false, false) .field(CtRole.PATTERN, false, false) .field(CtRole.CONDITION, false, false) diff --git a/src/test/java/spoon/test/receiverparameter/ReceiverParameterTest.java b/src/test/java/spoon/test/receiverparameter/ReceiverParameterTest.java new file mode 100644 index 00000000000..b9b767ce0b2 --- /dev/null +++ b/src/test/java/spoon/test/receiverparameter/ReceiverParameterTest.java @@ -0,0 +1,59 @@ +package spoon.test.receiverparameter; + +import java.util.List; + +import spoon.reflect.CtModel; +import spoon.reflect.declaration.CtConstructor; +import spoon.reflect.declaration.CtElement; +import spoon.reflect.declaration.CtReceiverParameter; +import spoon.reflect.declaration.CtType; +import spoon.reflect.declaration.CtTypeInformation; +import spoon.reflect.visitor.filter.TypeFilter; +import spoon.testing.assertions.SpoonAssertions; +import spoon.testing.utils.ModelTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ReceiverParameterTest { + + @ModelTest("src/test/resources/receiver/SimpleReceiverParameter.java") + void simpleParameter(CtModel model) { + // contract: receiver parameter is correctly parsed and can be accessed from the model + CtType targetType = model.getAllTypes().iterator().next(); + List receiverParams = targetType.getElements(new TypeFilter<>(CtReceiverParameter.class)); + assertEquals(1, receiverParams.size()); + CtReceiverParameter receiverParam = receiverParams.iterator().next(); + SpoonAssertions.assertThat(receiverParam.getType()).extracting(CtTypeInformation::getQualifiedName).isEqualTo("receiver.SimpleReceiverParameter"); + SpoonAssertions.assertThat(receiverParam).extracting(CtElement::toString).isEqualTo("SimpleReceiverParameter this"); + + } + + + @ModelTest("src/test/resources/receiver/InnerClassCtor.java") + void innerClassCtor(CtModel model) { + // contract: constructor of inner class can have receiver parameter with their outer class type + CtType targetType = model.getAllTypes().iterator().next(); + List receiverParams = targetType.getElements(new TypeFilter<>(CtReceiverParameter.class)); + assertEquals(1, receiverParams.size()); + CtReceiverParameter next1 = receiverParams.iterator().next(); + SpoonAssertions.assertThat(next1.getType()).extracting(CtTypeInformation::getQualifiedName).isEqualTo("receiver.Outer"); + CtConstructor ctConstructor = targetType.getElements(new TypeFilter<>(CtConstructor.class)).stream().filter(v -> v.getReceiverParameter() != null).findFirst().get(); + SpoonAssertions.assertThat(ctConstructor).isNotNull(); + SpoonAssertions.assertThat(ctConstructor.getReceiverParameter()).isNotNull(); + SpoonAssertions.assertThat(ctConstructor.getReceiverParameter().getType()).isNotNull(); + SpoonAssertions.assertThat(ctConstructor.getReceiverParameter()).extracting(CtElement::toString).isEqualTo("Outer Outer.this"); + } + + @ModelTest("src/test/resources/receiver/Outer.java") + void innerClassInnerClass(CtModel model) { + // contract: constructor of inner class which is an innerclass can have receiver parameter with their outer class type + CtType targetType = model.getAllTypes().iterator().next(); + List receiverParams = targetType.getElements(new TypeFilter<>(CtReceiverParameter.class)); + assertEquals(1, receiverParams.size()); + CtConstructor ctConstructor = targetType.getElements(new TypeFilter<>(CtConstructor.class)).stream().filter(v -> v.getReceiverParameter() != null).findFirst().get(); + SpoonAssertions.assertThat(ctConstructor).isNotNull(); + SpoonAssertions.assertThat(ctConstructor.getReceiverParameter()).isNotNull(); + SpoonAssertions.assertThat(ctConstructor.getReceiverParameter().getType()).isNotNull(); + SpoonAssertions.assertThat(ctConstructor.getReceiverParameter()).extracting(CtElement::toString).isEqualTo("Middle Middle.this"); + } +} diff --git a/src/test/java/spoon/testing/assertions/CtExecutableAssertInterface.java b/src/test/java/spoon/testing/assertions/CtExecutableAssertInterface.java index e44097db426..a89d91fb77f 100644 --- a/src/test/java/spoon/testing/assertions/CtExecutableAssertInterface.java +++ b/src/test/java/spoon/testing/assertions/CtExecutableAssertInterface.java @@ -16,6 +16,10 @@ default ListAssert> getParameters() { return Assertions.assertThat(actual().getParameters()); } + default CtReceiverParameterAssertInterface getReceiverParameter() { + return SpoonAssertions.assertThat(actual().getReceiverParameter()); + } + default AbstractCollectionAssert>, CtTypeReference, ?> getThrownTypes() { return Assertions.assertThat(actual().getThrownTypes()); } diff --git a/src/test/java/spoon/testing/assertions/CtReceiverParameterAssert.java b/src/test/java/spoon/testing/assertions/CtReceiverParameterAssert.java new file mode 100644 index 00000000000..95bc375020d --- /dev/null +++ b/src/test/java/spoon/testing/assertions/CtReceiverParameterAssert.java @@ -0,0 +1,23 @@ +package spoon.testing.assertions; +import org.assertj.core.api.AbstractObjectAssert; +import spoon.reflect.declaration.CtReceiverParameter; +public class CtReceiverParameterAssert extends AbstractObjectAssert implements CtReceiverParameterAssertInterface { + CtReceiverParameterAssert(CtReceiverParameter actual) { + super(actual, CtReceiverParameterAssert.class); + } + + @Override + public CtReceiverParameterAssert self() { + return this; + } + + @Override + public CtReceiverParameter actual() { + return this.actual; + } + + @Override + public void failWithMessage(String errorMessage, Object... arguments) { + super.failWithMessage(errorMessage, arguments); + } +} diff --git a/src/test/java/spoon/testing/assertions/CtReceiverParameterAssertInterface.java b/src/test/java/spoon/testing/assertions/CtReceiverParameterAssertInterface.java new file mode 100644 index 00000000000..2c3e5c90e56 --- /dev/null +++ b/src/test/java/spoon/testing/assertions/CtReceiverParameterAssertInterface.java @@ -0,0 +1,4 @@ +package spoon.testing.assertions; +import org.assertj.core.api.AbstractObjectAssert; +import spoon.reflect.declaration.CtReceiverParameter; +interface CtReceiverParameterAssertInterface, W extends CtReceiverParameter> extends CtElementAssertInterface , SpoonAssert , CtTypedElementAssertInterface , CtShadowableAssertInterface {} diff --git a/src/test/java/spoon/testing/assertions/SpoonAssertions.java b/src/test/java/spoon/testing/assertions/SpoonAssertions.java index 7546f9dd59b..4d8d8b29676 100644 --- a/src/test/java/spoon/testing/assertions/SpoonAssertions.java +++ b/src/test/java/spoon/testing/assertions/SpoonAssertions.java @@ -43,6 +43,7 @@ import spoon.reflect.code.CtNewArray; import spoon.reflect.code.CtNewClass; import spoon.reflect.code.CtOperatorAssignment; +import spoon.reflect.code.CtRecordPattern; import spoon.reflect.code.CtPattern; import spoon.reflect.code.CtRHSReceiver; import spoon.reflect.code.CtRecordPattern; @@ -96,6 +97,7 @@ import spoon.reflect.declaration.CtPackageExport; import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtProvidedService; +import spoon.reflect.declaration.CtReceiverParameter; import spoon.reflect.declaration.CtRecord; import spoon.reflect.declaration.CtRecordComponent; import spoon.reflect.declaration.CtSealable; @@ -309,6 +311,10 @@ public static CtAnnotationFieldAccessAssert assertThat(CtAnnotationFieldAccess ctAnnotationMethod) { return new CtAnnotationMethodAssert(ctAnnotationMethod); } diff --git a/src/test/resources/receiver/InnerClassCtor.java b/src/test/resources/receiver/InnerClassCtor.java new file mode 100644 index 00000000000..2d9d4b36310 --- /dev/null +++ b/src/test/resources/receiver/InnerClassCtor.java @@ -0,0 +1,8 @@ +package receiver; +public class Outer { + class Inner { + public Inner(Outer Outer.this) { + + } + } +} diff --git a/src/test/resources/receiver/Outer.java b/src/test/resources/receiver/Outer.java new file mode 100644 index 00000000000..36da3cbb61f --- /dev/null +++ b/src/test/resources/receiver/Outer.java @@ -0,0 +1,10 @@ +package receiver; +public class Outer { + class Middle { + class Inner { + public Inner(Middle Middle.this) { + + } + } + } +} diff --git a/src/test/resources/receiver/SimpleReceiverParameter.java b/src/test/resources/receiver/SimpleReceiverParameter.java new file mode 100644 index 00000000000..2c8fe95f8fc --- /dev/null +++ b/src/test/resources/receiver/SimpleReceiverParameter.java @@ -0,0 +1,8 @@ +package receiver; + +class SimpleReceiverParameter { + + public void foo(SimpleReceiverParameter this, int x) { + System.out.println(x) + } +}