mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Refactoring of DebugInformation. Reduce memory consumption and debug
file size. Add debug information reader
This commit is contained in:
parent
62281f696c
commit
444c599b17
|
@ -17,11 +17,11 @@ package org.teavm.debugging;
|
||||||
|
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
import org.teavm.common.IntegerArray;
|
||||||
import java.util.Collections;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import java.util.Map;
|
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,12 +31,15 @@ import org.teavm.model.MethodReference;
|
||||||
public class DebugInformation {
|
public class DebugInformation {
|
||||||
String[] fileNames;
|
String[] fileNames;
|
||||||
Map<String, Integer> fileNameMap;
|
Map<String, Integer> fileNameMap;
|
||||||
|
String[] classNames;
|
||||||
|
Map<String, Integer> classNameMap;
|
||||||
|
String[] methods;
|
||||||
|
Map<String, Integer> methodMap;
|
||||||
FileDescription[] fileDescriptions;
|
FileDescription[] fileDescriptions;
|
||||||
// TODO: for less memory consumption replace with two arrays + custom binary search
|
Mapping fileMapping;
|
||||||
GeneratedLocation[] fileNameKeys;
|
Mapping classMapping;
|
||||||
int[] fileNameValues;
|
Mapping methodMapping;
|
||||||
GeneratedLocation[] lineNumberKeys;
|
Mapping lineMapping;
|
||||||
int[] lineNumberValues;
|
|
||||||
|
|
||||||
public Collection<GeneratedLocation> getGeneratedLocations(String fileName, int line) {
|
public Collection<GeneratedLocation> getGeneratedLocations(String fileName, int line) {
|
||||||
Integer fileIndex = fileNameMap.get(fileName);
|
Integer fileIndex = fileNameMap.get(fileName);
|
||||||
|
@ -45,11 +48,19 @@ public class DebugInformation {
|
||||||
}
|
}
|
||||||
FileDescription description = fileIndex >= 0 ? fileDescriptions[fileIndex] : null;
|
FileDescription description = fileIndex >= 0 ? fileDescriptions[fileIndex] : null;
|
||||||
if (description == null) {
|
if (description == null) {
|
||||||
return null;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
GeneratedLocation[] locations = line < description.generatedLocations.length ?
|
if (line > description.generatedLocationStart.length) {
|
||||||
description.generatedLocations[line] : null;
|
return Collections.emptyList();
|
||||||
return locations != null ? Arrays.asList(locations) : Collections.<GeneratedLocation>emptyList();
|
}
|
||||||
|
int start = description.generatedLocationStart[line];
|
||||||
|
int end = description.generatedLocationStart[line + 1];
|
||||||
|
GeneratedLocation[] resultArray = new GeneratedLocation[(end - start) / 2];
|
||||||
|
for (int i = 0; i < resultArray.length; ++i) {
|
||||||
|
resultArray[i] = new GeneratedLocation(description.generatedLocationData[i * 2],
|
||||||
|
description.generatedLocationData[i * 2 + 1]);
|
||||||
|
}
|
||||||
|
return Arrays.asList(resultArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<GeneratedLocation> getGeneratedLocations(SourceLocation sourceLocation) {
|
public Collection<GeneratedLocation> getGeneratedLocations(SourceLocation sourceLocation) {
|
||||||
|
@ -61,40 +72,32 @@ public class DebugInformation {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceLocation getSourceLocation(GeneratedLocation generatedLocation) {
|
public SourceLocation getSourceLocation(GeneratedLocation generatedLocation) {
|
||||||
String fileName = componentByKey(fileNameKeys, fileNameValues, fileNames, generatedLocation);
|
String fileName = componentByKey(fileMapping, fileNames, generatedLocation);
|
||||||
int lineNumberIndex = indexByKey(lineNumberKeys, generatedLocation);
|
int lineNumberIndex = indexByKey(lineMapping, generatedLocation);
|
||||||
int lineNumber = lineNumberIndex >= 0 ? lineNumberValues[lineNumberIndex] : -1;
|
int lineNumber = lineNumberIndex >= 0 ? lineMapping.values[lineNumberIndex] : -1;
|
||||||
return new SourceLocation(fileName, lineNumber);
|
return new SourceLocation(fileName, lineNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference getMethodAt(String fileName, int line) {
|
public MethodReference getMethodAt(GeneratedLocation generatedLocation) {
|
||||||
if (line < 0) {
|
String className = componentByKey(classMapping, classNames, generatedLocation);
|
||||||
|
if (className == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Integer fileIndex = fileNameMap.get(fileName);
|
String method = componentByKey(methodMapping, methods, generatedLocation);
|
||||||
if (fileIndex == null) {
|
if (method == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
FileDescription description = fileDescriptions[fileIndex];
|
return new MethodReference(className, MethodDescriptor.parse(method));
|
||||||
if (description == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return line < description.methodMap.length ? description.methodMap[line] : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MethodReference getMethodAt(SourceLocation sourceLocation) {
|
private <T> T componentByKey(Mapping mapping, T[] values, GeneratedLocation location) {
|
||||||
return getMethodAt(sourceLocation.getFileName(), sourceLocation.getLine());
|
int keyIndex = indexByKey(mapping, location);
|
||||||
}
|
int valueIndex = keyIndex >= 0 ? mapping.values[keyIndex] : -1;
|
||||||
|
|
||||||
private <T> T componentByKey(GeneratedLocation[] keys, int[] valueIndexes, T[] values,
|
|
||||||
GeneratedLocation location) {
|
|
||||||
int keyIndex = indexByKey(keys, location);
|
|
||||||
int valueIndex = keyIndex >= 0 ? valueIndexes[keyIndex] : -1;
|
|
||||||
return valueIndex >= 0 ? values[valueIndex] : null;
|
return valueIndex >= 0 ? values[valueIndex] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int indexByKey(GeneratedLocation[] keys, GeneratedLocation location) {
|
private int indexByKey(Mapping mapping, GeneratedLocation location) {
|
||||||
int index = Arrays.binarySearch(keys, location);
|
int index = Collections.binarySearch(mapping.keyList(), location);
|
||||||
return index >= 0 ? index : -index - 2;
|
return index >= 0 ? index : -index - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,8 +106,179 @@ public class DebugInformation {
|
||||||
writer.write(this);
|
writer.write(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DebugInformation read(InputStream input) throws IOException {
|
||||||
|
DebugInformationReader reader = new DebugInformationReader(input);
|
||||||
|
return reader.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rebuildMaps() {
|
||||||
|
fileNameMap = mapArray(fileNames);
|
||||||
|
classNameMap = mapArray(classNames);
|
||||||
|
methodMap = mapArray(methods);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Integer> mapArray(String[] array) {
|
||||||
|
Map<String, Integer> map = new HashMap<>();
|
||||||
|
for (int i = 0; i < array.length; ++i) {
|
||||||
|
map.put(array[i], i);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rebuildFileDescriptions() {
|
||||||
|
FileDescriptionBuilder builder = new FileDescriptionBuilder(fileNames.length);
|
||||||
|
int fileIndex = 0;
|
||||||
|
int lineIndex = 0;
|
||||||
|
int currentFile = -1;
|
||||||
|
int currentLine = -1;
|
||||||
|
while (fileIndex < fileMapping.size() && lineIndex < lineMapping.size()) {
|
||||||
|
GeneratedLocation fileLoc = fileMapping.key(fileIndex);
|
||||||
|
GeneratedLocation lineLoc = lineMapping.key(lineIndex);
|
||||||
|
int cmp = fileLoc.compareTo(lineLoc);
|
||||||
|
if (cmp < 0) {
|
||||||
|
currentFile = fileMapping.values[fileIndex++];
|
||||||
|
} else if (cmp > 0){
|
||||||
|
currentLine = lineMapping.values[lineIndex++];
|
||||||
|
} else {
|
||||||
|
currentFile = fileMapping.values[fileIndex++];
|
||||||
|
currentLine = lineMapping.values[lineIndex++];
|
||||||
|
}
|
||||||
|
builder.emit(fileLoc.getLine(), fileLoc.getColumn(), currentFile, currentLine);
|
||||||
|
}
|
||||||
|
while (fileIndex < fileMapping.size()) {
|
||||||
|
builder.emit(fileMapping.lines[fileIndex], fileMapping.columns[fileIndex],
|
||||||
|
fileMapping.values[fileIndex], currentLine);
|
||||||
|
++fileIndex;
|
||||||
|
}
|
||||||
|
while (lineIndex < lineMapping.size()) {
|
||||||
|
builder.emit(lineMapping.lines[lineIndex], lineMapping.columns[lineIndex], currentFile,
|
||||||
|
lineMapping.values[lineIndex]);
|
||||||
|
++lineIndex;
|
||||||
|
}
|
||||||
|
fileDescriptions = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FileDescriptionBuilder {
|
||||||
|
FileDescriptionProto[] files;
|
||||||
|
|
||||||
|
public FileDescriptionBuilder(int size) {
|
||||||
|
files = new FileDescriptionProto[size];
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
files[i] = new FileDescriptionProto();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit(int line, int column, int fileIndex, int sourceLine) {
|
||||||
|
if (sourceLine == -1 || fileIndex == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FileDescriptionProto proto = files[fileIndex];
|
||||||
|
proto.addLocation(sourceLine, line, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileDescription[] build() {
|
||||||
|
FileDescription[] descriptions = new FileDescription[files.length];
|
||||||
|
for (int i = 0; i < files.length; ++i) {
|
||||||
|
descriptions[i] = files[i].build();
|
||||||
|
}
|
||||||
|
return descriptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FileDescriptionProto {
|
||||||
|
IntegerArray generatedLocationData = new IntegerArray(1);
|
||||||
|
IntegerArray generatedLocationPointers = new IntegerArray(1);
|
||||||
|
IntegerArray generatedLocationStart = new IntegerArray(1);
|
||||||
|
IntegerArray generatedLocationSize = new IntegerArray(1);
|
||||||
|
|
||||||
|
public void addLocation(int sourceLine, int line, int column) {
|
||||||
|
ensureLine(sourceLine);
|
||||||
|
generatedLocationSize.set(sourceLine, generatedLocationSize.get(sourceLine) + 1);
|
||||||
|
int slot = generatedLocationStart.get(sourceLine);
|
||||||
|
slot = addData(slot, column);
|
||||||
|
slot = addData(slot, line);
|
||||||
|
generatedLocationStart.set(sourceLine, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
int addData(int slot, int value) {
|
||||||
|
int result = generatedLocationData.size();
|
||||||
|
generatedLocationData.add(value);
|
||||||
|
generatedLocationPointers.add(slot);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensureLine(int sourceLine) {
|
||||||
|
while (sourceLine >= generatedLocationSize.size()) {
|
||||||
|
generatedLocationSize.add(0);
|
||||||
|
generatedLocationStart.add(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileDescription build() {
|
||||||
|
FileDescription description = new FileDescription();
|
||||||
|
description.generatedLocationData = new int[generatedLocationData.size()];
|
||||||
|
description.generatedLocationStart = new int[generatedLocationStart.size()];
|
||||||
|
int current = 0;
|
||||||
|
for (int i = 0; i < generatedLocationStart.size(); ++i) {
|
||||||
|
description.generatedLocationStart[i] = current;
|
||||||
|
current += generatedLocationSize.get(i) * 2;
|
||||||
|
int j = current;
|
||||||
|
int ptr = generatedLocationStart.get(i);
|
||||||
|
while (ptr >= 0) {
|
||||||
|
description.generatedLocationData[--j] = generatedLocationData.get(ptr);
|
||||||
|
ptr = generatedLocationPointers.get(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class FileDescription {
|
static class FileDescription {
|
||||||
GeneratedLocation[][] generatedLocations;
|
int[] generatedLocationData;
|
||||||
MethodReference[] methodMap;
|
int[] generatedLocationStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Mapping {
|
||||||
|
int[] lines;
|
||||||
|
int[] columns;
|
||||||
|
int[] values;
|
||||||
|
|
||||||
|
public Mapping(int[] lines, int[] columns, int[] values) {
|
||||||
|
this.lines = lines;
|
||||||
|
this.columns = columns;
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationList keyList() {
|
||||||
|
return new LocationList(lines, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return lines.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeneratedLocation key(int index) {
|
||||||
|
return new GeneratedLocation(lines[index], columns[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class LocationList extends AbstractList<GeneratedLocation> {
|
||||||
|
private int[] lines;
|
||||||
|
private int[] columns;
|
||||||
|
|
||||||
|
public LocationList(int[] lines, int[] columns) {
|
||||||
|
this.lines = lines;
|
||||||
|
this.columns = columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GeneratedLocation get(int index) {
|
||||||
|
return new GeneratedLocation(lines[index], columns[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return lines.length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,8 @@ package org.teavm.debugging;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.teavm.codegen.LocationProvider;
|
import org.teavm.codegen.LocationProvider;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.common.IntegerArray;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -26,14 +27,17 @@ import org.teavm.model.MethodReference;
|
||||||
public class DebugInformationBuilder implements DebugInformationEmitter {
|
public class DebugInformationBuilder implements DebugInformationEmitter {
|
||||||
private LocationProvider locationProvider;
|
private LocationProvider locationProvider;
|
||||||
private DebugInformation debugInformation;
|
private DebugInformation debugInformation;
|
||||||
private List<String> fileNames = new ArrayList<>();
|
private MappedList files = new MappedList();
|
||||||
private Map<String, Integer> fileNameMap = new HashMap<>();
|
private MappedList classes = new MappedList();
|
||||||
private List<Entry> fileNameEntries = new ArrayList<>();
|
private MappedList methods = new MappedList();
|
||||||
private List<Entry> lineNumberEntries = new ArrayList<>();
|
private Mapping fileMapping = new Mapping();
|
||||||
private MethodReference currentMethod;
|
private Mapping lineMapping = new Mapping();
|
||||||
|
private Mapping classMapping = new Mapping();
|
||||||
|
private Mapping methodMapping = new Mapping();
|
||||||
|
private MethodDescriptor currentMethod;
|
||||||
|
private String currentClass;
|
||||||
private String currentFileName;
|
private String currentFileName;
|
||||||
private int currentLine;
|
private int currentLine;
|
||||||
private List<FileDescriptionProto> fileDescriptions = new ArrayList<>();
|
|
||||||
|
|
||||||
public LocationProvider getLocationProvider() {
|
public LocationProvider getLocationProvider() {
|
||||||
return locationProvider;
|
return locationProvider;
|
||||||
|
@ -44,118 +48,100 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
||||||
this.locationProvider = locationProvider;
|
this.locationProvider = locationProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GeneratedLocation getGeneratedLocation() {
|
|
||||||
return new GeneratedLocation(locationProvider.getLine(), locationProvider.getColumn());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emitLocation(String fileName, int line) {
|
public void emitLocation(String fileName, int line) {
|
||||||
debugInformation = null;
|
debugInformation = null;
|
||||||
Integer fileIndex;
|
int fileIndex = files.index(fileName);
|
||||||
if (fileName != null) {
|
if (!Objects.equals(currentFileName, fileName)) {
|
||||||
fileIndex = fileNameMap.get(fileName);
|
fileMapping.add(locationProvider, fileIndex);
|
||||||
if (fileIndex == null) {
|
currentFileName = fileName;
|
||||||
fileIndex = fileNames.size();
|
|
||||||
fileNames.add(fileName);
|
|
||||||
fileNameMap.put(fileName, fileIndex);
|
|
||||||
fileDescriptions.add(new FileDescriptionProto());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fileIndex = -1;
|
|
||||||
}
|
|
||||||
if (currentFileName != fileName) {
|
|
||||||
fileNameEntries.add(new Entry(getGeneratedLocation(), fileIndex));
|
|
||||||
}
|
}
|
||||||
if (currentLine != line) {
|
if (currentLine != line) {
|
||||||
lineNumberEntries.add(new Entry(getGeneratedLocation(), line));
|
lineMapping.add(locationProvider, line);
|
||||||
}
|
currentLine = line;
|
||||||
if (fileName != null && line >= 0 && (currentFileName != fileName || currentLine != line)) {
|
|
||||||
FileDescriptionProto fileDesc = fileDescriptions.get(fileIndex);
|
|
||||||
fileDesc.setMethod(line, currentMethod);
|
|
||||||
fileDesc.addGeneratedLocation(line, getGeneratedLocation());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emitMethod(MethodReference method) {
|
public void emitClass(String className) {
|
||||||
debugInformation = null;
|
debugInformation = null;
|
||||||
|
int classIndex = classes.index(className);
|
||||||
|
if (!Objects.equals(className, currentClass)) {
|
||||||
|
classMapping.add(locationProvider, classIndex);
|
||||||
|
currentClass = className;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void emitMethod(MethodDescriptor method) {
|
||||||
|
debugInformation = null;
|
||||||
|
int methodIndex = methods.index(method != null ? method.toString() : null);
|
||||||
|
if (!Objects.equals(method, currentMethod)) {
|
||||||
|
methodMapping.add(locationProvider, methodIndex);
|
||||||
currentMethod = method;
|
currentMethod = method;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public DebugInformation getDebugInformation() {
|
public DebugInformation getDebugInformation() {
|
||||||
if (debugInformation == null) {
|
if (debugInformation == null) {
|
||||||
debugInformation = new DebugInformation();
|
debugInformation = new DebugInformation();
|
||||||
|
|
||||||
debugInformation.fileNames = fileNames.toArray(new String[0]);
|
debugInformation.fileNames = files.getItems();
|
||||||
debugInformation.fileNameMap = new HashMap<>(fileNameMap);
|
debugInformation.fileNameMap = files.getIndexes();
|
||||||
|
debugInformation.classNames = classes.getItems();
|
||||||
|
debugInformation.classNameMap = classes.getIndexes();
|
||||||
|
debugInformation.methods = methods.getItems();
|
||||||
|
debugInformation.methodMap = methods.getIndexes();
|
||||||
|
|
||||||
debugInformation.fileNameKeys = new GeneratedLocation[fileNameEntries.size()];
|
debugInformation.fileMapping = fileMapping.build();
|
||||||
debugInformation.fileNameValues = new int[fileNameEntries.size()];
|
debugInformation.lineMapping = lineMapping.build();
|
||||||
int index = 0;
|
debugInformation.classMapping = classMapping.build();
|
||||||
for (Entry entry : fileNameEntries) {
|
debugInformation.methodMapping = methodMapping.build();
|
||||||
debugInformation.fileNameKeys[index] = entry.key;
|
|
||||||
debugInformation.fileNameValues[index] = entry.value;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
debugInformation.lineNumberKeys = new GeneratedLocation[lineNumberEntries.size()];
|
debugInformation.rebuildFileDescriptions();
|
||||||
debugInformation.lineNumberValues = new int[lineNumberEntries.size()];
|
|
||||||
index = 0;
|
|
||||||
for (Entry entry : lineNumberEntries) {
|
|
||||||
debugInformation.lineNumberKeys[index] = entry.key;
|
|
||||||
debugInformation.lineNumberValues[index] = entry.value;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
debugInformation.fileDescriptions = new DebugInformation.FileDescription[fileDescriptions.size()];
|
|
||||||
index = 0;
|
|
||||||
for (FileDescriptionProto fileDescProto : fileDescriptions) {
|
|
||||||
DebugInformation.FileDescription fileDesc = new DebugInformation.FileDescription();
|
|
||||||
debugInformation.fileDescriptions[index++] = fileDesc;
|
|
||||||
fileDesc.methodMap = fileDescProto.methodMap.toArray(new MethodReference[0]);
|
|
||||||
fileDesc.generatedLocations = new GeneratedLocation[fileDescProto.generatedLocations.size()][];
|
|
||||||
for (int i = 0; i < fileDescProto.generatedLocations.size(); ++i) {
|
|
||||||
List<GeneratedLocation> locations = fileDescProto.generatedLocations.get(index);
|
|
||||||
fileDesc.generatedLocations[i] = locations != null ?
|
|
||||||
locations.toArray(new GeneratedLocation[0]) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return debugInformation;
|
return debugInformation;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class FileDescriptionProto {
|
static class Mapping {
|
||||||
List<List<GeneratedLocation>> generatedLocations = new ArrayList<>();
|
IntegerArray lines = new IntegerArray(1);
|
||||||
List<MethodReference> methodMap = new ArrayList<>();
|
IntegerArray columns = new IntegerArray(1);
|
||||||
|
IntegerArray values = new IntegerArray(1);
|
||||||
|
|
||||||
void addGeneratedLocation(int line, GeneratedLocation location) {
|
public void add(LocationProvider location, int value) {
|
||||||
if (line >= generatedLocations.size()) {
|
lines.add(location.getLine());
|
||||||
generatedLocations.addAll(Collections.<List<GeneratedLocation>>nCopies(
|
columns.add(location.getColumn());
|
||||||
line - generatedLocations.size() + 1, null));
|
values.add(value);
|
||||||
}
|
|
||||||
List<GeneratedLocation> existingLocations = generatedLocations.get(line);
|
|
||||||
if (existingLocations == null) {
|
|
||||||
existingLocations = new ArrayList<>();
|
|
||||||
generatedLocations.set(line, existingLocations);
|
|
||||||
}
|
|
||||||
existingLocations.add(location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMethod(int line, MethodReference method) {
|
DebugInformation.Mapping build() {
|
||||||
if (line >= methodMap.size()) {
|
return new DebugInformation.Mapping(lines.getAll(), columns.getAll(), values.getAll());
|
||||||
methodMap.addAll(Collections.<MethodReference>nCopies(line - methodMap.size() + 1, null));
|
|
||||||
}
|
|
||||||
methodMap.set(line, method);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Entry {
|
static class MappedList {
|
||||||
GeneratedLocation key;
|
private List<String> list = new ArrayList<>();
|
||||||
int value;
|
private Map<String, Integer> map = new HashMap<>();
|
||||||
|
|
||||||
public Entry(GeneratedLocation key, int value) {
|
public int index(String item) {
|
||||||
this.key = key;
|
if (item == null) {
|
||||||
this.value = value;
|
return -1;
|
||||||
|
}
|
||||||
|
Integer index = map.get(item);
|
||||||
|
if (index == null) {
|
||||||
|
index = list.size();
|
||||||
|
list.add(item);
|
||||||
|
map.put(item, index);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getItems() {
|
||||||
|
return list.toArray(new String[list.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Integer> getIndexes() {
|
||||||
|
return new HashMap<>(map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
package org.teavm.debugging;
|
package org.teavm.debugging;
|
||||||
|
|
||||||
import org.teavm.codegen.LocationProvider;
|
import org.teavm.codegen.LocationProvider;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -27,5 +27,7 @@ public interface DebugInformationEmitter {
|
||||||
|
|
||||||
void emitLocation(String fileName, int line);
|
void emitLocation(String fileName, int line);
|
||||||
|
|
||||||
void emitMethod(MethodReference method);
|
void emitMethod(MethodDescriptor method);
|
||||||
|
|
||||||
|
void emitClass(String className);
|
||||||
}
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 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.debugging;
|
||||||
|
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class DebugInformationReader {
|
||||||
|
private InputStream input;
|
||||||
|
private int lastNumber;
|
||||||
|
|
||||||
|
public DebugInformationReader(InputStream input) {
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DebugInformation read() throws IOException {
|
||||||
|
DebugInformation debugInfo = new DebugInformation();
|
||||||
|
debugInfo.fileNames = readStrings();
|
||||||
|
debugInfo.classNames = readStrings();
|
||||||
|
debugInfo.methods = readStrings();
|
||||||
|
debugInfo.fileMapping = readMapping();
|
||||||
|
debugInfo.lineMapping = readMapping();
|
||||||
|
debugInfo.classMapping = readMapping();
|
||||||
|
debugInfo.methodMapping = readMapping();
|
||||||
|
debugInfo.rebuildFileDescriptions();
|
||||||
|
return debugInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int processSign(int number) {
|
||||||
|
boolean negative = (number & 1) == 1;
|
||||||
|
number >>>= 1;
|
||||||
|
return !negative ? number : -number;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DebugInformation.Mapping readMapping() throws IOException {
|
||||||
|
int[] lines = readRle();
|
||||||
|
int last = 0;
|
||||||
|
for (int i = 0; i < lines.length; ++i) {
|
||||||
|
last += lines[i];
|
||||||
|
lines[i] = last;
|
||||||
|
}
|
||||||
|
int[] columns = new int[readUnsignedNumber()];
|
||||||
|
resetRelativeNumber();
|
||||||
|
for (int i = 0; i < columns.length; ++i) {
|
||||||
|
columns[i] = readRelativeNumber();
|
||||||
|
}
|
||||||
|
int[] values = new int[readUnsignedNumber()];
|
||||||
|
resetRelativeNumber();
|
||||||
|
for (int i = 0; i < values.length; ++i) {
|
||||||
|
values[i] = readRelativeNumber();
|
||||||
|
}
|
||||||
|
return new DebugInformation.Mapping(lines, columns, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] readStrings() throws IOException {
|
||||||
|
String[] array = new String[readUnsignedNumber()];
|
||||||
|
for (int i = 0; i < array.length; ++i) {
|
||||||
|
array[i] = readString();
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] readRle() throws IOException {
|
||||||
|
int[] array = new int[readUnsignedNumber()];
|
||||||
|
for (int i = 0; i < array.length;) {
|
||||||
|
int n = readUnsignedNumber();
|
||||||
|
int count = 1;
|
||||||
|
if ((n & 1) != 0) {
|
||||||
|
count = readUnsignedNumber();
|
||||||
|
}
|
||||||
|
n = processSign(n >>> 1);
|
||||||
|
while (count-- > 0) {
|
||||||
|
array[i] = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int readNumber() throws IOException {
|
||||||
|
return processSign(readUnsignedNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
private int readUnsignedNumber() throws IOException {
|
||||||
|
int number = 0;
|
||||||
|
while (true) {
|
||||||
|
int r = input.read();
|
||||||
|
if (r < 0) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
byte b = (byte)r;
|
||||||
|
number = (number << 7) | (b & 0x7F);
|
||||||
|
if ((b & 0x80) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int readRelativeNumber() throws IOException {
|
||||||
|
lastNumber += readNumber();
|
||||||
|
return lastNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetRelativeNumber() {
|
||||||
|
lastNumber = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readString() throws IOException {
|
||||||
|
byte[] bytes = new byte[readUnsignedNumber()];
|
||||||
|
int pos = 0;
|
||||||
|
while (pos < bytes.length) {
|
||||||
|
int read = input.read(bytes, pos, bytes.length - pos);
|
||||||
|
if (read == -1) {
|
||||||
|
throw new EOFException();
|
||||||
|
}
|
||||||
|
pos += read;
|
||||||
|
}
|
||||||
|
return new String(bytes, "UTF-8");
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,12 +17,6 @@ package org.teavm.debugging;
|
||||||
|
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.teavm.common.IntegerArray;
|
|
||||||
import org.teavm.debugging.DebugInformation.FileDescription;
|
|
||||||
import org.teavm.model.MethodReference;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -37,84 +31,52 @@ class DebugInformationWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(DebugInformation debugInfo) throws IOException {
|
public void write(DebugInformation debugInfo) throws IOException {
|
||||||
writeNumber(debugInfo.fileNames.length);
|
writeStringArray(debugInfo.fileNames);
|
||||||
for (int i = 0; i < debugInfo.fileNames.length; ++i) {
|
writeStringArray(debugInfo.classNames);
|
||||||
String fileName = debugInfo.fileNames[i];
|
writeStringArray(debugInfo.methods);
|
||||||
writeString(fileName);
|
|
||||||
writeMethods(debugInfo.fileDescriptions[i]);
|
writeMapping(debugInfo.fileMapping);
|
||||||
|
writeMapping(debugInfo.lineMapping);
|
||||||
|
writeMapping(debugInfo.classMapping);
|
||||||
|
writeMapping(debugInfo.methodMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeNumber(debugInfo.fileNameKeys.length);
|
private void writeStringArray(String[] array) throws IOException {
|
||||||
resetRelativeNumber();
|
writeUnsignedNumber(array.length);
|
||||||
for (int i = 0; i < debugInfo.fileNameKeys.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
writeRelativeNumber(debugInfo.fileNameKeys[i].getLine());
|
writeString(array[i]);
|
||||||
}
|
|
||||||
resetRelativeNumber();
|
|
||||||
for (int i = 0; i < debugInfo.fileNameKeys.length; ++i) {
|
|
||||||
writeRelativeNumber(debugInfo.fileNameKeys[i].getColumn());
|
|
||||||
}
|
|
||||||
resetRelativeNumber();
|
|
||||||
for (int i = 0; i < debugInfo.fileNameValues.length; ++i) {
|
|
||||||
writeRelativeNumber(debugInfo.fileNameValues[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
writeNumber(debugInfo.lineNumberKeys.length);
|
|
||||||
resetRelativeNumber();
|
|
||||||
resetRelativeNumber();
|
|
||||||
for (int i = 0; i < debugInfo.lineNumberKeys.length; ++i) {
|
|
||||||
writeRelativeNumber(debugInfo.lineNumberKeys[i].getLine());
|
|
||||||
}
|
|
||||||
resetRelativeNumber();
|
|
||||||
for (int i = 0; i < debugInfo.lineNumberKeys.length; ++i) {
|
|
||||||
writeRelativeNumber(debugInfo.lineNumberKeys[i].getColumn());
|
|
||||||
}
|
|
||||||
resetRelativeNumber();
|
|
||||||
for (int i = 0; i < debugInfo.fileNameValues.length; ++i) {
|
|
||||||
writeRelativeNumber(debugInfo.lineNumberValues[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeMethods(FileDescription fileDesc) throws IOException {
|
private void writeMapping(DebugInformation.Mapping mapping) throws IOException {
|
||||||
Map<MethodReference, IntegerArray> methodLineMap = new HashMap<>();
|
writeUnsignedNumber(mapping.lines.length);
|
||||||
for (int i = 0; i < fileDesc.methodMap.length; ++i) {
|
int[] lines = mapping.lines.clone();
|
||||||
MethodReference method = fileDesc.methodMap[i];
|
int last = 0;
|
||||||
if (method == null) {
|
for (int i = 0; i < lines.length; ++i) {
|
||||||
continue;
|
last = lines[i];
|
||||||
|
lines[i] -= last;
|
||||||
}
|
}
|
||||||
IntegerArray lines = methodLineMap.get(method);
|
writeRle(lines);
|
||||||
if (lines == null) {
|
resetRelativeNumber();
|
||||||
lines = new IntegerArray(1);
|
for (int i = 0; i < mapping.columns.length; ++i) {
|
||||||
methodLineMap.put(method, lines);
|
writeRelativeNumber(mapping.columns[i]);
|
||||||
}
|
}
|
||||||
lines.add(i);
|
resetRelativeNumber();
|
||||||
}
|
for (int i = 0; i < mapping.values.length; ++i) {
|
||||||
writeNumber(methodLineMap.size());
|
writeRelativeNumber(mapping.values[i]);
|
||||||
for (MethodReference method : methodLineMap.keySet()) {
|
|
||||||
writeString(method.toString());
|
|
||||||
int[] lines = methodLineMap.get(method).getAll();
|
|
||||||
Arrays.sort(lines);
|
|
||||||
for (int i = 0; i < lines.length;) {
|
|
||||||
writeRelativeNumber(i);
|
|
||||||
int j = i;
|
|
||||||
int last = lines[i];
|
|
||||||
++i;
|
|
||||||
while (i < lines.length && lines[i] == last + 1) {
|
|
||||||
++i;
|
|
||||||
++last;
|
|
||||||
}
|
|
||||||
writeNumber(i - j);
|
|
||||||
}
|
|
||||||
writeRelativeNumber(-1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeNumber(int number) throws IOException {
|
private void writeNumber(int number) throws IOException {
|
||||||
do {
|
writeUnsignedNumber(convertToSigned(number));
|
||||||
if (number < 0) {
|
|
||||||
number = (-number << 1) | 1;
|
|
||||||
} else {
|
|
||||||
number = number << 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int convertToSigned(int number) {
|
||||||
|
return number < 0 ? (-number << 1) | 1 : number << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeUnsignedNumber(int number) throws IOException {
|
||||||
|
do {
|
||||||
byte b = (byte)(number & 0x7F);
|
byte b = (byte)(number & 0x7F);
|
||||||
if ((number & 0xFFFFFF80) != 0) {
|
if ((number & 0xFFFFFF80) != 0) {
|
||||||
b |= 0x80;
|
b |= 0x80;
|
||||||
|
@ -124,6 +86,25 @@ class DebugInformationWriter {
|
||||||
} while (number != 0);
|
} while (number != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeRle(int[] array) throws IOException {
|
||||||
|
writeUnsignedNumber(array.length);
|
||||||
|
for (int i = 0; i < array.length;) {
|
||||||
|
int e = array[i];
|
||||||
|
int count = 1;
|
||||||
|
++i;
|
||||||
|
while (i < array.length && array[i] == e) {
|
||||||
|
++count;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (count > 1) {
|
||||||
|
writeUnsignedNumber((convertToSigned(e) << 1) | 1);
|
||||||
|
writeUnsignedNumber(count);
|
||||||
|
} else {
|
||||||
|
writeUnsignedNumber(convertToSigned(e) << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void writeRelativeNumber(int number) throws IOException {
|
private void writeRelativeNumber(int number) throws IOException {
|
||||||
writeNumber(number - lastNumber);
|
writeNumber(number - lastNumber);
|
||||||
lastNumber = number;
|
lastNumber = number;
|
||||||
|
@ -134,7 +115,8 @@ class DebugInformationWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeString(String str) throws IOException {
|
private void writeString(String str) throws IOException {
|
||||||
writeNumber(str.length());
|
byte[] bytes = str.getBytes("UTF-8");
|
||||||
output.write(str.getBytes("UTF-8"));
|
writeUnsignedNumber(bytes.length);
|
||||||
|
output.write(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ public class Debugger {
|
||||||
for (JavaScriptCallFrame jsFrame : javaScriptDebugger.getCallStack()) {
|
for (JavaScriptCallFrame jsFrame : javaScriptDebugger.getCallStack()) {
|
||||||
SourceLocation loc = debugInformation.getSourceLocation(jsFrame.getLocation());
|
SourceLocation loc = debugInformation.getSourceLocation(jsFrame.getLocation());
|
||||||
boolean empty = loc == null || (loc.getFileName() == null && loc.getLine() < 0);
|
boolean empty = loc == null || (loc.getFileName() == null && loc.getLine() < 0);
|
||||||
MethodReference method = !empty ? debugInformation.getMethodAt(loc) : null;
|
MethodReference method = !empty ? debugInformation.getMethodAt(jsFrame.getLocation()) : null;
|
||||||
if (!empty || !wasEmpty) {
|
if (!empty || !wasEmpty) {
|
||||||
frames.add(new CallFrame(loc, method));
|
frames.add(new CallFrame(loc, method));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
package org.teavm.debugging;
|
package org.teavm.debugging;
|
||||||
|
|
||||||
import org.teavm.codegen.LocationProvider;
|
import org.teavm.codegen.LocationProvider;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,7 +29,11 @@ public class DummyDebugInformationEmitter implements DebugInformationEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void emitMethod(MethodReference method) {
|
public void emitMethod(MethodDescriptor method) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void emitClass(String className) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -44,4 +44,30 @@ public class GeneratedLocation implements Comparable<GeneratedLocation> {
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + column;
|
||||||
|
result = prime * result + line;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GeneratedLocation other = (GeneratedLocation)obj;
|
||||||
|
return line == other.line && column == other.column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "line: " + line + ", column: " + column;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,6 +242,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(ClassNode cls) throws RenderingException {
|
public void render(ClassNode cls) throws RenderingException {
|
||||||
|
debugEmitter.emitClass(cls.getName());
|
||||||
try {
|
try {
|
||||||
writer.append("function ").appendClass(cls.getName()).append("()").ws().append("{")
|
writer.append("function ").appendClass(cls.getName()).append("()").ws().append("{")
|
||||||
.indent().softNewLine();
|
.indent().softNewLine();
|
||||||
|
@ -354,6 +355,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RenderingException("IO error occured", e);
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
|
debugEmitter.emitClass(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object getDefaultValue(ValueType type) {
|
private static Object getDefaultValue(ValueType type) {
|
||||||
|
@ -383,6 +385,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
|
|
||||||
private void renderInitializer(MethodNode method) throws IOException {
|
private void renderInitializer(MethodNode method) throws IOException {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
|
debugEmitter.emitMethod(ref.getDescriptor());
|
||||||
writer.appendClass(ref.getClassName()).append(".").appendMethod(ref).ws().append("=").ws().append("function(");
|
writer.appendClass(ref.getClassName()).append(".").appendMethod(ref).ws().append("=").ws().append("function(");
|
||||||
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
|
@ -403,21 +406,23 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
writer.append(");").softNewLine();
|
writer.append(");").softNewLine();
|
||||||
writer.append("return result;").softNewLine();
|
writer.append("return result;").softNewLine();
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").newLine();
|
||||||
|
debugEmitter.emitMethod(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderVirtualDeclarations(String className, List<MethodNode> methods)
|
private void renderVirtualDeclarations(String className, List<MethodNode> methods)
|
||||||
throws NamingException, IOException {
|
throws NamingException, IOException {
|
||||||
|
if (methods.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (MethodNode method : methods) {
|
for (MethodNode method : methods) {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
if (ref.getDescriptor().getName().equals("<init>")) {
|
if (ref.getDescriptor().getName().equals("<init>")) {
|
||||||
renderInitializer(method);
|
renderInitializer(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (methods.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
writer.append("$rt_virtualMethods(").appendClass(className).indent();
|
writer.append("$rt_virtualMethods(").appendClass(className).indent();
|
||||||
for (MethodNode method : methods) {
|
for (MethodNode method : methods) {
|
||||||
|
debugEmitter.emitMethod(method.getReference().getDescriptor());
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
writer.append(",").newLine();
|
writer.append(",").newLine();
|
||||||
if (method.isOriginalNamePreserved()) {
|
if (method.isOriginalNamePreserved()) {
|
||||||
|
@ -443,12 +448,14 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
writer.append(",").ws().append(variableName(i));
|
writer.append(",").ws().append(variableName(i));
|
||||||
}
|
}
|
||||||
writer.append(");").ws().append("}");
|
writer.append(");").ws().append("}");
|
||||||
|
debugEmitter.emitMethod(null);
|
||||||
}
|
}
|
||||||
writer.append(");").newLine().outdent();
|
writer.append(");").newLine().outdent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderStaticDeclaration(MethodNode method) throws NamingException, IOException {
|
private void renderStaticDeclaration(MethodNode method) throws NamingException, IOException {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
|
debugEmitter.emitMethod(ref.getDescriptor());
|
||||||
if (ref.getDescriptor().getName().equals("<init>")) {
|
if (ref.getDescriptor().getName().equals("<init>")) {
|
||||||
renderInitializer(method);
|
renderInitializer(method);
|
||||||
}
|
}
|
||||||
|
@ -470,11 +477,12 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
writer.appendClass(ref.getClassName()).append(".").append(ref.getName()).ws().append("=")
|
writer.appendClass(ref.getClassName()).append(".").append(ref.getName()).ws().append("=")
|
||||||
.ws().appendClass(ref.getClassName()).append(".").appendMethod(ref).append(';').newLine();
|
.ws().appendClass(ref.getClassName()).append(".").appendMethod(ref).append(';').newLine();
|
||||||
}
|
}
|
||||||
|
debugEmitter.emitMethod(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderBody(MethodNode method, boolean inner) throws IOException {
|
public void renderBody(MethodNode method, boolean inner) throws IOException {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
debugEmitter.emitMethod(ref);
|
debugEmitter.emitMethod(ref.getDescriptor());
|
||||||
if (inner) {
|
if (inner) {
|
||||||
writer.appendMethodBody(ref).ws().append("=").ws().append("function(");
|
writer.appendMethodBody(ref).ws().append("=").ws().append("function(");
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user