Class JavaOutputSink

All Implemented Interfaces:
ICodeDocument, ITextDocumentPart

public class JavaOutputSink extends CppLikeDocumentPart
This output sink is the recipient for the generation of a decompiled Java Abstract Syntax Tree (AST). The sink also contains configuration elements that will guide how certain AST elements are generated. Typically, a sink receives the output for a class or a method element.

Generating an AST yields a special type of elements, called items, that a client (such as the decompiler UI) may want to track to achieve higher level purpose such as xrefs building, renaming, easy syntax coloring, etc. Items include keywords, class/field/method/variable names, labels, etc. The type of items generated depends on the item factory provided to JavaOutputSink constructors.

  • Constructor Details

    • JavaOutputSink

      public JavaOutputSink(int baseAnchorId)
      Create an output sink.
      Parameters:
      baseAnchorId - base anchor identifier
    • JavaOutputSink

      public JavaOutputSink(int baseAnchorId, JavaDocument doc, IDexDecompilerUnit dexdec)
      Create an output sink for a Java document.
      Parameters:
      baseAnchorId - base anchor identifier
      doc - Java document, or null
      dexdec - dex decompiler, or null
  • Method Details

    • getDocument

      public JavaDocument getDocument()
      Retrieve the owning Java document.
      Returns:
      Java document, or null
    • getDecompilerUnit

      public IDexDecompilerUnit getDecompilerUnit()
      Retrieve the owning dex decompiler.
      Returns:
      dex decompiler, or null
    • getSortItemsForRendering

      public int getSortItemsForRendering()
      Retrieve the source-item sorting mode.
      Returns:
      sorting mode
    • getUseDebugInfoNames

      public boolean getUseDebugInfoNames()
      Determine whether dex debug-information names should be used.
      Returns:
      true if debug-information names should be used
    • getDisplayPrivateMethodsLast

      public boolean getDisplayPrivateMethodsLast()
      Determine whether private methods should be rendered last.
      Returns:
      true if private methods should be rendered last
    • getInsertBlankLinesAfterCompounds

      public boolean getInsertBlankLinesAfterCompounds()
      Determine whether blank lines should be inserted after compound statements.
      Returns:
      true if blank lines should be inserted
    • getGenerateSyntheticFields

      public boolean getGenerateSyntheticFields()
      Determine whether synthetic fields should be rendered.
      Returns:
      true if synthetic fields should be rendered
    • getGenerateSyntheticMethods

      public boolean getGenerateSyntheticMethods()
      Determine whether synthetic methods should be rendered.
      Returns:
      true if synthetic methods should be rendered
    • getGenerateAnnotations

      public boolean getGenerateAnnotations()
      Determine whether annotations should be rendered.
      Returns:
      true if annotations should be rendered
    • getDisplayMethodInternalsAsComment

      public int getDisplayMethodInternalsAsComment()
      Retrieve the method-internals comment rendering mode.
      Returns:
      method-internals rendering mode
    • getResolveMethodCallTargets

      public boolean getResolveMethodCallTargets()
      Determine whether method-call targets should be resolved.
      Returns:
      true if method-call targets should be resolved
    • getResolveFieldAccessTargets

      public boolean getResolveFieldAccessTargets()
      Determine whether field-access targets should be resolved.
      Returns:
      true if field-access targets should be resolved
    • getGenerateOverrideAnnotations

      public boolean getGenerateOverrideAnnotations()
      Determine whether additional @Override annotations should be rendered.
      Returns:
      true if override annotations should be rendered
    • getGenerateLambdas

      public boolean getGenerateLambdas()
      Determine whether lambdas should be rendered when possible.
      Returns:
      true if lambdas should be rendered
    • getUseVarReservedType

      public boolean getUseVarReservedType()
      Determine whether var should be rendered when possible.
      Returns:
      true if var should be used when possible
    • getSplitCallArgThreshold

      public int getSplitCallArgThreshold()
      Retrieve the argument-count threshold for split call rendering.
      Returns:
      split-call argument threshold
    • getDoNotGenerateThisIfPossible

      public boolean getDoNotGenerateThisIfPossible()
      Determine whether this should be omitted when possible.
      Returns:
      true if this should be omitted when possible
    • getDisregardCollapse

      public boolean getDisregardCollapse()
      Determine whether collapse metadata should be ignored.
      Returns:
      true if collapse metadata should be ignored
    • pushContainingClass

      public void pushContainingClass(IJavaClass c)
      Push a containing class on the generation stack.
      Parameters:
      c - containing class
    • popContainingClass

      public IJavaClass popContainingClass()
      Pop the current containing class.
      Returns:
      popped containing class
    • getCurrentContainingClass

      public IJavaClass getCurrentContainingClass()
      Retrieve the current containing class.
      Returns:
      current containing class, or null
    • getTopLevelClass

      public IJavaClass getTopLevelClass()
      Retrieve the top-level containing class.
      Returns:
      top-level class, or null
    • isBeingGenerated

      public boolean isBeingGenerated(IJavaElement elt)
      Determine whether an AST element is currently being generated.
      Parameters:
      elt - AST element
      Returns:
      true if the element is on the generation stack
    • astPush

      public IJavaElement astPush(IJavaElement elt)
      Push an AST element on the generation stack.
      Parameters:
      elt - AST element
      Returns:
      previous parent element, or null
    • astPop

      public IJavaElement astPop()
      Pop the current AST element from the generation stack.
      Returns:
      popped AST element
    • astParent

      public IJavaElement astParent()
      Make sure to call before generateEnter.
      Returns:
      the parent of the element AST about to be rendered or null if there is none or none can be found
    • astDepth

      public int astDepth()
      Retrieve the current AST generation depth.
      Returns:
      AST stack depth
    • pushContainingMethod

      public void pushContainingMethod(IJavaMethod m)
      Push a containing method on the generation stack.
      Parameters:
      m - containing method
    • popContainingMethod

      public IJavaMethod popContainingMethod()
      Pop the current containing method.
      Returns:
      popped containing method
    • getCurrentContainingMethod

      public IJavaMethod getCurrentContainingMethod()
      Retrieve the current containing method.
      Returns:
      current containing method, or null
    • getContainingMethods

      public Collection<IJavaMethod> getContainingMethods()
      Retrieve the containing method stack.
      Returns:
      read-only containing methods
    • setDynamicContentManager

      public void setDynamicContentManager(IDynamicContentManager dcm)
      Set the dynamic content manager.
      Parameters:
      dcm - dynamic content manager, or null
    • getDynamicContentManager

      public IDynamicContentManager getDynamicContentManager()
      Retrieve the dynamic content manager.
      Returns:
      dynamic content manager, or null
    • setCurrentMethodIndex

      public int setCurrentMethodIndex(int index)
      Set the method index of the method being generated
      Parameters:
      index - the current method index
      Returns:
      the previous index
    • getCurrentMethodIndex

      public int getCurrentMethodIndex()
      Get the method index of the method being generated
      Returns:
      a negative value if the index cannot be determined or is invalid
    • appendKeyword

      public void appendKeyword(JavaKeyword keyword)
      Append a Java keyword.
      Parameters:
      keyword - keyword to append
    • appendKeyword

      public void appendKeyword(JavaKeyword keyword, long itemId)
      Append a Java keyword with an item identifier.
      Parameters:
      keyword - keyword to append
      itemId - item identifier
    • renderPreComment

      public void renderPreComment(ICodeCoordinates coord)
      Render a pre-comment for code coordinates.

      An end-of-line marker is always appended.

      Parameters:
      coord - code coordinates
    • renderInlineComment

      public void renderInlineComment(ICodeCoordinates coord, boolean appendEOL)
      Render an inline comment for code coordinates.
      Parameters:
      coord - code coordinates
      appendEOL - true to append an end-of-line marker
    • loadCommentInline

      public void loadCommentInline(ICodeCoordinates insnCoord)
      Load an inline comment as the current end-of-line comment.
      Parameters:
      insnCoord - instruction coordinates
    • appendAnnotationsList

      public void appendAnnotationsList(List<IJavaAnnotation> annotations, char charAfterAnno)
      Append annotations.
      Parameters:
      annotations - annotations to append
      charAfterAnno - character to append after each annotation
    • appendAnnotationsList

      public void appendAnnotationsList(List<IJavaAnnotation> annotations, char charAfterAnno, Set<String> skiplist)
      Append annotations, skipping selected annotation types.
      Parameters:
      annotations - annotations to append
      charAfterAnno - character to append after each annotation
      skiplist - type signatures to skip, or null
    • recordIdentifierCoordinates

      public void recordIdentifierCoordinates(long objectId, ICodeCoordinates coordinates)
      Record coordinates for an identifier item.
      Parameters:
      objectId - identifier item id
      coordinates - code coordinates
    • getIdentifierCoordinates

      public Map<Long,List<ICodeCoordinates>> getIdentifierCoordinates()
      Retrieve recorded identifier coordinates.
      Returns:
      identifier coordinates keyed by item id
    • pushAnonymousBaseType

      public void pushAnonymousBaseType(IJavaType type)
      Push an anonymous-class base type.
      Parameters:
      type - base type, possibly null
    • popAnonymousBaseType

      public IJavaType popAnonymousBaseType()
      Pop the current anonymous-class base type.
      Returns:
      popped base type, possibly null
    • getCurrentAnonymousBaseType

      public IJavaType getCurrentAnonymousBaseType()
      Retrieve the current anonymous-class base type.
      Returns:
      current base type, or null
    • pushAnonymousCaptureInfo

      public void pushAnonymousCaptureInfo(JavaOutputSink.CaptureInfo info)
      Push anonymous-class capture information.
      Parameters:
      info - capture information
    • popAnonymousCaptureInfo

      public JavaOutputSink.CaptureInfo popAnonymousCaptureInfo()
      Pop anonymous-class capture information.
      Returns:
      popped capture information
    • getCurrentAnonymousCaptureInfo

      public JavaOutputSink.CaptureInfo getCurrentAnonymousCaptureInfo()
      Retrieve current anonymous-class capture information.
      Returns:
      capture information, or null
    • addGeneratedAnon

      public void addGeneratedAnon(IJavaElement container, IJavaClass c)
      Register an anonymous type (most likely a class) that's about to be rendered as inline code, inside a method or another class. We use this multi-map to track anonymous types that were actually rendered, and those that were not. That can happen in obfuscated files where anonymous inner classes are used by third-party (not the container) classes only.
      Parameters:
      container - method or class
      c - an anonymous that's about to be generated (recorded to avoid generated it later)
    • getGeneratedAnon

      public List<IJavaClass> getGeneratedAnon(IJavaElement container)
      Retrieve anonymous classes generated in a container.
      Parameters:
      container - method or class container
      Returns:
      generated anonymous classes, possibly empty
    • pushReplacements

      public void pushReplacements(Map<IJavaIdentifier,IJavaExpression> replmap)
      Push an identifier replacement map.
      Parameters:
      replmap - replacement map
    • popReplacements

      public Map<IJavaIdentifier,IJavaExpression> popReplacements()
      Pop the current identifier replacement map.
      Returns:
      replacement map
    • getReplacementFor

      public IJavaExpression getReplacementFor(IJavaIdentifier ident)
      Retrieve a replacement expression for an identifier.
      Parameters:
      ident - identifier
      Returns:
      replacement expression, or null
    • setGeneratingReplacement

      public void setGeneratingReplacement(boolean generatingReplacement)
      Set the replacement-generation state.
      Parameters:
      generatingReplacement - true if a replacement is being generated
    • requestGeneratingReplacement

      public boolean requestGeneratingReplacement()
      Request entry into replacement generation.
      Returns:
      true if replacement generation may proceed
    • doneGeneratingReplacement

      public void doneGeneratingReplacement()
      Mark replacement generation as complete.
    • recordGeneratedDecompilable

      public void recordGeneratedDecompilable(String signature)
      Record a generated decompilable item.
      Parameters:
      signature - decompilable item signature
    • getDecompilables

      public List<String> getDecompilables()
      Retrieve the list of addresses of the decompilable (classes, fields, methods) items generated in this part.
      Returns:
      a list of items, ordered as they appear in the decompiled output
    • validate

      public void validate()
      Overrides:
      validate in class CppLikeDocumentPart