From 06ad7f00d3984e20de610066d7767ac6f8c7b81b Mon Sep 17 00:00:00 2001 From: Lakshya A Agrawal Date: Wed, 4 Nov 2020 11:27:03 +0530 Subject: [PATCH] feature: add support for pretty-printing Java 15 text blocks (#3664) --- doc/code_elements.md | 10 ++++ .../inria/controlflow/ControlFlowBuilder.java | 6 +++ src/main/java/spoon/metamodel/Metamodel.java | 1 + .../java/spoon/reflect/code/CtLiteral.java | 4 +- .../java/spoon/reflect/code/CtTextBlock.java | 25 ++++++++++ .../spoon/reflect/factory/CodeFactory.java | 15 +++++- .../spoon/reflect/factory/CoreFactory.java | 6 +++ .../java/spoon/reflect/factory/Factory.java | 11 +++++ .../spoon/reflect/factory/FactoryImpl.java | 11 +++++ .../reflect/meta/impl/ModelRoleHandlers.java | 20 +++++++- .../reflect/visitor/CtAbstractVisitor.java | 6 +++ .../reflect/visitor/CtBiScannerDefault.java | 11 +++++ .../reflect/visitor/CtInheritanceScanner.java | 7 ++- .../java/spoon/reflect/visitor/CtScanner.java | 10 ++++ .../java/spoon/reflect/visitor/CtVisitor.java | 6 +++ .../visitor/DefaultJavaPrettyPrinter.java | 10 ++++ .../spoon/reflect/visitor/LiteralHelper.java | 13 +++++ .../spoon/support/DefaultCoreFactory.java | 12 +++++ .../support/compiler/jdt/JDTTreeBuilder.java | 8 +++- .../support/reflect/code/CtTextBlockImpl.java | 25 ++++++++++ .../support/visitor/clone/CloneBuilder.java | 1 + .../support/visitor/clone/CloneVisitor.java | 13 +++++ .../support/visitor/equals/EqualsChecker.java | 16 +++++++ .../visitor/replace/ReplacementVisitor.java | 9 ++++ src/test/java/spoon/test/api/Metamodel.java | 12 +++++ .../java/spoon/test/comment/CommentTest.java | 4 ++ .../spoon/test/textBlocks/TextBlockTest.java | 48 +++++++++++++++++-- 27 files changed, 309 insertions(+), 11 deletions(-) create mode 100644 src/main/java/spoon/reflect/code/CtTextBlock.java create mode 100644 src/main/java/spoon/support/reflect/code/CtTextBlockImpl.java diff --git a/doc/code_elements.md b/doc/code_elements.md index d1e697ccde9..0a229529479 100644 --- a/doc/code_elements.md +++ b/doc/code_elements.md @@ -346,6 +346,16 @@ int x = switch(i) { // <-- switch expression System.out.println("foo"); } +``` +### CtTextBlock +[(javadoc)](http://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/spoon/reflect/code/CtTextBlock.html) + +```java + + String example = """ + Test String + """; + ``` ### CtThisAccess [(javadoc)](http://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/spoon/reflect/code/CtThisAccess.html) diff --git a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java index 183a01777a3..4c4357b7060 100644 --- a/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java +++ b/spoon-control-flow/src/main/java/fr/inria/controlflow/ControlFlowBuilder.java @@ -62,6 +62,7 @@ import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSwitchExpression; import spoon.reflect.code.CtSynchronized; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -640,6 +641,11 @@ public void visitCtLiteral(CtLiteral literal) { } + @Override + public void visitCtTextBlock(CtTextBlock literal) { + + } + @Override public void visitCtLocalVariable(CtLocalVariable localVariable) { registerStatementLabel(localVariable); diff --git a/src/main/java/spoon/metamodel/Metamodel.java b/src/main/java/spoon/metamodel/Metamodel.java index 841447b76a5..ca9ddffdc8d 100644 --- a/src/main/java/spoon/metamodel/Metamodel.java +++ b/src/main/java/spoon/metamodel/Metamodel.java @@ -99,6 +99,7 @@ public static Set> getAllMetamodelInterfaces() { result.add(factory.Type().get(spoon.reflect.code.CtLabelledFlowBreak.class)); result.add(factory.Type().get(spoon.reflect.code.CtLambda.class)); result.add(factory.Type().get(spoon.reflect.code.CtLiteral.class)); + result.add(factory.Type().get(spoon.reflect.code.CtTextBlock.class)); result.add(factory.Type().get(spoon.reflect.code.CtLocalVariable.class)); result.add(factory.Type().get(spoon.reflect.code.CtLoop.class)); result.add(factory.Type().get(spoon.reflect.code.CtNewArray.class)); diff --git a/src/main/java/spoon/reflect/code/CtLiteral.java b/src/main/java/spoon/reflect/code/CtLiteral.java index 77b27ad72d4..e5315e5b3e5 100644 --- a/src/main/java/spoon/reflect/code/CtLiteral.java +++ b/src/main/java/spoon/reflect/code/CtLiteral.java @@ -39,13 +39,13 @@ public interface CtLiteral extends CtExpression { > C setValue(T value); /** - * Gets the base ot the numeric literal (2, 8, 10 or 16). + * Gets the base of the numeric literal (2, 8, 10 or 16). */ @PropertyGetter(role = LITERAL_BASE) LiteralBase getBase(); /** - * Sets the base ot the numeric literal. + * Sets the base of the numeric literal. */ @PropertySetter(role = LITERAL_BASE) > C setBase(LiteralBase base); diff --git a/src/main/java/spoon/reflect/code/CtTextBlock.java b/src/main/java/spoon/reflect/code/CtTextBlock.java new file mode 100644 index 00000000000..aacb2d1c580 --- /dev/null +++ b/src/main/java/spoon/reflect/code/CtTextBlock.java @@ -0,0 +1,25 @@ +/** + * SPDX-License-Identifier: (MIT OR CECILL-C) + * + * Copyright (C) 2006-2019 INRIA and contributors + * + * Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) of 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.code; + +/** + * This code element defines a Text Block String Literal. + * + *
+ *     String example = """
+ *		      Test String
+ *        	      """;
+ * 
+ * + * The example above shows a TextBlock literal, in which the string is represented by CtTextBlock + */ +public interface CtTextBlock extends CtLiteral { + /** Overriding return type, a clone of a CtTextBlock returns a CtTextBlock */ + @Override + CtTextBlock clone(); +} diff --git a/src/main/java/spoon/reflect/factory/CodeFactory.java b/src/main/java/spoon/reflect/factory/CodeFactory.java index a7420f3faf9..d650ec02e01 100644 --- a/src/main/java/spoon/reflect/factory/CodeFactory.java +++ b/src/main/java/spoon/reflect/factory/CodeFactory.java @@ -29,6 +29,7 @@ import spoon.reflect.code.CtNewClass; import spoon.reflect.code.CtStatement; import spoon.reflect.code.CtStatementList; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTypeAccess; @@ -269,6 +270,19 @@ public CtLiteral createLiteral(T value) { return literal; } + /** + * Creates a TextBlock with the given string value. + * @param value + * the string value of the literal + * @return a new literal + */ + public CtTextBlock createTextBlock(String value) { + CtTextBlock textblock = factory.Core().createTextBlock(); + textblock.setValue(value); + textblock.setType((CtTypeReference) factory.Type().STRING); + return textblock; + } + /** * Creates a one-dimension array that must only contain literals. */ @@ -759,5 +773,4 @@ public CtJavaDocTag createJavaDocTag(String content, CtJavaDocTag.TagType type, } return docTag.setContent(content.trim()).setType(type).setRealName(realName); } - } diff --git a/src/main/java/spoon/reflect/factory/CoreFactory.java b/src/main/java/spoon/reflect/factory/CoreFactory.java index 119d226210e..0e6eec9d6d1 100644 --- a/src/main/java/spoon/reflect/factory/CoreFactory.java +++ b/src/main/java/spoon/reflect/factory/CoreFactory.java @@ -49,6 +49,7 @@ import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSwitchExpression; import spoon.reflect.code.CtSynchronized; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -613,4 +614,9 @@ BodyHolderSourcePosition createBodyHolderSourcePosition( * @return yieldStatement */ CtYieldStatement createYieldStatement(); + + /** + * Creates a TextBlock String Literal + */ + CtTextBlock createTextBlock(); } diff --git a/src/main/java/spoon/reflect/factory/Factory.java b/src/main/java/spoon/reflect/factory/Factory.java index e94b1c9bf18..5af272a4098 100644 --- a/src/main/java/spoon/reflect/factory/Factory.java +++ b/src/main/java/spoon/reflect/factory/Factory.java @@ -52,6 +52,7 @@ import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSwitchExpression; import spoon.reflect.code.CtSynchronized; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -519,6 +520,16 @@ public interface Factory { */ CtLiteral createLiteral(); + /** + * @see CoreFactory#createTextBlock() + */ + CtTextBlock createTextBlock(); + + /** + * @see CodeFactory#createTextBlock(String) + */ + CtTextBlock createTextBlock(String value); + /** * @see CoreFactory#createLocalVariable() */ diff --git a/src/main/java/spoon/reflect/factory/FactoryImpl.java b/src/main/java/spoon/reflect/factory/FactoryImpl.java index 584b28f90c0..c734612ed20 100644 --- a/src/main/java/spoon/reflect/factory/FactoryImpl.java +++ b/src/main/java/spoon/reflect/factory/FactoryImpl.java @@ -53,6 +53,7 @@ import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSwitchExpression; import spoon.reflect.code.CtSynchronized; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -506,6 +507,11 @@ public CtLiteral createLiteral(T value) { return Code().createLiteral(value); } + @Override + public CtTextBlock createTextBlock(String value) { + return Code().createTextBlock(value); + } + @Override public CtLocalVariable createLocalVariable(CtTypeReference type, String name, CtExpression defaultExpression) { return Code().createLocalVariable(type, name, defaultExpression); @@ -1291,4 +1297,9 @@ public CtTypeReference createSimplyQualifiedReference(String qualifiedNam public CtYieldStatement createYieldStatement(boolean isImplicit) { return Core().createYieldStatement().setImplicit(isImplicit); } + + @Override + public CtTextBlock createTextBlock() { + return Core().createTextBlock(); + } } diff --git a/src/main/java/spoon/reflect/meta/impl/ModelRoleHandlers.java b/src/main/java/spoon/reflect/meta/impl/ModelRoleHandlers.java index fcfe7675c47..670f8d35be3 100644 --- a/src/main/java/spoon/reflect/meta/impl/ModelRoleHandlers.java +++ b/src/main/java/spoon/reflect/meta/impl/ModelRoleHandlers.java @@ -43,6 +43,7 @@ import spoon.reflect.code.CtStatementList; import spoon.reflect.code.CtSynchronized; import spoon.reflect.code.CtTargetedExpression; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; import spoon.reflect.code.CtTryWithResource; @@ -111,7 +112,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 CtAssert_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 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 CtElement_POSITION_RoleHandler(), new CtModule_PROVIDED_SERVICE_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 CtTypeMemberWildcardImportReference_TYPE_REF_RoleHandler(), new CtAnnotation_VALUE_RoleHandler(), new CtEnum_VALUE_RoleHandler(), new CtLiteral_VALUE_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 CtAssert_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 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 CtElement_POSITION_RoleHandler(), new CtModule_PROVIDED_SERVICE_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 CtTypeMemberWildcardImportReference_TYPE_REF_RoleHandler(), new CtAnnotation_VALUE_RoleHandler(), new CtEnum_VALUE_RoleHandler(), new CtLiteral_VALUE_RoleHandler(), new CtTextBlock_VALUE_RoleHandler(), new CtVariableAccess_VARIABLE_RoleHandler() }; static class CtVariableAccess_VARIABLE_RoleHandler extends SingleHandler> { private CtVariableAccess_VARIABLE_RoleHandler() { @@ -130,6 +131,23 @@ public void setValue(T element, U value) { } } + static class CtTextBlock_VALUE_RoleHandler extends SingleHandler { + private CtTextBlock_VALUE_RoleHandler() { + super(CtRole.VALUE, CtTextBlock.class, String.class); + } + + @SuppressWarnings("unchecked") + @Override + public U getValue(T element) { + return ((U) ((Object) (castTarget(element).getValue()))); + } + + @Override + public void setValue(T element, U value) { + castTarget(element).setValue(castValue(value)); + } + } + static class CtLiteral_VALUE_RoleHandler extends SingleHandler { private CtLiteral_VALUE_RoleHandler() { super(CtRole.VALUE, CtLiteral.class, Object.class); diff --git a/src/main/java/spoon/reflect/visitor/CtAbstractVisitor.java b/src/main/java/spoon/reflect/visitor/CtAbstractVisitor.java index 899bc3bc437..ca1658f4048 100644 --- a/src/main/java/spoon/reflect/visitor/CtAbstractVisitor.java +++ b/src/main/java/spoon/reflect/visitor/CtAbstractVisitor.java @@ -47,6 +47,7 @@ import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSwitchExpression; import spoon.reflect.code.CtSynchronized; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -265,6 +266,11 @@ public void visitCtLiteral(CtLiteral literal) { } + @Override + public void visitCtTextBlock(CtTextBlock ctTextBlock) { + + } + @Override public void visitCtLocalVariable(CtLocalVariable localVariable) { diff --git a/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java b/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java index bd81daba367..c238b07d2b7 100644 --- a/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java +++ b/src/main/java/spoon/reflect/visitor/CtBiScannerDefault.java @@ -425,6 +425,17 @@ public void visitCtLiteral(final spoon.reflect.code.CtLiteral literal) { exit(literal); } + // autogenerated by CtBiScannerGenerator + public void visitCtTextBlock(final spoon.reflect.code.CtTextBlock literal) { + spoon.reflect.code.CtTextBlock other = ((spoon.reflect.code.CtTextBlock) (this.stack.peek())); + enter(literal); + biScan(spoon.reflect.path.CtRole.ANNOTATION, literal.getAnnotations(), other.getAnnotations()); + biScan(spoon.reflect.path.CtRole.TYPE, literal.getType(), other.getType()); + biScan(spoon.reflect.path.CtRole.CAST, literal.getTypeCasts(), other.getTypeCasts()); + biScan(spoon.reflect.path.CtRole.COMMENT, literal.getComments(), other.getComments()); + exit(literal); + } + // autogenerated by CtBiScannerGenerator public void visitCtLocalVariable(final spoon.reflect.code.CtLocalVariable localVariable) { spoon.reflect.code.CtLocalVariable other = ((spoon.reflect.code.CtLocalVariable) (this.stack.peek())); diff --git a/src/main/java/spoon/reflect/visitor/CtInheritanceScanner.java b/src/main/java/spoon/reflect/visitor/CtInheritanceScanner.java index 01760f38e7d..bb6c38f3159 100644 --- a/src/main/java/spoon/reflect/visitor/CtInheritanceScanner.java +++ b/src/main/java/spoon/reflect/visitor/CtInheritanceScanner.java @@ -59,6 +59,7 @@ import spoon.reflect.code.CtSwitchExpression; import spoon.reflect.code.CtSynchronized; import spoon.reflect.code.CtTargetedExpression; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -129,7 +130,7 @@ /** * This class provides an abstract implementation of the visitor that allows its - * subclasses to scans the metamodel elements by recursively using their + * subclasses to scan the metamodel elements by recursively using their * (abstract) supertype scanning methods. It declares a scan method for each * abstract element of the AST and a visit method for each element of the AST. */ @@ -664,6 +665,10 @@ public void visitCtLiteral(CtLiteral e) { scanCtVisitable(e); } + public void visitCtTextBlock(CtTextBlock e) { + visitCtLiteral(e); + } + public void visitCtLocalVariable(CtLocalVariable e) { scanCtStatement(e); scanCtVariable(e); diff --git a/src/main/java/spoon/reflect/visitor/CtScanner.java b/src/main/java/spoon/reflect/visitor/CtScanner.java index e031110b920..28ac2fcc655 100644 --- a/src/main/java/spoon/reflect/visitor/CtScanner.java +++ b/src/main/java/spoon/reflect/visitor/CtScanner.java @@ -53,6 +53,7 @@ import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSwitchExpression; import spoon.reflect.code.CtSynchronized; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -515,6 +516,15 @@ public void visitCtLiteral(final CtLiteral literal) { exit(literal); } + public void visitCtTextBlock(final CtTextBlock literal) { + enter(literal); + scan(CtRole.ANNOTATION, literal.getAnnotations()); + scan(CtRole.TYPE, literal.getType()); + scan(CtRole.CAST, literal.getTypeCasts()); + scan(CtRole.COMMENT, literal.getComments()); + exit(literal); + } + public void visitCtLocalVariable(final CtLocalVariable localVariable) { enter(localVariable); scan(CtRole.ANNOTATION, localVariable.getAnnotations()); diff --git a/src/main/java/spoon/reflect/visitor/CtVisitor.java b/src/main/java/spoon/reflect/visitor/CtVisitor.java index 59d7df723ca..d7b24d82e99 100644 --- a/src/main/java/spoon/reflect/visitor/CtVisitor.java +++ b/src/main/java/spoon/reflect/visitor/CtVisitor.java @@ -47,6 +47,7 @@ import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSwitchExpression; import spoon.reflect.code.CtSynchronized; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -273,6 +274,11 @@ public interface CtVisitor { */ void visitCtLiteral(CtLiteral literal); + /** + * Visits a literal TextBlock string. + */ + void visitCtTextBlock(CtTextBlock ctTextBlock); + /** * Visits a local variable declaration. */ diff --git a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java index bb8daa3184d..1b8523039c1 100644 --- a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java +++ b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java @@ -60,6 +60,7 @@ import spoon.reflect.code.CtSwitchExpression; import spoon.reflect.code.CtSynchronized; import spoon.reflect.code.CtTargetedExpression; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -1342,6 +1343,15 @@ public void visitCtLiteral(CtLiteral literal) { exitCtExpression(literal); } + @Override + public void visitCtTextBlock(CtTextBlock ctTextBlock) { + enterCtExpression(ctTextBlock); + printer.writeLiteral( + LiteralHelper.getTextBlockToken(ctTextBlock) + ); + exitCtExpression(ctTextBlock); + } + @Override public void visitCtLocalVariable(CtLocalVariable localVariable) { enterCtStatement(localVariable); diff --git a/src/main/java/spoon/reflect/visitor/LiteralHelper.java b/src/main/java/spoon/reflect/visitor/LiteralHelper.java index fda60ec353d..354299bc640 100644 --- a/src/main/java/spoon/reflect/visitor/LiteralHelper.java +++ b/src/main/java/spoon/reflect/visitor/LiteralHelper.java @@ -8,6 +8,7 @@ package spoon.reflect.visitor; import spoon.reflect.code.CtLiteral; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.LiteralBase; import spoon.reflect.cu.SourcePosition; @@ -55,6 +56,18 @@ private static String getBasedString(Double value, LiteralBase base) { return Double.toString(value); } + /** + * @param literal CtTextBlock to be converted + * @param numTabs + * @return source code representation of the literal + */ + public static String getTextBlockToken(CtTextBlock literal) { + String token = "\"\"\"\n" + + literal.getValue() + + "\"\"\""; + return token; + } + /** * @param literal to be converted literal * @return source code representation of the literal diff --git a/src/main/java/spoon/support/DefaultCoreFactory.java b/src/main/java/spoon/support/DefaultCoreFactory.java index 12654b4a5a8..0de335614df 100644 --- a/src/main/java/spoon/support/DefaultCoreFactory.java +++ b/src/main/java/spoon/support/DefaultCoreFactory.java @@ -49,6 +49,7 @@ import spoon.reflect.code.CtSwitch; import spoon.reflect.code.CtSwitchExpression; import spoon.reflect.code.CtSynchronized; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtThisAccess; import spoon.reflect.code.CtThrow; import spoon.reflect.code.CtTry; @@ -143,6 +144,7 @@ import spoon.support.reflect.code.CtSwitchExpressionImpl; import spoon.support.reflect.code.CtSwitchImpl; import spoon.support.reflect.code.CtSynchronizedImpl; +import spoon.support.reflect.code.CtTextBlockImpl; import spoon.support.reflect.code.CtThisAccessImpl; import spoon.support.reflect.code.CtThrowImpl; import spoon.support.reflect.code.CtTryImpl; @@ -465,6 +467,13 @@ public CtLiteral createLiteral() { return e; } + @Override + public CtTextBlock createTextBlock() { + CtTextBlock textblock = new CtTextBlockImpl(); + textblock.setFactory(getMainFactory()); + return textblock; + } + @Override public CtLocalVariable createLocalVariable() { CtLocalVariable e = new CtLocalVariableImpl<>(); @@ -911,6 +920,9 @@ public CtElement create(Class klass) { if (klass.equals(spoon.reflect.code.CtLiteral.class)) { return createLiteral(); } + if (klass.equals(spoon.reflect.code.CtTextBlock.class)) { + return createTextBlock(); + } if (klass.equals(spoon.reflect.code.CtLocalVariable.class)) { return createLocalVariable(); } diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index dfa1bb1d614..60175548659 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -88,6 +88,7 @@ import org.eclipse.jdt.internal.compiler.ast.SwitchExpression; import org.eclipse.jdt.internal.compiler.ast.SwitchStatement; import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement; +import org.eclipse.jdt.internal.compiler.ast.TextBlock; import org.eclipse.jdt.internal.compiler.ast.ThisReference; import org.eclipse.jdt.internal.compiler.ast.ThrowStatement; import org.eclipse.jdt.internal.compiler.ast.TrueLiteral; @@ -1634,7 +1635,12 @@ public boolean visit(SingleTypeReference singleTypeReference, ClassScope scope) @Override public boolean visit(StringLiteral stringLiteral, BlockScope scope) { - context.enter(factory.Code().createLiteral(CharOperation.charToString(stringLiteral.source())), stringLiteral); + if (stringLiteral instanceof TextBlock) { + TextBlock textBlockLiteral = (TextBlock) stringLiteral; + context.enter(factory.Code().createTextBlock(CharOperation.charToString(textBlockLiteral.source())), textBlockLiteral); + } else { + context.enter(factory.Code().createLiteral(CharOperation.charToString(stringLiteral.source())), stringLiteral); + } return true; } diff --git a/src/main/java/spoon/support/reflect/code/CtTextBlockImpl.java b/src/main/java/spoon/support/reflect/code/CtTextBlockImpl.java new file mode 100644 index 00000000000..4d6235084ff --- /dev/null +++ b/src/main/java/spoon/support/reflect/code/CtTextBlockImpl.java @@ -0,0 +1,25 @@ +/** + * SPDX-License-Identifier: (MIT OR CECILL-C) + * + * Copyright (C) 2006-2019 INRIA and contributors + * + * Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) of 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.code; + +import spoon.reflect.code.CtTextBlock; +import spoon.reflect.visitor.CtVisitor; + +public class CtTextBlockImpl extends CtLiteralImpl implements CtTextBlock { + private static final long serialVersionUID = 1L; + + @Override + public CtTextBlock clone() { + return (CtTextBlock) super.clone(); + } + + @Override + public void accept(CtVisitor visitor) { + visitor.visitCtTextBlock(this); + } +} diff --git a/src/main/java/spoon/support/visitor/clone/CloneBuilder.java b/src/main/java/spoon/support/visitor/clone/CloneBuilder.java index faaee95afd3..fd611d1420e 100644 --- a/src/main/java/spoon/support/visitor/clone/CloneBuilder.java +++ b/src/main/java/spoon/support/visitor/clone/CloneBuilder.java @@ -6,6 +6,7 @@ * Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) of 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.visitor.clone; + /** * Used to set all data in the cloned element. * diff --git a/src/main/java/spoon/support/visitor/clone/CloneVisitor.java b/src/main/java/spoon/support/visitor/clone/CloneVisitor.java index 6322df49b8e..dfeecc7dbb1 100644 --- a/src/main/java/spoon/support/visitor/clone/CloneVisitor.java +++ b/src/main/java/spoon/support/visitor/clone/CloneVisitor.java @@ -6,6 +6,7 @@ * Spoon is available either under the terms of the MIT License (see LICENSE-MIT.txt) of 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.visitor.clone; + /** * Used to clone a given element. * @@ -435,6 +436,18 @@ public void visitCtLiteral(final spoon.reflect.code.CtLiteral literal) { this.other = aCtLiteral; } + // auto-generated, see spoon.generating.CloneVisitorGenerator + public void visitCtTextBlock(final spoon.reflect.code.CtTextBlock literal) { + spoon.reflect.code.CtTextBlock aCtTextBlock = literal.getFactory().Core().createTextBlock(); + this.builder.copy(literal, aCtTextBlock); + aCtTextBlock.setAnnotations(this.cloneHelper.clone(literal.getAnnotations())); + aCtTextBlock.setType(this.cloneHelper.clone(literal.getType())); + aCtTextBlock.setTypeCasts(this.cloneHelper.clone(literal.getTypeCasts())); + aCtTextBlock.setComments(this.cloneHelper.clone(literal.getComments())); + this.cloneHelper.tailor(literal, aCtTextBlock); + this.other = aCtTextBlock; + } + // auto-generated, see spoon.generating.CloneVisitorGenerator public void visitCtLocalVariable(final spoon.reflect.code.CtLocalVariable localVariable) { spoon.reflect.code.CtLocalVariable aCtLocalVariable = localVariable.getFactory().Core().createLocalVariable(); diff --git a/src/main/java/spoon/support/visitor/equals/EqualsChecker.java b/src/main/java/spoon/support/visitor/equals/EqualsChecker.java index 738c8d0b9eb..b8e65e174e0 100644 --- a/src/main/java/spoon/support/visitor/equals/EqualsChecker.java +++ b/src/main/java/spoon/support/visitor/equals/EqualsChecker.java @@ -14,6 +14,7 @@ import spoon.reflect.code.CtLiteral; import spoon.reflect.code.CtOperatorAssignment; import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtUnaryOperator; import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtMethod; @@ -242,6 +243,21 @@ public void visitCtLiteral(CtLiteral e) { super.visitCtLiteral(e); } + @Override + public void visitCtTextBlock(CtTextBlock e) { + final CtTextBlock peek = (CtTextBlock) this.other; + if (e.getValue() == null) { + if (peek.getValue() != null) { + setNotEqual(CtRole.VALUE); + } + } else if (peek.getValue() == null) { + setNotEqual(CtRole.VALUE); + } else if (!e.getValue().equals(peek.getValue())) { + setNotEqual(CtRole.VALUE); + } + super.visitCtTextBlock(e); + } + @Override public void visitCtImport(CtImport ctImport) { final CtImport peek = (CtImport) this.other; diff --git a/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java b/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java index 7063f9f9962..83960a589d0 100644 --- a/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java +++ b/src/main/java/spoon/support/visitor/replace/ReplacementVisitor.java @@ -1771,6 +1771,15 @@ public void visitCtLiteral(final spoon.reflect.code.CtLiteral literal) { replaceInListIfExist(literal.getComments(), new spoon.support.visitor.replace.ReplacementVisitor.CtElementCommentsReplaceListener(literal)); } + // auto-generated, see spoon.generating.ReplacementVisitorGenerator + @java.lang.Override + public void visitCtTextBlock(final spoon.reflect.code.CtTextBlock literal) { + replaceInListIfExist(literal.getAnnotations(), new spoon.support.visitor.replace.ReplacementVisitor.CtElementAnnotationsReplaceListener(literal)); + replaceElementIfExist(literal.getType(), new spoon.support.visitor.replace.ReplacementVisitor.CtTypedElementTypeReplaceListener(literal)); + replaceInListIfExist(literal.getTypeCasts(), new spoon.support.visitor.replace.ReplacementVisitor.CtExpressionTypeCastsReplaceListener(literal)); + replaceInListIfExist(literal.getComments(), new spoon.support.visitor.replace.ReplacementVisitor.CtElementCommentsReplaceListener(literal)); + } + // auto-generated, see spoon.generating.ReplacementVisitorGenerator @java.lang.Override public void visitCtLocalVariable(final spoon.reflect.code.CtLocalVariable localVariable) { diff --git a/src/test/java/spoon/test/api/Metamodel.java b/src/test/java/spoon/test/api/Metamodel.java index c9d5df2c30c..ede8bdd8734 100644 --- a/src/test/java/spoon/test/api/Metamodel.java +++ b/src/test/java/spoon/test/api/Metamodel.java @@ -1110,6 +1110,18 @@ private static void initTypes(List types) { )); + types.add(new Type("CtTextBlock", spoon.reflect.code.CtTextBlock.class, spoon.support.reflect.code.CtTextBlockImpl.class, fm -> fm + .field(CtRole.IS_IMPLICIT, false, false) + .field(CtRole.VALUE, false, false) + .field(CtRole.POSITION, false, false) + .field(CtRole.LITERAL_BASE, false, false) + .field(CtRole.ANNOTATION, false, false) + .field(CtRole.TYPE, false, false) + .field(CtRole.CAST, false, false) + .field(CtRole.COMMENT, false, false) + + )); + types.add(new Type("CtReturn", spoon.reflect.code.CtReturn.class, spoon.support.reflect.code.CtReturnImpl.class, fm -> fm .field(CtRole.IS_IMPLICIT, false, false) .field(CtRole.LABEL, false, false) diff --git a/src/test/java/spoon/test/comment/CommentTest.java b/src/test/java/spoon/test/comment/CommentTest.java index 16392b505b0..a996267cd48 100644 --- a/src/test/java/spoon/test/comment/CommentTest.java +++ b/src/test/java/spoon/test/comment/CommentTest.java @@ -803,7 +803,11 @@ public void testDocumentationContract() throws Exception { final Launcher launcher = new Launcher(); launcher.getEnvironment().setNoClasspath(true); launcher.getEnvironment().setCommentEnabled(true); + + // TODO: Compliance level should be set at 15 and previews disabled launcher.getEnvironment().setComplianceLevel(14); + launcher.getEnvironment().setPreviewFeaturesEnabled(true); + // interfaces. launcher.addInputResource("./src/main/java/spoon/reflect/"); launcher.addInputResource("./src/main/java/spoon/support/reflect/"); diff --git a/src/test/java/spoon/test/textBlocks/TextBlockTest.java b/src/test/java/spoon/test/textBlocks/TextBlockTest.java index 85c4cf6bf81..801dbb984bd 100644 --- a/src/test/java/spoon/test/textBlocks/TextBlockTest.java +++ b/src/test/java/spoon/test/textBlocks/TextBlockTest.java @@ -1,16 +1,21 @@ package spoon.test.textBlocks; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import org.junit.Test; import spoon.Launcher; +import spoon.reflect.code.CtBlock; import spoon.reflect.code.CtInvocation; import spoon.reflect.code.CtLiteral; +import spoon.reflect.code.CtReturn; import spoon.reflect.code.CtStatement; +import spoon.reflect.code.CtTextBlock; import spoon.reflect.code.CtTry; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtMethod; +import spoon.reflect.factory.Factory; import spoon.reflect.path.CtRole; /** Test for the new Java 15 text block feature with */ @@ -21,7 +26,13 @@ private Launcher setUpTest() { launcher.run(); return launcher; } - + + private Factory getSpoonFactory() { + final Launcher launcher = new Launcher(); + launcher.run(); + return launcher.getFactory(); + } + @Test public void testTextBlock1(){ //contract: Test Text Block usage introduced in Java 15 @@ -30,7 +41,8 @@ public void testTextBlock1(){ CtMethod m1 = allstmt.getMethod("m1"); CtStatement stmt1 = m1.getBody().getStatement(0); - CtLiteral l1 = (CtLiteral) stmt1.getValueByRole(CtRole.ASSIGNMENT); + assertTrue(stmt1.getValueByRole(CtRole.ASSIGNMENT) instanceof CtTextBlock); + CtTextBlock l1 = (CtTextBlock) stmt1.getValueByRole(CtRole.ASSIGNMENT); assertEquals(l1.getValue(), "\n \n

Hello, कसौटी 🥲

\n \n\n"); } @@ -42,7 +54,8 @@ public void testTextBlockqoute(){ CtMethod m2 = allstmt.getMethod("m2"); CtStatement stmt2 = m2.getBody().getStatement(0); - CtLiteral l2 = (CtLiteral) stmt2.getValueByRole(CtRole.ASSIGNMENT); + assertTrue(stmt2.getValueByRole(CtRole.ASSIGNMENT) instanceof CtTextBlock); + CtTextBlock l2 = (CtTextBlock) stmt2.getValueByRole(CtRole.ASSIGNMENT); assertEquals(l2.getValue(), "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n" + "WHERE \"CITY\" = 'INDIANAPOLIS'\n" + "ORDER BY \"EMP_ID\", \"LAST_NAME\";\n"); @@ -58,7 +71,8 @@ public void testTextBlockQouteWithinQoute(){ CtTry stmt4 = (CtTry) m3.getBody().getStatement(1); CtStatement stmt5 = stmt4.getBody().getStatement(0); CtInvocation inv = (CtInvocation) stmt5.getDirectChildren().get(1); - CtLiteral l3 = (CtLiteral) inv.getArguments().get(0); + assertTrue(inv.getArguments().get(0) instanceof CtTextBlock); + CtTextBlock l3 = (CtTextBlock) inv.getArguments().get(0); assertEquals(l3.getValue(), "function hello() {\n" + " print('\"Hello, world\"');\n" + "}\n" @@ -75,7 +89,31 @@ public void testTextBlockEmpty(){ CtMethod m4 = allstmt.getMethod("m4"); CtStatement stmt1 = m4.getBody().getStatement(0); - CtLiteral l1 = (CtLiteral) stmt1.getValueByRole(CtRole.ASSIGNMENT); + assertTrue(stmt1.getValueByRole(CtRole.ASSIGNMENT) instanceof CtTextBlock); + CtTextBlock l1 = (CtTextBlock) stmt1.getValueByRole(CtRole.ASSIGNMENT); assertEquals(l1.getValue(), ""); } + + @Test + public void testTextBlockCreation(){ + // contract: Test creation of TextBlock and prettyprinting + Factory factory = getSpoonFactory(); + CtClass c = Launcher.parseClass("class Test{public String m1(){String s = \"\";}}"); + CtBlock body = c.getMethod("m1").getBody(); + CtReturn ret = factory.createReturn(); + ret.setValueByRole(CtRole.EXPRESSION, factory.createTextBlock("Hello, \"World\"!\nTesting\n\tTabs")); + body.insertEnd(ret); + assertEquals( + "class Test {\n" + + " public String m1() {\n" + + " String s = \"\";\n" + + " return \"\"\"\n" + + " Hello, \"World\"!\n" + + " Testing\n" + + " Tabs\"\"\";\n" + + " }\n" + + "}", + c.toString() + ); + } }