Package com.strobel.decompiler

Source Code of com.strobel.decompiler.AnsiTextOutput

/*
* AnsiTextOutput.java
*
* Copyright (c) 2013 Mike Strobel
*
* 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.ir.Instruction;
import com.strobel.assembler.ir.OpCode;
import com.strobel.assembler.metadata.FieldReference;
import com.strobel.assembler.metadata.IMethodSignature;
import com.strobel.assembler.metadata.Label;
import com.strobel.assembler.metadata.MethodReference;
import com.strobel.assembler.metadata.PackageReference;
import com.strobel.assembler.metadata.ParameterReference;
import com.strobel.assembler.metadata.TypeDefinition;
import com.strobel.assembler.metadata.TypeReference;
import com.strobel.assembler.metadata.VariableReference;
import com.strobel.core.StringUtilities;
import com.strobel.decompiler.ast.AstCode;
import com.strobel.decompiler.ast.Variable;
import com.strobel.decompiler.languages.java.JavaOutputVisitor;
import com.strobel.io.Ansi;

import java.io.Writer;

public class AnsiTextOutput extends PlainTextOutput {
    private final static Ansi KEYWORD = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(33/*39*/), null);
    private final static Ansi INSTRUCTION = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(/*45*//*33*/141), null);
    private final static Ansi LABEL = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(249), null);
    private final static Ansi TYPE = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(45/*105*//*141*/), null);
    private final static Ansi PACKAGE = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(111), null);
    private final static Ansi METHOD = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(/*213*/212), null);
    private final static Ansi FIELD = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(222/*216*/), null);
    private final static Ansi LOCAL = new Ansi(Ansi.Attribute.NORMAL, /*new Ansi.AnsiColor(230)*/(Ansi.AnsiColor) null, null);
    private final static Ansi LITERAL = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(204), null);
    private final static Ansi TEXT_LITERAL = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(/*48*/42), null);
    private final static Ansi COMMENT = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(244), null);
    private final static Ansi OPERATOR = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(247), null);
    private final static Ansi DELIMITER = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(249), null);
    private final static Ansi ATTRIBUTE = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(214), null);
    private final static Ansi ERROR = new Ansi(Ansi.Attribute.NORMAL, new Ansi.AnsiColor(196), null);

    public AnsiTextOutput() {
    }

    public AnsiTextOutput(final Writer writer) {
        super(writer);
    }

    @Override
    public void writeError(final String value) {
        writeAnsi(value, ERROR.colorize(value));
    }

    @Override
    public void writeLabel(final String value) {
        writeAnsi(value, LABEL.colorize(value));
    }

    protected final void writeAnsi(final String originalText, final String ansiText) {
        super.write(ansiText);

        if (originalText != null && ansiText != null) {
            super.column -= (ansiText.length() - originalText.length());
        }
    }

    @Override
    public void writeLiteral(final Object value) {
        final String literal = String.valueOf(value);
        writeAnsi(literal, LITERAL.colorize(literal));
    }

    @Override
    public void writeTextLiteral(final Object value) {
        final String literal = String.valueOf(value);
        writeAnsi(literal, TEXT_LITERAL.colorize(literal));
    }

    @Override
    public void writeComment(final String value) {
        writeAnsi(value, COMMENT.colorize(value));
    }

    @Override
    public void writeComment(final String format, final Object... args) {
        final String text = String.format(format, args);
        writeAnsi(text, COMMENT.colorize(text));
    }

    @Override
    public void writeDelimiter(final String text) {
        writeAnsi(text, DELIMITER.colorize(text));
    }

    @Override
    public void writeAttribute(final String text) {
        writeAnsi(text, ATTRIBUTE.colorize(text));
    }

    @Override
    public void writeOperator(final String text) {
        writeAnsi(text, OPERATOR.colorize(text));
    }

    @Override
    public void writeKeyword(final String text) {
        writeAnsi(text, KEYWORD.colorize(text));
    }

    @Override
    public void writeDefinition(final String text, final Object definition, final boolean isLocal) {
        final String escapedText = JavaOutputVisitor.escapeUnicode(text);

        if (escapedText == null) {
            super.write(escapedText);
            return;
        }

        final String colorizedText;

        if (definition instanceof Instruction ||
            definition instanceof OpCode ||
            definition instanceof AstCode) {

            colorizedText = INSTRUCTION.colorize(escapedText);
        }
        else if (definition instanceof TypeReference) {
            colorizedText = colorizeType(escapedText, (TypeReference) definition);
        }
        else if (definition instanceof MethodReference ||
                 definition instanceof IMethodSignature) {
            colorizedText = METHOD.colorize(escapedText);
        }
        else if (definition instanceof FieldReference) {
            colorizedText = FIELD.colorize(escapedText);
        }
        else if (definition instanceof VariableReference ||
                 definition instanceof ParameterReference ||
                 definition instanceof Variable) {

            colorizedText = LOCAL.colorize(escapedText);
        }
        else if (definition instanceof PackageReference) {
            colorizedText = colorizePackage(escapedText);
        }
        else if (definition instanceof Label ||
                 definition instanceof com.strobel.decompiler.ast.Label) {

            colorizedText = LABEL.colorize(escapedText);
        }
        else {
            colorizedText = escapedText;
        }

        writeAnsi(escapedText, colorizedText);
    }

    @Override
    public void writeReference(final String text, final Object reference, final boolean isLocal) {
        final String escapedText = JavaOutputVisitor.escapeUnicode(text);

        if (escapedText == null) {
            super.write(escapedText);
            return;
        }

        final String colorizedText;

        if (reference instanceof Instruction ||
            reference instanceof OpCode ||
            reference instanceof AstCode) {

            colorizedText = INSTRUCTION.colorize(escapedText);
        }
        else if (reference instanceof TypeReference) {
            colorizedText = colorizeType(escapedText, (TypeReference) reference);
        }
        else if (reference instanceof MethodReference ||
                 reference instanceof IMethodSignature) {
            colorizedText = METHOD.colorize(escapedText);
        }
        else if (reference instanceof FieldReference) {
            colorizedText = FIELD.colorize(escapedText);
        }
        else if (reference instanceof VariableReference ||
                 reference instanceof ParameterReference ||
                 reference instanceof Variable) {

            colorizedText = LOCAL.colorize(escapedText);
        }
        else if (reference instanceof PackageReference) {
            colorizedText = colorizePackage(escapedText);
        }
        else if (reference instanceof Label ||
                 reference instanceof com.strobel.decompiler.ast.Label) {

            colorizedText = LABEL.colorize(escapedText);
        }
        else {
            colorizedText = escapedText;
        }

        writeAnsi(escapedText, colorizedText);
    }

    @SuppressWarnings("ConstantConditions")
    private String colorizeType(final String text, final TypeReference type) {
        if (type.isPrimitive()) {
            return KEYWORD.colorize(text);
        }

        final String packageName = type.getPackageName();
        final TypeDefinition resolvedType = type.resolve();

        if (StringUtilities.isNullOrEmpty(packageName)) {
            if (resolvedType != null && resolvedType.isAnnotation()) {
                return ATTRIBUTE.colorize(text);
            }
            else {
                return TYPE.colorize(text);
            }
        }

        String s = text;
        char delimiter = '.';
        String packagePrefix = packageName + delimiter;

        int arrayDepth = 0;

        while (arrayDepth < s.length() && s.charAt(arrayDepth) == '[') {
            arrayDepth++;
        }

        if (arrayDepth > 0) {
            s = s.substring(arrayDepth);
        }

        final boolean isSignature = s.startsWith("L") && s.endsWith(";");

        if (isSignature) {
            s = s.substring(1, s.length() - 1);
        }

        if (!StringUtilities.startsWith(s, packagePrefix)) {
            delimiter = '/';
            packagePrefix = packageName.replace('.', delimiter) + delimiter;
        }

        if (StringUtilities.startsWith(s, packagePrefix)) {
            final StringBuilder sb = new StringBuilder();
            final String[] packageParts = packageName.split("\\.");

            for (int i = 0; i < arrayDepth; i++) {
                sb.append('[');
            }

            if (isSignature) {
                sb.append('L');
            }

            for (int i = 0; i < packageParts.length; i++) {
                if (i != 0) {
                    sb.append(DELIMITER.colorize(String.valueOf(delimiter)));
                }

                sb.append(PACKAGE.colorize(packageParts[i]));
            }

            sb.append(DELIMITER.colorize(String.valueOf(delimiter)));

            final String typeName = s.substring(packagePrefix.length());
            final String[] typeParts = typeName.split("\\$|\\.");
            final Ansi typeColor = resolvedType != null && resolvedType.isAnnotation() ? ATTRIBUTE : TYPE;
            final boolean dollar = typeName.indexOf('$') >= 0;

            for (int i = 0; i < typeParts.length; i++) {
                if (i != 0) {
                    sb.append(DELIMITER.colorize(dollar ? "$" : "."));
                }

                sb.append(typeColor.colorize(typeParts[i]));
            }

            if (isSignature) {
                sb.append(';');
            }

            return sb.toString();
        }

        if (resolvedType != null && resolvedType.isAnnotation()) {
            return ATTRIBUTE.colorize(text);
        }
        else {
            return TYPE.colorize(text);
        }
    }

    private String colorizePackage(final String text) {
        final String[] packageParts = text.split("\\.");
        final StringBuilder sb = new StringBuilder(text.length() * 2);

        for (int i = 0; i < packageParts.length; i++) {
            if (i != 0) {
                sb.append(DELIMITER.colorize("."));
            }

            final String packagePart = packageParts[i];

            if ("*".equals(packagePart)) {
                sb.append(packagePart);
            }
            else {
                sb.append(PACKAGE.colorize(packagePart));
            }
        }

        return sb.toString();
    }
}
TOP

Related Classes of com.strobel.decompiler.AnsiTextOutput

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.