Skip to content

Commit

Permalink
#278 initial draft of jte modules
Browse files Browse the repository at this point in the history
  • Loading branch information
casid committed Sep 29, 2023
1 parent 254fa8a commit 7183854
Show file tree
Hide file tree
Showing 21 changed files with 363 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<>();
Expand All @@ -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
Expand Down Expand Up @@ -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);

Expand Down
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
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand All @@ -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);

Expand All @@ -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());
Expand All @@ -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) {
Expand Down Expand Up @@ -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
Expand Up @@ -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;
Expand All @@ -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<>();
Expand All @@ -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
Expand Down Expand Up @@ -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);

Expand Down
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.