mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
149 lines
4.1 KiB
Python
149 lines
4.1 KiB
Python
# Copyright 2014 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import os
|
|
import re
|
|
import tempfile
|
|
|
|
from pylib import constants
|
|
from pylib import cmd_helper
|
|
|
|
|
|
_PROGUARD_CLASS_RE = re.compile(r'\s*?- Program class:\s*([\S]+)$')
|
|
_PROGUARD_SUPERCLASS_RE = re.compile(r'\s*? Superclass:\s*([\S]+)$')
|
|
_PROGUARD_SECTION_RE = re.compile(
|
|
r'^(?:Interfaces|Constant Pool|Fields|Methods|Class file attributes) '
|
|
r'\(count = \d+\):$')
|
|
_PROGUARD_METHOD_RE = re.compile(r'\s*?- Method:\s*(\S*)[(].*$')
|
|
_PROGUARD_ANNOTATION_RE = re.compile(r'\s*?- Annotation \[L(\S*);\]:$')
|
|
_PROGUARD_ANNOTATION_CONST_RE = (
|
|
re.compile(r'\s*?- Constant element value.*$'))
|
|
_PROGUARD_ANNOTATION_VALUE_RE = re.compile(r'\s*?- \S+? \[(.*)\]$')
|
|
|
|
_PROGUARD_PATH_SDK = os.path.join(
|
|
constants.ANDROID_SDK_ROOT, 'tools', 'proguard', 'lib', 'proguard.jar')
|
|
_PROGUARD_PATH_BUILT = (
|
|
os.path.join(os.environ['ANDROID_BUILD_TOP'], 'external', 'proguard',
|
|
'lib', 'proguard.jar')
|
|
if 'ANDROID_BUILD_TOP' in os.environ else None)
|
|
_PROGUARD_PATH = (
|
|
_PROGUARD_PATH_SDK if os.path.exists(_PROGUARD_PATH_SDK)
|
|
else _PROGUARD_PATH_BUILT)
|
|
|
|
|
|
def Dump(jar_path):
|
|
"""Dumps class and method information from a JAR into a dict via proguard.
|
|
|
|
Args:
|
|
jar_path: An absolute path to the JAR file to dump.
|
|
Returns:
|
|
A dict in the following format:
|
|
{
|
|
'classes': [
|
|
{
|
|
'class': '',
|
|
'superclass': '',
|
|
'annotations': {},
|
|
'methods': [
|
|
{
|
|
'method': '',
|
|
'annotations': {},
|
|
},
|
|
...
|
|
],
|
|
},
|
|
...
|
|
],
|
|
}
|
|
"""
|
|
|
|
with tempfile.NamedTemporaryFile() as proguard_output:
|
|
cmd_helper.RunCmd(['java', '-jar',
|
|
_PROGUARD_PATH,
|
|
'-injars', jar_path,
|
|
'-dontshrink',
|
|
'-dontoptimize',
|
|
'-dontobfuscate',
|
|
'-dontpreverify',
|
|
'-dump', proguard_output.name])
|
|
|
|
|
|
results = {
|
|
'classes': [],
|
|
}
|
|
|
|
annotation = None
|
|
annotation_has_value = False
|
|
class_result = None
|
|
method_result = None
|
|
|
|
for line in proguard_output:
|
|
line = line.strip('\r\n')
|
|
|
|
m = _PROGUARD_CLASS_RE.match(line)
|
|
if m:
|
|
class_result = {
|
|
'class': m.group(1).replace('/', '.'),
|
|
'superclass': '',
|
|
'annotations': {},
|
|
'methods': [],
|
|
}
|
|
results['classes'].append(class_result)
|
|
annotation = None
|
|
annotation_has_value = False
|
|
method_result = None
|
|
continue
|
|
|
|
if not class_result:
|
|
continue
|
|
|
|
m = _PROGUARD_SUPERCLASS_RE.match(line)
|
|
if m:
|
|
class_result['superclass'] = m.group(1).replace('/', '.')
|
|
continue
|
|
|
|
m = _PROGUARD_SECTION_RE.match(line)
|
|
if m:
|
|
annotation = None
|
|
annotation_has_value = False
|
|
method_result = None
|
|
continue
|
|
|
|
m = _PROGUARD_METHOD_RE.match(line)
|
|
if m:
|
|
method_result = {
|
|
'method': m.group(1),
|
|
'annotations': {},
|
|
}
|
|
class_result['methods'].append(method_result)
|
|
annotation = None
|
|
annotation_has_value = False
|
|
continue
|
|
|
|
m = _PROGUARD_ANNOTATION_RE.match(line)
|
|
if m:
|
|
# Ignore the annotation package.
|
|
annotation = m.group(1).split('/')[-1]
|
|
if method_result:
|
|
method_result['annotations'][annotation] = None
|
|
else:
|
|
class_result['annotations'][annotation] = None
|
|
continue
|
|
|
|
if annotation:
|
|
if not annotation_has_value:
|
|
m = _PROGUARD_ANNOTATION_CONST_RE.match(line)
|
|
annotation_has_value = bool(m)
|
|
else:
|
|
m = _PROGUARD_ANNOTATION_VALUE_RE.match(line)
|
|
if m:
|
|
if method_result:
|
|
method_result['annotations'][annotation] = m.group(1)
|
|
else:
|
|
class_result['annotations'][annotation] = m.group(1)
|
|
annotation_has_value = None
|
|
|
|
return results
|
|
|