- /*
- * Copyright (c) 2001-2024, Jean Tessier
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of Jean Tessier nor the names of his contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- package com.jeantessier.classreader;
- import com.jeantessier.text.Hex;
- import java.io.*;
- import java.util.*;
- public class XMLPrinter extends Printer {
- public static final String DEFAULT_ENCODING = "utf-8";
- public static final String DEFAULT_DTD_PREFIX = "https://jeantessier.github.io/dependency-finder/dtd";
- private static final BitFormat format = new BitFormat(16);
- private boolean top = true;
- public XMLPrinter(PrintWriter out) {
- this(out, DEFAULT_ENCODING, DEFAULT_DTD_PREFIX);
- }
- public XMLPrinter(PrintWriter out, String encoding, String dtdPrefix) {
- super(out);
- appendHeader(encoding, dtdPrefix);
- }
- private Printer appendHeader(String encoding, String dtdPrefix) {
- append("<?xml version=\"1.0\" encoding=\"").append(encoding).append("\" ?>").eol();
- eol();
- append("<!DOCTYPE classfiles SYSTEM \"").append(dtdPrefix).append("/classfile.dtd\">").eol();
- eol();
- return this;
- }
- public void visitClassfiles(Collection<Classfile> classfiles) {
- indent().append("<classfiles>").eol();
- raiseIndent();
- super.visitClassfiles(classfiles);
- lowerIndent();
- indent().append("</classfiles>").eol();
- }
- public void visitClassfile(Classfile classfile) {
- indent().append("<!-- ").append(classfile.getClassName()).append(" -->").eol();
- indent().append("<classfile magic-number=\"0x").append(Integer.toHexString(classfile.getMagicNumber()).toUpperCase()).append("\" minor-version=\"").append(classfile.getMinorVersion()).append("\" major-version=\"").append(classfile.getMajorVersion()).append("\" access-flags=\"").append(format.format(classfile.getAccessFlags())).append("\">").eol();
- raiseIndent();
- top = true;
- classfile.getConstantPool().accept(this);
- top = false;
- if (classfile.isPublic()) indent().append("<public/>").eol();
- if (classfile.isFinal()) indent().append("<final/>").eol();
- if (classfile.isSuper()) indent().append("<super/>").eol();
- if (classfile.isInterface()) indent().append("<is-interface/>").eol();
- if (classfile.isAbstract()) indent().append("<abstract/>").eol();
- if (classfile.isSynthetic()) indent().append("<synthetic/>").eol();
- if (classfile.isAnnotation()) indent().append("<is-annotation/>").eol();
- if (classfile.isEnum()) indent().append("<enum/>").eol();
- if (classfile.isModule()) indent().append("<is-module/>").eol();
- indent();
- append("<this-class>");
- classfile.getRawClass().accept(this);
- append("</this-class>").eol();
- indent();
- append("<superclass>");
- if (classfile.hasSuperclass()) {
- classfile.getRawSuperclass().accept(this);
- }
- append("</superclass>").eol();
- if (!classfile.getAllInterfaces().isEmpty()) {
- indent().append("<interfaces>").eol();
- raiseIndent();
- for (Class_info class_info : classfile.getAllInterfaces()) {
- indent();
- append("<interface>");
- class_info.accept(this);
- append("</interface>").eol();
- }
- lowerIndent();
- indent().append("</interfaces>").eol();
- }
- if (!classfile.getAllFields().isEmpty()) {
- indent().append("<fields>").eol();
- raiseIndent();
- visitClassfileFields(classfile);
- lowerIndent();
- indent().append("</fields>").eol();
- }
- if (!classfile.getAllMethods().isEmpty()) {
- indent().append("<methods>").eol();
- raiseIndent();
- visitClassfileMethods(classfile);
- lowerIndent();
- indent().append("</methods>").eol();
- }
- if (!classfile.getAttributes().isEmpty()) {
- indent().append("<attributes>").eol();
- raiseIndent();
- visitClassfileAttributes(classfile);
- lowerIndent();
- indent().append("</attributes>").eol();
- }
- lowerIndent();
- indent().append("</classfile>").eol();
- }
- public void visitConstantPool(ConstantPool constantPool) {
- indent().append("<constant-pool>").eol();
- raiseIndent();
- super.visitConstantPool(constantPool);
- lowerIndent();
- indent().append("</constant-pool>").eol();
- }
- public void visitClass_info(Class_info entry) {
- if (top) {
- top = false;
- appendClassInfo(currentIndex(), entry);
- top = true;
- } else {
- // entry.getRawName().accept(this);
- append(entry.getName());
- }
- }
- public void visitFieldRef_info(FieldRef_info entry) {
- Class_info c = entry.getRawClass();
- NameAndType_info nat = entry.getRawNameAndType();
- if (top) {
- top = false;
- indent();
- append("<field-ref-info index=\"").append(currentIndex()).append("\">");
- append("<class>");
- c.accept(this);
- append("</class>");
- append("<type>");
- nat.getRawType().accept(this);
- append("</type>");
- append("<name>");
- nat.getRawName().accept(this);
- append("</name>");
- append("</field-ref-info>").eol();
- top = true;
- } else {
- append(DescriptorHelper.getType(nat.getType()));
- append(" ");
- append(entry.getFullSignature());
- }
- }
- public void visitMethodRef_info(MethodRef_info entry) {
- Class_info c = entry.getRawClass();
- NameAndType_info nat = entry.getRawNameAndType();
- if (top) {
- top = false;
- indent();
- append("<method-ref-info index=\"").append(currentIndex()).append("\">");
- append("<class>");
- c.accept(this);
- append("</class>");
- append("<name>");
- nat.getRawName().accept(this);
- append("</name>");
- append("<type>");
- nat.getRawType().accept(this);
- append("</type>");
- append("</method-ref-info>").eol();
- top = true;
- } else {
- if (!entry.isConstructor() && !entry.isStaticInitializer()) {
- append(DescriptorHelper.getReturnType(nat.getType())).append(" ");
- }
- append(entry.getFullSignature());
- }
- }
- public void visitInterfaceMethodRef_info(InterfaceMethodRef_info entry) {
- Class_info c = entry.getRawClass();
- NameAndType_info nat = entry.getRawNameAndType();
- if (top) {
- top = false;
- indent();
- append("<interface-method-ref-info index=\"").append(currentIndex()).append("\">");
- append("<class>");
- c.accept(this);
- append("</class>");
- append("<name>");
- nat.getRawName().accept(this);
- append("</name>");
- append("<type>");
- nat.getRawType().accept(this);
- append("</type>");
- append("</interface-method-ref-info>").eol();
- top = true;
- } else {
- append(DescriptorHelper.getReturnType(nat.getType()));
- append(" ");
- append(entry.getFullSignature());
- }
- }
- public void visitString_info(String_info entry) {
- if (top) {
- top = false;
- indent();
- append("<string-info index=\"").append(currentIndex()).append("\">");
- entry.getRawValue().accept(this);
- append("</string-info>").eol();
- top = true;
- } else {
- entry.getRawValue().accept(this);
- }
- }
- public void visitInteger_info(Integer_info entry) {
- if (top) {
- top = false;
- indent();
- append("<integer-info index=\"").append(currentIndex()).append("\">");
- append(entry.getValue());
- append("</integer-info>").eol();
- top = true;
- } else {
- append(entry.getValue());
- }
- }
- public void visitFloat_info(Float_info entry) {
- if (top) {
- top = false;
- indent();
- append("<float-info index=\"").append(currentIndex()).append("\">");
- append(entry.getValue());
- append("</float-info>").eol();
- top = true;
- } else {
- append(entry.getValue());
- }
- }
- public void visitLong_info(Long_info entry) {
- if (top) {
- top = false;
- indent();
- append("<long-info index=\"").append(currentIndex()).append("\">");
- append(entry.getValue());
- append("</long-info>").eol();
- top = true;
- } else {
- append(entry.getValue());
- }
- }
- public void visitDouble_info(Double_info entry) {
- if (top) {
- top = false;
- indent();
- append("<double-info index=\"").append(currentIndex()).append("\">");
- append(entry.getValue());
- append("</double-info>").eol();
- top = true;
- } else {
- append(entry.getValue());
- }
- }
- public void visitNameAndType_info(NameAndType_info entry) {
- if (top) {
- top = false;
- indent();
- append("<name-and-type-info index=\"").append(currentIndex()).append("\">");
- append("<name>");
- entry.getRawName().accept(this);
- append("</name>");
- append("<type>");
- entry.getRawType().accept(this);
- append("</type>");
- append("</name-and-type-info>").eol();
- top = true;
- } else {
- entry.getRawName().accept(this);
- append(" ");
- entry.getRawType().accept(this);
- }
- }
- public void visitUTF8_info(UTF8_info entry) {
- if (top) {
- top = false;
- indent().append("<utf8-info index=\"").append(currentIndex()).append("\">");
- append(escapeXMLCharacters(entry.getValue()));
- append("</utf8-info>").eol();
- top = true;
- } else {
- append(escapeXMLCharacters(entry.getValue()));
- }
- }
- public void visitMethodHandle_info(MethodHandle_info entry) {
- if (top) {
- top = false;
- indent();
- append("<method-handle-info index=\"").append(currentIndex()).append("\">");
- append("<reference-kind kind=\"").append(entry.getRawReferenceKind()).append("\">");
- append(entry.getReferenceKind().getDescription());
- append("</reference-kind>");
- append("<reference index=\"").append(entry.getReferenceIndex()).append("\">");
- entry.getReference().accept(this);
- append("</reference>");
- append("</method-handle-info>").eol();
- top = true;
- } else {
- append(entry.getReferenceKind().getDescription());
- append(" ");
- entry.getReference().accept(this);
- }
- }
- public void visitMethodType_info(MethodType_info entry) {
- if (top) {
- top = false;
- indent();
- append("<method-type-info index=\"").append(currentIndex()).append("\">");
- entry.getRawDescriptor().accept(this);
- append("</method-type-info>").eol();
- top = true;
- } else {
- entry.getRawDescriptor().accept(this);
- }
- }
- public void visitDynamic_info(Dynamic_info entry) {
- NameAndType_info nat = entry.getRawNameAndType();
- if (top) {
- top = false;
- indent();
- append("<dynamic-info index=\"").append(currentIndex()).append("\">");
- append("<bootstrap-method-attr index=\"").append(entry.getBootstrapMethodAttrIndex()).append("\"/>");
- append("<name>");
- nat.getRawName().accept(this);
- append("</name>");
- append("<type>");
- nat.getRawType().accept(this);
- append("</type>");
- append("</dynamic-info>").eol();
- top = true;
- } else {
- if (!entry.isStaticInitializer()) {
- append(DescriptorHelper.getReturnType(nat.getType())).append(" ");
- }
- append(entry.getSignature());
- }
- }
- public void visitInvokeDynamic_info(InvokeDynamic_info entry) {
- NameAndType_info nat = entry.getRawNameAndType();
- if (top) {
- top = false;
- indent();
- append("<invoke-dynamic-info index=\"").append(currentIndex()).append("\">");
- append("<bootstrap-method-attr index=\"").append(entry.getBootstrapMethodAttrIndex()).append("\"/>");
- append("<name>");
- nat.getRawName().accept(this);
- append("</name>");
- append("<type>");
- nat.getRawType().accept(this);
- append("</type>");
- append("</invoke-dynamic-info>").eol();
- top = true;
- } else {
- if (!entry.isStaticInitializer()) {
- append(DescriptorHelper.getReturnType(nat.getType())).append(" ");
- }
- append(entry.getSignature());
- }
- }
- public void visitModule_info(Module_info entry) {
- if (top) {
- top = false;
- indent();
- append("<module index=\"").append(currentIndex()).append("\">");
- // entry.getRawName().accept(this);
- append(entry.getName());
- append("</module>").eol();
- top = true;
- } else {
- // entry.getRawName().accept(this);
- append(entry.getName());
- }
- }
- public void visitPackage_info(Package_info entry) {
- if (top) {
- top = false;
- indent();
- append("<package index=\"").append(currentIndex()).append("\">");
- // entry.getRawName().accept(this);
- append(entry.getName());
- append("</package>").eol();
- top = true;
- } else {
- // entry.getRawName().accept(this);
- append(entry.getName());
- }
- }
- public void visitUnusableEntry(UnusableEntry entry) {
- if (top) {
- top = false;
- indent().append("<unusable index=\"").append(currentIndex()).append("\">").append(entry.getReason()).append("</unusable>").eol();
- top = true;
- } else {
- append(entry);
- }
- }
- public void visitField_info(Field_info entry) {
- indent().append("<field-info access-flags=\"").append(format.format(entry.getAccessFlags())).append("\">").eol();
- raiseIndent();
- if (entry.isPublic()) indent().append("<public/>").eol();
- if (entry.isProtected()) indent().append("<protected/>").eol();
- if (entry.isPrivate()) indent().append("<private/>").eol();
- if (entry.isStatic()) indent().append("<static/>").eol();
- if (entry.isFinal()) indent().append("<final/>").eol();
- if (entry.isVolatile()) indent().append("<volatile/>").eol();
- if (entry.isTransient()) indent().append("<transient/>").eol();
- if (entry.isSynthetic()) indent().append("<synthetic/>").eol();
- if (entry.isEnum()) indent().append("<enum/>").eol();
- indent();
- append("<name>");
- entry.getRawName().accept(this);
- append("</name>").eol();
- indent().append("<type>").append(entry.getType()).append("</type>").eol();
- if (!entry.getAttributes().isEmpty()) {
- indent().append("<attributes>").eol();
- raiseIndent();
- super.visitField_info(entry);
- lowerIndent();
- indent().append("</attributes>").eol();
- }
- lowerIndent();
- indent().append("</field-info>").eol();
- }
- public void visitMethod_info(Method_info entry) {
- indent().append("<method-info access-flags=\"").append(format.format(entry.getAccessFlags())).append("\">").eol();
- raiseIndent();
- if (entry.isPublic()) indent().append("<public/>").eol();
- if (entry.isProtected()) indent().append("<protected/>").eol();
- if (entry.isPrivate()) indent().append("<private/>").eol();
- if (entry.isStatic()) indent().append("<static/>").eol();
- if (entry.isFinal()) indent().append("<final/>").eol();
- if (entry.isSynchronized()) indent().append("<synchronized/>").eol();
- if (entry.isBridge()) indent().append("<bridge/>").eol();
- if (entry.isVarargs()) indent().append("<varargs/>").eol();
- if (entry.isNative()) indent().append("<native/>").eol();
- if (entry.isAbstract()) indent().append("<abstract/>").eol();
- if (entry.isStrict()) indent().append("<strict/>").eol();
- if (entry.isSynthetic()) indent().append("<synthetic/>").eol();
- indent();
- append("<name>");
- entry.getRawName().accept(this);
- append("</name>").eol();
- if (!entry.getName().equals("<init>") && !entry.getName().equals("<clinit>")) {
- indent().append("<return-type>").append((entry.getReturnType() != null) ? entry.getReturnType() : "void").append("</return-type>").eol();
- }
- indent().append("<signature>").append(entry.getSignature()).append("</signature>").eol();
- if (!entry.getAttributes().isEmpty()) {
- indent().append("<attributes>").eol();
- raiseIndent();
- super.visitMethod_info(entry);
- lowerIndent();
- indent().append("</attributes>").eol();
- }
- lowerIndent();
- indent().append("</method-info>").eol();
- }
- public void visitConstantValue_attribute(ConstantValue_attribute attribute) {
- indent().append("<constant-value-attribute>");
- attribute.getRawValue().accept(this);
- append("</constant-value-attribute>").eol();
- }
- public void visitCode_attribute(Code_attribute attribute) {
- indent().append("<code-attribute>").eol();
- raiseIndent();
- indent().append("<length>").append(attribute.getCode().length).append("</length>").eol();
- indent().append("<instructions>").eol();
- raiseIndent();
- for (Instruction instruction : attribute) {
- instruction.accept(this);
- }
- lowerIndent();
- indent().append("</instructions>").eol();
- if (!attribute.getExceptionHandlers().isEmpty()) {
- indent().append("<exception-handlers>").eol();
- raiseIndent();
- for (ExceptionHandler exceptionHandler : attribute.getExceptionHandlers()) {
- exceptionHandler.accept(this);
- }
- lowerIndent();
- indent().append("</exception-handlers>").eol();
- }
- if (!attribute.getAttributes().isEmpty()) {
- indent().append("<attributes>").eol();
- raiseIndent();
- for (Attribute_info attribute_info : attribute.getAttributes()) {
- attribute_info.accept(this);
- }
- lowerIndent();
- indent().append("</attributes>").eol();
- }
- lowerIndent();
- indent().append("</code-attribute>").eol();
- }
- public void visitStackMapTable_attribute(StackMapTable_attribute attribute) {
- indent().append("<stack-map-table-attribute>").eol();
- raiseIndent();
- super.visitStackMapTable_attribute(attribute);
- lowerIndent();
- indent().append("</stack-map-table-attribute>").eol();
- }
- public void visitExceptions_attribute(Exceptions_attribute attribute) {
- indent().append("<exceptions-attribute>").eol();
- raiseIndent();
- attribute.getExceptions().forEach(exception -> {
- indent();
- append("<exception>");
- exception.accept(this);
- append("</exception>").eol();
- });
- lowerIndent();
- indent().append("</exceptions-attribute>").eol();
- }
- public void visitInnerClasses_attribute(InnerClasses_attribute attribute) {
- indent().append("<inner-classes-attribute>").eol();
- raiseIndent();
- super.visitInnerClasses_attribute(attribute);
- lowerIndent();
- indent().append("</inner-classes-attribute>").eol();
- }
- public void visitEnclosingMethod_attribute(EnclosingMethod_attribute attribute) {
- indent().append("<enclosing-method-attribute>").eol();
- raiseIndent();
- appendClassInfo(attribute.getClassIndex(), attribute.getRawClassInfo());
- indent().append("<method>");
- if (attribute.hasMethod()) {
- NameAndType_info nat = attribute.getRawMethod();
- if (nat.getName().equals("<init>")) {
- String className = attribute.getClassInfo();
- className = className.substring(className.lastIndexOf(".") + 1);
- append(className).append(DescriptorHelper.getSignature(nat.getType()));
- } else {
- append(DescriptorHelper.getReturnType(nat.getType())).append(" ").append(nat.getName()).append(DescriptorHelper.getSignature(nat.getType()));
- }
- }
- append("</method>").eol();
- lowerIndent();
- indent().append("</enclosing-method-attribute>").eol();
- }
- public void visitSynthetic_attribute(Synthetic_attribute attribute) {
- indent().append("<synthetic-attribute/>").eol();
- }
- public void visitSignature_attribute(Signature_attribute attribute) {
- indent().append("<signature-attribute>");
- attribute.getRawSignature().accept(this);
- append("</signature-attribute>").eol();
- }
- public void visitSourceFile_attribute(SourceFile_attribute attribute) {
- indent().append("<source-file-attribute>").append(attribute.getSourceFile()).append("</source-file-attribute>").eol();
- }
- public void visitSourceDebugExtension_attribute(SourceDebugExtension_attribute attribute) {
- indent().append("<source-debug-extension>").append(attribute.getDebugExtension()).append("</source-debug-extension>").eol();
- }
- public void visitLineNumberTable_attribute(LineNumberTable_attribute attribute) {
- indent().append("<line-number-table-attribute>").eol();
- raiseIndent();
- super.visitLineNumberTable_attribute(attribute);
- lowerIndent();
- indent().append("</line-number-table-attribute>").eol();
- }
- public void visitLocalVariableTable_attribute(LocalVariableTable_attribute attribute) {
- indent().append("<local-variable-table-attribute>").eol();
- raiseIndent();
- super.visitLocalVariableTable_attribute(attribute);
- lowerIndent();
- indent().append("</local-variable-table-attribute>").eol();
- }
- public void visitLocalVariableTypeTable_attribute(LocalVariableTypeTable_attribute attribute) {
- indent().append("<local-variable-type-table-attribute>").eol();
- raiseIndent();
- super.visitLocalVariableTypeTable_attribute(attribute);
- lowerIndent();
- indent().append("</local-variable-type-table-attribute>").eol();
- }
- public void visitDeprecated_attribute(Deprecated_attribute attribute) {
- indent().append("<deprecated-attribute/>").eol();
- }
- public void visitRuntimeVisibleAnnotations_attribute(RuntimeVisibleAnnotations_attribute attribute) {
- indent().append("<runtime-visible-annotations-attribute>").eol();
- raiseIndent();
- super.visitRuntimeVisibleAnnotations_attribute(attribute);
- lowerIndent();
- indent().append("</runtime-visible-annotations-attribute>").eol();
- }
- public void visitRuntimeInvisibleAnnotations_attribute(RuntimeInvisibleAnnotations_attribute attribute) {
- indent().append("<runtime-invisible-annotations-attribute>").eol();
- raiseIndent();
- super.visitRuntimeInvisibleAnnotations_attribute(attribute);
- lowerIndent();
- indent().append("</runtime-invisible-annotations-attribute>").eol();
- }
- protected void visitRuntimeAnnotations_attribute(RuntimeAnnotations_attribute attribute) {
- indent().append("<annotations>").eol();
- raiseIndent();
- super.visitRuntimeAnnotations_attribute(attribute);
- lowerIndent();
- indent().append("</annotations>").eol();
- }
- public void visitRuntimeVisibleParameterAnnotations_attribute(RuntimeVisibleParameterAnnotations_attribute attribute) {
- indent().append("<runtime-visible-parameter-annotations-attribute>").eol();
- raiseIndent();
- super.visitRuntimeVisibleParameterAnnotations_attribute(attribute);
- lowerIndent();
- indent().append("</runtime-visible-parameter-annotations-attribute>").eol();
- }
- public void visitRuntimeInvisibleParameterAnnotations_attribute(RuntimeInvisibleParameterAnnotations_attribute attribute) {
- indent().append("<runtime-invisible-parameter-annotations-attribute>").eol();
- raiseIndent();
- super.visitRuntimeInvisibleParameterAnnotations_attribute(attribute);
- lowerIndent();
- indent().append("</runtime-invisible-parameter-annotations-attribute>").eol();
- }
- protected void visitRuntimeParameterAnnotations_attribute(RuntimeParameterAnnotations_attribute attribute) {
- indent().append("<parameter-annotations>").eol();
- raiseIndent();
- super.visitRuntimeParameterAnnotations_attribute(attribute);
- lowerIndent();
- indent().append("</parameter-annotations>").eol();
- }
- public void visitRuntimeVisibleTypeAnnotations_attribute(RuntimeVisibleTypeAnnotations_attribute attribute) {
- indent().append("<runtime-visible-type-annotations-attribute>").eol();
- raiseIndent();
- super.visitRuntimeVisibleTypeAnnotations_attribute(attribute);
- lowerIndent();
- indent().append("</runtime-visible-type-annotations-attribute>").eol();
- }
- public void visitRuntimeInvisibleTypeAnnotations_attribute(RuntimeInvisibleTypeAnnotations_attribute attribute) {
- indent().append("<runtime-invisible-type-annotations-attribute>").eol();
- raiseIndent();
- super.visitRuntimeInvisibleTypeAnnotations_attribute(attribute);
- lowerIndent();
- indent().append("</runtime-invisible-type-annotations-attribute>").eol();
- }
- protected void visitRuntimeTypeAnnotations_attribute(RuntimeTypeAnnotations_attribute attribute) {
- indent().append("<type-annotations>").eol();
- raiseIndent();
- super.visitRuntimeTypeAnnotations_attribute(attribute);
- lowerIndent();
- indent().append("</type-annotations>").eol();
- }
- public void visitAnnotationDefault_attribute(AnnotationDefault_attribute attribute) {
- indent().append("<annotation-default-attribute>").eol();
- raiseIndent();
- super.visitAnnotationDefault_attribute(attribute);
- lowerIndent();
- indent().append("</annotation-default-attribute>").eol();
- }
- public void visitBootstrapMethods_attribute(BootstrapMethods_attribute attribute) {
- indent().append("<bootstrap-methods-attribute>").eol();
- raiseIndent();
- super.visitBootstrapMethods_attribute(attribute);
- lowerIndent();
- indent().append("</bootstrap-methods-attribute>").eol();
- }
- public void visitMethodParameters_attribute(MethodParameters_attribute attribute) {
- indent().append("<method-parameters-attribute>").eol();
- raiseIndent();
- super.visitMethodParameters_attribute(attribute);
- lowerIndent();
- indent().append("</method-parameters-attribute>").eol();
- }
- public void visitModule_attribute(Module_attribute attribute) {
- indent().append("<module-attribute module-flags=\"").append(format.format(attribute.getModuleFlags())).append("\">").eol();
- raiseIndent();
- indent();
- append("<name index=\"").append(attribute.getModuleNameIndex()).append("\">");
- attribute.getRawModuleName().accept(this);
- append("</name>").eol();
- if (attribute.isOpen()) indent().append("<open/>").eol();
- if (attribute.isSynthetic()) indent().append("<synthetic/>").eol();
- if (attribute.isMandated()) indent().append("<mandated/>").eol();
- if (attribute.hasModuleVersion()) {
- indent();
- append("<version index=\"").append(attribute.getModuleVersionIndex()).append("\">");
- attribute.getRawModuleVersion().accept(this);
- append("</version>").eol();
- }
- super.visitModule_attribute(attribute);
- lowerIndent();
- indent().append("</module-attribute>").eol();
- }
- public void visitModulePackages_attribute(ModulePackages_attribute attribute) {
- indent().append("<module-packages-attribute>").eol();
- raiseIndent();
- super.visitModulePackages_attribute(attribute);
- lowerIndent();
- indent().append("</module-packages-attribute>").eol();
- }
- public void visitModuleMainClass_attribute(ModuleMainClass_attribute attribute) {
- indent();
- append("<module-main-class-attribute index=\"").append(attribute.getMainClassIndex()).append("\">");
- attribute.getRawMainClass().accept(this);
- append("</module-main-class-attribute>").eol();
- }
- public void visitNestHost_attribute(NestHost_attribute attribute) {
- indent();
- append("<nest-host-attribute index=\"").append(attribute.getHostClassIndex()).append("\">");
- attribute.getRawHostClass().accept(this);
- append("</nest-host-attribute>").eol();
- }
- public void visitNestMembers_attribute(NestMembers_attribute attribute) {
- indent().append("<nest-members-attribute>").eol();
- raiseIndent();
- super.visitNestMembers_attribute(attribute);
- lowerIndent();
- indent().append("</nest-members-attribute>").eol();
- }
- public void visitRecord_attribute(Record_attribute attribute) {
- indent().append("<record-attribute>").eol();
- raiseIndent();
- super.visitRecord_attribute(attribute);
- lowerIndent();
- indent().append("</record-attribute>").eol();
- }
- public void visitPermittedSubclasses_attribute(PermittedSubclasses_attribute attribute) {
- indent().append("<permitted-subclasses-attribute>").eol();
- raiseIndent();
- super.visitPermittedSubclasses_attribute(attribute);
- lowerIndent();
- indent().append("</permitted-subclasses-attribute>").eol();
- }
- public void visitCustom_attribute(Custom_attribute attribute) {
- indent().append("<custom-attribute name=\"").append(escapeXMLCharacters(attribute.getName())).append("\">").append(Hex.toString(attribute.getInfo())).append("</custom-attribute>").eol();
- }
- public void visitInstruction(Instruction instruction) {
- indent();
- append("<instruction pc=\"").append(instruction.getStart()).append("\" length=\"").append(instruction.getLength()).append("\" op-code=\"0x").append(String.format("%02X", instruction.getOpcode())).append("\"");
- switch (instruction.getOpcode()) {
- case 0x02: // iconst_m1
- case 0x03: // iconst_0
- case 0x04: // iconst_1
- case 0x05: // iconst_2
- case 0x06: // iconst_3
- case 0x07: // iconst_4
- case 0x08: // iconst_5
- case 0x09: // lconst_0
- case 0x0a: // lconst_1
- case 0x0b: // fconst_0
- case 0x0c: // fconst_1
- case 0x0d: // fconst_2
- case 0x0e: // dconst_0
- case 0x0f: // dconst_1
- append(" value=\"").append(instruction.getValue()).append("\">");
- append(instruction);
- break;
- case 0x10: // bipush
- case 0x11: // sipush
- append(" value=\"").append(instruction.getValue()).append("\">");
- append(instruction).append(" ").append(instruction.getValue());
- break;
- case 0x12: // ldc
- case 0x13: // ldc_w
- case 0x14: // ldc2_w
- case 0xb2: // getstatic
- case 0xb3: // putstatic
- case 0xb4: // getfield
- case 0xb5: // putfield
- case 0xb6: // invokevirtual
- case 0xb7: // invokespecial
- case 0xb8: // invokestatic
- case 0xb9: // invokeinterface
- case 0xbb: // new
- case 0xbd: // anewarray
- case 0xc0: // checkcast
- case 0xc1: // instanceof
- case 0xc5: // multianewarray
- append(" index=\"").append(instruction.getIndex()).append("\">");
- append(instruction);
- append(" ");
- instruction.getIndexedConstantPoolEntry().accept(this);
- break;
- case 0x1a: // iload_0
- case 0x1e: // lload_0
- case 0x22: // fload_0
- case 0x26: // dload_0
- case 0x2a: // aload_0
- case 0x3b: // istore_0
- case 0x3f: // lstore_0
- case 0x43: // fstore_0
- case 0x47: // dstore_0
- case 0x4b: // astore_0
- case 0x1b: // iload_1
- case 0x1f: // lload_1
- case 0x23: // fload_1
- case 0x27: // dload_1
- case 0x2b: // aload_1
- case 0x3c: // istore_1
- case 0x40: // lstore_1
- case 0x44: // fstore_1
- case 0x48: // dstore_1
- case 0x4c: // astore_1
- case 0x1c: // iload_2
- case 0x20: // lload_2
- case 0x24: // fload_2
- case 0x28: // dload_2
- case 0x2c: // aload_2
- case 0x3d: // istore_2
- case 0x41: // lstore_2
- case 0x45: // fstore_2
- case 0x49: // dstore_2
- case 0x4d: // astore_2
- case 0x1d: // iload_3
- case 0x21: // lload_3
- case 0x25: // fload_3
- case 0x29: // dload_3
- case 0x2d: // aload_3
- case 0x3e: // istore_3
- case 0x42: // lstore_3
- case 0x46: // fstore_3
- case 0x4a: // dstore_3
- case 0x4e: // astore_3
- case 0x15: // iload
- case 0x16: // llload
- case 0x17: // fload
- case 0x18: // dload
- case 0x19: // aload
- case 0x36: // istore
- case 0x37: // lstore
- case 0x38: // fstore
- case 0x39: // dstore
- case 0x3a: // astore
- case 0xa9: // ret
- append(" index=\"").append(instruction.getIndex()).append("\">");
- append(instruction);
- appendLocalVariable(instruction.getIndexedLocalVariable());
- break;
- case 0x99: // ifeq
- case 0x9a: // ifne
- case 0x9b: // iflt
- case 0x9c: // ifge
- case 0x9d: // ifgt
- case 0x9e: // ifle
- case 0x9f: // if_icmpeq
- case 0xa0: // if_icmpne
- case 0xa1: // if_icmplt
- case 0xa2: // if_icmpge
- case 0xa3: // if_icmpgt
- case 0xa4: // if_icmple
- case 0xa5: // if_acmpeq
- case 0xa6: // if_acmpne
- case 0xa7: // goto
- case 0xa8: // jsr
- case 0xc6: // ifnull
- case 0xc7: // ifnonnull
- case 0xc8: // goto_w
- case 0xc9: // jsr_w
- append(" offset=\"").append(instruction.getOffset()).append("\">");
- append(instruction).append(" ").append(instruction.getStart() + instruction.getOffset());
- break;
- case 0x84: // iinc
- append(" index=\"").append(instruction.getIndex()).append("\" value=\"").append(instruction.getValue()).append("\">");
- append(instruction);
- appendLocalVariable(instruction.getIndexedLocalVariable());
- break;
- case 0xaa: // tableswitch
- append(" padding=\"").append(instruction.getPadding()).append("\" default=\"").appendSwitchDefault(instruction).append("\" low=\"").append(instruction.getLow()).append("\" high=\"").append(instruction.getHigh()).append("\">");
- append(instruction).append(" ").appendTableSwitch(instruction, " | ");
- break;
- case 0xab: // lookupswitch
- append(" padding=\"").append(instruction.getPadding()).append("\" default=\"").appendSwitchDefault(instruction).append("\" npairs=\"").append(instruction.getNPairs()).append("\">");
- append(instruction).append(" ").appendLookupSwitch(instruction, " | ");
- break;
- case 0xba: // invokedynamic
- append(" index=\"").append(instruction.getIndex()).append("\">");
- append(instruction);
- var indexedEntry = instruction.getIndexedConstantPoolEntry();
- if (indexedEntry instanceof Dynamic_info dynamic_info) {
- append(" ").append(dynamic_info.getName());
- } else if (indexedEntry instanceof InvokeDynamic_info invokeDynamic_info) {
- append(" ").append(invokeDynamic_info.getName());
- }
- // TODO: Replace with type pattern matching in switch expression in Java 21
- // switch (instruction.getIndexedConstantPoolEntry()) {
- // case Dynamic_info entry -> append(" ").append(entry.getName());
- // case InvokeDynamic_info entry -> append(" ").append(entry.getName());
- // default -> append("");
- // }
- instruction.getDynamicConstantPoolEntries().forEach(entry -> {
- append(" ");
- entry.accept(this);
- });
- break;
- case 0xc4: // wide
- if (instruction.getByte(1) == 0x84 /* iinc */) {
- append(" index=\"").append(instruction.getIndex()).append("\" value=\"").append(instruction.getValue()).append("\">");
- } else {
- append(" index=\"").append(instruction.getIndex()).append("\">");
- }
- append(instruction);
- appendLocalVariable(instruction.getIndexedLocalVariable());
- break;
- default:
- append(">");
- append(instruction);
- break;
- }
- append("</instruction>").eol();
- }
- public void visitExceptionHandler(ExceptionHandler helper) {
- indent();
- append("<exception-handler>");
- append("<start-pc>").append(helper.getStartPC()).append("</start-pc>");
- append("<end-pc>").append(helper.getEndPC()).append("</end-pc>");
- append("<handler-pc>").append(helper.getHandlerPC()).append("</handler-pc>");
- append("<catch-type>");
- if (helper.hasCatchType()) {
- helper.getRawCatchType().accept(this);
- }
- append("</catch-type>");
- append("</exception-handler>").eol();
- }
- public void visitInnerClass(InnerClass helper) {
- indent().append("<inner-class access-flags=\"").append(format.format(helper.getAccessFlags())).append("\">").eol();
- raiseIndent();
- if (helper.isPublic()) indent().append("<public/>").eol();
- if (helper.isProtected()) indent().append("<protected/>").eol();
- if (helper.isPrivate()) indent().append("<private/>").eol();
- if (helper.isStatic()) indent().append("<static/>").eol();
- if (helper.isFinal()) indent().append("<final/>").eol();
- if (helper.isInterface()) indent().append("<is-interface/>").eol();
- if (helper.isAbstract()) indent().append("<abstract/>").eol();
- if (helper.isSynthetic()) indent().append("<synthetic/>").eol();
- if (helper.isAnnotation()) indent().append("<is-annotation/>").eol();
- if (helper.isEnum()) indent().append("<enum/>").eol();
- indent();
- append("<inner-class-info>");
- helper.getRawInnerClassInfo().accept(this);
- append("</inner-class-info>").eol();
- indent();
- append("<outer-class-info>");
- if (helper.hasOuterClassInfo()) {
- helper.getRawOuterClassInfo().accept(this);
- }
- append("</outer-class-info>").eol();
- indent();
- append("<inner-name>");
- if (helper.hasInnerName()) {
- helper.getRawInnerName().accept(this);
- }
- append("</inner-name>").eol();
- lowerIndent();
- indent().append("</inner-class>").eol();
- }
- public void visitLineNumber(LineNumber helper) {
- indent();
- append("<line-number>");
- append("<start-pc>").append(helper.getStartPC()).append("</start-pc>");
- append("<line>").append(helper.getLineNumber()).append("</line>");
- append("</line-number>").eol();
- }
- public void visitLocalVariable(LocalVariable helper) {
- indent();
- append("<local-variable pc=\"").append(helper.getStartPC()).append("\" length=\"").append(helper.getLength()).append("\" index=\"").append(helper.getIndex()).append("\">");
- append("<name>");
- helper.getRawName().accept(this);
- append("</name>");
- append("<type>").append(DescriptorHelper.getType(helper.getDescriptor())).append("</type>");
- append("</local-variable>").eol();
- }
- public void visitLocalVariableType(LocalVariableType helper) {
- indent();
- append("<local-variable-type pc=\"").append(helper.getStartPC()).append("\" length=\"").append(helper.getLength()).append("\" index=\"").append(helper.getIndex()).append("\">");
- append("<name>");
- helper.getRawName().accept(this);
- append("</name>");
- append("<signature>");
- helper.getRawSignature().accept(this);
- append("</signature>");
- append("</local-variable-type>").eol();
- }
- public void visitBootstrapMethod(BootstrapMethod helper) {
- indent().append("<bootstrap-method>").eol();
- raiseIndent();
- indent();
- append("<bootstrap-method-ref index=\"").append(helper.getBootstrapMethodRef()).append("\">");
- helper.getBootstrapMethod().accept(this);
- append("</bootstrap-method-ref>").eol();
- indent().append("<arguments>").eol();
- raiseIndent();
- helper.getArgumentIndices()
- .forEach(index -> {
- indent();
- append("<argument index=\"").append(index).append("\">");
- helper.getArgument(index).accept(this);
- append("</argument>").eol();
- });
- lowerIndent();
- indent().append("</arguments>").eol();
- lowerIndent();
- indent().append("</bootstrap-method>").eol();
- }
- public void visitMethodParameter(MethodParameter helper) {
- indent().append("<method-parameter access-flags=\"").append(format.format(helper.getAccessFlags())).append("\">").eol();
- raiseIndent();
- if (helper.hasName()) {
- indent();
- append("<name>");
- helper.getRawName().accept(this);
- append("</name>").eol();
- }
- if (helper.isFinal()) indent().append("<final/>").eol();
- if (helper.isSynthetic()) indent().append("<synthetic/>").eol();
- if (helper.isMandated()) indent().append("<mandated/>").eol();
- lowerIndent();
- indent().append("</method-parameter>").eol();
- }
- public void visitModuleRequires(ModuleRequires helper) {
- indent().append("<module-requires requires-flags=\"").append(format.format(helper.getRequiresFlags())).append("\">").eol();
- raiseIndent();
- indent();
- append("<module index=\"").append(helper.getRequiresIndex()).append("\">");
- helper.getRawRequires().accept(this);
- append("</module>").eol();
- if (helper.isTransitive()) indent().append("<transitive/>").eol();
- if (helper.isStaticPhase()) indent().append("<static-phase/>").eol();
- if (helper.isSynthetic()) indent().append("<synthetic/>").eol();
- if (helper.isMandated()) indent().append("<mandated/>").eol();
- if (helper.hasRequiresVersion()) {
- indent();
- append("<version index=\"").append(helper.getRequiresVersionIndex()).append("\">");
- helper.getRawRequiresVersion().accept(this);
- append("</version>").eol();
- }
- lowerIndent();
- indent().append("</module-requires>").eol();
- }
- public void visitModuleExports(ModuleExports helper) {
- indent().append("<module-exports exports-flags=\"").append(format.format(helper.getExportsFlags())).append("\">").eol();
- raiseIndent();
- indent();
- append("<package index=\"").append(helper.getExportsIndex()).append("\">");
- helper.getRawExports().accept(this);
- append("</package>").eol();
- if (helper.isSynthetic()) indent().append("<synthetic/>").eol();
- if (helper.isMandated()) indent().append("<mandated/>").eol();
- helper.getExportsTos().forEach(moduleExportsTo -> moduleExportsTo.accept(this));
- lowerIndent();
- indent().append("</module-exports>").eol();
- }
- public void visitModuleExportsTo(ModuleExportsTo helper) {
- indent().append("<module-exports-to>").eol();
- raiseIndent();
- indent();
- append("<module index=\"").append(helper.getExportsToIndex()).append("\">");
- helper.getRawExportsTo().accept(this);
- append("</module>").eol();
- lowerIndent();
- indent().append("</module-exports-to>").eol();
- }
- public void visitModuleOpens(ModuleOpens helper) {
- indent().append("<module-opens opens-flags=\"").append(format.format(helper.getOpensFlags())).append("\">").eol();
- raiseIndent();
- indent();
- append("<package index=\"").append(helper.getOpensIndex()).append("\">");
- helper.getRawOpens().accept(this);
- append("</package>").eol();
- if (helper.isSynthetic()) indent().append("<synthetic/>").eol();
- if (helper.isMandated()) indent().append("<mandated/>").eol();
- helper.getOpensTos().forEach(moduleOpensTo -> moduleOpensTo.accept(this));
- lowerIndent();
- indent().append("</module-opens>").eol();
- }
- public void visitModuleOpensTo(ModuleOpensTo helper) {
- indent().append("<module-opens-to>").eol();
- raiseIndent();
- indent();
- append("<module index=\"").append(helper.getOpensToIndex()).append("\">");
- helper.getRawOpensTo().accept(this);
- append("</module>").eol();
- lowerIndent();
- indent().append("</module-opens-to>").eol();
- }
- public void visitModuleUses(ModuleUses helper) {
- indent().append("<module-uses>").eol();
- raiseIndent();
- appendClassInfo(helper.getUsesIndex(), helper.getRawUses());
- lowerIndent();
- indent().append("</module-uses>").eol();
- }
- public void visitModuleProvides(ModuleProvides helper) {
- indent().append("<module-provides>").eol();
- raiseIndent();
- appendClassInfo(helper.getProvidesIndex(), helper.getRawProvides());
- helper.getProvidesWiths().forEach(moduleProvidesWith -> moduleProvidesWith.accept(this));
- lowerIndent();
- indent().append("</module-provides>").eol();
- }
- public void visitModuleProvidesWith(ModuleProvidesWith helper) {
- indent().append("<module-provides-with>").eol();
- raiseIndent();
- appendClassInfo(helper.getProvidesWithIndex(), helper.getRawProvidesWith());
- lowerIndent();
- indent().append("</module-provides-with>").eol();
- }
- public void visitModulePackage(ModulePackage helper) {
- indent();
- append("<package index=\"").append(helper.getPackageIndex()).append("\">");
- helper.getRawPackage().accept(this);
- append("</package>").eol();
- }
- public void visitNestMember(NestMember helper) {
- appendClassInfo(helper.getMemberClassIndex(), helper.getRawMemberClass());
- }
- public void visitRecordComponent_info(RecordComponent_info helper) {
- indent().append("<record-component>").eol();
- raiseIndent();
- indent();
- append("<name index=\"").append(helper.getNameIndex()).append("\">");
- helper.getRawName().accept(this);
- append("</name>").eol();
- indent().append("<type index=\"").append(helper.getDescriptorIndex()).append("\">").append(helper.getType()).append("</type>").eol();
- indent().append("<attributes>").eol();
- raiseIndent();
- super.visitRecordComponent_info(helper);
- lowerIndent();
- indent().append("</attributes>").eol();
- lowerIndent();
- indent().append("</record-component>").eol();
- }
- public void visitPermittedSubclass(PermittedSubclass helper) {
- appendClassInfo(helper.getSubclassIndex(), helper.getRawSubclass());
- }
- public void visitAnnotation(Annotation helper) {
- indent().append("<annotation>").eol();
- raiseIndent();
- indent().append("<type>").append(helper.getType()).append("</type>").eol();
- indent().append("<element-value-pairs>").eol();
- raiseIndent();
- super.visitAnnotation(helper);
- lowerIndent();
- indent().append("</element-value-pairs>").eol();
- lowerIndent();
- indent().append("</annotation>").eol();
- }
- public void visitParameterAnnotation(ParameterAnnotation helper) {
- indent().append("<parameter-annotation>").eol();
- raiseIndent();
- indent().append("<annotations>").eol();
- raiseIndent();
- super.visitParameterAnnotation(helper);
- lowerIndent();
- indent().append("</annotations>").eol();
- lowerIndent();
- indent().append("</parameter-annotation>").eol();
- }
- public void visitTypeAnnotation(TypeAnnotation helper) {
- indent().append("<type-annotation>").eol();
- raiseIndent();
- helper.getTarget().accept(this);
- indent().append("<target-path>").eol();
- raiseIndent();
- helper.getTargetPath().accept(this);
- lowerIndent();
- indent().append("</target-path>").eol();
- indent().append("<element-value-pairs>").eol();
- raiseIndent();
- helper.getElementValuePairs().forEach(elementValuePair -> elementValuePair.accept(this));
- lowerIndent();
- indent().append("</element-value-pairs>").eol();
- lowerIndent();
- indent().append("</type-annotation>").eol();
- }
- public void visitTypeParameterTarget(TypeParameterTarget helper) {
- indent().append("<type-parameter-target target-type=\"").append(helper.getHexTargetType()).append("\">").eol();
- raiseIndent();
- indent().append("<type-parameter-index>").append(helper.getTypeParameterIndex()).append("</type-parameter-index>").eol();
- lowerIndent();
- indent().append("</type-parameter-target>").eol();
- }
- public void visitSupertypeTarget(SupertypeTarget helper) {
- indent().append("<supertype-target target-type=\"").append(helper.getHexTargetType()).append("\">").eol();
- raiseIndent();
- indent().append("<supertype-index>").append(helper.getSupertypeIndex()).append("</supertype-index>").eol();
- lowerIndent();
- indent().append("</supertype-target>").eol();
- }
- public void visitTypeParameterBoundTarget(TypeParameterBoundTarget helper) {
- indent().append("<type-parameter-bound-target target-type=\"").append(helper.getHexTargetType()).append("\">").eol();
- raiseIndent();
- indent().append("<type-parameter-index>").append(helper.getTypeParameterIndex()).append("</type-parameter-index>").eol();
- indent().append("<bound-index>").append(helper.getBoundIndex()).append("</bound-index>").eol();
- lowerIndent();
- indent().append("</type-parameter-bound-target>").eol();
- }
- public void visitEmptyTarget(EmptyTarget helper) {
- indent().append("<empty-target target-type=\"").append(helper.getHexTargetType()).append("\"/>").eol();
- }
- public void visitFormalParameterTarget(FormalParameterTarget helper) {
- indent().append("<formal-parameter-target target-type=\"").append(helper.getHexTargetType()).append("\">").eol();
- raiseIndent();
- indent().append("<formal-parameter-index>").append(helper.getFormalParameterIndex()).append("</formal-parameter-index>").eol();
- lowerIndent();
- indent().append("</formal-parameter-target>").eol();
- }
- public void visitThrowsTarget(ThrowsTarget helper) {
- indent().append("<throws-target target-type=\"").append(helper.getHexTargetType()).append("\">").eol();
- raiseIndent();
- indent().append("<throws-type-index>").append(helper.getThrowsTypeIndex()).append("</throws-type-index>").eol();
- lowerIndent();
- indent().append("</throws-target>").eol();
- }
- public void visitLocalvarTarget(LocalvarTarget helper) {
- indent().append("<localvar-target target-type=\"").append(helper.getHexTargetType()).append("\">").eol();
- raiseIndent();
- super.visitLocalvarTarget(helper);
- lowerIndent();
- indent().append("</localvar-target>").eol();
- }
- public void visitCatchTarget(CatchTarget helper) {
- indent().append("<catch-target target-type=\"").append(helper.getHexTargetType()).append("\">").eol();
- raiseIndent();
- indent().append("<exception-table-index>").append(helper.getExceptionTableIndex()).append("</exception-table-index>").eol();
- lowerIndent();
- indent().append("</catch-target>").eol();
- }
- public void visitOffsetTarget(OffsetTarget helper) {
- indent().append("<offset-target target-type=\"").append(helper.getHexTargetType()).append("\">").eol();
- raiseIndent();
- indent().append("<offset>").append(helper.getOffset()).append("</offset>").eol();
- lowerIndent();
- indent().append("</offset-target>").eol();
- }
- public void visitTypeArgumentTarget(TypeArgumentTarget helper) {
- indent().append("<type-argument-target target-type=\"").append(helper.getHexTargetType()).append("\">").eol();
- raiseIndent();
- indent().append("<offset>").append(helper.getOffset()).append("</offset>").eol();
- indent().append("<type-argument-index>").append(helper.getTypeArgumentIndex()).append("</type-argument-index>").eol();
- lowerIndent();
- indent().append("</type-argument-target>").eol();
- }
- public void visitTypePathEntry(TypePathEntry helper) {
- indent().append("<type-path>").eol();
- raiseIndent();
- indent().append("<type-path-kind>").append(helper.getTypePathKind().getTypePathKind()).append("</type-path-kind>").eol();
- indent().append("<type-argument-index>").append(helper.getTypeArgumentIndex()).append("</type-argument-index>").eol();
- lowerIndent();
- indent().append("</type-path>").eol();
- }
- public void visitElementValuePair(ElementValuePair helper) {
- indent().append("<element-value-pair>").eol();
- raiseIndent();
- indent().append("<element-name>").append(helper.getElementName()).append("</element-name>").eol();
- super.visitElementValuePair(helper);
- lowerIndent();
- indent().append("</element-value-pair>").eol();
- }
- public void visitByteConstantElementValue(ByteConstantElementValue helper) {
- visitConstantElementValue(helper, "byte");
- }
- public void visitCharConstantElementValue(CharConstantElementValue helper) {
- visitConstantElementValue(helper, "char");
- }
- public void visitDoubleConstantElementValue(DoubleConstantElementValue helper) {
- visitConstantElementValue(helper, "double");
- }
- public void visitFloatConstantElementValue(FloatConstantElementValue helper) {
- visitConstantElementValue(helper, "float");
- }
- public void visitIntegerConstantElementValue(IntegerConstantElementValue helper) {
- visitConstantElementValue(helper, "integer");
- }
- public void visitLongConstantElementValue(LongConstantElementValue helper) {
- visitConstantElementValue(helper, "long");
- }
- public void visitShortConstantElementValue(ShortConstantElementValue helper) {
- visitConstantElementValue(helper, "short");
- }
- public void visitBooleanConstantElementValue(BooleanConstantElementValue helper) {
- visitConstantElementValue(helper, "boolean");
- }
- public void visitStringConstantElementValue(StringConstantElementValue helper) {
- visitConstantElementValue(helper, "string");
- }
- private void visitConstantElementValue(ConstantElementValue helper, String type) {
- indent();
- append("<").append(type).append("-element-value tag=\"").append(helper.getTag()).append("\">");
- helper.getRawConstValue().accept(this);
- append("</").append(type).append("-element-value>").eol();
- }
- public void visitEnumElementValue(EnumElementValue helper) {
- indent();
- append("<enum-element-value tag=\"").append(helper.getTag()).append("\">");
- append(helper.getTypeName()).append(".").append(helper.getConstName());
- append("</enum-element-value>").eol();
- }
- public void visitClassElementValue(ClassElementValue helper) {
- indent();
- append("<class-element-value tag=\"").append(helper.getTag()).append("\">");
- append(helper.getClassInfo());
- append("</class-element-value>").eol();
- }
- public void visitAnnotationElementValue(AnnotationElementValue helper) {
- indent().append("<annotation-element-value tag=\"").append(helper.getTag()).append("\">").eol();
- raiseIndent();
- super.visitAnnotationElementValue(helper);
- lowerIndent();
- indent().append("</annotation-element-value>").eol();
- }
- public void visitArrayElementValue(ArrayElementValue helper) {
- indent().append("<array-element-value tag=\"").append(helper.getTag()).append("\">").eol();
- raiseIndent();
- super.visitArrayElementValue(helper);
- lowerIndent();
- indent().append("</array-element-value>").eol();
- }
- public void visitLocalvarTableEntry(LocalvarTableEntry helper) {
- indent().append("<localvar start-pc=\"").append(helper.getStartPc()).append("\" length=\"").append(helper.getLength()).append("\" index=\"").append(helper.getIndex()).append("\"/>").eol();
- }
- public void visitSameFrame(SameFrame helper) {
- indent().append("<same-frame frame-type=\"").append(helper.getFrameType()).append("\"/>").eol();
- }
- public void visitSameLocals1StackItemFrame(SameLocals1StackItemFrame helper) {
- indent().append("<same-locals-1-stack-item-frame frame-type=\"").append(helper.getFrameType()).append("\">").eol();
- raiseIndent();
- indent().append("<stack>").eol();
- raiseIndent();
- super.visitSameLocals1StackItemFrame(helper);
- lowerIndent();
- indent().append("</stack>").eol();
- lowerIndent();
- indent().append("</same-locals-1-stack-item-frame>").eol();
- }
- public void visitSameLocals1StackItemFrameExtended(SameLocals1StackItemFrameExtended helper) {
- indent().append("<same-locals-1-stack-item-frame-extended frame-type=\"").append(helper.getFrameType()).append("\" offset-delta=\"").append(helper.getOffsetDelta()).append("\">").eol();
- raiseIndent();
- indent().append("<stack>").eol();
- raiseIndent();
- super.visitSameLocals1StackItemFrameExtended(helper);
- lowerIndent();
- indent().append("</stack>").eol();
- lowerIndent();
- indent().append("</same-locals-1-stack-item-frame-extended>").eol();
- }
- public void visitChopFrame(ChopFrame helper) {
- indent().append("<chop-frame frame-type=\"").append(helper.getFrameType()).append("\" offset-delta=\"").append(helper.getOffsetDelta()).append("\"/>").eol();
- }
- public void visitSameFrameExtended(SameFrameExtended helper) {
- indent().append("<same-frame-extended frame-type=\"").append(helper.getFrameType()).append("\" offset-delta=\"").append(helper.getOffsetDelta()).append("\"/>").eol();
- }
- public void visitAppendFrame(AppendFrame helper) {
- indent().append("<append-frame frame-type=\"").append(helper.getFrameType()).append("\" offset-delta=\"").append(helper.getOffsetDelta()).append("\">").eol();
- raiseIndent();
- indent().append("<locals>").eol();
- raiseIndent();
- super.visitAppendFrame(helper);
- lowerIndent();
- indent().append("</locals>").eol();
- lowerIndent();
- indent().append("</append-frame>").eol();
- }
- public void visitFullFrame(FullFrame helper) {
- indent().append("<full-frame frame-type=\"").append(helper.getFrameType()).append("\" offset-delta=\"").append(helper.getOffsetDelta()).append("\">").eol();
- raiseIndent();
- indent().append("<locals>").eol();
- raiseIndent();
- helper.getLocals().forEach(local -> local.accept(this));
- lowerIndent();
- indent().append("</locals>").eol();
- indent().append("<stack>").eol();
- raiseIndent();
- helper.getStack().forEach(local -> local.accept(this));
- lowerIndent();
- indent().append("</stack>").eol();
- lowerIndent();
- indent().append("</full-frame>").eol();
- }
- public void visitTopVariableInfo(TopVariableInfo helper) {
- indent().append("<top-variable-info tag=\"").append(helper.getTag()).append("\"/>").eol();
- }
- public void visitIntegerVariableInfo(IntegerVariableInfo helper) {
- indent().append("<integer-variable-info tag=\"").append(helper.getTag()).append("\"/>").eol();
- }
- public void visitFloatVariableInfo(FloatVariableInfo helper) {
- indent().append("<float-variable-info tag=\"").append(helper.getTag()).append("\"/>").eol();
- }
- public void visitLongVariableInfo(LongVariableInfo helper) {
- indent().append("<long-variable-info tag=\"").append(helper.getTag()).append("\"/>").eol();
- }
- public void visitDoubleVariableInfo(DoubleVariableInfo helper) {
- indent().append("<double-variable-info tag=\"").append(helper.getTag()).append("\"/>").eol();
- }
- public void visitNullVariableInfo(NullVariableInfo helper) {
- indent().append("<null-variable-info tag=\"").append(helper.getTag()).append("\"/>").eol();
- }
- public void visitUninitializedThisVariableInfo(UninitializedThisVariableInfo helper) {
- indent().append("<uninitialized-this-variable-info tag=\"").append(helper.getTag()).append("\"/>").eol();
- }
- public void visitObjectVariableInfo(ObjectVariableInfo helper) {
- indent().append("<object-variable-info tag=\"").append(helper.getTag()).append("\">").eol();
- raiseIndent();
- top = true;
- super.visitObjectVariableInfo(helper);
- top = false;
- lowerIndent();
- indent().append("</object-variable-info>").eol();
- }
- public void visitUninitializedVariableInfo(UninitializedVariableInfo helper) {
- indent().append("<uninitialized-variable-info tag=\"").append(helper.getTag()).append("\" offset=\"").append(helper.getOffset()).append("\"/>").eol();
- }
- private Printer appendLocalVariable(LocalVariable localVariable) {
- if (localVariable != null) {
- append(" ");
- append(DescriptorHelper.getType(localVariable.getDescriptor())).append(" ").append(localVariable.getName());
- }
- return this;
- }
- private Printer appendClassInfo(int index, Class_info class_info) {
- indent();
- append("<class index=\"").append(index).append("\">");
- class_info.accept(this);
- append("</class>").eol();
- return this;
- }
- // Visible for testing
- String escapeXMLCharacters(String text) {
- StringBuilder result = new StringBuilder();
- text.codePoints()
- .forEach(c -> {
- if (c == '&') {
- result.append("&");
- } else if (c == '<') {
- result.append("<");
- } else if (c == '>') {
- result.append(">");
- } else if (Character.isISOControl(c) || c > 0x9F) {
- result.append("&#x");
- result.append(Integer.toString(c, 16).toUpperCase());
- result.append(";");
- } else {
- result.append(Character.toChars(c));
- }
- });
- if (containsControlCharacters(text)) {
- return "<![CDATA[" + result + "]]>";
- } else {
- return result.toString();
- }
- }
- private boolean containsControlCharacters(String text) {
- return text.codePoints().anyMatch(c -> Character.isISOControl(c) || c > 0x9F);
- }
- }