Skip to content

Commit a16e3fe

Browse files
authored
Fix @GrailsCompileStatic on domain objects with inner classes (#13013)
Make sure that for every class a new scope is added to and removed from the stack. Previously a new scope was added for nearly every class but not removed. This had the effect that the wrong (empty) scope (from the inner class) was used for the entity class. This was then missing any of its `mapping`, `constraints` and `namedQueries` closures.
1 parent 0c5b853 commit a16e3fe

File tree

4 files changed

+65
-3
lines changed

4 files changed

+65
-3
lines changed

grails-core/src/main/groovy/org/grails/compiler/DomainMappingTypeCheckingExtension.groovy

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class DomainMappingTypeCheckingExtension extends TypeCheckingDSL {
4444
mappingClosureCode = mappingProperty.initialExpression.code
4545
}
4646
mappingProperty.initialExpression.code = new EmptyStatement()
47+
} else {
48+
newScope()
4749
}
4850
} else {
4951
newScope()
@@ -56,8 +58,8 @@ class DomainMappingTypeCheckingExtension extends TypeCheckingDSL {
5658
mappingProperty.initialExpression.code = currentScope.mappingClosureCode
5759
currentScope.checkingMappingClosure = true
5860
withTypeChecker { visitClosureExpression mappingProperty.initialExpression }
59-
scopeExit()
6061
}
62+
scopeExit()
6163
}
6264

6365
methodNotFound { ClassNode receiver, String name, ArgumentListExpression argList, ClassNode[] argTypes, MethodCall call ->

grails-core/src/main/groovy/org/grails/compiler/NamedQueryTypeCheckingExtension.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ class NamedQueryTypeCheckingExtension extends TypeCheckingDSL {
5252
def namedQueryProperty = classNode.getField('namedQueries')
5353
namedQueryProperty.initialExpression.code = currentScope.namedQueryClosureCode
5454
currentScope.checkingNamedQueryClosure = true
55-
scopeExit()
5655
}
56+
scopeExit()
5757
}
5858

5959
methodNotFound { ClassNode receiver, String name, ArgumentListExpression argList, ClassNode[] argTypes, MethodCall call ->

grails-core/src/main/groovy/org/grails/compiler/ValidateableTypeCheckingExtension.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ class ValidateableTypeCheckingExtension extends TypeCheckingDSL {
5252
constraintsProperty.initialExpression.code = currentScope.constraintsClosureCode
5353
currentScope.checkingConstraintsClosure = true
5454
withTypeChecker { visitClosureExpression constraintsProperty.initialExpression }
55-
scopeExit()
5655
}
56+
scopeExit()
5757
}
5858

5959
methodNotFound { ClassNode receiver, String name, ArgumentListExpression argList, ClassNode[] argTypes, MethodCall call ->
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package grails.compiler
2+
3+
import grails.compiler.GrailsCompileStatic
4+
import grails.persistence.Entity
5+
import grails.testing.gorm.DomainUnitTest
6+
import grails.validation.Validateable
7+
import spock.lang.Issue
8+
import spock.lang.Specification
9+
10+
class DomainClassWithInnerClassUsingStaticCompilationSpec extends Specification implements DomainUnitTest<SomeClass> {
11+
12+
@Issue('https://github.com/grails/grails-core/issues/12461')
13+
void 'a domain class marked with @GrailsCompileStatic containing an inner class and a "constraints" block'() {
14+
expect: 'the configuration from the "constraints" closure is available'
15+
SomeClass.constraints instanceof Closure
16+
SomeClass.constraintsClosureCalled
17+
}
18+
19+
@Issue('https://github.com/grails/grails-core/issues/12461')
20+
void 'a domain class marked with @GrailsCompileStatic containing an inner class and a "mapping" block'() {
21+
expect: 'the configuration from the "mapping" closure is available'
22+
SomeClass.mapping instanceof Closure
23+
SomeClass.mappingClosureCalled
24+
}
25+
26+
@Issue('https://github.com/grails/grails-core/issues/12461')
27+
void 'a domain class marked with @GrailsCompileStatic containing an inner class and a "namedQueries" block'() {
28+
setup:
29+
SomeClass.getNamedQuery('test')
30+
31+
expect: 'the configuration from the "namedQueries" closure is available'
32+
SomeClass.namedQueries instanceof Closure
33+
SomeClass.namedQueriesClosureCalled
34+
}
35+
}
36+
37+
@GrailsCompileStatic
38+
@Entity
39+
class SomeClass implements Validateable {
40+
41+
class SomeInnerClass {}
42+
43+
SomeInnerClass foo
44+
45+
static boolean constraintsClosureCalled = false
46+
static boolean mappingClosureCalled = false
47+
static boolean namedQueriesClosureCalled = false
48+
49+
static constraints = {
50+
constraintsClosureCalled = true
51+
}
52+
53+
static mapping = {
54+
mappingClosureCalled = true
55+
}
56+
57+
static namedQueries = {
58+
namedQueriesClosureCalled = true
59+
}
60+
}

0 commit comments

Comments
 (0)