diff --git a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/AppendOrAddStatementFactory.java b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/AppendOrAddStatementFactory.java index 8614d91..eaa7123 100644 --- a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/AppendOrAddStatementFactory.java +++ b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/AppendOrAddStatementFactory.java @@ -1,7 +1,6 @@ package groowt.view.component.web.transpile; import groowt.view.component.web.ast.node.BodyChildNode; -import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState; import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.stmt.Statement; diff --git a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/BodyTranspiler.java b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/BodyTranspiler.java index 3f291aa..51e7d8c 100644 --- a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/BodyTranspiler.java +++ b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/BodyTranspiler.java @@ -2,7 +2,6 @@ package groowt.view.component.web.transpile; import groowt.view.component.web.ast.node.BodyChildNode; import groowt.view.component.web.ast.node.BodyNode; -import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState; import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.stmt.BlockStatement; import org.codehaus.groovy.ast.stmt.Statement; diff --git a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/ComponentTranspiler.java b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/ComponentTranspiler.java index 21284e8..a8b785c 100644 --- a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/ComponentTranspiler.java +++ b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/ComponentTranspiler.java @@ -1,7 +1,6 @@ package groowt.view.component.web.transpile; import groowt.view.component.web.ast.node.ComponentNode; -import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState; import org.codehaus.groovy.ast.stmt.Statement; import java.util.List; diff --git a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultAppendOrAddStatementFactory.java b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultAppendOrAddStatementFactory.java index 95119d6..fe90a74 100644 --- a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultAppendOrAddStatementFactory.java +++ b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultAppendOrAddStatementFactory.java @@ -2,7 +2,6 @@ package groowt.view.component.web.transpile; import groovy.lang.Tuple2; import groowt.view.component.web.ast.node.BodyChildNode; -import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState; import org.codehaus.groovy.ast.expr.*; import org.codehaus.groovy.ast.stmt.ExpressionStatement; import org.codehaus.groovy.ast.stmt.Statement; diff --git a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultBodyTranspiler.java b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultBodyTranspiler.java index 389c1ca..695e3aa 100644 --- a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultBodyTranspiler.java +++ b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultBodyTranspiler.java @@ -2,7 +2,6 @@ package groowt.view.component.web.transpile; import groowt.view.component.web.WebViewComponentBugError; import groowt.view.component.web.ast.node.*; -import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState; import jakarta.inject.Inject; import org.codehaus.groovy.ast.expr.GStringExpression; import org.codehaus.groovy.ast.stmt.BlockStatement; diff --git a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultValueNodeTranspiler.java b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultValueNodeTranspiler.java index 30dd9ad..25b346f 100644 --- a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultValueNodeTranspiler.java +++ b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/DefaultValueNodeTranspiler.java @@ -2,7 +2,6 @@ package groowt.view.component.web.transpile; import groowt.view.component.web.WebViewComponentBugError; import groowt.view.component.web.ast.node.*; -import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState; import groowt.view.component.web.transpile.groovy.GroovyUtil; import groowt.view.component.web.transpile.groovy.GroovyUtil.ConvertResult; import org.codehaus.groovy.ast.Parameter; diff --git a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/TranspilerState.java b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/TranspilerState.java new file mode 100644 index 0000000..df61949 --- /dev/null +++ b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/TranspilerState.java @@ -0,0 +1,161 @@ +package groowt.view.component.web.transpile; + +import groowt.view.component.compiler.ComponentTemplateCompileException; +import org.codehaus.groovy.ast.Parameter; +import org.codehaus.groovy.ast.Variable; +import org.codehaus.groovy.ast.VariableScope; +import org.codehaus.groovy.ast.expr.VariableExpression; +import org.jetbrains.annotations.TestOnly; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; + +public final class TranspilerState { + + public static TranspilerState withRootScope( + Parameter componentContext, + Parameter writer, + Variable renderContext + ) { + final VariableScope rootScope = new VariableScope(); + rootScope.putDeclaredVariable(componentContext); + rootScope.putDeclaredVariable(writer); + rootScope.putDeclaredVariable(renderContext); + + return new TranspilerState(rootScope); + } + + @TestOnly + public static TranspilerState withDefaultRootScope() { + final VariableScope rootScope = new VariableScope(); + rootScope.putDeclaredVariable(new Parameter( + TranspilerUtil.COMPONENT_CONTEXT_TYPE, + TranspilerUtil.COMPONENT_CONTEXT_NAME + )); + rootScope.putDeclaredVariable(new Parameter( + TranspilerUtil.COMPONENT_WRITER_TYPE, + TranspilerUtil.COMPONENT_WRITER_NAME + )); + rootScope.putDeclaredVariable(new VariableExpression( + TranspilerUtil.RENDER_CONTEXT_NAME, + TranspilerUtil.WEB_VIEW_COMPONENT_RENDER_CONTEXT_TYPE + )); + return new TranspilerState(rootScope); + } + + private final AtomicInteger componentNumberCounter = new AtomicInteger(); + private final Deque scopeStack = new LinkedList<>(); + private final Deque componentStack = new LinkedList<>(); + private final Deque resolvedStack = new LinkedList<>(); + private final Deque childListStack = new LinkedList<>(); + private final List errors = new ArrayList<>(); + + private int lastComponentNumber; + + private TranspilerState(VariableScope rootScope) { + this.scopeStack.push(rootScope); + } + + public int getCurrentComponentNumber() { + return this.lastComponentNumber; + } + + public int newComponentNumber() { + this.lastComponentNumber = this.componentNumberCounter.getAndIncrement(); + return this.lastComponentNumber; + } + + public VariableScope pushScope() { + final VariableScope parent = this.scopeStack.peek(); + final VariableScope result = new VariableScope(parent); + this.scopeStack.push(result); + return result; + } + + public void popScope() { + this.scopeStack.pop(); + } + + public VariableScope getCurrentScope() { + return Objects.requireNonNull(this.scopeStack.peek()); + } + + private Variable getDeclaredVariable(String name) { + VariableScope scope = this.getCurrentScope(); + while (scope != null) { + final Variable potential = scope.getDeclaredVariable(name); + if (potential != null) { + return potential; + } else { + scope = scope.getParent(); + } + } + throw new NullPointerException("Cannot find variable: " + name); + } + + public VariableExpression getWriter() { + return new VariableExpression(this.getDeclaredVariable(TranspilerUtil.COMPONENT_WRITER_NAME)); + } + + public VariableExpression getRenderContext() { + return (VariableExpression) this.getDeclaredVariable(TranspilerUtil.RENDER_CONTEXT_NAME); + } + + public void pushComponent(VariableExpression componentVariable) { + this.componentStack.push(componentVariable); + } + + public void popComponent() { + this.componentStack.pop(); + } + + public VariableExpression getCurrentComponent() { + return Objects.requireNonNull(this.componentStack.peek()); + } + + public void pushResolved(VariableExpression resolvedVariable) { + this.resolvedStack.push(resolvedVariable); + } + + public void popResolved() { + this.resolvedStack.pop(); + } + + public VariableExpression getCurrentResolved() { + return Objects.requireNonNull(this.resolvedStack.peek()); + } + + public void pushChildList(Parameter childCollector) { + this.childListStack.push(childCollector); + } + + public void popChildList() { + this.childListStack.pop(); + } + + public VariableExpression getCurrentChildList() { + final Parameter childCollectorParam = Objects.requireNonNull(this.childListStack.peek()); + return new VariableExpression(childCollectorParam); + } + + public boolean hasCurrentChildList() { + return this.childListStack.peek() != null; + } + + public void addError(ComponentTemplateCompileException error) { + this.errors.add(error); + } + + public void addErrors(Collection errors) { + this.errors.addAll(errors); + } + + public boolean hasErrors() { + return !this.errors.isEmpty(); + } + + public List getErrors() { + return new ArrayList<>(this.errors); + } + +} diff --git a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/TranspilerUtil.java b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/TranspilerUtil.java index b19da46..59cb038 100644 --- a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/TranspilerUtil.java +++ b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/TranspilerUtil.java @@ -2,21 +2,16 @@ package groowt.view.component.web.transpile; import groovy.lang.Tuple2; import groowt.view.component.ComponentTemplate; -import groowt.view.component.compiler.ComponentTemplateCompileException; import groowt.view.component.context.ComponentContext; import groowt.view.component.runtime.ComponentWriter; import groowt.view.component.web.runtime.DefaultWebViewRenderContext; import groowt.view.component.web.runtime.WebViewComponentRenderContext; import groowt.view.component.web.util.SourcePosition; -import org.codehaus.groovy.ast.*; +import org.codehaus.groovy.ast.ClassHelper; +import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.expr.ConstantExpression; -import org.codehaus.groovy.ast.expr.VariableExpression; import org.codehaus.groovy.syntax.Token; import org.codehaus.groovy.syntax.Types; -import org.jetbrains.annotations.TestOnly; - -import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; public final class TranspilerUtil { @@ -57,149 +52,6 @@ public final class TranspilerUtil { return new Token(Types.LEFT_SHIFT, "<<", -1, -1); } - public static final class TranspilerState { - - public static TranspilerState withRootScope( - Parameter componentContext, - Parameter writer, - Variable renderContext - ) { - final VariableScope rootScope = new VariableScope(); - rootScope.putDeclaredVariable(componentContext); - rootScope.putDeclaredVariable(writer); - rootScope.putDeclaredVariable(renderContext); - - return new TranspilerState(rootScope); - } - - @TestOnly - public static TranspilerState withDefaultRootScope() { - final VariableScope rootScope = new VariableScope(); - rootScope.putDeclaredVariable(new Parameter(COMPONENT_CONTEXT_TYPE, COMPONENT_CONTEXT_NAME)); - rootScope.putDeclaredVariable(new Parameter(COMPONENT_WRITER_TYPE, COMPONENT_WRITER_NAME)); - rootScope.putDeclaredVariable(new VariableExpression(RENDER_CONTEXT_NAME, - WEB_VIEW_COMPONENT_RENDER_CONTEXT_TYPE - )); - return new TranspilerState(rootScope); - } - - private final AtomicInteger componentNumberCounter = new AtomicInteger(); - private final Deque scopeStack = new LinkedList<>(); - private final Deque componentStack = new LinkedList<>(); - private final Deque resolvedStack = new LinkedList<>(); - private final Deque childListStack = new LinkedList<>(); - private final List errors = new ArrayList<>(); - - private int lastComponentNumber; - - private TranspilerState(VariableScope rootScope) { - this.scopeStack.push(rootScope); - } - - public int getCurrentComponentNumber() { - return this.lastComponentNumber; - } - - public int newComponentNumber() { - this.lastComponentNumber = this.componentNumberCounter.getAndIncrement(); - return this.lastComponentNumber; - } - - public VariableScope pushScope() { - final VariableScope parent = this.scopeStack.peek(); - final VariableScope result = new VariableScope(parent); - this.scopeStack.push(result); - return result; - } - - public void popScope() { - this.scopeStack.pop(); - } - - public VariableScope getCurrentScope() { - return Objects.requireNonNull(this.scopeStack.peek()); - } - - private Variable getDeclaredVariable(String name) { - VariableScope scope = this.getCurrentScope(); - while (scope != null) { - final Variable potential = scope.getDeclaredVariable(name); - if (potential != null) { - return potential; - } else { - scope = scope.getParent(); - } - } - throw new NullPointerException("Cannot find variable: " + name); - } - - public VariableExpression getWriter() { - return new VariableExpression(this.getDeclaredVariable(COMPONENT_WRITER_NAME)); - } - - public VariableExpression getRenderContext() { - return (VariableExpression) this.getDeclaredVariable(RENDER_CONTEXT_NAME); - } - - public void pushComponent(VariableExpression componentVariable) { - this.componentStack.push(componentVariable); - } - - public void popComponent() { - this.componentStack.pop(); - } - - public VariableExpression getCurrentComponent() { - return Objects.requireNonNull(this.componentStack.peek()); - } - - public void pushResolved(VariableExpression resolvedVariable) { - this.resolvedStack.push(resolvedVariable); - } - - public void popResolved() { - this.resolvedStack.pop(); - } - - public VariableExpression getCurrentResolved() { - return Objects.requireNonNull(this.resolvedStack.peek()); - } - - public void pushChildList(Parameter childCollector) { - this.childListStack.push(childCollector); - } - - public void popChildList() { - this.childListStack.pop(); - } - - public VariableExpression getCurrentChildList() { - final Parameter childCollectorParam = Objects.requireNonNull(this.childListStack.peek()); - return new VariableExpression(childCollectorParam); - } - - public boolean hasCurrentChildList() { - return this.childListStack.peek() != null; - } - - public void addError(ComponentTemplateCompileException error) { - this.errors.add(error); - } - - public void addErrors(Collection errors) { - this.errors.addAll(errors); - } - - public boolean hasErrors() { - return !this.errors.isEmpty(); - } - - public List getErrors() { - return new ArrayList<>(this.errors); - } - - } - private TranspilerUtil() {} } diff --git a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/ValueNodeTranspiler.java b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/ValueNodeTranspiler.java index 4b2a1bb..2e8eedc 100644 --- a/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/ValueNodeTranspiler.java +++ b/web-view-components-compiler/src/main/java/groowt/view/component/web/transpile/ValueNodeTranspiler.java @@ -1,7 +1,6 @@ package groowt.view.component.web.transpile; import groowt.view.component.web.ast.node.ValueNode; -import groowt.view.component.web.transpile.TranspilerUtil.TranspilerState; import org.codehaus.groovy.ast.expr.Expression; public interface ValueNodeTranspiler { diff --git a/web-view-components-compiler/src/testFixtures/java/groowt/view/component/web/transpiler/BodyTranspilerTests.java b/web-view-components-compiler/src/testFixtures/java/groowt/view/component/web/transpiler/BodyTranspilerTests.java index 7ab2ffa..4c33682 100644 --- a/web-view-components-compiler/src/testFixtures/java/groowt/view/component/web/transpiler/BodyTranspilerTests.java +++ b/web-view-components-compiler/src/testFixtures/java/groowt/view/component/web/transpiler/BodyTranspilerTests.java @@ -8,7 +8,7 @@ import groowt.view.component.web.ast.node.BodyNode; import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit; import groowt.view.component.web.transpile.BodyTranspiler; import groowt.view.component.web.transpile.TranspilerConfiguration; -import groowt.view.component.web.transpile.TranspilerUtil; +import groowt.view.component.web.transpile.TranspilerState; import org.codehaus.groovy.ast.ModuleNode; import org.codehaus.groovy.ast.expr.ConstantExpression; import org.codehaus.groovy.ast.expr.MethodCallExpression; @@ -67,12 +67,12 @@ public abstract class BodyTranspilerTests { final var buildResult = this.build(source); final var configuration = this.getConfiguration(compileUnit, moduleNode); final var transpiler = this.getBodyTranspiler(configuration); - final var state = TranspilerUtil.TranspilerState.withDefaultRootScope(); + final var state = TranspilerState.withDefaultRootScope(); final var addOrAppend = configuration.getAppendOrAddStatementFactory(); final BlockStatement blockStatement = transpiler.transpileBody( buildResult.bodyNode(), (node, expression) -> addOrAppend.addOrAppend(node, state, ignored -> expression), - TranspilerUtil.TranspilerState.withDefaultRootScope() + TranspilerState.withDefaultRootScope() ); assertEquals(1, blockStatement.getStatements().size()); } @@ -86,12 +86,12 @@ public abstract class BodyTranspilerTests { final var buildResult = this.build(source); final var configuration = this.getConfiguration(compileUnit, moduleNode); final var transpiler = this.getBodyTranspiler(configuration); - final var state = TranspilerUtil.TranspilerState.withDefaultRootScope(); + final var state = TranspilerState.withDefaultRootScope(); final var addOrAppend = configuration.getAppendOrAddStatementFactory(); final BlockStatement blockStatement = transpiler.transpileBody( buildResult.bodyNode(), (node, expression) -> addOrAppend.addOrAppend(node, state, ignored -> expression), - TranspilerUtil.TranspilerState.withDefaultRootScope() + TranspilerState.withDefaultRootScope() ); assertEquals(1, blockStatement.getStatements().size()); final var s0 = (ExpressionStatement) blockStatement.getStatements().getFirst();