mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-16 16:58:56 +00:00
[generator] Created easier mechanism for importing types in Java files
Signed-off-by: Miro Spönemann <miro.spoenemann@itemis.de>
This commit is contained in:
parent
ba1ee21786
commit
36e2a8fd4c
9 changed files with 201 additions and 139 deletions
|
@ -10,6 +10,7 @@ package org.eclipse.xtext.xtext.generator
|
|||
import com.google.inject.Singleton
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtext.Grammar
|
||||
import org.eclipse.xtext.xtext.generator.model.TypeReference
|
||||
|
||||
import static org.eclipse.xtext.GrammarUtil.*
|
||||
|
||||
|
@ -19,36 +20,28 @@ class XtextGeneratorNaming {
|
|||
@Accessors(PUBLIC_SETTER)
|
||||
String eclipsePluginActivator
|
||||
|
||||
def getPackage(String qualifiedName) {
|
||||
qualifiedName.substring(0, qualifiedName.lastIndexOf('.'))
|
||||
}
|
||||
|
||||
def getSimple(String qualifiedName) {
|
||||
qualifiedName.substring(qualifiedName.lastIndexOf('.'))
|
||||
}
|
||||
|
||||
def getRuntimeBasePackage(Grammar grammar) {
|
||||
getNamespace(grammar)
|
||||
}
|
||||
|
||||
def getRuntimeModule(Grammar grammar) {
|
||||
grammar.runtimeBasePackage + '.' + getName(grammar) + 'RuntimeModule'
|
||||
new TypeReference(grammar.runtimeBasePackage, getName(grammar) + 'RuntimeModule')
|
||||
}
|
||||
|
||||
def getRuntimeGenModule(Grammar grammar) {
|
||||
grammar.runtimeBasePackage + '.Abstract' + getName(grammar) + 'RuntimeModule'
|
||||
new TypeReference(grammar.runtimeBasePackage, 'Abstract' + getName(grammar) + 'RuntimeModule')
|
||||
}
|
||||
|
||||
def getRuntimeDefaultModule(Grammar grammar) {
|
||||
'org.eclipse.xtext.service.DefaultRuntimeModule'
|
||||
new TypeReference('org.eclipse.xtext.service.DefaultRuntimeModule')
|
||||
}
|
||||
|
||||
def getRuntimeSetup(Grammar grammar) {
|
||||
grammar.runtimeBasePackage + '.' + getName(grammar) + 'StandaloneSetup'
|
||||
new TypeReference(grammar.runtimeBasePackage, getName(grammar) + 'StandaloneSetup')
|
||||
}
|
||||
|
||||
def getRuntimeGenSetup(Grammar grammar) {
|
||||
grammar.runtimeBasePackage + '.' + getName(grammar) + 'StandaloneSetupGenerated'
|
||||
new TypeReference(grammar.runtimeBasePackage, getName(grammar) + 'StandaloneSetupGenerated')
|
||||
}
|
||||
|
||||
def getEclipsePluginBasePackage(Grammar grammar) {
|
||||
|
@ -56,26 +49,26 @@ class XtextGeneratorNaming {
|
|||
}
|
||||
|
||||
def getEclipsePluginModule(Grammar grammar) {
|
||||
grammar.eclipsePluginBasePackage + '.' + getName(grammar) + 'UiModule'
|
||||
new TypeReference(grammar.eclipsePluginBasePackage, getName(grammar) + 'UiModule')
|
||||
}
|
||||
|
||||
def getEclipsePluginGenModule(Grammar grammar) {
|
||||
grammar.eclipsePluginBasePackage + '.' + 'Abstract' + getName(grammar) + 'UiModule'
|
||||
new TypeReference(grammar.eclipsePluginBasePackage, 'Abstract' + getName(grammar) + 'UiModule')
|
||||
}
|
||||
|
||||
def getEclipsePluginDefaultModule(Grammar grammar) {
|
||||
'org.eclipse.xtext.ui.DefaultUiModule'
|
||||
new TypeReference('org.eclipse.xtext.ui.DefaultUiModule')
|
||||
}
|
||||
|
||||
def getEclipsePluginExecutableExtensionFactory(Grammar grammar) {
|
||||
grammar.eclipsePluginBasePackage + '.' + getName(grammar) + 'ExecutableExtensionFactory'
|
||||
new TypeReference(grammar.eclipsePluginBasePackage, getName(grammar) + 'ExecutableExtensionFactory')
|
||||
}
|
||||
|
||||
def getEclipsePluginActivator(Grammar grammar) {
|
||||
if (eclipsePluginActivator === null) {
|
||||
eclipsePluginActivator = grammar.eclipsePluginBasePackage + '.internal.' + getName(grammar) + 'Activator'
|
||||
}
|
||||
return eclipsePluginActivator
|
||||
return new TypeReference(eclipsePluginActivator)
|
||||
}
|
||||
|
||||
}
|
|
@ -7,8 +7,19 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator
|
||||
|
||||
import com.google.inject.Binder
|
||||
import com.google.inject.Guice
|
||||
import com.google.inject.Inject
|
||||
import com.google.inject.Injector
|
||||
import com.google.inject.Provider
|
||||
import com.google.inject.Singleton
|
||||
import com.google.inject.name.Names
|
||||
import org.eclipse.xtext.Constants
|
||||
import org.eclipse.xtext.ISetup
|
||||
import org.eclipse.xtext.ISetupExtension
|
||||
import org.eclipse.xtext.XtextPackage
|
||||
import org.eclipse.xtext.resource.impl.BinaryGrammarResourceFactoryImpl
|
||||
import org.eclipse.xtext.service.SingletonBinding
|
||||
import org.eclipse.xtext.xtext.generator.model.CodeConfig
|
||||
import org.eclipse.xtext.xtext.generator.model.GuiceModuleAccess
|
||||
import org.eclipse.xtext.xtext.generator.model.JavaFileAccess
|
||||
|
@ -23,7 +34,7 @@ class XtextGeneratorTemplates {
|
|||
|
||||
def TextFileAccess startPluginXml(TextFileAccess file) {
|
||||
file.path = 'plugin.xml'
|
||||
file.codeFragments += '''
|
||||
file.content = '''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.0"?>
|
||||
|
||||
|
@ -33,7 +44,7 @@ class XtextGeneratorTemplates {
|
|||
}
|
||||
|
||||
def TextFileAccess finishPluginXml(TextFileAccess file) {
|
||||
file.codeFragments += '''
|
||||
file.content = '''
|
||||
</plugin>
|
||||
'''
|
||||
return file
|
||||
|
@ -42,18 +53,17 @@ class XtextGeneratorTemplates {
|
|||
def JavaFileAccess getRuntimeSetup(LanguageConfig2 langConfig) {
|
||||
val g = langConfig.grammar
|
||||
val javaFile = new JavaFileAccess(g.runtimeSetup, codeConfig)
|
||||
val runtimeSetupImpl = javaFile.imported(g.runtimeGenSetup)
|
||||
|
||||
javaFile.typeComment = '''
|
||||
/**
|
||||
* Initialization support for running Xtext languages without Equinox extension registry.
|
||||
*/
|
||||
'''
|
||||
javaFile.codeFragments += '''
|
||||
public class «g.runtimeSetup.simple» extends «runtimeSetupImpl»{
|
||||
javaFile.javaContent = '''
|
||||
public class «g.runtimeSetup.simpleName» extends «g.runtimeGenSetup»{
|
||||
|
||||
public static void doSetup() {
|
||||
new «g.runtimeSetup.simple»().createInjectorAndDoEMFRegistration();
|
||||
new «g.runtimeSetup.simpleName»().createInjectorAndDoEMFRegistration();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -64,62 +74,52 @@ class XtextGeneratorTemplates {
|
|||
def JavaFileAccess startRuntimeGenSetup(LanguageConfig2 langConfig) {
|
||||
val g = langConfig.grammar
|
||||
val javaFile = new JavaFileAccess(g.runtimeGenSetup, codeConfig)
|
||||
javaFile.imported('org.eclipse.emf.ecore.EPackage')
|
||||
javaFile.imported('org.eclipse.emf.ecore.resource.Resource')
|
||||
javaFile.imported('org.eclipse.xtext.ISetup')
|
||||
javaFile.imported('org.eclipse.xtext.ISetupExtension')
|
||||
javaFile.imported('com.google.inject.Guice')
|
||||
javaFile.imported('com.google.inject.Injector')
|
||||
javaFile.imported('java.util.List')
|
||||
javaFile.imported('java.util.Arrays')
|
||||
val runtimeGuiceModule = javaFile.imported(g.runtimeModule)
|
||||
val usedRuntimeSetups = g.usedGrammars.map[javaFile.imported(it.runtimeSetup)]
|
||||
|
||||
javaFile.codeFragments += '''
|
||||
public class «g.runtimeGenSetup.simple» implements ISetup, ISetupExtension {
|
||||
javaFile.javaContent = '''
|
||||
public class «g.runtimeGenSetup.simpleName» implements «ISetup», «ISetupExtension» {
|
||||
|
||||
@Override
|
||||
public List<String> getFileExtensions() {
|
||||
return Arrays.asList(«FOR fileExtension : langConfig.fileExtensions SEPARATOR ','»"«fileExtension»"«ENDFOR»);
|
||||
public «'java.util.List'»<String> getFileExtensions() {
|
||||
return «'java.util.Arrays'».asList(«FOR fileExtension : langConfig.fileExtensions SEPARATOR ','»"«fileExtension»"«ENDFOR»);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Injector createInjectorAndDoEMFRegistration() {
|
||||
«FOR usedSetup : usedRuntimeSetups»
|
||||
«usedSetup».doSetup();
|
||||
public «Injector» createInjectorAndDoEMFRegistration() {
|
||||
«FOR usedGrammar : g.usedGrammars»
|
||||
«usedGrammar.runtimeSetup».doSetup();
|
||||
«ENDFOR»
|
||||
«IF g.usedGrammars.isEmpty»
|
||||
// register default ePackages
|
||||
if (!Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().containsKey("ecore"))
|
||||
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(
|
||||
"ecore", new org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl());
|
||||
if (!Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().containsKey("xmi"))
|
||||
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(
|
||||
"xmi", new org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl());
|
||||
if (!Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().containsKey("xtextbin"))
|
||||
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(
|
||||
"xtextbin", new org.eclipse.xtext.resource.impl.BinaryGrammarResourceFactoryImpl());
|
||||
if (!EPackage.Registry.INSTANCE.containsKey(org.eclipse.xtext.XtextPackage.eNS_URI))
|
||||
EPackage.Registry.INSTANCE.put(org.eclipse.xtext.XtextPackage.eNS_URI, org.eclipse.xtext.XtextPackage.eINSTANCE);
|
||||
if (!«'org.eclipse.emf.ecore.resource.Resource'».Factory.Registry.INSTANCE.getExtensionToFactoryMap().containsKey("ecore"))
|
||||
«'org.eclipse.emf.ecore.resource.Resource'».Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(
|
||||
"ecore", new «'org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl'»());
|
||||
if (!«'org.eclipse.emf.ecore.resource.Resource'».Factory.Registry.INSTANCE.getExtensionToFactoryMap().containsKey("xmi"))
|
||||
«'org.eclipse.emf.ecore.resource.Resource'».Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(
|
||||
"xmi", new «'org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl'»());
|
||||
if (!«'org.eclipse.emf.ecore.resource.Resource'».Factory.Registry.INSTANCE.getExtensionToFactoryMap().containsKey("xtextbin"))
|
||||
«'org.eclipse.emf.ecore.resource.Resource'».Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(
|
||||
"xtextbin", new «BinaryGrammarResourceFactoryImpl»());
|
||||
if (!«'org.eclipse.emf.ecore.EPackage'».Registry.INSTANCE.containsKey(«XtextPackage».eNS_URI))
|
||||
«'org.eclipse.emf.ecore.EPackage'».Registry.INSTANCE.put(«XtextPackage».eNS_URI, «XtextPackage».eINSTANCE);
|
||||
«ENDIF»
|
||||
|
||||
Injector injector = createInjector();
|
||||
«Injector» injector = createInjector();
|
||||
register(injector);
|
||||
return injector;
|
||||
}
|
||||
|
||||
public Injector createInjector() {
|
||||
return Guice.createInjector(new «runtimeGuiceModule»());
|
||||
public «Injector» createInjector() {
|
||||
return «Guice».createInjector(new «g.runtimeModule»());
|
||||
}
|
||||
|
||||
public void register(Injector injector) {
|
||||
public void register(«Injector» injector) {
|
||||
'''
|
||||
javaFile.markedAsGenerated = true
|
||||
return javaFile
|
||||
}
|
||||
|
||||
def JavaFileAccess finishRuntimeGenSetup(JavaFileAccess javaFile) {
|
||||
javaFile.codeFragments += '''
|
||||
javaFile.javaContent = '''
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
@ -147,14 +147,13 @@ class XtextGeneratorTemplates {
|
|||
def JavaFileAccess getRuntimeModule(LanguageConfig2 langConfig) {
|
||||
val g = langConfig.grammar
|
||||
val javaFile = new JavaFileAccess(g.runtimeModule, codeConfig)
|
||||
val runtimeGeneratedModule = javaFile.imported(g.runtimeGenModule)
|
||||
javaFile.typeComment = '''
|
||||
/**
|
||||
* Use this class to register components to be used at runtime / without the Equinox extension registry.
|
||||
*/
|
||||
'''
|
||||
javaFile.codeFragments += '''
|
||||
public class «g.runtimeModule.simple» extends «runtimeGeneratedModule» {
|
||||
javaFile.javaContent = '''
|
||||
public class «g.runtimeModule.simpleName» extends «g.runtimeGenModule» {
|
||||
|
||||
}
|
||||
'''
|
||||
|
@ -164,35 +163,30 @@ class XtextGeneratorTemplates {
|
|||
def GuiceModuleAccess startRuntimeGenModule(LanguageConfig2 langConfig) {
|
||||
val g = langConfig.grammar
|
||||
val module = new GuiceModuleAccess(g.runtimeGenModule, codeConfig)
|
||||
module.imported('java.util.Properties')
|
||||
module.imported('org.eclipse.xtext.Constants')
|
||||
module.imported('com.google.inject.Binder')
|
||||
module.imported('com.google.inject.name.Names')
|
||||
val runtimeDefaultModule = module.imported(g.runtimeDefaultModule)
|
||||
|
||||
module.typeComment = '''
|
||||
/**
|
||||
* Manual modifications go to {@link «g.runtimeModule.simple»}.
|
||||
* Manual modifications go to {@link «g.runtimeModule.simpleName»}.
|
||||
*/
|
||||
'''
|
||||
module.codeFragments += '''
|
||||
public abstract class «g.runtimeGenModule.simple» extends «runtimeDefaultModule» {
|
||||
module.javaContent = '''
|
||||
public abstract class «g.runtimeGenModule.simpleName» extends «g.runtimeDefaultModule» {
|
||||
|
||||
protected Properties properties = null;
|
||||
protected «'java.util.Properties'» properties = null;
|
||||
|
||||
@Override
|
||||
public void configure(Binder binder) {
|
||||
public void configure(«Binder» binder) {
|
||||
properties = tryBindProperties(binder, "«g.name.replaceAll("\\.","/")».properties");
|
||||
super.configure(binder);
|
||||
}
|
||||
|
||||
public void configureLanguageName(Binder binder) {
|
||||
binder.bind(String.class).annotatedWith(Names.named(Constants.LANGUAGE_NAME)).toInstance("«g.name»");
|
||||
public void configureLanguageName(«Binder» binder) {
|
||||
binder.bind(String.class).annotatedWith(«Names».named(«Constants».LANGUAGE_NAME)).toInstance("«g.name»");
|
||||
}
|
||||
|
||||
public void configureFileExtensions(Binder binder) {
|
||||
public void configureFileExtensions(«Binder» binder) {
|
||||
if (properties == null || properties.getProperty(Constants.FILE_EXTENSIONS) == null)
|
||||
binder.bind(String.class).annotatedWith(Names.named(Constants.FILE_EXTENSIONS)).toInstance("«langConfig.fileExtensions.join(',')»");
|
||||
binder.bind(String.class).annotatedWith(«Names».named(«Constants».FILE_EXTENSIONS)).toInstance("«langConfig.fileExtensions.join(',')»");
|
||||
}
|
||||
'''
|
||||
module.markedAsGenerated = true
|
||||
|
@ -202,16 +196,14 @@ class XtextGeneratorTemplates {
|
|||
def JavaFileAccess getEclipsePluginModule(LanguageConfig2 langConfig) {
|
||||
val g = langConfig.grammar
|
||||
val javaFile = new JavaFileAccess(g.eclipsePluginModule, codeConfig)
|
||||
val eclipsePluginGenGuiceModule = javaFile.imported(g.eclipsePluginGenModule)
|
||||
javaFile.imported('org.eclipse.ui.plugin.AbstractUIPlugin')
|
||||
javaFile.typeComment = '''
|
||||
/**
|
||||
* Use this class to register components to be used within the Eclipse IDE.
|
||||
*/
|
||||
'''
|
||||
javaFile.codeFragments += '''
|
||||
public class «g.eclipsePluginModule.simple» extends «eclipsePluginGenGuiceModule» {
|
||||
public «g.eclipsePluginModule.simple»(AbstractUIPlugin plugin) {
|
||||
javaFile.javaContent = '''
|
||||
public class «g.eclipsePluginModule.simpleName» extends «g.eclipsePluginGenModule» {
|
||||
public «g.eclipsePluginModule.simpleName»(«'org.eclipse.ui.plugin.AbstractUIPlugin'» plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
}
|
||||
|
@ -222,18 +214,16 @@ class XtextGeneratorTemplates {
|
|||
def GuiceModuleAccess startEclipsePluginGenModule(LanguageConfig2 langConfig) {
|
||||
val g = langConfig.grammar
|
||||
val module = new GuiceModuleAccess(g.eclipsePluginGenModule, codeConfig)
|
||||
module.imported('org.eclipse.ui.plugin.AbstractUIPlugin')
|
||||
val eclipsePluginDefaultModule = module.imported(g.eclipsePluginDefaultModule)
|
||||
|
||||
module.typeComment = '''
|
||||
/**
|
||||
* Manual modifications go to {@link «g.eclipsePluginModule.simple»}.
|
||||
* Manual modifications go to {@link «g.eclipsePluginModule.simpleName»}.
|
||||
*/
|
||||
'''
|
||||
module.codeFragments += '''
|
||||
public abstract class «g.eclipsePluginGenModule.simple» extends «eclipsePluginDefaultModule» {
|
||||
module.javaContent = '''
|
||||
public abstract class «g.eclipsePluginGenModule.simpleName» extends «g.eclipsePluginDefaultModule» {
|
||||
|
||||
public «g.eclipsePluginGenModule.simple»(AbstractUIPlugin plugin) {
|
||||
public «g.eclipsePluginGenModule.simpleName»(«'org.eclipse.ui.plugin.AbstractUIPlugin'» plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
'''
|
||||
|
@ -242,26 +232,23 @@ class XtextGeneratorTemplates {
|
|||
}
|
||||
|
||||
def GuiceModuleAccess finishGenModule(GuiceModuleAccess module) {
|
||||
val binder = module.imported('com.google.inject.Binder')
|
||||
val provider = module.imported('com.google.inject.Provider')
|
||||
val singletonBinding = module.imported('org.eclipse.xtext.service.SingletonBinding')
|
||||
for (it : module.bindings) {
|
||||
module.codeFragments += '''
|
||||
module.javaContent = '''
|
||||
«IF !value.provider && value.statements.isEmpty»
|
||||
// contributed by «contributedBy»
|
||||
«IF key.singleton»@«singletonBinding»«IF key.eagerSingleton»(eager=true)«ENDIF»«ENDIF»
|
||||
public «IF value.expression === null»Class<? extends «module.imported(key.type)»>«ELSE»«module.imported(key.type)»«ENDIF» «bindMethodName»() {
|
||||
«IF key.singleton»@«SingletonBinding»«IF key.eagerSingleton»(eager=true)«ENDIF»«ENDIF»
|
||||
public «IF value.expression === null»Class<? extends «key.type»>«ELSE»«key.type»«ENDIF» «bindMethodName»() {
|
||||
return «IF value.expression !== null»«value.expression»«ELSE»«value.typeName».class«ENDIF»;
|
||||
}
|
||||
«ELSEIF value.statements.isEmpty»
|
||||
// contributed by «contributedBy»
|
||||
«IF key.singleton»@«singletonBinding»«IF key.eagerSingleton»(eager=true)«ENDIF»«ENDIF»
|
||||
public «IF value.expression==null»Class<? extends «provider»<«key.type»>>«ELSE»«provider»<«key.type»>«ENDIF» «bindMethodName»() {
|
||||
«IF key.singleton»@«SingletonBinding»«IF key.eagerSingleton»(eager=true)«ENDIF»«ENDIF»
|
||||
public «IF value.expression==null»Class<? extends «Provider»<«key.type»>>«ELSE»«Provider»<«key.type»>«ENDIF» «bindMethodName»() {
|
||||
return «IF value.expression!=null»«value.expression»«ELSE»«value.typeName».class«ENDIF»;
|
||||
}
|
||||
«ELSE»
|
||||
// contributed by «contributedBy»
|
||||
public void «bindMethodName»(«binder» binder) {
|
||||
public void «bindMethodName»(«Binder» binder) {
|
||||
«FOR statement : value.statements»
|
||||
«statement»«IF !statement.endsWith(';')»;«ENDIF»
|
||||
«ENDFOR»
|
||||
|
@ -269,7 +256,7 @@ class XtextGeneratorTemplates {
|
|||
«ENDIF»
|
||||
'''
|
||||
}
|
||||
module.codeFragments += '''
|
||||
module.javaContent = '''
|
||||
}
|
||||
'''
|
||||
return module
|
||||
|
@ -278,10 +265,6 @@ class XtextGeneratorTemplates {
|
|||
def JavaFileAccess getEclipsePluginExecutableExtensionFactory(LanguageConfig2 langConfig) {
|
||||
val g = langConfig.grammar
|
||||
val javaFile = new JavaFileAccess(g.eclipsePluginExecutableExtensionFactory, codeConfig)
|
||||
javaFile.imported('org.osgi.framework.Bundle')
|
||||
javaFile.imported('com.google.inject.Injector')
|
||||
val superClass = javaFile.imported('org.eclipse.xtext.ui.guice.AbstractGuiceAwareExecutableExtensionFactory')
|
||||
val activator = javaFile.imported(g.eclipsePluginActivator)
|
||||
|
||||
javaFile.typeComment = '''
|
||||
/**
|
||||
|
@ -289,17 +272,17 @@ class XtextGeneratorTemplates {
|
|||
* introduced subclass.
|
||||
*/
|
||||
'''
|
||||
javaFile.codeFragments += '''
|
||||
public class «g.eclipsePluginExecutableExtensionFactory.simple» extends «superClass» {
|
||||
javaFile.javaContent = '''
|
||||
public class «g.eclipsePluginExecutableExtensionFactory.simpleName» extends «'org.eclipse.xtext.ui.guice.AbstractGuiceAwareExecutableExtensionFactory'» {
|
||||
|
||||
@Override
|
||||
protected Bundle getBundle() {
|
||||
return «activator».getInstance().getBundle();
|
||||
protected «'org.osgi.framework.Bundle'» getBundle() {
|
||||
return «g.eclipsePluginActivator».getInstance().getBundle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Injector getInjector() {
|
||||
return «activator».getInstance().getInjector(«activator».«g.name.toUpperCase.replaceAll('\\.', '_')»);
|
||||
protected «Injector» getInjector() {
|
||||
return «g.eclipsePluginActivator».getInstance().getInjector(«g.eclipsePluginActivator».«g.name.toUpperCase.replaceAll('\\.', '_')»);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -65,6 +65,10 @@ class CodeConfig implements IGuiceAwareGeneratorComponent {
|
|||
|
||||
override initialize(Injector injector) {
|
||||
injector.injectMembers(this)
|
||||
|
||||
if (lineDelimiter === null)
|
||||
lineDelimiter = '\n'
|
||||
|
||||
var fileHeader = fileHeaderTemplate
|
||||
if (fileHeader != null) {
|
||||
if (fileHeader.contains(FILE_HEADER_VAR_TIME)) {
|
||||
|
@ -148,7 +152,7 @@ class CodeConfig implements IGuiceAwareGeneratorComponent {
|
|||
val stringBuilder = new StringBuilder
|
||||
for (annotation : classAnnotations) {
|
||||
val importString = annotation.annotationImport
|
||||
if (!Strings.isEmpty(importString)) {
|
||||
if (importString !== null) {
|
||||
stringBuilder.append('import ').append(importString).append(';').append(Strings.newLine)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ class GeneratedClassAnnotation implements IClassAnnotation {
|
|||
}
|
||||
|
||||
override getAnnotationImport() {
|
||||
return 'javax.annotation.Generated'
|
||||
return new TypeReference('javax.annotation.Generated')
|
||||
}
|
||||
|
||||
private def void +=(StringBuilder stringBuilder, String s) {
|
||||
|
|
|
@ -39,8 +39,8 @@ class GuiceModuleAccess extends JavaFileAccess {
|
|||
@Accessors
|
||||
val List<Binding> bindings = newArrayList
|
||||
|
||||
new(String qualifiedName, CodeConfig codeConfig) {
|
||||
super(qualifiedName, codeConfig)
|
||||
new(TypeReference typeRef, CodeConfig codeConfig) {
|
||||
super(typeRef, codeConfig)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,6 @@ interface IClassAnnotation {
|
|||
* Return the qualified name of the annotation interface for use in import declarations,
|
||||
* or {@code null} if no import is required.
|
||||
*/
|
||||
def String getAnnotationImport()
|
||||
def TypeReference getAnnotationImport()
|
||||
|
||||
}
|
||||
|
|
|
@ -10,12 +10,15 @@ package org.eclipse.xtext.xtext.generator.model
|
|||
import com.google.common.collect.Lists
|
||||
import java.util.Collections
|
||||
import java.util.Map
|
||||
import java.util.regex.Pattern
|
||||
import org.eclipse.emf.codegen.util.CodeGenUtil
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtend2.lib.StringConcatenation
|
||||
import org.eclipse.xtend2.lib.StringConcatenationClient
|
||||
|
||||
class JavaFileAccess extends TextFileAccess {
|
||||
|
||||
val Map<String, String> imports = newHashMap
|
||||
val Map<String, TypeReference> imports = newHashMap
|
||||
|
||||
val String packageName
|
||||
|
||||
|
@ -28,38 +31,42 @@ class JavaFileAccess extends TextFileAccess {
|
|||
boolean markedAsGenerated
|
||||
|
||||
new(String qualifiedName, CodeConfig codeConfig) {
|
||||
val simpleNameIndex = qualifiedName.lastIndexOf('.')
|
||||
this.packageName = qualifiedName.substring(0, simpleNameIndex)
|
||||
val simpleName = qualifiedName.substring(simpleNameIndex + 1)
|
||||
this.path = packageName.replace('.', '/') + '/' + simpleName + '.java'
|
||||
this.codeConfig = codeConfig
|
||||
this(new TypeReference(qualifiedName), codeConfig)
|
||||
}
|
||||
|
||||
def String imported(Class<?> clazz) {
|
||||
return imported(clazz.name.replace('$', '.'))
|
||||
new(TypeReference typeRef, CodeConfig codeConfig) {
|
||||
this.packageName = typeRef.package
|
||||
if (typeRef.name != packageName + '.' + typeRef.simpleName)
|
||||
throw new IllegalArgumentException('Nested types cannot be serialized.')
|
||||
this.path = packageName.replace('.', '/') + '/' + typeRef.simpleName + '.java'
|
||||
this.codeConfig = codeConfig
|
||||
}
|
||||
|
||||
def String imported(String clazz) {
|
||||
val simpleNameIndex = clazz.lastIndexOf('.')
|
||||
val simpleName = clazz.substring(simpleNameIndex + 1)
|
||||
val packageName = clazz.substring(0, simpleNameIndex)
|
||||
if (CodeGenUtil.isJavaDefaultType(simpleName) || this.packageName == packageName)
|
||||
def String importType(TypeReference typeRef) {
|
||||
val simpleName = typeRef.simpleName
|
||||
if (CodeGenUtil.isJavaDefaultType(simpleName) || this.packageName == typeRef.package)
|
||||
return simpleName
|
||||
val imported = imports.get(simpleName)
|
||||
if (imported != null) {
|
||||
if (imported.equals(clazz))
|
||||
if (imported == typeRef)
|
||||
return simpleName
|
||||
else
|
||||
return clazz
|
||||
return typeRef.name
|
||||
}
|
||||
imports.put(simpleName, clazz)
|
||||
imports.put(simpleName, typeRef)
|
||||
return simpleName
|
||||
}
|
||||
|
||||
def void setJavaContent(StringConcatenationClient javaContent) {
|
||||
val javaStringConcat = new JavaStringConcatenation(this)
|
||||
javaStringConcat.append(javaContent)
|
||||
content = javaStringConcat
|
||||
}
|
||||
|
||||
override generate() {
|
||||
val classAnnotations = codeConfig.classAnnotations.filter[appliesTo(this)]
|
||||
classAnnotations.forEach[imported(annotationImport)]
|
||||
val sortedImports = Lists.newArrayList(imports.values())
|
||||
classAnnotations.forEach[importType(annotationImport)]
|
||||
val sortedImports = Lists.newArrayList(imports.values.map[name])
|
||||
Collections.sort(sortedImports)
|
||||
return '''
|
||||
«codeConfig.fileHeader»
|
||||
|
@ -73,10 +80,32 @@ class JavaFileAccess extends TextFileAccess {
|
|||
«FOR annot : classAnnotations»
|
||||
«annot.generate()»
|
||||
«ENDFOR»
|
||||
«FOR fragment : codeFragments»
|
||||
«fragment»
|
||||
«ENDFOR»
|
||||
«content»
|
||||
'''
|
||||
}
|
||||
|
||||
private static class JavaStringConcatenation extends StringConcatenation {
|
||||
|
||||
val JavaFileAccess access
|
||||
|
||||
val typeNamePattern = Pattern.compile('[a-z]+(\\.[a-z]+)*(\\.[A-Z][a-zA-Z]*)+')
|
||||
|
||||
new(JavaFileAccess access) {
|
||||
super(access.codeConfig.lineDelimiter)
|
||||
this.access = access
|
||||
}
|
||||
|
||||
override getStringRepresentation(Object object) {
|
||||
if (object instanceof TypeReference)
|
||||
access.importType(object)
|
||||
else if (object instanceof Class<?>)
|
||||
access.importType(new TypeReference(object as Class<?>))
|
||||
else if (object instanceof String && typeNamePattern.matcher(object as String).matches)
|
||||
access.importType(new TypeReference(object as String))
|
||||
else
|
||||
object.toString
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -10,10 +10,8 @@ package org.eclipse.xtext.xtext.generator.model
|
|||
import com.google.common.io.Files
|
||||
import java.io.File
|
||||
import java.nio.charset.Charset
|
||||
import java.util.List
|
||||
import org.eclipse.emf.common.util.URI
|
||||
import org.eclipse.xtend.lib.annotations.Accessors
|
||||
import org.eclipse.xtend2.lib.StringConcatenation
|
||||
import org.eclipse.xtext.generator.IFileSystemAccess2
|
||||
import org.eclipse.xtext.parser.IEncodingProvider
|
||||
|
||||
|
@ -23,17 +21,13 @@ class TextFileAccess {
|
|||
String path
|
||||
|
||||
@Accessors
|
||||
val List<CharSequence> codeFragments = newArrayList
|
||||
CharSequence content
|
||||
|
||||
@Accessors
|
||||
IEncodingProvider encodingProvider
|
||||
|
||||
def CharSequence generate() {
|
||||
val result = new StringConcatenation
|
||||
for (fragment : codeFragments) {
|
||||
result.append(fragment)
|
||||
}
|
||||
return result
|
||||
return content
|
||||
}
|
||||
|
||||
def writeTo(IFileSystemAccess2 fileSystemAccess) {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2015 itemis AG (http://www.itemis.eu) and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*******************************************************************************/
|
||||
package org.eclipse.xtext.xtext.generator.model
|
||||
|
||||
import org.eclipse.xtend.lib.annotations.EqualsHashCode
|
||||
|
||||
@EqualsHashCode
|
||||
class TypeReference {
|
||||
|
||||
val String name
|
||||
|
||||
new(String name) {
|
||||
this.name = name
|
||||
}
|
||||
|
||||
new(String packageName, String className) {
|
||||
this.name = packageName + '.' + className
|
||||
}
|
||||
|
||||
new(Class<?> clazz) {
|
||||
this.name = clazz.name.replace('$', '.')
|
||||
}
|
||||
|
||||
override toString() {
|
||||
name
|
||||
}
|
||||
|
||||
def getName() {
|
||||
name
|
||||
}
|
||||
|
||||
def getSimpleName() {
|
||||
val simpleNameIndex = name.lastIndexOf('.')
|
||||
return name.substring(simpleNameIndex + 1)
|
||||
}
|
||||
|
||||
def getPackage() {
|
||||
var packageEnd = name.length
|
||||
for (var i = name.length - 1; i >= 0; i--) {
|
||||
if (name.charAt(i).matches('.')) {
|
||||
if (Character.isLowerCase(name.charAt(i + 1)))
|
||||
return name.substring(0, packageEnd)
|
||||
else
|
||||
packageEnd = i
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
private def matches(char c1, char c2) {
|
||||
c1 == c2
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue