prettyEncodedMethod :: DexFile -> [(MethodId, [VisibleAnnotation])] -> (Word32, EncodedMethod) -> PP.Doc
prettyEncodedMethod dex annots (n, m) =
  case (mmeth, mmeth >>= (getProto dex . methProtoId)) of
    (Just method, Just proto) ->
      let flags = methAccessFlags m
          adoc | Just vannots <- lookup (methId m) annots =
                   "      annots" $+$ PP.nest 8 (vsep (map (prettyVisibleAnnotation dex) vannots))
               | otherwise = PP.empty
      in vsep [ "    #" <> word32Dec n <> "              : (in" <+> getTypeName' dex (methClassId method) <> ")"
                 , prettyField "      name" (PP.quotes (getStr' dex (methNameId method)))
                 , prettyField "      type" (PP.quotes (protoDesc dex proto))
                 , prettyFieldHexS "      access" flags (AF.flagsString AF.AMethod flags)
                 , adoc
                 , maybe ("     code:    (none)") (prettyCode dex flags (methId m)) (methCode m)
                 ]
    (Nothing, _) -> "<unknown method ID: " <> word16HexFixed (methId m) <> ">"
    (Just method, Nothing) -> "<unknown prototype ID: " <> word16HexFixed (methProtoId method) <> ">"
  where
    mmeth = getMethod dex (methId m)

-- | Like 'PP.vcat', except it never collapses overlapping lines
prettyEncodedMethod :: DexFile -> [(MethodId, [VisibleAnnotation])] -> (Word32, EncodedMethod) -> PP.Doc
prettyEncodedMethod dex annots (n, m) =
  case (mmeth, mmeth >>= (getProto dex . methProtoId)) of
    (Just method, Just proto) ->
      let flags = methAccessFlags m
          adoc | Just vannots <- lookup (methId m) annots =
                   "      annots" $+$ PP.nest 8 (vsep (map (prettyVisibleAnnotation dex) vannots))
               | otherwise = PP.empty
      in vsep [ "    #" <> word32Dec n <> "              : (in" <+> getTypeName' dex (methClassId method) <> ")"
                 , prettyField "      name" (PP.quotes (getStr' dex (methNameId method)))
                 , prettyField "      type" (PP.quotes (protoDesc dex proto))
                 , prettyFieldHexS "      access" flags (AF.flagsString AF.AMethod flags)
                 , adoc
                 , maybe ("     code:    (none)") (prettyCode dex flags (methId m)) (methCode m)
                 ]
    (Nothing, _) -> "<unknown method ID: " <> word16HexFixed (methId m) <> ">"
    (Just method, Nothing) -> "<unknown prototype ID: " <> word16HexFixed (methProtoId method) <> ">"
  where
    mmeth = getMethod dex (methId m)

-- | Like 'PP.vcat', except it never collapses overlapping lines
prettyEncodedMethod dex annots (n, m) =
  case (mmeth, mmeth >>= (getProto dex . methProtoId)) of
    (Just method, Just proto) ->
      let flags = methAccessFlags m
          adoc | Just vannots <- lookup (methId m) annots =
                   "      annots" $+$ PP.nest 8 (vsep (map (prettyVisibleAnnotation dex) vannots))
               | otherwise = PP.empty
      in vsep [ "    #" <> word32Dec n <> "              : (in" <+> getTypeName' dex (methClassId method) <> ")"
                 , prettyField "      name" (PP.quotes (getStr' dex (methNameId method)))
                 , prettyField "      type" (PP.quotes (protoDesc dex proto))
                 , prettyFieldHexS "      access" flags (AF.flagsString AF.AMethod flags)
                 , adoc
                 , maybe ("     code:    (none)") (prettyCode dex flags (methId m)) (methCode m)
                 ]
    (Nothing, _) -> "<unknown method ID: " <> word16HexFixed (methId m) <> ">"
    (Just method, Nothing) -> "<unknown prototype ID: " <> word16HexFixed (methProtoId method) <> ">"
  where
    mmeth = getMethod dex (methId m)

-- | Like 'PP.vcat', except it never collapses overlapping lines