diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformation.java b/grails-core/src/main/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformation.java index dd00f56c95e..ee8ef11809d 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformation.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/ArtefactTypeAstTransformation.java @@ -87,7 +87,7 @@ public void visit(ASTNode[] astNodes, SourceUnit sourceUnit) { protected void performTraitInjectionOnArtefactType(SourceUnit sourceUnit, ClassNode cNode, String artefactType) { if (compilationUnit != null) { - GrailsAwareTraitInjectionOperation.processTraitsForNode(sourceUnit, cNode, artefactType, compilationUnit); + TraitInjectionUtils.processTraitsForNode(sourceUnit, cNode, artefactType, compilationUnit); } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/EntityASTTransformation.java b/grails-core/src/main/groovy/org/grails/compiler/injection/EntityASTTransformation.java index 3e01b5b56a1..2b87b80ab38 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/EntityASTTransformation.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/EntityASTTransformation.java @@ -90,7 +90,7 @@ public void applyTransformation(SourceUnit sourceUnit, ClassNode classNode) { } if(compilationUnit != null) { - GrailsAwareTraitInjectionOperation.processTraitsForNode(sourceUnit, classNode, DomainClassArtefactHandler.TYPE, compilationUnit); + TraitInjectionUtils.processTraitsForNode(sourceUnit, classNode, DomainClassArtefactHandler.TYPE, compilationUnit); } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy b/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy index 79e35ee6a01..ca0586d55d7 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GlobalGrailsClassInjectorTransformation.groovy @@ -2,7 +2,6 @@ package org.grails.compiler.injection import grails.artefact.Artefact import grails.compiler.ast.ClassInjector -import grails.compiler.traits.TraitInjector import grails.core.ArtefactHandler import grails.io.IOUtils import grails.plugins.metadata.GrailsPlugin @@ -58,24 +57,10 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp List artefactHandlers = GrailsFactoriesLoader.loadFactories(ArtefactHandler) ClassInjector[] classInjectors = GrailsAwareInjectionOperation.getClassInjectors() - GrailsAwareTraitInjectionOperation grailsTraitInjector = new GrailsAwareTraitInjectionOperation(compilationUnit) - List allTraitInjectors = grailsTraitInjector.getTraitInjectors() - Map> cache = new HashMap>().withDefault { String key -> ArtefactTypeAstTransformation.findInjectors(key, classInjectors) } - Map> traitInjectorCache = new HashMap>().withDefault { String key -> - List injectorsToUse = new ArrayList(); - for(TraitInjector injector : allTraitInjectors) { - List artefactTypes = Arrays.asList(injector.getArtefactTypes()) - if(artefactTypes.contains(key)) { - injectorsToUse.add(injector) - } - } - injectorsToUse - } - Set transformedClasses = [] String pluginVersion = null ClassNode pluginClassNode = null @@ -130,11 +115,7 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp List injectors = cache[handler.type] ArtefactTypeAstTransformation.performInjection(source, classNode, injectors) - - List traitInjectorsToUse = traitInjectorCache[handler.type] - if(traitInjectorsToUse != null && traitInjectorsToUse.size() > 0) { - grailsTraitInjector.performTraitInjection(source, classNode, traitInjectorsToUse) - } + TraitInjectionUtils.processTraitsForNode(source, classNode, handler.getType(), compilationUnit) } } } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareClassLoader.java b/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareClassLoader.java index eea77d5b338..2098c2db65f 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareClassLoader.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareClassLoader.java @@ -16,15 +16,12 @@ package org.grails.compiler.injection; import grails.compiler.ast.ClassInjector; -import grails.compiler.traits.TraitInjector; import groovy.lang.GroovyClassLoader; - import org.codehaus.groovy.control.CompilationUnit; import org.codehaus.groovy.control.CompilerConfiguration; import org.codehaus.groovy.control.Phases; import java.security.CodeSource; -import java.util.Arrays; /** * A class loader that is aware of Groovy sources and injection operations. @@ -55,16 +52,11 @@ public GrailsAwareClassLoader(ClassLoader loader, CompilerConfiguration config) } private ClassInjector[] classInjectors; - private TraitInjector[] traitInjectors; public void setClassInjectors(ClassInjector[] classInjectors) { this.classInjectors = classInjectors; } - public void setTraitInjectors(TraitInjector[] traitInjectors) { - this.traitInjectors = traitInjectors; - } - /** * @see groovy.lang.GroovyClassLoader#createCompilationUnit(org.codehaus.groovy.control.CompilerConfiguration, java.security.CodeSource) */ @@ -82,12 +74,6 @@ protected CompilationUnit createCompilationUnit(CompilerConfiguration config, Co } cu.addPhaseOperation(operation, Phases.CANONICALIZATION); - - if(traitInjectors != null) { - GrailsAwareTraitInjectionOperation grailsTraitInjector = new GrailsAwareTraitInjectionOperation(cu); - grailsTraitInjector.setTraitInjectors(Arrays.asList(traitInjectors)); - cu.addPhaseOperation(grailsTraitInjector, Phases.SEMANTIC_ANALYSIS); - } return cu; } diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareTraitInjectionOperation.java b/grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionUtils.java similarity index 64% rename from grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareTraitInjectionOperation.java rename to grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionUtils.java index 55bfc02defe..7591a4ffa14 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsAwareTraitInjectionOperation.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/TraitInjectionUtils.java @@ -16,27 +16,16 @@ package org.grails.compiler.injection; import grails.compiler.traits.TraitInjector; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.GenericsType; -import org.codehaus.groovy.classgen.GeneratorContext; -import org.codehaus.groovy.control.CompilationFailedException; import org.codehaus.groovy.control.CompilationUnit; import org.codehaus.groovy.control.CompilePhase; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.transform.trait.TraitComposer; import org.grails.core.io.support.GrailsFactoriesLoader; -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; + +import java.util.*; /** * @@ -44,46 +33,11 @@ * @since 3.0 * */ -public class GrailsAwareTraitInjectionOperation extends - CompilationUnit.PrimaryClassNodeOperation { - - protected CompilationUnit unit; - protected List traitInjectors; - - public GrailsAwareTraitInjectionOperation(CompilationUnit unit) { - this.unit = unit; - traitInjectors = GrailsFactoriesLoader.loadFactories(TraitInjector.class); - } - - public void setTraitInjectors(List i) { - traitInjectors = i; - } +public class TraitInjectionUtils { - @Override - public void call(SourceUnit source, GeneratorContext context, - ClassNode classNode) throws CompilationFailedException { + private static List traitInjectors; - URL url = null; - final String filename = source.getName(); - Resource resource = new FileSystemResource(filename); - if (resource.exists()) { - try { - url = resource.getURL(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - List injectorsToUse = new ArrayList(); - for (TraitInjector injector : traitInjectors) { - if (injector.shouldInject(url)) { - injectorsToUse.add(injector); - } - } - performTraitInjection(source, classNode, injectorsToUse); - } - - public void performTraitInjection(SourceUnit source, ClassNode classNode, + private static void doInjectionInternal(CompilationUnit unit, SourceUnit source, ClassNode classNode, List injectorsToUse) { boolean traitsAdded = false; for (TraitInjector injector : injectorsToUse) { @@ -114,7 +68,10 @@ public void performTraitInjection(SourceUnit source, ClassNode classNode, } } - public List getTraitInjectors() { + private static List getTraitInjectors() { + if(traitInjectors == null) { + traitInjectors = GrailsFactoriesLoader.loadFactories(TraitInjector.class); + } return Collections.unmodifiableList(traitInjectors); } @@ -122,8 +79,7 @@ public static void processTraitsForNode(final SourceUnit sourceUnit, final ClassNode cNode, final String artefactType, final CompilationUnit compilationUnit) { - final GrailsAwareTraitInjectionOperation grailsTraitInjector = new GrailsAwareTraitInjectionOperation(compilationUnit); - final List traitInjectors = grailsTraitInjector.getTraitInjectors(); + final List traitInjectors = getTraitInjectors(); final List injectorsToUse = new ArrayList(); for (final TraitInjector injector : traitInjectors) { final List artefactTypes = Arrays.asList(injector.getArtefactTypes()); @@ -133,11 +89,11 @@ public static void processTraitsForNode(final SourceUnit sourceUnit, } try { if(injectorsToUse.size() > 0) { - grailsTraitInjector.performTraitInjection(sourceUnit, cNode, injectorsToUse); + doInjectionInternal(compilationUnit, sourceUnit, cNode, injectorsToUse); } } catch (RuntimeException e) { try { - System.err.println("Error occurred calling Trait injector ["+grailsTraitInjector.getClass().getName()+"]: " + System.err.println("Error occurred calling Trait injector ["+TraitInjectionUtils.class.getName()+"]: " + e.getMessage()); e.printStackTrace(); } catch (Throwable t) { diff --git a/grails-plugin-controllers/src/test/groovy/org/codehaus/groovy/grails/compiler/web/ControllerActionTransformerClosureActionOverridingSpec.groovy b/grails-plugin-controllers/src/test/groovy/org/codehaus/groovy/grails/compiler/web/ControllerActionTransformerClosureActionOverridingSpec.groovy index 86109aff66d..a6dc8153bc6 100644 --- a/grails-plugin-controllers/src/test/groovy/org/codehaus/groovy/grails/compiler/web/ControllerActionTransformerClosureActionOverridingSpec.groovy +++ b/grails-plugin-controllers/src/test/groovy/org/codehaus/groovy/grails/compiler/web/ControllerActionTransformerClosureActionOverridingSpec.groovy @@ -21,18 +21,11 @@ class ControllerActionTransformerClosureActionOverridingSpec extends Specificati @Override boolean shouldInject(URL url) { true } } - def controllerTraitInjector = new ControllerTraitInjector() { - @Override - boolean shouldInject(URL url) { - true - } - } - - gcl.traitInjectors = [controllerTraitInjector] as TraitInjector[] gcl.classInjectors = [transformer] as ClassInjector[] // Make sure this parent controller is compiled before the subclass. This is relevant to GRAILS-8268 gcl.parseClass(''' + @grails.artefact.Artefact('Controller') abstract class MyAbstractController { def index = { [name: 'Abstract Parent Controller'] @@ -40,6 +33,7 @@ class ControllerActionTransformerClosureActionOverridingSpec extends Specificati } ''') subclassControllerClass = gcl.parseClass(''' + @grails.artefact.Artefact('Controller') class SubClassController extends MyAbstractController { def index = { [name: 'Subclass Controller'] diff --git a/grails-plugin-controllers/src/test/groovy/org/codehaus/groovy/grails/compiler/web/ControllerActionTransformerSpec.groovy b/grails-plugin-controllers/src/test/groovy/org/codehaus/groovy/grails/compiler/web/ControllerActionTransformerSpec.groovy index fd4b2992f1a..d09bf9b30d1 100644 --- a/grails-plugin-controllers/src/test/groovy/org/codehaus/groovy/grails/compiler/web/ControllerActionTransformerSpec.groovy +++ b/grails-plugin-controllers/src/test/groovy/org/codehaus/groovy/grails/compiler/web/ControllerActionTransformerSpec.groovy @@ -29,11 +29,6 @@ class ControllerActionTransformerSpec extends Specification { boolean shouldInject(URL url) { true } } - def controllerTraitInjector = new ControllerTraitInjector() { - boolean shouldInject(URL url) { true } - } - - gcl.traitInjectors = [controllerTraitInjector] as TraitInjector[] gcl.classInjectors = [transformer] as ClassInjector[] def webRequest = GrailsWebMockUtil.bindMockWebRequest() def appCtx = new GrailsWebApplicationContext() @@ -95,6 +90,7 @@ class ControllerActionTransformerSpec extends Specification { void 'Test that a controller may have an abstract method - GRAILS-10509'() { given: def controllerClass = gcl.parseClass(''' + @grails.artefact.Artefact('Controller') abstract class SomeController { def someAction() {} abstract someAbstractMethod() @@ -116,6 +112,7 @@ class ControllerActionTransformerSpec extends Specification { void 'Test action overiding'() { given: def superControllerClass = gcl.parseClass(''' + @grails.artefact.Artefact('Controller') class SuperController { def methodAction() { [ actionInvoked: 'SuperController.methodAction' ] diff --git a/grails-plugin-rest/src/main/groovy/org/grails/plugins/web/rest/transform/ResourceTransform.groovy b/grails-plugin-rest/src/main/groovy/org/grails/plugins/web/rest/transform/ResourceTransform.groovy index d9312a022d0..ad320012db2 100644 --- a/grails-plugin-rest/src/main/groovy/org/grails/plugins/web/rest/transform/ResourceTransform.groovy +++ b/grails-plugin-rest/src/main/groovy/org/grails/plugins/web/rest/transform/ResourceTransform.groovy @@ -66,7 +66,7 @@ import org.codehaus.groovy.transform.ASTTransformation import org.codehaus.groovy.transform.GroovyASTTransformation import org.grails.compiler.injection.ArtefactTypeAstTransformation import org.grails.compiler.injection.GrailsAwareInjectionOperation -import org.grails.compiler.injection.GrailsAwareTraitInjectionOperation +import org.grails.compiler.injection.TraitInjectionUtils import org.grails.compiler.web.ControllerActionTransformer import org.grails.core.artefact.ControllerArtefactHandler import org.grails.core.io.DefaultResourceLocator @@ -154,7 +154,7 @@ class ResourceTransform implements ASTTransformation, CompilationUnitAware { ArtefactTypeAstTransformation.performInjection(source, newControllerClassNode, injectors.findAll { !(it instanceof ControllerActionTransformer) }) if(unit) { - GrailsAwareTraitInjectionOperation.processTraitsForNode(source, newControllerClassNode, 'Controller', unit) + TraitInjectionUtils.processTraitsForNode(source, newControllerClassNode, 'Controller', unit) } final responseFormatsAttr = annotationNode.getMember(ATTR_RESPONSE_FORMATS) diff --git a/grails-test-suite-uber/src/test/groovy/org/grails/compiler/injection/ParameterizedTraitSpec.groovy b/grails-test-suite-uber/src/test/groovy/org/grails/compiler/injection/ParameterizedTraitSpec.groovy deleted file mode 100644 index 355263fccd9..00000000000 --- a/grails-test-suite-uber/src/test/groovy/org/grails/compiler/injection/ParameterizedTraitSpec.groovy +++ /dev/null @@ -1,49 +0,0 @@ -package org.grails.compiler.injection - -import grails.compiler.traits.TraitInjector -import spock.lang.Specification - -class ParameterizedTraitSpec extends Specification { - - void 'test that generic parameters are populated as expected'() { - setup: - def gcl = new GrailsAwareClassLoader() - def traitInjector = new SampleTraitInjector() - gcl.traitInjectors = [traitInjector] as TraitInjector[] - - when: 'a class is loaded with a trait injector which injects a parameteried trait' - def widgetClass = gcl.parseClass ''' -class Widget {} -''' - - then: 'the trait is applied to the class' - SampleTrait.isAssignableFrom widgetClass - - and: 'parameters are replaced with the type which the trait is being applied to' - widgetClass.methods.find { method -> - method.name == 'getValue' && method.returnType == widgetClass - } - } -} - -class SampleTraitInjector implements TraitInjector { - - @Override - Class getTrait() { - SampleTrait - } - - @Override - boolean shouldInject(URL url) { - true - } - - @Override - String[] getArtefactTypes() { - [] - } -} - -trait SampleTrait { - D getValue() {} -}