Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Using CompilationTestHelper with a custom classloader
Using CompilationTestHelper with a custom classloader [message #1769925] Sun, 06 August 2017 02:52
Eric Salemi is currently offline Eric SalemiFriend
Messages: 35
Registered: September 2016
Location: Belgium
Member
Hi,

I have an xbase DSL and run into troubles when trying to use a custom class loader in combination with the CompilationTestHelper.

I managed to reproduce the issue on a minimalistic project:

grammar com.septentrio.infrastructure.juggle.Juggle with org.eclipse.xtext.xbase.annotations.XbaseWithAnnotations
generate juggle "http://www.septentrio.com/infrastructure/juggle/Juggle"
import "http://www.eclipse.org/xtext/common/JavaVMTypes" as types
import "http://www.eclipse.org/xtext/xbase/Xbase" as xbase

Model:
    package=Package?
    importSection=XImportSection?
    variables+=Variable*;

Package:
    'package' name=QualifiedName;

Variable:
    'variable' type=JvmTypeReference name=ID;


The test uses Janino to compile the "Doer" class on-the-fly and inject the resulting classloader into the instance of CompilationTestHelper:


class JuggleGeneratorTest {
    private Logger logger = LoggerFactory.getLogger(JuggleGeneratorTest)
    private Server server
    @Inject private Provider<CompilationTestHelper> compilationTestHelperProvider
    @Test def void testGeneratedCode() {
        val clazz = '''
        package com.example;
        public class Doer {
            public void doSomething() {}
        }
        '''.load('com.example.Doer')
        Thread.currentThread.contextClassLoader = clazz.classLoader
        '''
        package mypackage
        import com.example.Doer
        variable Doer doer
        '''
        .compile(clazz.classLoader)[
            System.out.println(generatedCode)
        ]
    }
    private def compile(CharSequence string, ClassLoader cl, IAcceptor<Result> result) {
        val cth = compilationTestHelperProvider.get
        cth.javaCompilerClassPath = cl
        cth.compile(string, result)
    }
    private def load(CharSequence string, String className) {
        val compiler = new SimpleCompiler
        compiler.cook(null, new ByteArrayInputStream(string.toString.getBytes))
        compiler.classLoader.loadClass(className)
    }
}


The inferrer is minimal:

class JuggleJvmModelInferrer extends AbstractModelInferrer {
    @Inject extension JvmTypesBuilder
    def dispatch void infer(Model model, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
        acceptor.accept(model.toClass(model.getJavaClassName)) [
            for(variable: model.variables) {
                members += variable.toField(variable.name, variable.type)
            }
        ]
    }
    def getJavaClassName(Model it) {
        getPackageName+'.'+eResource.URI.trimFileExtension.lastSegment
    }
    def getPackageName(Model it) {
        eResource.allContents.filter(Package).head.name
    }
}


The resulting java code seems to not be able to resolve the "com.example.Doer" class:

public class MyFile {
  private /* Doer */Object doer;
}
}


If the "Doer" class is defined as a regular java file, instead of being compiled on-the-fly, everything is OK.

Are there any restriction on the type of class loader I can use?
Is this the right way to use a custom class loader?
Previous Topic:Changing the Qualified name based on reference
Next Topic:Content Assistant in a Xtext custom language
Goto Forum:
  


Current Time: Sat Sep 25 15:55:44 GMT 2021

Powered by FUDForum. Page generated in 0.01389 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top