diff --git a/grails-datamapping-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy b/grails-datamapping-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy index 508582e6d4a..8263d9443ad 100644 --- a/grails-datamapping-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy +++ b/grails-datamapping-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy @@ -20,7 +20,7 @@ package grails.gorm.async import groovy.transform.CompileStatic - +import groovy.transform.Generated import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.GormEntity import org.grails.datastore.gorm.async.GormAsyncStaticApi @@ -37,6 +37,7 @@ trait AsyncEntity extends GormEntity { /** * @return The async version of the GORM static API */ + @Generated static GormAsyncStaticApi getAsync() { return new GormAsyncStaticApi(GormEnhancer.findStaticApi(this)) } diff --git a/grails-datamapping-core-test/src/test/groovy/org/grails/datastore/gorm/schemaless/ImplementsDynamicAttributes.groovy b/grails-datamapping-core-test/src/test/groovy/org/grails/datastore/gorm/schemaless/ImplementsDynamicAttributes.groovy index e350ae6f32f..a0469bede39 100644 --- a/grails-datamapping-core-test/src/test/groovy/org/grails/datastore/gorm/schemaless/ImplementsDynamicAttributes.groovy +++ b/grails-datamapping-core-test/src/test/groovy/org/grails/datastore/gorm/schemaless/ImplementsDynamicAttributes.groovy @@ -18,9 +18,12 @@ */ package org.grails.datastore.gorm.schemaless +import groovy.transform.Generated import spock.lang.Issue import spock.lang.Specification +import java.lang.reflect.Method + class DynamicDomainSpec extends Specification { @@ -41,6 +44,12 @@ class DynamicDomainSpec extends Specification { entity.attributes().foo == 123 } + void "test that all DynamicAttributes trait methods are marked as Generated"() { + expect: "all DynamicAttributes methods are marked as Generated on implementation class" + DynamicAttributes.getMethods().each { Method traitMethod -> + assert DynamicEntity.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } } class DynamicEntity implements DynamicAttributes { @@ -51,4 +60,4 @@ class DynamicEntity implements DynamicAttributes { "foo" } -} \ No newline at end of file +} diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/MultiTenant.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/MultiTenant.groovy index 5e8053bc4e1..4e93062bc6b 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/MultiTenant.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/MultiTenant.groovy @@ -20,7 +20,7 @@ package grails.gorm import groovy.transform.CompileStatic - +import groovy.transform.Generated import grails.gorm.api.GormAllOperations import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.mapping.core.connections.ConnectionSource @@ -41,6 +41,7 @@ trait MultiTenant extends Entity { * @param callable The closure * @return The result of the closure */ + @Generated static T withTenant(Serializable tenantId, Closure callable) { GormEnhancer.findStaticApi(this).withTenant(tenantId, callable) } @@ -51,6 +52,7 @@ trait MultiTenant extends Entity { * @param callable The closure * @return The result of the closure */ + @Generated static GormAllOperations eachTenant(Closure callable) { GormEnhancer.findStaticApi(this, ConnectionSource.DEFAULT).eachTenant(callable) } @@ -61,6 +63,7 @@ trait MultiTenant extends Entity { * @param tenantId The tenant id * @return The operations */ + @Generated static GormAllOperations withTenant(Serializable tenantId) { (GormAllOperations) GormEnhancer.findStaticApi(this).withTenant(tenantId) } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/time/InstantConverter.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/time/InstantConverter.groovy index 938cec5747f..7dc7ee2df5c 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/time/InstantConverter.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/time/InstantConverter.groovy @@ -22,6 +22,7 @@ package grails.gorm.time import java.time.Instant import groovy.transform.CompileStatic +import groovy.transform.Generated /** * A trait to convert a {@link java.time.Instant} to and from a long @@ -31,10 +32,12 @@ import groovy.transform.CompileStatic @CompileStatic trait InstantConverter { + @Generated Long convert(Instant value) { value.toEpochMilli() } + @Generated Instant convert(Long value) { Instant.ofEpochMilli(value) } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy index e613f3441fe..70cbdeed4a9 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy @@ -27,6 +27,7 @@ import java.time.ZoneId import java.time.ZoneOffset import groovy.transform.CompileStatic +import groovy.transform.Generated /** * A trait to convert a {@link LocalDate} to and from a long @@ -37,12 +38,14 @@ import groovy.transform.CompileStatic trait LocalDateConverter extends TemporalConverter { @Override + @Generated Long convert(LocalDate value) { LocalDateTime localDateTime = LocalDateTime.of(value, LocalTime.MIN) localDateTime.toInstant(ZoneOffset.UTC).toEpochMilli() } @Override + @Generated LocalDate convert(Long value) { Instant instant = Instant.ofEpochMilli(value) LocalDateTime.ofInstant(instant, ZoneId.of('UTC')).toLocalDate() diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateTimeConverter.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateTimeConverter.groovy index 02998a1df29..47843839f1f 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateTimeConverter.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalDateTimeConverter.groovy @@ -25,6 +25,7 @@ import java.time.ZoneId import java.time.ZoneOffset import groovy.transform.CompileStatic +import groovy.transform.Generated /** * A trait to convert a {@link java.time.LocalDateTime} to and from a long @@ -35,11 +36,13 @@ import groovy.transform.CompileStatic trait LocalDateTimeConverter implements TemporalConverter { @Override + @Generated Long convert(LocalDateTime value) { value.toInstant(ZoneOffset.UTC).toEpochMilli() } @Override + @Generated LocalDateTime convert(Long value) { LocalDateTime.ofInstant(Instant.ofEpochMilli(value), ZoneId.of('UTC')) } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalTimeConverter.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalTimeConverter.groovy index 91c092098c1..cdc699256c2 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalTimeConverter.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/time/LocalTimeConverter.groovy @@ -22,6 +22,7 @@ package grails.gorm.time import java.time.LocalTime import groovy.transform.CompileStatic +import groovy.transform.Generated /** * A trait to convert a {@link LocalTime} to and from a long @@ -32,11 +33,13 @@ import groovy.transform.CompileStatic trait LocalTimeConverter implements TemporalConverter { @Override + @Generated Long convert(LocalTime value) { value.toNanoOfDay() } @Override + @Generated LocalTime convert(Long value) { LocalTime.ofNanoOfDay(value) } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/time/OffsetDateTimeConverter.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/time/OffsetDateTimeConverter.groovy index 751b068927c..08de04fa32f 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/time/OffsetDateTimeConverter.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/time/OffsetDateTimeConverter.groovy @@ -23,6 +23,7 @@ import java.time.Instant import java.time.OffsetDateTime import groovy.transform.CompileStatic +import groovy.transform.Generated /** * A trait to convert a {@link java.time.OffsetDateTime} to and from a long @@ -33,11 +34,13 @@ import groovy.transform.CompileStatic trait OffsetDateTimeConverter implements TemporalConverter { @Override + @Generated Long convert(OffsetDateTime value) { value.toInstant().toEpochMilli() } @Override + @Generated OffsetDateTime convert(Long value) { OffsetDateTime.ofInstant(Instant.ofEpochMilli(value), systemOffset) } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/time/OffsetTimeConverter.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/time/OffsetTimeConverter.groovy index 0fed43f99d1..b72e0bba463 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/time/OffsetTimeConverter.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/time/OffsetTimeConverter.groovy @@ -24,6 +24,7 @@ import java.time.OffsetTime import java.time.ZoneOffset import groovy.transform.CompileStatic +import groovy.transform.Generated /** * A trait to convert a {@link java.time.OffsetTime} to and from a long @@ -34,11 +35,13 @@ import groovy.transform.CompileStatic trait OffsetTimeConverter implements TemporalConverter { @Override + @Generated Long convert(OffsetTime value) { value.withOffsetSameInstant(ZoneOffset.UTC).toLocalTime().toNanoOfDay() } @Override + @Generated OffsetTime convert(Long value) { OffsetTime.of(LocalTime.ofNanoOfDay(value), ZoneOffset.UTC).withOffsetSameInstant(systemOffset) } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/time/PeriodConverter.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/time/PeriodConverter.groovy index 6e3e68efaf5..a354dd36676 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/time/PeriodConverter.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/time/PeriodConverter.groovy @@ -22,6 +22,7 @@ package grails.gorm.time import java.time.Period import groovy.transform.CompileStatic +import groovy.transform.Generated /** * A trait to convert a {@link java.time.Period} to and from a String @@ -31,10 +32,12 @@ import groovy.transform.CompileStatic @CompileStatic trait PeriodConverter { + @Generated String convert(Period value) { value.toString() } + @Generated Period convert(String value) { Period.parse(value) } diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/time/TemporalConverter.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/time/TemporalConverter.groovy index 9c88d30eb08..be4092e6af4 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/time/TemporalConverter.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/time/TemporalConverter.groovy @@ -19,6 +19,8 @@ package grails.gorm.time +import groovy.transform.Generated + import java.time.Instant import java.time.ZoneId import java.time.ZoneOffset @@ -29,6 +31,7 @@ trait TemporalConverter { abstract T convert(Long value) + @Generated ZoneOffset getSystemOffset() { Instant instant = Instant.now() ZoneId systemZone = ZoneId.systemDefault() diff --git a/grails-datamapping-core/src/main/groovy/grails/gorm/time/ZonedDateTimeConverter.groovy b/grails-datamapping-core/src/main/groovy/grails/gorm/time/ZonedDateTimeConverter.groovy index 4da0c6e3d94..8e6b4fa65ff 100644 --- a/grails-datamapping-core/src/main/groovy/grails/gorm/time/ZonedDateTimeConverter.groovy +++ b/grails-datamapping-core/src/main/groovy/grails/gorm/time/ZonedDateTimeConverter.groovy @@ -23,6 +23,7 @@ import java.time.Instant import java.time.ZonedDateTime import groovy.transform.CompileStatic +import groovy.transform.Generated /** * A trait to convert a {@link java.time.ZonedDateTime} to and from a long @@ -32,11 +33,13 @@ import groovy.transform.CompileStatic @CompileStatic trait ZonedDateTimeConverter implements TemporalConverter { + @Generated @Override Long convert(ZonedDateTime value) { value.toInstant().toEpochMilli() } + @Generated @Override ZonedDateTime convert(Long value) { ZonedDateTime.ofInstant(Instant.ofEpochMilli(value), systemOffset) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy index 752298a5639..cad27db9b54 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy @@ -72,6 +72,7 @@ import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_PARAMETERS import static org.grails.datastore.mapping.reflect.AstUtils.addAnnotationIfNecessary import static org.grails.datastore.mapping.reflect.AstUtils.hasAnnotation import static org.grails.datastore.mapping.reflect.AstUtils.isDomainClass +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated /** * @@ -217,6 +218,8 @@ class DirtyCheckingTransformer implements CompilationUnitAware { null, GeneralUtils.returnS(GeneralUtils.varX(propertyField)) ) + + markAsGenerated(classNode, getIdMethod) classNode.addMethod(getIdMethod) getIdMethod.addAnnotation(GormEntityTransformation.JPA_TRANSIENT_ANNOTATION_NODE) } @@ -237,6 +240,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { null, GeneralUtils.returnS(GeneralUtils.varX(propertyField)) ) + markAsGenerated(classNode, getVersionMethod) classNode.addMethod(getVersionMethod) getVersionMethod.addAnnotation(GormEntityTransformation.JPA_TRANSIENT_ANNOTATION_NODE) } @@ -262,13 +266,15 @@ class DirtyCheckingTransformer implements CompilationUnitAware { if (getter == null) { getter = classNode.addMethod(getterName, PUBLIC, returnType, ZERO_PARAMETERS, null, returnS(varX(fieldName))) + markAsGenerated(classNode, getter) getter.addAnnotation(DIRTY_CHECKED_PROPERTY_ANNOTATION_NODE) staticCompilationVisitor.visitMethod( getter ) if (booleanProperty) { - classNode.addMethod(NameUtils.getGetterName(propertyName, true), PUBLIC, returnType, ZERO_PARAMETERS, null, returnS(varX(fieldName))) + MethodNode methodNode = classNode.addMethod(NameUtils.getGetterName(propertyName, true), PUBLIC, returnType, ZERO_PARAMETERS, null, returnS(varX(fieldName))) + markAsGenerated(classNode, methodNode) } } @@ -309,6 +315,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { null, GeneralUtils.returnS(GeneralUtils.constX(0)) ) + markAsGenerated(classNode, getVersionMethod) classNode.addMethod(getVersionMethod) getVersionMethod.addAnnotation(GormEntityTransformation.JPA_TRANSIENT_ANNOTATION_NODE) } @@ -362,6 +369,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { setterBody.addStatement(assignS(propX(varX('this'), fieldName), varX(setterParameter))) setter = classNode.addMethod(setterName, PUBLIC, ClassHelper.VOID_TYPE, params(setterParameter), null, setterBody) + markAsGenerated(classNode, setter) setter.addAnnotation(DIRTY_CHECKED_PROPERTY_ANNOTATION_NODE) staticCompilationVisitor.visitMethod( setter diff --git a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy index a899527c43d..d20647c2b57 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy @@ -78,6 +78,7 @@ import org.grails.datastore.mapping.reflect.AstUtils import org.grails.datastore.mapping.reflect.ClassUtils import org.grails.datastore.mapping.reflect.NameUtils +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated import static org.codehaus.groovy.ast.tools.GeneralUtils.args import static org.codehaus.groovy.ast.tools.GeneralUtils.callX import static org.codehaus.groovy.ast.tools.GeneralUtils.classX @@ -261,7 +262,9 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp ) def methodMissingParameters = [methodNameParam, methodArgsParam] as Parameter[] - classNode.addMethod('$static_methodMissing', Modifier.PUBLIC | Modifier.STATIC, AstUtils.OBJECT_CLASS_NODE, methodMissingParameters, null, methodMissingBody) + MethodNode methodMissingNode = + classNode.addMethod('$static_methodMissing', Modifier.PUBLIC | Modifier.STATIC, AstUtils.OBJECT_CLASS_NODE, methodMissingParameters, null, methodMissingBody) + markAsGenerated(classNode, methodMissingNode) // $static_propertyMissing setter def propertyMissingSetBody = new BlockStatement() @@ -273,7 +276,9 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp new ExpressionStatement(propertyMissingSetMethodCall) ) def propertyMissingSetParameters = [propertyMissingSetNameParam, propertyMissingSetValueParam] as Parameter[] - classNode.addMethod('$static_propertyMissing', Modifier.PUBLIC | Modifier.STATIC, AstUtils.OBJECT_CLASS_NODE, propertyMissingSetParameters, null, propertyMissingSetBody) + MethodNode propertyMissingNodeSetter = + classNode.addMethod('$static_propertyMissing', Modifier.PUBLIC | Modifier.STATIC, AstUtils.OBJECT_CLASS_NODE, propertyMissingSetParameters, null, propertyMissingSetBody) + markAsGenerated(classNode, propertyMissingNodeSetter) // $static_propertyMissing getter def propertyMissingGetBody = new BlockStatement() @@ -284,7 +289,9 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp new ExpressionStatement(propertyMissingGetMethodCall) ) def propertyMissingGetParameters = [propertyMissingGetNameParam] as Parameter[] - classNode.addMethod('$static_propertyMissing', Modifier.PUBLIC | Modifier.STATIC, AstUtils.OBJECT_CLASS_NODE, propertyMissingGetParameters, null, propertyMissingGetBody) + MethodNode propertyMissingNodeGetter = + classNode.addMethod('$static_propertyMissing', Modifier.PUBLIC | Modifier.STATIC, AstUtils.OBJECT_CLASS_NODE, propertyMissingGetParameters, null, propertyMissingGetBody) + markAsGenerated(classNode, propertyMissingNodeGetter) // now process named query associations // see https://grails.apache.org/docs/latest/ref/Domain%20Classes/namedQueries.html @@ -343,6 +350,8 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp } methodBody.addStatement(returnS(createNamedQueryCall)) MethodNode newMethod = new MethodNode(methodName, Modifier.PUBLIC | Modifier.STATIC, queryOperationsClassNode, newParams, null, methodBody) + + markAsGenerated(thisClassNode, newMethod) thisClassNode.addMethod(newMethod) if (!hasParameters) { @@ -351,6 +360,7 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp existing = thisClassNode.getMethod(namedQueryGetter, AstUtils.ZERO_PARAMETERS) if (existing == null || !existing.getDeclaringClass().equals(thisClassNode)) { newMethod = new MethodNode(namedQueryGetter, Modifier.PUBLIC | Modifier.STATIC, queryOperationsClassNode, AstUtils.ZERO_PARAMETERS, null, methodBody) + markAsGenerated(thisClassNode, newMethod) thisClassNode.addMethod(newMethod) } } @@ -581,6 +591,7 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp ) def mn = new MethodNode(idProperty, Modifier.PUBLIC, AstUtils.OBJECT_CLASS_NODE, AstUtils.ZERO_PARAMETERS, null, methodBody) + markAsGenerated(classNode, mn) classNode.addMethod(mn) } } @@ -626,6 +637,7 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp ) def mn = new MethodNode(addToMethod, Modifier.PUBLIC, classNode.getPlainNodeReference(), ADD_TO_PARAMETERS, null, methodBody) + markAsGenerated(classNode, mn) classNode.addMethod(mn) } @@ -647,6 +659,7 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp ) def mn = new MethodNode(removeFromMethod, Modifier.PUBLIC, classNode.getPlainNodeReference(), ADD_TO_PARAMETERS, null, methodBody) + markAsGenerated(classNode, mn) classNode.addMethod(mn) } } @@ -681,6 +694,7 @@ class GormEntityTransformation extends AbstractASTTransformation implements Comp ge.addValue(new TernaryExpression(new BooleanExpression(idVariable), idVariable, new ConstantExpression('(unsaved)'))) Statement s = new ReturnStatement(ge) MethodNode mn = new MethodNode('toString', Modifier.PUBLIC, new ClassNode(String), new Parameter[0], new ClassNode[0], s) + markAsGenerated(classNode, mn) classNode.addMethod(mn) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy index 93b9cf670a7..f0ceb2b4e8a 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy @@ -20,7 +20,7 @@ package org.grails.datastore.gorm import groovy.transform.CompileDynamic import groovy.transform.CompileStatic - +import groovy.transform.Generated import jakarta.persistence.Transient import org.springframework.transaction.TransactionDefinition @@ -59,6 +59,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi getGormDynamicFinders() { currentGormStaticApi().gormDynamicFinders } @@ -437,6 +465,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi where(Closure callable) { currentGormStaticApi().where(callable) } @@ -446,6 +475,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi whereLazy(Closure callable) { currentGormStaticApi().whereLazy(callable) } @@ -455,6 +485,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi whereAny(Closure callable) { currentGormStaticApi().whereAny(callable) } @@ -465,6 +496,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(Closure callable) { currentGormStaticApi().findAll(callable) } @@ -476,6 +508,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(Map args, Closure callable) { currentGormStaticApi().findAll(args, callable) } @@ -486,6 +519,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi saveAll(Object... objectsToSave) { currentGormStaticApi().saveAll(objectsToSave) } @@ -504,6 +539,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi saveAll(Iterable objectsToSave) { currentGormStaticApi().saveAll(objectsToSave) } @@ -512,6 +548,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi getAll(Iterable ids) { currentGormStaticApi().getAll(ids) } @@ -593,6 +639,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi getAll(Serializable... ids) { currentGormStaticApi().getAll(ids) } @@ -600,6 +647,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi getAll() { list() } @@ -607,6 +655,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi list(Map params) { currentGormStaticApi().list(params) } @@ -680,6 +737,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi list() { currentGormStaticApi().list() } @@ -689,6 +747,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(Map params = Collections.emptyMap()) { currentGormStaticApi().findAll(params) } @@ -699,6 +758,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(D example) { currentGormStaticApi().findAll(example) } @@ -711,6 +771,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(D example, Map args) { currentGormStaticApi().findAll(example, args) } @@ -720,6 +781,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi findAllWhere(Map queryMap) { currentGormStaticApi().findAllWhere(queryMap) } @@ -839,6 +910,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAllWhere(Map queryMap, Map args) { currentGormStaticApi().findAllWhere(queryMap, args) } @@ -849,6 +921,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi T withSession(Closure callable) { currentGormStaticApi().withSession(callable) } @@ -925,6 +1004,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withDatastoreSession(Closure callable) { currentGormStaticApi().withDatastoreSession(callable) } @@ -939,6 +1019,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withTransaction(Closure callable) { currentGormStaticApi().withTransaction(callable) } @@ -952,6 +1033,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withNewTransaction(Closure callable) { currentGormStaticApi().withNewTransaction(callable) } @@ -979,6 +1061,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withTransaction(Map transactionProperties, Closure callable) { currentGormStaticApi().withTransaction(transactionProperties, callable) } @@ -1008,6 +1091,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withNewTransaction(Map transactionProperties, Closure callable) { currentGormStaticApi().withNewTransaction(transactionProperties, callable) } @@ -1018,6 +1102,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withTransaction(TransactionDefinition definition, Closure callable) { currentGormStaticApi().withTransaction(definition, callable) } @@ -1025,6 +1110,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withNewSession(Closure callable) { currentGormStaticApi().withNewSession(callable) } @@ -1032,6 +1118,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withStatelessSession(Closure callable) { currentGormStaticApi().withStatelessSession(callable) } @@ -1042,6 +1129,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query) { currentGormStaticApi().findAll(query) } @@ -1284,6 +1390,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query, Map params) { currentGormStaticApi().findAll(query, params) } @@ -1297,6 +1404,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query, Map params, Map args) { currentGormStaticApi().findAll(query, params, args) } @@ -1309,6 +1417,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query, Collection params) { currentGormStaticApi().findAll(query, params) } @@ -1321,6 +1430,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query, Object[] params) { currentGormStaticApi().findAll(query, params) } @@ -1334,6 +1444,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query, Collection params, Map args) { currentGormStaticApi().findAll(query, params, args) } @@ -1346,6 +1457,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi getNamedQuery(String queryName) { GormEnhancer.createNamedQuery(this, queryName) @@ -1358,15 +1470,18 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi getNamedQuery(String queryName, Object...args) { GormEnhancer.createNamedQuery(this, queryName, args) } + @Generated private GormInstanceApi currentGormInstanceApi() { (GormInstanceApi) GormEnhancer.findInstanceApi(getClass()) } + @Generated private static GormStaticApi currentGormStaticApi() { (GormStaticApi) GormEnhancer.findStaticApi(this) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityDirtyCheckable.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityDirtyCheckable.groovy index 2de81cfa794..9b5edc66e00 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityDirtyCheckable.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormEntityDirtyCheckable.groovy @@ -21,7 +21,7 @@ package org.grails.datastore.gorm import groovy.transform.CompileStatic import jakarta.annotation.Generated - +import groovy.transform.Generated as GroovyGenerated import org.grails.datastore.mapping.config.Property import org.grails.datastore.mapping.dirty.checking.DirtyCheckable import org.grails.datastore.mapping.model.PersistentEntity @@ -39,6 +39,7 @@ trait GormEntityDirtyCheckable extends DirtyCheckable { @Override @Generated + @GroovyGenerated boolean hasChanged(String propertyName) { PersistentEntity entity = currentGormInstanceApi().persistentEntity diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormValidateable.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormValidateable.groovy index f3b67923ab9..2baf26e05e0 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormValidateable.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/GormValidateable.groovy @@ -19,7 +19,7 @@ package org.grails.datastore.gorm import groovy.transform.CompileStatic - +import groovy.transform.Generated import jakarta.persistence.Transient import org.springframework.validation.Errors @@ -42,13 +42,14 @@ trait GormValidateable { * The validation errors object */ @Transient - Errors errors + private Errors errors /** * Marks this instance to skip validation * * @param shouldSkip True if validation should be skipped */ + @Generated void skipValidation(boolean shouldSkip) { this.skipValidate = shouldSkip } @@ -56,6 +57,7 @@ trait GormValidateable { /** * @return Whether this instance should skip validation */ + @Generated boolean shouldSkipValidation() { // skip validation if validation set to true or validation handled by jakarta.validation return this.skipValidate @@ -67,6 +69,7 @@ trait GormValidateable { * @param arguments The arguments to use * @return True if the instance is valid */ + @Generated boolean validate(Map arguments) { currentGormValidationApi().validate(this, arguments) } @@ -77,6 +80,7 @@ trait GormValidateable { * @param fields The list of fields to validate * @return True if the instance is valid */ + @Generated boolean validate(List fields) { currentGormValidationApi().validate(this, fields) } @@ -86,6 +90,7 @@ trait GormValidateable { * * @return True if the instance is valid */ + @Generated boolean validate() { currentGormValidationApi().validate(this) } @@ -94,6 +99,7 @@ trait GormValidateable { * Obtains the errors for an instance * @return The {@link Errors} instance */ + @Generated @Transient Errors getErrors() { if (errors == null) { @@ -102,9 +108,16 @@ trait GormValidateable { errors } + @Generated + @Transient + void setErrors(Errors errors) { + this.errors = errors + } + /** * Clears any errors that exist on an instance */ + @Generated void clearErrors() { errors = new ValidationErrors(this) } @@ -113,6 +126,7 @@ trait GormValidateable { * Tests whether an instance has any errors * @return True if errors exist */ + @Generated Boolean hasErrors() { getErrors().hasErrors() } @@ -120,6 +134,7 @@ trait GormValidateable { /** * Used to obtain the {@link GormValidationApi} instance. This method is used internally by the framework and SHOULD NOT be called by the developer */ + @Generated private GormValidationApi currentGormValidationApi() { GormEnhancer.findValidationApi(getClass()) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy index 6a808ce89e8..2003abc726a 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy @@ -20,7 +20,7 @@ package org.grails.datastore.gorm.schemaless import groovy.transform.CompileStatic - +import groovy.transform.Generated import org.grails.datastore.mapping.dirty.checking.DirtyCheckable /** @@ -34,6 +34,7 @@ trait DynamicAttributes { private transient Map dynamicAttributes = [:] + @Generated private void putAtDynamic(String name, value) { def oldValue = dynamicAttributes.put(name, value) if (oldValue != value) { @@ -49,6 +50,7 @@ trait DynamicAttributes { * @param name The name of the attribute * @param value The value of the attribute */ + @Generated void putAt(String name, value) { if (this.hasProperty(name)) { try { @@ -67,6 +69,7 @@ trait DynamicAttributes { * @param name The name of the attribute * @return The value of the attribute */ + @Generated def getAt(String name) { if (this.hasProperty(name)) { return ((GroovyObject) this).getProperty(name) @@ -81,6 +84,7 @@ trait DynamicAttributes { * * @return The dynamic attributes */ + @Generated Map attributes() { return this.dynamicAttributes } @@ -91,6 +95,7 @@ trait DynamicAttributes { * @param newAttributes The new attributes * @return The dynamic attributes */ + @Generated Map attributes(Map newAttributes) { if (newAttributes != null) { this.dynamicAttributes.putAll(newAttributes) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy index b15c0a9d8f8..fbd74fce15e 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy @@ -25,6 +25,8 @@ import org.codehaus.groovy.ast.MethodNode import org.grails.datastore.mapping.reflect.AstUtils +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated + /** * Abstract implementation of a finder that handles Array and Iterables of domain classes * @@ -54,6 +56,7 @@ abstract class AbstractArrayOrIterableResultImplementer extends AbstractReadOper domainClassNode = domainClassForReturnType } doImplement(domainClassNode, targetClassNode, abstractMethodNode, newMethodNode, isArray) + markAsGenerated(targetClassNode, newMethodNode) } /** diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy index 2991db00090..08cf9aeffed 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy @@ -32,6 +32,8 @@ import org.grails.datastore.gorm.services.ServiceEnhancer import org.grails.datastore.gorm.transactions.transform.TransactionalTransform import org.grails.datastore.mapping.reflect.AstUtils +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated + /** * Abstract implementor for read operations * @@ -64,6 +66,9 @@ abstract class AbstractReadOperationImplementer extends AbstractServiceImplement domainClassNode = domainClassFromSignature } doImplement(domainClassNode, abstractMethodNode, newMethodNode, targetClassNode) + + markAsGenerated(targetClassNode, newMethodNode) + abstractMethodNode.putNodeMetaData(IMPLEMENTED, Boolean.TRUE) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy index 3d4528d16a8..a08205afb31 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy @@ -27,6 +27,8 @@ import org.codehaus.groovy.ast.MethodNode import org.grails.datastore.gorm.services.ServiceEnhancer import org.grails.datastore.gorm.transactions.transform.TransactionalTransform +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated + /** * Abstract implementer for write operations * @@ -55,6 +57,9 @@ abstract class AbstractWriteOperationImplementer extends AbstractServiceImplemen } doImplement(domainClassNode, abstractMethodNode, newMethodNode, targetClassNode) + + markAsGenerated(targetClassNode, newMethodNode) + abstractMethodNode.putNodeMetaData(IMPLEMENTED, Boolean.TRUE) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy index b1f93aa0e33..992736c182f 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy @@ -22,6 +22,7 @@ package org.grails.datastore.gorm.services.implementers import java.lang.reflect.Modifier import groovy.transform.CompileStatic +import groovy.transform.Generated import org.codehaus.groovy.ast.ASTNode import org.codehaus.groovy.ast.AnnotationNode import org.codehaus.groovy.ast.ClassHelper @@ -40,6 +41,7 @@ import org.grails.datastore.gorm.transform.AstPropertyResolveUtils import org.grails.datastore.mapping.reflect.AstUtils import org.grails.datastore.mapping.reflect.NameUtils +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS import static org.codehaus.groovy.ast.tools.GeneralUtils.block import static org.codehaus.groovy.ast.tools.GeneralUtils.param @@ -55,6 +57,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.varX @CompileStatic trait InterfaceProjectionBuilder { + @Generated boolean isInterfaceProjection(ClassNode domainClass, MethodNode methodNode, ClassNode returnType) { if (returnType.isInterface() && !returnType.packageName?.startsWith('java.')) { List interfacePropertyNames = AstPropertyResolveUtils.getPropertyNames(returnType) @@ -74,6 +77,7 @@ trait InterfaceProjectionBuilder { return false } + @Generated MethodNode buildInterfaceImpl(ClassNode interfaceNode, ClassNode declaringClass, ClassNode targetDomainClass, MethodNode abstractMethodNode) { List getterNames = (List) AstPropertyResolveUtils.getPropertyNames(interfaceNode) .collect() { @@ -93,6 +97,8 @@ trait InterfaceProjectionBuilder { methodTarget = innerClassNode.addMethod('$setTarget', Modifier.PUBLIC, ClassHelper.VOID_TYPE, params, null, block( assignS(varX(field), varX(domainClassParam)) )) + markAsGenerated(innerClassNode, methodTarget) + AnnotationNode delegateAnn = new AnnotationNode(new ClassNode(Delegate)) delegateAnn.setMember('includes', new ListExpression(getterNames)) delegateAnn.setMember('interfaces', new ConstantExpression(false)) diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy index 35dcc4755c5..000c71283f6 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy @@ -20,6 +20,7 @@ package org.grails.datastore.gorm.services.implementers import groovy.transform.CompileStatic +import groovy.transform.Generated import org.codehaus.groovy.ast.ClassHelper import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode @@ -64,6 +65,7 @@ trait IterableInterfaceProjectionBuilder extends InterfaceProjectionBuilder { * @param returnType * @return True if it is */ + @Generated @Override boolean isInterfaceProjection(ClassNode domainClass, MethodNode methodNode, ClassNode returnType) { if (AstUtils.isSubclassOfOrImplementsInterface(returnType, Iterable.name) || returnType.isArray()) { @@ -88,6 +90,7 @@ trait IterableInterfaceProjectionBuilder extends InterfaceProjectionBuilder { return false } + @Generated Statement buildInterfaceProjection(ClassNode targetDomainClass, MethodNode abstractMethodNode, Expression queryMethodCall, Expression args, MethodNode newMethodNode) { ClassNode declaringClass = newMethodNode.declaringClass ClassNode returnType = (ClassNode) newMethodNode.getNodeMetaData(ServiceImplementer.RETURN_TYPE) ?: abstractMethodNode.returnType diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy index b92242f257a..90ce2891a51 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy @@ -20,6 +20,7 @@ package org.grails.datastore.gorm.services.implementers import groovy.transform.CompileStatic +import groovy.transform.Generated import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.expr.Expression @@ -48,6 +49,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.varX @CompileStatic trait SingleResultInterfaceProjectionBuilder extends InterfaceProjectionBuilder { + @Generated Statement buildInterfaceProjection(ClassNode targetDomainClass, MethodNode abstractMethodNode, Expression queryMethodCall, Expression args, MethodNode newMethodNode) { ClassNode declaringClass = newMethodNode.declaringClass ClassNode interfaceNode = (ClassNode) newMethodNode.getNodeMetaData(ServiceImplementer.RETURN_TYPE) ?: abstractMethodNode.returnType diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy index 2aa717d8c00..b0808d594b2 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy @@ -108,6 +108,7 @@ import static org.grails.datastore.mapping.reflect.AstUtils.error import static org.grails.datastore.mapping.reflect.AstUtils.findAllUnimplementedAbstractMethods import static org.grails.datastore.mapping.reflect.AstUtils.findAnnotation import static org.grails.datastore.mapping.reflect.AstUtils.hasAnnotation +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated import static org.grails.datastore.mapping.reflect.AstUtils.warning /** @@ -231,15 +232,17 @@ class ServiceTransformation extends AbstractTraitApplyingGormASTTransformation i BlockStatement body = block() Parameter datastoreParam = param(datastoreType, 'd') - impl.addMethod('setDatastore', Modifier.PUBLIC, ClassHelper.VOID_TYPE, params( + MethodNode datastoreSetterNode = impl.addMethod('setDatastore', Modifier.PUBLIC, ClassHelper.VOID_TYPE, params( datastoreParam ), null, body) + markAsGenerated(impl, datastoreSetterNode) body.addStatement( assignS(datastoreFieldVar, varX(datastoreParam)) ) - impl.addMethod('getDatastore', Modifier.PUBLIC, datastoreType.plainNodeReference, ZERO_PARAMETERS, null, + MethodNode datastoreGetterNode = impl.addMethod('getDatastore', Modifier.PUBLIC, datastoreType.plainNodeReference, ZERO_PARAMETERS, null, returnS(datastoreFieldVar) ) + markAsGenerated(impl, datastoreGetterNode) for (FieldNode fn in propertiesFields) { body.addStatement( assignS(varX(fn), callX(datastoreFieldVar, 'getService', classX(fn.type.plainNodeReference))) @@ -311,6 +314,7 @@ class ServiceTransformation extends AbstractTraitApplyingGormASTTransformation i } implementedAnn.setMember('by', classX(implementedClass)) methodImpl.addAnnotation(implementedAnn) + markAsGenerated(impl, methodImpl) impl.addMethod(methodImpl) break } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy index bb24eb457ac..a4fcbaa100d 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy @@ -86,6 +86,7 @@ import static org.grails.datastore.mapping.reflect.AstUtils.findAnnotation import static org.grails.datastore.mapping.reflect.AstUtils.hasOrInheritsProperty import static org.grails.datastore.mapping.reflect.AstUtils.implementsInterface import static org.grails.datastore.mapping.reflect.AstUtils.isSubclassOf +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated import static org.grails.datastore.mapping.reflect.AstUtils.nonGeneric import static org.grails.datastore.mapping.reflect.AstUtils.varThis @@ -277,12 +278,12 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma returnS(transactionManagerLookupExpr) ) - declaringClassNode.addMethod(GET_TRANSACTION_MANAGER_METHOD, + MethodNode methodNode = declaringClassNode.addMethod(GET_TRANSACTION_MANAGER_METHOD, Modifier.PUBLIC, transactionManagerClassNode, ZERO_PARAMETERS, null, ifElse) - + markAsGenerated(declaringClassNode, methodNode) } else { /// Add field: PlatformTransactionManager $transactionManager @@ -318,11 +319,12 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma getterBody.addStatement(ifElse) // Add Method: PlatformTransactionManager getTransactionManager() - declaringClassNode.addMethod(GET_TRANSACTION_MANAGER_METHOD, + MethodNode getterNode = declaringClassNode.addMethod(GET_TRANSACTION_MANAGER_METHOD, Modifier.PUBLIC, transactionManagerClassNode, ZERO_PARAMETERS, null, getterBody) + markAsGenerated(declaringClassNode, getterNode) // Prepare setter parameters Parameter p = param(transactionManagerClassNode, PROPERTY_TRANSACTION_MANAGER) @@ -331,12 +333,14 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma Statement setterBody = assignS(transactionManagerPropertyExpr, varX(p)) // Add Setter Method: void setTransactionManager(PlatformTransactionManager transactionManager) - declaringClassNode.addMethod(SET_TRANSACTION_MANAGER, + MethodNode setterNode = declaringClassNode.addMethod(SET_TRANSACTION_MANAGER, Modifier.PUBLIC, VOID_TYPE, parameters, null, setterBody) + + markAsGenerated(declaringClassNode, setterNode) } } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy index 4350b1a268a..1dcd715cadf 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy @@ -61,6 +61,7 @@ import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_PARAMETERS import static org.grails.datastore.mapping.reflect.AstUtils.addAnnotationOrGetExisting import static org.grails.datastore.mapping.reflect.AstUtils.implementsInterface import static org.grails.datastore.mapping.reflect.AstUtils.isSpockTest +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated /** * An abstract implementation for transformations that decorate a method invocation such that @@ -126,6 +127,7 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM returnS(callD(castX(make(MultipleConnectionSourceCapableDatastore), datastoreVar), METHOD_GET_DATASTORE_FOR_CONNECTION, varX(connectionNameParam))), returnS(datastoreLookupCall) )) + markAsGenerated(declaringClassNode, mn) compileMethodStatically(source, mn) } if (declaringClassNode.getMethod(METHOD_GET_TARGET_DATASTORE, ZERO_PARAMETERS) == null) { @@ -134,7 +136,7 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM returnS(datastoreVar), returnS(datastoreLookupDefaultCall)) ) - + markAsGenerated(declaringClassNode, mn) compileMethodStatically(source, mn) } } @@ -171,6 +173,7 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM Parameter[] setTargetDatastoreParams = params(datastoresParam) if (declaringClassNode.getMethod('setTargetDatastore', setTargetDatastoreParams) == null) { MethodNode setTargetDatastoreMethod = declaringClassNode.addMethod('setTargetDatastore', Modifier.PUBLIC, VOID_TYPE, setTargetDatastoreParams, null, setTargetDatastoreBody) + markAsGenerated(declaringClassNode, setTargetDatastoreMethod) // Autowire setTargetDatastore via Spring addAnnotationOrGetExisting(setTargetDatastoreMethod, Autowired) @@ -194,6 +197,7 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM returnS(callX(datastoreFieldVar, METHOD_GET_DATASTORE_FOR_CONNECTION, varX(connectionNameParam))), returnS(datastoreLookupCall) )) + markAsGenerated(declaringClassNode, mn) if (!isSpockTest) { compileMethodStatically(source, mn) } @@ -205,6 +209,7 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM returnS(datastoreLookupDefaultCall)) ) + markAsGenerated(declaringClassNode, mn) if (!isSpockTest) { compileMethodStatically(source, mn) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy index 4ec411ce4f0..16f608bbdb0 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy @@ -56,6 +56,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.closureX import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt import static org.codehaus.groovy.ast.tools.GeneralUtils.varX +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.paramsForArgs import static org.grails.datastore.mapping.reflect.AstUtils.COMPILE_STATIC_TYPE import static org.grails.datastore.mapping.reflect.AstUtils.EMPTY_CLASS_ARRAY @@ -351,6 +352,7 @@ abstract class AbstractMethodDecoratingTransformation extends AbstractGormASTTra renamedMethodNode.addAnnotations(methodNode.getAnnotations(TYPE_CHECKED_TYPE)) methodNode.setCode(null) + markAsGenerated(classNode, renamedMethodNode) classNode.addMethod(renamedMethodNode) // Use a dummy source unit to process the variable scopes to avoid the issue where this is run twice producing an error diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/ValidatedService.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/ValidatedService.groovy index f5c4d513078..16d5f29e91c 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/ValidatedService.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/ValidatedService.groovy @@ -22,7 +22,7 @@ package org.grails.datastore.gorm.validation.jakarta.services import java.lang.reflect.Method import groovy.transform.CompileStatic - +import groovy.transform.Generated import jakarta.validation.Configuration import jakarta.validation.ConstraintViolation import jakarta.validation.ConstraintViolationException @@ -49,20 +49,32 @@ trait ValidatedService extends Service { /** * The parameter name provided for this service */ - ParameterNameProvider parameterNameProvider + private ParameterNameProvider parameterNameProvider /** * The validator factory */ private ValidatorFactory validatorFactoryInstance + @Generated private Map executableValidatorMap = new LinkedHashMap().withDefault { validatorFactory.getValidator().forExecutables() } + @Generated + void setParameterNameProvider(ParameterNameProvider parameterNameProvider) { + this.parameterNameProvider = parameterNameProvider + } + + @Generated + ParameterNameProvider getParameterNameProvider() { + return this.parameterNameProvider + } + /** * @return The validator factory for this service */ + @Generated ValidatorFactory getValidatorFactory() { if (validatorFactoryInstance == null) { @@ -95,6 +107,7 @@ trait ValidatedService extends Service { * * @throws ConstraintViolationException If a validation error occurs */ + @Generated void jakartaValidate(Object instance, Method method, Object...args) throws ConstraintViolationException { ExecutableValidator validator = executableValidatorMap.get(method) Set> constraintViolations = validator.validateParameters(instance, method, args) @@ -112,6 +125,7 @@ trait ValidatedService extends Service { * * @throws ValidationException If a validation error occurs */ + @Generated void validate(Object instance, Method method, Object...args) throws ValidationException { ExecutableValidator validator = executableValidatorMap.get(method) Set> constraintViolations = validator.validateParameters(instance, method, args) @@ -127,6 +141,7 @@ trait ValidatedService extends Service { * @param e The exception * @return The errors */ + @Generated Errors asErrors(Object object, ConstraintViolationException e) { ConstraintViolationUtils.asErrors(object, e) } @@ -138,6 +153,7 @@ trait ValidatedService extends Service { * @param e The exception * @return The errors */ + @Generated Errors asErrors(Object object, Set constraintViolations) { ConstraintViolationUtils.asErrors(object, constraintViolations) } diff --git a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/implementers/MethodValidationImplementer.groovy b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/implementers/MethodValidationImplementer.groovy index 3b3e78da839..f4e145de8a5 100644 --- a/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/implementers/MethodValidationImplementer.groovy +++ b/grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/validation/jakarta/services/implementers/MethodValidationImplementer.groovy @@ -49,6 +49,7 @@ import org.grails.datastore.gorm.validation.jakarta.ConfigurableParameterNamePro import org.grails.datastore.gorm.validation.jakarta.services.ValidatedService import org.grails.datastore.mapping.reflect.ClassUtils +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated import static org.codehaus.groovy.ast.ClassHelper.CLASS_Type import static org.codehaus.groovy.ast.ClassHelper.OBJECT_TYPE import static org.codehaus.groovy.ast.ClassHelper.make @@ -196,6 +197,7 @@ class MethodValidationImplementer implements ServiceEnhancer { if (constructorNode == null) { constructorNode = new ConstructorNode(Modifier.PUBLIC, ZERO_PARAMETERS, null, new BlockStatement()) innerClassNode.addConstructor(constructorNode) + markAsGenerated(innerClassNode, constructorNode) } BlockStatement constructorBody = (BlockStatement) constructorNode.code constructorBody.addStatement( diff --git a/grails-datamapping-core/src/test/groovy/grails/gorm/services/MethodValidationTransformSpec.groovy b/grails-datamapping-core/src/test/groovy/grails/gorm/services/MethodValidationTransformSpec.groovy index fa2967c1142..c4cb871f9c8 100644 --- a/grails-datamapping-core/src/test/groovy/grails/gorm/services/MethodValidationTransformSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/grails/gorm/services/MethodValidationTransformSpec.groovy @@ -18,6 +18,8 @@ */ package grails.gorm.services +import groovy.transform.Generated + import grails.gorm.annotation.Entity import grails.validation.ValidationException import jakarta.validation.constraints.NotNull @@ -26,6 +28,7 @@ import spock.lang.Specification import jakarta.validation.ConstraintViolationException import jakarta.validation.ParameterNameProvider +import java.lang.reflect.Method /** * Created by graemerocher on 14/02/2017. @@ -66,6 +69,11 @@ class Foo { org.grails.datastore.mapping.services.Service.isAssignableFrom(impl) ValidatedService.isAssignableFrom(impl) + and: "All implemented Trait methods are marked as Generated" + ValidatedService.getMethods().each { Method traitMethod -> + assert impl.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + when:"The parameter data is obtained" ParameterNameProvider parameterNameProvider = service.classLoader.loadClass("\$MyServiceImplementation\$ParameterNameProvider").newInstance() def instance = impl.newInstance() diff --git a/grails-datamapping-core/src/test/groovy/grails/gorm/time/InstantConverterSpec.groovy b/grails-datamapping-core/src/test/groovy/grails/gorm/time/InstantConverterSpec.groovy index 9c17e207bac..3ccd2f0421a 100644 --- a/grails-datamapping-core/src/test/groovy/grails/gorm/time/InstantConverterSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/grails/gorm/time/InstantConverterSpec.groovy @@ -19,8 +19,10 @@ package grails.gorm.time import spock.lang.Shared +import groovy.transform.Generated import spock.lang.Specification +import java.lang.reflect.Method import java.time.Instant class InstantConverterSpec extends Specification implements InstantConverter { @@ -42,4 +44,10 @@ class InstantConverterSpec extends Specification implements InstantConverter { convert(100L) == instant } + void "test that all InstantConverter trait methods are marked as Generated"() { + expect: "all InstantConverter methods are marked as Generated on implementation class" + InstantConverter.getMethods().each { Method traitMethod -> + assert InstantConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } } diff --git a/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalDateConverterSpec.groovy b/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalDateConverterSpec.groovy index 85d7083f253..538fbb24890 100644 --- a/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalDateConverterSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalDateConverterSpec.groovy @@ -21,6 +21,9 @@ package grails.gorm.time import spock.lang.Shared import spock.lang.Specification +import groovy.transform.Generated + +import java.lang.reflect.Method import java.time.LocalDate class LocalDateConverterSpec extends Specification implements LocalDateConverter { @@ -42,4 +45,15 @@ class LocalDateConverterSpec extends Specification implements LocalDateConverter convert(-914803200000L) == localDate } + void "test that all LocalDateConverter/TemporalConverter trait methods are marked as Generated"() { + expect: "all LocalDateConverter methods are marked as Generated on implementation class" + LocalDateConverter.getMethods().each { Method traitMethod -> + assert LocalDateConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + + and: "all TemporalConverter methods are marked as Generated on implementation class" + TemporalConverter.getMethods().each { Method traitMethod -> + assert LocalDateConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } } diff --git a/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalDateTimeConverterSpec.groovy b/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalDateTimeConverterSpec.groovy index d40fd548141..a9521589ac2 100644 --- a/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalDateTimeConverterSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalDateTimeConverterSpec.groovy @@ -21,6 +21,9 @@ package grails.gorm.time import spock.lang.Shared import spock.lang.Specification +import groovy.transform.Generated + +import java.lang.reflect.Method import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime @@ -47,4 +50,15 @@ class LocalDateTimeConverterSpec extends Specification implements LocalDateTimeC convert(-914781296000L) == localDateTime.withNano(0) } -} \ No newline at end of file + void "test that all LocalDateTimeConverter/TemporalConverter trait methods are marked as Generated"() { + expect: "all LocalDateTimeConverter methods are marked as Generated on implementation class" + LocalDateTimeConverter.getMethods().each { Method traitMethod -> + assert LocalDateTimeConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + + and: "all TemporalConverter methods are marked as Generated on implementation class" + TemporalConverter.getMethods().each { Method traitMethod -> + assert LocalDateTimeConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } +} diff --git a/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalTimeConverterSpec.groovy b/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalTimeConverterSpec.groovy index c3f73307802..282f20801df 100644 --- a/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalTimeConverterSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/grails/gorm/time/LocalTimeConverterSpec.groovy @@ -20,7 +20,9 @@ package grails.gorm.time import spock.lang.Shared import spock.lang.Specification +import groovy.transform.Generated +import java.lang.reflect.Method import java.time.LocalTime class LocalTimeConverterSpec extends Specification implements LocalTimeConverter { @@ -42,4 +44,15 @@ class LocalTimeConverterSpec extends Specification implements LocalTimeConverter convert(21904000000003L) == localTime } -} \ No newline at end of file + void "test that all LocalTimeConverter/TemporalConverter trait methods are marked as Generated"() { + expect: "all LocalTimeConverter methods are marked as Generated on implementation class" + LocalTimeConverter.getMethods().each { Method traitMethod -> + assert LocalTimeConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + + and: "all TemporalConverter methods are marked as Generated on implementation class" + TemporalConverter.getMethods().each { Method traitMethod -> + assert LocalTimeConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } +} diff --git a/grails-datamapping-core/src/test/groovy/grails/gorm/time/OffsetDateTimeConverterSpec.groovy b/grails-datamapping-core/src/test/groovy/grails/gorm/time/OffsetDateTimeConverterSpec.groovy index f8ca63a6a53..afc47bea352 100644 --- a/grails-datamapping-core/src/test/groovy/grails/gorm/time/OffsetDateTimeConverterSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/grails/gorm/time/OffsetDateTimeConverterSpec.groovy @@ -21,6 +21,9 @@ package grails.gorm.time import spock.lang.Shared import spock.lang.Specification +import groovy.transform.Generated + +import java.lang.reflect.Method import java.time.* class OffsetDateTimeConverterSpec extends Specification implements OffsetDateTimeConverter { @@ -50,4 +53,15 @@ class OffsetDateTimeConverterSpec extends Specification implements OffsetDateTim converted == offsetDateTime.withNano(0).withOffsetSameInstant(ZoneOffset.ofHours(-8)) } -} \ No newline at end of file + void "test that all OffsetDateTimeConverter/TemporalConverter trait methods are marked as Generated"() { + expect: "all OffsetDateTimeConverter methods are marked as Generated on implementation class" + OffsetDateTimeConverter.getMethods().each { Method traitMethod -> + assert OffsetDateTimeConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + + and: "all TemporalConverter methods are marked as Generated on implementation class" + TemporalConverter.getMethods().each { Method traitMethod -> + assert OffsetDateTimeConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } +} diff --git a/grails-datamapping-core/src/test/groovy/grails/gorm/time/OffsetTimeConverterSpec.groovy b/grails-datamapping-core/src/test/groovy/grails/gorm/time/OffsetTimeConverterSpec.groovy index 0f7b9f52559..372f5dc9e3f 100644 --- a/grails-datamapping-core/src/test/groovy/grails/gorm/time/OffsetTimeConverterSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/grails/gorm/time/OffsetTimeConverterSpec.groovy @@ -21,6 +21,9 @@ package grails.gorm.time import spock.lang.Shared import spock.lang.Specification +import groovy.transform.Generated + +import java.lang.reflect.Method import java.time.LocalTime import java.time.OffsetTime import java.time.ZoneOffset @@ -50,4 +53,15 @@ class OffsetTimeConverterSpec extends Specification implements OffsetTimeConvert converted == offsetTime.withOffsetSameInstant(ZoneOffset.ofHours(-8)) } + void "test that all OffsetTimeConverter/TemporalConverter trait methods are marked as Generated"() { + expect: "all OffsetTimeConverter methods are marked as Generated on implementation class" + OffsetTimeConverter.getMethods().each { Method traitMethod -> + assert OffsetTimeConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + + and: "all TemporalConverter methods are marked as Generated on implementation class" + TemporalConverter.getMethods().each { Method traitMethod -> + assert OffsetTimeConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } } diff --git a/grails-datamapping-core/src/test/groovy/grails/gorm/time/PeriodConverterSpec.groovy b/grails-datamapping-core/src/test/groovy/grails/gorm/time/PeriodConverterSpec.groovy index f2fd49302e4..cdb1fb57761 100644 --- a/grails-datamapping-core/src/test/groovy/grails/gorm/time/PeriodConverterSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/grails/gorm/time/PeriodConverterSpec.groovy @@ -21,6 +21,9 @@ package grails.gorm.time import spock.lang.Shared import spock.lang.Specification +import groovy.transform.Generated + +import java.lang.reflect.Method import java.time.Period class PeriodConverterSpec extends Specification implements PeriodConverter { @@ -42,4 +45,10 @@ class PeriodConverterSpec extends Specification implements PeriodConverter { convert('P1941Y1M5D') == period } + void "test that all PeriodConverter trait methods are marked as Generated"() { + expect: "all PeriodConverter methods are marked as Generated on implementation class" + PeriodConverter.getMethods().each { Method traitMethod -> + assert PeriodConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } } diff --git a/grails-datamapping-core/src/test/groovy/grails/gorm/time/ZonedDateTimeConverterSpec.groovy b/grails-datamapping-core/src/test/groovy/grails/gorm/time/ZonedDateTimeConverterSpec.groovy index 9c9d5e838bd..9f19b9fc7d9 100644 --- a/grails-datamapping-core/src/test/groovy/grails/gorm/time/ZonedDateTimeConverterSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/grails/gorm/time/ZonedDateTimeConverterSpec.groovy @@ -21,6 +21,9 @@ package grails.gorm.time import spock.lang.Shared import spock.lang.Specification +import groovy.transform.Generated + +import java.lang.reflect.Method import java.time.* class ZonedDateTimeConverterSpec extends Specification implements ZonedDateTimeConverter { @@ -49,4 +52,15 @@ class ZonedDateTimeConverterSpec extends Specification implements ZonedDateTimeC converted == zonedDateTime.withNano(0).withZoneSameInstant(ZoneOffset.ofHours(-7)) || converted == zonedDateTime.withNano(0).withZoneSameInstant(ZoneOffset.ofHours(-8)) } -} \ No newline at end of file + void "test that all ZonedDateTimeConverter/TemporalConverter trait methods are marked as Generated"() { + expect: "all ZonedDateTimeConverter methods are marked as Generated on implementation class" + ZonedDateTimeConverter.getMethods().each { Method traitMethod -> + assert ZonedDateTimeConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + + and: "all TemporalConverter methods are marked as Generated on implementation class" + TemporalConverter.getMethods().each { Method traitMethod -> + assert ZonedDateTimeConverterSpec.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } +} diff --git a/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/EntityWithGenericSignaturesSpec.groovy b/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/EntityWithGenericSignaturesSpec.groovy index 2d287bffd43..5fd385470a6 100644 --- a/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/EntityWithGenericSignaturesSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/EntityWithGenericSignaturesSpec.groovy @@ -18,6 +18,7 @@ */ package org.grails.compiler.gorm +import groovy.transform.Generated import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext import org.grails.datastore.mapping.keyvalue.mapping.config.KeyValuePersistentEntity import org.grails.datastore.mapping.model.MappingContext @@ -69,5 +70,10 @@ class HotWidgetSetting extends WidgetSetting { entity.getPropertyByName("setting") entity.getPropertyByName("setting") entity.getPropertyByName("setting").type.name == 'test.WidgetSetting' + + and: "generated methods are marked as Generated" + cls.getMethod("getSetting").isAnnotationPresent(Generated) + cls.getMethod("getId").isAnnotationPresent(Generated) + cls.getMethod("getVersion").isAnnotationPresent(Generated) } } diff --git a/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/GormEntityTransformSpec.groovy b/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/GormEntityTransformSpec.groovy index 866fb45484b..2f6b97e7974 100644 --- a/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/GormEntityTransformSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/GormEntityTransformSpec.groovy @@ -17,13 +17,17 @@ * under the License. */ package org.grails.compiler.gorm + import grails.gorm.annotation.Entity +import groovy.transform.Generated import org.codehaus.groovy.ast.ClassNode import org.grails.datastore.gorm.GormEntity import org.grails.datastore.gorm.GormValidateable import org.grails.datastore.mapping.dirty.checking.DirtyCheckable import spock.lang.Specification +import java.lang.reflect.Method + /** * @author graemerocher */ @@ -63,8 +67,13 @@ class Book { bookClass.getMethod('startsWithA') bookClass.getMethod('getStartsWithB') bookClass.getMethod('startsWithB') - bookClass.getMethod('startsWithLetter', String) + and: "they are all marked as Generated" + bookClass.getMethod('getStartsWithA').isAnnotationPresent(Generated) + bookClass.getMethod('startsWithA').isAnnotationPresent(Generated) + bookClass.getMethod('getStartsWithB').isAnnotationPresent(Generated) + bookClass.getMethod('startsWithB').isAnnotationPresent(Generated) + bookClass.getMethod('startsWithLetter', String).isAnnotationPresent(Generated) } void "test parse withTransaction usage in spock"() { @@ -175,6 +184,13 @@ class Foo { Book.getAnnotation(Entity) new Author().respondsTo('addToBooks', Book) new Book().hasProperty('authorId') + + Author.getDeclaredMethod('addToBooks', Object).isAnnotationPresent(Generated) + Author.getDeclaredMethod('removeFromBooks', Object).isAnnotationPresent(Generated) + Author.getDeclaredMethod('setBooks', Set).isAnnotationPresent(Generated) + Author.getDeclaredMethod('getBooks').isAnnotationPresent(Generated) + + Book.getDeclaredMethod('getAuthorId').isAnnotationPresent(Generated) } void "Test property/method missing"() { @@ -187,14 +203,39 @@ class Foo { def var = Book.bar then: Book.getDeclaredMethod('$static_propertyMissing', String) + Book.getDeclaredMethod('$static_propertyMissing', String).isAnnotationPresent(Generated) thrown MissingPropertyException when: Book.bar = 'blah' then: Book.getDeclaredMethod('$static_propertyMissing', String, Object) + Book.getDeclaredMethod('$static_propertyMissing', String, Object).isAnnotationPresent(Generated) thrown MissingPropertyException } + void "test that all GormEntity/GormValidateable trait methods are marked as Generated"() { + expect: "all GormEntity methods are marked as Generated on implementation class" + GormEntity.getMethods().each { Method traitMethod -> + assert Book.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + + and: "all GormValidateable methods are marked as Generated on implementation class" + GormValidateable.getMethods().each { Method traitMethod -> + assert Book.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } + + void "test that all DirtyCheckingTransformer added methods are marked as Generated"() { + expect: "added getId and getVersion methods are marked" + Book.getMethod('getId').isAnnotationPresent(Generated) + Book.getMethod('getVersion').isAnnotationPresent(Generated) + + and: "getter and setter methods are marked" + Book.getMethod('getTitle').isAnnotationPresent(Generated) + Book.getMethod('setTitle', String).isAnnotationPresent(Generated) + Book.getMethod('getAuthor').isAnnotationPresent(Generated) + Book.getMethod('setAuthor', Author).isAnnotationPresent(Generated) + } } @Entity diff --git a/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/JpaEntityTransformSpec.groovy b/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/JpaEntityTransformSpec.groovy index 55f4a36059b..897bfd6345c 100644 --- a/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/JpaEntityTransformSpec.groovy +++ b/grails-datamapping-core/src/test/groovy/org/grails/compiler/gorm/JpaEntityTransformSpec.groovy @@ -18,6 +18,7 @@ */ package org.grails.compiler.gorm +import groovy.transform.Generated import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.model.config.GormProperties import org.grails.datastore.mapping.reflect.ClassPropertyFetcher @@ -63,9 +64,12 @@ class Customer { customerClass.getAnnotation(Validated) customerClass.getDeclaredMethod("getId").returnType == Long customerClass.getDeclaredMethod("getId").getAnnotation(Transient) + customerClass.getDeclaredMethod("getId").isAnnotationPresent(Generated) cpf.getPropertyDescriptor(GormProperties.IDENTITY) customerClass.getDeclaredMethod('addToRelated', Object) + customerClass.getDeclaredMethod('addToRelated', Object).isAnnotationPresent(Generated) customerClass.getDeclaredMethod('removeFromRelated', Object) + customerClass.getDeclaredMethod('removeFromRelated', Object).isAnnotationPresent(Generated) } } diff --git a/grails-datamapping-rx/src/main/groovy/grails/gorm/rx/MultiTenant.groovy b/grails-datamapping-rx/src/main/groovy/grails/gorm/rx/MultiTenant.groovy index 7bd00d69280..1bc2181bd9d 100644 --- a/grails-datamapping-rx/src/main/groovy/grails/gorm/rx/MultiTenant.groovy +++ b/grails-datamapping-rx/src/main/groovy/grails/gorm/rx/MultiTenant.groovy @@ -22,6 +22,7 @@ package grails.gorm.rx import grails.gorm.api.GormAllOperations import grails.gorm.rx.api.RxGormAllOperations import groovy.transform.CompileStatic +import groovy.transform.Generated import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.gorm.rx.api.RxGormEnhancer @@ -41,6 +42,7 @@ trait MultiTenant extends RxEntity { * @param callable The closure * @return The result of the closure */ + @Generated static T withTenant(Serializable tenantId, @DelegatesTo(RxGormAllOperations) Closure callable) { RxGormEnhancer.findStaticApi(this).withTenant tenantId, callable } @@ -51,6 +53,7 @@ trait MultiTenant extends RxEntity { * @param callable The closure * @return The result of the closure */ + @Generated static RxGormAllOperations eachTenant( @DelegatesTo(RxGormAllOperations) Closure callable) { RxGormEnhancer.findStaticApi(this, ConnectionSource.DEFAULT).eachTenant callable } @@ -61,7 +64,8 @@ trait MultiTenant extends RxEntity { * @param tenantId The tenant id * @return The operations */ + @Generated static RxGormAllOperations withTenant(Serializable tenantId) { (RxGormAllOperations)RxGormEnhancer.findStaticApi(this).withTenant(tenantId) } -} \ No newline at end of file +} diff --git a/grails-datamapping-rx/src/main/groovy/grails/gorm/rx/RxEntity.groovy b/grails-datamapping-rx/src/main/groovy/grails/gorm/rx/RxEntity.groovy index 08a447173a0..e5c572fd505 100644 --- a/grails-datamapping-rx/src/main/groovy/grails/gorm/rx/RxEntity.groovy +++ b/grails-datamapping-rx/src/main/groovy/grails/gorm/rx/RxEntity.groovy @@ -25,6 +25,7 @@ import grails.gorm.rx.api.RxGormOperations import grails.gorm.rx.api.RxGormStaticOperations import grails.gorm.rx.proxy.ObservableProxy import groovy.transform.CompileStatic +import groovy.transform.Generated import org.grails.datastore.gorm.GormValidateable import org.grails.datastore.gorm.finders.FinderMethod import org.grails.datastore.mapping.dirty.checking.DirtyCheckable @@ -53,21 +54,25 @@ import rx.Subscriber */ @CompileStatic trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckable, Serializable { + @Generated @Override boolean validate(Map arguments) { RxGormEnhancer.findValidationApi((Class)getClass()).validate((D)this, arguments) } + @Generated @Override boolean validate(List fields) { RxGormEnhancer.findValidationApi((Class)getClass()).validate((D)this, fields) } + @Generated @Override boolean validate() { RxGormEnhancer.findValidationApi((Class)getClass()).validate((D)this) } + @Generated @Override Observable insert(Map arguments = Collections.emptyMap()) { return doSave(arguments, true) @@ -77,6 +82,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable */ + @Generated Observable save() { save(Collections.emptyMap()) } @@ -86,10 +92,12 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable */ + @Generated Observable save(Map arguments) { return doSave(arguments, false) } + @Generated private Observable doSave(Map arguments, boolean isInsert) { boolean shouldValidate = arguments?.containsKey("validate") ? arguments.validate : true if (shouldValidate) { @@ -118,6 +126,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab /** * Returns the objects identifier */ + @Generated Serializable ident() { currentRxGormInstanceApi().ident this } @@ -128,6 +137,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @return An observable that returns a boolean true if successful */ @Override + @Generated Observable delete(Map arguments = Collections.emptyMap()) { currentRxGormInstanceApi().delete this, arguments } @@ -141,6 +151,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return true if the field is dirty */ + @Generated boolean isDirty(String fieldName) { hasChanged(fieldName) } @@ -151,6 +162,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param instance The instance * @return true if it is dirty */ + @Generated boolean isDirty() { hasChanged() } @@ -162,6 +174,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param arg The value * @return This domain instance */ + @Generated D removeFrom(String associationName, Object arg) { final PersistentEntity entity = getGormPersistentEntity() def prop = entity.getPropertyByName(associationName) @@ -210,6 +223,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param associationName The association name * @return The id of the association or null if it doesn't have one */ + @Generated Serializable getAssociationId(String associationName) { PersistentEntity entity = getGormPersistentEntity() def association = entity.getPropertyByName(associationName) @@ -237,6 +251,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param arg The value * @return This domain instance */ + @Generated D addTo(String associationName, Object arg) { final PersistentEntity entity = getGormPersistentEntity() final def prop = entity.getPropertyByName(associationName) @@ -316,6 +331,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab /** * @return A new instance of this RxEntity */ + @Generated static D create() { (D)this.newInstance() } @@ -326,6 +342,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param id The id of the instance * @return An observable */ + @Generated static Observable get(Serializable id, Map args = Collections.emptyMap()) { currentRxGormStaticApi().get(id, args) } @@ -336,6 +353,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param id The id of the instance * @return An observable */ + @Generated static ObservableProxy proxy(Serializable id, Map args = Collections.emptyMap()) { currentRxGormStaticApi().proxy(id, args) } @@ -347,12 +365,14 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param query The query that returns the instance * @return An observable */ + @Generated static ObservableProxy proxy(DetachedCriteria query, Map args = Collections.emptyMap()) { currentRxGormStaticApi().proxy(query, args) } /** * @return Counts the number of instances */ + @Generated static Observable count() { currentRxGormStaticApi().count() } @@ -363,6 +383,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param objects The objects to delete * @return The number of objects actually deleted */ + @Generated static Observable deleteAll(D...objects) { deleteAll( (Iterable)Arrays.asList(objects) ) } @@ -373,6 +394,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param objects The objects to delete * @return The number of objects actually deleted */ + @Generated static Observable deleteAll(Iterable objects) { currentRxGormStaticApi().deleteAll(objects) } @@ -383,6 +405,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param objects The objects to save * @return An observable that emits the identifiers of the saved objects */ + @Generated static Observable> saveAll(Iterable objects, Map arguments = Collections.emptyMap()) { currentRxGormStaticApi().saveAll(objects, arguments) } @@ -393,6 +416,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param objects The objects to save * @return An observable that emits the identifiers of the saved objects */ + @Generated static Observable> saveAll(D... objects) { saveAll((Iterable)Arrays.asList(objects)) } @@ -403,6 +427,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param objects The objects to save * @return An observable that emits the identifiers of the saved objects */ + @Generated static Observable> insertAll(Iterable objects, Map arguments = Collections.emptyMap()) { currentRxGormStaticApi().insertAll(objects, arguments) } @@ -413,6 +438,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param objects The objects to save * @return An observable that emits the identifiers of the saved objects */ + @Generated static Observable> insertAll(D... objects) { insertAll((Iterable)Arrays.asList(objects)) } @@ -423,6 +449,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param id * @return */ + @Generated static Observable exists(Serializable id) { get(id).map { D o -> o != null @@ -436,6 +463,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return A single that will emit the first object, if it exists */ + @Generated static Observable first() { currentRxGormStaticApi().first() } @@ -447,6 +475,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return A single that will emit the first object, if it exists */ + @Generated static Observable first(String propertyName) { currentRxGormStaticApi().first propertyName } @@ -460,6 +489,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return the first object in the datastore, null if none exist */ + @Generated static Observable first(Map queryParams) { currentRxGormStaticApi().first queryParams } @@ -469,6 +499,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return A single that will emit the last object, if it exists */ + @Generated static Observable last() { currentRxGormStaticApi().last() } @@ -480,6 +511,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return A single that will emit the last object, if it exists */ + @Generated static Observable last(String propertyName) { currentRxGormStaticApi().last propertyName } @@ -493,6 +525,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return A single that will emit the last object, if it exists */ + @Generated static Observable last(Map params) { currentRxGormStaticApi().last params } @@ -504,6 +537,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable with all results */ + @Generated static Observable> list() { currentRxGormStaticApi().list() } @@ -513,6 +547,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable with all results */ + @Generated static Observable> list(Map args) { currentRxGormStaticApi().list(args) } @@ -522,6 +557,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable with all results */ + @Generated static Observable findAll() { findAll(Collections. emptyMap()) } @@ -531,6 +567,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable with all results */ + @Generated static Observable findAll(Map args) { currentRxGormStaticApi().findAll(args) } @@ -541,6 +578,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param queryMap The map of conditions * @return A single result */ + @Generated static Observable findWhere(Map queryMap) { currentRxGormStaticApi().findWhere queryMap } @@ -553,6 +591,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return A single result */ + @Generated static Observable findWhere(Map queryMap, Map args) { currentRxGormStaticApi().findWhere queryMap, args } @@ -564,6 +603,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param queryMap The map of conditions * @return A single result */ + @Generated static Observable findOrCreateWhere(Map queryMap) { currentRxGormStaticApi().findOrCreateWhere queryMap } @@ -575,6 +615,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param queryMap The map of conditions * @return A single result */ + @Generated static Observable findOrSaveWhere(Map queryMap) { currentRxGormStaticApi().findOrSaveWhere queryMap } @@ -585,6 +626,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param queryMap The map of conditions * @return A list of results */ + @Generated static Observable findAllWhere(Map queryMap) { currentRxGormStaticApi().findAllWhere queryMap } @@ -597,6 +639,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return A list of results */ + @Generated static Observable findAllWhere(Map queryMap, Map args) { currentRxGormStaticApi().findAllWhere queryMap, args } @@ -607,6 +650,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param callable The callable * @return The observable */ + @Generated static Observable findAll(@DelegatesTo(DetachedCriteria) Closure callable) { currentRxGormStaticApi().findAll callable } @@ -617,6 +661,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param callable The callable * @return The observable */ + @Generated static Observable find(@DelegatesTo(DetachedCriteria) Closure callable) { currentRxGormStaticApi().find callable } @@ -625,6 +670,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param callable Callable closure containing detached criteria definition * @return The DetachedCriteria instance */ + @Generated static DetachedCriteria where(@DelegatesTo(DetachedCriteria) Closure callable) { currentRxGormStaticApi().where callable } @@ -634,6 +680,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param callable Callable closure containing detached criteria definition * @return The DetachedCriteria instance that is lazily initialized */ + @Generated static DetachedCriteria whereLazy(@DelegatesTo(DetachedCriteria) Closure callable) { currentRxGormStaticApi().whereLazy callable } @@ -643,6 +690,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param callable Callable closure containing detached criteria definition * @return The DetachedCriteria instance */ + @Generated static DetachedCriteria whereAny(@DelegatesTo(DetachedCriteria) Closure callable) { currentRxGormStaticApi().whereAny callable } @@ -650,6 +698,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab /** * Creates a criteria builder instance */ + @Generated static CriteriaBuilder createCriteria() { currentRxGormStaticApi().createCriteria() } @@ -657,6 +706,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab /** * Creates a criteria builder instance */ + @Generated static Observable withCriteria(@DelegatesTo(CriteriaBuilder) Closure callable) { currentRxGormStaticApi().withCriteria callable } @@ -664,6 +714,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab /** * Creates a criteria builder instance */ + @Generated static Observable withCriteria(Map builderArgs, @DelegatesTo(CriteriaBuilder) Closure callable) { currentRxGormStaticApi().withCriteria builderArgs, callable } @@ -674,6 +725,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param connectionName The name of the connection * @return The {@link RxGormStaticOperations} instance */ + @Generated RxGormAllOperations withConnection(String connectionName) { return (RxGormAllOperations)RxGormEnhancer.findStaticApi(getClass(), connectionName) } @@ -686,6 +738,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param callable The closure * @return */ + @Generated static T withConnection(String connectionName, @DelegatesTo(RxGormAllOperations) Closure callable ) { def staticOperations = (RxGormAllOperations) RxGormEnhancer.findStaticApi(this, connectionName) callable.setDelegate(staticOperations) @@ -700,10 +753,12 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable with the result */ + @Generated static Observable staticMethodMissing(String methodName, arg) { currentRxGormStaticApi().methodMissing(methodName, arg) } + @Generated static Object staticPropertyMissing(String property) { currentRxGormStaticApi().propertyMissing(property) } @@ -711,18 +766,22 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab /** * @return The dynamic finders for this domain class */ + @Generated static List getGormDynamicFinders() { currentRxGormStaticApi().gormDynamicFinders } + @Generated static PersistentEntity getGormPersistentEntity() { currentRxGormStaticApi().entity } + @Generated private RxGormInstanceApi currentRxGormInstanceApi() { (RxGormInstanceApi)RxGormEnhancer.findInstanceApi(this.getClass()) } + @Generated private static RxGormStaticApi currentRxGormStaticApi() { (RxGormStaticApi)RxGormEnhancer.findStaticApi(this) } diff --git a/grails-datamapping-rx/src/main/groovy/org/grails/datastore/rx/collection/RxCollection.groovy b/grails-datamapping-rx/src/main/groovy/org/grails/datastore/rx/collection/RxCollection.groovy index dc94b850fb1..4a9dbb631e4 100644 --- a/grails-datamapping-rx/src/main/groovy/org/grails/datastore/rx/collection/RxCollection.groovy +++ b/grails-datamapping-rx/src/main/groovy/org/grails/datastore/rx/collection/RxCollection.groovy @@ -20,6 +20,7 @@ package org.grails.datastore.rx.collection import grails.gorm.rx.collection.ObservableCollection import groovy.transform.CompileStatic +import groovy.transform.Generated import rx.Observable import rx.Subscriber import rx.Subscription @@ -41,15 +42,18 @@ trait RxCollection implements ObservableCollection{ /** * @return A list observable */ + @Generated Observable toListObservable() { observable.toList() } + @Generated Observable toObservable() { return this.observable } + @Generated Subscription subscribe(Subscriber subscriber) { return observable.subscribe(subscriber) } -} \ No newline at end of file +} diff --git a/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java b/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java index b3be2c5c31c..1d2083a1ac2 100644 --- a/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java +++ b/grails-datastore-async/src/main/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncTransformation.java @@ -63,6 +63,7 @@ import org.apache.grails.common.compiler.GroovyTransformOrder; import org.grails.async.transform.internal.DelegateAsyncUtils; +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated; import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse; import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec; @@ -163,6 +164,8 @@ private void applyDelegateAsyncTransform(ClassNode classNode, ClassNode targetAp MethodCallExpression delegateMethodCall = new MethodCallExpression(new VariableExpression(fieldName), candidate.getName(), arguments); promiseBody.addStatement(new ExpressionStatement(delegateMethodCall)); MethodNode newMethodNode = new MethodNode(candidate.getName(), Modifier.PUBLIC, promiseNode, parameters, null, methodBody); + + markAsGenerated(classNode, newMethodNode); classNode.addMethod(newMethodNode); } } diff --git a/grails-datastore-async/src/test/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncSpec.groovy b/grails-datastore-async/src/test/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncSpec.groovy index 5a8cd2f2249..e88b657f788 100644 --- a/grails-datastore-async/src/test/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncSpec.groovy +++ b/grails-datastore-async/src/test/groovy/org/grails/datastore/gorm/async/transform/DelegateAsyncSpec.groovy @@ -19,9 +19,12 @@ package org.grails.datastore.gorm.async.transform import grails.async.Promise +import groovy.transform.Generated import org.codehaus.groovy.ast.ClassNode import spock.lang.Specification +import java.lang.reflect.Method + /** * Created by graemerocher on 01/07/16. */ @@ -43,7 +46,12 @@ interface Foo { ''') expect:"The method is retrieved" new ClassNode(cls).methods - Promise.isAssignableFrom( cls.getMethod("withTransaction", Closure).returnType ) + + Method method = cls.getMethod("withTransaction", Closure) + Promise.isAssignableFrom( method.returnType ) + + and: 'marked as Generated' + method.isAnnotationPresent(Generated) } } diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy index 7f300fdc190..5b4fffcbcab 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckable.groovy @@ -20,7 +20,7 @@ package org.grails.datastore.mapping.dirty.checking import groovy.transform.CompileStatic - +import groovy.transform.Generated import jakarta.persistence.Transient import org.grails.datastore.mapping.proxy.EntityProxy @@ -42,6 +42,7 @@ trait DirtyCheckable { * Indicates that the instance should start tacking changes. Note that if the instance is dirty this will clear any previously tracked * changes */ + @Generated void trackChanges() { $changedProperties = new LinkedHashMap() } @@ -51,6 +52,7 @@ trait DirtyCheckable { * * @param o a given object */ + @Generated void syncChangedProperties(Object o) { if (o instanceof DirtyCheckable) { o.trackChanges($changedProperties) @@ -62,6 +64,7 @@ trait DirtyCheckable { * * @param changedProperties The changes. */ + @Generated void trackChanges(Map changedProperties) { $changedProperties = changedProperties } @@ -69,6 +72,7 @@ trait DirtyCheckable { /** * @return True if the instance has any changes */ + @Generated boolean hasChanged() { if (this instanceof EntityProxy && !((EntityProxy) this).isInitialized()) { return false @@ -82,6 +86,7 @@ trait DirtyCheckable { * @param propertyName The name of the property * @return True if the given property has any changes */ + @Generated boolean hasChanged(String propertyName) { if (this instanceof EntityProxy && !((EntityProxy) this).isInitialized()) { return false @@ -94,6 +99,7 @@ trait DirtyCheckable { /** * Marks the whole class and all its properties as dirty. When called any future call to any of the hasChanged methods will return true. */ + @Generated void markDirty() { if ($changedProperties != null && $changedProperties.isEmpty()) { $changedProperties = DirtyCheckingSupport.DIRTY_CLASS_MARKER @@ -104,6 +110,7 @@ trait DirtyCheckable { * Marks the given property name as dirty * @param propertyName The property name */ + @Generated void markDirty(String propertyName) { if ($changedProperties != null && !$changedProperties.containsKey(propertyName)) { if (DirtyCheckingSupport.DIRTY_CLASS_MARKER.is($changedProperties)) { @@ -118,6 +125,7 @@ trait DirtyCheckable { * @param propertyName The property name * @param newValue The new value */ + @Generated void markDirty(String propertyName, newValue) { if ($changedProperties != null && !$changedProperties.containsKey(propertyName)) { def oldValue = ((GroovyObject) this).getProperty(propertyName) @@ -130,6 +138,7 @@ trait DirtyCheckable { * @param propertyName The property name * @param newValue The new value */ + @Generated void markDirty(String propertyName, newValue, oldValue) { if ($changedProperties != null && !$changedProperties.containsKey(propertyName)) { boolean isNull = newValue == null @@ -147,6 +156,7 @@ trait DirtyCheckable { /** * @return A list of the dirty property names */ + @Generated List listDirtyPropertyNames() { if (this instanceof EntityProxy && !((EntityProxy) this).isInitialized()) { return Collections.emptyList() @@ -166,6 +176,7 @@ trait DirtyCheckable { * @param propertyName The property name * @return The original value */ + @Generated Object getOriginalValue(String propertyName) { if ($changedProperties != null && $changedProperties.containsKey(propertyName)) { return $changedProperties.get(propertyName) diff --git a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/Service.groovy b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/Service.groovy index 61754b85e9f..969299ec897 100644 --- a/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/Service.groovy +++ b/grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/services/Service.groovy @@ -18,6 +18,7 @@ */ package org.grails.datastore.mapping.services +import groovy.transform.Generated import org.grails.datastore.mapping.core.Datastore /** @@ -33,5 +34,15 @@ trait Service { /** * The datastore that this service is related to */ - Datastore datastore + private Datastore datastore + + @Generated + Datastore getDatastore() { + return datastore + } + + @Generated + void setDatastore(Datastore datastore) { + this.datastore = datastore + } } diff --git a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckableSpec.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckableSpec.groovy index b577e2bbb09..e1cc92e8606 100644 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckableSpec.groovy +++ b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/dirty/checking/DirtyCheckableSpec.groovy @@ -18,11 +18,13 @@ */ package org.grails.datastore.mapping.dirty.checking - import groovy.transform.Sortable +import groovy.transform.Generated import spock.lang.Issue import spock.lang.Specification +import java.lang.reflect.Method + class DirtyCheckableSpec extends Specification { @Issue('https://github.com/apache/grails-data-mapping/issues/1231') @@ -77,6 +79,13 @@ class DirtyCheckableSpec extends Specification { animal.hasChanged("barks") } + + void "test that all DirtyCheckable trait methods are marked as Generated"() { + expect: "all DirtyCheckable methods are marked as Generated on implementation class" + DirtyCheckable.getMethods().each { Method traitMethod -> + assert Animal.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } } class Animal implements DirtyCheckable { diff --git a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/services/DefaultServiceRegistrySpec.groovy b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/services/DefaultServiceRegistrySpec.groovy index 5cfcb676a53..83e9feeb2d6 100644 --- a/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/services/DefaultServiceRegistrySpec.groovy +++ b/grails-datastore-core/src/test/groovy/org/grails/datastore/mapping/services/DefaultServiceRegistrySpec.groovy @@ -18,9 +18,13 @@ */ package org.grails.datastore.mapping.services +import groovy.transform.Generated import org.grails.datastore.mapping.core.Datastore +import org.grails.datastore.mapping.dirty.checking.DirtyCheckable import spock.lang.Specification +import java.lang.reflect.Method + /** * Created by graemerocher on 11/01/2017. */ @@ -40,8 +44,15 @@ class DefaultServiceRegistrySpec extends Specification { reg.getService(TestService) != reg2.getService(TestService) reg.getService(TestService).datastore != reg2.getService(TestService).datastore } + + void "test that all Service trait methods are marked as Generated"() { + expect: "all Service methods are marked as Generated on implementation class" + Service.getMethods().each { Method traitMethod -> + assert TestService.class.getMethod(traitMethod.name, traitMethod.parameterTypes).isAnnotationPresent(Generated) + } + } } class TestService implements Service, ITestService { } -interface ITestService {} \ No newline at end of file +interface ITestService {}