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 fb6c76a7b21..39eccc09e8e 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 @@ -24,6 +24,8 @@ import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse; import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec; +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated; + @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION) public class DelegateAsyncTransformation implements ASTTransformation { private static final ArgumentListExpression NO_ARGS = new ArgumentListExpression(); @@ -122,6 +124,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 fc3cfcb2066..9b8c08b43e0 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 @@ -1,9 +1,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. */ @@ -25,7 +28,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 b97d9c01d3a..e9cb10b7a68 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 @@ -1,6 +1,7 @@ package org.grails.datastore.mapping.dirty.checking import groovy.transform.CompileStatic +import groovy.transform.Generated import org.grails.datastore.mapping.proxy.EntityProxy import javax.persistence.Transient @@ -22,6 +23,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() } @@ -31,6 +33,7 @@ trait DirtyCheckable { * * @param o a given object */ + @Generated void syncChangedProperties(Object o) { if (o instanceof DirtyCheckable) { o.trackChanges($changedProperties) @@ -42,13 +45,15 @@ trait DirtyCheckable { * * @param changedProperties The changes. */ - void trackChanges(Map changedProperties) { + @Generated + void trackChanges(Map changedProperties) { $changedProperties = changedProperties } /** * @return True if the instance has any changes */ + @Generated boolean hasChanged() { if(this instanceof EntityProxy && !((EntityProxy)this).isInitialized()) { return false @@ -62,6 +67,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 @@ -74,6 +80,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 @@ -84,6 +91,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)) { @@ -98,6 +106,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) @@ -110,6 +119,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 @@ -127,6 +137,7 @@ trait DirtyCheckable { /** * @return A list of the dirty property names */ + @Generated List listDirtyPropertyNames() { if(this instanceof EntityProxy && !((EntityProxy)this).isInitialized()) { return Collections.emptyList() @@ -146,6 +157,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 3a45f1e384a..c90c103507e 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 @@ -15,6 +15,7 @@ */ package org.grails.datastore.mapping.services +import groovy.transform.Generated import org.grails.datastore.mapping.core.Datastore /** @@ -30,5 +31,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 + } } \ No newline at end of file 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 3c5a258d028..a1669b67163 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 @@ -1,10 +1,12 @@ 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/grails/grails-data-mapping/issues/1231') @@ -59,6 +61,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 20eb93fbf9b..7014705b2d3 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 @@ -1,8 +1,12 @@ 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. */ @@ -22,6 +26,13 @@ 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 { diff --git a/grails-datastore-gorm-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy b/grails-datastore-gorm-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy index 1f3c3936755..4c8809f3721 100644 --- a/grails-datastore-gorm-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy +++ b/grails-datastore-gorm-async/src/main/groovy/grails/gorm/async/AsyncEntity.groovy @@ -1,6 +1,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 @@ -16,6 +17,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-datastore-gorm-rx/src/main/groovy/grails/gorm/rx/MultiTenant.groovy b/grails-datastore-gorm-rx/src/main/groovy/grails/gorm/rx/MultiTenant.groovy index 839d1f6bc51..f57b54b16a3 100644 --- a/grails-datastore-gorm-rx/src/main/groovy/grails/gorm/rx/MultiTenant.groovy +++ b/grails-datastore-gorm-rx/src/main/groovy/grails/gorm/rx/MultiTenant.groovy @@ -3,6 +3,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 @@ -22,6 +23,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 } @@ -32,6 +34,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 } @@ -42,6 +45,7 @@ trait MultiTenant extends RxEntity { * @param tenantId The tenant id * @return The operations */ + @Generated static RxGormAllOperations withTenant(Serializable tenantId) { (RxGormAllOperations)RxGormEnhancer.findStaticApi(this).withTenant(tenantId) } diff --git a/grails-datastore-gorm-rx/src/main/groovy/grails/gorm/rx/RxEntity.groovy b/grails-datastore-gorm-rx/src/main/groovy/grails/gorm/rx/RxEntity.groovy index bea5148c6f0..4397430d47b 100644 --- a/grails-datastore-gorm-rx/src/main/groovy/grails/gorm/rx/RxEntity.groovy +++ b/grails-datastore-gorm-rx/src/main/groovy/grails/gorm/rx/RxEntity.groovy @@ -6,6 +6,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 @@ -34,21 +35,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) @@ -58,6 +63,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable */ + @Generated Observable save() { save(Collections.emptyMap()) } @@ -67,10 +73,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) { @@ -99,6 +107,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab /** * Returns the objects identifier */ + @Generated Serializable ident() { currentRxGormInstanceApi().ident this } @@ -109,6 +118,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 } @@ -122,6 +132,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return true if the field is dirty */ + @Generated boolean isDirty(String fieldName) { hasChanged(fieldName) } @@ -132,6 +143,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param instance The instance * @return true if it is dirty */ + @Generated boolean isDirty() { hasChanged() } @@ -143,6 +155,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) @@ -191,6 +204,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) @@ -218,6 +232,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) @@ -297,6 +312,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab /** * @return A new instance of this RxEntity */ + @Generated static D create() { (D)this.newInstance() } @@ -307,6 +323,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) } @@ -317,6 +334,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) } @@ -328,12 +346,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() } @@ -344,6 +364,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) ) } @@ -354,6 +375,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) } @@ -364,6 +386,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) } @@ -374,6 +397,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)) } @@ -384,6 +408,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) } @@ -394,6 +419,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)) } @@ -404,6 +430,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * @param id * @return */ + @Generated static Observable exists(Serializable id) { get(id).map { D o -> o != null @@ -417,6 +444,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() } @@ -428,6 +456,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 } @@ -441,6 +470,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 } @@ -450,6 +480,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() } @@ -461,6 +492,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 } @@ -474,6 +506,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 } @@ -485,6 +518,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable with all results */ + @Generated static Observable> list() { currentRxGormStaticApi().list() } @@ -494,6 +528,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable with all results */ + @Generated static Observable> list(Map args) { currentRxGormStaticApi().list(args) } @@ -503,6 +538,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable with all results */ + @Generated static Observable findAll() { findAll(Collections.emptyMap()) } @@ -512,6 +548,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return An observable with all results */ + @Generated static Observable findAll(Map args) { currentRxGormStaticApi().findAll(args) } @@ -522,6 +559,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 } @@ -534,6 +572,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return A single result */ + @Generated static Observable findWhere(Map queryMap, Map args) { currentRxGormStaticApi().findWhere queryMap, args } @@ -545,6 +584,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 } @@ -556,6 +596,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 } @@ -566,6 +607,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 } @@ -578,6 +620,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab * * @return A list of results */ + @Generated static Observable findAllWhere(Map queryMap, Map args) { currentRxGormStaticApi().findAllWhere queryMap, args } @@ -588,6 +631,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 } @@ -598,6 +642,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 } @@ -606,6 +651,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 } @@ -615,6 +661,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 } @@ -624,6 +671,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 } @@ -631,6 +679,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab /** * Creates a criteria builder instance */ + @Generated static CriteriaBuilder createCriteria() { currentRxGormStaticApi().createCriteria() } @@ -638,6 +687,7 @@ trait RxEntity implements RxGormOperations, GormValidateable, DirtyCheckab /** * Creates a criteria builder instance */ + @Generated static Observable withCriteria(@DelegatesTo(CriteriaBuilder) Closure callable) { currentRxGormStaticApi().withCriteria callable } @@ -645,6 +695,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 } @@ -655,6 +706,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) } @@ -667,6 +719,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) @@ -681,10 +734,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) } @@ -692,18 +747,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-datastore-gorm-rx/src/main/groovy/org/grails/datastore/rx/collection/RxCollection.groovy b/grails-datastore-gorm-rx/src/main/groovy/org/grails/datastore/rx/collection/RxCollection.groovy index 8e9964fc7d4..b596b136965 100644 --- a/grails-datastore-gorm-rx/src/main/groovy/org/grails/datastore/rx/collection/RxCollection.groovy +++ b/grails-datastore-gorm-rx/src/main/groovy/org/grails/datastore/rx/collection/RxCollection.groovy @@ -2,6 +2,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 @@ -23,14 +24,17 @@ 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) } diff --git a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/schemaless/ImplementsDynamicAttributes.groovy b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/schemaless/ImplementsDynamicAttributes.groovy index da90129fbae..087013fe731 100644 --- a/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/schemaless/ImplementsDynamicAttributes.groovy +++ b/grails-datastore-gorm-test/src/test/groovy/org/grails/datastore/gorm/schemaless/ImplementsDynamicAttributes.groovy @@ -1,8 +1,11 @@ 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 { @@ -23,6 +26,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 { diff --git a/grails-datastore-gorm/src/main/groovy/grails/gorm/MultiTenant.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/MultiTenant.groovy index b31275dcacf..4eb199cac89 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/MultiTenant.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/MultiTenant.groovy @@ -2,6 +2,7 @@ package grails.gorm import grails.gorm.api.GormAllOperations import groovy.transform.CompileStatic +import groovy.transform.Generated import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.mapping.core.connections.ConnectionSource @@ -21,6 +22,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 } @@ -31,6 +33,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 } @@ -41,6 +44,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-datastore-gorm/src/main/groovy/grails/gorm/time/InstantConverter.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/InstantConverter.groovy index 4970b0cbcdf..6d2c5b6633e 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/InstantConverter.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/InstantConverter.groovy @@ -1,6 +1,7 @@ package grails.gorm.time import groovy.transform.CompileStatic +import groovy.transform.Generated import java.time.Instant @@ -12,10 +13,12 @@ import java.time.Instant @CompileStatic trait InstantConverter { + @Generated Long convert(Instant value) { value.toEpochMilli() } + @Generated Instant convert(Long value) { Instant.ofEpochMilli(value) } diff --git a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy index 3383c1fb503..86675ca5b12 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/LocalDateConverter.groovy @@ -1,6 +1,7 @@ package grails.gorm.time import groovy.transform.CompileStatic +import groovy.transform.Generated import java.time.* @@ -13,12 +14,14 @@ import java.time.* 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-datastore-gorm/src/main/groovy/grails/gorm/time/LocalDateTimeConverter.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/LocalDateTimeConverter.groovy index 5f9135142e2..3a27a28d799 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/LocalDateTimeConverter.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/LocalDateTimeConverter.groovy @@ -1,6 +1,7 @@ package grails.gorm.time import groovy.transform.CompileStatic +import groovy.transform.Generated import java.time.Instant import java.time.LocalDateTime @@ -16,11 +17,13 @@ import java.time.ZoneOffset 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-datastore-gorm/src/main/groovy/grails/gorm/time/LocalTimeConverter.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/LocalTimeConverter.groovy index 468d30fcb2f..c3dfa1bdac2 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/LocalTimeConverter.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/LocalTimeConverter.groovy @@ -1,6 +1,7 @@ package grails.gorm.time import groovy.transform.CompileStatic +import groovy.transform.Generated import java.time.LocalTime @@ -13,11 +14,13 @@ import java.time.LocalTime 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-datastore-gorm/src/main/groovy/grails/gorm/time/OffsetDateTimeConverter.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/OffsetDateTimeConverter.groovy index da68eace368..ac16a182270 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/OffsetDateTimeConverter.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/OffsetDateTimeConverter.groovy @@ -1,6 +1,7 @@ package grails.gorm.time import groovy.transform.CompileStatic +import groovy.transform.Generated import java.time.Instant import java.time.OffsetDateTime @@ -14,11 +15,13 @@ import java.time.OffsetDateTime 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-datastore-gorm/src/main/groovy/grails/gorm/time/OffsetTimeConverter.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/OffsetTimeConverter.groovy index 66e1423dbad..f62a7986d2e 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/OffsetTimeConverter.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/OffsetTimeConverter.groovy @@ -1,6 +1,7 @@ package grails.gorm.time import groovy.transform.CompileStatic +import groovy.transform.Generated import java.time.LocalTime import java.time.OffsetTime @@ -15,11 +16,13 @@ import java.time.ZoneOffset 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-datastore-gorm/src/main/groovy/grails/gorm/time/PeriodConverter.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/PeriodConverter.groovy index ab636b33d7e..abe83c834bd 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/PeriodConverter.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/PeriodConverter.groovy @@ -1,6 +1,7 @@ package grails.gorm.time import groovy.transform.CompileStatic +import groovy.transform.Generated import java.time.Period @@ -12,10 +13,12 @@ import java.time.Period @CompileStatic trait PeriodConverter { + @Generated String convert(Period value) { value.toString() } + @Generated Period convert(String value) { Period.parse(value) } diff --git a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/TemporalConverter.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/TemporalConverter.groovy index a13e869a722..e499b247383 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/TemporalConverter.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/TemporalConverter.groovy @@ -1,5 +1,7 @@ package grails.gorm.time +import groovy.transform.Generated + import java.time.Instant import java.time.ZoneId import java.time.ZoneOffset @@ -10,6 +12,7 @@ trait TemporalConverter { abstract T convert(Long value) + @Generated ZoneOffset getSystemOffset() { Instant instant = Instant.now() ZoneId systemZone = ZoneId.systemDefault() diff --git a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/ZonedDateTimeConverter.groovy b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/ZonedDateTimeConverter.groovy index 4d68b49fe93..21d14c23d78 100644 --- a/grails-datastore-gorm/src/main/groovy/grails/gorm/time/ZonedDateTimeConverter.groovy +++ b/grails-datastore-gorm/src/main/groovy/grails/gorm/time/ZonedDateTimeConverter.groovy @@ -1,6 +1,7 @@ package grails.gorm.time import groovy.transform.CompileStatic +import groovy.transform.Generated import java.time.Instant import java.time.ZonedDateTime @@ -13,11 +14,13 @@ import java.time.ZonedDateTime @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-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy index 23cc81cd0d1..8eaccdfe372 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/DirtyCheckingTransformer.groovy @@ -4,7 +4,15 @@ import grails.gorm.dirty.checking.DirtyCheck import grails.gorm.dirty.checking.DirtyCheckedProperty import groovy.transform.CompilationUnitAware import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.* +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassHelper +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.FieldNode +import org.codehaus.groovy.ast.GenericsType +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter +import org.codehaus.groovy.ast.PropertyNode +import org.codehaus.groovy.ast.Variable import org.codehaus.groovy.ast.expr.ConstantExpression import org.codehaus.groovy.ast.expr.ListExpression import org.codehaus.groovy.ast.expr.MethodCallExpression @@ -24,9 +32,26 @@ import org.springframework.validation.annotation.Validated import java.lang.reflect.Modifier -import static java.lang.reflect.Modifier.* -import static org.codehaus.groovy.ast.tools.GeneralUtils.* -import static org.grails.datastore.mapping.reflect.AstUtils.* +import static java.lang.reflect.Modifier.PUBLIC +import static java.lang.reflect.Modifier.isFinal +import static java.lang.reflect.Modifier.isTransient +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +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.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.propX +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.grails.datastore.mapping.reflect.AstUtils.OBJECT_CLASS_NODE +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; /** * @@ -168,6 +193,8 @@ class DirtyCheckingTransformer implements CompilationUnitAware { null, GeneralUtils.returnS(GeneralUtils.varX(propertyField)) ) + + markAsGenerated(classNode, getIdMethod) classNode.addMethod(getIdMethod) getIdMethod.addAnnotation(GormEntityTransformation.JPA_TRANSIENT_ANNOTATION_NODE) } @@ -188,6 +215,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { null, GeneralUtils.returnS(GeneralUtils.varX(propertyField)) ) + markAsGenerated(classNode, getVersionMethod) classNode.addMethod(getVersionMethod) getVersionMethod.addAnnotation(GormEntityTransformation.JPA_TRANSIENT_ANNOTATION_NODE) } @@ -214,13 +242,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) } } @@ -261,6 +291,7 @@ class DirtyCheckingTransformer implements CompilationUnitAware { null, GeneralUtils.returnS(GeneralUtils.constX(0)) ) + markAsGenerated(classNode, getVersionMethod) classNode.addMethod(getVersionMethod) getVersionMethod.addAnnotation(GormEntityTransformation.JPA_TRANSIENT_ANNOTATION_NODE) } @@ -314,6 +345,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-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy index cc7bd4e38a1..ad86208f043 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/compiler/gorm/GormEntityTransformation.groovy @@ -71,6 +71,7 @@ import javax.persistence.Version import java.lang.annotation.Annotation import java.lang.reflect.Modifier +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated /** * An AST transformation that adds the following features:

@@ -254,7 +255,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 @@ -267,7 +270,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() @@ -278,8 +283,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.github.io/grails-doc/latest/ref/Domain%20Classes/namedQueries.html @@ -338,6 +344,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) { @@ -346,6 +354,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) } } @@ -588,6 +597,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) } } @@ -634,6 +644,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) } @@ -655,6 +666,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) } } @@ -689,6 +701,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.class), new Parameter[0], new ClassNode[0], s); + markAsGenerated(classNode, mn) classNode.addMethod(mn) } } diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy index edc0e37bb09..86bdf27c1d6 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormEntity.groovy @@ -18,6 +18,7 @@ package org.grails.datastore.gorm import grails.gorm.DetachedCriteria import groovy.transform.CompileDynamic import groovy.transform.CompileStatic +import groovy.transform.Generated import org.grails.datastore.gorm.finders.FinderMethod import org.grails.datastore.gorm.query.GormQueryOperations import org.grails.datastore.mapping.dirty.checking.DirtyCheckable @@ -55,6 +56,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 } @@ -434,6 +463,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi where(Closure callable) { currentGormStaticApi().where callable } @@ -443,6 +473,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi whereLazy(Closure callable) { currentGormStaticApi().whereLazy callable } @@ -452,6 +483,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi whereAny(Closure callable) { currentGormStaticApi().whereAny callable } @@ -462,6 +494,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(Closure callable) { currentGormStaticApi().findAll callable } @@ -473,6 +506,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(Map args, Closure callable) { currentGormStaticApi().findAll args, callable } @@ -483,6 +517,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi implements GormValidateable, DirtyCheckable, GormEntityApi saveAll(Object... objectsToSave) { currentGormStaticApi().saveAll objectsToSave } @@ -502,6 +538,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi saveAll(Iterable objectsToSave) { currentGormStaticApi().saveAll objectsToSave } @@ -510,6 +547,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 } @@ -591,6 +638,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi getAll(Serializable... ids) { currentGormStaticApi().getAll ids } @@ -598,6 +646,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi getAll() { list() } @@ -605,6 +654,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 } @@ -678,6 +736,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi list() { currentGormStaticApi().list() } @@ -687,6 +746,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(Map params = Collections.emptyMap()) { currentGormStaticApi().findAll params } @@ -697,6 +757,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(D example) { currentGormStaticApi().findAll example } @@ -709,6 +770,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(D example, Map args) { currentGormStaticApi().findAll example, args } @@ -718,6 +780,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 } @@ -837,6 +909,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAllWhere(Map queryMap, Map args) { currentGormStaticApi().findAllWhere queryMap, args } @@ -847,6 +920,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 } @@ -923,6 +1003,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withDatastoreSession(Closure callable) { currentGormStaticApi().withDatastoreSession callable } @@ -937,6 +1018,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withTransaction(Closure callable) { currentGormStaticApi().withTransaction callable } @@ -950,6 +1032,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withNewTransaction(Closure callable) { currentGormStaticApi().withNewTransaction callable } @@ -977,6 +1060,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withTransaction(Map transactionProperties, Closure callable) { currentGormStaticApi().withTransaction transactionProperties, callable } @@ -1006,6 +1090,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withNewTransaction(Map transactionProperties, Closure callable) { currentGormStaticApi().withNewTransaction transactionProperties, callable } @@ -1016,6 +1101,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withTransaction(TransactionDefinition definition, Closure callable) { currentGormStaticApi().withTransaction definition, callable } @@ -1023,6 +1109,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withNewSession(Closure callable) { currentGormStaticApi().withNewSession callable } @@ -1030,6 +1117,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi T withStatelessSession(Closure callable) { currentGormStaticApi().withStatelessSession callable } @@ -1041,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 } @@ -1283,6 +1390,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query, Map params) { currentGormStaticApi().findAll query, params } @@ -1296,6 +1404,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query, Map params, Map args) { currentGormStaticApi().findAll query, params, args } @@ -1308,6 +1417,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query, Collection params) { currentGormStaticApi().findAll query, params } @@ -1320,6 +1430,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query, Object[] params) { currentGormStaticApi().findAll query, params } @@ -1333,6 +1444,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi findAll(CharSequence query, Collection params, Map args) { currentGormStaticApi().findAll query, params, args } @@ -1345,6 +1457,7 @@ trait GormEntity implements GormValidateable, DirtyCheckable, GormEntityApi getNamedQuery(String queryName) { GormEnhancer.createNamedQuery(this, queryName) @@ -1357,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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormValidateable.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormValidateable.groovy index 4235c78e685..8f2ec3c334f 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormValidateable.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/GormValidateable.groovy @@ -16,6 +16,7 @@ package org.grails.datastore.gorm import groovy.transform.CompileStatic +import groovy.transform.Generated import org.grails.datastore.mapping.validation.ValidationErrors import org.springframework.validation.Errors import org.springframework.validation.annotation.Validated @@ -39,13 +40,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 } @@ -53,6 +55,7 @@ trait GormValidateable { /** * @return Whether this instance should skip validation */ + @Generated boolean shouldSkipValidation() { // skip validation if validation set to true or validation handled by javax.validation return this.skipValidate @@ -66,6 +69,7 @@ trait GormValidateable { * @param arguments The arguments to use * @return True if the instance is valid */ + @Generated boolean validate(Map arguments) { if(!shouldSkipValidation()) { currentGormValidationApi().validate this, arguments @@ -80,6 +84,7 @@ trait GormValidateable { * @param fields The list of fields to validate * @return True if the instance is valid */ + @Generated boolean validate(List fields) { if(!shouldSkipValidation()) { currentGormValidationApi().validate this, fields @@ -93,6 +98,7 @@ trait GormValidateable { * * @return True if the instance is valid */ + @Generated boolean validate() { currentGormValidationApi().validate this } @@ -101,6 +107,7 @@ trait GormValidateable { * Obtains the errors for an instance * @return The {@link Errors} instance */ + @Generated @Transient Errors getErrors() { if(errors == null) { @@ -109,9 +116,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) } @@ -120,6 +134,7 @@ trait GormValidateable { * Tests whether an instance has any errors * @return True if errors exist */ + @Generated Boolean hasErrors() { getErrors().hasErrors() } @@ -127,6 +142,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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy index 09d1df18c8f..ed43f627e79 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/schemaless/DynamicAttributes.groovy @@ -1,6 +1,7 @@ package org.grails.datastore.gorm.schemaless import groovy.transform.CompileStatic +import groovy.transform.Generated import org.grails.datastore.mapping.dirty.checking.DirtyCheckable /** @@ -14,6 +15,7 @@ trait DynamicAttributes { private transient Map dynamicAttributes = [:] + @Generated private void putAtDynamic(String name, value) { def oldValue = dynamicAttributes.put(name, value) if(oldValue != value) { @@ -29,6 +31,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 { @@ -47,6 +50,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) @@ -61,6 +65,7 @@ trait DynamicAttributes { * * @return The dynamic attributes */ + @Generated Map attributes() { return this.dynamicAttributes } @@ -71,6 +76,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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy index 3d6a66f14ad..f4b46c89fea 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractArrayOrIterableResultImplementer.groovy @@ -21,6 +21,8 @@ import org.codehaus.groovy.ast.GenericsType 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 * @@ -50,6 +52,7 @@ abstract class AbstractArrayOrIterableResultImplementer extends AbstractReadOper domainClassNode = domainClassForReturnType } doImplement(domainClassNode, targetClassNode, abstractMethodNode, newMethodNode, isArray) + markAsGenerated(targetClassNode, newMethodNode) } /** diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy index 14e7faa086f..6cfbd748c98 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractReadOperationImplementer.groovy @@ -28,6 +28,8 @@ import org.grails.datastore.mapping.reflect.AstUtils import java.lang.reflect.Modifier +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated + /** * Abstract implementor for read operations * @@ -60,6 +62,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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy index 0eb50b994ce..938185acd54 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/AbstractWriteOperationImplementer.groovy @@ -6,6 +6,9 @@ import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.MethodNode 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 implementer for write operations @@ -34,6 +37,9 @@ abstract class AbstractWriteOperationImplementer extends AbstractServiceImplemen } doImplement(domainClassNode, abstractMethodNode, newMethodNode, targetClassNode) + + markAsGenerated(targetClassNode, newMethodNode) + abstractMethodNode.putNodeMetaData(IMPLEMENTED, Boolean.TRUE) } diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy index d4ff18b8751..d310cd85c23 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/InterfaceProjectionBuilder.groovy @@ -1,6 +1,7 @@ package org.grails.datastore.gorm.services.implementers 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 @@ -20,6 +21,7 @@ import org.grails.datastore.mapping.reflect.NameUtils import java.lang.reflect.Modifier +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 @@ -35,6 +37,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) @@ -54,6 +57,7 @@ trait InterfaceProjectionBuilder { return false } + @Generated MethodNode buildInterfaceImpl(ClassNode interfaceNode, ClassNode declaringClass, ClassNode targetDomainClass, MethodNode abstractMethodNode) { List getterNames = (List) AstPropertyResolveUtils.getPropertyNames(interfaceNode) .collect() { @@ -73,6 +77,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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy index 333b0a8cc95..79f55f1446b 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/IterableInterfaceProjectionBuilder.groovy @@ -1,6 +1,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 @@ -34,6 +35,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()) { @@ -58,6 +60,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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy index 98665c67f35..6652b43bbac 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/implementers/SingleResultInterfaceProjectionBuilder.groovy @@ -1,6 +1,7 @@ package org.grails.datastore.gorm.services.implementers import groovy.transform.CompileStatic +import groovy.transform.Generated import org.codehaus.groovy.ast.* import org.codehaus.groovy.ast.expr.ConstantExpression import org.codehaus.groovy.ast.expr.Expression @@ -27,6 +28,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.* @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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy index 86696ceda5d..040741d070e 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/services/transform/ServiceTransformation.groovy @@ -52,13 +52,14 @@ import org.grails.datastore.gorm.services.implementers.CountImplementer import org.grails.datastore.gorm.services.implementers.CountWhereImplementer import org.grails.datastore.gorm.services.implementers.DeleteImplementer import org.grails.datastore.gorm.services.implementers.DeleteWhereImplementer +import org.grails.datastore.gorm.services.implementers.FindAllByImplementer import org.grails.datastore.gorm.services.implementers.FindAllByInterfaceProjectionImplementer +import org.grails.datastore.gorm.services.implementers.FindAllImplementer import org.grails.datastore.gorm.services.implementers.FindAllInterfaceProjectionImplementer +import org.grails.datastore.gorm.services.implementers.FindAllPropertyProjectionImplementer import org.grails.datastore.gorm.services.implementers.FindAllStringQueryImplementer import org.grails.datastore.gorm.services.implementers.FindAllWhereImplementer import org.grails.datastore.gorm.services.implementers.FindAndDeleteImplementer -import org.grails.datastore.gorm.services.implementers.FindAllImplementer -import org.grails.datastore.gorm.services.implementers.FindAllByImplementer import org.grails.datastore.gorm.services.implementers.FindOneByImplementer import org.grails.datastore.gorm.services.implementers.FindOneByInterfaceProjectionImplementer import org.grails.datastore.gorm.services.implementers.FindOneImplementer @@ -66,23 +67,43 @@ import org.grails.datastore.gorm.services.implementers.FindOneInterfaceProjectio import org.grails.datastore.gorm.services.implementers.FindOneInterfaceProjectionStringQueryImplementer import org.grails.datastore.gorm.services.implementers.FindOneInterfaceProjectionWhereImplementer import org.grails.datastore.gorm.services.implementers.FindOnePropertyProjectionImplementer -import org.grails.datastore.gorm.services.implementers.FindAllPropertyProjectionImplementer -import org.grails.datastore.gorm.services.implementers.SaveImplementer import org.grails.datastore.gorm.services.implementers.FindOneStringQueryImplementer -import org.grails.datastore.gorm.services.implementers.UpdateOneImplementer import org.grails.datastore.gorm.services.implementers.FindOneWhereImplementer +import org.grails.datastore.gorm.services.implementers.SaveImplementer +import org.grails.datastore.gorm.services.implementers.UpdateOneImplementer import org.grails.datastore.gorm.services.implementers.UpdateStringQueryImplementer import org.grails.datastore.gorm.transactions.transform.TransactionalTransform import org.grails.datastore.gorm.transform.AbstractTraitApplyingGormASTTransformation import org.grails.datastore.gorm.validation.javax.services.implementers.MethodValidationImplementer import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.core.order.OrderedComparator +import org.grails.datastore.mapping.reflect.AstUtils import java.beans.Introspector import java.lang.reflect.Modifier -import static org.codehaus.groovy.ast.tools.GeneralUtils.* -import static org.grails.datastore.mapping.reflect.AstUtils.* +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS +import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.equalsNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX +import static org.grails.datastore.mapping.reflect.AstUtils.COMPILE_STATIC_TYPE +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.copyAnnotations +import static org.grails.datastore.mapping.reflect.AstUtils.copyParameters +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 /** * Makes a class implement the {@link org.grails.datastore.mapping.services.Service} trait and generates the necessary @@ -204,15 +225,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))) @@ -283,6 +306,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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy index 26e789aa26d..8e8feb90902 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transactions/transform/TransactionalTransform.groovy @@ -20,8 +20,18 @@ import grails.gorm.transactions.ReadOnly import grails.gorm.transactions.Rollback import grails.gorm.transactions.Transactional import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.* -import org.codehaus.groovy.ast.expr.* +import org.codehaus.groovy.ast.AnnotatedNode +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.FieldNode +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter +import org.codehaus.groovy.ast.expr.ClassExpression +import org.codehaus.groovy.ast.expr.ConstantExpression +import org.codehaus.groovy.ast.expr.Expression +import org.codehaus.groovy.ast.expr.ListExpression +import org.codehaus.groovy.ast.expr.MethodCallExpression +import org.codehaus.groovy.ast.expr.VariableExpression import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.Statement import org.codehaus.groovy.control.CompilePhase @@ -44,9 +54,40 @@ import org.springframework.transaction.interceptor.RollbackRuleAttribute import java.lang.reflect.Modifier -import static org.codehaus.groovy.ast.ClassHelper.* -import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.* -import static org.grails.datastore.mapping.reflect.AstUtils.* +import static org.codehaus.groovy.ast.ClassHelper.CLASS_Type +import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE +import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE +import static org.codehaus.groovy.ast.ClassHelper.make +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +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.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX +import static org.codehaus.groovy.ast.tools.GeneralUtils.declS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifElseS +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifS +import static org.codehaus.groovy.ast.tools.GeneralUtils.notNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.propX +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.grails.datastore.gorm.transform.AstMethodDispatchUtils.callD +import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callThisD +import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_ARGUMENTS +import static org.grails.datastore.mapping.reflect.AstUtils.ZERO_PARAMETERS +import static org.grails.datastore.mapping.reflect.AstUtils.buildGetPropertyExpression +import static org.grails.datastore.mapping.reflect.AstUtils.copyParameters +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 /** *

This AST transform reads the {@link Transactional} annotation and transforms method calls by @@ -251,14 +292,14 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma notNullX(datastoreVar), returnS( propX( castX(transactionCapableDatastore, datastoreLookupExpr), PROPERTY_TRANSACTION_MANAGER) ), returnS( transactionManagerLookupExpr ) - ) + ) as Statement - 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 @@ -291,16 +332,17 @@ class TransactionalTransform extends AbstractDatastoreMethodDecoratingTransforma notNullX( transactionManagerPropertyExpr ), returnS( transactionManagerPropertyExpr ), returnS(transactionManagerLookupExpr) - ) + ) as Statement 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) @@ -309,12 +351,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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy index abd6bb4a30f..3b8fabafd6a 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transform/AbstractDatastoreMethodDecoratingTransformation.groovy @@ -16,7 +16,11 @@ package org.grails.datastore.gorm.transform import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.* +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.FieldNode +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter import org.codehaus.groovy.ast.expr.ClassExpression import org.codehaus.groovy.ast.expr.Expression import org.codehaus.groovy.ast.expr.MethodCallExpression @@ -33,10 +37,27 @@ import org.springframework.beans.factory.annotation.Autowired import java.lang.reflect.Modifier -import static org.codehaus.groovy.ast.ClassHelper.* -import static org.codehaus.groovy.ast.tools.GeneralUtils.* +import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE +import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE +import static org.codehaus.groovy.ast.ClassHelper.make +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.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX +import static org.codehaus.groovy.ast.tools.GeneralUtils.classX +import static org.codehaus.groovy.ast.tools.GeneralUtils.constX +import static org.codehaus.groovy.ast.tools.GeneralUtils.ifElseS +import static org.codehaus.groovy.ast.tools.GeneralUtils.notNullX +import static org.codehaus.groovy.ast.tools.GeneralUtils.param +import static org.codehaus.groovy.ast.tools.GeneralUtils.params +import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS +import static org.codehaus.groovy.ast.tools.GeneralUtils.varX import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callD -import static org.grails.datastore.mapping.reflect.AstUtils.* +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 @@ -103,6 +124,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) { @@ -111,7 +133,7 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM returnS(datastoreVar), returnS(datastoreLookupDefaultCall)) ) - + markAsGenerated(declaringClassNode, mn) compileMethodStatically(source, mn) } } @@ -148,6 +170,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) @@ -173,6 +196,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) } @@ -184,6 +208,7 @@ abstract class AbstractDatastoreMethodDecoratingTransformation extends AbstractM returnS(datastoreLookupDefaultCall)) ) + markAsGenerated(declaringClassNode, mn) if(!isSpockTest) { compileMethodStatically(source, mn) } diff --git a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy index ac000b8a702..8a6a961f2ef 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/transform/AbstractMethodDecoratingTransformation.groovy @@ -16,8 +16,17 @@ package org.grails.datastore.gorm.transform import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.* -import org.codehaus.groovy.ast.expr.* +import org.codehaus.groovy.ast.ASTNode +import org.codehaus.groovy.ast.AnnotatedNode +import org.codehaus.groovy.ast.AnnotationNode +import org.codehaus.groovy.ast.ClassNode +import org.codehaus.groovy.ast.MethodNode +import org.codehaus.groovy.ast.Parameter +import org.codehaus.groovy.ast.VariableScope +import org.codehaus.groovy.ast.expr.ArgumentListExpression +import org.codehaus.groovy.ast.expr.ClosureExpression +import org.codehaus.groovy.ast.expr.Expression +import org.codehaus.groovy.ast.expr.MethodCallExpression import org.codehaus.groovy.ast.stmt.BlockStatement import org.codehaus.groovy.ast.stmt.Statement import org.codehaus.groovy.ast.tools.GenericsUtils @@ -26,6 +35,7 @@ import org.codehaus.groovy.control.ErrorCollector import org.codehaus.groovy.control.SourceUnit import org.codehaus.groovy.transform.sc.StaticCompileTransformation import org.codehaus.groovy.transform.trait.Traits +import org.grails.datastore.mapping.reflect.AstUtils import org.grails.datastore.mapping.reflect.NameUtils import javax.annotation.PostConstruct @@ -33,9 +43,29 @@ import javax.annotation.PreDestroy import java.beans.Introspector import java.lang.reflect.Modifier -import static org.codehaus.groovy.ast.ClassHelper.* -import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.* -import static org.grails.datastore.mapping.reflect.AstUtils.* +import static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE +import static org.codehaus.groovy.ast.tools.GeneralUtils.args +import static org.codehaus.groovy.ast.tools.GeneralUtils.block +import static org.codehaus.groovy.ast.tools.GeneralUtils.callX +import static org.codehaus.groovy.ast.tools.GeneralUtils.castX +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 +import static org.grails.datastore.mapping.reflect.AstUtils.TYPE_CHECKED_TYPE +import static org.grails.datastore.mapping.reflect.AstUtils.addAnnotationIfNecessary +import static org.grails.datastore.mapping.reflect.AstUtils.copyParameters +import static org.grails.datastore.mapping.reflect.AstUtils.findAnnotation +import static org.grails.datastore.mapping.reflect.AstUtils.hasAnnotation +import static org.grails.datastore.mapping.reflect.AstUtils.hasJunitAnnotation +import static org.grails.datastore.mapping.reflect.AstUtils.isGetter +import static org.grails.datastore.mapping.reflect.AstUtils.isSetter +import static org.grails.datastore.mapping.reflect.AstUtils.isSpockTest +import static org.grails.datastore.mapping.reflect.AstUtils.processVariableScopes /** * An abstract implementation for transformations that decorate a method invocation such that @@ -324,6 +354,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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/javax/services/ValidatedService.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/javax/services/ValidatedService.groovy index 55eaec2aa00..ed25187396e 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/javax/services/ValidatedService.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/javax/services/ValidatedService.groovy @@ -1,6 +1,7 @@ package org.grails.datastore.gorm.validation.javax.services import groovy.transform.CompileStatic +import groovy.transform.Generated import org.grails.datastore.gorm.validation.javax.ConstraintViolationUtils import org.grails.datastore.gorm.validation.javax.JavaxValidatorRegistry import org.grails.datastore.mapping.services.Service @@ -28,20 +29,32 @@ trait ValidatedService extends Service { /** * The parameter name provided for this service */ - ParameterNameProvider parameterNameProvider + private ParameterNameProvider parameterNameProvider /** * The validator factory */ private ValidatorFactory validatorFactory + @Generated private Map executableValidatorMap = new LinkedHashMap().withDefault { getValidatorFactory().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(validatorFactory == null) { @@ -74,6 +87,7 @@ trait ValidatedService extends Service { * * @throws ConstraintViolationException If a validation error occurs */ + @Generated void javaxValidate(Object instance, Method method, Object...args) throws ConstraintViolationException { ExecutableValidator validator = executableValidatorMap.get(method) Set constraintViolations = validator.validateParameters(instance, method, args) @@ -91,6 +105,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) @@ -106,6 +121,7 @@ trait ValidatedService extends Service { * @param e The exception * @return The errors */ + @Generated Errors asErrors(Object object, ConstraintViolationException e) { ConstraintViolationUtils.asErrors(object, e) } @@ -117,6 +133,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-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/javax/services/implementers/MethodValidationImplementer.groovy b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/javax/services/implementers/MethodValidationImplementer.groovy index 462a6872e4b..096ddd017ba 100644 --- a/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/javax/services/implementers/MethodValidationImplementer.groovy +++ b/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/validation/javax/services/implementers/MethodValidationImplementer.groovy @@ -17,6 +17,7 @@ import javax.validation.ParameterNameProvider import java.lang.reflect.Method import java.lang.reflect.Modifier +import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated import static org.codehaus.groovy.ast.ClassHelper.* import static org.codehaus.groovy.ast.tools.GeneralUtils.* import static org.grails.datastore.gorm.transform.AstMethodDispatchUtils.callThisD @@ -154,6 +155,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-datastore-gorm/src/test/groovy/grails/gorm/services/MethodValidationTransformSpec.groovy b/grails-datastore-gorm/src/test/groovy/grails/gorm/services/MethodValidationTransformSpec.groovy index 7e3685fd104..aba49ad828c 100644 --- a/grails-datastore-gorm/src/test/groovy/grails/gorm/services/MethodValidationTransformSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/grails/gorm/services/MethodValidationTransformSpec.groovy @@ -1,11 +1,14 @@ package grails.gorm.services +import groovy.transform.Generated + import org.grails.datastore.gorm.validation.javax.services.ValidatedService import org.grails.datastore.mapping.validation.ValidationException import spock.lang.Specification import javax.validation.ConstraintViolationException import javax.validation.ParameterNameProvider +import java.lang.reflect.Method /** * Created by graemerocher on 14/02/2017. @@ -46,6 +49,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-datastore-gorm/src/test/groovy/grails/gorm/time/InstantConverterSpec.groovy b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/InstantConverterSpec.groovy index 79b9c355b64..6a8953bd6a6 100644 --- a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/InstantConverterSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/InstantConverterSpec.groovy @@ -1,8 +1,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 { @@ -24,4 +26,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-datastore-gorm/src/test/groovy/grails/gorm/time/LocalDateConverterSpec.groovy b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/LocalDateConverterSpec.groovy index 5c818c83081..7b04fc98cec 100644 --- a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/LocalDateConverterSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/LocalDateConverterSpec.groovy @@ -3,6 +3,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 { @@ -24,4 +27,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-datastore-gorm/src/test/groovy/grails/gorm/time/LocalDateTimeConverterSpec.groovy b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/LocalDateTimeConverterSpec.groovy index ac4a3eef0dc..7666dfff361 100644 --- a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/LocalDateTimeConverterSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/LocalDateTimeConverterSpec.groovy @@ -3,6 +3,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 @@ -29,4 +32,15 @@ class LocalDateTimeConverterSpec extends Specification implements LocalDateTimeC convert(-914781296000L) == localDateTime.withNano(0) } + 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) + } + } } \ No newline at end of file diff --git a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/LocalTimeConverterSpec.groovy b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/LocalTimeConverterSpec.groovy index e5dc7811fba..a1680bb1c93 100644 --- a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/LocalTimeConverterSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/LocalTimeConverterSpec.groovy @@ -3,6 +3,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 { @@ -24,4 +27,15 @@ class LocalTimeConverterSpec extends Specification implements LocalTimeConverter convert(21904000000003L) == localTime } + 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) + } + } } \ No newline at end of file diff --git a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/OffsetDateTimeConverterSpec.groovy b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/OffsetDateTimeConverterSpec.groovy index 79beecc8996..be80e5994e2 100644 --- a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/OffsetDateTimeConverterSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/OffsetDateTimeConverterSpec.groovy @@ -3,6 +3,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 { @@ -32,4 +35,15 @@ class OffsetDateTimeConverterSpec extends Specification implements OffsetDateTim converted == offsetDateTime.withNano(0).withOffsetSameInstant(ZoneOffset.ofHours(-8)) } + 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) + } + } } \ No newline at end of file diff --git a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/OffsetTimeConverterSpec.groovy b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/OffsetTimeConverterSpec.groovy index 274e96b70d0..e44eb1bd6d9 100644 --- a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/OffsetTimeConverterSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/OffsetTimeConverterSpec.groovy @@ -3,6 +3,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 @@ -32,4 +35,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-datastore-gorm/src/test/groovy/grails/gorm/time/PeriodConverterSpec.groovy b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/PeriodConverterSpec.groovy index c8a852aec23..3a61af2e01a 100644 --- a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/PeriodConverterSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/PeriodConverterSpec.groovy @@ -3,6 +3,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 { @@ -24,4 +27,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-datastore-gorm/src/test/groovy/grails/gorm/time/ZonedDateTimeConverterSpec.groovy b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/ZonedDateTimeConverterSpec.groovy index 1970de43791..ca18970ba3a 100644 --- a/grails-datastore-gorm/src/test/groovy/grails/gorm/time/ZonedDateTimeConverterSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/grails/gorm/time/ZonedDateTimeConverterSpec.groovy @@ -3,6 +3,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 { @@ -31,4 +34,15 @@ class ZonedDateTimeConverterSpec extends Specification implements ZonedDateTimeC converted == zonedDateTime.withNano(0).withZoneSameInstant(ZoneOffset.ofHours(-7)) || converted == zonedDateTime.withNano(0).withZoneSameInstant(ZoneOffset.ofHours(-8)) } + 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) + } + } } \ No newline at end of file diff --git a/grails-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/EntityWithGenericSignaturesSpec.groovy b/grails-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/EntityWithGenericSignaturesSpec.groovy index 11cf5700049..c872f46c3de 100644 --- a/grails-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/EntityWithGenericSignaturesSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/EntityWithGenericSignaturesSpec.groovy @@ -1,5 +1,6 @@ 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 @@ -42,7 +43,6 @@ class HotWidgetSetting extends WidgetSetting { cls.name == 'test.Widget' cls.getMethod("getSetting").returnType.name == 'test.WidgetSetting' - when:"A mapping context is created" MappingContext mappingContext = new KeyValueMappingContext("test") PersistentEntity entity = mappingContext.addPersistentEntity(cls) @@ -51,5 +51,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-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/GormEntityTransformSpec.groovy b/grails-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/GormEntityTransformSpec.groovy index a84f3531b14..c4325541c93 100644 --- a/grails-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/GormEntityTransformSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/GormEntityTransformSpec.groovy @@ -1,10 +1,15 @@ 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 + /* * Copyright 2014 original authors * @@ -62,6 +67,12 @@ class Book { 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"() { @@ -172,6 +183,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"() { @@ -184,14 +202,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-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/JpaEntityTransformSpec.groovy b/grails-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/JpaEntityTransformSpec.groovy index 3be22e090c0..2b3badd1f3e 100644 --- a/grails-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/JpaEntityTransformSpec.groovy +++ b/grails-datastore-gorm/src/test/groovy/org/grails/compiler/gorm/JpaEntityTransformSpec.groovy @@ -1,5 +1,6 @@ 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 @@ -45,9 +46,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) } }