Skip to content

Commit

Permalink
Merge remote-tracking branch 'jeff/traitinjection'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeff Scott Brown committed Mar 2, 2015
2 parents 076edbd + 3c1d409 commit f957673
Show file tree
Hide file tree
Showing 9 changed files with 21 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -58,24 +57,10 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp
List<ArtefactHandler> artefactHandlers = GrailsFactoriesLoader.loadFactories(ArtefactHandler)
ClassInjector[] classInjectors = GrailsAwareInjectionOperation.getClassInjectors()

GrailsAwareTraitInjectionOperation grailsTraitInjector = new GrailsAwareTraitInjectionOperation(compilationUnit)
List<TraitInjector> allTraitInjectors = grailsTraitInjector.getTraitInjectors()

Map<String, List<ClassInjector>> cache = new HashMap<String, List<ClassInjector>>().withDefault { String key ->
ArtefactTypeAstTransformation.findInjectors(key, classInjectors)
}

Map<String, List<TraitInjector>> traitInjectorCache = new HashMap<String, List<TraitInjector>>().withDefault { String key ->
List<TraitInjector> injectorsToUse = new ArrayList<TraitInjector>();
for(TraitInjector injector : allTraitInjectors) {
List<String> artefactTypes = Arrays.asList(injector.getArtefactTypes())
if(artefactTypes.contains(key)) {
injectorsToUse.add(injector)
}
}
injectorsToUse
}

Set<String> transformedClasses = []
String pluginVersion = null
ClassNode pluginClassNode = null
Expand Down Expand Up @@ -130,11 +115,7 @@ class GlobalGrailsClassInjectorTransformation implements ASTTransformation, Comp

List<ClassInjector> injectors = cache[handler.type]
ArtefactTypeAstTransformation.performInjection(source, classNode, injectors)

List<TraitInjector> traitInjectorsToUse = traitInjectorCache[handler.type]
if(traitInjectorsToUse != null && traitInjectorsToUse.size() > 0) {
grailsTraitInjector.performTraitInjection(source, classNode, traitInjectorsToUse)
}
TraitInjectionUtils.processTraitsForNode(source, classNode, handler.getType(), compilationUnit)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
*/
Expand All @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,74 +16,28 @@
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.*;

/**
*
* @author Jeff Brown
* @since 3.0
*
*/
public class GrailsAwareTraitInjectionOperation extends
CompilationUnit.PrimaryClassNodeOperation {

protected CompilationUnit unit;
protected List<TraitInjector> traitInjectors;

public GrailsAwareTraitInjectionOperation(CompilationUnit unit) {
this.unit = unit;
traitInjectors = GrailsFactoriesLoader.loadFactories(TraitInjector.class);
}

public void setTraitInjectors(List<TraitInjector> i) {
traitInjectors = i;
}
public class TraitInjectionUtils {

@Override
public void call(SourceUnit source, GeneratorContext context,
ClassNode classNode) throws CompilationFailedException {
private static List<TraitInjector> 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<TraitInjector> injectorsToUse = new ArrayList<TraitInjector>();
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<TraitInjector> injectorsToUse) {
boolean traitsAdded = false;
for (TraitInjector injector : injectorsToUse) {
Expand Down Expand Up @@ -114,16 +68,18 @@ public void performTraitInjection(SourceUnit source, ClassNode classNode,
}
}

public List<TraitInjector> getTraitInjectors() {
private static List<TraitInjector> getTraitInjectors() {
if(traitInjectors == null) {
traitInjectors = GrailsFactoriesLoader.loadFactories(TraitInjector.class);
}
return Collections.unmodifiableList(traitInjectors);
}

public static void processTraitsForNode(final SourceUnit sourceUnit,
final ClassNode cNode,
final String artefactType,
final CompilationUnit compilationUnit) {
final GrailsAwareTraitInjectionOperation grailsTraitInjector = new GrailsAwareTraitInjectionOperation(compilationUnit);
final List<TraitInjector> traitInjectors = grailsTraitInjector.getTraitInjectors();
final List<TraitInjector> traitInjectors = getTraitInjectors();
final List<TraitInjector> injectorsToUse = new ArrayList<TraitInjector>();
for (final TraitInjector injector : traitInjectors) {
final List<String> artefactTypes = Arrays.asList(injector.getArtefactTypes());
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,19 @@ 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']
}
}
''')
subclassControllerClass = gcl.parseClass('''
@grails.artefact.Artefact('Controller')
class SubClassController extends MyAbstractController {
def index = {
[name: 'Subclass Controller']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand All @@ -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' ]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down

This file was deleted.

0 comments on commit f957673

Please sign in to comment.