[java decompiler] moves TextBuffer into "util" package
This commit is contained in:
@@ -27,6 +27,7 @@ import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
|
||||
import org.jetbrains.java.decompiler.struct.gen.VarType;
|
||||
import org.jetbrains.java.decompiler.struct.gen.generics.*;
|
||||
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
||||
import org.jetbrains.java.decompiler.util.TextBuffer;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package org.jetbrains.java.decompiler.main;
|
||||
|
||||
import org.jetbrains.java.decompiler.code.CodeConstants;
|
||||
@@ -19,6 +21,7 @@ import org.jetbrains.java.decompiler.struct.StructMethod;
|
||||
import org.jetbrains.java.decompiler.struct.attr.StructInnerClassesAttribute;
|
||||
import org.jetbrains.java.decompiler.struct.gen.VarType;
|
||||
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
||||
import org.jetbrains.java.decompiler.util.TextBuffer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package org.jetbrains.java.decompiler.main;
|
||||
|
||||
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
|
||||
@@ -10,6 +12,7 @@ import org.jetbrains.java.decompiler.struct.IDecompiledData;
|
||||
import org.jetbrains.java.decompiler.struct.StructClass;
|
||||
import org.jetbrains.java.decompiler.struct.StructContext;
|
||||
import org.jetbrains.java.decompiler.struct.lazy.LazyLoader;
|
||||
import org.jetbrains.java.decompiler.util.TextBuffer;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.java.decompiler.main;
|
||||
|
||||
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Allows to connect text with resulting lines
|
||||
*
|
||||
* @author egor
|
||||
*/
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
public class TextBuffer {
|
||||
private final String myLineSeparator = DecompilerContext.getNewLineSeparator();
|
||||
private final String myIndent = (String)DecompilerContext.getProperty(IFernflowerPreferences.INDENT_STRING);
|
||||
private final StringBuilder myStringBuilder;
|
||||
private Map<Integer, Integer> myLineToOffsetMapping = null;
|
||||
|
||||
public TextBuffer() {
|
||||
myStringBuilder = new StringBuilder();
|
||||
}
|
||||
|
||||
public TextBuffer(int size) {
|
||||
myStringBuilder = new StringBuilder(size);
|
||||
}
|
||||
|
||||
public TextBuffer(String text) {
|
||||
myStringBuilder = new StringBuilder(text);
|
||||
}
|
||||
|
||||
public TextBuffer append(String str) {
|
||||
myStringBuilder.append(str);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextBuffer append(char ch) {
|
||||
myStringBuilder.append(ch);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextBuffer append(int i) {
|
||||
myStringBuilder.append(i);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextBuffer appendLineSeparator() {
|
||||
myStringBuilder.append(myLineSeparator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextBuffer appendIndent(int length) {
|
||||
while (length-- > 0) {
|
||||
append(myIndent);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextBuffer prepend(String s) {
|
||||
myStringBuilder.insert(0, s);
|
||||
shiftMapping(s.length());
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextBuffer enclose(String left, String right) {
|
||||
prepend(left);
|
||||
append(right);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean containsOnlyWhitespaces() {
|
||||
for (int i = 0; i < myStringBuilder.length(); i++) {
|
||||
if (myStringBuilder.charAt(i) != ' ') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String original = myStringBuilder.toString();
|
||||
if (myLineToOffsetMapping == null || myLineToOffsetMapping.isEmpty()) {
|
||||
if (myLineMapping != null) {
|
||||
return addOriginalLineNumbers();
|
||||
}
|
||||
return original;
|
||||
}
|
||||
else {
|
||||
StringBuilder res = new StringBuilder();
|
||||
String[] srcLines = original.split(myLineSeparator);
|
||||
int currentLineStartOffset = 0;
|
||||
int currentLine = 0;
|
||||
int previousMarkLine = 0;
|
||||
int dumpedLines = 0;
|
||||
ArrayList<Integer> linesWithMarks = new ArrayList<>(myLineToOffsetMapping.keySet());
|
||||
Collections.sort(linesWithMarks);
|
||||
for (Integer markLine : linesWithMarks) {
|
||||
Integer markOffset = myLineToOffsetMapping.get(markLine);
|
||||
while (currentLine < srcLines.length) {
|
||||
String line = srcLines[currentLine];
|
||||
int lineEnd = currentLineStartOffset + line.length() + myLineSeparator.length();
|
||||
if (markOffset <= lineEnd) {
|
||||
int requiredLine = markLine - 1;
|
||||
int linesToAdd = requiredLine - dumpedLines;
|
||||
dumpedLines = requiredLine;
|
||||
appendLines(res, srcLines, previousMarkLine, currentLine, linesToAdd);
|
||||
previousMarkLine = currentLine;
|
||||
break;
|
||||
}
|
||||
currentLineStartOffset = lineEnd;
|
||||
currentLine++;
|
||||
}
|
||||
}
|
||||
if (previousMarkLine < srcLines.length) {
|
||||
appendLines(res, srcLines, previousMarkLine, srcLines.length, srcLines.length - previousMarkLine);
|
||||
}
|
||||
|
||||
return res.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private String addOriginalLineNumbers() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int lineStart = 0, lineEnd;
|
||||
int count = 0, length = myLineSeparator.length();
|
||||
while ((lineEnd = myStringBuilder.indexOf(myLineSeparator, lineStart)) > 0) {
|
||||
++count;
|
||||
sb.append(myStringBuilder.substring(lineStart, lineEnd));
|
||||
Set<Integer> integers = myLineMapping.get(count);
|
||||
if (integers != null) {
|
||||
sb.append("//");
|
||||
for (Integer integer : integers) {
|
||||
sb.append(' ').append(integer);
|
||||
}
|
||||
}
|
||||
sb.append(myLineSeparator);
|
||||
lineStart = lineEnd + length;
|
||||
}
|
||||
if (lineStart < myStringBuilder.length()) {
|
||||
sb.append(myStringBuilder.substring(lineStart));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void appendLines(StringBuilder res, String[] srcLines, int from, int to, int requiredLineNumber) {
|
||||
if (to - from > requiredLineNumber) {
|
||||
List<String> strings = compactLines(Arrays.asList(srcLines).subList(from, to) ,requiredLineNumber);
|
||||
int separatorsRequired = requiredLineNumber - 1;
|
||||
for (String s : strings) {
|
||||
res.append(s);
|
||||
if (separatorsRequired-- > 0) {
|
||||
res.append(myLineSeparator);
|
||||
}
|
||||
}
|
||||
res.append(myLineSeparator);
|
||||
}
|
||||
else if (to - from <= requiredLineNumber) {
|
||||
for (int i = from; i < to; i++) {
|
||||
res.append(srcLines[i]).append(myLineSeparator);
|
||||
}
|
||||
for (int i = 0; i < requiredLineNumber - to + from; i++) {
|
||||
res.append(myLineSeparator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return myStringBuilder.length();
|
||||
}
|
||||
|
||||
public void setStart(int position) {
|
||||
myStringBuilder.delete(0, position);
|
||||
shiftMapping(-position);
|
||||
}
|
||||
|
||||
public void setLength(int position) {
|
||||
myStringBuilder.setLength(position);
|
||||
if (myLineToOffsetMapping != null) {
|
||||
Map<Integer, Integer> newMap = new HashMap<>();
|
||||
for (Map.Entry<Integer, Integer> entry : myLineToOffsetMapping.entrySet()) {
|
||||
if (entry.getValue() <= position) {
|
||||
newMap.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
myLineToOffsetMapping = newMap;
|
||||
}
|
||||
}
|
||||
|
||||
public TextBuffer append(TextBuffer buffer) {
|
||||
if (buffer.myLineToOffsetMapping != null && !buffer.myLineToOffsetMapping.isEmpty()) {
|
||||
checkMapCreated();
|
||||
for (Map.Entry<Integer, Integer> entry : buffer.myLineToOffsetMapping.entrySet()) {
|
||||
myLineToOffsetMapping.put(entry.getKey(), entry.getValue() + myStringBuilder.length());
|
||||
}
|
||||
}
|
||||
myStringBuilder.append(buffer.myStringBuilder);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void shiftMapping(int shiftOffset) {
|
||||
if (myLineToOffsetMapping != null) {
|
||||
Map<Integer, Integer> newMap = new HashMap<>();
|
||||
for (Map.Entry<Integer, Integer> entry : myLineToOffsetMapping.entrySet()) {
|
||||
int newValue = entry.getValue();
|
||||
if (newValue >= 0) {
|
||||
newValue += shiftOffset;
|
||||
}
|
||||
if (newValue >= 0) {
|
||||
newMap.put(entry.getKey(), newValue);
|
||||
}
|
||||
}
|
||||
myLineToOffsetMapping = newMap;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkMapCreated() {
|
||||
if (myLineToOffsetMapping == null) {
|
||||
myLineToOffsetMapping = new HashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
public int countLines() {
|
||||
return countLines(0);
|
||||
}
|
||||
|
||||
public int countLines(int from) {
|
||||
return count(myLineSeparator, from);
|
||||
}
|
||||
|
||||
public int count(String substring, int from) {
|
||||
int count = 0, length = substring.length(), p = from;
|
||||
while ((p = myStringBuilder.indexOf(substring, p)) > 0) {
|
||||
++count;
|
||||
p += length;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private static List<String> compactLines(List<String> srcLines, int requiredLineNumber) {
|
||||
if (srcLines.size() < 2 || srcLines.size() <= requiredLineNumber) {
|
||||
return srcLines;
|
||||
}
|
||||
List<String> res = new LinkedList<>(srcLines);
|
||||
// first join lines with a single { or }
|
||||
for (int i = res.size()-1; i > 0 ; i--) {
|
||||
String s = res.get(i);
|
||||
if (s.trim().equals("{") || s.trim().equals("}")) {
|
||||
res.set(i-1, res.get(i-1).concat(s));
|
||||
res.remove(i);
|
||||
}
|
||||
if (res.size() <= requiredLineNumber) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
// now join empty lines
|
||||
for (int i = res.size()-1; i > 0 ; i--) {
|
||||
String s = res.get(i);
|
||||
if (s.trim().isEmpty()) {
|
||||
res.set(i-1, res.get(i-1).concat(s));
|
||||
res.remove(i);
|
||||
}
|
||||
if (res.size() <= requiredLineNumber) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private Map<Integer, Set<Integer>> myLineMapping = null; // new to original
|
||||
|
||||
public void dumpOriginalLineNumbers(int[] lineMapping) {
|
||||
if (lineMapping.length > 0) {
|
||||
myLineMapping = new HashMap<>();
|
||||
for (int i = 0; i < lineMapping.length; i += 2) {
|
||||
int key = lineMapping[i + 1];
|
||||
Set<Integer> existing = myLineMapping.computeIfAbsent(key, k -> new TreeSet<>());
|
||||
existing.add(lineMapping[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package org.jetbrains.java.decompiler.main.collectors;
|
||||
|
||||
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
||||
import org.jetbrains.java.decompiler.main.TextBuffer;
|
||||
import org.jetbrains.java.decompiler.util.TextBuffer;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@@ -5,7 +5,7 @@ package org.jetbrains.java.decompiler.main.collectors;
|
||||
|
||||
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
|
||||
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
||||
import org.jetbrains.java.decompiler.main.TextBuffer;
|
||||
import org.jetbrains.java.decompiler.util.TextBuffer;
|
||||
import org.jetbrains.java.decompiler.struct.StructClass;
|
||||
import org.jetbrains.java.decompiler.struct.StructContext;
|
||||
import org.jetbrains.java.decompiler.struct.StructField;
|
||||
|
||||
Reference in New Issue
Block a user