This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-compiler-java.git
commit cd39d0a5e2b2f685c793931b7e09b262de7fd19e Author: Radu Cotescu <[email protected]> AuthorDate: Wed Oct 18 16:00:09 2017 +0000 SLING-7205 - Generate import statements for data-sly-use Java use objects * added support for generating the import statements for fully qualified Java class names passed as identifiers to data-sly-resource; use objects stored in the repository are ignored git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1812544 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 1 + .../java/compiler/JavaClassBackendCompiler.java | 18 ++++++++++- .../sightly/java/compiler/JavaImportsAnalyzer.java | 37 ++++++++++++++++++++++ .../sightly/java/compiler/impl/CodeGenVisitor.java | 4 +-- .../java/compiler/impl/JavaClassTemplate.java | 10 ++++-- .../scripting/sightly/java/compiler/impl/Type.java | 31 ++++++++++++------ .../sightly/java/compiler/impl/TypeInference.java | 30 ++++++++++++++---- .../sightly/java/compiler/impl/UnitBuilder.java | 17 ++++++++-- .../java/compiler/impl/VariableDescriptor.java | 2 +- .../sightly/java/compiler/package-info.java | 2 +- .../resources/templates/compiled_unit_template.txt | 2 ++ .../java/JavaClassBackendCompilerTest.java | 12 +++++++ src/test/resources/imports.html | 22 +++++++++++++ .../resources/imports.html.java} | 19 ++++++++--- 14 files changed, 176 insertions(+), 31 deletions(-) diff --git a/pom.xml b/pom.xml index b891e9d..51b6c0a 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,7 @@ <properties> <jacoco.maven.plugin.version>0.7.9</jacoco.maven.plugin.version> + <sling.java.version>8</sling.java.version> </properties> <!-- ======================================================================= --> diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/JavaClassBackendCompiler.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/JavaClassBackendCompiler.java index 87e9655..8069cb0 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/JavaClassBackendCompiler.java +++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/JavaClassBackendCompiler.java @@ -38,7 +38,8 @@ public final class JavaClassBackendCompiler implements BackendCompiler { private static final String mainTemplate; private static final String childTemplate; - private UnitBuilder unitBuilder = new UnitBuilder(); + private UnitBuilder unitBuilder; + private final JavaImportsAnalyzer JAVA_IMPORTS_ANALYZER; static { try { @@ -50,6 +51,14 @@ public final class JavaClassBackendCompiler implements BackendCompiler { } } + public JavaClassBackendCompiler() { + this(new JavaImportsAnalyzer() {}); + } + + public JavaClassBackendCompiler(JavaImportsAnalyzer javaImportsAnalyzer) { + JAVA_IMPORTS_ANALYZER = javaImportsAnalyzer; + unitBuilder = new UnitBuilder(JAVA_IMPORTS_ANALYZER); + } @Override public void handle(CommandStream stream) { @@ -76,6 +85,13 @@ public final class JavaClassBackendCompiler implements BackendCompiler { JavaClassTemplate mainTemplate = newMainTemplate(); mainTemplate.setPackageName(classInfo.getPackageName()); mainTemplate.setClassName(classInfo.getSimpleClassName()); + StringBuilder imports = new StringBuilder(); + for (String importClass : unitBuilder.getImports()) { + if (JAVA_IMPORTS_ANALYZER.allowImport(importClass)) { + imports.append("import ").append(importClass).append(";").append(System.lineSeparator()); + } + } + mainTemplate.setImports(imports.toString()); processCompilationResult(compilationOutput, mainTemplate); return mainTemplate.toString(); } diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/JavaImportsAnalyzer.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/JavaImportsAnalyzer.java new file mode 100644 index 0000000..23a94e4 --- /dev/null +++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/JavaImportsAnalyzer.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ******************************************************************************/ +package org.apache.sling.scripting.sightly.java.compiler; + +/** + * The {@code JavaImportsAnalyzer} allows checking imports in generated HTL Java classes, in order to optimise dependencies. + */ +public interface JavaImportsAnalyzer { + + /** + * Analyses the provided {@code importedClass} and decides if this class should be an explicit import or not in the generated HTL + * Java class. + * + * @param importedClass the import to analyse + * @return {@code true} if the import should be declared, {@code false} otherwise + */ + default boolean allowImport(String importedClass) { + return true; + } + +} diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/CodeGenVisitor.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/CodeGenVisitor.java index a619ff6..629f9ac 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/CodeGenVisitor.java +++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/CodeGenVisitor.java @@ -117,7 +117,7 @@ public class CodeGenVisitor implements CommandVisitor { @Override public void visit(VariableBinding.Start variableBinding) { source.startBlock(); - TypeInfo typeInfo = TypeInference.inferTypes(variableBinding.getExpression(), analyzer); + TypeInfo typeInfo = TypeInference.inferTypes(variableBinding.getExpression(), analyzer, unitBuilder.getImports()); Type type = typeInfo.typeOf(variableBinding.getExpression()); String properName = declare(variableBinding.getVariableName(), type); source.beginAssignment(properName, type.getNativeClass()); @@ -142,7 +142,7 @@ public class CodeGenVisitor implements CommandVisitor { @Override public void visit(VariableBinding.Global globalAssignment) { - TypeInfo typeInfo = TypeInference.inferTypes(globalAssignment.getExpression(), analyzer); + TypeInfo typeInfo = TypeInference.inferTypes(globalAssignment.getExpression(), analyzer, unitBuilder.getImports()); VariableDescriptor descriptor = analyzer.declareGlobal(globalAssignment.getVariableName()); String name = descriptor.getAssignedName(); source.append(name).assign(); diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/JavaClassTemplate.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/JavaClassTemplate.java index 34be88b..85a0236 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/JavaClassTemplate.java +++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/JavaClassTemplate.java @@ -23,10 +23,10 @@ public class JavaClassTemplate { private String classTemplate; - - private static final String MAIN_BODY = "MainBody"; - private static final String CLASS_NAME = "ClassName"; private static final String PACKAGE_NAME = "PackageName"; + private static final String IMPORTS = "Imports"; + private static final String CLASS_NAME = "ClassName"; + private static final String MAIN_BODY = "MainBody"; private static final String TEMPLATE_INIT = "SubTemplateMapInit"; private static final String NAME = "Name"; @@ -52,6 +52,10 @@ public class JavaClassTemplate { setPart(PACKAGE_NAME, name); } + public void setImports(String imports) { + setPart(IMPORTS, imports); + } + @Override public String toString() { return insertPart(TEMPLATE_INIT, classTemplate, templateInitBuilder.toString()); diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/Type.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/Type.java index e73d5e5..187c650 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/Type.java +++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/Type.java @@ -20,27 +20,38 @@ package org.apache.sling.scripting.sightly.java.compiler.impl; /** * Type inferred for an expression */ -public enum Type { - UNKNOWN("Object", false), - STRING("String", false), - LONG("long", true), - DOUBLE("double", true), - BOOLEAN("boolean", true), - MAP("java.util.Map", false); - - private final String nativeClass; +public class Type { + + public static final Type UNKNOWN = new Type("Object", false, null); + public static final Type STRING = new Type("String", false, null); + public static final Type LONG = new Type("long", true, 0); + public static final Type DOUBLE = new Type("double", true, 0.0d); + public static final Type BOOLEAN = new Type("boolean", true, false); + public static final Type MAP = new Type("java.util.Map", false, null); + + private String nativeClass; private final boolean isPrimitive; + private final Object defaultValue; - Type(String nativeClass, boolean isPrimitive) { + private Type(String nativeClass, boolean isPrimitive, Object defaultValue) { this.nativeClass = nativeClass; this.isPrimitive = isPrimitive; + this.defaultValue = defaultValue; } public String getNativeClass() { return nativeClass; } + public Object getDefaultValue() { + return defaultValue; + } + public boolean isPrimitive() { return isPrimitive; } + + public static Type dynamic(String type) { + return new Type(type, false, null); + } } diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/TypeInference.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/TypeInference.java index 39377b8..6511de3 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/TypeInference.java +++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/TypeInference.java @@ -19,10 +19,10 @@ package org.apache.sling.scripting.sightly.java.compiler.impl; import java.util.IdentityHashMap; import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; -import org.apache.sling.scripting.sightly.java.compiler.impl.operator.BinaryOpGen; -import org.apache.sling.scripting.sightly.java.compiler.impl.operator.Operators; -import org.apache.sling.scripting.sightly.java.compiler.impl.operator.UnaryOpGen; +import org.apache.sling.scripting.sightly.compiler.RuntimeFunction; import org.apache.sling.scripting.sightly.compiler.expression.ExpressionNode; import org.apache.sling.scripting.sightly.compiler.expression.NodeVisitor; import org.apache.sling.scripting.sightly.compiler.expression.nodes.ArrayLiteral; @@ -37,6 +37,9 @@ import org.apache.sling.scripting.sightly.compiler.expression.nodes.RuntimeCall; import org.apache.sling.scripting.sightly.compiler.expression.nodes.StringConstant; import org.apache.sling.scripting.sightly.compiler.expression.nodes.TernaryOperator; import org.apache.sling.scripting.sightly.compiler.expression.nodes.UnaryOperation; +import org.apache.sling.scripting.sightly.java.compiler.impl.operator.BinaryOpGen; +import org.apache.sling.scripting.sightly.java.compiler.impl.operator.Operators; +import org.apache.sling.scripting.sightly.java.compiler.impl.operator.UnaryOpGen; /** * Expression translator which uses type information @@ -44,17 +47,20 @@ import org.apache.sling.scripting.sightly.compiler.expression.nodes.UnaryOperati public final class TypeInference implements NodeVisitor<Type> { private final VariableAnalyzer analyzer; - private final Map<ExpressionNode, Type> inferMap = new IdentityHashMap<ExpressionNode, Type>(); + private final Map<ExpressionNode, Type> inferMap = new IdentityHashMap<>(); + private final Set<String> imports; + private static final Pattern FQCN_PATTERN = Pattern.compile("([[\\p{L}&&[^\\p{Lu}]]_$][\\p{L}\\p{N}_$]*\\.)+[\\p{Lu}_$][\\p{L}\\p{N}_$]*"); - public static TypeInfo inferTypes(ExpressionNode node, VariableAnalyzer analyzer) { - TypeInference typeInference = new TypeInference(analyzer); + public static TypeInfo inferTypes(ExpressionNode node, VariableAnalyzer analyzer, Set<String> imports) { + TypeInference typeInference = new TypeInference(analyzer, imports); typeInference.infer(node); return new TypeInfo(typeInference.inferMap); } - private TypeInference(VariableAnalyzer analyzer) { + private TypeInference(VariableAnalyzer analyzer, Set<String> imports) { this.analyzer = analyzer; + this.imports = imports; } @@ -128,6 +134,16 @@ public final class TypeInference implements NodeVisitor<Type> { @Override public Type evaluate(RuntimeCall runtimeCall) { inferAll(runtimeCall.getArguments()); + if (runtimeCall.getFunctionName().equals(RuntimeFunction.USE)) { + ExpressionNode identifier = runtimeCall.getArguments().get(0); + if (identifier instanceof StringConstant) { + String objectType = ((StringConstant) identifier).getText(); + if (FQCN_PATTERN.matcher(objectType).matches()) { + imports.add(objectType); + return Type.dynamic(objectType); + } + } + } return Type.UNKNOWN; } diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/UnitBuilder.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/UnitBuilder.java index 990bf8c..3a7678c 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/UnitBuilder.java +++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/UnitBuilder.java @@ -19,10 +19,12 @@ package org.apache.sling.scripting.sightly.java.compiler.impl; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.sling.scripting.sightly.java.compiler.CompilationOutput; +import org.apache.sling.scripting.sightly.java.compiler.JavaImportsAnalyzer; /** * Builder for compiled sources @@ -32,9 +34,12 @@ public class UnitBuilder { private final JavaSource source = new JavaSource(); private final Set<String> parameters; private final Map<String, UnitBuilder> subTemplates = new HashMap<String, UnitBuilder>(); + private Set<String> imports = new HashSet<>(); + private JavaImportsAnalyzer javaImportsAnalyzer; - public UnitBuilder() { - this(Collections.<String>emptySet()); + public UnitBuilder(JavaImportsAnalyzer javaImportsAnalyzer) { + this(Collections.emptySet()); + this.javaImportsAnalyzer = javaImportsAnalyzer; } public UnitBuilder(Set<String> parameters) { @@ -62,4 +67,12 @@ public class UnitBuilder { } return new CompilationOutputImpl(source.toString(), map); } + + public JavaImportsAnalyzer getJavaImportsAnalyzer() { + return javaImportsAnalyzer; + } + + public Set<String> getImports() { + return imports; + } } diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/VariableDescriptor.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/VariableDescriptor.java index 51193d6..800a5bd 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/VariableDescriptor.java +++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/impl/VariableDescriptor.java @@ -78,7 +78,7 @@ public class VariableDescriptor { } /** - * Get the inferred type fot this variable + * Get the inferred type for this variable * @return - the class of the variable */ public Type getType() { diff --git a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/package-info.java b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/package-info.java index 4502fd2..45ddcbe 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/java/compiler/package-info.java +++ b/src/main/java/org/apache/sling/scripting/sightly/java/compiler/package-info.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ -@Version("1.1.0") +@Version("1.2.0") package org.apache.sling.scripting.sightly.java.compiler; import org.osgi.annotation.versioning.Version; diff --git a/src/main/resources/templates/compiled_unit_template.txt b/src/main/resources/templates/compiled_unit_template.txt index a327d6a..3ce6585 100644 --- a/src/main/resources/templates/compiled_unit_template.txt +++ b/src/main/resources/templates/compiled_unit_template.txt @@ -25,6 +25,8 @@ import javax.script.Bindings; import org.apache.sling.scripting.sightly.java.compiler.RenderUnit; import org.apache.sling.scripting.sightly.render.RenderContext; +##Imports## + public final class ##ClassName## extends RenderUnit { @Override diff --git a/src/test/java/org/apache/sling/scripting/sightly/compiler/java/JavaClassBackendCompilerTest.java b/src/test/java/org/apache/sling/scripting/sightly/compiler/java/JavaClassBackendCompilerTest.java index 3dd3c8c..924e519 100644 --- a/src/test/java/org/apache/sling/scripting/sightly/compiler/java/JavaClassBackendCompilerTest.java +++ b/src/test/java/org/apache/sling/scripting/sightly/compiler/java/JavaClassBackendCompilerTest.java @@ -93,6 +93,18 @@ public class JavaClassBackendCompilerTest { assertEquals(expectedOutput, writer.toString()); } + @Test + public void generateImportStatements() throws Exception { + CompilationUnit compilationUnit = TestUtils.readScriptFromClasspath("/imports.html"); + JavaClassBackendCompiler backendCompiler = new JavaClassBackendCompiler(); + SightlyCompiler sightlyCompiler = new SightlyCompiler(); + sightlyCompiler.compile(compilationUnit, backendCompiler); + ClassInfo classInfo = buildClassInfo("imports"); + String source = backendCompiler.build(classInfo); + String expectedJavaOutput = IOUtils.toString(this.getClass().getResourceAsStream("/imports.html.java"), "UTF-8"); + assertEquals(expectedJavaOutput, source); + } + private ClassInfo buildClassInfo(final String info) { return new ClassInfo() { @Override diff --git a/src/test/resources/imports.html b/src/test/resources/imports.html new file mode 100644 index 0000000..82d1905 --- /dev/null +++ b/src/test/resources/imports.html @@ -0,0 +1,22 @@ +<!--/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ Licensed to the Apache Software Foundation (ASF) under one + ~ or more contributor license agreements. See the NOTICE file + ~ distributed with this work for additional information + ~ regarding copyright ownership. The ASF licenses this file + ~ to you under the Apache License, Version 2.0 (the + ~ "License"); you may not use this file except in compliance + ~ with the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, + ~ software distributed under the License is distributed on an + ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + ~ KIND, either express or implied. See the License for the + ~ specific language governing permissions and limitations + ~ under the License. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/--> +<div data-sly-use.slingSettings="org.apache.sling.settings.SlingSettingsService" + data-sly-use.js="script.js" + data-sly-use.pojo="Pojo" +></div> diff --git a/src/main/resources/templates/compiled_unit_template.txt b/src/test/resources/imports.html.java similarity index 77% copy from src/main/resources/templates/compiled_unit_template.txt copy to src/test/resources/imports.html.java index a327d6a..f80f7db 100644 --- a/src/main/resources/templates/compiled_unit_template.txt +++ b/src/test/resources/imports.html.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. ******************************************************************************/ -package ##PackageName##; +package org.apache.sling.scripting.sightly.compiler.java; import java.io.PrintWriter; import java.util.Collection; @@ -25,7 +25,10 @@ import javax.script.Bindings; import org.apache.sling.scripting.sightly.java.compiler.RenderUnit; import org.apache.sling.scripting.sightly.render.RenderContext; -public final class ##ClassName## extends RenderUnit { +import org.apache.sling.settings.SlingSettingsService; + + +public final class Test_imports extends RenderUnit { @Override protected final void render(PrintWriter out, @@ -34,7 +37,15 @@ public final class ##ClassName## extends RenderUnit { RenderContext renderContext) { // Main Template Body ----------------------------------------------------------------------------- -##MainBody## +Object _global_slingsettings = null; +Object _global_js = null; +Object _global_pojo = null; +out.write("\n"); +_global_slingsettings = renderContext.call("use", "org.apache.sling.settings.SlingSettingsService", obj()); +_global_js = renderContext.call("use", "script.js", obj()); +_global_pojo = renderContext.call("use", "Pojo", obj()); +out.write("<div></div>\n"); + // End Of Main Template Body ---------------------------------------------------------------------- } @@ -44,7 +55,7 @@ public final class ##ClassName## extends RenderUnit { { //Sub-Templates Initialization -------------------------------------------------------------------- -##SubTemplateMapInit## + //End of Sub-Templates Initialization ------------------------------------------------------------- } -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
