Skip to content

Commit

Permalink
#278 initial draft of jte modules
Browse files Browse the repository at this point in the history
casid committed Sep 29, 2023
1 parent 254fa8a commit 7183854
Showing 21 changed files with 363 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
import gg.jte.TemplateException;
import gg.jte.compiler.*;
import gg.jte.compiler.CodeBuilder.CodeMarker;
import gg.jte.compiler.module.Module;
import gg.jte.runtime.ClassInfo;
import gg.jte.runtime.Constants;
import gg.jte.runtime.DebugInfo;
@@ -25,6 +26,7 @@ public class KotlinCodeGenerator implements CodeGenerator {
private final CodeBuilder kotlinCode = new CodeBuilder(CodeType.Kotlin);
private final LinkedHashSet<ClassDefinition> classDefinitions;
private final LinkedHashSet<TemplateDependency> templateDependencies;
private final Module module;
private final List<ParamInfo> parameters = new ArrayList<>();
private final List<String> imports = new ArrayList<>();
private final List<byte[]> binaryTextParts = new ArrayList<>();
@@ -35,13 +37,14 @@ public class KotlinCodeGenerator implements CodeGenerator {
private CodeMarker fieldsMarker;
private int attributeCounter;

public KotlinCodeGenerator(TemplateCompiler compiler, TemplateConfig config, ConcurrentHashMap<String, List<ParamInfo>> paramOrder, ClassInfo classInfo, LinkedHashSet<ClassDefinition> classDefinitions, LinkedHashSet<TemplateDependency> templateDependencies) {
public KotlinCodeGenerator(TemplateCompiler compiler, TemplateConfig config, ConcurrentHashMap<String, List<ParamInfo>> paramOrder, ClassInfo classInfo, LinkedHashSet<ClassDefinition> classDefinitions, LinkedHashSet<TemplateDependency> templateDependencies, Module module ) {
this.compiler = compiler;
this.config = config;
this.paramOrder = paramOrder;
this.classInfo = classInfo;
this.classDefinitions = classDefinitions;
this.templateDependencies = templateDependencies;
this.module = module;
}

@Override
@@ -426,7 +429,7 @@ public void onForLoopEnd(int depth) {

@Override
public void onTemplateCall(int depth, String name, List<String> params) {
ClassInfo tagInfo = compiler.generateTemplateCall(name, "kte", classDefinitions, templateDependencies, getCurrentDebugInfo());
ClassInfo tagInfo = compiler.generateTemplateCall(name, "kte", classDefinitions, templateDependencies, getCurrentDebugInfo(), module);

writeIndentation(depth);

62 changes: 49 additions & 13 deletions jte/src/main/java/gg/jte/compiler/TemplateCompiler.java
Original file line number Diff line number Diff line change
@@ -8,10 +8,15 @@
import gg.jte.compiler.extensionsupport.ExtensionTemplateDescription;
import gg.jte.compiler.java.JavaClassCompiler;
import gg.jte.compiler.java.JavaCodeGenerator;
import gg.jte.compiler.module.Module;
import gg.jte.compiler.module.ModuleImport;
import gg.jte.compiler.module.ModuleInfo;
import gg.jte.compiler.module.ModuleInfoParser;
import gg.jte.extension.api.JteConfig;
import gg.jte.extension.api.JteExtension;
import gg.jte.extension.api.TemplateDescription;
import gg.jte.output.FileOutput;
import gg.jte.resolve.DirectoryCodeResolver;
import gg.jte.runtime.*;

import java.io.IOException;
@@ -86,7 +91,8 @@ public List<String> generateAll() {

@Override
public List<String> precompileAll() {
return precompile(codeResolver.resolveAllTemplateNames());
LinkedHashSet<ClassDefinition> classDefinitions = generate(codeResolver.resolveAllTemplateNames(), false);
return precompileClasses(classDefinitions);
}

public List<String> precompile(List<String> names) {
@@ -161,12 +167,14 @@ ClassCompiler createCompiler(String extension) {
}
}

private LinkedHashSet<ClassDefinition> generate(List<String> names, boolean trackChanges) {
private LinkedHashSet<ClassDefinition> generate(List<String> names, boolean trackChanges ) {
Module module = readModuleInformation("", codeResolver);

LinkedHashSet<ClassDefinition> classDefinitions = new LinkedHashSet<>();
for (String name : names) {
LinkedHashSet<TemplateDependency> dependencies = initTemplateDependencies(name);

ClassInfo templateInfo = generateTemplateCall(name, classDefinitions, dependencies, null);
ClassInfo templateInfo = generateTemplateCall(name, classDefinitions, dependencies, null, module);

templateDependencies.put(name, dependencies);
templateByClassName.put(templateInfo.name, templateInfo);
@@ -223,21 +231,44 @@ private LinkedHashSet<ClassDefinition> generate(List<String> names, boolean trac
return classDefinitions;
}

private Module readModuleInformation(String alias, CodeResolver codeResolver) {
String jteRootContent = codeResolver.resolve(".jteroot");
if (jteRootContent == null) {
return new Module(alias, codeResolver, Map.of());
}

if (!(codeResolver instanceof DirectoryCodeResolver directoryCodeResolver)) {
return new Module(alias, codeResolver, Map.of());
}

ModuleInfo moduleInfo = ModuleInfoParser.parse(jteRootContent);
Map<String, Module> children = new LinkedHashMap<>();

for ( ModuleImport moduleImport : moduleInfo.imports() ) {
DirectoryCodeResolver moduleDirectoryResolver = new DirectoryCodeResolver(directoryCodeResolver.getRoot().resolve(moduleImport.from()));
children.put(moduleImport.alias(), readModuleInformation(moduleImport.alias(), moduleDirectoryResolver));
}

return new Module(alias, codeResolver, children);
}

private LinkedHashSet<TemplateDependency> initTemplateDependencies(String name) {
LinkedHashSet<TemplateDependency> templateDependencies = new LinkedHashSet<>();
templateDependencies.add(new TemplateDependency(name, codeResolver.getLastModified(name)));
return templateDependencies;
}

public ClassInfo generateTemplateCall(String simpleName, String extension, LinkedHashSet<ClassDefinition> classDefinitions, LinkedHashSet<TemplateDependency> templateDependencies, DebugInfo debugInfo) {
public ClassInfo generateTemplateCall(String simpleName, String extension, LinkedHashSet<ClassDefinition> classDefinitions, LinkedHashSet<TemplateDependency> templateDependencies, DebugInfo debugInfo, Module module) {
String name = resolveTemplateName(simpleName, extension);
try {
return generateTemplateCall(name, classDefinitions, templateDependencies, debugInfo);
return generateTemplateCall(name, classDefinitions, templateDependencies, debugInfo, module);
} catch (TemplateNotFoundException e) {
String alternativeName = resolveTemplateName(simpleName, "jte".equals(extension) ? "kte" : "jte");

Module templateModule = module.resolve(name);
CodeResolver codeResolver = templateModule.getCodeResolver();
if (codeResolver.exists(alternativeName)) {
return generateTemplateCall(alternativeName, classDefinitions, templateDependencies, debugInfo);
return generateTemplateCall(alternativeName, classDefinitions, templateDependencies, debugInfo, module);
} else {
throw e;
}
@@ -248,7 +279,10 @@ private String resolveTemplateName(String simpleName, String extension) {
return simpleName.replace('.', '/') + "." + extension;
}

public ClassInfo generateTemplateCall(String name, LinkedHashSet<ClassDefinition> classDefinitions, LinkedHashSet<TemplateDependency> templateDependencies, DebugInfo debugInfo) {
public ClassInfo generateTemplateCall(String name, LinkedHashSet<ClassDefinition> classDefinitions, LinkedHashSet<TemplateDependency> templateDependencies, DebugInfo debugInfo, Module module) {
Module templateModule = module.resolve(name);
CodeResolver codeResolver = templateModule.getCodeResolver();

templateDependencies.add(new TemplateDependency(name, codeResolver.getLastModified(name)));
ClassInfo classInfo = new ClassInfo(name, config.packageName);

@@ -257,11 +291,11 @@ public ClassInfo generateTemplateCall(String name, LinkedHashSet<ClassDefinition
return classInfo;
}

String code = resolveCode(name, debugInfo);
String code = resolveCode(codeResolver, name, debugInfo);

classDefinitions.add(classDefinition);

CodeGenerator codeGenerator = createCodeGenerator(classInfo, classDefinitions, templateDependencies);
CodeGenerator codeGenerator = createCodeGenerator(classInfo, classDefinitions, templateDependencies, templateModule);
new TemplateParser(code, TemplateType.Template, codeGenerator, config).parse();

classDefinition.setCode(codeGenerator.getCode(), codeGenerator.getBinaryTextParts(), codeGenerator.getParamInfo(), codeGenerator.getImports());
@@ -274,20 +308,21 @@ public ClassInfo generateTemplateCall(String name, LinkedHashSet<ClassDefinition
return classInfo;
}

private CodeGenerator createCodeGenerator(ClassInfo classInfo, LinkedHashSet<ClassDefinition> classDefinitions, LinkedHashSet<TemplateDependency> templateDependencies) {
private CodeGenerator createCodeGenerator(ClassInfo classInfo, LinkedHashSet<ClassDefinition> classDefinitions, LinkedHashSet<TemplateDependency> templateDependencies,
Module module ) {
if ("kte".equals(classInfo.extension)) {
try {
Class<?> compilerClass = Class.forName("gg.jte.compiler.kotlin.KotlinCodeGenerator");
return (CodeGenerator)compilerClass.getConstructor(TemplateCompiler.class, TemplateConfig.class, ConcurrentHashMap.class, ClassInfo.class, LinkedHashSet.class, LinkedHashSet.class).newInstance(this, this.config, paramOrder, classInfo, classDefinitions, templateDependencies);
return (CodeGenerator)compilerClass.getConstructor(TemplateCompiler.class, TemplateConfig.class, ConcurrentHashMap.class, ClassInfo.class, LinkedHashSet.class, LinkedHashSet.class, Module.class).newInstance(this, this.config, paramOrder, classInfo, classDefinitions, templateDependencies, module);
} catch (Exception e) {
throw new TemplateException("Failed to create kotlin generator. To handle .kte files, you need to add gg.jte:jte-kotlin to your project.", e);
}
} else {
return new JavaCodeGenerator(this, this.config, paramOrder, classInfo, classDefinitions, templateDependencies);
return new JavaCodeGenerator(this, this.config, paramOrder, classInfo, classDefinitions, templateDependencies, module);
}
}

private String resolveCode(String name, DebugInfo debugInfo) {
private String resolveCode(CodeResolver codeResolver, String name, DebugInfo debugInfo) {
try {
return codeResolver.resolveRequired(name);
} catch (TemplateNotFoundException e) {
@@ -341,4 +376,5 @@ private JteExtension loadExtension(Map.Entry<String, Map<String, String>> extens
throw new TemplateException("Failed to load extension " + extensionSettings.getKey(), e);
}
}

}
7 changes: 5 additions & 2 deletions jte/src/main/java/gg/jte/compiler/java/JavaCodeGenerator.java
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
import gg.jte.TemplateException;
import gg.jte.compiler.*;
import gg.jte.compiler.CodeBuilder.CodeMarker;
import gg.jte.compiler.module.Module;
import gg.jte.runtime.ClassInfo;
import gg.jte.runtime.Constants;
import gg.jte.runtime.DebugInfo;
@@ -24,6 +25,7 @@ public class JavaCodeGenerator implements CodeGenerator {
private final CodeBuilder javaCode = new CodeBuilder(CodeType.Java);
private final LinkedHashSet<ClassDefinition> classDefinitions;
private final LinkedHashSet<TemplateDependency> templateDependencies;
private final Module module;
private final List<ParamInfo> parameters = new ArrayList<>();
private final List<String> imports = new ArrayList<>();
private final List<byte[]> binaryTextParts = new ArrayList<>();
@@ -34,13 +36,14 @@ public class JavaCodeGenerator implements CodeGenerator {
private CodeMarker fieldsMarker;
private int attributeCounter;

public JavaCodeGenerator(TemplateCompiler compiler, TemplateConfig config, ConcurrentHashMap<String, List<ParamInfo>> paramOrder, ClassInfo classInfo, LinkedHashSet<ClassDefinition> classDefinitions, LinkedHashSet<TemplateDependency> templateDependencies) {
public JavaCodeGenerator(TemplateCompiler compiler, TemplateConfig config, ConcurrentHashMap<String, List<ParamInfo>> paramOrder, ClassInfo classInfo, LinkedHashSet<ClassDefinition> classDefinitions, LinkedHashSet<TemplateDependency> templateDependencies, Module module ) {
this.compiler = compiler;
this.config = config;
this.paramOrder = paramOrder;
this.classInfo = classInfo;
this.classDefinitions = classDefinitions;
this.templateDependencies = templateDependencies;
this.module = module;
}

@Override
@@ -420,7 +423,7 @@ public void onForLoopEnd(int depth) {

@Override
public void onTemplateCall(int depth, String name, List<String> params) {
ClassInfo tagInfo = compiler.generateTemplateCall(name, "jte", classDefinitions, templateDependencies, getCurrentDebugInfo());
ClassInfo tagInfo = compiler.generateTemplateCall(name, "jte", classDefinitions, templateDependencies, getCurrentDebugInfo(), module);

writeIndentation(depth);

58 changes: 58 additions & 0 deletions jte/src/main/java/gg/jte/compiler/module/Module.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package gg.jte.compiler.module;

import java.util.Map;

import gg.jte.CodeResolver;


public final class Module {

public static String getModuleAlias(String name) {
int index = name.indexOf('/');
if (index == -1) {
return null;
}

return name.substring(0, index);
}

private final String alias;
private final CodeResolver codeResolver;
private final Map<String, Module> children;

public Module( String alias, CodeResolver codeResolver, Map<String, Module> children ) {
this.alias = alias;
this.codeResolver = isRoot() ? codeResolver : new ModuleCodeResolver(alias, codeResolver);
this.children = children;
}

public Module resolve(String name) {
if (children.isEmpty()) {
return this;
}

String moduleAlias = getModuleAlias(name);
if (moduleAlias == null) {
return this;
}

Module result = children.get(moduleAlias);
if (result == null) {
return this;
}

return result;
}

public boolean isRoot() {
return alias.isEmpty();
}

public String getAlias() {
return alias;
}

public CodeResolver getCodeResolver() {
return codeResolver;
}
}
44 changes: 44 additions & 0 deletions jte/src/main/java/gg/jte/compiler/module/ModuleCodeResolver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package gg.jte.compiler.module;

import gg.jte.CodeResolver;
import gg.jte.TemplateNotFoundException;


public class ModuleCodeResolver implements CodeResolver {

private final CodeResolver codeResolver;
private final String aliasSlash;

public ModuleCodeResolver( String alias, CodeResolver codeResolver ) {
this.codeResolver = codeResolver;
this.aliasSlash = alias + "/";
}

@Override
public String resolve( String name ) {
return codeResolver.resolve(removeAlias(name));
}

@Override
public String resolveRequired( String name ) throws TemplateNotFoundException {
return codeResolver.resolveRequired(removeAlias(name));
}

@Override
public long getLastModified( String name ) {
return codeResolver.getLastModified(removeAlias(name));
}

@Override
public boolean exists( String name ) {
return codeResolver.exists(removeAlias(name));
}

private String removeAlias(String name) {
if (name.startsWith(aliasSlash)) {
return name.substring(aliasSlash.length());
}

return name;
}
}
3 changes: 3 additions & 0 deletions jte/src/main/java/gg/jte/compiler/module/ModuleImport.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package gg.jte.compiler.module;

public record ModuleImport(String alias, String from) {}
6 changes: 6 additions & 0 deletions jte/src/main/java/gg/jte/compiler/module/ModuleInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package gg.jte.compiler.module;

import java.util.List;


public record ModuleInfo(List<ModuleImport> imports) {}
Loading

0 comments on commit 7183854

Please sign in to comment.