Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jte Modules #279

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
54 changes: 38 additions & 16 deletions jte/src/main/java/gg/jte/compiler/TemplateCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
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.extension.api.JteConfig;
import gg.jte.extension.api.JteExtension;
import gg.jte.extension.api.TemplateDescription;
Expand Down Expand Up @@ -53,7 +54,7 @@ public Template load(String name) {

@Override
public Template hotReload(String name) {
LinkedHashSet<ClassDefinition> classDefinitions = generate(Collections.singletonList(name), true);
LinkedHashSet<ClassDefinition> classDefinitions = generate(Collections.singletonList(name), true, getModule());
classDefinitions.removeIf(c -> !c.isChanged());

if (!classDefinitions.isEmpty()) {
Expand All @@ -80,17 +81,24 @@ public void cleanAll() {

@Override
public List<String> generateAll() {
LinkedHashSet<ClassDefinition> classDefinitions = generate(codeResolver.resolveAllTemplateNames(), false);
Module module = getModule();
Collection<String> names = module.resolveAllTemplateNames();
LinkedHashSet<ClassDefinition> classDefinitions = generate(names, false, module);

return classDefinitions.stream().map(ClassDefinition::getSourceFileName).collect(Collectors.toList());
}

@Override
public List<String> precompileAll() {
return precompile(codeResolver.resolveAllTemplateNames());
Module module = getModule();
Collection<String> names = module.resolveAllTemplateNames();
LinkedHashSet<ClassDefinition> classDefinitions = generate(names, false, module);

return precompileClasses(classDefinitions);
}

public List<String> precompile(List<String> names) {
LinkedHashSet<ClassDefinition> classDefinitions = generate(names, false);
LinkedHashSet<ClassDefinition> classDefinitions = generate(names, false, getModule());
return precompileClasses(classDefinitions);
}

Expand Down Expand Up @@ -161,12 +169,13 @@ ClassCompiler createCompiler(String extension) {
}
}

private LinkedHashSet<ClassDefinition> generate(List<String> names, boolean trackChanges) {
private LinkedHashSet<ClassDefinition> generate(Collection<String> names, boolean trackChanges, Module module) {

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 @@ -229,15 +238,17 @@ private LinkedHashSet<TemplateDependency> initTemplateDependencies(String 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 +259,12 @@ 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();

name = templateModule.normalize(name);

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

Expand All @@ -257,11 +273,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 +290,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 +358,9 @@ private JteExtension loadExtension(Map.Entry<String, Map<String, String>> extens
throw new TemplateException("Failed to load extension " + extensionSettings.getKey(), e);
}
}

private Module getModule() {
return Module.create("", codeResolver);
}

}
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
111 changes: 111 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,111 @@
package gg.jte.compiler.module;

import java.nio.file.Path;
import java.util.*;

import gg.jte.CodeResolver;
import gg.jte.resolve.DirectoryCodeResolver;


public final class Module {

public static Module create(String alias, CodeResolver codeResolver) {
String jteRootContent = codeResolver.resolve(".jteroot");
if (jteRootContent == null) {
return new Module(alias, codeResolver, Map.of(), false);
}

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

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

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

return new Module(alias, codeResolver, children, moduleInfo.parent());
}

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;
private final boolean parent;

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

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 String normalize(String name) {
if (isRoot()) {
return name;
} else {
if (name.startsWith(alias + "/")) {
return name;
} else {
return alias + "/" + name;
}
}
}

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

public CodeResolver getCodeResolver() {
return codeResolver;
}

public Collection<String> resolveAllTemplateNames() {
LinkedHashSet<String> result = new LinkedHashSet<>();
resolveAllTemplateNames(result);
return result;
}

private void resolveAllTemplateNames(LinkedHashSet<String> result) {
if (!parent) {
List<String> names = codeResolver.resolveAllTemplateNames();
for (String name : names) {
result.add(normalize(name));
}
}

for (Module module : children.values()) {
module.resolveAllTemplateNames(result);
}
}
}
51 changes: 51 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,51 @@
package gg.jte.compiler.module;

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

import java.util.List;


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 List<String> resolveAllTemplateNames() {
return codeResolver.resolveAllTemplateNames();
}

@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) {}
Loading