diff --git a/Procyon.CompilerTools/src/main/java/com/strobel/decompiler/Decompiler.java b/Procyon.CompilerTools/src/main/java/com/strobel/decompiler/Decompiler.java index 7b348f4d..8d801830 100644 --- a/Procyon.CompilerTools/src/main/java/com/strobel/decompiler/Decompiler.java +++ b/Procyon.CompilerTools/src/main/java/com/strobel/decompiler/Decompiler.java @@ -19,14 +19,21 @@ import com.strobel.assembler.InputTypeLoader; import com.strobel.assembler.metadata.*; import com.strobel.core.VerifyArgument; +import com.strobel.decompiler.languages.TypeDecompilationResults; import com.strobel.decompiler.languages.java.JavaFormattingOptions; +import java.util.Collections; + public final class Decompiler { - public static void decompile(final String internalName, final ITextOutput output) { - decompile(internalName, output, new DecompilerSettings()); + + private Decompiler() { + } + + public static TypeDecompilationResults decompile(final String internalName, final ITextOutput output) { + return decompile(internalName, output, new DecompilerSettings()); } - public static void decompile(final String internalName, final ITextOutput output, final DecompilerSettings settings) { + public static TypeDecompilationResults decompile(final String internalName, final ITextOutput output, final DecompilerSettings settings) { VerifyArgument.notNull(internalName, "internalName"); VerifyArgument.notNull(settings, "settings"); @@ -53,7 +60,7 @@ public static void decompile(final String internalName, final ITextOutput output if (type == null || (resolvedType = type.resolve()) == null) { output.writeLine("!!! ERROR: Failed to load class %s.", internalName); - return; + return new TypeDecompilationResults(null); } DeobfuscationUtilities.processType(resolvedType); @@ -67,6 +74,6 @@ public static void decompile(final String internalName, final ITextOutput output settings.setJavaFormattingOptions(JavaFormattingOptions.createDefault()); } - settings.getLanguage().decompileType(resolvedType, output, options); + return settings.getLanguage().decompileType(resolvedType, output, options); } } diff --git a/Procyon.Decompiler/src/main/java/com/strobel/decompiler/AbstractLineNumberFormatter.java b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/AbstractLineNumberFormatter.java new file mode 100644 index 00000000..bd3121b4 --- /dev/null +++ b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/AbstractLineNumberFormatter.java @@ -0,0 +1,225 @@ +/* + * AbstractLineNumberFormatter.java + * + * Copyright (c) 2013-2022 Mike Strobel and other contributors + * + * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain; + * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. + * A copy of the license can be found in the License.html file at the root of this distribution. + * By using this source code in any fashion, you are agreeing to be bound by the terms of the + * Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + */ + +package com.strobel.decompiler; + +import com.strobel.decompiler.languages.LineNumberPosition; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; + +public abstract class AbstractLineNumberFormatter { + + private final List _positions; + private final EnumSet _options; + + /** + * Constructs an instance. + * + * @param lineNumberPositions a recipe for how to fix the line numbers in 'file'. + * @param options controls how 'this' represents line numbers in the resulting file + */ + protected AbstractLineNumberFormatter( + List lineNumberPositions, + EnumSet options) { + _positions = lineNumberPositions; + _options = (options == null ? EnumSet.noneOf(LineNumberOption.class) : options); + } + + /** + * Rewrites the file passed to 'this' constructor so that the actual line + * numbers match the recipe passed to 'this' constructor. + * + * @return The formatted source code + */ + public String reformatFile() throws IOException { + List lineBrokenPositions = new ArrayList<>(); + List brokenLines = breakLines(lineBrokenPositions); + try (StringWriter sw = new StringWriter()) { + emitFormatted(brokenLines, lineBrokenPositions, sw); + return sw.toString(); + } + } + + /** + * Processes {@link #_file}, breaking apart any lines on which multiple line-number markers + * appear in different columns. + * + * @return the list of broken lines + */ + private List breakLines(List o_LineBrokenPositions) throws IOException { + int numLinesRead = 0; + int lineOffset = 0; + List brokenLines = new ArrayList<>(); + + try (BufferedReader r = createReader()) { + for (int posIndex = 0; posIndex < _positions.size(); posIndex++) { + LineNumberPosition pos = _positions.get(posIndex); + o_LineBrokenPositions.add( new LineNumberPosition( + pos.getOriginalLine(), pos.getEmittedLine()+lineOffset, pos.getEmittedColumn())); + + // Copy the input file up to but not including the emitted line # in "pos". + while (numLinesRead < pos.getEmittedLine() - 1) { + brokenLines.add(r.readLine()); + numLinesRead++; + } + + // Read the line that contains the next line number annotations, but don't write it yet. + String line = r.readLine(); + numLinesRead++; + + // See if there are two original line annotations on the same emitted line. + LineNumberPosition nextPos; + int prevPartLen = 0; + char[] indent = {}; + do { + nextPos = (posIndex < _positions.size() - 1) ? _positions.get(posIndex + 1) : null; + if ( nextPos != null + && nextPos.getEmittedLine() == pos.getEmittedLine() + && nextPos.getOriginalLine() > pos.getOriginalLine()) { + // Two different source line numbers on the same emitted line! + posIndex++; + lineOffset++; + String firstPart = line.substring(0, nextPos.getEmittedColumn() - prevPartLen - 1); + brokenLines.add(new String(indent) + firstPart); + prevPartLen += firstPart.length(); + indent = new char[prevPartLen]; + Arrays.fill(indent, ' '); + line = line.substring(firstPart.length(), line.length()); + + // Alter the position while adding it. + o_LineBrokenPositions.add( new LineNumberPosition( + nextPos.getOriginalLine(), nextPos.getEmittedLine()+lineOffset, nextPos.getEmittedColumn())); + } else { + nextPos = null; + } + } while (nextPos != null); + + // Nothing special here-- just emit the line. + brokenLines.add(new String(indent) + line); + } + + // Copy out the remainder of the file. + String line; + while ((line = r.readLine()) != null) { + brokenLines.add(line); + } + } + return brokenLines; + } + + protected abstract BufferedReader createReader() throws IOException; + + private void emitFormatted(List brokenLines, List lineBrokenPositions, Writer writer) { + int globalOffset = 0; + int numLinesRead = 0; + Iterator lines = brokenLines.iterator(); + + int maxLineNo = LineNumberPosition.computeMaxLineNumber(lineBrokenPositions); + try (LineNumberPrintWriter w = new LineNumberPrintWriter(maxLineNo, writer)) { + + // Suppress all line numbers if we weren't asked to show them. + if (!_options.contains(LineNumberOption.LEADING_COMMENTS)) { + w.suppressLineNumbers(); + } + + // Suppress stretching if we weren't asked to do it. + boolean doStretching = (_options.contains(LineNumberOption.STRETCHED)); + + for (LineNumberPosition pos : lineBrokenPositions) { + int nextTarget = pos.getOriginalLine(); + int nextActual = pos.getEmittedLine(); + int requiredAdjustment = (nextTarget - nextActual - globalOffset); + + if (doStretching && requiredAdjustment < 0) { + // We currently need to remove newlines to squeeze things together. + // prefer to remove empty lines, + // 1. read all lines before nextActual and remove empty lines as needed + List stripped = new ArrayList<>(); + while (numLinesRead < nextActual - 1) { + String line = lines.next(); + numLinesRead++; + if ((requiredAdjustment < 0) && line.trim().isEmpty()) { + requiredAdjustment++; + globalOffset--; + } else { + stripped.add(line); + } + } + // 2. print non empty lines while stripping further as needed + int lineNoToPrint = (stripped.size() + requiredAdjustment <= 0) + ? nextTarget : LineNumberPrintWriter.NO_LINE_NUMBER; + for (String line : stripped) { + if (requiredAdjustment < 0) { + w.print(lineNoToPrint, line); + w.print(" "); + requiredAdjustment++; + globalOffset--; + } else { + w.println(lineNoToPrint, line); + } + } + // 3. read and print next actual + String line = lines.next(); + numLinesRead++; + if (requiredAdjustment < 0) { + w.print(nextTarget, line); + w.print(" "); + globalOffset--; + } else { + w.println(nextTarget, line); + } + + } else { + while (numLinesRead < nextActual) { + String line = lines.next(); + numLinesRead++; + boolean isLast = (numLinesRead >= nextActual); + int lineNoToPrint = isLast ? nextTarget : LineNumberPrintWriter.NO_LINE_NUMBER; + + if (requiredAdjustment > 0 && doStretching) { + // We currently need to inject newlines to space things out. + do { + w.println(""); + requiredAdjustment--; + globalOffset++; + } while (isLast && requiredAdjustment > 0); + w.println(lineNoToPrint, line); + } else { + // No tweaks needed-- we are on the ball. + w.println(lineNoToPrint, line); + } + } + } + } + + // Finish out the file. + String line; + while (lines.hasNext()) { + line = lines.next(); + w.println(line); + } + } + } + +} diff --git a/Procyon.Decompiler/src/main/java/com/strobel/decompiler/DecompilerDriver.java b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/DecompilerDriver.java index 67800d13..84d1b55f 100644 --- a/Procyon.Decompiler/src/main/java/com/strobel/decompiler/DecompilerDriver.java +++ b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/DecompilerDriver.java @@ -1,15 +1,38 @@ +/* + * DecompilerDriver.java + * + * Copyright (c) 2013-2022 Mike Strobel and other contributors + * + * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain; + * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. + * A copy of the license can be found in the License.html file at the root of this distribution. + * By using this source code in any fashion, you are agreeing to be bound by the terms of the + * Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + */ + package com.strobel.decompiler; import com.beust.jcommander.JCommander; import com.strobel.Procyon; import com.strobel.annotations.NotNull; import com.strobel.assembler.InputTypeLoader; -import com.strobel.assembler.metadata.*; +import com.strobel.assembler.metadata.CompositeTypeLoader; +import com.strobel.assembler.metadata.DeobfuscationUtilities; +import com.strobel.assembler.metadata.IMetadataResolver; +import com.strobel.assembler.metadata.ITypeLoader; +import com.strobel.assembler.metadata.JarTypeLoader; +import com.strobel.assembler.metadata.MetadataParser; +import com.strobel.assembler.metadata.MetadataSystem; +import com.strobel.assembler.metadata.TypeDefinition; +import com.strobel.assembler.metadata.TypeReference; import com.strobel.core.ExceptionUtilities; import com.strobel.core.StringUtilities; -import com.strobel.decompiler.LineNumberFormatter.LineNumberOption; -import com.strobel.decompiler.languages.BytecodeOutputOptions; import com.strobel.decompiler.languages.BytecodeLanguage; +import com.strobel.decompiler.languages.BytecodeOutputOptions; import com.strobel.decompiler.languages.Languages; import com.strobel.decompiler.languages.LineNumberPosition; import com.strobel.decompiler.languages.TypeDecompilationResults; @@ -24,14 +47,13 @@ import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.EnumSet; import java.util.Enumeration; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.logging.ConsoleHandler; @@ -295,7 +317,7 @@ private static void decompileType( final TypeDefinition resolvedType; if (type == null || (resolvedType = type.resolve()) == null) { - System.err.printf("!!! ERROR: Failed to load class %s.\n", typeName); + System.err.printf("!!! ERROR: Failed to load class %s.%n", typeName); return; } @@ -327,7 +349,7 @@ private static void decompileType( } if (writeToFile) { - System.out.printf("Decompiling %s...\n", typeName); + System.out.printf("Decompiling %s...%n", typeName); } final TypeDecompilationResults results = settings.getLanguage().decompileType(resolvedType, output, options); @@ -353,13 +375,17 @@ private static void decompileType( lineNumberOptions.add(LineNumberOption.STRETCHED); } + final File outputFile = ((FileOutputWriter) writer).getFile(); final LineNumberFormatter lineFormatter = new LineNumberFormatter( - ((FileOutputWriter) writer).getFile(), + outputFile, lineNumberPositions, lineNumberOptions ); - lineFormatter.reformatFile(); + final String reformattedFile = lineFormatter.reformatFile(); + final Charset charset = settings.isUnicodeOutputEnabled() ? StandardCharsets.UTF_8 + : Charset.defaultCharset(); + Files.write(outputFile.toPath(), reformattedFile.getBytes(charset)); } } @@ -454,30 +480,4 @@ public String format(@NotNull final LogRecord record) { " [" + record.getLevel() + "] " + loggerName + ": " + record.getMessage() + ' ' + lineSep; } -} - -final class NoRetryMetadataSystem extends MetadataSystem { - private final Set _failedTypes = new HashSet<>(); - - NoRetryMetadataSystem() { - } - - NoRetryMetadataSystem(final ITypeLoader typeLoader) { - super(typeLoader); - } - - @Override - protected TypeDefinition resolveType(final String descriptor, final boolean mightBePrimitive) { - if (_failedTypes.contains(descriptor)) { - return null; - } - - final TypeDefinition result = super.resolveType(descriptor, mightBePrimitive); - - if (result == null) { - _failedTypes.add(descriptor); - } - - return result; - } } \ No newline at end of file diff --git a/Procyon.Decompiler/src/main/java/com/strobel/decompiler/InMemoryLineNumberFormatter.java b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/InMemoryLineNumberFormatter.java new file mode 100644 index 00000000..78d44a56 --- /dev/null +++ b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/InMemoryLineNumberFormatter.java @@ -0,0 +1,58 @@ +/* + * InMemoryLineNumberFormatter.java + * + * Copyright (c) 2013-2022 Mike Strobel and other contributors + * + * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain; + * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. + * A copy of the license can be found in the License.html file at the root of this distribution. + * By using this source code in any fashion, you are agreeing to be bound by the terms of the + * Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + */ + +package com.strobel.decompiler; + +import com.strobel.decompiler.languages.LineNumberPosition; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.EnumSet; +import java.util.List; + +/** + * An InMemoryLineNumberFormatter is used to rewrite an existing .java source, introducing + * line number information. It can handle either, or both, of the following jobs: + * + *
    + *
  • Introduce line numbers as leading comments. + *
  • Stretch the source so that the line number comments match the physical lines. + *
+ */ +public class InMemoryLineNumberFormatter extends AbstractLineNumberFormatter { + + private final String _source; + + /** + * Constructs an instance. + * + * @param source the source whose line numbers should be fixed + * @param lineNumberPositions a recipe for how to fix the line numbers in source. + * @param options controls how 'this' represents line numbers in the resulting source + */ + public InMemoryLineNumberFormatter(String source, + List lineNumberPositions, + EnumSet options) { + super(lineNumberPositions, options); + _source = source; + } + + @Override + protected BufferedReader createReader() throws IOException { + return new BufferedReader(new StringReader(_source)); + } +} diff --git a/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberFormatter.java b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberFormatter.java index a05e386d..3b16f7e2 100644 --- a/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberFormatter.java +++ b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberFormatter.java @@ -1,227 +1,59 @@ +/* + * LineNumberFormatter.java + * + * Copyright (c) 2013-2022 Mike Strobel and other contributors + * + * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain; + * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. + * A copy of the license can be found in the License.html file at the root of this distribution. + * By using this source code in any fashion, you are agreeing to be bound by the terms of the + * Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + */ + package com.strobel.decompiler; +import com.strobel.decompiler.languages.LineNumberPosition; + import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; +import java.nio.file.Files; import java.util.EnumSet; -import java.util.Iterator; import java.util.List; -import com.strobel.decompiler.languages.LineNumberPosition; - /** * A LineNumberFormatter is used to rewrite an existing .java file, introducing * line number information. It can handle either, or both, of the following jobs: * *
    - *
  • Introduce line numbers as leading comments. + *
  • Introduce line numbers as leading comments. *
  • Stretch the file so that the line number comments match the physical lines. *
*/ -public class LineNumberFormatter { - private final List _positions; +public class LineNumberFormatter extends AbstractLineNumberFormatter { + private final File _file; - private final EnumSet _options; - - public enum LineNumberOption - { - LEADING_COMMENTS, - STRETCHED, - } - + /** * Constructs an instance. * - * @param file the file whose line numbers should be fixed + * @param file the file whose line numbers should be fixed * @param lineNumberPositions a recipe for how to fix the line numbers in 'file'. * @param options controls how 'this' represents line numbers in the resulting file */ public LineNumberFormatter(File file, List lineNumberPositions, EnumSet options) { + super(lineNumberPositions, options); _file = file; - _positions = lineNumberPositions; - _options = (options == null ? EnumSet.noneOf( LineNumberOption.class) : options); } - /** - * Rewrites the file passed to 'this' constructor so that the actual line numbers match - * the recipe passed to 'this' constructor. - */ - public void reformatFile() throws IOException { - List lineBrokenPositions = new ArrayList(); - List brokenLines = breakLines( lineBrokenPositions); - emitFormatted( brokenLines, lineBrokenPositions); + @Override + protected BufferedReader createReader() throws IOException { + return Files.newBufferedReader(_file.toPath()); } - - /** - * Processes {@link #_file}, breaking apart any lines on which multiple line-number markers - * appear in different columns. - * - * @return the list of broken lines - */ - private List breakLines( List o_LineBrokenPositions) throws IOException { - int numLinesRead = 0; - int lineOffset = 0; - List brokenLines = new ArrayList<>(); - - try( BufferedReader r = new BufferedReader( new FileReader( _file))) { - for ( int posIndex=0; posIndex<_positions.size(); posIndex++) { - LineNumberPosition pos = _positions.get( posIndex); - o_LineBrokenPositions.add( new LineNumberPosition( - pos.getOriginalLine(), pos.getEmittedLine()+lineOffset, pos.getEmittedColumn())); - - // Copy the input file up to but not including the emitted line # in "pos". - while ( numLinesRead < pos.getEmittedLine()-1) { - brokenLines.add( r.readLine()); - numLinesRead++; - } - - // Read the line that contains the next line number annotations, but don't write it yet. - String line = r.readLine(); - numLinesRead++; - - // See if there are two original line annotations on the same emitted line. - LineNumberPosition nextPos; - int prevPartLen = 0; - char[] indent = {}; - do { - nextPos = (posIndex < _positions.size()-1) ? _positions.get( posIndex+1) : null; - if ( nextPos != null - && nextPos.getEmittedLine() == pos.getEmittedLine() - && nextPos.getOriginalLine() > pos.getOriginalLine()) { - // Two different source line numbers on the same emitted line! - posIndex++; - lineOffset++; - String firstPart = line.substring( 0, nextPos.getEmittedColumn() - prevPartLen - 1); - brokenLines.add( new String(indent) + firstPart); - prevPartLen += firstPart.length(); - indent = new char[prevPartLen]; - Arrays.fill( indent, ' '); - line = line.substring( firstPart.length(), line.length()); - - // Alter the position while adding it. - o_LineBrokenPositions.add( new LineNumberPosition( - nextPos.getOriginalLine(), nextPos.getEmittedLine()+lineOffset, nextPos.getEmittedColumn())); - } else { - nextPos = null; - } - } while ( nextPos != null); - - // Nothing special here-- just emit the line. - brokenLines.add( new String(indent) + line); - } - - // Copy out the remainder of the file. - String line; - while ( (line = r.readLine()) != null) { - brokenLines.add( line); - } - } - return brokenLines; - } - - private void emitFormatted( List brokenLines, List lineBrokenPositions) throws IOException { - File tempFile = new File( _file.getAbsolutePath() + ".fixed"); - int globalOffset = 0; - int numLinesRead = 0; - Iterator lines = brokenLines.iterator(); - - int maxLineNo = LineNumberPosition.computeMaxLineNumber( lineBrokenPositions); - try( LineNumberPrintWriter w = new LineNumberPrintWriter( - maxLineNo, new BufferedWriter( new FileWriter( tempFile)))) { - - // Suppress all line numbers if we weren't asked to show them. - if ( ! _options.contains( LineNumberOption.LEADING_COMMENTS)) { - w.suppressLineNumbers(); - } - - // Suppress stretching if we weren't asked to do it. - boolean doStretching = (_options.contains( LineNumberOption.STRETCHED)); - - for ( LineNumberPosition pos : lineBrokenPositions) { - int nextTarget = pos.getOriginalLine(); - int nextActual = pos.getEmittedLine(); - int requiredAdjustment = (nextTarget - nextActual - globalOffset); - - if (doStretching && requiredAdjustment < 0) { - // We currently need to remove newlines to squeeze things together. - // prefer to remove empty lines, - // 1. read all lines before nextActual and remove empty lines as needed - List stripped = new ArrayList<>(); - while( numLinesRead < nextActual - 1) { - String line = lines.next(); - numLinesRead++; - if ((requiredAdjustment < 0) && line.trim().isEmpty()) { - requiredAdjustment++; - globalOffset--; - } else { - stripped.add(line); - } - } - // 2. print non empty lines while stripping further as needed - int lineNoToPrint = (stripped.size() + requiredAdjustment <= 0) - ? nextTarget : LineNumberPrintWriter.NO_LINE_NUMBER; - for (String line : stripped) { - if (requiredAdjustment < 0) { - w.print( lineNoToPrint, line); - w.print( " "); - requiredAdjustment++; - globalOffset--; - } else { - w.println( lineNoToPrint, line); - } - } - // 3. read and print next actual - String line = lines.next(); - numLinesRead++; - if (requiredAdjustment < 0) { - w.print( nextTarget, line); - w.print( " "); - globalOffset--; - } else { - w.println( nextTarget, line); - } - - } else { - while( numLinesRead < nextActual) { - String line = lines.next(); - numLinesRead++; - boolean isLast = (numLinesRead >= nextActual); - int lineNoToPrint = isLast ? nextTarget : LineNumberPrintWriter.NO_LINE_NUMBER; - - if ( requiredAdjustment > 0 && doStretching) { - // We currently need to inject newlines to space things out. - do { - w.println( ""); - requiredAdjustment--; - globalOffset++; - } while ( isLast && requiredAdjustment > 0); - w.println( lineNoToPrint, line); - } else { - // No tweaks needed-- we are on the ball. - w.println( lineNoToPrint, line); - } - } - } - } - - // Finish out the file. - String line; - while ( lines.hasNext()) { - line = lines.next(); - w.println( line); - } - } - - // Delete the original file and rename the formatted temp file over the original. - _file.delete(); - tempFile.renameTo( _file); - } - } diff --git a/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberOption.java b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberOption.java new file mode 100644 index 00000000..e8e6f016 --- /dev/null +++ b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberOption.java @@ -0,0 +1,23 @@ +/* + * LineNumberOption.java + * + * Copyright (c) 2013-2022 Mike Strobel and other contributors + * + * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain; + * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. + * A copy of the license can be found in the License.html file at the root of this distribution. + * By using this source code in any fashion, you are agreeing to be bound by the terms of the + * Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + */ + +package com.strobel.decompiler; + +public enum LineNumberOption +{ + LEADING_COMMENTS, + STRETCHED, +} \ No newline at end of file diff --git a/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberPrintWriter.java b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberPrintWriter.java index bdc2baa3..0b00fdc4 100644 --- a/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberPrintWriter.java +++ b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/LineNumberPrintWriter.java @@ -1,3 +1,19 @@ +/* + * LineNumberPrintWriter.java + * + * Copyright (c) 2013-2022 Mike Strobel and other contributors + * + * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain; + * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. + * A copy of the license can be found in the License.html file at the root of this distribution. + * By using this source code in any fashion, you are agreeing to be bound by the terms of the + * Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + */ + package com.strobel.decompiler; import java.io.PrintWriter; diff --git a/Procyon.Decompiler/src/main/java/com/strobel/decompiler/NoRetryMetadataSystem.java b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/NoRetryMetadataSystem.java new file mode 100644 index 00000000..a17e1e7f --- /dev/null +++ b/Procyon.Decompiler/src/main/java/com/strobel/decompiler/NoRetryMetadataSystem.java @@ -0,0 +1,50 @@ +/* + * NoRetryMetadataSystem.java + * + * Copyright (c) 2013-2022 Mike Strobel and other contributors + * + * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain; + * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa. + * + * This source code is subject to terms and conditions of the Apache License, Version 2.0. + * A copy of the license can be found in the License.html file at the root of this distribution. + * By using this source code in any fashion, you are agreeing to be bound by the terms of the + * Apache License, Version 2.0. + * + * You must not remove this notice, or any other, from this software. + */ + +package com.strobel.decompiler; + +import com.strobel.assembler.metadata.ITypeLoader; +import com.strobel.assembler.metadata.MetadataSystem; +import com.strobel.assembler.metadata.TypeDefinition; + +import java.util.HashSet; +import java.util.Set; + +public final class NoRetryMetadataSystem extends MetadataSystem { + private final Set _failedTypes = new HashSet<>(); + + NoRetryMetadataSystem() { + } + + NoRetryMetadataSystem(final ITypeLoader typeLoader) { + super(typeLoader); + } + + @Override + protected TypeDefinition resolveType(final String descriptor, final boolean mightBePrimitive) { + if (_failedTypes.contains(descriptor)) { + return null; + } + + final TypeDefinition result = super.resolveType(descriptor, mightBePrimitive); + + if (result == null) { + _failedTypes.add(descriptor); + } + + return result; + } +} \ No newline at end of file