mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-03 05:44:10 -08:00
JS: split SourceWriter into interface and implementation part
This commit is contained in:
parent
23ad999bbd
commit
8024d84ed5
|
@ -50,8 +50,8 @@ import org.teavm.backend.javascript.codegen.AliasProvider;
|
||||||
import org.teavm.backend.javascript.codegen.DefaultAliasProvider;
|
import org.teavm.backend.javascript.codegen.DefaultAliasProvider;
|
||||||
import org.teavm.backend.javascript.codegen.DefaultNamingStrategy;
|
import org.teavm.backend.javascript.codegen.DefaultNamingStrategy;
|
||||||
import org.teavm.backend.javascript.codegen.MinifyingAliasProvider;
|
import org.teavm.backend.javascript.codegen.MinifyingAliasProvider;
|
||||||
|
import org.teavm.backend.javascript.codegen.OutputSourceWriterBuilder;
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriterBuilder;
|
|
||||||
import org.teavm.backend.javascript.decompile.PreparedClass;
|
import org.teavm.backend.javascript.decompile.PreparedClass;
|
||||||
import org.teavm.backend.javascript.decompile.PreparedMethod;
|
import org.teavm.backend.javascript.decompile.PreparedMethod;
|
||||||
import org.teavm.backend.javascript.intrinsics.ref.ReferenceQueueGenerator;
|
import org.teavm.backend.javascript.intrinsics.ref.ReferenceQueueGenerator;
|
||||||
|
@ -414,14 +414,16 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
? new MinifyingAliasProvider(topLevelNameLimit)
|
? new MinifyingAliasProvider(topLevelNameLimit)
|
||||||
: new DefaultAliasProvider(topLevelNameLimit);
|
: new DefaultAliasProvider(topLevelNameLimit);
|
||||||
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, controller.getUnprocessedClassSource());
|
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, controller.getUnprocessedClassSource());
|
||||||
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
OutputSourceWriterBuilder builder = new OutputSourceWriterBuilder(naming);
|
||||||
builder.setMinified(obfuscated);
|
builder.setMinified(obfuscated);
|
||||||
SourceWriter sourceWriter = builder.build(writer);
|
var sourceWriter = builder.build(writer);
|
||||||
|
|
||||||
DebugInformationEmitter debugEmitterToUse = debugEmitter;
|
DebugInformationEmitter debugEmitterToUse = debugEmitter;
|
||||||
if (debugEmitterToUse == null) {
|
if (debugEmitterToUse == null) {
|
||||||
debugEmitterToUse = new DummyDebugInformationEmitter();
|
debugEmitterToUse = new DummyDebugInformationEmitter();
|
||||||
}
|
}
|
||||||
|
sourceWriter.setDebugInformationEmitter(debugEmitterToUse);
|
||||||
|
|
||||||
var virtualMethodContributorContext = new VirtualMethodContributorContextImpl(classes);
|
var virtualMethodContributorContext = new VirtualMethodContributorContextImpl(classes);
|
||||||
RenderingContext renderingContext = new RenderingContext(debugEmitterToUse,
|
RenderingContext renderingContext = new RenderingContext(debugEmitterToUse,
|
||||||
controller.getUnprocessedClassSource(), classes,
|
controller.getUnprocessedClassSource(), classes,
|
||||||
|
@ -454,7 +456,6 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
}
|
}
|
||||||
renderer.setDebugEmitter(debugEmitter);
|
renderer.setDebugEmitter(debugEmitter);
|
||||||
}
|
}
|
||||||
renderer.getDebugEmitter().setLocationProvider(sourceWriter);
|
|
||||||
for (var entry : methodInjectors.entrySet()) {
|
for (var entry : methodInjectors.entrySet()) {
|
||||||
renderingContext.addInjector(entry.getKey(), entry.getValue());
|
renderingContext.addInjector(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,279 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed 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.teavm.backend.javascript.codegen;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.teavm.debugging.information.DebugInformationEmitter;
|
||||||
|
import org.teavm.debugging.information.DummyDebugInformationEmitter;
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
public class OutputSourceWriter extends SourceWriter implements LocationProvider {
|
||||||
|
private final Appendable innerWriter;
|
||||||
|
private int indentSize;
|
||||||
|
private final NamingStrategy naming;
|
||||||
|
private boolean lineStart;
|
||||||
|
private boolean minified;
|
||||||
|
private final int lineWidth;
|
||||||
|
private int column;
|
||||||
|
private int line;
|
||||||
|
private int offset;
|
||||||
|
private DebugInformationEmitter debugInformationEmitter = new DummyDebugInformationEmitter();
|
||||||
|
|
||||||
|
OutputSourceWriter(NamingStrategy naming, Appendable innerWriter, int lineWidth) {
|
||||||
|
this.naming = naming;
|
||||||
|
this.innerWriter = innerWriter;
|
||||||
|
this.lineWidth = lineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugInformationEmitter(DebugInformationEmitter debugInformationEmitter) {
|
||||||
|
this.debugInformationEmitter = debugInformationEmitter;
|
||||||
|
debugInformationEmitter.setLocationProvider(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMinified(boolean minified) {
|
||||||
|
this.minified = minified;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter append(char value) {
|
||||||
|
appendIndent();
|
||||||
|
try {
|
||||||
|
innerWriter.append(value);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
if (value == '\n') {
|
||||||
|
newLine();
|
||||||
|
} else {
|
||||||
|
column++;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter append(CharSequence csq, int start, int end) {
|
||||||
|
int last = start;
|
||||||
|
for (int i = start; i < end; ++i) {
|
||||||
|
if (csq.charAt(i) == '\n') {
|
||||||
|
appendSingleLine(csq, last, i);
|
||||||
|
newLine();
|
||||||
|
last = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
appendSingleLine(csq, last, end);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendSingleLine(CharSequence csq, int start, int end) {
|
||||||
|
if (start == end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
appendIndent();
|
||||||
|
column += end - start;
|
||||||
|
offset += end - start;
|
||||||
|
try {
|
||||||
|
innerWriter.append(csq, start, end);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter appendClass(String cls) {
|
||||||
|
return appendName(naming.getNameFor(cls));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter appendField(FieldReference field) {
|
||||||
|
return append(naming.getNameFor(field));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter appendStaticField(FieldReference field) {
|
||||||
|
return appendName(naming.getFullNameFor(field));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter appendMethod(MethodDescriptor method) {
|
||||||
|
return append(naming.getNameFor(method));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter appendMethodBody(MethodReference method) {
|
||||||
|
return appendName(naming.getFullNameFor(method));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter appendFunction(String name) {
|
||||||
|
return append(naming.getNameForFunction(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter appendInit(MethodReference method) {
|
||||||
|
return appendName(naming.getNameForInit(method));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter appendClassInit(String className) {
|
||||||
|
return appendName(naming.getNameForClassInit(className));
|
||||||
|
}
|
||||||
|
|
||||||
|
private SourceWriter appendName(ScopedName name) {
|
||||||
|
if (name.scoped) {
|
||||||
|
append(naming.getScopeName()).append(".");
|
||||||
|
}
|
||||||
|
append(name.value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendIndent() {
|
||||||
|
if (minified) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (lineStart) {
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < indentSize; ++i) {
|
||||||
|
innerWriter.append(" ");
|
||||||
|
column += 4;
|
||||||
|
offset += 4;
|
||||||
|
}
|
||||||
|
lineStart = false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter newLine() {
|
||||||
|
try {
|
||||||
|
innerWriter.append('\n');
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
column = 0;
|
||||||
|
++line;
|
||||||
|
++offset;
|
||||||
|
lineStart = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter ws() {
|
||||||
|
if (column >= lineWidth) {
|
||||||
|
newLine();
|
||||||
|
} else {
|
||||||
|
if (!minified) {
|
||||||
|
try {
|
||||||
|
innerWriter.append(' ');
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
column++;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter tokenBoundary() {
|
||||||
|
if (column >= lineWidth) {
|
||||||
|
newLine();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter softNewLine() {
|
||||||
|
if (!minified) {
|
||||||
|
try {
|
||||||
|
innerWriter.append('\n');
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
column = 0;
|
||||||
|
++offset;
|
||||||
|
++line;
|
||||||
|
lineStart = true;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter indent() {
|
||||||
|
++indentSize;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter outdent() {
|
||||||
|
--indentSize;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter emitLocation(String fileName, int line) {
|
||||||
|
debugInformationEmitter.emitLocation(fileName, line);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter enterLocation() {
|
||||||
|
debugInformationEmitter.enterLocation();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter exitLocation() {
|
||||||
|
debugInformationEmitter.exitLocation();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SourceWriter emitStatementStart() {
|
||||||
|
debugInformationEmitter.emitStatementStart();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void emitMethod(MethodDescriptor method) {
|
||||||
|
debugInformationEmitter.emitMethod(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void emitClass(String className) {
|
||||||
|
debugInformationEmitter.emitClass(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLine() {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getColumn() {
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOffset() {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,12 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.javascript.codegen;
|
package org.teavm.backend.javascript.codegen;
|
||||||
|
|
||||||
public class SourceWriterBuilder {
|
public class OutputSourceWriterBuilder {
|
||||||
private NamingStrategy naming;
|
private NamingStrategy naming;
|
||||||
private boolean minified;
|
private boolean minified;
|
||||||
private int lineWidth = 512;
|
private int lineWidth = 512;
|
||||||
|
|
||||||
public SourceWriterBuilder(NamingStrategy naming) {
|
public OutputSourceWriterBuilder(NamingStrategy naming) {
|
||||||
this.naming = naming;
|
this.naming = naming;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ public class SourceWriterBuilder {
|
||||||
this.lineWidth = lineWidth;
|
this.lineWidth = lineWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter build(Appendable innerWriter) {
|
public OutputSourceWriter build(Appendable innerWriter) {
|
||||||
SourceWriter writer = new SourceWriter(naming, innerWriter, lineWidth);
|
var writer = new OutputSourceWriter(naming, innerWriter, lineWidth);
|
||||||
writer.setMinified(minified);
|
writer.setMinified(minified);
|
||||||
return writer;
|
return writer;
|
||||||
}
|
}
|
|
@ -15,33 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.javascript.codegen;
|
package org.teavm.backend.javascript.codegen;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
public class SourceWriter implements Appendable, LocationProvider {
|
public abstract class SourceWriter implements Appendable {
|
||||||
private final Appendable innerWriter;
|
|
||||||
private int indentSize;
|
|
||||||
private final NamingStrategy naming;
|
|
||||||
private boolean lineStart;
|
|
||||||
private boolean minified;
|
|
||||||
private final int lineWidth;
|
|
||||||
private int column;
|
|
||||||
private int line;
|
|
||||||
private int offset;
|
|
||||||
|
|
||||||
SourceWriter(NamingStrategy naming, Appendable innerWriter, int lineWidth) {
|
|
||||||
this.naming = naming;
|
|
||||||
this.innerWriter = innerWriter;
|
|
||||||
this.lineWidth = lineWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMinified(boolean minified) {
|
|
||||||
this.minified = minified;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter append(String value) {
|
public SourceWriter append(String value) {
|
||||||
append((CharSequence) value);
|
append((CharSequence) value);
|
||||||
return this;
|
return this;
|
||||||
|
@ -72,21 +51,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SourceWriter append(char value) {
|
public abstract SourceWriter append(char value);
|
||||||
appendIndent();
|
|
||||||
try {
|
|
||||||
innerWriter.append(value);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
if (value == '\n') {
|
|
||||||
newLine();
|
|
||||||
} else {
|
|
||||||
column++;
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SourceWriter append(CharSequence csq) {
|
public SourceWriter append(CharSequence csq) {
|
||||||
|
@ -95,60 +60,25 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SourceWriter append(CharSequence csq, int start, int end) {
|
public abstract SourceWriter append(CharSequence csq, int start, int end);
|
||||||
int last = start;
|
|
||||||
for (int i = start; i < end; ++i) {
|
|
||||||
if (csq.charAt(i) == '\n') {
|
|
||||||
appendSingleLine(csq, last, i);
|
|
||||||
newLine();
|
|
||||||
last = i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
appendSingleLine(csq, last, end);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendSingleLine(CharSequence csq, int start, int end) {
|
public abstract SourceWriter appendClass(String cls);
|
||||||
if (start == end) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
appendIndent();
|
|
||||||
column += end - start;
|
|
||||||
offset += end - start;
|
|
||||||
try {
|
|
||||||
innerWriter.append(csq, start, end);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter appendClass(String cls) {
|
|
||||||
return appendName(naming.getNameFor(cls));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter appendClass(Class<?> cls) {
|
public SourceWriter appendClass(Class<?> cls) {
|
||||||
return appendClass(cls.getName());
|
return appendClass(cls.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendField(FieldReference field) {
|
public abstract SourceWriter appendField(FieldReference field);
|
||||||
return append(naming.getNameFor(field));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter appendStaticField(FieldReference field) {
|
public abstract SourceWriter appendStaticField(FieldReference field);
|
||||||
return appendName(naming.getFullNameFor(field));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter appendMethod(MethodDescriptor method) {
|
public abstract SourceWriter appendMethod(MethodDescriptor method);
|
||||||
return append(naming.getNameFor(method));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter appendMethod(String name, Class<?>... params) {
|
public SourceWriter appendMethod(String name, Class<?>... params) {
|
||||||
return append(naming.getNameFor(new MethodDescriptor(name, params)));
|
return appendMethod(new MethodDescriptor(name, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendMethodBody(MethodReference method) {
|
public abstract SourceWriter appendMethodBody(MethodReference method);
|
||||||
return appendName(naming.getFullNameFor(method));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter appendMethodBody(String className, String name, ValueType... params) {
|
public SourceWriter appendMethodBody(String className, String name, ValueType... params) {
|
||||||
return appendMethodBody(new MethodReference(className, new MethodDescriptor(name, params)));
|
return appendMethodBody(new MethodReference(className, new MethodDescriptor(name, params)));
|
||||||
|
@ -158,122 +88,33 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
return appendMethodBody(new MethodReference(cls, name, params));
|
return appendMethodBody(new MethodReference(cls, name, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendFunction(String name) {
|
public abstract SourceWriter appendFunction(String name);
|
||||||
return append(naming.getNameForFunction(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter appendInit(MethodReference method) {
|
public abstract SourceWriter appendInit(MethodReference method);
|
||||||
return appendName(naming.getNameForInit(method));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter appendClassInit(String className) {
|
public abstract SourceWriter appendClassInit(String className);
|
||||||
return appendName(naming.getNameForClassInit(className));
|
|
||||||
}
|
|
||||||
|
|
||||||
private SourceWriter appendName(ScopedName name) {
|
public abstract SourceWriter newLine();
|
||||||
if (name.scoped) {
|
|
||||||
append(naming.getScopeName()).append(".");
|
|
||||||
}
|
|
||||||
append(name.value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void appendIndent() {
|
public abstract SourceWriter ws();
|
||||||
if (minified) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (lineStart) {
|
|
||||||
try {
|
|
||||||
for (int i = 0; i < indentSize; ++i) {
|
|
||||||
innerWriter.append(" ");
|
|
||||||
column += 4;
|
|
||||||
offset += 4;
|
|
||||||
}
|
|
||||||
lineStart = false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter newLine() {
|
public abstract SourceWriter tokenBoundary();
|
||||||
try {
|
|
||||||
innerWriter.append('\n');
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
column = 0;
|
|
||||||
++line;
|
|
||||||
++offset;
|
|
||||||
lineStart = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter ws() {
|
public abstract SourceWriter softNewLine();
|
||||||
if (column >= lineWidth) {
|
|
||||||
newLine();
|
|
||||||
} else {
|
|
||||||
if (!minified) {
|
|
||||||
try {
|
|
||||||
innerWriter.append(' ');
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
column++;
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter tokenBoundary() {
|
public abstract SourceWriter indent();
|
||||||
if (column >= lineWidth) {
|
|
||||||
newLine();
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter softNewLine() {
|
public abstract SourceWriter outdent();
|
||||||
if (!minified) {
|
|
||||||
try {
|
|
||||||
innerWriter.append('\n');
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
column = 0;
|
|
||||||
++offset;
|
|
||||||
++line;
|
|
||||||
lineStart = true;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter indent() {
|
public abstract SourceWriter emitLocation(String fileName, int line);
|
||||||
++indentSize;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter outdent() {
|
public abstract SourceWriter enterLocation();
|
||||||
--indentSize;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NamingStrategy getNaming() {
|
public abstract SourceWriter exitLocation();
|
||||||
return naming;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public abstract SourceWriter emitStatementStart();
|
||||||
public int getColumn() {
|
|
||||||
return column;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public abstract void emitMethod(MethodDescriptor method);
|
||||||
public int getLine() {
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public abstract void emitClass(String className);
|
||||||
public int getOffset() {
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.teavm.ast.Statement;
|
||||||
import org.teavm.ast.VariableNode;
|
import org.teavm.ast.VariableNode;
|
||||||
import org.teavm.backend.javascript.codegen.NamingOrderer;
|
import org.teavm.backend.javascript.codegen.NamingOrderer;
|
||||||
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
||||||
|
import org.teavm.backend.javascript.codegen.OutputSourceWriter;
|
||||||
import org.teavm.backend.javascript.codegen.ScopedName;
|
import org.teavm.backend.javascript.codegen.ScopedName;
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
import org.teavm.backend.javascript.decompile.PreparedClass;
|
import org.teavm.backend.javascript.decompile.PreparedClass;
|
||||||
|
@ -64,7 +65,7 @@ import org.teavm.vm.TeaVMProgressFeedback;
|
||||||
|
|
||||||
public class Renderer implements RenderingManager {
|
public class Renderer implements RenderingManager {
|
||||||
private final NamingStrategy naming;
|
private final NamingStrategy naming;
|
||||||
private final SourceWriter writer;
|
private final OutputSourceWriter writer;
|
||||||
private final ListableClassReaderSource classSource;
|
private final ListableClassReaderSource classSource;
|
||||||
private final ClassLoader classLoader;
|
private final ClassLoader classLoader;
|
||||||
private boolean minifying;
|
private boolean minifying;
|
||||||
|
@ -86,8 +87,8 @@ public class Renderer implements RenderingManager {
|
||||||
private boolean longLibraryUsed;
|
private boolean longLibraryUsed;
|
||||||
private boolean threadLibraryUsed;
|
private boolean threadLibraryUsed;
|
||||||
|
|
||||||
public Renderer(SourceWriter writer, Set<MethodReference> asyncMethods, Set<MethodReference> asyncFamilyMethods,
|
public Renderer(OutputSourceWriter writer, Set<MethodReference> asyncMethods,
|
||||||
Diagnostics diagnostics, RenderingContext context) {
|
Set<MethodReference> asyncFamilyMethods, Diagnostics diagnostics, RenderingContext context) {
|
||||||
this.naming = context.getNaming();
|
this.naming = context.getNaming();
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
this.classSource = context.getClassSource();
|
this.classSource = context.getClassSource();
|
||||||
|
|
|
@ -17,14 +17,11 @@ package org.teavm.backend.javascript.rendering;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayDeque;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Deque;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
||||||
|
@ -38,11 +35,9 @@ import org.teavm.interop.PlatformMarker;
|
||||||
import org.teavm.model.AnnotationReader;
|
import org.teavm.model.AnnotationReader;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.InliningInfo;
|
|
||||||
import org.teavm.model.ListableClassReaderSource;
|
import org.teavm.model.ListableClassReaderSource;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.TextLocation;
|
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.analysis.ClassInitializerInfo;
|
import org.teavm.model.analysis.ClassInitializerInfo;
|
||||||
|
|
||||||
|
@ -56,14 +51,12 @@ public abstract class RenderingContext {
|
||||||
private NamingStrategy naming;
|
private NamingStrategy naming;
|
||||||
private DependencyInfo dependencyInfo;
|
private DependencyInfo dependencyInfo;
|
||||||
private Predicate<MethodReference> virtualPredicate;
|
private Predicate<MethodReference> virtualPredicate;
|
||||||
private final Deque<LocationStackEntry> locationStack = new ArrayDeque<>();
|
|
||||||
private final Map<String, Integer> stringPoolMap = new HashMap<>();
|
private final Map<String, Integer> stringPoolMap = new HashMap<>();
|
||||||
private final List<String> stringPool = new ArrayList<>();
|
private final List<String> stringPool = new ArrayList<>();
|
||||||
private final List<String> readonlyStringPool = Collections.unmodifiableList(stringPool);
|
private final List<String> readonlyStringPool = Collections.unmodifiableList(stringPool);
|
||||||
private final Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
|
private final Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
|
||||||
private boolean minifying;
|
private boolean minifying;
|
||||||
private ClassInitializerInfo classInitializerInfo;
|
private ClassInitializerInfo classInitializerInfo;
|
||||||
private TextLocation lastEmittedLocation = TextLocation.EMPTY;
|
|
||||||
private boolean strict;
|
private boolean strict;
|
||||||
|
|
||||||
public RenderingContext(DebugInformationEmitter debugEmitter,
|
public RenderingContext(DebugInformationEmitter debugEmitter,
|
||||||
|
@ -129,83 +122,6 @@ public abstract class RenderingContext {
|
||||||
return classInitializerInfo.isDynamicInitializer(className);
|
return classInitializerInfo.isDynamicInitializer(className);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushLocation(TextLocation location) {
|
|
||||||
LocationStackEntry prevEntry = locationStack.peek();
|
|
||||||
if (location != null) {
|
|
||||||
if (prevEntry == null || !location.equals(prevEntry.location)) {
|
|
||||||
emitLocation(location);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (prevEntry != null) {
|
|
||||||
emitLocation(TextLocation.EMPTY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
locationStack.push(new LocationStackEntry(location));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void popLocation() {
|
|
||||||
LocationStackEntry prevEntry = locationStack.pop();
|
|
||||||
LocationStackEntry entry = locationStack.peek();
|
|
||||||
if (entry != null) {
|
|
||||||
if (!entry.location.equals(prevEntry.location)) {
|
|
||||||
emitLocation(entry.location);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
emitLocation(TextLocation.EMPTY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void emitLocation(TextLocation location) {
|
|
||||||
if (lastEmittedLocation.equals(location)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String fileName = lastEmittedLocation.getFileName();
|
|
||||||
int lineNumber = lastEmittedLocation.getLine();
|
|
||||||
if (lastEmittedLocation.getInlining() != location.getInlining()) {
|
|
||||||
InliningInfo[] newPath = location.getInliningPath();
|
|
||||||
InliningInfo[] prevPath = lastEmittedLocation.getInliningPath();
|
|
||||||
|
|
||||||
InliningInfo lastCommonInlining = null;
|
|
||||||
int pathIndex = 0;
|
|
||||||
while (pathIndex < prevPath.length && pathIndex < newPath.length
|
|
||||||
&& prevPath[pathIndex].equals(newPath[pathIndex])) {
|
|
||||||
lastCommonInlining = prevPath[pathIndex++];
|
|
||||||
}
|
|
||||||
|
|
||||||
InliningInfo prevInlining = lastEmittedLocation.getInlining();
|
|
||||||
while (prevInlining != lastCommonInlining) {
|
|
||||||
debugEmitter.exitLocation();
|
|
||||||
fileName = prevInlining.getFileName();
|
|
||||||
lineNumber = prevInlining.getLine();
|
|
||||||
prevInlining = prevInlining.getParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (pathIndex < newPath.length) {
|
|
||||||
InliningInfo inlining = newPath[pathIndex++];
|
|
||||||
emitSimpleLocation(fileName, lineNumber, inlining.getFileName(), inlining.getLine());
|
|
||||||
fileName = null;
|
|
||||||
lineNumber = -1;
|
|
||||||
|
|
||||||
debugEmitter.enterLocation();
|
|
||||||
debugEmitter.emitClass(inlining.getMethod().getClassName());
|
|
||||||
debugEmitter.emitMethod(inlining.getMethod().getDescriptor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emitSimpleLocation(fileName, lineNumber, location.getFileName(), location.getLine());
|
|
||||||
lastEmittedLocation = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void emitSimpleLocation(String fileName, int lineNumber, String newFileName, int newLineNumber) {
|
|
||||||
if (Objects.equals(fileName, newFileName) && lineNumber == newLineNumber) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
debugEmitter.emitLocation(newFileName, newLineNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMinifying() {
|
public boolean isMinifying() {
|
||||||
return minifying;
|
return minifying;
|
||||||
}
|
}
|
||||||
|
@ -367,14 +283,6 @@ public abstract class RenderingContext {
|
||||||
return minifying ? "$T" : "$thread";
|
return minifying ? "$T" : "$thread";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LocationStackEntry {
|
|
||||||
final TextLocation location;
|
|
||||||
|
|
||||||
LocationStackEntry(TextLocation location) {
|
|
||||||
this.location = location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addInjector(MethodReference method, Injector injector) {
|
public void addInjector(MethodReference method, Injector injector) {
|
||||||
injectorMap.put(method, new InjectorHolder(injector));
|
injectorMap.put(method, new InjectorHolder(injector));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,14 @@ package org.teavm.backend.javascript.rendering;
|
||||||
|
|
||||||
import com.carrotsearch.hppc.IntArrayList;
|
import com.carrotsearch.hppc.IntArrayList;
|
||||||
import com.carrotsearch.hppc.IntIndexedContainer;
|
import com.carrotsearch.hppc.IntIndexedContainer;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Deque;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import org.teavm.ast.ArrayFromDataExpr;
|
import org.teavm.ast.ArrayFromDataExpr;
|
||||||
import org.teavm.ast.AssignmentStatement;
|
import org.teavm.ast.AssignmentStatement;
|
||||||
|
@ -68,11 +71,10 @@ import org.teavm.backend.javascript.codegen.NamingStrategy;
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
import org.teavm.backend.javascript.spi.Injector;
|
import org.teavm.backend.javascript.spi.Injector;
|
||||||
import org.teavm.backend.javascript.spi.InjectorContext;
|
import org.teavm.backend.javascript.spi.InjectorContext;
|
||||||
import org.teavm.debugging.information.DebugInformationEmitter;
|
|
||||||
import org.teavm.debugging.information.DeferredCallSite;
|
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
|
import org.teavm.model.InliningInfo;
|
||||||
import org.teavm.model.ListableClassReaderSource;
|
import org.teavm.model.ListableClassReaderSource;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
|
@ -88,10 +90,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
private boolean async;
|
private boolean async;
|
||||||
private boolean minifying;
|
private boolean minifying;
|
||||||
private Precedence precedence;
|
private Precedence precedence;
|
||||||
private DebugInformationEmitter debugEmitter;
|
|
||||||
private NamingStrategy naming;
|
private NamingStrategy naming;
|
||||||
private DeferredCallSite lastCallSite;
|
|
||||||
private DeferredCallSite prevCallSite;
|
|
||||||
private boolean end;
|
private boolean end;
|
||||||
private final Map<String, String> blockIdMap = new HashMap<>();
|
private final Map<String, String> blockIdMap = new HashMap<>();
|
||||||
private int currentPart;
|
private int currentPart;
|
||||||
|
@ -100,6 +99,8 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
private boolean longLibraryUsed;
|
private boolean longLibraryUsed;
|
||||||
private static final MethodDescriptor CLINIT_METHOD = new MethodDescriptor("<clinit>", ValueType.VOID);
|
private static final MethodDescriptor CLINIT_METHOD = new MethodDescriptor("<clinit>", ValueType.VOID);
|
||||||
private VariableNameGenerator variableNameGenerator;
|
private VariableNameGenerator variableNameGenerator;
|
||||||
|
private final Deque<LocationStackEntry> locationStack = new ArrayDeque<>();
|
||||||
|
private TextLocation lastEmittedLocation = TextLocation.EMPTY;
|
||||||
|
|
||||||
public StatementRenderer(RenderingContext context, SourceWriter writer) {
|
public StatementRenderer(RenderingContext context, SourceWriter writer) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
@ -107,7 +108,6 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
this.classSource = context.getClassSource();
|
this.classSource = context.getClassSource();
|
||||||
this.minifying = context.isMinifying();
|
this.minifying = context.isMinifying();
|
||||||
this.naming = context.getNaming();
|
this.naming = context.getNaming();
|
||||||
this.debugEmitter = context.getDebugEmitter();
|
|
||||||
variableNameGenerator = new VariableNameGenerator(minifying);
|
variableNameGenerator = new VariableNameGenerator(minifying);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,21 +135,88 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
this.end = end;
|
this.end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pushLocation(TextLocation location) {
|
public void pushLocation(TextLocation location) {
|
||||||
context.pushLocation(location);
|
var prevEntry = locationStack.peek();
|
||||||
|
if (location != null) {
|
||||||
|
if (prevEntry == null || !location.equals(prevEntry.location)) {
|
||||||
|
emitLocation(location);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (prevEntry != null) {
|
||||||
|
emitLocation(TextLocation.EMPTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
locationStack.push(new LocationStackEntry(location));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void popLocation() {
|
public void popLocation() {
|
||||||
context.popLocation();
|
var prevEntry = locationStack.pop();
|
||||||
|
var entry = locationStack.peek();
|
||||||
|
if (entry != null) {
|
||||||
|
if (!entry.location.equals(prevEntry.location)) {
|
||||||
|
emitLocation(entry.location);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emitLocation(TextLocation.EMPTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void emitLocation(TextLocation location) {
|
||||||
|
if (lastEmittedLocation.equals(location)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String fileName = lastEmittedLocation.getFileName();
|
||||||
|
int lineNumber = lastEmittedLocation.getLine();
|
||||||
|
if (lastEmittedLocation.getInlining() != location.getInlining()) {
|
||||||
|
InliningInfo[] newPath = location.getInliningPath();
|
||||||
|
InliningInfo[] prevPath = lastEmittedLocation.getInliningPath();
|
||||||
|
|
||||||
|
InliningInfo lastCommonInlining = null;
|
||||||
|
int pathIndex = 0;
|
||||||
|
while (pathIndex < prevPath.length && pathIndex < newPath.length
|
||||||
|
&& prevPath[pathIndex].equals(newPath[pathIndex])) {
|
||||||
|
lastCommonInlining = prevPath[pathIndex++];
|
||||||
|
}
|
||||||
|
|
||||||
|
InliningInfo prevInlining = lastEmittedLocation.getInlining();
|
||||||
|
while (prevInlining != lastCommonInlining) {
|
||||||
|
writer.exitLocation();
|
||||||
|
fileName = prevInlining.getFileName();
|
||||||
|
lineNumber = prevInlining.getLine();
|
||||||
|
prevInlining = prevInlining.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pathIndex < newPath.length) {
|
||||||
|
InliningInfo inlining = newPath[pathIndex++];
|
||||||
|
emitSimpleLocation(fileName, lineNumber, inlining.getFileName(), inlining.getLine());
|
||||||
|
fileName = null;
|
||||||
|
lineNumber = -1;
|
||||||
|
|
||||||
|
writer.enterLocation();
|
||||||
|
writer.emitClass(inlining.getMethod().getClassName());
|
||||||
|
writer.emitMethod(inlining.getMethod().getDescriptor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emitSimpleLocation(fileName, lineNumber, location.getFileName(), location.getLine());
|
||||||
|
lastEmittedLocation = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void emitSimpleLocation(String fileName, int lineNumber, String newFileName, int newLineNumber) {
|
||||||
|
if (Objects.equals(fileName, newFileName) && lineNumber == newLineNumber) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.emitLocation(newFileName, newLineNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignmentStatement statement) throws RenderingException {
|
public void visit(AssignmentStatement statement) throws RenderingException {
|
||||||
debugEmitter.emitStatementStart();
|
writer.emitStatementStart();
|
||||||
if (statement.getLocation() != null) {
|
if (statement.getLocation() != null) {
|
||||||
pushLocation(statement.getLocation());
|
pushLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
prevCallSite = debugEmitter.emitCallSite();
|
|
||||||
if (statement.getLeftValue() != null) {
|
if (statement.getLeftValue() != null) {
|
||||||
if (statement.isAsync()) {
|
if (statement.isAsync()) {
|
||||||
writer.append(context.tempVarName());
|
writer.append(context.tempVarName());
|
||||||
|
@ -161,7 +228,6 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
precedence = Precedence.COMMA;
|
precedence = Precedence.COMMA;
|
||||||
statement.getRightValue().acceptVisitor(this);
|
statement.getRightValue().acceptVisitor(this);
|
||||||
debugEmitter.emitCallSite();
|
|
||||||
writer.append(";").softNewLine();
|
writer.append(";").softNewLine();
|
||||||
if (statement.isAsync()) {
|
if (statement.isAsync()) {
|
||||||
emitSuspendChecker();
|
emitSuspendChecker();
|
||||||
|
@ -185,18 +251,16 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
public void visit(ConditionalStatement statement) {
|
public void visit(ConditionalStatement statement) {
|
||||||
boolean needClosingBracket;
|
boolean needClosingBracket;
|
||||||
while (true) {
|
while (true) {
|
||||||
debugEmitter.emitStatementStart();
|
writer.emitStatementStart();
|
||||||
if (statement.getCondition().getLocation() != null) {
|
if (statement.getCondition().getLocation() != null) {
|
||||||
pushLocation(statement.getCondition().getLocation());
|
pushLocation(statement.getCondition().getLocation());
|
||||||
}
|
}
|
||||||
prevCallSite = debugEmitter.emitCallSite();
|
|
||||||
writer.append("if").ws().append("(");
|
writer.append("if").ws().append("(");
|
||||||
precedence = Precedence.COMMA;
|
precedence = Precedence.COMMA;
|
||||||
statement.getCondition().acceptVisitor(this);
|
statement.getCondition().acceptVisitor(this);
|
||||||
if (statement.getCondition().getLocation() != null) {
|
if (statement.getCondition().getLocation() != null) {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
debugEmitter.emitCallSite();
|
|
||||||
writer.append(")");
|
writer.append(")");
|
||||||
if (isSimpleIfContent(statement.getConsequent())) {
|
if (isSimpleIfContent(statement.getConsequent())) {
|
||||||
needClosingBracket = false;
|
needClosingBracket = false;
|
||||||
|
@ -250,21 +314,19 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SwitchStatement statement) {
|
public void visit(SwitchStatement statement) {
|
||||||
debugEmitter.emitStatementStart();
|
writer.emitStatementStart();
|
||||||
if (statement.getValue().getLocation() != null) {
|
if (statement.getValue().getLocation() != null) {
|
||||||
pushLocation(statement.getValue().getLocation());
|
pushLocation(statement.getValue().getLocation());
|
||||||
}
|
}
|
||||||
if (statement.getId() != null) {
|
if (statement.getId() != null) {
|
||||||
writer.append(mapBlockId(statement.getId())).append(":").ws();
|
writer.append(mapBlockId(statement.getId())).append(":").ws();
|
||||||
}
|
}
|
||||||
prevCallSite = debugEmitter.emitCallSite();
|
|
||||||
writer.append("switch").ws().append("(");
|
writer.append("switch").ws().append("(");
|
||||||
precedence = Precedence.min();
|
precedence = Precedence.min();
|
||||||
statement.getValue().acceptVisitor(this);
|
statement.getValue().acceptVisitor(this);
|
||||||
if (statement.getValue().getLocation() != null) {
|
if (statement.getValue().getLocation() != null) {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
debugEmitter.emitCallSite();
|
|
||||||
writer.append(")").ws().append("{").softNewLine().indent();
|
writer.append(")").ws().append("{").softNewLine().indent();
|
||||||
for (SwitchClause clause : statement.getClauses()) {
|
for (SwitchClause clause : statement.getClauses()) {
|
||||||
for (int condition : clause.getConditions()) {
|
for (int condition : clause.getConditions()) {
|
||||||
|
@ -294,17 +356,15 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(WhileStatement statement) {
|
public void visit(WhileStatement statement) {
|
||||||
debugEmitter.emitStatementStart();
|
writer.emitStatementStart();
|
||||||
if (statement.getId() != null) {
|
if (statement.getId() != null) {
|
||||||
writer.append(mapBlockId(statement.getId())).append(":").ws();
|
writer.append(mapBlockId(statement.getId())).append(":").ws();
|
||||||
}
|
}
|
||||||
writer.append("while");
|
writer.append("while");
|
||||||
writer.ws().append("(");
|
writer.ws().append("(");
|
||||||
if (statement.getCondition() != null) {
|
if (statement.getCondition() != null) {
|
||||||
prevCallSite = debugEmitter.emitCallSite();
|
|
||||||
precedence = Precedence.min();
|
precedence = Precedence.min();
|
||||||
statement.getCondition().acceptVisitor(this);
|
statement.getCondition().acceptVisitor(this);
|
||||||
debugEmitter.emitCallSite();
|
|
||||||
} else {
|
} else {
|
||||||
writer.append("true");
|
writer.append("true");
|
||||||
}
|
}
|
||||||
|
@ -351,7 +411,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BreakStatement statement) {
|
public void visit(BreakStatement statement) {
|
||||||
debugEmitter.emitStatementStart();
|
writer.emitStatementStart();
|
||||||
if (statement.getLocation() != null) {
|
if (statement.getLocation() != null) {
|
||||||
pushLocation(statement.getLocation());
|
pushLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
@ -367,7 +427,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ContinueStatement statement) {
|
public void visit(ContinueStatement statement) {
|
||||||
debugEmitter.emitStatementStart();
|
writer.emitStatementStart();
|
||||||
if (statement.getLocation() != null) {
|
if (statement.getLocation() != null) {
|
||||||
pushLocation(statement.getLocation());
|
pushLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
@ -383,17 +443,15 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ReturnStatement statement) {
|
public void visit(ReturnStatement statement) {
|
||||||
debugEmitter.emitStatementStart();
|
writer.emitStatementStart();
|
||||||
if (statement.getLocation() != null) {
|
if (statement.getLocation() != null) {
|
||||||
pushLocation(statement.getLocation());
|
pushLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
writer.append("return");
|
writer.append("return");
|
||||||
if (statement.getResult() != null) {
|
if (statement.getResult() != null) {
|
||||||
writer.append(' ');
|
writer.append(' ');
|
||||||
prevCallSite = debugEmitter.emitCallSite();
|
|
||||||
precedence = Precedence.min();
|
precedence = Precedence.min();
|
||||||
statement.getResult().acceptVisitor(this);
|
statement.getResult().acceptVisitor(this);
|
||||||
debugEmitter.emitCallSite();
|
|
||||||
}
|
}
|
||||||
writer.append(";").softNewLine();
|
writer.append(";").softNewLine();
|
||||||
if (statement.getLocation() != null) {
|
if (statement.getLocation() != null) {
|
||||||
|
@ -403,16 +461,14 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ThrowStatement statement) {
|
public void visit(ThrowStatement statement) {
|
||||||
debugEmitter.emitStatementStart();
|
writer.emitStatementStart();
|
||||||
if (statement.getLocation() != null) {
|
if (statement.getLocation() != null) {
|
||||||
pushLocation(statement.getLocation());
|
pushLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
writer.appendFunction("$rt_throw").append("(");
|
writer.appendFunction("$rt_throw").append("(");
|
||||||
prevCallSite = debugEmitter.emitCallSite();
|
|
||||||
precedence = Precedence.min();
|
precedence = Precedence.min();
|
||||||
statement.getException().acceptVisitor(this);
|
statement.getException().acceptVisitor(this);
|
||||||
writer.append(");").softNewLine();
|
writer.append(");").softNewLine();
|
||||||
debugEmitter.emitCallSite();
|
|
||||||
if (statement.getLocation() != null) {
|
if (statement.getLocation() != null) {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
@ -428,7 +484,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debugEmitter.emitStatementStart();
|
writer.emitStatementStart();
|
||||||
if (statement.getLocation() != null) {
|
if (statement.getLocation() != null) {
|
||||||
pushLocation(statement.getLocation());
|
pushLocation(statement.getLocation());
|
||||||
}
|
}
|
||||||
|
@ -1040,16 +1096,9 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
MethodReference method = expr.getMethod();
|
MethodReference method = expr.getMethod();
|
||||||
String name = naming.getNameFor(method.getDescriptor());
|
String name = naming.getNameFor(method.getDescriptor());
|
||||||
DeferredCallSite callSite = prevCallSite;
|
|
||||||
boolean shouldEraseCallSite = lastCallSite == null;
|
|
||||||
if (lastCallSite == null) {
|
|
||||||
lastCallSite = callSite;
|
|
||||||
}
|
|
||||||
boolean virtual = false;
|
|
||||||
switch (expr.getType()) {
|
switch (expr.getType()) {
|
||||||
case STATIC:
|
case STATIC:
|
||||||
writer.appendMethodBody(method).append("(");
|
writer.appendMethodBody(method).append("(");
|
||||||
prevCallSite = debugEmitter.emitCallSite();
|
|
||||||
for (int i = 0; i < expr.getArguments().size(); ++i) {
|
for (int i = 0; i < expr.getArguments().size(); ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
writer.append(",").ws();
|
writer.append(",").ws();
|
||||||
|
@ -1060,7 +1109,6 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
break;
|
break;
|
||||||
case SPECIAL:
|
case SPECIAL:
|
||||||
writer.appendMethodBody(method).append("(");
|
writer.appendMethodBody(method).append("(");
|
||||||
prevCallSite = debugEmitter.emitCallSite();
|
|
||||||
precedence = Precedence.min();
|
precedence = Precedence.min();
|
||||||
expr.getArguments().get(0).acceptVisitor(this);
|
expr.getArguments().get(0).acceptVisitor(this);
|
||||||
for (int i = 1; i < expr.getArguments().size(); ++i) {
|
for (int i = 1; i < expr.getArguments().size(); ++i) {
|
||||||
|
@ -1071,7 +1119,6 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
break;
|
break;
|
||||||
case DYNAMIC:
|
case DYNAMIC:
|
||||||
writer.append(".").append(name).append("(");
|
writer.append(".").append(name).append("(");
|
||||||
prevCallSite = debugEmitter.emitCallSite();
|
|
||||||
for (int i = 1; i < expr.getArguments().size(); ++i) {
|
for (int i = 1; i < expr.getArguments().size(); ++i) {
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
writer.append(",").ws();
|
writer.append(",").ws();
|
||||||
|
@ -1079,11 +1126,9 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
precedence = Precedence.min();
|
precedence = Precedence.min();
|
||||||
expr.getArguments().get(i).acceptVisitor(this);
|
expr.getArguments().get(i).acceptVisitor(this);
|
||||||
}
|
}
|
||||||
virtual = true;
|
|
||||||
break;
|
break;
|
||||||
case CONSTRUCTOR:
|
case CONSTRUCTOR:
|
||||||
writer.appendInit(expr.getMethod()).append("(");
|
writer.appendInit(expr.getMethod()).append("(");
|
||||||
prevCallSite = debugEmitter.emitCallSite();
|
|
||||||
for (int i = 0; i < expr.getArguments().size(); ++i) {
|
for (int i = 0; i < expr.getArguments().size(); ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
writer.append(",").ws();
|
writer.append(",").ws();
|
||||||
|
@ -1094,17 +1139,6 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
writer.append(')');
|
writer.append(')');
|
||||||
if (lastCallSite != null) {
|
|
||||||
if (virtual) {
|
|
||||||
lastCallSite.setVirtualMethod(expr.getMethod());
|
|
||||||
} else {
|
|
||||||
lastCallSite.setStaticMethod(expr.getMethod());
|
|
||||||
}
|
|
||||||
lastCallSite = callSite;
|
|
||||||
}
|
|
||||||
if (shouldEraseCallSite) {
|
|
||||||
lastCallSite = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outerPrecedence.ordinal() > Precedence.FUNCTION_CALL.ordinal()) {
|
if (outerPrecedence.ordinal() > Precedence.FUNCTION_CALL.ordinal()) {
|
||||||
writer.append(')');
|
writer.append(')');
|
||||||
|
@ -1612,4 +1646,12 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
return context.importModule(name);
|
return context.importModule(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class LocationStackEntry {
|
||||||
|
final TextLocation location;
|
||||||
|
|
||||||
|
LocationStackEntry(TextLocation location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ import java.io.StringReader;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mozilla.javascript.CompilerEnvirons;
|
import org.mozilla.javascript.CompilerEnvirons;
|
||||||
import org.mozilla.javascript.Context;
|
import org.mozilla.javascript.Context;
|
||||||
|
import org.teavm.backend.javascript.codegen.OutputSourceWriterBuilder;
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriterBuilder;
|
|
||||||
|
|
||||||
public class AstWriterTest {
|
public class AstWriterTest {
|
||||||
private StringBuilder sb = new StringBuilder();
|
private StringBuilder sb = new StringBuilder();
|
||||||
|
@ -31,7 +31,7 @@ public class AstWriterTest {
|
||||||
private AstWriter writerWithGlobals;
|
private AstWriter writerWithGlobals;
|
||||||
|
|
||||||
public AstWriterTest() {
|
public AstWriterTest() {
|
||||||
var builder = new SourceWriterBuilder(null);
|
var builder = new OutputSourceWriterBuilder(null);
|
||||||
builder.setMinified(true);
|
builder.setMinified(true);
|
||||||
sourceWriter = builder.build(sb);
|
sourceWriter = builder.build(sb);
|
||||||
writer = new AstWriter(sourceWriter, null);
|
writer = new AstWriter(sourceWriter, null);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user